create-cen-app
Version:
create an client-engineering-style app
102 lines (88 loc) • 3.34 kB
text/typescript
import { formatFile } from "../utils/formatFile.js";
import { getProcessedCommand } from "./processCommands.js";
import fs from "fs-extra";
import path from "path";
export const templateDeps = ["tailwind", "trpc", "extBackend", "recoil", "carbon"] as const;
export type TemplateDeps = (typeof templateDeps)[number];
interface ProcessTemplateProps {
templatePath: string;
resultPath: string;
usedDependencies: TemplateDeps[];
}
export const processTemplate = ({
templatePath,
resultPath,
usedDependencies,
}: ProcessTemplateProps) => {
const fileContents = fs.readFileSync(templatePath, "utf-8");
const lines = fileContents.split("\n");
const processedLines: string[] = [];
let deleteMode = false;
let activeDeleteCommand: string | null = null;
// find out which lines should be kept:
for (let i = 0; i < lines.length; i++) {
const line = lines[i]!.trim();
const templateCommand = getProcessedCommand(line, usedDependencies);
if (templateCommand) {
// checks if we have a different delete command active and if so, skip the current command
if (templateCommand.position === "start" && activeDeleteCommand) {
continue;
}
// set activeDeleteCommand
if (templateCommand.mode === "delete" && templateCommand.position === "start") {
deleteMode = true;
activeDeleteCommand = templateCommand.conditionString;
}
// if we are in delete mode and the current command is the one that ends the delete mode (supports nested commands)
if (
templateCommand.mode === "delete" &&
templateCommand.position === "end" &&
activeDeleteCommand === templateCommand.conditionString
) {
deleteMode = false;
activeDeleteCommand = null;
}
}
if (!deleteMode && !templateCommand) {
processedLines.push(line);
}
}
// create result file if it doesn't exist
if (!fs.existsSync(resultPath)) {
fs.ensureFileSync(resultPath);
}
// TODO: optimize this to not save the file twice
// write the processed lines to result file
fs.writeFileSync(resultPath, processedLines.join("\n"));
const parser = resultPath.endsWith(".ts") || resultPath.endsWith(".tsx") ? "typescript" : "scss";
formatFile(resultPath, parser);
};
interface ProcessFilesProps {
templateDir: string;
resultDir: string;
usedDependencies: TemplateDeps[];
}
export const processFiles = ({ templateDir, resultDir, usedDependencies }: ProcessFilesProps) => {
// loop over files in templateBasePath and check if name contains .tmpl. If so, process the file
const files = fs.readdirSync(templateDir);
for (const file of files) {
const filePath = path.join(templateDir, file);
if (fs.statSync(filePath).isDirectory()) {
processFiles({
templateDir: filePath,
resultDir: `${resultDir}/${file}`,
usedDependencies,
});
} else {
if (file.includes(".tmpl")) {
const templatePath = `${templateDir}/${file}`;
const resultPath = `${resultDir}/${file.replace(".tmpl", "")}`;
processTemplate({ templatePath, resultPath, usedDependencies });
} else {
const templatePath = `${templateDir}/${file}`;
const resultPath = `${resultDir}/${file}`;
fs.copySync(templatePath, resultPath);
}
}
}
};