@eddeee888/gcg-typescript-resolver-files
Version:
This [GraphQL Code Generator](https://www.the-guild.dev/graphql/codegen) plugin creates resolvers given GraphQL schema.
213 lines • 11.5 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.preset = exports.presetName = void 0;
const tslib_1 = require("tslib");
const path = tslib_1.__importStar(require("path"));
const addPlugin = tslib_1.__importStar(require("@graphql-codegen/add"));
const schemaAstPlugin = tslib_1.__importStar(require("@graphql-codegen/schema-ast"));
const typeScriptPlugin = tslib_1.__importStar(require("@graphql-codegen/typescript"));
const typescript_resolvers_1 = require("@graphql-codegen/typescript-resolvers");
const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
const ts_morph_1 = require("ts-morph");
const gcg_server_config_1 = require("@eddeee888/gcg-server-config");
const parseSources_1 = require("./parseSources");
const parseGraphQLSchema_1 = require("./parseGraphQLSchema");
const generateResolverFiles_1 = require("./generateResolverFiles");
const generateTypeDefsFiles_1 = require("./generateTypeDefsFiles");
const getGraphQLObjectTypeResolversToGenerate_1 = require("./getGraphQLObjectTypeResolversToGenerate");
const addVirtualTypesFileToTsMorphProject_1 = require("./addVirtualTypesFileToTsMorphProject");
const parseTypeMappers_1 = require("./parseTypeMappers");
const validatePresetConfig_1 = require("./validatePresetConfig");
const validateAndMergeParsedConfigs_1 = require("./validateAndMergeParsedConfigs");
const normalizeAddConfigPath_1 = require("./normalizeAddConfigPath");
const utils_1 = require("./utils");
exports.presetName = '@eddeee888/gcg-typescript-resolver-files';
exports.preset = {
buildGeneratesSection: (_a) => tslib_1.__awaiter(void 0, [_a], void 0, function* ({ schema, schemaAst, presetConfig: rawPresetConfig, baseOutputDir, profiler = (0, plugin_helpers_1.createNoopProfiler)(), }) {
if (!schemaAst) {
throw new Error('Missing schemaAst');
}
const sources = schemaAst.extensions.extendedSources;
if (!Array.isArray(sources) || sources.length === 0) {
throw new Error('Empty Sources. Make sure schema files are parsed correctly.');
}
const { add, resolverTypesPath: relativeResolverTypesPathFromBaseOutputDir, resolverRelativeTargetDir, mappersRelativeTargetDir: typeMappersRelativeTargetDir, mappersFileExtension: typeMappersFileExtension, mappersSuffix: typeMappersSuffix, resolverMainFile, resolverMainFileMode, resolverGeneration, typeDefsFilePath, typeDefsFileMode, mergeSchema, moduleNamingMode, scalarsModule, scalarsOverrides, mode, whitelistedModules, blacklistedModules, externalResolvers, typesPluginsConfig, tsMorphProjectOptions, fixObjectTypeResolvers, emitLegacyCommonJSImports, } = (0, validatePresetConfig_1.validatePresetConfig)(rawPresetConfig);
const resolverTypesPath = path.posix.join(baseOutputDir, relativeResolverTypesPathFromBaseOutputDir);
const normalizedAdd = (0, normalizeAddConfigPath_1.normalizeAddConfigPath)({ add, baseOutputDir });
const { sourceMap } = (0, parseSources_1.parseSources)({
sources,
baseOutputDir,
moduleNamingMode,
});
const tsMorphProject = yield profiler.run(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () { return new ts_morph_1.Project(tsMorphProjectOptions); }), createProfilerRunName('Initialising ts-morph project'));
const typeMappersMap = yield profiler.run(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
return (0, parseTypeMappers_1.parseTypeMappers)({
sourceMap,
resolverTypesPath,
typeMappersRelativeTargetDir,
typeMappersFileExtension,
typeMappersSuffix,
tsMorphProject,
emitLegacyCommonJSImports,
});
}), createProfilerRunName('parseTypeMappers'));
const generatesSection = [];
const parsedGraphQLSchemaMeta = yield profiler.run(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
return (0, parseGraphQLSchema_1.parseGraphQLSchema)({
schemaAst,
sourceMap,
resolverTypesPath,
scalarsModule,
scalarsOverrides,
typeMappersMap,
mode,
baseOutputDir,
resolverRelativeTargetDir,
whitelistedModules,
blacklistedModules,
});
}), createProfilerRunName('parseGraphQLSchema'));
const mergedConfig = (0, validateAndMergeParsedConfigs_1.validateAndMergeParsedConfigs)({
unmanagedNonScalarResolvers: externalResolvers,
parsedGraphQLSchemaMeta,
});
// typescript and typescript-resolvers plugins config
const resolverTypesConfig = (0, gcg_server_config_1.defineConfig)(Object.assign(Object.assign({ optionalResolveType: true, resolversNonOptionalTypename: {
unionMember: true,
interfaceImplementingType: true,
}, namingConvention: 'keep', emitLegacyCommonJSImports, generateInternalResolversIfNeeded: {
__resolveReference: true,
} }, typesPluginsConfig), { scalars: mergedConfig.scalarTypes, mappers: Object.assign(Object.assign({}, mergedConfig.typeMappers), typesPluginsConfig.mappers) }));
// typesSourceFile is the virtual `types.generated.ts`
// This is useful when we need to do static analysis as most types come from this file
// e.g. comparing mappers field type vs schema object field type
const { typesSourceFile, meta: generatedTypesFileMeta } = yield profiler.run(() => (0, addVirtualTypesFileToTsMorphProject_1.addVirtualTypesFileToTsMorphProject)({
tsMorphProject,
schemaAst,
resolverTypesConfig,
resolverTypesPath,
addConfig: normalizedAdd === null || normalizedAdd === void 0 ? void 0 : normalizedAdd[resolverTypesPath],
}), createProfilerRunName('addVirtualTypesFileToTsMorphProject'));
const graphQLObjectTypeResolversToGenerate = yield profiler.run(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
return fixObjectTypeResolvers.object === 'smart'
? (0, getGraphQLObjectTypeResolversToGenerate_1.getGraphQLObjectTypeResolversToGenerate)({
tsMorphProject,
typesSourceFile,
userDefinedSchemaObjectTypeMap: mergedConfig.userDefinedSchemaTypeMap.object,
typeMappersMap,
generatedTypesFileMeta,
})
: {};
}), createProfilerRunName('getGraphQLObjectTypeResolversToGenerate'));
const resolverTypesFilePlugins = [
{ typescript: {} },
{ ['typescript-resolvers']: {} },
];
if (normalizedAdd === null || normalizedAdd === void 0 ? void 0 : normalizedAdd[resolverTypesPath]) {
resolverTypesFilePlugins.push({
add: normalizedAdd[resolverTypesPath],
});
}
const resolverTypesFile = {
filename: resolverTypesPath,
pluginMap: {
typescript: typeScriptPlugin,
'typescript-resolvers': { plugin: typescript_resolvers_1.plugin },
add: addPlugin,
},
plugins: resolverTypesFilePlugins,
config: resolverTypesConfig,
schema,
documents: [],
};
generatesSection.push(resolverTypesFile);
// typeDefs
if (typeDefsFilePath) {
const typeDefsFiles = yield profiler.run(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
return (0, generateTypeDefsFiles_1.generateTypeDefsFiles)({
baseOutputDir,
typeDefsFilePath,
typeDefsFileMode,
sourceMap,
whitelistedModules,
blacklistedModules,
});
}), createProfilerRunName('generateTypeDefsFiles'));
Object.entries(typeDefsFiles).forEach(([filename, meta]) => {
const typeDefsFile = {
filename: filename,
pluginMap: { add: addPlugin },
plugins: [{ add: { content: meta.content } }],
config: {},
schema,
documents: [],
};
generatesSection.push(typeDefsFile);
});
}
// merge schema
if (mergeSchema) {
generatesSection.push({
filename: path.posix.join(baseOutputDir, mergeSchema.path),
pluginMap: { ['schema-ast']: schemaAstPlugin },
plugins: [{ ['schema-ast']: {} }],
schema,
documents: [],
config: mergeSchema.config,
});
}
// resolver files
const result = {
files: {},
externalImports: {},
};
yield profiler.run(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
return (0, generateResolverFiles_1.generateResolverFiles)({
config: {
baseOutputDir,
resolverTypesPath,
resolverRelativeTargetDir,
resolverMainFile,
resolverMainFileMode,
resolverGeneration,
typeMappersMap,
parsedGraphQLSchemaMeta,
graphQLObjectTypeResolversToGenerate,
tsMorph: {
project: tsMorphProject,
typesSourceFile,
},
fixObjectTypeResolvers,
unmanagedResolvers: Object.assign({}, mergedConfig.unmanagedResolvers),
emitLegacyCommonJSImports,
generatedTypesFileMeta,
},
result,
});
}), createProfilerRunName('generateResolverFiles'));
const resultFilesArray = Object.entries(result.files);
const resolverFilesGenerateOptions = resultFilesArray
.filter(([_, file]) => {
// Only generate files that are:
// 1. `virtual` - because file doesn't exist yet
// 2. on `filesystem` and with `contentUpdated` - because file content has been updated, so we want to apply the changes
return (file.filesystem.type === 'virtual' ||
(file.filesystem.type === 'filesystem' &&
file.filesystem.contentUpdated === true));
})
.map(([filename, { content }]) => {
return {
filename,
pluginMap: { add: addPlugin },
plugins: [{ add: { content } }],
config: {},
schema,
documents: [],
};
});
utils_1.logger.debug(`Applying changes to ${resolverFilesGenerateOptions.length}/${resultFilesArray.length} files. (${resultFilesArray.length - resolverFilesGenerateOptions.length} skipped files because they are already on filesystem and are not updated)`);
return [...resolverFilesGenerateOptions, ...generatesSection];
}),
};
const createProfilerRunName = (traceName) => `[${exports.presetName}]: ${traceName}`;
//# sourceMappingURL=preset.js.map
;