@ifecodes/backend-template 1.1.9 → 1.4.1
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 +423 -383
- package/bin/cli.js +1294 -964
- package/bin/lib/microservice-config.js +155 -150
- package/bin/lib/prompts.js +277 -241
- package/bin/lib/readme-generator.js +364 -329
- package/bin/lib/service-setup.js +901 -684
- package/package.json +64 -55
- package/template/base/js/.eslintrc.json +10 -13
- package/template/base/js/.prettierrc +7 -7
- package/template/base/js/eslint.config.js +33 -31
- package/template/base/js/package.json +29 -28
- package/template/base/js/src/app.js +20 -18
- package/template/base/js/src/config/db.js +8 -8
- package/template/base/js/src/config/env.js +44 -14
- package/template/base/js/src/config/index.js +7 -7
- package/template/base/js/src/docs/index.js +5 -0
- package/template/base/js/src/docs/route-registry.js +63 -0
- package/template/base/js/src/middlewares/error-handler.middleware.js +22 -19
- package/template/base/js/src/middlewares/index.js +15 -11
- package/template/base/js/src/middlewares/method-not-allowed.middleware.js +19 -13
- package/template/base/js/src/middlewares/not-found.middleware.js +13 -10
- package/template/base/js/src/middlewares/observability.middleware.js +24 -0
- package/template/base/js/src/middlewares/root.middleware.js +18 -16
- package/template/base/js/src/middlewares/validation.middleware.js +39 -0
- package/template/base/js/src/modules/index.js +8 -8
- package/template/base/js/src/modules/v1/health/health.controller.auth.js +29 -0
- package/template/base/js/src/modules/v1/health/health.controller.js +21 -21
- package/template/base/js/src/modules/v1/health/health.route.js +74 -9
- package/template/base/js/src/modules/v1/health/index.js +5 -5
- package/template/base/js/src/modules/v1/index.js +8 -8
- package/template/base/js/src/routes.js +23 -16
- package/template/base/js/src/server.js +18 -18
- package/template/base/js/src/utils/http-error.js +74 -74
- package/template/base/js/src/utils/index.js +28 -28
- package/template/base/js/src/utils/logger.js +57 -67
- package/template/base/ts/.eslintrc.json +13 -17
- package/template/base/ts/.prettierrc +7 -7
- package/template/base/ts/eslint.config.js +33 -33
- package/template/base/ts/package.json +41 -39
- package/template/base/ts/src/app.ts +20 -18
- package/template/base/ts/src/config/db.ts +4 -4
- package/template/base/ts/src/config/env.ts +40 -10
- package/template/base/ts/src/config/index.ts +2 -2
- package/template/base/ts/src/docs/index.ts +3 -0
- package/template/base/ts/src/docs/route-registry.ts +98 -0
- package/template/base/ts/src/middlewares/error-handler.middleware.ts +4 -1
- package/template/base/ts/src/middlewares/index.ts +6 -4
- package/template/base/ts/src/middlewares/method-not-allowed.middleware.ts +23 -18
- package/template/base/ts/src/middlewares/not-found.middleware.ts +10 -8
- package/template/base/ts/src/middlewares/observability.middleware.ts +25 -0
- package/template/base/ts/src/middlewares/root.middleware.ts +16 -14
- package/template/base/ts/src/middlewares/validation.middleware.ts +46 -0
- package/template/base/ts/src/modules/index.ts +8 -8
- package/template/base/ts/src/modules/v1/health/health.controller.auth.ts +26 -0
- package/template/base/ts/src/modules/v1/health/health.controller.ts +18 -18
- package/template/base/ts/src/modules/v1/health/health.route.ts +68 -9
- package/template/base/ts/src/modules/v1/health/index.ts +1 -1
- package/template/base/ts/src/modules/v1/index.ts +8 -8
- package/template/base/ts/src/routes.ts +23 -15
- package/template/base/ts/src/server.ts +19 -19
- package/template/base/ts/src/utils/http-error.ts +63 -63
- package/template/base/ts/src/utils/index.ts +14 -14
- package/template/base/ts/src/utils/logger.ts +58 -68
- package/template/base/ts/tsconfig.json +21 -21
- package/template/features/auth/argon2/inject.js +50 -50
- package/template/features/auth/base/health-openapi.ts +62 -0
- package/template/features/auth/base/inject.js +174 -172
- package/template/features/auth/bcrypt/inject.js +40 -40
- package/template/features/auth/models/index.ts +1 -1
- package/template/features/auth/models/user.model.js +24 -24
- package/template/features/auth/models/user.model.ts +28 -28
- package/template/features/auth/modules/auth.controller.js +21 -21
- package/template/features/auth/modules/auth.controller.ts +28 -20
- package/template/features/auth/modules/auth.routes.js +89 -10
- package/template/features/auth/modules/auth.routes.ts +86 -11
- package/template/features/auth/modules/auth.service.js +29 -29
- package/template/features/auth/modules/auth.service.ts +38 -38
- package/template/features/auth/modules/index.js +1 -1
- package/template/features/auth/modules/index.ts +1 -1
- package/template/features/auth/utils/hash.ts +20 -20
- package/template/features/auth/utils/jwt.js +12 -12
- package/template/features/auth/utils/jwt.ts +15 -15
- package/template/features/cors/inject.js +14 -13
- package/template/features/helmet/inject.js +7 -6
- package/template/features/morgan/inject.js +8 -7
- package/template/features/rate-limit/inject.js +7 -6
- package/template/gateway/js/app.js +42 -42
- package/template/gateway/js/inject.js +33 -33
- package/template/gateway/js/server.js +19 -19
- package/template/gateway/ts/app.ts +43 -43
- package/template/gateway/ts/inject.js +33 -33
- package/template/gateway/ts/server.ts +19 -19
- package/template/microservice/docker/docker-compose.yml +5 -5
- package/template/microservice/nodocker/pm2.config.js +3 -3
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
export const deps = ["argon2"];
|
|
2
|
-
|
|
3
|
-
export const getFiles = (language = "typescript") => {
|
|
4
|
-
const ext = language === "javascript" ? ".js" : ".ts";
|
|
5
|
-
|
|
6
|
-
const tsContent = `import argon2 from "argon2";
|
|
7
|
-
|
|
8
|
-
const HASH_OPTIONS = {
|
|
9
|
-
type: argon2.argon2id,
|
|
10
|
-
memoryCost: 2 ** 16,
|
|
11
|
-
timeCost: 3,
|
|
12
|
-
parallelism: 1,
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const hashPassword = async (password: string): Promise<string> => {
|
|
16
|
-
return argon2.hash(password, HASH_OPTIONS);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const verifyPassword = async (
|
|
20
|
-
hash: string,
|
|
21
|
-
password: string,
|
|
22
|
-
): Promise<boolean> => {
|
|
23
|
-
return argon2.verify(hash, password);
|
|
24
|
-
};
|
|
25
|
-
`;
|
|
26
|
-
|
|
27
|
-
const jsContent = `const argon2 = require("argon2");
|
|
28
|
-
|
|
29
|
-
const HASH_OPTIONS = {
|
|
30
|
-
type: argon2.argon2id,
|
|
31
|
-
memoryCost: 2 ** 16,
|
|
32
|
-
timeCost: 3,
|
|
33
|
-
parallelism: 1,
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
async function hashPassword(password) {
|
|
37
|
-
return argon2.hash(password, HASH_OPTIONS);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async function verifyPassword(hash, password) {
|
|
41
|
-
return argon2.verify(hash, password);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
module.exports = { hashPassword, verifyPassword };
|
|
45
|
-
`;
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
[`src/utils/hash${ext}`]: language === "javascript" ? jsContent : tsContent,
|
|
49
|
-
};
|
|
50
|
-
};
|
|
1
|
+
export const deps = ["argon2"];
|
|
2
|
+
|
|
3
|
+
export const getFiles = (language = "typescript") => {
|
|
4
|
+
const ext = language === "javascript" ? ".js" : ".ts";
|
|
5
|
+
|
|
6
|
+
const tsContent = `import argon2 from "argon2";
|
|
7
|
+
|
|
8
|
+
const HASH_OPTIONS = {
|
|
9
|
+
type: argon2.argon2id,
|
|
10
|
+
memoryCost: 2 ** 16,
|
|
11
|
+
timeCost: 3,
|
|
12
|
+
parallelism: 1,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const hashPassword = async (password: string): Promise<string> => {
|
|
16
|
+
return argon2.hash(password, HASH_OPTIONS);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const verifyPassword = async (
|
|
20
|
+
hash: string,
|
|
21
|
+
password: string,
|
|
22
|
+
): Promise<boolean> => {
|
|
23
|
+
return argon2.verify(hash, password);
|
|
24
|
+
};
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
const jsContent = `const argon2 = require("argon2");
|
|
28
|
+
|
|
29
|
+
const HASH_OPTIONS = {
|
|
30
|
+
type: argon2.argon2id,
|
|
31
|
+
memoryCost: 2 ** 16,
|
|
32
|
+
timeCost: 3,
|
|
33
|
+
parallelism: 1,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
async function hashPassword(password) {
|
|
37
|
+
return argon2.hash(password, HASH_OPTIONS);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function verifyPassword(hash, password) {
|
|
41
|
+
return argon2.verify(hash, password);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = { hashPassword, verifyPassword };
|
|
45
|
+
`;
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
[`src/utils/hash${ext}`]: language === "javascript" ? jsContent : tsContent,
|
|
49
|
+
};
|
|
50
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Enhanced OpenAPI spec for health endpoint when auth is enabled
|
|
2
|
+
export const healthOpenApiWithMongo = {
|
|
3
|
+
get: {
|
|
4
|
+
tags: ["Health"],
|
|
5
|
+
summary: "Health check with MongoDB status",
|
|
6
|
+
description:
|
|
7
|
+
"Returns API health, runtime metrics, and MongoDB connection status.",
|
|
8
|
+
parameters: [
|
|
9
|
+
{
|
|
10
|
+
name: "verbose",
|
|
11
|
+
in: "query",
|
|
12
|
+
required: false,
|
|
13
|
+
schema: { type: "boolean" },
|
|
14
|
+
description: "Optional verbose mode for richer diagnostics.",
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
responses: {
|
|
18
|
+
"200": {
|
|
19
|
+
description: "Healthy response",
|
|
20
|
+
content: {
|
|
21
|
+
"application/json": {
|
|
22
|
+
schema: {
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: {
|
|
25
|
+
status: { type: "string", enum: ["healthy", "unhealthy"] },
|
|
26
|
+
uptime: { type: "number" },
|
|
27
|
+
timestamp: { type: "string" },
|
|
28
|
+
services: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
mongodb: {
|
|
32
|
+
type: "string",
|
|
33
|
+
enum: ["connected", "disconnected"],
|
|
34
|
+
},
|
|
35
|
+
memory: {
|
|
36
|
+
type: "object",
|
|
37
|
+
properties: {
|
|
38
|
+
rss: { type: "number" },
|
|
39
|
+
heapUsed: { type: "number" },
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
failed: {
|
|
45
|
+
type: "array",
|
|
46
|
+
items: { type: "string" },
|
|
47
|
+
description: "List of failed services",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
"400": {
|
|
55
|
+
description: "Validation error",
|
|
56
|
+
},
|
|
57
|
+
"503": {
|
|
58
|
+
description: "Service unhealthy (when MongoDB is down)",
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
@@ -1,172 +1,174 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
|
|
5
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
-
|
|
7
|
-
// Read all module files
|
|
8
|
-
const modulesDir = path.join(__dirname, "../modules");
|
|
9
|
-
const modelsDir = path.join(__dirname, "../models");
|
|
10
|
-
const utilsDir = path.join(__dirname, "../utils");
|
|
11
|
-
|
|
12
|
-
const readDirFiles = (dir, prefix = "", language = "typescript") => {
|
|
13
|
-
const files = {};
|
|
14
|
-
const items = fs.readdirSync(dir);
|
|
15
|
-
const ext = language === "javascript" ? ".js" : ".ts";
|
|
16
|
-
|
|
17
|
-
for (const item of items) {
|
|
18
|
-
const fullPath = path.join(dir, item);
|
|
19
|
-
const isDir = fs.statSync(fullPath).isDirectory();
|
|
20
|
-
const desiredName = item.replace(/\.ts$|\.js$/, ext);
|
|
21
|
-
const chosenPath = isDir
|
|
22
|
-
? fullPath
|
|
23
|
-
: fs.existsSync(path.join(dir, desiredName))
|
|
24
|
-
? path.join(dir, desiredName)
|
|
25
|
-
: fullPath;
|
|
26
|
-
|
|
27
|
-
const relativePath = path.join(prefix, path.basename(desiredName));
|
|
28
|
-
|
|
29
|
-
if (isDir) {
|
|
30
|
-
Object.assign(files, readDirFiles(chosenPath, relativePath, language));
|
|
31
|
-
} else {
|
|
32
|
-
const content = fs.readFileSync(chosenPath, "utf8");
|
|
33
|
-
files[relativePath] = content;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return files;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const getDbContent = (language) => {
|
|
41
|
-
const tsContent = `import mongoose from "mongoose";
|
|
42
|
-
import { ENV } from "./env";
|
|
43
|
-
import { logger } from "@/utils";
|
|
44
|
-
|
|
45
|
-
export const connectDB = async () => {
|
|
46
|
-
try {
|
|
47
|
-
await mongoose.connect(ENV.MONGO_URI);
|
|
48
|
-
logger.log("db", "MongoDB connected");
|
|
49
|
-
} catch (error) {
|
|
50
|
-
logger.error("db", "MongoDB connection failed", error);
|
|
51
|
-
process.exit(1);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
`;
|
|
55
|
-
|
|
56
|
-
if (language === "javascript") {
|
|
57
|
-
return `const mongoose = require("mongoose");
|
|
58
|
-
const { ENV } = require("./env");
|
|
59
|
-
const { logger } = require("../utils");
|
|
60
|
-
|
|
61
|
-
async function connectDB() {
|
|
62
|
-
try {
|
|
63
|
-
await mongoose.connect(ENV.MONGO_URI);
|
|
64
|
-
logger.log("db", "MongoDB connected");
|
|
65
|
-
} catch (error) {
|
|
66
|
-
logger.error("db", "MongoDB connection failed", error);
|
|
67
|
-
process.exit(1);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
module.exports = { connectDB };
|
|
72
|
-
`;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return tsContent;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const getHealthControllerContent = (language) => {
|
|
79
|
-
const tsContent = `import { Request, Response } from "express";
|
|
80
|
-
import mongoose from "mongoose";
|
|
81
|
-
const { logger } = require("../../../utils");
|
|
82
|
-
|
|
83
|
-
export const healthCheck = async (_req: Request, res: Response) => {
|
|
84
|
-
const mongoState = mongoose.connection.readyState;
|
|
85
|
-
const healthy = mongoState === 1;
|
|
86
|
-
|
|
87
|
-
const failed: string[] = [];
|
|
88
|
-
if (mongoState !== 1) failed.push("mongodb");
|
|
89
|
-
|
|
90
|
-
logger.info("Health", healthy ? "healthy" : "unhealthy");
|
|
91
|
-
|
|
92
|
-
return res.status(healthy ? 200 : 503).json({
|
|
93
|
-
status: healthy ? "healthy" : "unhealthy",
|
|
94
|
-
uptime: process.uptime(),
|
|
95
|
-
timestamp: new Date().toISOString(),
|
|
96
|
-
services: {
|
|
97
|
-
mongodb: mongoState === 1 ? "connected" : "disconnected",
|
|
98
|
-
memory: {
|
|
99
|
-
rss: process.memoryUsage().rss,
|
|
100
|
-
heapUsed: process.memoryUsage().heapUsed,
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
failed,
|
|
104
|
-
});
|
|
105
|
-
};
|
|
106
|
-
`;
|
|
107
|
-
|
|
108
|
-
if (language === "javascript") {
|
|
109
|
-
return `const mongoose = require("mongoose");
|
|
110
|
-
const { logger } = require("../../../utils");
|
|
111
|
-
|
|
112
|
-
async function healthCheck(_req, res) {
|
|
113
|
-
const mongoState = mongoose.connection.readyState;
|
|
114
|
-
const healthy = mongoState === 1;
|
|
115
|
-
|
|
116
|
-
const failed = [];
|
|
117
|
-
if (mongoState !== 1) failed.push("mongodb");
|
|
118
|
-
|
|
119
|
-
logger.info("Health", healthy ? "healthy" : "unhealthy");
|
|
120
|
-
|
|
121
|
-
return res.status(healthy ? 200 : 503).json({
|
|
122
|
-
status: healthy ? "healthy" : "unhealthy",
|
|
123
|
-
uptime: process.uptime(),
|
|
124
|
-
timestamp: new Date().toISOString(),
|
|
125
|
-
services: {
|
|
126
|
-
mongodb: mongoState === 1 ? "connected" : "disconnected",
|
|
127
|
-
memory: {
|
|
128
|
-
rss: process.memoryUsage().rss,
|
|
129
|
-
heapUsed: process.memoryUsage().heapUsed,
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
failed,
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
module.exports = { healthCheck };
|
|
137
|
-
`;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return tsContent;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
export const getFiles = (language = "typescript") => {
|
|
144
|
-
const ext = language === "javascript" ? ".js" : ".ts";
|
|
145
|
-
const moduleFiles = readDirFiles(modulesDir, "src/modules/v1/auth", language);
|
|
146
|
-
const modelFiles = readDirFiles(modelsDir, "src/models", language);
|
|
147
|
-
const utilFiles = readDirFiles(utilsDir, "src/utils", language);
|
|
148
|
-
|
|
149
|
-
return {
|
|
150
|
-
...moduleFiles,
|
|
151
|
-
...modelFiles,
|
|
152
|
-
...utilFiles,
|
|
153
|
-
[`src/config/db${ext}`]: getDbContent(language),
|
|
154
|
-
[`src/modules/v1/health/health.controller${ext}`]:
|
|
155
|
-
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
export const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
export const
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
|
|
7
|
+
// Read all module files
|
|
8
|
+
const modulesDir = path.join(__dirname, "../modules");
|
|
9
|
+
const modelsDir = path.join(__dirname, "../models");
|
|
10
|
+
const utilsDir = path.join(__dirname, "../utils");
|
|
11
|
+
|
|
12
|
+
const readDirFiles = (dir, prefix = "", language = "typescript") => {
|
|
13
|
+
const files = {};
|
|
14
|
+
const items = fs.readdirSync(dir);
|
|
15
|
+
const ext = language === "javascript" ? ".js" : ".ts";
|
|
16
|
+
|
|
17
|
+
for (const item of items) {
|
|
18
|
+
const fullPath = path.join(dir, item);
|
|
19
|
+
const isDir = fs.statSync(fullPath).isDirectory();
|
|
20
|
+
const desiredName = item.replace(/\.ts$|\.js$/, ext);
|
|
21
|
+
const chosenPath = isDir
|
|
22
|
+
? fullPath
|
|
23
|
+
: fs.existsSync(path.join(dir, desiredName))
|
|
24
|
+
? path.join(dir, desiredName)
|
|
25
|
+
: fullPath;
|
|
26
|
+
|
|
27
|
+
const relativePath = path.join(prefix, path.basename(desiredName));
|
|
28
|
+
|
|
29
|
+
if (isDir) {
|
|
30
|
+
Object.assign(files, readDirFiles(chosenPath, relativePath, language));
|
|
31
|
+
} else {
|
|
32
|
+
const content = fs.readFileSync(chosenPath, "utf8");
|
|
33
|
+
files[relativePath] = content;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return files;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const getDbContent = (language) => {
|
|
41
|
+
const tsContent = `import mongoose from "mongoose";
|
|
42
|
+
import { ENV } from "./env";
|
|
43
|
+
import { logger } from "@/utils";
|
|
44
|
+
|
|
45
|
+
export const connectDB = async () => {
|
|
46
|
+
try {
|
|
47
|
+
await mongoose.connect(ENV.MONGO_URI);
|
|
48
|
+
logger.log("db", "MongoDB connected");
|
|
49
|
+
} catch (error) {
|
|
50
|
+
logger.error("db", "MongoDB connection failed", error);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
if (language === "javascript") {
|
|
57
|
+
return `const mongoose = require("mongoose");
|
|
58
|
+
const { ENV } = require("./env");
|
|
59
|
+
const { logger } = require("../utils");
|
|
60
|
+
|
|
61
|
+
async function connectDB() {
|
|
62
|
+
try {
|
|
63
|
+
await mongoose.connect(ENV.MONGO_URI);
|
|
64
|
+
logger.log("db", "MongoDB connected");
|
|
65
|
+
} catch (error) {
|
|
66
|
+
logger.error("db", "MongoDB connection failed", error);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = { connectDB };
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return tsContent;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const getHealthControllerContent = (language) => {
|
|
79
|
+
const tsContent = `import { Request, Response } from "express";
|
|
80
|
+
import mongoose from "mongoose";
|
|
81
|
+
const { logger } = require("../../../utils");
|
|
82
|
+
|
|
83
|
+
export const healthCheck = async (_req: Request, res: Response) => {
|
|
84
|
+
const mongoState = mongoose.connection.readyState;
|
|
85
|
+
const healthy = mongoState === 1;
|
|
86
|
+
|
|
87
|
+
const failed: string[] = [];
|
|
88
|
+
if (mongoState !== 1) failed.push("mongodb");
|
|
89
|
+
|
|
90
|
+
logger.info("Health", healthy ? "healthy" : "unhealthy");
|
|
91
|
+
|
|
92
|
+
return res.status(healthy ? 200 : 503).json({
|
|
93
|
+
status: healthy ? "healthy" : "unhealthy",
|
|
94
|
+
uptime: process.uptime(),
|
|
95
|
+
timestamp: new Date().toISOString(),
|
|
96
|
+
services: {
|
|
97
|
+
mongodb: mongoState === 1 ? "connected" : "disconnected",
|
|
98
|
+
memory: {
|
|
99
|
+
rss: process.memoryUsage().rss,
|
|
100
|
+
heapUsed: process.memoryUsage().heapUsed,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
failed,
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
if (language === "javascript") {
|
|
109
|
+
return `const mongoose = require("mongoose");
|
|
110
|
+
const { logger } = require("../../../utils");
|
|
111
|
+
|
|
112
|
+
async function healthCheck(_req, res) {
|
|
113
|
+
const mongoState = mongoose.connection.readyState;
|
|
114
|
+
const healthy = mongoState === 1;
|
|
115
|
+
|
|
116
|
+
const failed = [];
|
|
117
|
+
if (mongoState !== 1) failed.push("mongodb");
|
|
118
|
+
|
|
119
|
+
logger.info("Health", healthy ? "healthy" : "unhealthy");
|
|
120
|
+
|
|
121
|
+
return res.status(healthy ? 200 : 503).json({
|
|
122
|
+
status: healthy ? "healthy" : "unhealthy",
|
|
123
|
+
uptime: process.uptime(),
|
|
124
|
+
timestamp: new Date().toISOString(),
|
|
125
|
+
services: {
|
|
126
|
+
mongodb: mongoState === 1 ? "connected" : "disconnected",
|
|
127
|
+
memory: {
|
|
128
|
+
rss: process.memoryUsage().rss,
|
|
129
|
+
heapUsed: process.memoryUsage().heapUsed,
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
failed,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports = { healthCheck };
|
|
137
|
+
`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return tsContent;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export const getFiles = (language = "typescript") => {
|
|
144
|
+
const ext = language === "javascript" ? ".js" : ".ts";
|
|
145
|
+
const moduleFiles = readDirFiles(modulesDir, "src/modules/v1/auth", language);
|
|
146
|
+
const modelFiles = readDirFiles(modelsDir, "src/models", language);
|
|
147
|
+
const utilFiles = readDirFiles(utilsDir, "src/utils", language);
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
...moduleFiles,
|
|
151
|
+
...modelFiles,
|
|
152
|
+
...utilFiles,
|
|
153
|
+
[`src/config/db${ext}`]: getDbContent(language),
|
|
154
|
+
[`src/modules/v1/health/health.controller${ext}`]:
|
|
155
|
+
getHealthControllerContent(language),
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// For backward compatibility
|
|
160
|
+
export const files = getFiles("typescript");
|
|
161
|
+
|
|
162
|
+
export const imports = `import { authRoutes } from "./auth";`;
|
|
163
|
+
|
|
164
|
+
export const getImports = (language) =>
|
|
165
|
+
language === "javascript"
|
|
166
|
+
? `const { authRoutes } = require("./auth");`
|
|
167
|
+
: `import { authRoutes } from "./auth";`;
|
|
168
|
+
|
|
169
|
+
export const middleware = `router.use("/auth", authRoutes);`;
|
|
170
|
+
|
|
171
|
+
export const deps = ["jsonwebtoken", "mongoose"];
|
|
172
|
+
export const devDeps = ["@types/jsonwebtoken"];
|
|
173
|
+
|
|
174
|
+
export const targetFile = "src/modules/v1/index.ts";
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
export const deps = ["bcrypt"];
|
|
2
|
-
|
|
3
|
-
export const devDeps = ["@types/bcrypt"];
|
|
4
|
-
|
|
5
|
-
export const getFiles = (language = "typescript") => {
|
|
6
|
-
const ext = language === "javascript" ? ".js" : ".ts";
|
|
7
|
-
|
|
8
|
-
const tsContent = `import bcrypt from "bcrypt";
|
|
9
|
-
|
|
10
|
-
export const hashPassword = async (password: string): Promise<string> => {
|
|
11
|
-
const salt = await bcrypt.genSalt(10);
|
|
12
|
-
return bcrypt.hash(password, salt);
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const verifyPassword = async (
|
|
16
|
-
hash: string,
|
|
17
|
-
password: string,
|
|
18
|
-
): Promise<boolean> => {
|
|
19
|
-
return bcrypt.compare(password, hash);
|
|
20
|
-
};
|
|
21
|
-
`;
|
|
22
|
-
|
|
23
|
-
const jsContent = `const bcrypt = require("bcrypt");
|
|
24
|
-
|
|
25
|
-
async function hashPassword(password) {
|
|
26
|
-
const salt = await bcrypt.genSalt(10);
|
|
27
|
-
return bcrypt.hash(password, salt);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async function verifyPassword(hash, password) {
|
|
31
|
-
return bcrypt.compare(password, hash);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
module.exports = { hashPassword, verifyPassword };
|
|
35
|
-
`;
|
|
36
|
-
|
|
37
|
-
return {
|
|
38
|
-
[`src/utils/hash${ext}`]: language === "javascript" ? jsContent : tsContent,
|
|
39
|
-
};
|
|
40
|
-
};
|
|
1
|
+
export const deps = ["bcrypt"];
|
|
2
|
+
|
|
3
|
+
export const devDeps = ["@types/bcrypt"];
|
|
4
|
+
|
|
5
|
+
export const getFiles = (language = "typescript") => {
|
|
6
|
+
const ext = language === "javascript" ? ".js" : ".ts";
|
|
7
|
+
|
|
8
|
+
const tsContent = `import bcrypt from "bcrypt";
|
|
9
|
+
|
|
10
|
+
export const hashPassword = async (password: string): Promise<string> => {
|
|
11
|
+
const salt = await bcrypt.genSalt(10);
|
|
12
|
+
return bcrypt.hash(password, salt);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const verifyPassword = async (
|
|
16
|
+
hash: string,
|
|
17
|
+
password: string,
|
|
18
|
+
): Promise<boolean> => {
|
|
19
|
+
return bcrypt.compare(password, hash);
|
|
20
|
+
};
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
const jsContent = `const bcrypt = require("bcrypt");
|
|
24
|
+
|
|
25
|
+
async function hashPassword(password) {
|
|
26
|
+
const salt = await bcrypt.genSalt(10);
|
|
27
|
+
return bcrypt.hash(password, salt);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function verifyPassword(hash, password) {
|
|
31
|
+
return bcrypt.compare(password, hash);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = { hashPassword, verifyPassword };
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
[`src/utils/hash${ext}`]: language === "javascript" ? jsContent : tsContent,
|
|
39
|
+
};
|
|
40
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { UserModel, IUser } from "./user.model";
|
|
1
|
+
export { UserModel, IUser } from "./user.model";
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
const mongoose = require("mongoose");
|
|
2
|
-
|
|
3
|
-
const userSchema = new mongoose.Schema(
|
|
4
|
-
{
|
|
5
|
-
email: {
|
|
6
|
-
type: String,
|
|
7
|
-
required: true,
|
|
8
|
-
unique: true,
|
|
9
|
-
},
|
|
10
|
-
password: {
|
|
11
|
-
type: String,
|
|
12
|
-
required: true,
|
|
13
|
-
},
|
|
14
|
-
fullName: {
|
|
15
|
-
type: String,
|
|
16
|
-
required: true,
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
{ timestamps: true }
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
const UserModel = mongoose.model("User", userSchema);
|
|
23
|
-
|
|
24
|
-
module.exports = { UserModel };
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
|
|
3
|
+
const userSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
email: {
|
|
6
|
+
type: String,
|
|
7
|
+
required: true,
|
|
8
|
+
unique: true,
|
|
9
|
+
},
|
|
10
|
+
password: {
|
|
11
|
+
type: String,
|
|
12
|
+
required: true,
|
|
13
|
+
},
|
|
14
|
+
fullName: {
|
|
15
|
+
type: String,
|
|
16
|
+
required: true,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{ timestamps: true }
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const UserModel = mongoose.model("User", userSchema);
|
|
23
|
+
|
|
24
|
+
module.exports = { UserModel };
|