Skip to content

Commit 6d03cf0

Browse files
authored
Merge pull request #107 from mernxl/mongoose-discriminantors
Mongoose discriminantors, composeWithMongooseDiscriminators
2 parents 34e756d + 6a7b2b0 commit 6d03cf0

File tree

69 files changed

+5452
-1050
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+5452
-1050
lines changed

.babelrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"env": {
77
"cjs": {
88
"plugins": [
9+
"transform-class-properties",
910
["transform-runtime", { "polyfill": false }]
1011
],
1112
"presets": [
@@ -17,6 +18,7 @@
1718
]
1819
},
1920
"mjs": {
21+
"plugins": ["transform-class-properties"],
2022
"presets": [
2123
[
2224
"env",
@@ -31,9 +33,11 @@
3133
]
3234
},
3335
"es": {
36+
"plugins": ["transform-class-properties"],
3437
},
3538
"node8": {
3639
"plugins": [
40+
"transform-class-properties",
3741
["transform-runtime", { "polyfill": false }]
3842
],
3943
"presets": [
@@ -47,6 +51,9 @@
4751
]
4852
},
4953
"test": {
54+
"plugins": [
55+
"transform-class-properties",
56+
],
5057
"presets": [
5158
["env", {
5259
"targets": {

.travis.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ notifications:
1010
node_js:
1111
- "9"
1212
- "8"
13-
before_install: yarn global add greenkeeper-lockfile@1
14-
before_script: greenkeeper-lockfile-update
15-
after_script: greenkeeper-lockfile-upload
1613
script:
1714
- yarn run test
1815
- yarn run build

README.md

Lines changed: 125 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ const User = mongoose.model('User', UserSchema);
9292
const customizationOptions = {}; // left it empty for simplicity, described below
9393
const UserTC = composeWithMongoose(User, customizationOptions);
9494

95-
// STEP 3: CREATE CRAZY GraphQL SCHEMA WITH ALL CRUD USER OPERATIONS
95+
// STEP 3: Add needed CRUD User operations to the GraphQL Schema
9696
// via graphql-compose it will be much much easier, with less typing
97-
schemaComposer.rootQuery().addFields({
97+
schemaComposer.Query.addFields({
9898
userById: UserTC.getResolver('findById'),
9999
userByIds: UserTC.getResolver('findByIds'),
100100
userOne: UserTC.getResolver('findOne'),
@@ -104,7 +104,7 @@ schemaComposer.rootQuery().addFields({
104104
userPagination: UserTC.getResolver('pagination'),
105105
});
106106

107-
schemaComposer.rootMutation().addFields({
107+
schemaComposer.Mutation.addFields({
108108
userCreate: UserTC.getResolver('createOne'),
109109
userUpdateById: UserTC.getResolver('updateById'),
110110
userUpdateOne: UserTC.getResolver('updateOne'),
@@ -122,6 +122,126 @@ You think that is to much code?
122122
I don't think so, because by default internally was created about 55 graphql types (for input, sorting, filtering). So you will need much much more lines of code to implement all these CRUD operations by hands.
123123

124124

125+
### Working with Mongoose Collection Level Discriminators
126+
Variable Namings
127+
* `...DTC` - Suffix for a `DiscriminatorTypeComposer` instance, which is also an instance of `TypeComposer`. All fields and Relations manipulations on this instance affects all registered discriminators and the Discriminator Interface.
128+
129+
```js
130+
import mongoose from 'mongoose';
131+
import { schemaComposer } from 'graphql-compose';
132+
import { composeWithMongooseDiscriminators } from 'graphql-compose-mongoose';
133+
134+
// pick a discriminatorKey
135+
const DKey = 'type';
136+
137+
const enumCharacterType = {
138+
PERSON: 'Person',
139+
DROID: 'Droid',
140+
};
141+
142+
// DEFINE BASE SCHEMA
143+
const CharacterSchema = new mongoose.Schema({
144+
// _id: field...
145+
type: {
146+
type: String,
147+
require: true,
148+
enum: (Object.keys(enumCharacterType): Array<string>),
149+
description: 'Character type Droid or Person',
150+
},
151+
152+
name: String,
153+
height: Number,
154+
mass: Number,
155+
films: [String],
156+
});
157+
158+
// DEFINE DISCRIMINATOR SCHEMAS
159+
const DroidSchema = new mongoose.Schema({
160+
makeDate: String,
161+
primaryFunction: [String],
162+
});
163+
164+
const PersonSchema = new mongoose.Schema({
165+
gender: String,
166+
hairColor: String,
167+
starships: [String],
168+
});
169+
170+
// set discriminator Key
171+
CharacterSchema.set('discriminatorKey', DKey);
172+
173+
// create base Model
174+
const CharacterModel = mongoose.model('Character', CharacterSchema);
175+
176+
// create mongoose discriminator models
177+
const DroidModel = CharacterModel.discriminator(enumCharacterType.DROID, DroidSchema);
178+
const PersonModel = CharacterModel.discriminator(enumCharacterType.PERSON, PersonSchema);
179+
180+
// create DiscriminatorTypeComposer
181+
const baseOptions = { // regular TypeConverterOptions, passed to composeWithMongoose
182+
fields: {
183+
remove: ['friends'],
184+
}
185+
}
186+
const CharacterDTC = composeWithMongooseDiscriminators(CharacterModel, baseOptions);
187+
188+
// create Discriminator Types
189+
const droidTypeConverterOptions = { // this options will be merged with baseOptions -> customisationsOptions
190+
fields: {
191+
remove: ['makeDate'],
192+
}
193+
};
194+
const DroidTC = CharacterDTC.discriminator(DroidModel, droidTypeConverterOptions);
195+
const PersonTC = CharacterDTC.discriminator(PersonModel); // baseOptions -> customisationsOptions applied
196+
197+
// You may now use CharacterDTC to add fields to all Discriminators
198+
// Use DroidTC, `PersonTC as any other TypeComposer.
199+
schemaComposer.Mutation.addFields({
200+
droidCreate: DroidTC.getResolver('createOne'),
201+
personCreate: PersonTC.getResolver('createOne'),
202+
});
203+
204+
const schema = schemaComposer.buildSchema();
205+
206+
describe('createOne', () => {
207+
it('should create child document without specifying DKey', async () => {
208+
const res = await graphql.graphql(
209+
schema,
210+
`mutation CreateCharacters {
211+
droidCreate(record: {name: "Queue XL", modelNumber: 360 }) {
212+
record {
213+
__typename
214+
type
215+
name
216+
modelNumber
217+
}
218+
}
219+
220+
personCreate(record: {name: "mernxl", dob: 57275272}) {
221+
record {
222+
__typename
223+
type
224+
name
225+
dob
226+
}
227+
}
228+
}`
229+
);
230+
231+
expect(res).toEqual({
232+
data: {
233+
droidCreate: {
234+
record: { __typename: 'Droid', type: 'Droid', name: 'Queue XL', modelNumber: 360 },
235+
},
236+
personCreate: {
237+
record: { __typename: 'Person', type: 'Person', name: 'mernxl', dob: 57275272 },
238+
},
239+
},
240+
});
241+
});
242+
});
243+
```
244+
125245
## FAQ
126246

127247
### Can I get generated vanilla GraphQL types?
@@ -273,7 +393,7 @@ The typical implementation may be like this:
273393
// extend resolve params with hook
274394
rp.beforeRecordMutate = async function(doc, rp) {
275395
doc.userTouchedAt = new Date();
276-
396+
277397
const canMakeUpdate = await performAsyncTask( ...provide data from doc... )
278398
if (!canMakeUpdate) {
279399
throw new Error('Forbidden!');
@@ -304,7 +424,7 @@ function adminAccess(resolvers) {
304424

305425
// extend resolve params with hook
306426
rp.beforeRecordMutate = async function(doc, rp) { ... }
307-
427+
308428
return next(rp)
309429
})
310430
})
@@ -465,4 +585,3 @@ This plugin adds `pagination` resolver.
465585

466586
## License
467587
[MIT](https://github.com/graphql-compose/graphql-compose-mongoose/blob/master/LICENSE.md)
468-

flow-typed/npm/babel-cli_vx.x.x.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// flow-typed signature: adfc416d3944bc9e0c30c54aa3ad632b
2-
// flow-typed version: <<STUB>>/babel-cli_v^6.26.0/flow_v0.54.1
1+
// flow-typed signature: 40ac71f9403783e7957989cfd3c8695f
2+
// flow-typed version: <<STUB>>/babel-cli_v^6.26.0/flow_v0.76.0
33

44
/**
55
* This is an autogenerated libdef stub for:

0 commit comments

Comments
 (0)