1.0.8 • Published 5 years ago

@brownpapertickets/surya-gql-demo v1.0.8

Weekly downloads
1
License
MIT
Repository
bitbucket
Last release
5 years ago

Surya GQL Demo

A demonstration project that shows how to combine the surya-gql modules to create a powerful, flexible and scalable GraphQL service with back-end data support.

The service implemented in src/index.js is very rudumentary but shows how the various components interact. It does not include proper configuration management or logging or a functioning auth system but stubs are in place for each of these. The Surya is an overlay on top of Apollo Graphql and utilizes it's front end logic.

The guts of the unique service api definition, data definition and business logic resides fully in the /types modules which follow a specific structure:

Data Type Definitions - in one or more .js files write one or more classes that define the data to be input, output and potentially stored in a data store or forwarded on to another service. These "universal" Type classes are not GraphQL or Database-specific but are an intermediate and generalized system that allows you to define data once and have it accessible and applied everywhere at the front, back, and middle ends. There is no need to hand-maintain cumbersome data conversion functions or data redaction logic for field-level security. It's all defined in the model metadata. GraphQL Query, Mutation and Subscription definitions for those data structures. Resolvers that are invoked when those queries, mutations or subscriptions are invoked by a client Managers - Business and procedural logic that does the heavy lifting for the Resolvers. Managers are build from powerful base classes that dramatically reduce the amount of code for common CRUD and business sceanrios but are fully extensible. APIs - Back-end O/R-like logic for MongoDB, PostgreSQL and any other data store you want to add. The provided APIs use the universal Data Definitions. The handshake between the standard Manager classes and the APIs provide tremendous power and great consistency across data back ends including a standardized argument set for queries including a cross-platform filter and sort syntax with proper parsing rules and per-backend transformations.

Each type module is contained in a subdirectory under /types. The main server logic instantiates a TypesManager() and then calls

await typesManager.loadTypeModules(__dirname + "/types")

Type Manifest

This scans each directory that contains a "manifiest.js" file. The manifest which looks something like this:

export const Manifest = {
  sysVersion: "1.0.0",
  typeVersion: "0.1.0",
  description: "MongoDB Based Users storage",
  types: ["User", "Address", "AuthToken"],
  queries: "UserQueries",
  resolvers: "UserResolvers",
  manager: "UserManager",
  data: {
    interface: "MongoDB",
    api: "UserAPI",
    config: { collection: "demo-user" },
  },
}

Provides information to the loader to help it understand the role of each the files in the module. A naming convention is also available so that a placeholder manifest can be used for routine structured modules.

Types: A list of the names of classes that are derived from BaseType and may be refrenced by queries or mutations.

Note: for each defined type name. For example "User", the BaseType class will generate a set of related data structures automatically for registration with the GraphQL system: : The class as defined Input : For use as input structures for example for create and update calls. This structure will not include fields flagged as input: false or symbolic: true SetResponse: A response from a call that returns a list of objects as: success: boolean : true if the query succeeded offset: integer : the passed offset total: integer : Total number of objects returned by query before pagination. items: : Array of objects

MutationResponse: Returned by mutation operations create, update, delete, etc. success: boolean message: string data:

Details on writing Type classes are detailed

Queries: A straight-forward representation of the graphql specification for the queries, mutations and subscriptions for these types

Resolvers: A resolver is a map of simple functions that are called when a query, mutation or subscription is called by the client.

The function is passed arguments, possibly the relevant data object and a context object which you define when you intantiate the ApolloGraphQL server. By convention for Surya, it contains a logger, the map of Managers for all of the Type modules keyed by the TypeName and the Authorization token or credentials The "Surya Way" is to minimize code in the resolvers and look up the appropriate manager and call it's corresponding method passing through the arguments, context and options. Some minor logic may be involved for individual field resolvers. Note: The demo should add some resolver examples for single and multiple lookups and for symbolics.

Managers: Standardized classes that do the business logic heavy lifting for Type Modules.

Managers are built from BaseClasses that provide basic functionality like authorization and authentication and possibly standardized CRUD logic. Methods can be added to managers where needed or standard methods can be sub-classed for replacement or for pre and/or post operations to the standard logic. For most straight-forward cases where CRUD+ logic is called for, only a placeholder is needed as all of the basic functionality is built in.

Data APIs

If your Type Module is a standard CRUD data interface you can define your API in the data: section. interface: defines what kind of database or data store you are using. api: is the class you defined, which is typically subclassed from a standard API base class config: is an API-specific configuration data object. See the BaseAPI in each case.