@kontent-ai/model-generator
Version:
This utility generates strongly-typed models for Delivery JS SDK, Migration toolkit or just general scripting to improve the experience when referencing Kontent.ai related objects.
113 lines (100 loc) • 3.7 kB
text/typescript
import * as fs from "node:fs";
import { dirname } from "node:path";
import type { EnvironmentModels } from "@kontent-ai/management-sdk";
import chalk from "chalk";
import type { Options } from "prettier";
import { coreConfig } from "../config.js";
import { getEnvironmentInfoComment } from "../core/comment.utils.js";
import type { GeneratedFile, GeneratedSet, ModuleFileExtension } from "../core/core.models.js";
import { toOutputDirPath } from "../core/core.utils.js";
import { getImporter } from "../core/importer.js";
import { formatCodeAsync } from "../format/formatter.js";
export function getFileManager(config: {
readonly moduleFileExtension: ModuleFileExtension;
readonly outputDir?: string;
readonly formatOptions?: Readonly<Options>;
readonly environmentInfo: Readonly<EnvironmentModels.EnvironmentInformationModel>;
readonly addTimestamp: boolean;
}) {
const fixedOutputDir = toOutputDirPath(config.outputDir);
const importer = getImporter(config.moduleFileExtension);
const createFileOnFs = (text: string, filePath: string): void => {
const fullFilePath = `${fixedOutputDir.endsWith("/") ? fixedOutputDir : `${fixedOutputDir}/`}${filePath}`;
const fileContent = removeFirstEmptyLine(
`${getEnvironmentInfoComment({
environmentInfo: config.environmentInfo,
timestampDate: config.addTimestamp ? new Date() : undefined,
})}\n\n${text}`,
);
ensureDirectoryExistence(fullFilePath);
fs.writeFileSync(`./${fullFilePath}`, fileContent, {});
console.log(`Created '${chalk.yellow(fullFilePath)}'`);
};
const getFormattedCodeAsync = async (code: string, filePath: string): Promise<string> => {
try {
if (filePath.endsWith(".ts")) {
return await formatCodeAsync(code, config.formatOptions);
}
return code;
} catch {
console.log(`Failed to format file '${chalk.red(filePath)}'. Skipping prettier.`);
return code;
}
};
const removeFirstEmptyLine = (code: string): string => {
if (code.startsWith("\n")) {
return code.substring(1);
}
return code;
};
const ensureDirectoryExistence = (filePath: string): void => {
const resolvedDirname = dirname(filePath);
if (fs.existsSync(resolvedDirname)) {
return;
}
ensureDirectoryExistence(resolvedDirname);
fs.mkdirSync(resolvedDirname);
};
const createFiles = (files: readonly GeneratedFile[]): void => {
for (const file of files) {
createFileOnFs(file.text, file.filename);
}
};
const getSetFolder = (set: GeneratedSet): string => {
return set.folderName ? `${set.folderName}/` : "";
};
const getSetFiles = (set: GeneratedSet): readonly GeneratedFile[] => {
const setFolder = getSetFolder(set);
const setFiles: readonly GeneratedFile[] = set.files.map<GeneratedFile>((file) => {
return {
filename: `${setFolder}${file.filename}`,
text: file.text,
};
});
return setFiles;
};
const getSetsBarrelExportFiles = (sets: readonly GeneratedSet[]): GeneratedFile => {
return {
filename: coreConfig.barrelExportFilename,
text: importer.getBarrelExportCode(
sets.flatMap((set) => {
return set.files.map((file) => importer.getGeneratedFilename(`./${getSetFolder(set)}${file.filename}`));
}),
),
};
};
return {
getSetFilesAsync: async (sets: readonly GeneratedSet[]): Promise<readonly GeneratedFile[]> => {
return await Promise.all(
[...sets.flatMap((set) => getSetFiles(set)), getSetsBarrelExportFiles(sets)].map<Promise<GeneratedFile>>(async (file) => {
const generatedFilename = importer.getGeneratedFilename(file.filename);
return {
filename: generatedFilename,
text: await getFormattedCodeAsync(file.text, generatedFilename),
};
}),
);
},
createFiles,
};
}