|
2 | 2 |
|
3 | 3 | # create-graphql-server-query-arguments
|
4 | 4 |
|
5 |
| -Build query arguments for create-graphql-server GraphQL types for filter and orderBy MongoDB queries. |
| 5 | +Build query arguments for filter and orderBy MongoDB queries. |
6 | 6 |
|
| 7 | +** This is still under development ** |
| 8 | +** TODO: prepare proper end-to-end test cases for the different filters ** |
7 | 9 |
|
8 |
| -** This is work in progress ** |
| 10 | +## Purpose |
| 11 | +You build a GraphQL server with the npm package "create-graphql-server", which serves as a backend to web applications. This "create-graphql-server" generates schemas, resolvers and models for an express-js server. |
9 | 12 |
|
10 |
| -## Installation |
| 13 | +As soon as you are building the web application on top of this server, you want to access this backend server with specific GraphQL queries. Sometimes you want to set filters, to get just filtered records. Sometimes you want to sort data by different fields in ascending or descending order. Sometimes you want just pages of data with the first ten data records, or just the second page after the first ten records and so on. |
| 14 | + |
| 15 | +In order to enable such accesses to your GraphQL server backend, the schema needs to provide query arguments such as: |
| 16 | +* filter |
| 17 | +* orderBy |
| 18 | +* limit |
| 19 | +* skip |
| 20 | + |
| 21 | +TODO: as enhanced version of limit and skip: |
| 22 | +* first |
| 23 | +* before |
| 24 | +* last |
| 25 | +* after |
| 26 | + |
| 27 | +Additionally, your data model must know, how to map these query arguments into valid database queries for the mongoDB database. |
| 28 | + |
| 29 | +That's the purpose of this module. |
| 30 | +* it provides a function for the schema generator, to generate additional query arguments |
| 31 | +* it provides a function for basic types for all arguments later |
| 32 | +* it provides a function for the data model, to map query arguments, into a database query |
| 33 | + |
| 34 | +GraphQL query argument to mongoDB mapper: |
| 35 | +```javascript |
| 36 | +const { baseQuery, sortQuery, skip, limit} = prepareQueries( query_arguments ) |
| 37 | +``` |
| 38 | + |
| 39 | +GraphQL schema Query argument generator: |
| 40 | +```javascript |
| 41 | +buildRequiredTypes(); |
| 42 | +``` |
| 43 | + |
| 44 | +GraphQL schema Query argument generator: |
| 45 | +```javascript |
| 46 | +const enhancedOutputSchema = enhanceSchemaWithQueryArguments( inputSchema ); |
| 47 | +``` |
| 48 | + |
| 49 | +It provides the following query arguments: |
| 50 | + |
| 51 | +### orderBy |
| 52 | +All fields of the type definitions are automatically added to the orderBy sort field selection, except for associations to other types. |
| 53 | + |
| 54 | +### limit |
| 55 | +A limit argument is added, to choose the number of documents/records the query should return. |
| 56 | + |
| 57 | +### skip |
| 58 | +A skip argument is added, to skip a number of found records, not to be returned by the query. |
| 59 | + |
| 60 | +### filter |
| 61 | +The following filter query arguments are added to list types, which you can use to build complex queries: |
| 62 | +* eq |
| 63 | +* all |
| 64 | +* ne |
| 65 | +* in |
| 66 | +* nin |
| 67 | +* lt |
| 68 | +* lte |
| 69 | +* gt |
| 70 | +* gte |
| 71 | +* regex |
| 72 | +* contains |
| 73 | +* starts_with |
| 74 | +* ends_with |
| 75 | +* not_contains |
| 76 | +* not_starts_with |
| 77 | +* not_ends_with |
| 78 | +* not_in |
| 79 | +* exists |
| 80 | +* type |
| 81 | +* AND |
| 82 | +* NOT |
| 83 | +* NOR |
| 84 | +* OR |
| 85 | + |
| 86 | +## Installation |
| 87 | + |
| 88 | +### Installation Part 1 -- add the module to create-graphql-server project |
11 | 89 |
|
12 | 90 | ```bash
|
13 | 91 | yarn add create-graphql-server-query-arguments
|
14 | 92 | ```
|
15 | 93 |
|
| 94 | +### Installation Part 2 -- add it to the server for the mongoDB accesses |
| 95 | +Add this module to your express server in "create-graphql-server/skel/server/index.js" and provide it to your data model by: |
| 96 | +```javascript |
| 97 | +... |
| 98 | +import { prepareQueries } from 'create-graphql-server-query-arguments'; |
| 99 | +... |
| 100 | +``` |
| 101 | + |
| 102 | +... and also in skel/server/index.js add it it your your data model context by... |
| 103 | +```javascript |
| 104 | +... |
| 105 | +app.use('/graphql', (req, res, next) => { |
| 106 | + passport.authenticate('jwt', { session: false }, (err, me) => { |
| 107 | + req.context = addModelsToContext({ |
| 108 | + db, pubsub, me, UserCollection, log, prepareQueries // <=== |
| 109 | + }); |
| 110 | + graphqlExpress(() => { |
| 111 | + ... |
| 112 | + }) |
| 113 | + }); |
| 114 | +}) |
| 115 | +... |
| 116 | +``` |
| 117 | + |
| 118 | +Now you can access it in your data models with "this.context.prepareQueries": |
| 119 | +```javascript |
| 120 | +find(args, me, resolver) { |
| 121 | + const { baseQuery, sortQuery, skip, limit} = this.context.prepareQueries( args ); // <=== |
| 122 | + const authQuery = queryForRoles(/* auth logic here */); |
| 123 | + const finalQuery = { ...baseQuery, ...authQuery }; |
| 124 | + return this.collection |
| 125 | + .find(finalQuery) |
| 126 | + .sort(sortQuery) |
| 127 | + .skip(skip) |
| 128 | + .limit(limit) |
| 129 | + .toArray(); |
| 130 | +} |
| 131 | +``` |
| 132 | +Be sure, that also the resolver(s) pass on all "args" to your model method "find". |
| 133 | + |
| 134 | +Add these adjustments also to your: "test/output-app/server/index.js", otherwise your test runs will fail, as it compares the generated app files from "skel" with this "output-app" files. |
| 135 | + |
| 136 | +### Installation Part 3 -- General Type Definitions for all arguments, but can be defined only once |
| 137 | + |
| 138 | +add to file "skel/schema/index.js" |
| 139 | +```javascript |
| 140 | +... |
| 141 | +import { buildRequiredTypes } from 'create-graphql-server-query-arguments'; // <=== add this line |
| 142 | +... |
| 143 | +const typeDefs = [` |
| 144 | + scalar ObjID |
| 145 | +
|
| 146 | + type Query { |
| 147 | + # A placeholder, please ignore |
| 148 | + __placeholder: Int |
| 149 | + } |
| 150 | +
|
| 151 | + type Mutation { |
| 152 | + # A placeholder, please ignore |
| 153 | + __placeholder: Int |
| 154 | + } |
| 155 | +
|
| 156 | + type Subscription { |
| 157 | + # A placeholder, please ignore |
| 158 | + __placeholder: Int |
| 159 | + } |
| 160 | +`]; |
| 161 | + |
| 162 | +typeDefs.push(buildRequiredTypes()); // <=== add this line |
| 163 | + |
| 164 | +export default typeDefs; |
| 165 | +... |
| 166 | +``` |
| 167 | +Caution: Do the same again in the "test/output-app/schema/index.js" to have proper test runs. |
| 168 | + |
| 169 | +### Installation Part 4 -- Generator for Schema for individual argument type definitions |
| 170 | +Add to file "generate/index.js" the following two statements: |
| 171 | +```javascript |
| 172 | +... |
| 173 | +import { |
| 174 | + enhanceSchemaWithQueryArguments |
| 175 | +} from 'create-graphql-server-query-arguments'; // <=== |
| 176 | + |
| 177 | +export default function generate(inputSchemaStr) { |
| 178 | + const inputSchema = parse(inputSchemaStr); |
| 179 | + const type = inputSchema.definitions[0]; |
| 180 | + const TypeName = type.name.value; |
| 181 | + const typeName = lcFirst(TypeName); |
| 182 | + const outputSchema = generateSchema(inputSchema); |
| 183 | + const enhancedSchema = enhanceSchemaWithQueryArguments(outputSchema); // <=== |
| 184 | +... |
| 185 | +} |
| 186 | +``` |
| 187 | + |
| 188 | +Add those types to your outputSchema. |
| 189 | + |
| 190 | + |
| 191 | + |
16 | 192 | ## Documentation
|
17 | 193 | [API Documentation](https://tobkle.github.io/create-graphql-server-query-arguments/)
|
18 | 194 |
|
|
0 commit comments