apisculptify
Version:
Apisculptify is a powerful Node.js tool designed to automate the process of generating RESTful APIs for your TypeORM models. With Apisculptify, you can quickly create a new project, define your TypeORM models, and effortlessly generate CRUD (Create, Read,
163 lines (162 loc) • 6.6 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.bootstrap = bootstrap;
const ts_morph_1 = require("ts-morph");
const fs_1 = __importStar(require("fs"));
const path_1 = __importDefault(require("path"));
const inquirer = require("inquirer");
inquirer.registerPrompt("directory", require("inquirer-select-directory"));
function bootstrap() {
-inquirer
.prompt([
{
type: "directory",
name: "path",
message: "Navigate to your initialized directory`s src folder?",
options: {
displayFiles: false,
},
basePath: process.cwd(),
},
])
.then(async function (data) {
let selectedpath = data.path;
await run(selectedpath);
});
}
async function run(selectedpath) {
const project = new ts_morph_1.Project();
let sources = [];
sources.push(selectedpath + "/model/*.model.ts");
const sourceFiles = project.addSourceFilesAtPaths(sources);
let classMap = await createClassMap(sourceFiles);
var lastIndexBuild = __dirname.lastIndexOf("build");
var basePath = path_1.default.resolve(__dirname.substring(0, lastIndexBuild));
for (let key of classMap.keys()) {
let keywords = {
MODEL_NAME: key,
MODEL_NAME_WITHOUT_KEY: key.replace(/Model$/, ""),
MODEL_NAME_WITH_DASH: convertWithDash(key.toString()),
MODEL_NAME_WITHOUT_KEY_LOWER: key
.replace(/Model$/, "")
.toLowerCase(),
DYNAMIC_IMPORTS: "",
ENRICH: "",
};
console.log(key + " processed");
generateController(keywords, selectedpath, basePath);
generateRouter(keywords, selectedpath, basePath);
generateService(keywords, classMap.get(key), selectedpath, basePath);
}
}
function generateController(keywords, selectedpath, basePath) {
let template = fs_1.default
.readFileSync(basePath + "/templates/generic.controller.txt")
.toString();
template = replaceVariable(template, keywords);
writeFile(template, selectedpath + "/controllers/", keywords.MODEL_NAME_WITH_DASH + ".controller.ts");
}
function generateRouter(keywords, selectedpath, basePath) {
let template = fs_1.default
.readFileSync(basePath + "/templates/generic.router.txt")
.toString();
template = replaceVariable(template, keywords);
writeFile(template, selectedpath + "/router/", keywords.MODEL_NAME_WITH_DASH + ".router.ts");
}
function generateService(keywords, properties, selectedpath, basePath) {
for (let prop of properties) {
if (prop.isForeignKey) {
keywords.DYNAMIC_IMPORTS =
keywords.DYNAMIC_IMPORTS +
`\nimport { ${prop.type.replace(/Model$/, "")}Service } from "./${convertWithDash(prop.type)}.service";`;
keywords.ENRICH =
keywords.ENRICH +
`\nif (model.${prop.property} && model.${prop.property}.uid) {
const ${prop.property} = await ${prop.type.replace(/Model$/, "")}Service.getByUid(model.${prop.property}.uid)
if (!${prop.property}) {
throw new Error("${prop.property} not found");
}
model.${prop.property} = ${prop.property}
}`;
}
}
let template = fs_1.default
.readFileSync(basePath + "/templates/generic.service.txt")
.toString();
template = replaceVariable(template, keywords);
writeFile(template, selectedpath + "/service/", keywords.MODEL_NAME_WITH_DASH + ".service.ts");
}
function writeFile(template, destination, fileName) {
(0, fs_1.writeFileSync)(destination + fileName, template);
}
function replaceVariable(template, keywords) {
for (let key in keywords) {
template = template.replaceAll(`[[${key}]]`, keywords[key]);
}
return template;
}
function convertWithDash(input) {
let trimWord = input.replace(/Model$/, "");
return trimWord.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
}
async function createClassMap(sourceFiles) {
let classMap = new Map();
for (let sourceFile of sourceFiles) {
let className = sourceFile.getClasses()[0].getName();
let properties = [];
if (!classMap.has(className)) {
for (let prop of sourceFile.getClasses()[0].getProperties()) {
var newObj = {
property: prop.getName(),
type: "",
isForeignKey: false,
};
if (prop.getType().getText().includes(".")) {
const importStatement = prop.getType().getText();
const lastDotIndex = importStatement.lastIndexOf(".");
const lastSubstring = importStatement.substring(lastDotIndex + 1);
newObj.type = lastSubstring;
}
else {
newObj.type = prop.getType().getText();
}
properties.push(newObj);
}
classMap.set(className, properties);
}
}
for (let key of classMap.keys()) {
for (let prop of classMap.get(key)) {
if (classMap.has(prop.type)) {
prop.isForeignKey = true;
}
}
}
return classMap;
}