@patel.ajay745/exinit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +73 -0
- package/dist/fs.js +99 -0
- package/dist/installer.js +15 -0
- package/dist/messages.js +33 -0
- package/dist/naming.js +10 -0
- package/dist/packageManager.js +59 -0
- package/dist/prompt.js +99 -0
- package/dist/scaffolder.js +55 -0
- package/dist/types.js +2 -0
- package/dist/validation.js +57 -0
- package/package.json +27 -0
- package/templates/js-cjs/.env.example +2 -0
- package/templates/js-cjs/gitignore +3 -0
- package/templates/js-cjs/package.json.template +21 -0
- package/templates/js-cjs/src/config/.gitkeep +0 -0
- package/templates/js-cjs/src/controllers/.gitkeep +0 -0
- package/templates/js-cjs/src/index.js +17 -0
- package/templates/js-cjs/src/middlewares/.gitkeep +0 -0
- package/templates/js-cjs/src/models/.gitkeep +0 -0
- package/templates/js-cjs/src/routes/index.js +11 -0
- package/templates/js-cjs/src/services/.gitkeep +0 -0
- package/templates/js-cjs/src/utils/apiError.js +17 -0
- package/templates/js-cjs/src/utils/apiResponse.js +10 -0
- package/templates/js-cjs/src/utils/asyncHandler.js +8 -0
- package/templates/js-cjs/src/utils/errorHandler.js +23 -0
- package/templates/js-esm/.env.example +2 -0
- package/templates/js-esm/gitignore +3 -0
- package/templates/js-esm/package.json.template +18 -0
- package/templates/js-esm/src/config/.gitkeep +0 -0
- package/templates/js-esm/src/controllers/.gitkeep +0 -0
- package/templates/js-esm/src/index.js +16 -0
- package/templates/js-esm/src/middlewares/.gitkeep +0 -0
- package/templates/js-esm/src/models/.gitkeep +0 -0
- package/templates/js-esm/src/routes/index.js +9 -0
- package/templates/js-esm/src/services/.gitkeep +0 -0
- package/templates/js-esm/src/utils/apiError.js +15 -0
- package/templates/js-esm/src/utils/apiResponse.js +8 -0
- package/templates/js-esm/src/utils/asyncHandler.js +6 -0
- package/templates/js-esm/src/utils/errorHandler.js +21 -0
- package/templates/ts/.env.example +2 -0
- package/templates/ts/gitignore +4 -0
- package/templates/ts/package.json.template +23 -0
- package/templates/ts/src/config/.gitkeep +0 -0
- package/templates/ts/src/controllers/.gitkeep +0 -0
- package/templates/ts/src/dto/.gitkeep +0 -0
- package/templates/ts/src/index.ts +16 -0
- package/templates/ts/src/middlewares/.gitkeep +0 -0
- package/templates/ts/src/models/.gitkeep +0 -0
- package/templates/ts/src/routes/index.ts +9 -0
- package/templates/ts/src/services/.gitkeep +0 -0
- package/templates/ts/src/types/.gitkeep +0 -0
- package/templates/ts/src/utils/apiError.ts +20 -0
- package/templates/ts/src/utils/apiResponse.ts +13 -0
- package/templates/ts/src/utils/asyncHandler.ts +8 -0
- package/templates/ts/src/utils/errorHandler.ts +22 -0
- package/templates/ts/tsconfig.json +20 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const validation_1 = require("./validation");
|
|
39
|
+
const naming_1 = require("./naming");
|
|
40
|
+
const prompt_1 = require("./prompt");
|
|
41
|
+
const packageManager_1 = require("./packageManager");
|
|
42
|
+
const scaffolder_1 = require("./scaffolder");
|
|
43
|
+
function resolveTemplateDir(baseDir, lang, moduleSystem) {
|
|
44
|
+
if (lang === "ts")
|
|
45
|
+
return path.join(baseDir, "ts");
|
|
46
|
+
return path.join(baseDir, moduleSystem === "esm" ? "js-esm" : "js-cjs");
|
|
47
|
+
}
|
|
48
|
+
async function main() {
|
|
49
|
+
try {
|
|
50
|
+
const arg = process.argv[2];
|
|
51
|
+
const isCurrentDir = !arg || arg === ".";
|
|
52
|
+
const projectName = isCurrentDir ? path.basename(process.cwd()) : arg;
|
|
53
|
+
const targetDir = isCurrentDir ? process.cwd() : path.resolve(process.cwd(), projectName);
|
|
54
|
+
(0, validation_1.validateProjectName)(projectName);
|
|
55
|
+
if (isCurrentDir) {
|
|
56
|
+
(0, validation_1.validateCurrentDir)(targetDir);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
(0, validation_1.validateNewDir)(targetDir, projectName);
|
|
60
|
+
}
|
|
61
|
+
const lang = await (0, prompt_1.promptLanguage)();
|
|
62
|
+
const moduleSystem = lang === "js" ? await (0, prompt_1.promptModuleSystem)() : undefined;
|
|
63
|
+
const packageManager = await (0, prompt_1.promptPackageManager)((0, packageManager_1.detectPackageManagers)());
|
|
64
|
+
const routerName = (0, naming_1.toRouterName)(projectName);
|
|
65
|
+
const templateDir = resolveTemplateDir(path.join(__dirname, "..", "templates"), lang, moduleSystem);
|
|
66
|
+
(0, scaffolder_1.scaffoldProject)({ projectName, lang, packageManager, routerName, targetDir, templateDir, isCurrentDir });
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
main();
|
package/dist/fs.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.copyDir = copyDir;
|
|
37
|
+
exports.copyTemplate = copyTemplate;
|
|
38
|
+
exports.applyReplacementsInSources = applyReplacementsInSources;
|
|
39
|
+
exports.finalizePackageJson = finalizePackageJson;
|
|
40
|
+
exports.renameGitignore = renameGitignore;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const messages_1 = require("./messages");
|
|
44
|
+
function copyDir(src, dest) {
|
|
45
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
46
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
47
|
+
const srcPath = path.join(src, entry.name);
|
|
48
|
+
const destPath = path.join(dest, entry.name);
|
|
49
|
+
if (entry.isDirectory()) {
|
|
50
|
+
copyDir(srcPath, destPath);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
fs.copyFileSync(srcPath, destPath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function copyTemplate(templateDir, targetDir) {
|
|
58
|
+
try {
|
|
59
|
+
copyDir(templateDir, targetDir);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
63
|
+
throw new Error(messages_1.Messages.copyFailed(err));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function escapeForRegex(str) {
|
|
67
|
+
return str.replace(/[{}.*+?^$|[\]\\]/g, "\\$&");
|
|
68
|
+
}
|
|
69
|
+
function applyReplacements(content, replacements) {
|
|
70
|
+
return Object.entries(replacements).reduce((result, [placeholder, value]) => {
|
|
71
|
+
return result.replace(new RegExp(escapeForRegex(placeholder), "g"), value);
|
|
72
|
+
}, content);
|
|
73
|
+
}
|
|
74
|
+
function applyReplacementsInSources(srcDir, replacements) {
|
|
75
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
76
|
+
const fullPath = path.join(srcDir, entry.name);
|
|
77
|
+
if (entry.isDirectory()) {
|
|
78
|
+
applyReplacementsInSources(fullPath, replacements);
|
|
79
|
+
}
|
|
80
|
+
else if ([".ts", ".js"].includes(path.extname(entry.name))) {
|
|
81
|
+
const updated = applyReplacements(fs.readFileSync(fullPath, "utf-8"), replacements);
|
|
82
|
+
fs.writeFileSync(fullPath, updated);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function finalizePackageJson(targetDir, replacements) {
|
|
87
|
+
const templatePath = path.join(targetDir, "package.json.template");
|
|
88
|
+
const outputPath = path.join(targetDir, "package.json");
|
|
89
|
+
const content = applyReplacements(fs.readFileSync(templatePath, "utf-8"), replacements);
|
|
90
|
+
fs.writeFileSync(outputPath, content);
|
|
91
|
+
fs.unlinkSync(templatePath);
|
|
92
|
+
}
|
|
93
|
+
function renameGitignore(targetDir) {
|
|
94
|
+
const src = path.join(targetDir, "gitignore");
|
|
95
|
+
const dest = path.join(targetDir, ".gitignore");
|
|
96
|
+
if (fs.existsSync(src)) {
|
|
97
|
+
fs.renameSync(src, dest);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.installDependencies = installDependencies;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const messages_1 = require("./messages");
|
|
6
|
+
const packageManager_1 = require("./packageManager");
|
|
7
|
+
function installDependencies(targetDir, projectName, pm) {
|
|
8
|
+
console.log(messages_1.Messages.installingDeps());
|
|
9
|
+
try {
|
|
10
|
+
(0, child_process_1.execSync)((0, packageManager_1.getInstallCommand)(pm), { cwd: targetDir, stdio: "inherit" });
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
console.warn(messages_1.Messages.installFailed(projectName, (0, packageManager_1.getInstallCommand)(pm)));
|
|
14
|
+
}
|
|
15
|
+
}
|
package/dist/messages.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Messages = void 0;
|
|
4
|
+
exports.Messages = {
|
|
5
|
+
usage: () => "Usage: npx exinit [project-name]\n" +
|
|
6
|
+
"Omit the name to scaffold in the current directory.",
|
|
7
|
+
invalidName: (name) => `Error: "${name}" is not a valid project name.\n` +
|
|
8
|
+
`Use lowercase letters, numbers, and hyphens only (e.g., my-app).`,
|
|
9
|
+
dirExists: (name) => `Error: Directory "${name}" already exists.\n` +
|
|
10
|
+
`Choose a different name or remove the existing directory.`,
|
|
11
|
+
alreadyInitialized: () => "Error: This directory already has a package.json.\n" +
|
|
12
|
+
"Run in an empty directory or provide a project name to create a new one.",
|
|
13
|
+
copyFailed: (err) => `Error: Failed to copy template files. ${err}`,
|
|
14
|
+
creatingProject: (lang, name) => {
|
|
15
|
+
const label = lang === "ts" ? "TypeScript" : "JavaScript";
|
|
16
|
+
return `\nCreating ${label} project "${name}"...`;
|
|
17
|
+
},
|
|
18
|
+
installingDeps: () => "Installing dependencies...\n",
|
|
19
|
+
installFailed: (name, installCmd) => `\nWarning: install failed. Run it manually:\n cd ${name} && ${installCmd}`,
|
|
20
|
+
success: (name, devCmd, prodCmd, isCurrentDir) => {
|
|
21
|
+
const nav = isCurrentDir ? ` ${devCmd}` : ` cd ${name}\n ${devCmd}`;
|
|
22
|
+
return `
|
|
23
|
+
Done! Your project "${name}" is ready.
|
|
24
|
+
|
|
25
|
+
${nav}
|
|
26
|
+
|
|
27
|
+
Next steps:
|
|
28
|
+
- Copy .env.example to .env and set your environment variables
|
|
29
|
+
- Add routes in src/routes/
|
|
30
|
+
- Production: ${prodCmd}
|
|
31
|
+
`;
|
|
32
|
+
},
|
|
33
|
+
};
|
package/dist/naming.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toCamelCase = toCamelCase;
|
|
4
|
+
exports.toRouterName = toRouterName;
|
|
5
|
+
function toCamelCase(name) {
|
|
6
|
+
return name.replace(/-([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
7
|
+
}
|
|
8
|
+
function toRouterName(projectName) {
|
|
9
|
+
return toCamelCase(projectName) + "Router";
|
|
10
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectPackageManagers = detectPackageManagers;
|
|
4
|
+
exports.getInstallCommand = getInstallCommand;
|
|
5
|
+
exports.getDevCommand = getDevCommand;
|
|
6
|
+
exports.getProdCommand = getProdCommand;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const ALL_PACKAGE_MANAGERS = ["npm", "bun", "pnpm", "yarn"];
|
|
9
|
+
function isInstalled(pm) {
|
|
10
|
+
try {
|
|
11
|
+
(0, child_process_1.execSync)(`${pm} --version`, { stdio: "ignore" });
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function detectPackageManagers() {
|
|
19
|
+
return ALL_PACKAGE_MANAGERS.map((name) => ({
|
|
20
|
+
name,
|
|
21
|
+
installed: isInstalled(name),
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
function getInstallCommand(pm) {
|
|
25
|
+
const commands = {
|
|
26
|
+
npm: "npm install",
|
|
27
|
+
bun: "bun install",
|
|
28
|
+
pnpm: "pnpm install",
|
|
29
|
+
yarn: "yarn",
|
|
30
|
+
};
|
|
31
|
+
return commands[pm];
|
|
32
|
+
}
|
|
33
|
+
function getDevCommand(pm) {
|
|
34
|
+
const commands = {
|
|
35
|
+
npm: "npm run dev",
|
|
36
|
+
bun: "bun dev",
|
|
37
|
+
pnpm: "pnpm dev",
|
|
38
|
+
yarn: "yarn dev",
|
|
39
|
+
};
|
|
40
|
+
return commands[pm];
|
|
41
|
+
}
|
|
42
|
+
function getProdCommand(pm, lang) {
|
|
43
|
+
if (lang === "js") {
|
|
44
|
+
const startCmds = {
|
|
45
|
+
npm: "npm start",
|
|
46
|
+
bun: "bun start",
|
|
47
|
+
pnpm: "pnpm start",
|
|
48
|
+
yarn: "yarn start",
|
|
49
|
+
};
|
|
50
|
+
return startCmds[pm];
|
|
51
|
+
}
|
|
52
|
+
const buildAndStartCmds = {
|
|
53
|
+
npm: "npm run build && npm start",
|
|
54
|
+
bun: "bun run build && bun start",
|
|
55
|
+
pnpm: "pnpm build && pnpm start",
|
|
56
|
+
yarn: "yarn build && yarn start",
|
|
57
|
+
};
|
|
58
|
+
return buildAndStartCmds[pm];
|
|
59
|
+
}
|
package/dist/prompt.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promptLanguage = promptLanguage;
|
|
4
|
+
exports.promptModuleSystem = promptModuleSystem;
|
|
5
|
+
exports.promptPackageManager = promptPackageManager;
|
|
6
|
+
function renderMenu(title, options, selectedIndex, firstRender) {
|
|
7
|
+
if (!firstRender) {
|
|
8
|
+
process.stdout.write(`\x1B[${options.length + 1}A\r`);
|
|
9
|
+
}
|
|
10
|
+
process.stdout.write(`? ${title}: (Use arrow keys)\n`);
|
|
11
|
+
options.forEach((opt, i) => {
|
|
12
|
+
const hint = opt.hint ? ` ${opt.hint}` : "";
|
|
13
|
+
const isSelected = i === selectedIndex;
|
|
14
|
+
if (opt.disabled) {
|
|
15
|
+
process.stdout.write(` \x1B[2m${opt.label}${hint}\x1B[0m\n`);
|
|
16
|
+
}
|
|
17
|
+
else if (isSelected) {
|
|
18
|
+
process.stdout.write(` \x1B[36m> ${opt.label}${hint}\x1B[0m\n`);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
process.stdout.write(` ${opt.label}${hint}\n`);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function findNextEnabled(options, current, direction) {
|
|
26
|
+
let next = current + direction;
|
|
27
|
+
while (next >= 0 && next < options.length) {
|
|
28
|
+
if (!options[next].disabled)
|
|
29
|
+
return next;
|
|
30
|
+
next += direction;
|
|
31
|
+
}
|
|
32
|
+
return current;
|
|
33
|
+
}
|
|
34
|
+
function promptSelection(title, options) {
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
const defaultIndex = options.findIndex((opt) => !opt.disabled);
|
|
37
|
+
let selected = defaultIndex >= 0 ? defaultIndex : 0;
|
|
38
|
+
renderMenu(title, options, selected, true);
|
|
39
|
+
if (!process.stdin.isTTY) {
|
|
40
|
+
resolve(selected);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
process.stdin.setRawMode(true);
|
|
44
|
+
process.stdin.resume();
|
|
45
|
+
const handleKey = (key) => {
|
|
46
|
+
const isUpArrow = key[0] === 0x1b && key[1] === 0x5b && key[2] === 0x41;
|
|
47
|
+
const isDownArrow = key[0] === 0x1b && key[1] === 0x5b && key[2] === 0x42;
|
|
48
|
+
const isEnter = key[0] === 0x0d || key[0] === 0x0a;
|
|
49
|
+
const isCtrlC = key[0] === 0x03;
|
|
50
|
+
if (isUpArrow) {
|
|
51
|
+
selected = findNextEnabled(options, selected, -1);
|
|
52
|
+
renderMenu(title, options, selected, false);
|
|
53
|
+
}
|
|
54
|
+
else if (isDownArrow) {
|
|
55
|
+
selected = findNextEnabled(options, selected, 1);
|
|
56
|
+
renderMenu(title, options, selected, false);
|
|
57
|
+
}
|
|
58
|
+
else if (isEnter) {
|
|
59
|
+
process.stdin.setRawMode(false);
|
|
60
|
+
process.stdin.pause();
|
|
61
|
+
process.stdin.removeListener("data", handleKey);
|
|
62
|
+
process.stdout.write(`\x1B[${options.length + 1}A\r\x1B[J`);
|
|
63
|
+
process.stdout.write(`? ${title}: \x1B[36m${options[selected].label}\x1B[0m\n`);
|
|
64
|
+
resolve(selected);
|
|
65
|
+
}
|
|
66
|
+
else if (isCtrlC) {
|
|
67
|
+
process.stdin.setRawMode(false);
|
|
68
|
+
process.stdin.removeListener("data", handleKey);
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
process.stdin.on("data", handleKey);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async function promptLanguage() {
|
|
76
|
+
const options = [
|
|
77
|
+
{ label: "TypeScript" },
|
|
78
|
+
{ label: "JavaScript" },
|
|
79
|
+
];
|
|
80
|
+
const index = await promptSelection("Select language", options);
|
|
81
|
+
return index === 0 ? "ts" : "js";
|
|
82
|
+
}
|
|
83
|
+
async function promptModuleSystem() {
|
|
84
|
+
const options = [
|
|
85
|
+
{ label: "CommonJS", hint: "(require / module.exports)" },
|
|
86
|
+
{ label: "ES Modules", hint: "(import / export)" },
|
|
87
|
+
];
|
|
88
|
+
const index = await promptSelection("Choose module system", options);
|
|
89
|
+
return index === 0 ? "cjs" : "esm";
|
|
90
|
+
}
|
|
91
|
+
async function promptPackageManager(managers) {
|
|
92
|
+
const options = managers.map((m) => ({
|
|
93
|
+
label: m.name,
|
|
94
|
+
disabled: !m.installed,
|
|
95
|
+
hint: !m.installed ? "(not installed)" : m.name === "npm" ? "(default)" : undefined,
|
|
96
|
+
}));
|
|
97
|
+
const index = await promptSelection("Choose package manager", options);
|
|
98
|
+
return managers[index].name;
|
|
99
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.scaffoldProject = scaffoldProject;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const messages_1 = require("./messages");
|
|
39
|
+
const fs_1 = require("./fs");
|
|
40
|
+
const installer_1 = require("./installer");
|
|
41
|
+
const packageManager_1 = require("./packageManager");
|
|
42
|
+
function scaffoldProject(config) {
|
|
43
|
+
const { projectName, lang, packageManager, routerName, targetDir, templateDir, isCurrentDir } = config;
|
|
44
|
+
const replacements = {
|
|
45
|
+
"{{PROJECT_NAME}}": projectName,
|
|
46
|
+
"{{ROUTER_NAME}}": routerName,
|
|
47
|
+
};
|
|
48
|
+
console.log(messages_1.Messages.creatingProject(lang, projectName));
|
|
49
|
+
(0, fs_1.copyTemplate)(templateDir, targetDir);
|
|
50
|
+
(0, fs_1.finalizePackageJson)(targetDir, replacements);
|
|
51
|
+
(0, fs_1.applyReplacementsInSources)(path.join(targetDir, "src"), replacements);
|
|
52
|
+
(0, fs_1.renameGitignore)(targetDir);
|
|
53
|
+
(0, installer_1.installDependencies)(targetDir, projectName, packageManager);
|
|
54
|
+
console.log(messages_1.Messages.success(projectName, (0, packageManager_1.getDevCommand)(packageManager), (0, packageManager_1.getProdCommand)(packageManager, lang), isCurrentDir));
|
|
55
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.validateProjectName = validateProjectName;
|
|
37
|
+
exports.validateNewDir = validateNewDir;
|
|
38
|
+
exports.validateCurrentDir = validateCurrentDir;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const messages_1 = require("./messages");
|
|
42
|
+
function isValidPackageName(name) {
|
|
43
|
+
return /^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$/.test(name);
|
|
44
|
+
}
|
|
45
|
+
function validateProjectName(name) {
|
|
46
|
+
if (!isValidPackageName(name))
|
|
47
|
+
throw new Error(messages_1.Messages.invalidName(name));
|
|
48
|
+
}
|
|
49
|
+
function validateNewDir(targetDir, projectName) {
|
|
50
|
+
if (fs.existsSync(targetDir))
|
|
51
|
+
throw new Error(messages_1.Messages.dirExists(projectName));
|
|
52
|
+
}
|
|
53
|
+
function validateCurrentDir(targetDir) {
|
|
54
|
+
if (fs.existsSync(path.join(targetDir, "package.json"))) {
|
|
55
|
+
throw new Error(messages_1.Messages.alreadyInitialized());
|
|
56
|
+
}
|
|
57
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@patel.ajay745/exinit",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Scaffold a production-ready Express project in seconds",
|
|
5
|
+
"bin": {
|
|
6
|
+
"exinit": "./dist/cli.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist/",
|
|
10
|
+
"templates/"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"postbuild": "chmod +x dist/cli.js",
|
|
15
|
+
"dev": "tsc --watch",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=18.0.0"
|
|
20
|
+
},
|
|
21
|
+
"keywords": ["express", "typescript", "boilerplate", "scaffold", "starter"],
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"typescript": "^5.4.5",
|
|
25
|
+
"@types/node": "^20.12.7"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"_moduleAliases": {
|
|
7
|
+
"@": "src"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "nodemon src/index.js",
|
|
11
|
+
"start": "node src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"express": "^4.18.2",
|
|
15
|
+
"dotenv": "^16.4.5",
|
|
16
|
+
"module-alias": "^2.2.3"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"nodemon": "^3.1.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require("module-alias/register");
|
|
2
|
+
require("dotenv/config");
|
|
3
|
+
const express = require("express");
|
|
4
|
+
const { {{ROUTER_NAME}} } = require("@/routes/index");
|
|
5
|
+
const { errorHandler } = require("@/utils/errorHandler");
|
|
6
|
+
|
|
7
|
+
const app = express();
|
|
8
|
+
const PORT = process.env.PORT || 3000;
|
|
9
|
+
|
|
10
|
+
app.use(express.json());
|
|
11
|
+
app.use(express.urlencoded({ extended: true }));
|
|
12
|
+
app.use("/api", {{ROUTER_NAME}});
|
|
13
|
+
app.use(errorHandler);
|
|
14
|
+
|
|
15
|
+
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
|
|
16
|
+
|
|
17
|
+
module.exports = app;
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const { Router } = require("express");
|
|
2
|
+
const { asyncHandler } = require("@/utils/asyncHandler");
|
|
3
|
+
const { ApiResponse } = require("@/utils/apiResponse");
|
|
4
|
+
|
|
5
|
+
const {{ROUTER_NAME}} = Router();
|
|
6
|
+
|
|
7
|
+
{{ROUTER_NAME}}.get("/health", asyncHandler(async (req, res) => {
|
|
8
|
+
res.status(200).json(new ApiResponse(200, "Server is healthy", { status: "ok" }));
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
module.exports = { {{ROUTER_NAME}} };
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class ApiError extends Error {
|
|
2
|
+
constructor(statusCode = 500, message = "", errors = [], stack = "") {
|
|
3
|
+
super(message);
|
|
4
|
+
this.statusCode = statusCode;
|
|
5
|
+
this.message = message;
|
|
6
|
+
this.success = false;
|
|
7
|
+
this.errors = errors;
|
|
8
|
+
|
|
9
|
+
if (stack) {
|
|
10
|
+
this.stack = stack;
|
|
11
|
+
} else {
|
|
12
|
+
Error.captureStackTrace(this, this.constructor);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = { ApiError };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const { ApiError } = require("@/utils/apiError");
|
|
2
|
+
|
|
3
|
+
const errorHandler = (err, req, res, next) => {
|
|
4
|
+
if (res.headersSent) {
|
|
5
|
+
return next(err);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (err instanceof ApiError) {
|
|
9
|
+
res.status(err.statusCode).json({
|
|
10
|
+
success: false,
|
|
11
|
+
message: err.message,
|
|
12
|
+
errors: err.errors,
|
|
13
|
+
});
|
|
14
|
+
} else {
|
|
15
|
+
res.status(500).json({
|
|
16
|
+
success: false,
|
|
17
|
+
message: err.message,
|
|
18
|
+
errors: [],
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
module.exports = { errorHandler };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "nodemon src/index.js",
|
|
9
|
+
"start": "node src/index.js"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"express": "^4.18.2",
|
|
13
|
+
"dotenv": "^16.4.5"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"nodemon": "^3.1.0"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import "dotenv/config";
|
|
2
|
+
import express from "express";
|
|
3
|
+
import { {{ROUTER_NAME}} } from "./routes/index.js";
|
|
4
|
+
import { errorHandler } from "./utils/errorHandler.js";
|
|
5
|
+
|
|
6
|
+
const app = express();
|
|
7
|
+
const PORT = process.env.PORT || 3000;
|
|
8
|
+
|
|
9
|
+
app.use(express.json());
|
|
10
|
+
app.use(express.urlencoded({ extended: true }));
|
|
11
|
+
app.use("/api", {{ROUTER_NAME}});
|
|
12
|
+
app.use(errorHandler);
|
|
13
|
+
|
|
14
|
+
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
|
|
15
|
+
|
|
16
|
+
export default app;
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { asyncHandler } from "../utils/asyncHandler.js";
|
|
3
|
+
import { ApiResponse } from "../utils/apiResponse.js";
|
|
4
|
+
|
|
5
|
+
export const {{ROUTER_NAME}} = Router();
|
|
6
|
+
|
|
7
|
+
{{ROUTER_NAME}}.get("/health", asyncHandler(async (req, res) => {
|
|
8
|
+
res.status(200).json(new ApiResponse(200, "Server is healthy", { status: "ok" }));
|
|
9
|
+
}));
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class ApiError extends Error {
|
|
2
|
+
constructor(statusCode = 500, message = "", errors = [], stack = "") {
|
|
3
|
+
super(message);
|
|
4
|
+
this.statusCode = statusCode;
|
|
5
|
+
this.message = message;
|
|
6
|
+
this.success = false;
|
|
7
|
+
this.errors = errors;
|
|
8
|
+
|
|
9
|
+
if (stack) {
|
|
10
|
+
this.stack = stack;
|
|
11
|
+
} else {
|
|
12
|
+
Error.captureStackTrace(this, this.constructor);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ApiError } from "./apiError.js";
|
|
2
|
+
|
|
3
|
+
export const errorHandler = (err, req, res, next) => {
|
|
4
|
+
if (res.headersSent) {
|
|
5
|
+
return next(err);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (err instanceof ApiError) {
|
|
9
|
+
res.status(err.statusCode).json({
|
|
10
|
+
success: false,
|
|
11
|
+
message: err.message,
|
|
12
|
+
errors: err.errors,
|
|
13
|
+
});
|
|
14
|
+
} else {
|
|
15
|
+
res.status(500).json({
|
|
16
|
+
success: false,
|
|
17
|
+
message: err.message,
|
|
18
|
+
errors: [],
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "ts-node-dev --require tsconfig-paths/register --respawn --transpile-only src/index.ts",
|
|
8
|
+
"build": "tsc && tsc-alias",
|
|
9
|
+
"start": "node dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"express": "^4.18.2",
|
|
13
|
+
"dotenv": "^16.4.5"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"typescript": "^5.4.5",
|
|
17
|
+
"@types/express": "^4.17.21",
|
|
18
|
+
"@types/node": "^20.12.7",
|
|
19
|
+
"ts-node-dev": "^2.0.0",
|
|
20
|
+
"tsconfig-paths": "^4.2.0",
|
|
21
|
+
"tsc-alias": "^1.8.10"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import "dotenv/config";
|
|
2
|
+
import express from "express";
|
|
3
|
+
import { {{ROUTER_NAME}} } from "@/routes/index";
|
|
4
|
+
import { errorHandler } from "@/utils/errorHandler";
|
|
5
|
+
|
|
6
|
+
const app = express();
|
|
7
|
+
const PORT = process.env.PORT || 3000;
|
|
8
|
+
|
|
9
|
+
app.use(express.json());
|
|
10
|
+
app.use(express.urlencoded({ extended: true }));
|
|
11
|
+
app.use("/api", {{ROUTER_NAME}});
|
|
12
|
+
app.use(errorHandler);
|
|
13
|
+
|
|
14
|
+
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
|
|
15
|
+
|
|
16
|
+
export default app;
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { asyncHandler } from "@/utils/asyncHandler";
|
|
3
|
+
import { ApiResponse } from "@/utils/apiResponse";
|
|
4
|
+
|
|
5
|
+
export const {{ROUTER_NAME}} = Router();
|
|
6
|
+
|
|
7
|
+
{{ROUTER_NAME}}.get("/health", asyncHandler(async (req: any, res: any) => {
|
|
8
|
+
res.status(200).json(new ApiResponse(200, "Server is healthy", { status: "ok" }));
|
|
9
|
+
}));
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export class ApiError extends Error {
|
|
2
|
+
statusCode: number
|
|
3
|
+
message: string
|
|
4
|
+
success: boolean
|
|
5
|
+
errors: string[]
|
|
6
|
+
|
|
7
|
+
constructor(statusCode = 500, message = "", errors = [], stack = "") {
|
|
8
|
+
super(message)
|
|
9
|
+
this.statusCode = statusCode
|
|
10
|
+
this.message = message
|
|
11
|
+
this.success = false
|
|
12
|
+
this.errors = errors
|
|
13
|
+
|
|
14
|
+
if (stack) {
|
|
15
|
+
this.stack = stack
|
|
16
|
+
} else {
|
|
17
|
+
Error.captureStackTrace(this, this.constructor)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class ApiResponse {
|
|
2
|
+
statusCode: number
|
|
3
|
+
message: string
|
|
4
|
+
data: Object
|
|
5
|
+
success: boolean
|
|
6
|
+
|
|
7
|
+
constructor(statusCode: number = 200, message: string = "Success", data?: Object) {
|
|
8
|
+
this.statusCode = statusCode
|
|
9
|
+
this.message = message
|
|
10
|
+
this.data = data || {}
|
|
11
|
+
this.success = statusCode < 400
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type{ Request, Response, NextFunction } from "express"
|
|
2
|
+
|
|
3
|
+
export const asyncHandler = (requestHandler: Function) => {
|
|
4
|
+
return function (req: Request, res: Response, next: NextFunction) {
|
|
5
|
+
Promise.resolve(requestHandler(req, res, next))
|
|
6
|
+
.catch((error) => { next(error) })
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ApiError } from "@/utils/apiError";
|
|
2
|
+
import type { NextFunction, Request, Response } from "express";
|
|
3
|
+
|
|
4
|
+
export const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => {
|
|
5
|
+
if (res.headersSent) {
|
|
6
|
+
return next(err);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (err instanceof ApiError) {
|
|
10
|
+
res.status(err.statusCode).json({
|
|
11
|
+
success: false,
|
|
12
|
+
message: err.message,
|
|
13
|
+
errors: err.errors,
|
|
14
|
+
});
|
|
15
|
+
} else {
|
|
16
|
+
res.status(500).json({
|
|
17
|
+
success: false,
|
|
18
|
+
message: err.message,
|
|
19
|
+
errors: [],
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"baseUrl": ".",
|
|
9
|
+
"paths": {
|
|
10
|
+
"@/*": ["./src/*"]
|
|
11
|
+
},
|
|
12
|
+
"strict": true,
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"forceConsistentCasingInFileNames": true,
|
|
16
|
+
"resolveJsonModule": true
|
|
17
|
+
},
|
|
18
|
+
"include": ["src/**/*"],
|
|
19
|
+
"exclude": ["node_modules", "dist"]
|
|
20
|
+
}
|