express-project-init 0.0.0-stage → 1.1.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/README.md +140 -2
- package/dist/features.js +17 -0
- package/dist/features.js.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/services/file.service.js +73 -0
- package/dist/services/file.service.js.map +1 -0
- package/dist/services/project.service.js +44 -0
- package/dist/services/project.service.js.map +1 -0
- package/dist/services/prompts.service.js +92 -0
- package/dist/services/prompts.service.js.map +1 -0
- package/dist/services/template.service.js +200 -0
- package/dist/services/template.service.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +57 -4
- package/templates/format/biome/both/biome.json +17 -0
- package/templates/format/biome/both/package.json +12 -0
- package/templates/format/biome/format/biome.json +14 -0
- package/templates/format/biome/format/package.json +9 -0
- package/templates/format/prettier/.prettierignore +3 -0
- package/templates/format/prettier/.prettierrc +6 -0
- package/templates/format/prettier/package.json +9 -0
- package/templates/javascript/base/package.json +13 -0
- package/templates/javascript/base/src/app.js +22 -0
- package/templates/javascript/base/src/server.js +8 -0
- package/templates/javascript/base/src/utils/helpers.js +3 -0
- package/templates/javascript/base/src/utils/responseHelpers.js +19 -0
- package/templates/javascript/error-handler/src/app.js +28 -0
- package/templates/javascript/error-handler/src/middleware/error.middleware.js +36 -0
- package/templates/javascript/error-handler/src/middleware/notFound.middleware.js +5 -0
- package/templates/javascript/error-handler/src/utils/AppError.js +30 -0
- package/templates/lint/biome/biome.json +15 -0
- package/templates/lint/biome/package.json +9 -0
- package/templates/lint/eslint/eslint.config.js +36 -0
- package/templates/lint/eslint/package.json +12 -0
- package/templates/lint/oxlint/.oxlintrc.json +13 -0
- package/templates/lint/oxlint/package.json +9 -0
- package/templates/typescript/base/package.json +20 -0
- package/templates/typescript/base/src/app.ts +22 -0
- package/templates/typescript/base/src/server.ts +8 -0
- package/templates/typescript/base/src/utils/helpers.ts +3 -0
- package/templates/typescript/base/src/utils/responseHelpers.ts +42 -0
- package/templates/typescript/base/tsconfig.json +30 -0
- package/templates/typescript/error-handler/src/app.ts +28 -0
- package/templates/typescript/error-handler/src/middleware/error.middleware.ts +42 -0
- package/templates/typescript/error-handler/src/middleware/notFound.middleware.ts +10 -0
- package/templates/typescript/error-handler/src/utils/AppError.ts +44 -0
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-project-init",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Create production-ready Express.js API projects with JavaScript or TypeScript using clean, reusable starter templates.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"express-project-init": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"templates",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=20"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"dev": "tsx src/index.ts",
|
|
21
|
+
"clean": "node -e \"const fs=require('node:fs'); for (const p of ['dist','tsconfig.tsbuildinfo']) fs.rmSync(p,{recursive:true,force:true})\"",
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"prepack": "npm run clean && npm run build",
|
|
25
|
+
"start": "node dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/raunak-ray/ExpressKit.git"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/raunak-ray/ExpressKit#readme",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/raunak-ray/ExpressKit/issues"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"express",
|
|
37
|
+
"expressjs",
|
|
38
|
+
"express-generator",
|
|
39
|
+
"express-cli",
|
|
40
|
+
"nodejs",
|
|
41
|
+
"api-generator",
|
|
42
|
+
"backend",
|
|
43
|
+
"project-scaffolding",
|
|
44
|
+
"boilerplate",
|
|
45
|
+
"starter-template",
|
|
46
|
+
"typescript",
|
|
47
|
+
"javascript"
|
|
48
|
+
],
|
|
49
|
+
"author": "Raunak Ray",
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@clack/prompts": "^1.8.1"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "^26.6.5",
|
|
56
|
+
"tsx": "^4.23.15",
|
|
57
|
+
"typescript": "^7.0.2"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.6.4/schema.json",
|
|
3
|
+
"files": {
|
|
4
|
+
"ignoreUnknown": false
|
|
5
|
+
},
|
|
6
|
+
"formatter": {
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"indentStyle": "space",
|
|
9
|
+
"indentWidth": 2
|
|
10
|
+
},
|
|
11
|
+
"linter": {
|
|
12
|
+
"enabled": true,
|
|
13
|
+
"rules": {
|
|
14
|
+
"preset": "recommended"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-api",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Express API generated by ExpressKit",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "node --watch src/server.js",
|
|
8
|
+
"start": "node src/server.js"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"express": "^5.1.0"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import { getTimeStamp } from "./utils/helpers.js";
|
|
3
|
+
import { successResponse } from "./utils/responseHelpers.js";
|
|
4
|
+
|
|
5
|
+
const app = express();
|
|
6
|
+
|
|
7
|
+
app.use(express.json());
|
|
8
|
+
|
|
9
|
+
// Health check
|
|
10
|
+
app.get("/health", (_req, res) =>
|
|
11
|
+
successResponse(res, {
|
|
12
|
+
statusCode: 200,
|
|
13
|
+
message: "API is up and running",
|
|
14
|
+
data: {
|
|
15
|
+
status: "ok",
|
|
16
|
+
uptime: Math.round(process.uptime()),
|
|
17
|
+
timestamp: getTimeStamp(),
|
|
18
|
+
},
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export default app;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function successResponse(res, { statusCode = 200, message, data }) {
|
|
2
|
+
return res.status(statusCode).json({
|
|
3
|
+
success: true,
|
|
4
|
+
message,
|
|
5
|
+
data,
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function errorResponse(
|
|
10
|
+
res,
|
|
11
|
+
{ statusCode = 500, message, code = "INTERNAL_ERROR", fields },
|
|
12
|
+
) {
|
|
13
|
+
return res.status(statusCode).json({
|
|
14
|
+
success: false,
|
|
15
|
+
message,
|
|
16
|
+
code,
|
|
17
|
+
fields,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import errorMiddleware from "./middleware/error.middleware.js";
|
|
3
|
+
import notFoundMiddleware from "./middleware/notFound.middleware.js";
|
|
4
|
+
import { getTimeStamp } from "./utils/helpers.js";
|
|
5
|
+
import { successResponse } from "./utils/responseHelpers.js";
|
|
6
|
+
|
|
7
|
+
const app = express();
|
|
8
|
+
|
|
9
|
+
app.use(express.json());
|
|
10
|
+
|
|
11
|
+
// Health check
|
|
12
|
+
app.get("/health", (_req, res) =>
|
|
13
|
+
successResponse(res, {
|
|
14
|
+
statusCode: 200,
|
|
15
|
+
message: "API is up and running",
|
|
16
|
+
data: {
|
|
17
|
+
status: "ok",
|
|
18
|
+
uptime: Math.round(process.uptime()),
|
|
19
|
+
timestamp: getTimeStamp(),
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Unknown routes → 404, then every error gets formatted in one place.
|
|
25
|
+
app.use(notFoundMiddleware);
|
|
26
|
+
app.use(errorMiddleware);
|
|
27
|
+
|
|
28
|
+
export default app;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { AppError, BadRequestError } from "../utils/AppError.js";
|
|
2
|
+
import { getTimeStamp } from "../utils/helpers.js";
|
|
3
|
+
import { errorResponse } from "../utils/responseHelpers.js";
|
|
4
|
+
|
|
5
|
+
// Express error handler — needs all 4 params, that's how Express recognizes it.
|
|
6
|
+
export default function errorMiddleware(error, req, res, _next) {
|
|
7
|
+
const timeStamp = getTimeStamp();
|
|
8
|
+
|
|
9
|
+
// Expected errors — log them and send their details
|
|
10
|
+
if (error instanceof AppError) {
|
|
11
|
+
console.log(
|
|
12
|
+
`[${timeStamp}] [ERROR] ${req.method} ${req.originalUrl} - ${error.message}`,
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
return errorResponse(res, {
|
|
16
|
+
statusCode: error.statusCode,
|
|
17
|
+
message: error.message,
|
|
18
|
+
code: error.code,
|
|
19
|
+
fields: error instanceof BadRequestError ? error.fields : undefined, // fields only for bad requests
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Not an AppError — build a message if it's an Error, otherwise fall back
|
|
24
|
+
const message =
|
|
25
|
+
error instanceof Error ? error.message : "Internal server error";
|
|
26
|
+
|
|
27
|
+
console.error(
|
|
28
|
+
`[${timeStamp}] [ERROR] ${req.method} ${req.originalUrl} - ${message}`,
|
|
29
|
+
error,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return errorResponse(res, {
|
|
33
|
+
statusCode: 500,
|
|
34
|
+
message,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class AppError extends Error {
|
|
2
|
+
constructor(message, { code = "INTERNAL_ERROR", statusCode = 500 } = {}) {
|
|
3
|
+
super(message);
|
|
4
|
+
|
|
5
|
+
this.name = this.constructor.name;
|
|
6
|
+
this.code = code; // machine-readable code, e.g. "BAD_REQUEST"
|
|
7
|
+
this.statusCode = statusCode; // HTTP status to send back
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class BadRequestError extends AppError {
|
|
12
|
+
// fields: validation errors, e.g. [{ field: "email", message: "required" }]
|
|
13
|
+
constructor(message = "Bad request", fields = []) {
|
|
14
|
+
super(message, { code: "BAD_REQUEST", statusCode: 400 });
|
|
15
|
+
|
|
16
|
+
this.fields = fields;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class UnauthorizedError extends AppError {
|
|
21
|
+
constructor(message = "Unauthorized") {
|
|
22
|
+
super(message, { code: "UNAUTHORIZED", statusCode: 401 });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class NotFoundError extends AppError {
|
|
27
|
+
constructor(message = "Not found") {
|
|
28
|
+
super(message, { code: "NOT_FOUND", statusCode: 404 });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
2
|
+
import globals from "globals";
|
|
3
|
+
import tseslint from "typescript-eslint";
|
|
4
|
+
|
|
5
|
+
let prettier = [];
|
|
6
|
+
try {
|
|
7
|
+
const prettierConfig = await import("eslint-config-prettier");
|
|
8
|
+
prettier = [prettierConfig.default];
|
|
9
|
+
} catch (error) {
|
|
10
|
+
// eslint-config-prettier is optional, used when Prettier is also configured
|
|
11
|
+
void error;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default tseslint.config(
|
|
15
|
+
{
|
|
16
|
+
languageOptions: {
|
|
17
|
+
globals: {
|
|
18
|
+
...globals.node,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
js.configs.recommended,
|
|
23
|
+
...tseslint.configs.recommended,
|
|
24
|
+
{
|
|
25
|
+
rules: {
|
|
26
|
+
"@typescript-eslint/no-unused-vars": [
|
|
27
|
+
"error",
|
|
28
|
+
{
|
|
29
|
+
argsIgnorePattern: "^_",
|
|
30
|
+
varsIgnorePattern: "^_",
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
...prettier,
|
|
36
|
+
);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
3
|
+
"plugins": ["typescript", "unicorn", "oxc"],
|
|
4
|
+
"categories": {
|
|
5
|
+
"correctness": "error"
|
|
6
|
+
},
|
|
7
|
+
"rules": {},
|
|
8
|
+
"env": {
|
|
9
|
+
"builtin": true,
|
|
10
|
+
"node": true
|
|
11
|
+
},
|
|
12
|
+
"ignorePatterns": ["node_modules", "dist"]
|
|
13
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-api",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Express API generated by ExpressKit",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "tsx watch src/server.ts",
|
|
8
|
+
"start": "tsx src/server.ts",
|
|
9
|
+
"typecheck": "tsc --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"express": "^5.1.0"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/express": "^5.0.0",
|
|
16
|
+
"@types/node": "^26.6.5",
|
|
17
|
+
"tsx": "^4.23.15",
|
|
18
|
+
"typescript": "^5.9.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import express, { type Request, type Response } from "express";
|
|
2
|
+
import { getTimeStamp } from "./utils/helpers";
|
|
3
|
+
import { successResponse } from "./utils/responseHelpers";
|
|
4
|
+
|
|
5
|
+
const app = express();
|
|
6
|
+
|
|
7
|
+
app.use(express.json());
|
|
8
|
+
|
|
9
|
+
// Health check
|
|
10
|
+
app.get("/health", (_req: Request, res: Response) =>
|
|
11
|
+
successResponse(res, {
|
|
12
|
+
statusCode: 200,
|
|
13
|
+
message: "API is up and running",
|
|
14
|
+
data: {
|
|
15
|
+
status: "ok",
|
|
16
|
+
uptime: Math.round(process.uptime()),
|
|
17
|
+
timestamp: getTimeStamp(),
|
|
18
|
+
},
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export default app;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Response } from "express";
|
|
2
|
+
|
|
3
|
+
export type FieldError = {
|
|
4
|
+
field: string;
|
|
5
|
+
message: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type SuccessOptions<T> = {
|
|
9
|
+
statusCode?: number;
|
|
10
|
+
message: string;
|
|
11
|
+
data?: T;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function successResponse<T>(
|
|
15
|
+
res: Response,
|
|
16
|
+
{ statusCode = 200, message, data }: SuccessOptions<T>,
|
|
17
|
+
): Response {
|
|
18
|
+
return res.status(statusCode).json({
|
|
19
|
+
success: true,
|
|
20
|
+
message,
|
|
21
|
+
data,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type ErrorOptions = {
|
|
26
|
+
statusCode?: number;
|
|
27
|
+
message: string;
|
|
28
|
+
code?: string;
|
|
29
|
+
fields?: FieldError[];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export function errorResponse(
|
|
33
|
+
res: Response,
|
|
34
|
+
{ statusCode = 500, message, code = "INTERNAL_ERROR", fields }: ErrorOptions,
|
|
35
|
+
): Response {
|
|
36
|
+
return res.status(statusCode).json({
|
|
37
|
+
success: false,
|
|
38
|
+
message,
|
|
39
|
+
code,
|
|
40
|
+
fields,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Imports / modules
|
|
4
|
+
// "bundler" is THE setting that lets you import WITHOUT extensions:
|
|
5
|
+
// import app from "./app" (not "./app.ts")
|
|
6
|
+
"module": "esnext", // emit modern ES module syntax
|
|
7
|
+
"moduleResolution": "bundler", // resolve imports without ".ts" extensions
|
|
8
|
+
"moduleDetection": "force", // treat every file as an ES module (no CommonJS guessing)
|
|
9
|
+
"esModuleInterop": true, // allow normal default imports from CJS packages (express)
|
|
10
|
+
"verbatimModuleSyntax": true, // keep imports exactly as written; type-only imports must use "import type"
|
|
11
|
+
|
|
12
|
+
// Language level
|
|
13
|
+
"target": "esnext", // allow the newest JS features, no downleveling
|
|
14
|
+
|
|
15
|
+
// Type checking
|
|
16
|
+
"strict": true, // turn on all strict type checks
|
|
17
|
+
"noUnusedLocals": true, // error on declared-but-unused variables
|
|
18
|
+
"noUnusedParameters": true, // error on unused function parameters
|
|
19
|
+
"skipLibCheck": true, // don't type-check ".d.ts" files inside node_modules (faster)
|
|
20
|
+
|
|
21
|
+
// Runtime types
|
|
22
|
+
"types": ["node"], // auto-include ONLY Node types (no stray umbrella types)
|
|
23
|
+
|
|
24
|
+
// Output
|
|
25
|
+
"noEmit": true // tsx runs the code directly, so tsc only type-checks, never writes files
|
|
26
|
+
},
|
|
27
|
+
// Files in scope
|
|
28
|
+
"include": ["src"], // the compiler only looks at src/
|
|
29
|
+
"exclude": ["node_modules"] // never scan dependencies
|
|
30
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import express, { type Request, type Response } from "express";
|
|
2
|
+
import errorMiddleware from "./middleware/error.middleware";
|
|
3
|
+
import notFoundMiddleware from "./middleware/notFound.middleware";
|
|
4
|
+
import { getTimeStamp } from "./utils/helpers";
|
|
5
|
+
import { successResponse } from "./utils/responseHelpers";
|
|
6
|
+
|
|
7
|
+
const app = express();
|
|
8
|
+
|
|
9
|
+
app.use(express.json());
|
|
10
|
+
|
|
11
|
+
// Health check
|
|
12
|
+
app.get("/health", (_req: Request, res: Response) =>
|
|
13
|
+
successResponse(res, {
|
|
14
|
+
statusCode: 200,
|
|
15
|
+
message: "API is up and running",
|
|
16
|
+
data: {
|
|
17
|
+
status: "ok",
|
|
18
|
+
uptime: Math.round(process.uptime()),
|
|
19
|
+
timestamp: getTimeStamp(),
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Unknown routes → 404, then every error gets formatted in one place.
|
|
25
|
+
app.use(notFoundMiddleware);
|
|
26
|
+
app.use(errorMiddleware);
|
|
27
|
+
|
|
28
|
+
export default app;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { NextFunction, Request, Response } from "express";
|
|
2
|
+
import { AppError, BadRequestError } from "../utils/AppError";
|
|
3
|
+
import { getTimeStamp } from "../utils/helpers";
|
|
4
|
+
import { errorResponse } from "../utils/responseHelpers";
|
|
5
|
+
|
|
6
|
+
// Express error handler — needs all 4 params, that's how Express recognizes it.
|
|
7
|
+
export default function errorMiddleware(
|
|
8
|
+
error: unknown,
|
|
9
|
+
req: Request,
|
|
10
|
+
res: Response,
|
|
11
|
+
_next: NextFunction,
|
|
12
|
+
): Response {
|
|
13
|
+
const timeStamp = getTimeStamp();
|
|
14
|
+
|
|
15
|
+
// Expected errors — log them and send their details
|
|
16
|
+
if (error instanceof AppError) {
|
|
17
|
+
console.log(
|
|
18
|
+
`[${timeStamp}] [ERROR] ${req.method} ${req.originalUrl} - ${error.message}`,
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
return errorResponse(res, {
|
|
22
|
+
statusCode: error.statusCode,
|
|
23
|
+
message: error.message,
|
|
24
|
+
code: error.code,
|
|
25
|
+
fields: error instanceof BadRequestError ? error.fields : undefined, // fields only for bad requests
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Not an AppError — build a message if it's an Error, otherwise fall back
|
|
30
|
+
const message =
|
|
31
|
+
error instanceof Error ? error.message : "Internal server error";
|
|
32
|
+
|
|
33
|
+
console.error(
|
|
34
|
+
`[${timeStamp}] [ERROR] ${req.method} ${req.originalUrl} - ${message}`,
|
|
35
|
+
error,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return errorResponse(res, {
|
|
39
|
+
statusCode: 500,
|
|
40
|
+
message,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { NextFunction, Request, Response } from "express";
|
|
2
|
+
import { NotFoundError } from "../utils/AppError";
|
|
3
|
+
|
|
4
|
+
export default function notFoundMiddleware(
|
|
5
|
+
_req: Request,
|
|
6
|
+
_res: Response,
|
|
7
|
+
next: NextFunction,
|
|
8
|
+
): void {
|
|
9
|
+
next(new NotFoundError("Route not found"));
|
|
10
|
+
}
|