UNPKG

@graphql-mesh/mongoose

Version:
120 lines (119 loc) 5.52 kB
import { specifiedDirectives } from 'graphql'; import { SchemaComposer } from 'graphql-compose'; import { composeWithMongoose, composeWithMongooseDiscriminators } from 'graphql-compose-mongoose'; import { connect, disconnect } from 'mongoose'; import { stringInterpolator } from '@graphql-mesh/string-interpolation'; import { loadFromModuleExportExpression } from '@graphql-mesh/utils'; const modelQueryOperations = [ 'findById', 'findByIds', 'findOne', 'findMany', 'count', 'connection', 'pagination', 'dataLoader', 'dataLoaderMany', ]; const modelMutationOperations = [ 'createOne', 'createMany', 'updateById', 'updateOne', 'updateMany', 'removeById', 'removeOne', 'removeMany', ]; export default class MongooseHandler { constructor({ name, config, baseDir, pubsub, importFn, logger, }) { this.config = config; this.baseDir = baseDir; this.pubsub = pubsub; this.importFn = importFn; this.logger = logger; } async getMeshSource() { if (this.config.connectionString) { const interpolatedConnectionString = stringInterpolator.parse(this.config.connectionString, { env: process.env, }); connect(interpolatedConnectionString, { useNewUrlParser: true, useUnifiedTopology: true, }).catch(e => this.logger.error(e)); const id = this.pubsub.subscribe('destroy', () => { disconnect() .catch(e => this.logger.error(e)) .finally(() => this.pubsub.unsubscribe(id)); }); } const schemaComposer = new SchemaComposer(); const typeMergingOptions = {}; await Promise.all([ Promise.all(this.config.models?.map(async (modelConfig) => { const model = await loadFromModuleExportExpression(modelConfig.path, { defaultExportName: modelConfig.name, cwd: this.baseDir, importFn: this.importFn, }); if (!model) { throw new Error(`Model ${modelConfig.name} cannot be imported ${modelConfig.path}!`); } const modelTC = composeWithMongoose(model, modelConfig.options); const resolversOption = modelConfig.options?.resolvers; function isResolverEnabled(operation) { return (resolversOption == null || Object.prototype.hasOwnProperty.call(resolversOption, operation) || resolversOption[operation] !== false); } const enabledQueryOperations = modelQueryOperations.filter(isResolverEnabled); const enabledMutationOperations = modelMutationOperations.filter(isResolverEnabled); await Promise.all([ Promise.all(enabledQueryOperations.map(async (queryOperation) => schemaComposer.Query.addFields({ [`${modelConfig.name}_${queryOperation}`]: modelTC.getResolver(queryOperation), }))), Promise.all(enabledMutationOperations.map(async (mutationOperation) => schemaComposer.Mutation.addFields({ [`${modelConfig.name}_${mutationOperation}`]: modelTC.getResolver(mutationOperation), }))), ]); const typeName = modelTC.getTypeName(); typeMergingOptions[typeName] = { selectionSet: `{ id }`, key: ({ id }) => id, argsFromKeys: ids => ({ ids }), fieldName: `${typeName}_dataLoaderMany`, }; }) || []), Promise.all(this.config.discriminators?.map(async (discriminatorConfig) => { const discriminator = await loadFromModuleExportExpression(discriminatorConfig.path, { defaultExportName: discriminatorConfig.name, cwd: this.baseDir, importFn: this.importFn, }); const discriminatorTC = composeWithMongooseDiscriminators(discriminator, discriminatorConfig.options); await Promise.all([ Promise.all(modelQueryOperations.map(async (queryOperation) => schemaComposer.Query.addFields({ [`${discriminatorConfig.name}_${queryOperation}`]: discriminatorTC.getResolver(queryOperation), }))), Promise.all(modelMutationOperations.map(async (mutationOperation) => schemaComposer.Mutation.addFields({ [`${discriminatorConfig.name}_${mutationOperation}`]: discriminatorTC.getResolver(mutationOperation), }))), ]); const typeName = discriminatorTC.getTypeName(); typeMergingOptions[typeName] = { selectionSet: `{ id }`, key: ({ id }) => id, argsFromKeys: ids => ({ ids }), fieldName: `${typeName}_dataLoaderMany`, }; }) || []), ]); // graphql-compose doesn't add @defer and @stream to the schema specifiedDirectives.forEach(directive => schemaComposer.addDirective(directive)); const schema = schemaComposer.buildSchema(); return { schema, }; } }