|
8 | 8 |  |
9 | 9 | [](#backers) |
10 | 10 | [](#sponsors) |
| 11 | + |
| 12 | +This is a toolkit for creating big GraphQL schemas with code-first approach in JavaScript. |
| 13 | + |
| 14 | +## Quick demo |
| 15 | + |
| 16 | +You may find a simple GraphQL server example in the following folder: [examples/simple](./examples/simple). |
| 17 | + |
| 18 | +## GraphQL schema entrypoints from a file structure |
| 19 | + |
| 20 | +When you are using code-first approach in GraphQL Schema construction you may meet with problem when you cannot understand what entrypoints has your schema. And where exactly placed the code which serves this or that entrypoint. |
| 21 | + |
| 22 | +`graphql-compose-modules` uses a file-system based schema entrypoint definition (something like does NextJS with its pages concept for routing). You just create folder `schema/` and put inside it the following sub-folders (root directories): `query`, `mutation` and `subscription`. Inside these folders you may put `.js` or `.ts` files with FieldConfigs. Assume you create the following directory structure: |
| 23 | + |
| 24 | +```bash |
| 25 | +schema/ |
| 26 | + query/ |
| 27 | + articleById.ts |
| 28 | + articlesList.ts |
| 29 | + mutation/ |
| 30 | + createArticle.ts |
| 31 | + updateArticle.ts |
| 32 | + removeArticle.ts |
| 33 | + subscription/ |
| 34 | + onArticleChange.ts |
| 35 | +``` |
| 36 | + |
| 37 | +With this directory structure `graphql-compose-modules` will use file names as field names for your root types and you get the following GraphQL schema: |
| 38 | + |
| 39 | +```graphql |
| 40 | +type Query { |
| 41 | + articleById: ... |
| 42 | + articlesList: ... |
| 43 | +} |
| 44 | + |
| 45 | +type Mutation { |
| 46 | + createArticle: ... |
| 47 | + updateArticle: ... |
| 48 | + removeArticle: ... |
| 49 | +} |
| 50 | + |
| 51 | +type Subscription { |
| 52 | + onArticleChange: ... |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +If you want rename field `articlesList` to `articleList` in your schema just rename `articlesList.ts` file. If you want to add a new field to Schema – just add a new file to `Query`, `Mutation`, `Subscription` folders. **This simple approach helps you understand entrypoints of your schema without launching the GraphQL server – what you see in folders that you get in GraphQL Schema**. |
| 57 | + |
| 58 | +## Describing FieldConfigs in files |
| 59 | + |
| 60 | +Every FieldConfig definition is described in separate file. This file contains all information about input args, output type, resolve function and additional fields like description & deprecationReason. As an example let's create `schema/Query/sum.ts` and put inside the following content: |
| 61 | + |
| 62 | +```ts |
| 63 | +export default { |
| 64 | + type: 'Int!', |
| 65 | + args: { |
| 66 | + a: 'Int!', |
| 67 | + b: 'Int!', |
| 68 | + }, |
| 69 | + resolve: (source, args, context, info) => { |
| 70 | + return args.a + args.b; |
| 71 | + }, |
| 72 | + description: 'This method sums two numbers', |
| 73 | + deprecationReason: 'This method is deprecated and will be removed soon.', |
| 74 | +}; |
| 75 | +``` |
| 76 | + |
| 77 | +If you familiar with [graphql-js FieldConfig definition](https://graphql.org/graphql-js/type/#examples) then you may notice that `type` & `args` properties are defined in SDL format. This syntax sugar provided by [graphql-compose](https://github.com/graphql-compose/graphql-compose#examples) package. |
| 78 | + |
| 79 | +## Namespaces for big schemas |
| 80 | + |
| 81 | +If your GraphQL Schema has a lot of methods you may create sub-folders for grouping some entrypoints fields according to some Entity or Namespace: |
| 82 | + |
| 83 | +```bash |
| 84 | +schema/ |
| 85 | + query/ |
| 86 | + articles/ |
| 87 | + byId.ts |
| 88 | + list.ts |
| 89 | + ... |
| 90 | + mutation/ |
| 91 | + articles/ |
| 92 | + create.ts |
| 93 | + update.ts |
| 94 | + remove.ts |
| 95 | + ... |
| 96 | +``` |
| 97 | + |
| 98 | +With such structure you will get the following schema. Namespace types `QueryArticles` & `MutationArticles` are created automatically: |
| 99 | + |
| 100 | +```graphql |
| 101 | +type Query { |
| 102 | + articles: QueryArticles |
| 103 | +} |
| 104 | + |
| 105 | +type Mutation { |
| 106 | + articles: MutationArticles |
| 107 | +} |
| 108 | + |
| 109 | +type QueryArticles { |
| 110 | + byId: ... |
| 111 | + list: ... |
| 112 | +} |
| 113 | + |
| 114 | +type MutationArticles { |
| 115 | + create: ... |
| 116 | + update: ... |
| 117 | + remove: ... |
| 118 | +} |
| 119 | +``` |
| 120 | + |
| 121 | +You may use sub-folders for `Query` & `Mutation` and all servers supports this feature. But for `Subscription` most current server implementations (eg. [apollo-server](https://www.apollographql.com/docs/apollo-server/data/subscriptions/)) does not support this yet. |
| 122 | + |
| 123 | +## API |
| 124 | + |
| 125 | +For now I provide basic overview of available API methods and I will describe them later. |
| 126 | + |
| 127 | +### Main API method: |
| 128 | + |
| 129 | +- `buildSchema(module: NodeModule, opts: BuildOptions): GraphQLSchema` – use this method for creating graphql schema |
| 130 | + |
| 131 | +### Advanced API methods: |
| 132 | + |
| 133 | +The following methods helps to use schema composition, applying middlewares and schema transformation via visitor pattern: |
| 134 | + |
| 135 | +- `loadSchemaComposer(module: NodeModule, options: BuildOptions): SchemaComposer` – construct SchemaComposer from folder (uses `directoryToAst` & `astToSchema` methods under the hood) |
| 136 | +- `directoryToAst(module: NodeModule, options: DirectoryToAstOptions): AstRootNode` – traverses directories and construct AST for your graphql entrypoints |
| 137 | +- `astToSchema(ast: AstRootNode, opts: AstToSchemaOptions): SchemaComposer` – converts AST to GraphQL Schema |
| 138 | +- `astMerge(...asts: Array<AstRootNode>): AstRootNode` – combines several ASTs to one AST (helps compose several graphql schemas) |
| 139 | +- `astVisitor(ast: AstRootNode, visitor: AstVisitor): void` – modify AST via visitor pattern |
0 commit comments