express-api-creator
Version:
Scaffold an Express.js boilerplate project. You can generate express.js boilerplate code with a single command.
283 lines (231 loc) • 9.93 kB
JavaScript
import { fileURLToPath } from "url";
import { dirname, join } from "path";
import { color } from "console-log-colors";
import { readFileSync, existsSync, writeFileSync } from "fs";
import { toCapitalizeFirstChar } from "./helpers.js";
/**
* ### Create Dynamic Files for JavaScript
* @description - This function creates dynamic files for a requested CRUD operation in JavaScript.
*
* @param {*} fields - Array of strings representing field names
* @param {*} requestedCrud - Model name
* @param {*} destinationPath - Path to the destination directory
* @param {*} isProtected - Auth middleware will be apply
* @returns - Promise<void>
*/
export const createDynamicFiles = async (
fields,
requestedCrud,
destinationPath,
isProtected
) => {
let schema = "";
const __dirname = dirname(fileURLToPath(import.meta.url));
let requestedCrudTitleCase = toCapitalizeFirstChar(requestedCrud);
if (requestedCrud) {
let dynamicRoutePath = join(__dirname, "../templates/js/route.txt");
let dynamicModelPath = join(__dirname, "../templates/js/model.txt");
let dynamicControllerPath = join(
__dirname,
"../templates/js/controller.txt"
);
// Fetching route data & update
let routePath = join(destinationPath, `/src/routes`);
let sampleRoute = readFileSync(dynamicRoutePath, "utf-8");
sampleRoute = sampleRoute.replaceAll("_name_", requestedCrud);
if (!existsSync(routePath)) {
console.error(
color.red(`❌ No proper directory structure found. ${destinationPath}`)
);
console.error(
color.blue(
"ℹ️ Run `npx express-api-creator create` to create the directory structure."
)
);
return;
}
try {
let rootRoutePath = join(destinationPath, `/src/routes/index.js`); // Replace with actual file
let data = readFileSync(rootRoutePath, "utf-8");
const defineRoutes = `/* ====== Define routes end ===== */`;
const importRoutes = `/* ====== Import routes end ===== */`;
if (!data.includes(defineRoutes) || !data.includes(importRoutes)) {
console.error(
color.red(
"❌ Error: Root route file does not contains route definitions comments."
)
);
return;
}
const importFile = `import ${requestedCrud}Route from "./${requestedCrud}Route.js";`;
let fileRequire = `rootRouter.use("/${requestedCrud}", auth, ${requestedCrud}Route);`;
if (!isProtected)
fileRequire = `rootRouter.use("/${requestedCrud}", ${requestedCrud}Route);`;
// Insert Router require
if (!data.includes(fileRequire)) {
data = data
.replace(importRoutes, `${importFile}\n\n${importRoutes}`)
.replace(defineRoutes, `${fileRequire}\n\n${defineRoutes}`);
}
writeFileSync(rootRoutePath, data, "utf-8");
console.log(color.green("✔️ File updated successfully!"));
} catch (err) {
console.error(color.red("❌ Error processing file: "), err);
}
// Fetching route data & update
routePath = join(routePath, `${requestedCrud}Route.js`);
writeFileSync(routePath, sampleRoute, { encoding: "utf8" });
console.log(color.green("✔️ Route file created!"));
// Fetching Controller data & update
let sampleController = readFileSync(dynamicControllerPath, "utf-8");
sampleController = sampleController
.replaceAll("_name_", requestedCrud)
.replaceAll("_Name_", requestedCrudTitleCase);
let controllerPath = join(
destinationPath,
`/src/controllers/${requestedCrud}Controller.js`
);
writeFileSync(controllerPath, sampleController, { encoding: "utf8" });
console.log(color.green("✔️ Controller file created!"));
// Fetching Model data & update
const schemaString = `\n _field: { type: String, required: true },`;
if (requestedCrud && fields.length === 0) {
schema = `{
name: { type: String, required: true },
}`;
} else {
schema = "{";
fields.forEach((field) => {
schema += schemaString.replace("_field", field);
});
schema += "\n}";
}
let sampleModel = readFileSync(dynamicModelPath, "utf-8");
sampleModel = sampleModel
.replaceAll("_name_", requestedCrud)
.replaceAll("_Name_", requestedCrudTitleCase)
.replaceAll("_schema_", schema);
const modelPath = join(destinationPath, `/src/models/${requestedCrud}.js`);
writeFileSync(modelPath, sampleModel, { encoding: "utf8" });
console.log(color.green("✔️ Model file created!"));
}
};
/**
* ### Create Dynamic Files for TypeScript
* @description - This function creates dynamic files for a requested CRUD operation in TypeScript.
*
* @param {*} fields - Array of strings representing field names
* @param {*} requestedCrud - Model name
* @param {*} destinationPath - Path to the destination directory
* @param {*} isProtected - Auth middleware will be apply
* @returns - Promise<void>
*/
export const createDynamicFilesTS = async (
fields,
requestedCrud,
destinationPath,
isProtected
) => {
let schema = "";
const __dirname = dirname(fileURLToPath(import.meta.url));
let requestedCrudTitleCase = toCapitalizeFirstChar(requestedCrud);
if (requestedCrud) {
let dynamicLangPath = join(__dirname, "../templates/ts/lang.txt");
let dynamicModelPath = join(__dirname, "../templates/ts/model.txt");
let dynamicRoutePath = join(__dirname, "../templates/ts/route.txt");
let dynamicControllerPath = join(
__dirname,
"../templates/ts/controller.txt"
);
// Fetching route data & update
let routePath = join(destinationPath, `/src/routes`);
let sampleRoute = readFileSync(dynamicRoutePath, "utf-8");
sampleRoute = sampleRoute.replaceAll("_name_", requestedCrud);
if (!existsSync(routePath)) {
console.error(color.red("❌ No proper directory structure found."));
console.error(
color.blue(
"ℹ️ Run `npx express-api-creator create` to create the directory structure."
)
);
return;
}
try {
let rootRoutePath = join(destinationPath, `/src/routes/index.ts`); // Replace with actual file
let data = readFileSync(rootRoutePath, "utf-8");
const defineRoutes = `/* ====== Define routes end ===== */`;
const importRoutes = `/* ====== Import routes end ===== */`;
if (!data.includes(defineRoutes) || !data.includes(importRoutes)) {
console.error(
color.red(
"❌ Error: Root route file does not contains route definitions comments."
)
);
return;
}
const importFile = `import ${requestedCrud}Route from "./${requestedCrud}Route";`;
let fileRequire = `rootRouter.use("/${requestedCrud}", auth, ${requestedCrud}Route);`;
if (!isProtected)
fileRequire = `rootRouter.use("/${requestedCrud}", ${requestedCrud}Route);`;
// Insert Router require
if (!data.includes(fileRequire)) {
data = data
.replace(importRoutes, `${importFile}\n${importRoutes}`)
.replace(defineRoutes, `${fileRequire}\n${defineRoutes}`);
}
writeFileSync(rootRoutePath, data, "utf-8");
console.log("✔️ File updated successfully!");
} catch (err) {
console.error(color.red("❌ Error processing file: "), err);
}
routePath = join(routePath, `${requestedCrud}Route.ts`);
writeFileSync(routePath, sampleRoute, { encoding: "utf8" });
console.log("✔️ Route file created!");
// Fetching Lang data & update
let sampleLang = readFileSync(dynamicLangPath, "utf-8");
sampleLang = sampleLang
.replaceAll("_name_", requestedCrud)
.replaceAll("_Name_", requestedCrudTitleCase)
.replaceAll("_NAME_", requestedCrud.toUpperCase());
let langPath = join(destinationPath, `/src/lang/en/${requestedCrud}.ts`);
writeFileSync(langPath, sampleLang, { encoding: "utf8" });
console.log("✔️ Lang file created!");
// Fetching Controller data & update
let sampleController = readFileSync(dynamicControllerPath, "utf-8");
sampleController = sampleController
.replaceAll("_name_", requestedCrud)
.replaceAll("_Name_", requestedCrudTitleCase)
.replaceAll("_NAME_", requestedCrud.toUpperCase());
let controllerPath = join(
destinationPath,
`/src/controllers/${requestedCrud}Controller.ts`
);
writeFileSync(controllerPath, sampleController, { encoding: "utf8" });
console.log("✔️ Controller file created!");
// Fetching Model data & update
let interfaceSchema = "";
const interfaceString = `\n _field: String;`;
const schemaString = `\n _field: { type: String, required: true },`;
if (requestedCrud && fields.length === 0) {
schema = `{
name: { type: String, required: true },
}`;
} else {
schema = "{";
fields.forEach((field) => {
schema += schemaString.replace("_field", field);
interfaceSchema += interfaceString.replace("_field", field);
});
schema += "\n}";
}
let sampleModel = readFileSync(dynamicModelPath, "utf-8");
sampleModel = sampleModel
.replaceAll("_schema_", schema)
.replaceAll("_name_", requestedCrud)
.replaceAll("_interface_", interfaceSchema)
.replaceAll("_Name_", requestedCrudTitleCase);
const modelPath = join(destinationPath, `/src/models/${requestedCrud}.ts`);
writeFileSync(modelPath, sampleModel, { encoding: "utf8" });
console.log("✔️ Model file created!");
}
};