@graphql-codegen/near-operation-file-preset
Version:
GraphQL Code Generator preset for generating operation code near the operation file
143 lines (142 loc) • 7.13 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.preset = exports.resolveDocumentImports = void 0;
const tslib_1 = require("tslib");
const path_1 = require("path");
const graphql_1 = require("graphql");
const add_1 = tslib_1.__importDefault(require("@graphql-codegen/add"));
const visitor_plugin_common_1 = require("@graphql-codegen/visitor-plugin-common");
const resolve_document_imports_js_1 = require("./resolve-document-imports.js");
Object.defineProperty(exports, "resolveDocumentImports", { enumerable: true, get: function () { return resolve_document_imports_js_1.resolveDocumentImports; } });
const utils_js_1 = require("./utils.js");
exports.preset = {
buildGeneratesSection: options => {
var _a;
const schemaObject = options.schemaAst
? options.schemaAst
: (0, graphql_1.buildASTSchema)(options.schema, options.config);
const baseDir = options.presetConfig.cwd || process.cwd();
const fileName = options.presetConfig.fileName || '';
const extension = options.presetConfig.extension || '.generated.ts';
const folder = options.presetConfig.folder || '';
const importTypesNamespace = options.presetConfig.importTypesNamespace || 'Types';
const importAllFragmentsFrom = options.presetConfig.importAllFragmentsFrom || null;
const { baseTypesPath } = options.presetConfig;
if (!baseTypesPath) {
throw new Error(`Preset "near-operation-file" requires you to specify "baseTypesPath" configuration and point it to your base types file (generated by "typescript" plugin)!`);
}
const shouldAbsolute = !baseTypesPath.startsWith('~');
const pluginMap = {
...options.pluginMap,
add: add_1.default,
};
const sources = (0, resolve_document_imports_js_1.resolveDocumentImports)(options, schemaObject, {
baseDir,
generateFilePath(location) {
const newFilePath = (0, utils_js_1.defineFilepathSubfolder)(location, folder);
return (0, utils_js_1.appendFileNameToFilePath)(newFilePath, fileName, extension);
},
schemaTypesSource: {
path: shouldAbsolute ? (0, path_1.join)(options.baseOutputDir, baseTypesPath) : baseTypesPath,
namespace: importTypesNamespace,
},
typesImport: (_a = options.config.useTypeImports) !== null && _a !== void 0 ? _a : false,
}, (0, visitor_plugin_common_1.getConfigValue)(options.config.dedupeFragments, false));
const filePathsMap = new Map();
for (const source of sources) {
let record = filePathsMap.get(source.filename);
if (record === undefined) {
record = {
importStatements: new Set(),
documents: [],
externalFragments: [],
fragmentImports: [],
};
filePathsMap.set(source.filename, record);
}
for (const importStatement of source.importStatements) {
record.importStatements.add(importStatement);
}
record.documents.push(...source.documents);
record.externalFragments.push(...source.externalFragments);
record.fragmentImports.push(...source.fragmentImports);
}
const artifacts = [];
for (const [filename, record] of filePathsMap.entries()) {
let fragmentImportsArr = record.fragmentImports;
if (importAllFragmentsFrom) {
fragmentImportsArr = record.fragmentImports.map(t => {
const newImportSource = typeof importAllFragmentsFrom === 'string'
? { ...t.importSource, path: importAllFragmentsFrom }
: importAllFragmentsFrom(t.importSource, filename);
return {
...t,
importSource: newImportSource || t.importSource,
};
});
}
// Merge multiple fragment imports from the same file
const fragmentImportsByImportSource = {};
fragmentImportsArr.forEach(fi => {
if (!fragmentImportsByImportSource[fi.importSource.path]) {
fragmentImportsByImportSource[fi.importSource.path] = fi;
}
else {
const mergedIdentifiersByName = {};
fragmentImportsByImportSource[fi.importSource.path].importSource.identifiers.forEach(identifier => {
mergedIdentifiersByName[identifier.name] = identifier;
});
fi.importSource.identifiers.forEach(identifier => {
mergedIdentifiersByName[identifier.name] = identifier;
});
fragmentImportsByImportSource[fi.importSource.path].importSource.identifiers =
Object.values(mergedIdentifiersByName);
}
});
fragmentImportsArr = Object.values(fragmentImportsByImportSource);
const plugins = [
// TODO/NOTE I made globalNamespace include schema types - is that correct?
...(options.config.globalNamespace
? []
: Array.from(record.importStatements).map(importStatement => ({
add: { content: importStatement },
}))),
...options.plugins,
];
const config = {
...options.config,
// This is set here in order to make sure the fragment spreads sub types
// are exported from operations file
exportFragmentSpreadSubTypes: true,
namespacedImportName: importTypesNamespace,
externalFragments: record.externalFragments,
fragmentImports: fragmentImportsArr,
};
const document = { kind: graphql_1.Kind.DOCUMENT, definitions: [] };
const combinedSource = {
rawSDL: '',
document,
location: record.documents[0].location,
};
for (const source of record.documents) {
combinedSource.rawSDL += source.rawSDL;
combinedSource.document.definitions.push(...source.document.definitions);
}
artifacts.push({
...options,
filename,
documents: [combinedSource],
plugins,
pluginMap,
config,
schema: options.schema,
schemaAst: schemaObject,
skipDocumentsValidation: typeof options.config.skipDocumentsValidation === 'undefined'
? { skipDuplicateValidation: true }
: options.config.skipDocumentsValidation,
});
}
return artifacts;
},
};
exports.default = exports.preset;
;