Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] - Feature: Discriminator Support on composeMongoose #340

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
643bae0
Switch type check to use 'instanceof' instead of constructor.name for…
jhbuchanan45 May 10, 2021
afe10e6
Fix linting error in case block
jhbuchanan45 May 12, 2021
8d9bdc6
Merge branch 'graphql-compose:master' into master
jhbuchanan45 May 21, 2021
7d11ae9
Implement optional discriminator handling inside composeMongoose func…
jhbuchanan45 May 24, 2021
0799c4e
Add unit test cases for enhanced discriminator handling
jhbuchanan45 May 24, 2021
fc20db7
Refactor input TC field adding into class method
jhbuchanan45 May 25, 2021
e602693
Export EDiscriminatorTypeComposer index exports and fix type error wi…
jhbuchanan45 May 25, 2021
d586798
Ensure correct types for DTCs are referenced in resolvers using tc.ge…
jhbuchanan45 May 25, 2021
16a5140
Fix bugs with discrimTC resolvers, such as preferring model over scha…
jhbuchanan45 May 26, 2021
425fbb4
Add test case for getDiscriminatorTCs()
jhbuchanan45 May 26, 2021
3cd5c33
Override makeFieldNullable/NonNull() for eDTC with tests
jhbuchanan45 May 27, 2021
01a7d71
Merge branch 'graphql-compose:master' into master
jhbuchanan45 Jun 10, 2021
1523524
Refactor calls to schemaComposer.getAnyTC(...) to use only tc.getType…
jhbuchanan45 Jun 10, 2021
e4b22a5
Merge branch 'graphql-compose:master' into master
jhbuchanan45 Jul 9, 2021
595b147
Merge changes from upstream (Especially allowing resolvers to accept …
jhbuchanan45 Jul 27, 2021
5c8bde5
Merge branch 'master' of https://github.com/graphql-compose/graphql-c…
jhbuchanan45 Jul 27, 2021
14d82de
Change eDTC to extend InterfaceTypeComposer and fix various resulting…
jhbuchanan45 Jul 29, 2021
7d29a85
Tidy eDTC code
jhbuchanan45 Jul 29, 2021
0167cb2
Revert resolvers using tc.getTypeName() instead of directly passing t…
jhbuchanan45 Jul 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/composeMongoose.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { SchemaComposer, Resolver, InputTypeComposer } from 'graphql-compose';
import { schemaComposer as globalSchemaComposer, ObjectTypeComposer } from 'graphql-compose';
import type { Model, Document } from 'mongoose';
import { EDiscriminatorTypeComposer } from './enhancedDiscriminators';
import { convertModelToGraphQL } from './fieldsConverter';
import { resolverFactory } from './resolvers';
import MongoID from './types/MongoID';
Expand Down Expand Up @@ -71,6 +72,15 @@ export type ComposeMongooseOpts<TContext = any> = {
* You can make fields as NonNull if they have default value in mongoose model.
*/
defaultsAsNonNull?: boolean;
/**
* Support discriminators on base models
*/
includeBaseDiscriminators?: boolean;
/**
* EXPERIMENTAL - Support discriminated fields on nested fields
* May not work as expected on input types for mutations
*/
includeNestedDiscriminators?: boolean;

/** @deprecated */
fields?: {
Expand Down Expand Up @@ -101,7 +111,7 @@ export type GenerateResolverType<TDoc extends Document, TContext = any> = {
export function composeMongoose<TDoc extends Document, TContext = any>(
model: Model<TDoc>,
opts: ComposeMongooseOpts<TContext> = {}
): ObjectTypeComposer<TDoc, TContext> & {
): (ObjectTypeComposer<TDoc, TContext> | EDiscriminatorTypeComposer<TDoc, TContext>) & {
mongooseResolvers: GenerateResolverType<TDoc, TContext>;
} {
const m: Model<any> = model;
Expand All @@ -121,7 +131,7 @@ export function composeMongoose<TDoc extends Document, TContext = any>(
sc.delete(m.schema);
}

const tc = convertModelToGraphQL(m, name, sc);
const tc = convertModelToGraphQL(m, name, sc, { ...opts });

if (opts.description) {
tc.setDescription(opts.description);
Expand Down
3 changes: 2 additions & 1 deletion src/discriminators/prepareBaseResolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export function prepareBaseResolvers(baseTC: DiscriminatorTypeComposer<any, any>
});
break;

case 'connection':
case 'connection': {
const edgesTC = resolver
.getOTC()
.getFieldOTC('edges')
Expand All @@ -91,6 +91,7 @@ export function prepareBaseResolvers(baseTC: DiscriminatorTypeComposer<any, any>

resolver.getOTC().setField('edges', edgesTC.NonNull.List.NonNull);
break;
}

default:
}
Expand Down
97 changes: 97 additions & 0 deletions src/enhancedDiscriminators/__mocks__/characterDiscrimModels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import type { Model } from 'mongoose';
import { mongoose, Schema, Types } from '../../__mocks__/mongooseCommon';

export const PersonSchema = new Schema({
dob: Number,
primaryFunction: [String],
starShips: [String],
totalCredits: Number,
});

export const DroidSchema = new Schema({
makeDate: Date,
modelNumber: Number,
primaryFunction: [String],
});

const MovieSchema = new Schema({
_id: String,

characters: {
type: [String], // redundant but i need it.
description: 'A character in the Movie, Person or Droid.',
},

director: {
type: String, // id of director
description: 'Directed the movie.',
},

imdbRatings: String,
releaseDate: String,
});

export const MovieModel = mongoose.model('Movie', MovieSchema);

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

export const CharacterObject = {
_id: {
type: String,
default: (): any => new Types.ObjectId(),
},
name: String,

type: {
type: String,
require: true,
enum: Object.keys(enumCharacterType),
},
kind: {
type: String,
require: true,
enum: Object.keys(enumCharacterType),
},

friends: [String], // another Character
appearsIn: [String], // movie
};

export function getCharacterModels(
DKey?: string,
name: string = 'Character'
): { CharacterModel: Model<any>; PersonModel: Model<any>; DroidModel: Model<any> } {
const CharacterSchema = DKey
? new Schema(CharacterObject, { discriminatorKey: DKey })
: new Schema(CharacterObject);

const CharacterModel: Model<any> = mongoose.model(name, CharacterSchema);

const PersonModel: Model<any> = CharacterModel.discriminator(
name + enumCharacterType.PERSON,
PersonSchema
);

const DroidModel: Model<any> = CharacterModel.discriminator(
name + enumCharacterType.DROID,
DroidSchema
);

return { CharacterModel, PersonModel, DroidModel };
}

export function getCharacterModelClone(): { NoDKeyCharacterModel: Model<any> } {
const ACharacterSchema = new Schema({ ...CharacterObject });
const NoDKeyCharacterModel = mongoose.model('NoDKeyCharacter', ACharacterSchema);

/*
const APersonModel = ACharacterModel.discriminator('A' + enumCharacterType.PERSON, PersonSchema.clone());

const ADroidModel = ACharacterModel.discriminator('A' + enumCharacterType.DROID, DroidSchema.clone());
*/

return { NoDKeyCharacterModel }; // APersonModel, ADroidModel };
}
Loading