chimp
Version:
Your development companion for doing quality, faster.
388 lines (387 loc) • 21.7 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeGeneration = void 0;
const tslib_1 = require("tslib");
const get_module_infos_1 = tslib_1.__importDefault(require("./parse-graphql/get-module-infos"));
const fs = tslib_1.__importStar(require("node:fs"));
const path = tslib_1.__importStar(require("node:path"));
// @ts-ignore
const shelljs = tslib_1.__importStar(require("shelljs"));
const debug_1 = tslib_1.__importDefault(require("debug"));
const graphql_1 = require("graphql");
const pascal_case_1 = require("pascal-case");
const getModuleNames_1 = tslib_1.__importDefault(require("./parse-graphql/getModuleNames"));
const getFederatedEntities_1 = tslib_1.__importDefault(require("./parse-graphql/getFederatedEntities"));
const getInterfaces_1 = tslib_1.__importDefault(require("./parse-graphql/getInterfaces"));
const getScalars_1 = tslib_1.__importDefault(require("./parse-graphql/getScalars"));
// import checkIfGitStateClean from './helpers/checkIfGitStateClean';
const saveRenderedTemplate_1 = require("./helpers/saveRenderedTemplate");
const findProjectMainPath_1 = require("./helpers/findProjectMainPath");
const execQuietly_1 = require("./helpers/execQuietly");
const getUnions_1 = tslib_1.__importDefault(require("./parse-graphql/getUnions"));
const debug = (0, debug_1.default)('generate-module');
const generateSchema = async (projectMainPath) => {
await (0, execQuietly_1.execQuietly)(`PROJECT_PATH=${projectMainPath} npx tsx -r tsconfig-paths/register ${__dirname}/templates/printSchema.ts`, {});
};
const executeGeneration = async (appPrefix = '~app', generatedPrefix = '~generated', modulesPath = 'src/') => {
const capitalize = (string) => string.charAt(0).toUpperCase() + string.slice(1);
const projectMainPath = (0, findProjectMainPath_1.findProjectMainPath)();
shelljs.mkdir('-p', `${projectMainPath}/generated/graphql/helpers`);
// "Framework" "generated" files - initial generation
const createGenericDataModelSchema = () => {
const templateName = './templates/genericDataModelSchema.graphql';
const filePath = `${projectMainPath}/generated/graphql/`;
const fileName = 'genericDataModelSchema.graphql';
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, {}, filePath, fileName);
};
debug('createGenericDataModelSchema');
createGenericDataModelSchema();
const modulesResolvedPath = path.join(projectMainPath, modulesPath);
const graphqlPaths = shelljs.ls(path.join(modulesResolvedPath, '**/*.graphql'));
const moduleNames = (0, getModuleNames_1.default)(graphqlPaths, projectMainPath);
const modules = (0, get_module_infos_1.default)(moduleNames);
const createGlobalResolvers = () => {
const templateName = './templates/resolvers.handlebars';
const context = { modules };
const filePath = `${projectMainPath}/generated/graphql/`;
const fileName = 'resolvers.ts';
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName);
};
debug('createGlobalResolvers');
createGlobalResolvers();
// End of "Framework" "generated" files
// Initial App Setup files
debug('generateSchema');
await generateSchema(projectMainPath);
const globalSchemaString = fs.readFileSync(path.join(projectMainPath, 'schema.graphql')); // read file
const createGlobalSchema = () => {
const templateName = './templates/schema.ts';
const context = { modules, schemaString: globalSchemaString.toString().replace(/`/g, '\\`'), generatedPrefix };
const filePath = `${projectMainPath}/generated/graphql/`;
const fileName = 'schema.ts';
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName);
};
debug('createGlobalSchema');
createGlobalSchema();
for (const module of modules) {
const moduleName = module.name;
const { graphqlFileRootPath, queries, mutations } = module;
const createQuery = (queryName, hasArguments) => {
const templateName = './templates/query.handlebars';
const context = {
queryName,
moduleName,
hasArguments,
generatedPrefix,
};
const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/queries/`;
const fileName = `${queryName}Query.ts`;
const keepIfExists = true;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
};
const createQuerySpec = (queryName, hasArguments) => {
const templateName = './templates/query.spec.handlebars';
const context = {
queryName,
moduleName,
hasArguments,
generatedPrefix,
pascalCasedArgName: `Query${(0, pascal_case_1.pascalCase)(queryName)}Args`,
};
const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/queries/`;
const fileName = `${queryName}Query.spec.ts`;
const keepIfExists = true;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
};
const createQuerySpecWrapper = (queryName, hasArguments) => {
const templateName = './templates/querySpecWrapper.handlebars';
const context = {
queryName,
moduleName,
hasArguments,
generatedPrefix,
appPrefix,
graphqlFileRootPath,
pascalCasedArgName: `Query${(0, pascal_case_1.pascalCase)(queryName)}Args`,
};
const filePath = `${projectMainPath}/generated/graphql/helpers/`;
const fileName = `${queryName}QuerySpecWrapper.ts`;
const keepIfExists = false;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
};
if (queries && queries.length > 0) {
shelljs.mkdir('-p', `${projectMainPath}/src/${graphqlFileRootPath}/queries`);
for (const { name, hasArguments } of queries) {
createQuery(name, hasArguments);
createQuerySpec(name, hasArguments);
createQuerySpecWrapper(name, hasArguments);
}
}
const createMutation = (mutationName, hasArguments) => {
const templateName = './templates/mutation.handlebars';
const context = {
mutationName,
moduleName,
hasArguments,
generatedPrefix,
};
const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/mutations/`;
const fileName = `${mutationName}Mutation.ts`;
const keepIfExists = true;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
};
const createMutationSpec = (mutationName, hasArguments) => {
const templateName = './templates/mutation.spec.handlebars';
const context = {
mutationName,
moduleName,
hasArguments,
generatedPrefix,
appPrefix,
graphqlFileRootPath,
pascalCasedArgName: `Mutation${(0, pascal_case_1.pascalCase)(mutationName)}Args`,
};
const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/mutations/`;
const fileName = `${mutationName}Mutation.spec.ts`;
const keepIfExists = true;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
};
const createMutationSpecWrapper = (mutationName, hasArguments) => {
const templateName = './templates/mutationSpecWrapper.handlebars';
const context = {
mutationName,
moduleName,
hasArguments,
generatedPrefix,
appPrefix,
graphqlFileRootPath,
pascalCasedArgName: `Mutation${(0, pascal_case_1.pascalCase)(mutationName)}Args`,
};
const filePath = `${projectMainPath}/generated/graphql/helpers/`;
const fileName = `${mutationName}MutationSpecWrapper.ts`;
const keepIfExists = false;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
};
if (mutations && mutations.length > 0) {
shelljs.mkdir('-p', `${projectMainPath}/src/${graphqlFileRootPath}/mutations`);
for (const { name, hasArguments } of mutations) {
createMutation(name, hasArguments);
createMutationSpec(name, hasArguments);
createMutationSpecWrapper(name, hasArguments);
}
}
}
const createTypeResolvers = () => {
for (const { name, typeDefinitions, types, schemaString, queries, mutations, graphqlFileRootPath } of modules) {
const typeResolvers = [];
if (types) {
debug(`create type resolvers for module ${name}`);
const federatedEntities = (0, getFederatedEntities_1.default)(schemaString);
const interfaces = (0, getInterfaces_1.default)(schemaString);
const unions = (0, getUnions_1.default)(schemaString);
// Leaving this for now
const source = new graphql_1.Source(schemaString.replace(/extend type/g, 'type'));
const schema = (0, graphql_1.buildSchema)(source, { assumeValidSDL: true });
shelljs.mkdir('-p', `${projectMainPath}/src/${graphqlFileRootPath}/types/`);
const createResolveType = (resolverTypeName) => {
const templateName = './templates/typeTypeResolvers.handlebars';
const capitalizedFieldName = capitalize('__resolveType');
const context = {
typeName: resolverTypeName,
fieldName: '__resolveType',
moduleName: name,
resolveReferenceType: true,
capitalizedFieldName,
generatedPrefix,
};
const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/types/`;
const fileName = `${resolverTypeName}${capitalizedFieldName}.ts`;
const keepIfExists = true;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
};
const createResolveTypeSpec = (resolverTypeName) => {
const templateName = './templates/typeTypeResolvers.spec.handlebars';
const capitalizedFieldName = capitalize('__resolveType');
const context = {
typeName: resolverTypeName,
fieldName: '__resolveType',
moduleName: name,
hasArguments: false,
resolveReferenceType: true,
capitalizedFieldName,
generatedPrefix,
};
const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/types/`;
const fileName = `${resolverTypeName}${capitalizedFieldName}.spec.ts`;
const keepIfExists = true;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
};
const createResolveTypeSpecWrapper = (resolverTypeName) => {
const templateName = './templates/typeTypeResolversSpecWrapper.handlebars';
const capitalizedFieldName = capitalize('__resolveType');
const context = {
typeName: resolverTypeName,
fieldName: '__resolveType',
moduleName: name,
hasArguments: false,
resolveReferenceType: true,
capitalizedFieldName,
generatedPrefix,
appPrefix,
graphqlFileRootPath,
};
const filePath = `${projectMainPath}/generated/graphql/helpers/`;
const fileName = `${resolverTypeName}${capitalizedFieldName}SpecWrapper.ts`;
const keepIfExists = false;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
};
for (const interfaceName of interfaces) {
createResolveType(interfaceName);
createResolveTypeSpec(interfaceName);
createResolveTypeSpecWrapper(interfaceName);
typeResolvers.push({
typeName: interfaceName,
fieldName: [{ name: '__resolveType', capitalizedName: capitalize('__resolveType') }],
});
}
for (const unionName of unions) {
createResolveType(unionName);
createResolveTypeSpec(unionName);
createResolveTypeSpecWrapper(unionName);
typeResolvers.push({
typeName: unionName,
fieldName: [{ name: '__resolveType', capitalizedName: capitalize('__resolveType') }],
});
}
for (const typeDef of typeDefinitions) {
let filtered = [];
let type = schema.getType(typeDef.name);
if (!type) {
const newSchemaString = schemaString.replace(`extend type ${typeDef.name}`, `type ${typeDef.name}`);
type = (0, graphql_1.buildSchema)(new graphql_1.Source(newSchemaString)).getType(typeDef.name);
}
if (type === null || type === void 0 ? void 0 : type.astNode) {
// @ts-ignore
filtered = type.astNode.fields.filter((field) => field.directives.find((d) => d.name.value === 'computed' ||
d.name.value === 'link' ||
d.name.value === 'requires' ||
d.name.value === 'map'));
}
let isFederatedAndExternal = false;
if (federatedEntities.includes(typeDef.name)) {
filtered.push({ name: { value: '__resolveReference' }, resolveReferenceType: true });
isFederatedAndExternal =
Boolean(type.astNode) &&
Boolean(
// @ts-ignore
type === null || type === void 0 ? void 0 : type.astNode.fields.find((field) => field.directives.find((d) => d.name.value === 'external')));
}
for (const { name: { value }, resolveReferenceType, } of filtered) {
const templateName = './templates/typeTypeResolvers.handlebars';
const capitalizedFieldName = capitalize(value);
const context = {
typeName: typeDef.name,
fieldName: value,
moduleName: name,
resolveReferenceType,
capitalizedFieldName,
generatedPrefix,
};
const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/types/`;
const fileName = `${typeDef.name}${capitalizedFieldName}.ts`;
const keepIfExists = true;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
}
const createTypeFieldResolverSpec = (value, resolveReferenceType, resolverArguments) => {
const templateName = './templates/typeTypeResolvers.spec.handlebars';
const capitalizedFieldName = capitalize(value);
const context = {
typeName: typeDef.name,
fieldName: value,
moduleName: name,
hasArguments: resolverArguments && resolverArguments.length > 0,
resolveReferenceType,
capitalizedFieldName,
generatedPrefix,
pascalCasedArgName: `${typeDef.name}${(0, pascal_case_1.pascalCase)(capitalizedFieldName)}Args`,
};
const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/types/`;
const fileName = `${typeDef.name}${capitalizedFieldName}.spec.ts`;
const keepIfExists = true;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
};
const createTypeFieldResolverSpecWrapper = (value, resolveReferenceType, resolverArguments) => {
const templateName = './templates/typeTypeResolversSpecWrapper.handlebars';
const capitalizedFieldName = capitalize(value);
const context = {
typeName: typeDef.name,
fieldName: value,
moduleName: name,
hasArguments: resolverArguments && resolverArguments.length > 0,
resolveReferenceType,
capitalizedFieldName,
generatedPrefix,
appPrefix,
graphqlFileRootPath,
isFederatedAndExternal,
pascalCasedArgName: `${typeDef.name}${(0, pascal_case_1.pascalCase)(capitalizedFieldName)}Args`,
};
const filePath = `${projectMainPath}/generated/graphql/helpers/`;
const fileName = `${typeDef.name}${capitalizedFieldName}SpecWrapper.ts`;
const keepIfExists = true;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
};
for (const { name: { value }, arguments: resolverArguments, resolveReferenceType, } of filtered) {
createTypeFieldResolverSpec(value, resolveReferenceType, resolverArguments);
createTypeFieldResolverSpecWrapper(value, resolveReferenceType, resolverArguments);
}
if (filtered.length > 0) {
typeResolvers.push({
typeName: typeDef.name,
fieldName: filtered.map(({ name: { value } }) => ({ name: value, capitalizedName: capitalize(value) })),
});
}
}
}
const scalars = (0, getScalars_1.default)(schemaString);
const createScalarResolvers = () => {
if (scalars && scalars.length > 0) {
shelljs.mkdir('-p', `${projectMainPath}/src/${graphqlFileRootPath}/scalars/`);
}
for (const scalarName of scalars) {
const templateName = './templates/scalarResolver.handlebars';
const context = {
scalarName,
moduleName: name,
generatedPrefix,
};
const filePath = `${projectMainPath}/src/${graphqlFileRootPath}/scalars/`;
const fileName = `${scalarName}.ts`;
const keepIfExists = true;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName, keepIfExists);
}
};
createScalarResolvers();
const moduleName = name;
const createModuleResolvers = () => {
const templateName = './templates/moduleResolvers.handlebars';
const context = {
moduleName,
queries,
mutations,
typeResolvers,
graphqlFileRootPath,
appPrefix,
scalars,
};
const filePath = `${projectMainPath}/generated/graphql/`;
const fileName = `${moduleName}Resolvers.ts`;
(0, saveRenderedTemplate_1.saveRenderedTemplate)(templateName, context, filePath, fileName);
};
createModuleResolvers();
}
};
debug('createTypeResolvers');
createTypeResolvers();
};
exports.executeGeneration = executeGeneration;
;