UNPKG

@eddeee888/gcg-typescript-resolver-files

Version:

This [GraphQL Code Generator](https://www.the-guild.dev/graphql/codegen) plugin creates resolvers given GraphQL schema.

283 lines 12.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseGraphQLSchema = void 0; const tslib_1 = require("tslib"); const path = tslib_1.__importStar(require("path")); const fs = tslib_1.__importStar(require("fs")); const graphql_1 = require("graphql"); const utils_1 = require("../utils"); const parseLocationForOutputDir_1 = require("./parseLocationForOutputDir"); const normalizeResolverName_1 = require("./normalizeResolverName"); const parseGraphQLSchema = (_a) => tslib_1.__awaiter(void 0, [_a], void 0, function* ({ schemaAst, sourceMap, resolverTypesPath, typeMappersMap, scalarsModule, scalarsOverrides, mode, baseOutputDir, resolverRelativeTargetDir, whitelistedModules, blacklistedModules, }) { const scalarsModuleResolverMap = scalarsModule ? yield getScalarResolverMapFromModule(scalarsModule) : {}; return Object.entries(schemaAst.getTypeMap()).reduce((res, [schemaType, namedType]) => { var _a, _b, _c; if ((0, utils_1.isNativeNamedType)(namedType)) { if ((0, graphql_1.isSpecifiedScalarType)(namedType)) { handleNativeScalarType({ schemaType, result: res, scalarsOverrides }); } return res; } // Root object types e.g. Query, Mutation, Subscription if ((0, utils_1.isRootObjectType)(schemaType) && (0, graphql_1.isObjectType)(namedType)) { Object.entries(namedType.getFields()).forEach(([fieldName, fieldNode]) => { var _a; const resolverDetails = createResolverDetails({ belongsToRootObject: schemaType, mode, sourceMap, resolverRelativeTargetDir, resolverTypesPath, baseOutputDir, blacklistedModules, whitelistedModules, schemaType, nestedDirs: [schemaType], location: (_a = fieldNode.astNode) === null || _a === void 0 ? void 0 : _a.loc, resolverName: fieldName, }); if (!resolverDetails) { return; } res.userDefinedSchemaTypeMap[schemaType.toLowerCase()][resolverDetails.normalizedResolverName.withModule] = resolverDetails; }); return res; } // Wire up `mappers` config: // - Interface // - Enum // - Non-root object types if ((0, graphql_1.isInterfaceType)(namedType) || (0, graphql_1.isEnumType)(namedType) || (!(0, utils_1.isRootObjectType)(schemaType) && (0, graphql_1.isObjectType)(namedType))) { const typeMapperDetails = typeMappersMap[schemaType]; if (typeMapperDetails) { res.pluginsConfig.defaultTypeMappers[typeMapperDetails.schemaType] = typeMapperDetails.configImportPath; } } // Other output object types if (!(0, utils_1.isRootObjectType)(schemaType) && (0, graphql_1.isObjectType)(namedType)) { handleObjectType({ mode, sourceMap, resolverTypesPath, resolverRelativeTargetDir, baseOutputDir, blacklistedModules, whitelistedModules, namedType, schemaType, result: res, }); return res; } // Handle scalar type wireups if ((0, graphql_1.isScalarType)(namedType)) { handleScalarType({ scalarsModuleResolverMap, schemaType, scalarsModule, scalarsOverrides, result: res, }); } // create resolver details for other types: // - Scalar // - Union // - Interface // - Enum const resolverDetails = createResolverDetails({ belongsToRootObject: null, mode, sourceMap, resolverRelativeTargetDir, resolverTypesPath, baseOutputDir, blacklistedModules, whitelistedModules, schemaType, nestedDirs: [], location: (_a = namedType.astNode) === null || _a === void 0 ? void 0 : _a.loc, resolverName: namedType.name, }); if (resolverDetails) { if ((0, graphql_1.isScalarType)(namedType)) { res.userDefinedSchemaTypeMap.scalar[schemaType] = resolverDetails; } else if ((0, graphql_1.isUnionType)(namedType)) { res.userDefinedSchemaTypeMap.union[schemaType] = resolverDetails; } else if ((0, graphql_1.isInterfaceType)(namedType)) { res.userDefinedSchemaTypeMap.interface[schemaType] = resolverDetails; } else if ((0, graphql_1.isEnumType)(namedType)) { res.userDefinedSchemaTypeMap.enum[schemaType] = Object.assign(Object.assign({}, resolverDetails), { allowedValues: ((_c = (_b = namedType.astNode) === null || _b === void 0 ? void 0 : _b.values) === null || _c === void 0 ? void 0 : _c.map((v) => v.name.value)) || [] }); } } return res; }, { userDefinedSchemaTypeMap: { query: {}, mutation: {}, subscription: {}, object: {}, scalar: {}, interface: {}, union: {}, enum: {}, }, pluginsConfig: { defaultScalarTypesMap: {}, scalarsModuleResolvers: {}, unmanagedScalarResolvers: {}, defaultTypeMappers: {}, }, }); }); exports.parseGraphQLSchema = parseGraphQLSchema; const handleScalarType = ({ scalarsModuleResolverMap, schemaType, scalarsModule, scalarsOverrides, result, }) => { const scalarsModuleResolver = scalarsModuleResolverMap[schemaType]; // Use found the scalar from scalar module if (scalarsModuleResolver) { if (scalarsModuleResolver.extensions.codegenScalarType && typeof scalarsModuleResolver.extensions.codegenScalarType === 'string') { result.pluginsConfig.defaultScalarTypesMap[schemaType] = scalarsModuleResolver.extensions.codegenScalarType; } result.pluginsConfig.scalarsModuleResolvers[schemaType] = `~${scalarsModule}#${scalarsModuleResolver.name}Resolver`; } // If found scalar overrides, use them const override = scalarsOverrides[schemaType]; if (override) { if (override.type) { result.pluginsConfig.defaultScalarTypesMap[schemaType] = override.type; } if (override.resolver) { result.pluginsConfig.unmanagedScalarResolvers[schemaType] = override.resolver; } } }; const getScalarResolverMapFromModule = (scalarsModule) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { let module; try { module = yield Promise.resolve(`${scalarsModule}`).then(s => tslib_1.__importStar(require(s))); } catch (err) { if (err instanceof Error && 'code' in err && err.code === 'MODULE_NOT_FOUND') { utils_1.logger.warn(`Unable to import \`${scalarsModule}\`. Install \`${scalarsModule}\` or you have to implement Scalar resolvers by yourself.`); } } if (!module || !module.resolvers) { return {}; } return module.resolvers; }); const handleNativeScalarType = ({ schemaType, result, scalarsOverrides, }) => { const override = scalarsOverrides[schemaType]; // Note: only override the type i.e. same functionality as `typescript` plugin's scalars // I've never seen someone overriding native scalar's implementation so it's probably not a thing. if (override && override.type) { result.pluginsConfig.defaultScalarTypesMap[schemaType] = override.type; } }; const handleObjectType = ({ mode, sourceMap, resolverTypesPath, resolverRelativeTargetDir, baseOutputDir, blacklistedModules, whitelistedModules, namedType, schemaType, result, }) => { // parse for details const fieldsByGraphQLModule = Object.entries(namedType.getFields()).reduce((res, [_, fieldNode]) => { var _a; const fieldLocation = (_a = fieldNode.astNode) === null || _a === void 0 ? void 0 : _a.loc; const modulePath = path.dirname((fieldLocation === null || fieldLocation === void 0 ? void 0 : fieldLocation.source.name) || ''); if (!res[modulePath]) { res[modulePath] = { fieldNodes: [], // Note: fieldLocation here is the location of the first field found in a GraphQL Module. // The reason we use field's location instead of the object type's location is because when `extend type ObjectType` is used, the location of object type is the last found location. // i.e. we cannot rely on object's location if `extend type` is used. firstFieldLocation: fieldLocation, }; } res[modulePath].fieldNodes.push(fieldNode); return res; }, {}); result.userDefinedSchemaTypeMap.object[schemaType] = result.userDefinedSchemaTypeMap.object[schemaType] || {}; Object.entries(fieldsByGraphQLModule).forEach(([_modulePath, { firstFieldLocation, fieldNodes }], _index, graphQLModules) => { const resolverDetails = createResolverDetails({ belongsToRootObject: null, mode, sourceMap, resolverRelativeTargetDir, resolverTypesPath, baseOutputDir, blacklistedModules, whitelistedModules, schemaType, nestedDirs: [], location: firstFieldLocation, resolverName: namedType.name, }); if (!resolverDetails) { return; } // If there are multiple object type files to generate // e.g. `extend type ObjectType` is used across multiple modules // We create an array of fields to pick for each module // // If there's only one module, we return an empty array i.e. pick all fields const fieldsToPick = graphQLModules.length > 1 ? fieldNodes.map((field) => field.name) : []; result.userDefinedSchemaTypeMap.object[schemaType][resolverDetails.normalizedResolverName.withModule] = Object.assign(Object.assign({}, resolverDetails), { fieldsToPick }); }); }; const createResolverDetails = ({ belongsToRootObject, mode, sourceMap, resolverRelativeTargetDir, resolverTypesPath, baseOutputDir, blacklistedModules, whitelistedModules, schemaType, nestedDirs, location, resolverName, }) => { const parsedDetails = (0, parseLocationForOutputDir_1.parseLocationForOutputDir)({ nestedDirs, location, mode, sourceMap, resolverRelativeTargetDir, baseOutputDir, blacklistedModules, whitelistedModules, }); if (!parsedDetails) { // No `parsedDetails` means the location is NOT whitelisted, ignore. return; } const { moduleName, resolversOutputDir, relativePathFromBaseToModule } = parsedDetails; const normalizedResolverName = (0, normalizeResolverName_1.normalizeResolverName)(moduleName, resolverName, belongsToRootObject); const resolverFilePath = path.posix.join(resolversOutputDir, `${resolverName}.ts`); return { schemaType, moduleName, resolverFile: { name: resolverName, path: resolverFilePath, isOnFilesystem: fs.existsSync(resolverFilePath), }, relativePathFromBaseToModule, normalizedResolverName, typeNamedImport: ({ generatedResolverTypes }) => { var _a; return ((_a = generatedResolverTypes.userDefined[schemaType]) === null || _a === void 0 ? void 0 : _a.name) || `${schemaType}Resolvers`; }, typeString: ({ generatedResolverTypes }) => { var _a; if (belongsToRootObject) { return generatedResolverTypes.userDefined[schemaType] ? `${generatedResolverTypes.userDefined[schemaType].name}['${resolverName}']` : `${schemaType}Resolvers['${resolverName}']`; } return (((_a = generatedResolverTypes.userDefined[schemaType]) === null || _a === void 0 ? void 0 : _a.name) || `${schemaType}Resolvers`); }, relativePathToResolverTypesFile: (0, utils_1.relativeModulePath)(resolversOutputDir, resolverTypesPath), }; }; //# sourceMappingURL=parseGraphQLSchema.js.map