UNPKG

@graphql-mesh/mongoose

Version:
129 lines (128 loc) 5.51 kB
import { specifiedDirectives } from 'graphql'; import { SchemaComposer } from 'graphql-compose'; import { composeWithMongoose, composeWithMongooseDiscriminators } from 'graphql-compose-mongoose'; import { connect, disconnect } from 'mongoose'; 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.name = name; this.config = config; this.baseDir = baseDir; this.pubsub = pubsub; this.importFn = importFn; this.logger = logger; } async getMeshSource() { if (this.config.connectionString) { connect(this.config.connectionString, { useNewUrlParser: true, useUnifiedTopology: true, logger: { className: this.name, debug: this.logger.debug.bind(this.logger), info: this.logger.info.bind(this.logger), warn: this.logger.warn.bind(this.logger), error: this.logger.error.bind(this.logger), isDebug() { return true; }, isError() { return true; }, isInfo() { return true; }, isWarn() { return true; }, }, loggerLevel: 'debug', }).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); await Promise.all([ Promise.all(modelQueryOperations.map(async (queryOperation) => schemaComposer.Query.addFields({ [`${modelConfig.name}_${queryOperation}`]: modelTC.getResolver(queryOperation), }))), Promise.all(modelMutationOperations.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, }; } }