UNPKG

@graphql-codegen/typescript-mongodb

Version:

GraphQL Code Generator plugin for generting a ready-to-use ORM types for MongoDB

234 lines (233 loc) • 11.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TsMongoVisitor = void 0; const tslib_1 = require("tslib"); const auto_bind_1 = tslib_1.__importDefault(require("auto-bind")); const graphql_1 = require("graphql"); const visitor_plugin_common_1 = require("@graphql-codegen/visitor-plugin-common"); const config_js_1 = require("./config.js"); const fields_tree_js_1 = require("./fields-tree.js"); function resolveObjectId(pointer) { if (!pointer) { return { identifier: 'ObjectId', module: 'mongodb' }; } if (pointer.includes('#')) { const [path, module] = pointer.split('#'); return { identifier: path, module }; } return { identifier: pointer, module: null, }; } class TsMongoVisitor extends visitor_plugin_common_1.BaseVisitor { constructor(_schema, pluginConfig) { super(pluginConfig, { dbTypeSuffix: pluginConfig.dbTypeSuffix || 'DbObject', dbInterfaceSuffix: pluginConfig.dbInterfaceSuffix || 'DbInterface', objectIdType: resolveObjectId(pluginConfig.objectIdType).identifier, objectIdImport: resolveObjectId(pluginConfig.objectIdType).module, idFieldName: pluginConfig.idFieldName || '_id', enumsAsString: (0, visitor_plugin_common_1.getConfigValue)(pluginConfig.enumsAsString, true), avoidOptionals: (0, visitor_plugin_common_1.getConfigValue)(pluginConfig.avoidOptionals, false), scalars: (0, visitor_plugin_common_1.buildScalarsFromConfig)(_schema, pluginConfig), }); this._schema = _schema; (0, auto_bind_1.default)(this); } get objectIdImport() { if (this.config.objectIdImport === null) { return null; } return `import { ${this.config.objectIdType} } from '${this.config.objectIdImport}';`; } _resolveDirectiveValue(valueNode) { switch (valueNode.kind) { case graphql_1.Kind.INT: case graphql_1.Kind.STRING: case graphql_1.Kind.FLOAT: case graphql_1.Kind.BOOLEAN: case graphql_1.Kind.ENUM: return valueNode.value; case graphql_1.Kind.LIST: return valueNode.values.map(v => this._resolveDirectiveValue(v)); case graphql_1.Kind.NULL: return null; case graphql_1.Kind.OBJECT: return valueNode.fields.reduce((prev, f) => { return { ...prev, [f.name.value]: this._resolveDirectiveValue(f.value), }; }, {}); default: return undefined; } } _getDirectiveArgValue(node, argName) { if (!node || !node.arguments || node.arguments.length === 0) { return undefined; } const foundArgument = node.arguments.find(a => a.name.value === argName); if (!foundArgument) { return undefined; } return this._resolveDirectiveValue(foundArgument.value); } _getDirectiveFromAstNode(node, directiveName) { if (!node || !node.directives || node.directives.length === 0) { return null; } const foundDirective = node.directives.find(d => d.name === directiveName || (d.name.value && d.name.value === directiveName)); if (!foundDirective) { return null; } return foundDirective; } _buildInterfaces(interfaces) { return (interfaces || []) .map(namedType => { const schemaType = this._schema.getType(namedType.name.value); const abstractEntityDirective = this._getDirectiveFromAstNode(schemaType.astNode, config_js_1.Directives.ABSTRACT_ENTITY); if (!abstractEntityDirective) { return null; } return this.convertName(namedType.name.value, { suffix: this.config.dbInterfaceSuffix }); }) .filter(a => a); } _handleIdField(fieldNode, tree, addOptionalSign) { tree.addField(`${this.config.idFieldName}${addOptionalSign ? '?' : ''}`, (0, visitor_plugin_common_1.wrapTypeNodeWithModifiers)(this.config.objectIdType, fieldNode.type)); } _handleLinkField(fieldNode, tree, linkDirective, mapPath, addOptionalSign) { const overrideType = this._getDirectiveArgValue(linkDirective, 'overrideType'); const coreType = overrideType || (0, visitor_plugin_common_1.getBaseTypeNode)(fieldNode.type); const type = this.convertName(coreType, { suffix: this.config.dbTypeSuffix }); tree.addField(`${mapPath || fieldNode.name.value}${addOptionalSign ? '?' : ''}`, (0, visitor_plugin_common_1.wrapTypeNodeWithModifiers)(`${type}['${this.config.idFieldName}']`, fieldNode.type)); } _handleColumnField(fieldNode, tree, columnDirective, mapPath, addOptionalSign) { const overrideType = this._getDirectiveArgValue(columnDirective, 'overrideType'); const coreType = (0, visitor_plugin_common_1.getBaseTypeNode)(fieldNode.type); let type = null; if (this.scalars[coreType.name.value]) { type = this.scalars[coreType.name.value]; } else { const schemaType = this._schema.getType(coreType.name.value); if ((0, graphql_1.isEnumType)(schemaType) && this.config.enumsAsString) { type = this.scalars.String; } else { type = coreType.name.value; } } tree.addField(`${mapPath || fieldNode.name.value}${addOptionalSign ? '?' : ''}`, overrideType || (0, visitor_plugin_common_1.wrapTypeNodeWithModifiers)(type, fieldNode.type)); } _handleEmbeddedField(fieldNode, tree, mapPath, addOptionalSign) { const coreType = (0, visitor_plugin_common_1.getBaseTypeNode)(fieldNode.type); const type = this.convertName(coreType, { suffix: this.config.dbTypeSuffix }); tree.addField(`${mapPath || fieldNode.name.value}${addOptionalSign ? '?' : ''}`, (0, visitor_plugin_common_1.wrapTypeNodeWithModifiers)(type, fieldNode.type)); } _buildFieldsTree(fields) { const tree = new fields_tree_js_1.FieldsTree(); fields.forEach(field => { const idDirective = this._getDirectiveFromAstNode(field, config_js_1.Directives.ID); const linkDirective = this._getDirectiveFromAstNode(field, config_js_1.Directives.LINK); const columnDirective = this._getDirectiveFromAstNode(field, config_js_1.Directives.COLUMN); const embeddedDirective = this._getDirectiveFromAstNode(field, config_js_1.Directives.EMBEDDED); const mapDirective = this._getDirectiveFromAstNode(field, config_js_1.Directives.MAP); const mapPath = this._getDirectiveArgValue(mapDirective, 'path'); const addOptionalSign = !this.config.avoidOptionals && field.type.kind !== graphql_1.Kind.NON_NULL_TYPE; if (idDirective) { this._handleIdField(field, tree, addOptionalSign); } else if (linkDirective) { this._handleLinkField(field, tree, linkDirective, mapPath, addOptionalSign); } else if (columnDirective) { this._handleColumnField(field, tree, columnDirective, mapPath, addOptionalSign); } else if (embeddedDirective) { this._handleEmbeddedField(field, tree, mapPath, addOptionalSign); } }); return tree; } _addAdditionalFields(tree, additioalFields) { const { avoidOptionals } = this.config; if (!additioalFields || additioalFields.length === 0) { return; } for (const field of additioalFields) { const isOptional = field.path.includes('?'); tree.addField(`${isOptional && avoidOptionals ? field.path.replace(/\?/g, '') : field.path}`, field.type); } } InterfaceTypeDefinition(node) { const abstractEntityDirective = this._getDirectiveFromAstNode(node, config_js_1.Directives.ABSTRACT_ENTITY); if (abstractEntityDirective === null) { return null; } const discriminatorField = this._getDirectiveArgValue(abstractEntityDirective, 'discriminatorField'); const additionalFields = this._getDirectiveArgValue(abstractEntityDirective, 'additionalFields'); const fields = this._buildFieldsTree(node.fields); fields.addField(discriminatorField, this.scalars.String); this._addAdditionalFields(fields, additionalFields); return new visitor_plugin_common_1.DeclarationBlock(this._declarationBlockConfig) .export() .asKind('type') .withName(this.convertName(node, { suffix: this.config.dbInterfaceSuffix })) .withBlock(fields.string).string; } UnionTypeDefinition(node) { const unionDirective = this._getDirectiveFromAstNode(node, config_js_1.Directives.UNION); if (unionDirective === null) { return null; } const discriminatorField = this._getDirectiveArgValue(unionDirective, 'discriminatorField'); const possibleTypes = node.types .map(namedType => { const schemaType = this._schema.getType(namedType.name.value); const entityDirective = this._getDirectiveFromAstNode(schemaType.astNode, config_js_1.Directives.ENTITY); const abstractEntityDirective = this._getDirectiveFromAstNode(schemaType.astNode, config_js_1.Directives.ABSTRACT_ENTITY); if (entityDirective) { return this.convertName(namedType, { suffix: this.config.dbTypeSuffix }); } if (abstractEntityDirective) { return this.convertName(namedType, { suffix: this.config.dbInterfaceSuffix }); } return null; }) .filter(a => a); if (possibleTypes.length === 0) { return null; } const additionalFields = this._getDirectiveArgValue(unionDirective, 'additionalFields'); const fields = new fields_tree_js_1.FieldsTree(); fields.addField(discriminatorField, this.scalars.String); this._addAdditionalFields(fields, additionalFields); return new visitor_plugin_common_1.DeclarationBlock(this._declarationBlockConfig) .export() .asKind('type') .withName(this.convertName(node, { suffix: this.config.dbTypeSuffix })) .withContent(`(${possibleTypes.join(' | ')}) & `) .withBlock(fields.string).string; } ObjectTypeDefinition(node) { const entityDirective = this._getDirectiveFromAstNode(node, config_js_1.Directives.ENTITY); if (entityDirective === null) { return null; } const implementingInterfaces = this._buildInterfaces(node.interfaces); const fields = this._buildFieldsTree(node.fields); const additionalFields = this._getDirectiveArgValue(entityDirective, 'additionalFields'); this._addAdditionalFields(fields, additionalFields); return new visitor_plugin_common_1.DeclarationBlock(this._declarationBlockConfig) .export() .asKind('type') .withName(this.convertName(node, { suffix: this.config.dbTypeSuffix })) .withContent(implementingInterfaces.length ? implementingInterfaces.join(' & ') + ' & ' : '') .withBlock(fields.string).string; } } exports.TsMongoVisitor = TsMongoVisitor;