UNPKG

@graphql-codegen/near-operation-file-preset

Version:

GraphQL Code Generator preset for generating operation code near the operation file

132 lines (131 loc) 6.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const graphql_1 = require("graphql"); const visitor_plugin_common_1 = require("@graphql-codegen/visitor-plugin-common"); const utils_js_1 = require("./utils.js"); /** * Used by `buildFragmentResolver` to build a mapping of fragmentNames to paths, importNames, and other useful info */ function buildFragmentRegistry({ generateFilePath }, { documents, config }, schemaObject) { const baseVisitor = new visitor_plugin_common_1.BaseVisitor(config, { scalars: (0, visitor_plugin_common_1.buildScalarsFromConfig)(schemaObject, config), dedupeOperationSuffix: (0, visitor_plugin_common_1.getConfigValue)(config.dedupeOperationSuffix, false), omitOperationSuffix: (0, visitor_plugin_common_1.getConfigValue)(config.omitOperationSuffix, false), fragmentVariablePrefix: (0, visitor_plugin_common_1.getConfigValue)(config.fragmentVariablePrefix, ''), fragmentVariableSuffix: (0, visitor_plugin_common_1.getConfigValue)(config.fragmentVariableSuffix, 'FragmentDoc'), }); const getFragmentImports = (possbileTypes, name) => { const fragmentImports = []; fragmentImports.push({ name: baseVisitor.getFragmentVariableName(name), kind: 'document' }); const fragmentSuffix = baseVisitor.getFragmentSuffix(name); if (possbileTypes.length === 1) { fragmentImports.push({ name: baseVisitor.convertName(name, { useTypesPrefix: true, suffix: fragmentSuffix, }), kind: 'type', }); } else if (possbileTypes.length !== 0) { possbileTypes.forEach(typeName => { fragmentImports.push({ name: baseVisitor.convertName(name, { useTypesPrefix: true, suffix: `_${typeName}_${fragmentSuffix}`, }), kind: 'type', }); }); } return fragmentImports; }; const duplicateFragmentNames = []; const registry = documents.reduce((prev, documentRecord) => { const fragments = documentRecord.document.definitions.filter(d => d.kind === graphql_1.Kind.FRAGMENT_DEFINITION); if (fragments.length > 0) { for (const fragment of fragments) { const schemaType = schemaObject.getType(fragment.typeCondition.name.value); if (!schemaType) { throw new Error(`Fragment "${fragment.name.value}" is set on non-existing type "${fragment.typeCondition.name.value}"!`); } const possibleTypes = (0, visitor_plugin_common_1.getPossibleTypes)(schemaObject, schemaType); const filePath = generateFilePath(documentRecord.location); const imports = getFragmentImports(possibleTypes.map(t => t.name), fragment.name.value); if (prev[fragment.name.value] && (0, graphql_1.print)(fragment) !== (0, graphql_1.print)(prev[fragment.name.value].node)) { duplicateFragmentNames.push(fragment.name.value); } prev[fragment.name.value] = { filePath, imports, onType: fragment.typeCondition.name.value, node: fragment, }; } } return prev; }, {}); if (duplicateFragmentNames.length) { throw new Error(`Multiple fragments with the name(s) "${duplicateFragmentNames.join(', ')}" were found.`); } return registry; } /** * Builds a fragment "resolver" that collects `externalFragments` definitions and `fragmentImportStatements` */ function buildFragmentResolver(collectorOptions, presetOptions, schemaObject, dedupeFragments = false) { const fragmentRegistry = buildFragmentRegistry(collectorOptions, presetOptions, schemaObject); const { baseOutputDir } = presetOptions; const { baseDir, typesImport } = collectorOptions; function resolveFragments(generatedFilePath, documentFileContent) { const fragmentsInUse = (0, utils_js_1.extractExternalFragmentsInUse)(documentFileContent, fragmentRegistry); const externalFragments = []; // fragment files to import names const fragmentFileImports = {}; for (const fragmentName of Object.keys(fragmentsInUse)) { const level = fragmentsInUse[fragmentName]; const fragmentDetails = fragmentRegistry[fragmentName]; if (fragmentDetails) { // add top level references to the import object // we don't checkf or global namespace because the calling config can do so if (level === 0 || (dedupeFragments && ['OperationDefinition', 'FragmentDefinition'].includes(documentFileContent.definitions[0].kind))) { if (fragmentDetails.filePath !== generatedFilePath) { // don't emit imports to same location if (fragmentFileImports[fragmentDetails.filePath] === undefined) { fragmentFileImports[fragmentDetails.filePath] = fragmentDetails.imports; } else { fragmentFileImports[fragmentDetails.filePath].push(...fragmentDetails.imports); } } } externalFragments.push({ level, isExternal: true, name: fragmentName, onType: fragmentDetails.onType, node: fragmentDetails.node, }); } } return { externalFragments, fragmentImports: Object.entries(fragmentFileImports).map(([fragmentsFilePath, identifiers]) => ({ baseDir, baseOutputDir, outputPath: generatedFilePath, importSource: { path: fragmentsFilePath, identifiers, }, emitLegacyCommonJSImports: presetOptions.config.emitLegacyCommonJSImports, typesImport, })), }; } return resolveFragments; } exports.default = buildFragmentResolver;