-
-
Notifications
You must be signed in to change notification settings - Fork 99
Expand file tree
/
Copy pathcomposeWithMongoose.ts
More file actions
96 lines (81 loc) · 3.27 KB
/
composeWithMongoose.ts
File metadata and controls
96 lines (81 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/* eslint-disable no-use-before-define, no-param-reassign, global-require */
import type { SchemaComposer } from 'graphql-compose';
import { ObjectTypeComposer, schemaComposer as globalSchemaComposer } from 'graphql-compose';
import type { Model, Document } from 'mongoose';
import { convertModelToGraphQL } from './fieldsConverter';
import { resolverFactory, AllResolversOpts } from './resolvers';
import MongoID from './types/MongoID';
import { GraphQLResolveInfo } from 'graphql';
import { TypeConverterInputTypeOpts, prepareFields, createInputType } from './composeMongoose';
export type ComposeWithMongooseOpts<TContext> = {
schemaComposer?: SchemaComposer<TContext>;
name?: string;
description?: string;
fields?: {
only?: string[];
// rename?: { [oldName: string]: string },
remove?: string[];
};
inputType?: TypeConverterInputTypeOpts;
resolvers?: false | AllResolversOpts;
/** You may customize document id */
transformRecordId?: TransformRecordIdFn<TContext>;
};
export type TransformRecordIdFn<TContext = any> = (
source: Document,
context: TContext,
info: GraphQLResolveInfo
) => any;
export function composeWithMongoose<TDoc extends Document, TContext = any>(
model: Model<TDoc>,
opts: ComposeWithMongooseOpts<TContext> = {}
): ObjectTypeComposer<TDoc, TContext> {
const m: Model<any> = model;
const name: string = (opts && opts.name) || m.modelName;
const sc = opts.schemaComposer || globalSchemaComposer;
sc.add(MongoID);
if (sc.has(name)) {
throw new Error(
`You try to generate GraphQL Type with name ${name} from mongoose model but this type already exists in SchemaComposer. Please choose another type name "composeWithMongoose(model, { name: 'NewTypeName' })", or reuse existed type "schemaComposer.getOTC('TypeName')", or remove type from SchemaComposer before calling composeWithMongoose method "schemaComposer.delete('TypeName')".`
);
}
if (sc.has(m.schema)) {
// looks like you want to generate new TypeComposer from model
// so remove cached model (which is used for cross-reference types)
sc.delete(m.schema);
}
const tc = convertModelToGraphQL(m, name, sc);
if (!(tc instanceof ObjectTypeComposer)) {
// should be impossible I hope
throw new Error(
'composeWithMongoose does not support discriminator mode, use composeMongoose or composeWithMongooseDiscriminators instead'
);
}
if (opts.description) {
tc.setDescription(opts.description);
}
prepareFields(tc, opts);
createInputType(tc, opts.inputType);
if (!{}.hasOwnProperty.call(opts, 'resolvers') || opts.resolvers !== false) {
createResolvers(m, tc, opts.resolvers || {});
}
tc.makeFieldNonNull('_id');
return tc;
}
export function createResolvers(
model: Model<any>,
tc: ObjectTypeComposer<any, any>,
opts: AllResolversOpts
): void {
(Object.keys(resolverFactory) as any).forEach((resolverName: keyof typeof resolverFactory) => {
if (!opts.hasOwnProperty(resolverName) || opts[resolverName] !== false) {
const createResolverFn = resolverFactory[resolverName] as any;
if (typeof createResolverFn === 'function') {
const resolver = createResolverFn(model, tc, opts[resolverName] || {});
if (resolver) {
tc.setResolver(resolverName, resolver);
}
}
}
});
}