Skip to content

Commit

Permalink
Merge pull request #107 from mernxl/mongoose-discriminantors
Browse files Browse the repository at this point in the history
Mongoose discriminantors, composeWithMongooseDiscriminators
  • Loading branch information
nodkz authored Jul 17, 2018
2 parents 34e756d + 6a7b2b0 commit 6d03cf0
Show file tree
Hide file tree
Showing 69 changed files with 5,452 additions and 1,050 deletions.
7 changes: 7 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"env": {
"cjs": {
"plugins": [
"transform-class-properties",
["transform-runtime", { "polyfill": false }]
],
"presets": [
Expand All @@ -17,6 +18,7 @@
]
},
"mjs": {
"plugins": ["transform-class-properties"],
"presets": [
[
"env",
Expand All @@ -31,9 +33,11 @@
]
},
"es": {
"plugins": ["transform-class-properties"],
},
"node8": {
"plugins": [
"transform-class-properties",
["transform-runtime", { "polyfill": false }]
],
"presets": [
Expand All @@ -47,6 +51,9 @@
]
},
"test": {
"plugins": [
"transform-class-properties",
],
"presets": [
["env", {
"targets": {
Expand Down
3 changes: 0 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ notifications:
node_js:
- "9"
- "8"
before_install: yarn global add greenkeeper-lockfile@1
before_script: greenkeeper-lockfile-update
after_script: greenkeeper-lockfile-upload
script:
- yarn run test
- yarn run build
Expand Down
131 changes: 125 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ const User = mongoose.model('User', UserSchema);
const customizationOptions = {}; // left it empty for simplicity, described below
const UserTC = composeWithMongoose(User, customizationOptions);

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

schemaComposer.rootMutation().addFields({
schemaComposer.Mutation.addFields({
userCreate: UserTC.getResolver('createOne'),
userUpdateById: UserTC.getResolver('updateById'),
userUpdateOne: UserTC.getResolver('updateOne'),
Expand All @@ -122,6 +122,126 @@ You think that is to much code?
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.


### Working with Mongoose Collection Level Discriminators
Variable Namings
* `...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.

```js
import mongoose from 'mongoose';
import { schemaComposer } from 'graphql-compose';
import { composeWithMongooseDiscriminators } from 'graphql-compose-mongoose';

// pick a discriminatorKey
const DKey = 'type';

const enumCharacterType = {
PERSON: 'Person',
DROID: 'Droid',
};

// DEFINE BASE SCHEMA
const CharacterSchema = new mongoose.Schema({
// _id: field...
type: {
type: String,
require: true,
enum: (Object.keys(enumCharacterType): Array<string>),
description: 'Character type Droid or Person',
},

name: String,
height: Number,
mass: Number,
films: [String],
});

// DEFINE DISCRIMINATOR SCHEMAS
const DroidSchema = new mongoose.Schema({
makeDate: String,
primaryFunction: [String],
});

const PersonSchema = new mongoose.Schema({
gender: String,
hairColor: String,
starships: [String],
});

// set discriminator Key
CharacterSchema.set('discriminatorKey', DKey);

// create base Model
const CharacterModel = mongoose.model('Character', CharacterSchema);

// create mongoose discriminator models
const DroidModel = CharacterModel.discriminator(enumCharacterType.DROID, DroidSchema);
const PersonModel = CharacterModel.discriminator(enumCharacterType.PERSON, PersonSchema);

// create DiscriminatorTypeComposer
const baseOptions = { // regular TypeConverterOptions, passed to composeWithMongoose
fields: {
remove: ['friends'],
}
}
const CharacterDTC = composeWithMongooseDiscriminators(CharacterModel, baseOptions);

// create Discriminator Types
const droidTypeConverterOptions = { // this options will be merged with baseOptions -> customisationsOptions
fields: {
remove: ['makeDate'],
}
};
const DroidTC = CharacterDTC.discriminator(DroidModel, droidTypeConverterOptions);
const PersonTC = CharacterDTC.discriminator(PersonModel); // baseOptions -> customisationsOptions applied

// You may now use CharacterDTC to add fields to all Discriminators
// Use DroidTC, `PersonTC as any other TypeComposer.
schemaComposer.Mutation.addFields({
droidCreate: DroidTC.getResolver('createOne'),
personCreate: PersonTC.getResolver('createOne'),
});

const schema = schemaComposer.buildSchema();

describe('createOne', () => {
it('should create child document without specifying DKey', async () => {
const res = await graphql.graphql(
schema,
`mutation CreateCharacters {
droidCreate(record: {name: "Queue XL", modelNumber: 360 }) {
record {
__typename
type
name
modelNumber
}
}
personCreate(record: {name: "mernxl", dob: 57275272}) {
record {
__typename
type
name
dob
}
}
}`
);

expect(res).toEqual({
data: {
droidCreate: {
record: { __typename: 'Droid', type: 'Droid', name: 'Queue XL', modelNumber: 360 },
},
personCreate: {
record: { __typename: 'Person', type: 'Person', name: 'mernxl', dob: 57275272 },
},
},
});
});
});
```

## FAQ

### Can I get generated vanilla GraphQL types?
Expand Down Expand Up @@ -273,7 +393,7 @@ The typical implementation may be like this:
// extend resolve params with hook
rp.beforeRecordMutate = async function(doc, rp) {
doc.userTouchedAt = new Date();

const canMakeUpdate = await performAsyncTask( ...provide data from doc... )
if (!canMakeUpdate) {
throw new Error('Forbidden!');
Expand Down Expand Up @@ -304,7 +424,7 @@ function adminAccess(resolvers) {

// extend resolve params with hook
rp.beforeRecordMutate = async function(doc, rp) { ... }

return next(rp)
})
})
Expand Down Expand Up @@ -465,4 +585,3 @@ This plugin adds `pagination` resolver.

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

4 changes: 2 additions & 2 deletions flow-typed/npm/babel-cli_vx.x.x.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// flow-typed signature: adfc416d3944bc9e0c30c54aa3ad632b
// flow-typed version: <<STUB>>/babel-cli_v^6.26.0/flow_v0.54.1
// flow-typed signature: 40ac71f9403783e7957989cfd3c8695f
// flow-typed version: <<STUB>>/babel-cli_v^6.26.0/flow_v0.76.0

/**
* This is an autogenerated libdef stub for:
Expand Down
Loading

0 comments on commit 6d03cf0

Please sign in to comment.