UNPKG

@aws-amplify/graphql-generator

Version:
213 lines 9.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.sortPrependValues = exports.codegen = void 0; const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers"); const profiler_1 = require("../../../profiler"); const graphql_1 = require("graphql"); const execute_plugin_1 = require("./execute-plugin"); const utils_1 = require("@graphql-tools/utils"); const schema_1 = require("@graphql-tools/schema"); const utils_2 = require("./utils"); function codegen(options) { const documents = options.documents || []; const profiler = (0, profiler_1.createNoopProfiler)(); const skipDocumentsValidation = (0, utils_2.getSkipDocumentsValidationOption)(options); if (documents.length > 0 && (0, utils_2.shouldValidateDuplicateDocuments)(skipDocumentsValidation)) { profiler.run(() => validateDuplicateDocuments(documents), 'validateDuplicateDocuments'); } const pluginPackages = Object.keys(options.pluginMap).map(key => options.pluginMap[key]); const additionalTypeDefs = []; for (const plugin of pluginPackages) { const addToSchema = typeof plugin.addToSchema === 'function' ? plugin.addToSchema(options.config) : plugin.addToSchema; if (addToSchema) { additionalTypeDefs.push(addToSchema); } } const federationInConfig = (0, utils_2.pickFlag)('federation', options.config); const isFederation = (0, utils_2.prioritize)(federationInConfig, false); if (isFederation && !(0, utils_2.hasFederationSpec)(options.schemaAst || options.schema)) { additionalTypeDefs.push(plugin_helpers_1.federationSpec); } const mergeNeeded = !options.schemaAst || additionalTypeDefs.length > 0; const schemaInstance = profiler.run(() => { return mergeNeeded ? (0, schema_1.mergeSchemas)({ schemas: options.schemaAst ? [options.schemaAst] : [], typeDefs: options.schemaAst ? additionalTypeDefs : [options.schema, ...additionalTypeDefs], convertExtensions: true, assumeValid: true, assumeValidSDL: true, ...options.config, }) : options.schemaAst; }, 'Create schema instance'); const schemaDocumentNode = mergeNeeded || !options.schema ? (0, plugin_helpers_1.getCachedDocumentNodeFromSchema)(schemaInstance) : options.schema; if (schemaInstance && documents.length > 0 && (0, utils_2.shouldValidateDocumentsAgainstSchema)(skipDocumentsValidation)) { const ignored = ['NoUnusedFragments', 'NoUnusedVariables', 'KnownDirectives']; if (typeof skipDocumentsValidation === 'object' && skipDocumentsValidation.ignoreRules) { ignored.push(...(0, utils_1.asArray)(skipDocumentsValidation.ignoreRules)); } const extraFragments = (0, utils_2.pickFlag)('externalFragments', options.config) || []; const errors = profiler.run(() => { const fragments = extraFragments.map(f => ({ location: f.importFrom, document: { kind: graphql_1.Kind.DOCUMENT, definitions: [f.node] }, })); const rules = graphql_1.specifiedRules.filter(rule => !ignored.some(ignoredRule => rule.name.startsWith(ignoredRule))); const schemaHash = (0, utils_2.extractHashFromSchema)(schemaInstance); if (!schemaHash || !options.cache || documents.some(d => typeof d.hash !== 'string')) { return (0, utils_1.validateGraphQlDocuments)(schemaInstance, [...documents.flatMap(d => d.document), ...fragments.flatMap(f => f.document)], rules); } const cacheKey = [schemaHash] .concat(documents.map(doc => doc.hash)) .concat(JSON.stringify(fragments)) .join(','); return options.cache('documents-validation', cacheKey, () => (0, utils_1.validateGraphQlDocuments)(schemaInstance, [...documents.flatMap(d => d.document), ...fragments.flatMap(f => f.document)], rules)); }, 'Validate documents against schema'); if (errors.length > 0) { throw new Error(`GraphQL Document Validation failed with ${errors.length} errors; ${errors.map((error, index) => `Error ${index}: ${error.stack}`).join('\n\n')}`); } } const prepend = new Set(); const append = new Set(); const output = options.plugins.map(plugin => { const name = Object.keys(plugin)[0]; const pluginPackage = options.pluginMap[name]; const pluginConfig = plugin[name] || {}; const execConfig = typeof pluginConfig !== 'object' ? pluginConfig : { ...options.config, ...pluginConfig, }; const result = profiler.run(() => (0, execute_plugin_1.executePlugin)({ name, config: execConfig, parentConfig: options.config, schema: schemaDocumentNode, schemaAst: schemaInstance, documents: options.documents, outputFilename: options.filename, allPlugins: options.plugins, skipDocumentsValidation: options.skipDocumentsValidation, pluginContext: options.pluginContext, profiler, }, pluginPackage), `Plugin ${name}`); if (typeof result === 'string') { return result || ''; } if ((0, plugin_helpers_1.isComplexPluginOutput)(result)) { if (result.append && result.append.length > 0) { for (const item of result.append) { if (item) { append.add(item); } } } if (result.prepend && result.prepend.length > 0) { for (const item of result.prepend) { if (item) { prepend.add(item); } } } return result.content || ''; } return ''; }); return [...sortPrependValues(Array.from(prepend.values())), ...output, ...Array.from(append.values())] .filter(Boolean) .join('\n'); } exports.codegen = codegen; function resolveCompareValue(a) { if (a.startsWith('/*') || a.startsWith('//') || a.startsWith(' *') || a.startsWith(' */') || a.startsWith('*/')) { return 0; } if (a.startsWith('package')) { return 1; } if (a.startsWith('import')) { return 2; } return 3; } function sortPrependValues(values) { return values.sort((a, b) => { const aV = resolveCompareValue(a); const bV = resolveCompareValue(b); if (aV < bV) { return -1; } if (aV > bV) { return 1; } return 0; }); } exports.sortPrependValues = sortPrependValues; function validateDuplicateDocuments(files) { const definitionMap = {}; function addDefinition(file, node, deduplicatedDefinitions) { if (typeof node.name !== 'undefined') { if (!definitionMap[node.kind]) { definitionMap[node.kind] = {}; } if (!definitionMap[node.kind][node.name.value]) { definitionMap[node.kind][node.name.value] = { paths: new Set(), contents: new Set(), }; } const definitionKindMap = definitionMap[node.kind]; const length = definitionKindMap[node.name.value].contents.size; definitionKindMap[node.name.value].paths.add(file.location); definitionKindMap[node.name.value].contents.add((0, graphql_1.print)(node)); if (length === definitionKindMap[node.name.value].contents.size) { return null; } } return deduplicatedDefinitions.add(node); } files.forEach(file => { const deduplicatedDefinitions = new Set(); (0, graphql_1.visit)(file.document, { OperationDefinition(node) { addDefinition(file, node, deduplicatedDefinitions); }, FragmentDefinition(node) { addDefinition(file, node, deduplicatedDefinitions); }, }); file.document.definitions = Array.from(deduplicatedDefinitions); }); const kinds = Object.keys(definitionMap); kinds.forEach(kind => { const definitionKindMap = definitionMap[kind]; const names = Object.keys(definitionKindMap); if (names.length) { const duplicated = names.filter(name => definitionKindMap[name].contents.size > 1); if (!duplicated.length) { return; } const list = duplicated .map(name => ` * ${name} found in: ${[...definitionKindMap[name].paths] .map(filepath => { return ` - ${filepath} `.trimRight(); }) .join('')} `.trimRight()) .join(''); const definitionKindName = kind.replace('Definition', '').toLowerCase(); throw new Error(`Not all ${definitionKindName}s have an unique name: ${duplicated.join(', ')}: \n ${list} `); } }); } //# sourceMappingURL=codegen.js.map