@ifecodes/backend-template 1.1.8 → 1.4.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/LICENSE +201 -0
- package/README.md +423 -365
- package/bin/cli.js +1276 -836
- package/bin/lib/microservice-config.js +155 -150
- package/bin/lib/prompts.js +277 -241
- package/bin/lib/readme-generator.js +364 -335
- package/bin/lib/service-setup.js +901 -679
- package/package.json +64 -55
- package/template/base/js/.env.example +5 -5
- package/template/base/js/.eslintrc.json +10 -13
- package/template/base/js/.husky/pre-commit +1 -7
- 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 -15
- package/template/base/js/src/config/env.js +32 -2
- package/template/base/js/src/config/index.js +2 -2
- 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 -0
- package/template/base/js/src/middlewares/index.js +9 -3
- package/template/base/js/src/middlewares/method-not-allowed.middleware.js +8 -2
- package/template/base/js/src/middlewares/not-found.middleware.js +4 -1
- package/template/base/js/src/middlewares/observability.middleware.js +24 -0
- package/template/base/js/src/middlewares/root.middleware.js +7 -5
- 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 +4 -4
- package/template/base/js/src/modules/v1/health/health.route.js +70 -5
- package/template/base/js/src/modules/v1/health/index.js +1 -1
- package/template/base/js/src/modules/v1/index.js +3 -3
- package/template/base/js/src/routes.js +13 -6
- package/template/base/js/src/server.js +18 -18
- package/template/base/js/src/utils/http-error.js +27 -6
- package/template/base/js/src/utils/index.js +28 -22
- 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 -15
- 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 +26 -0
- package/template/base/ts/src/middlewares/index.ts +6 -3
- package/template/base/ts/src/middlewares/method-not-allowed.middleware.ts +23 -16
- 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 -45
- package/template/base/ts/src/utils/index.ts +14 -11
- package/template/base/ts/src/utils/logger.ts +58 -68
- package/template/base/ts/tsconfig.json +21 -22
- 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/user.model.js +24 -24
- package/template/features/auth/models/user.model.ts +1 -1
- 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/utils/hash.ts +20 -20
- package/template/features/auth/utils/jwt.js +12 -12
- 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 -31
- 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,335 +1,364 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
readme +=
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
readme +=
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
readme +=
|
|
76
|
-
readme +=
|
|
77
|
-
readme +=
|
|
78
|
-
readme +=
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
readme +=
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
readme += `\`\`\`bash\n`;
|
|
101
|
-
readme += `#
|
|
102
|
-
readme +=
|
|
103
|
-
readme +=
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
readme +=
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
readme +=
|
|
124
|
-
readme += `#
|
|
125
|
-
readme +=
|
|
126
|
-
readme += `\`\`\`\n\n`;
|
|
127
|
-
} else
|
|
128
|
-
readme +=
|
|
129
|
-
readme +=
|
|
130
|
-
readme +=
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
readme +=
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
readme +=
|
|
142
|
-
readme +=
|
|
143
|
-
readme +=
|
|
144
|
-
readme +=
|
|
145
|
-
readme +=
|
|
146
|
-
readme += `npm run
|
|
147
|
-
readme +=
|
|
148
|
-
readme +=
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
readme +=
|
|
156
|
-
|
|
157
|
-
readme +=
|
|
158
|
-
readme +=
|
|
159
|
-
readme +=
|
|
160
|
-
|
|
161
|
-
readme +=
|
|
162
|
-
|
|
163
|
-
readme +=
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
readme +=
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
readme +=
|
|
184
|
-
|
|
185
|
-
readme +=
|
|
186
|
-
readme +=
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
readme +=
|
|
222
|
-
readme +=
|
|
223
|
-
readme +=
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
readme +=
|
|
229
|
-
|
|
230
|
-
readme +=
|
|
231
|
-
readme +=
|
|
232
|
-
readme +=
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
readme +=
|
|
236
|
-
readme +=
|
|
237
|
-
readme +=
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
readme +=
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
readme +=
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
readme +=
|
|
263
|
-
readme += `├──
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
readme += `├──
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
readme +=
|
|
271
|
-
readme +=
|
|
272
|
-
|
|
273
|
-
readme +=
|
|
274
|
-
if (
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
readme += `├──
|
|
281
|
-
readme +=
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
if (
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
readme +=
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
readme +=
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
readme +=
|
|
318
|
-
readme +=
|
|
319
|
-
}
|
|
320
|
-
readme += `\n`;
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
readme +=
|
|
324
|
-
readme +=
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
1
|
+
export const generateReadme = (config, serviceName = null) => {
|
|
2
|
+
const { projectType, mode, features = [], auth, sanitizedName } = config;
|
|
3
|
+
const isMicroservice = projectType === "microservice";
|
|
4
|
+
const isTypeScript = config.language === "typescript";
|
|
5
|
+
const languageLabel = isTypeScript ? "TypeScript" : "JavaScript";
|
|
6
|
+
const monolithFileExt = isTypeScript ? "ts" : "js";
|
|
7
|
+
|
|
8
|
+
const getServices = () =>
|
|
9
|
+
config.allServices && config.allServices.length
|
|
10
|
+
? config.allServices
|
|
11
|
+
: ["gateway", "health-service", ...(auth ? ["auth-service"] : [])];
|
|
12
|
+
|
|
13
|
+
const getPort = (services, serviceName, index) =>
|
|
14
|
+
serviceName === "gateway"
|
|
15
|
+
? 4000
|
|
16
|
+
: 4001 +
|
|
17
|
+
services.filter(
|
|
18
|
+
(service, serviceIndex) =>
|
|
19
|
+
service !== "gateway" && serviceIndex < index
|
|
20
|
+
).length;
|
|
21
|
+
|
|
22
|
+
let readme = `# ${serviceName || sanitizedName}\n\n`;
|
|
23
|
+
|
|
24
|
+
if (isMicroservice && serviceName) {
|
|
25
|
+
readme += `A microservice for ${sanitizedName}.\n\n`;
|
|
26
|
+
} else if (isMicroservice) {
|
|
27
|
+
readme += `A microservices-based backend application.\n\n`;
|
|
28
|
+
} else {
|
|
29
|
+
readme += `A monolithic backend API application.\n\n`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
readme += `## Architecture\n\n`;
|
|
33
|
+
if (isMicroservice) {
|
|
34
|
+
const servicesList = getServices();
|
|
35
|
+
readme += `- **Type**: Microservice\n`;
|
|
36
|
+
readme += `- **Deployment**: ${mode === "docker" ? "Docker" : "PM2"}\n`;
|
|
37
|
+
readme += `- **Gateway**: Port 4000 (main entry point)\n`;
|
|
38
|
+
readme += `- **Services**:\n`;
|
|
39
|
+
servicesList.forEach((service, index) => {
|
|
40
|
+
const pretty = service
|
|
41
|
+
.split("-")
|
|
42
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
43
|
+
.join(" ");
|
|
44
|
+
readme += ` - ${pretty} (port ${getPort(
|
|
45
|
+
servicesList,
|
|
46
|
+
service,
|
|
47
|
+
index
|
|
48
|
+
)})\n`;
|
|
49
|
+
});
|
|
50
|
+
readme += `\n`;
|
|
51
|
+
} else {
|
|
52
|
+
readme += `- **Type**: Monolith API\n`;
|
|
53
|
+
readme += `- **Port**: 4000 (default)\n\n`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
readme += `## Tech Stack\n\n`;
|
|
57
|
+
readme += `- **Runtime**: Node.js\n`;
|
|
58
|
+
readme += `- **Language**: ${languageLabel}\n`;
|
|
59
|
+
readme += `- **Framework**: Express.js\n`;
|
|
60
|
+
if (auth) readme += `- **Database**: MongoDB (Mongoose)\n`;
|
|
61
|
+
readme += `- **Operations**: Environment validation at startup and request tracing headers\n`;
|
|
62
|
+
if (config.validation) {
|
|
63
|
+
readme += `- **Validation**: Zod schema-based request validation middleware\n`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (features.length > 0 || auth) {
|
|
67
|
+
readme += `- **Features**:\n`;
|
|
68
|
+
if (features.includes("cors")) readme += ` - CORS\n`;
|
|
69
|
+
if (features.includes("helmet"))
|
|
70
|
+
readme += ` - Helmet (Security headers)\n`;
|
|
71
|
+
if (features.includes("rate-limit")) readme += ` - Rate Limiting\n`;
|
|
72
|
+
if (features.includes("morgan")) readme += ` - Morgan (HTTP logging)\n`;
|
|
73
|
+
if (auth) readme += ` - Authentication (JWT)\n`;
|
|
74
|
+
}
|
|
75
|
+
readme += `- **Observability**: Request IDs and HTTP access logs\n`;
|
|
76
|
+
readme += `- **API Docs**: OpenAPI Swagger UI (/api-docs)\n`;
|
|
77
|
+
if (config.cicd) readme += `- **CI/CD**: GitHub Actions starter workflow\n`;
|
|
78
|
+
readme += `\n`;
|
|
79
|
+
|
|
80
|
+
readme += `## Getting Started\n\n`;
|
|
81
|
+
readme += `### Prerequisites\n\n`;
|
|
82
|
+
readme += `- Node.js (v18 or higher)\n`;
|
|
83
|
+
readme += `- npm or yarn\n`;
|
|
84
|
+
if (auth) readme += `- MongoDB\n`;
|
|
85
|
+
if (isMicroservice && mode === "docker")
|
|
86
|
+
readme += `- Docker & Docker Compose\n`;
|
|
87
|
+
if (isMicroservice && mode === "nodocker")
|
|
88
|
+
readme += `- PM2 (\`npm install -g pm2\`)\n`;
|
|
89
|
+
readme += `\n`;
|
|
90
|
+
|
|
91
|
+
readme += `### Installation\n\n`;
|
|
92
|
+
readme += `1. Clone the repository\n`;
|
|
93
|
+
readme += `\`\`\`bash\n`;
|
|
94
|
+
readme += `cd ${sanitizedName}\n`;
|
|
95
|
+
readme += `\`\`\`\n\n`;
|
|
96
|
+
|
|
97
|
+
if (isMicroservice) {
|
|
98
|
+
const servicesList = getServices();
|
|
99
|
+
readme += `2. Install dependencies for all services\n`;
|
|
100
|
+
readme += `\`\`\`bash\n`;
|
|
101
|
+
readme += `# Install root dependencies (Husky)\n`;
|
|
102
|
+
readme += `npm install\n\n`;
|
|
103
|
+
readme += `# Install dependencies for each service\n`;
|
|
104
|
+
servicesList.forEach((service) => {
|
|
105
|
+
if (
|
|
106
|
+
service === "gateway" ||
|
|
107
|
+
service === "health-service" ||
|
|
108
|
+
service === "auth-service"
|
|
109
|
+
) {
|
|
110
|
+
readme += `cd services/${service} && npm install && cd ../..\n`;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
readme += `\`\`\`\n\n`;
|
|
114
|
+
} else {
|
|
115
|
+
readme += `2. Install dependencies\n`;
|
|
116
|
+
readme += `\`\`\`bash\n`;
|
|
117
|
+
readme += `npm install\n`;
|
|
118
|
+
readme += `\`\`\`\n\n`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
readme += `3. Set up environment variables\n`;
|
|
122
|
+
if (isMicroservice) {
|
|
123
|
+
readme += `\`\`\`bash\n`;
|
|
124
|
+
readme += `# Environment variables are configured in docker-compose.yml or pm2.config.js\n`;
|
|
125
|
+
readme += `# No .env files needed for individual services\n`;
|
|
126
|
+
readme += `\`\`\`\n\n`;
|
|
127
|
+
} else {
|
|
128
|
+
readme += `\`\`\`bash\n`;
|
|
129
|
+
readme += `cp .env.example .env\n`;
|
|
130
|
+
readme += `\`\`\`\n\n`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (auth) {
|
|
134
|
+
readme += `4. Configure your MongoDB connection and JWT secret in the \`.env\` file${
|
|
135
|
+
isMicroservice ? "s" : ""
|
|
136
|
+
}\n\n`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
readme += `## Running the Application\n\n`;
|
|
140
|
+
if (isMicroservice && mode === "docker") {
|
|
141
|
+
readme += `### With Docker\n\n`;
|
|
142
|
+
readme += `\`\`\`bash\n`;
|
|
143
|
+
readme += `# Start all services\n`;
|
|
144
|
+
readme += `npm run dev\n\n`;
|
|
145
|
+
readme += `# Start in detached mode\n`;
|
|
146
|
+
readme += `npm run dev -d\n\n`;
|
|
147
|
+
readme += `# Stop all services\n`;
|
|
148
|
+
readme += `npm stop\n`;
|
|
149
|
+
readme += `\`\`\`\n\n`;
|
|
150
|
+
} else if (isMicroservice && mode === "nodocker") {
|
|
151
|
+
readme += `### With PM2\n\n`;
|
|
152
|
+
readme += `\`\`\`bash\n`;
|
|
153
|
+
readme += `# Start all services\n`;
|
|
154
|
+
readme += `pm2 start pm2.config.js\n\n`;
|
|
155
|
+
readme += `# View logs\n`;
|
|
156
|
+
readme += `pm2 logs\n\n`;
|
|
157
|
+
readme += `# Stop all services\n`;
|
|
158
|
+
readme += `pm2 stop all\n\n`;
|
|
159
|
+
readme += `# Delete all services\n`;
|
|
160
|
+
readme += `pm2 delete all\n`;
|
|
161
|
+
readme += `\`\`\`\n\n`;
|
|
162
|
+
} else {
|
|
163
|
+
readme += `### Development\n\n`;
|
|
164
|
+
readme += `\`\`\`bash\n`;
|
|
165
|
+
readme += `npm run dev\n`;
|
|
166
|
+
readme += `\`\`\`\n\n`;
|
|
167
|
+
if (isTypeScript) {
|
|
168
|
+
readme += `### Production\n\n`;
|
|
169
|
+
readme += `\`\`\`bash\n`;
|
|
170
|
+
readme += `npm run build\n`;
|
|
171
|
+
readme += `npm start\n`;
|
|
172
|
+
readme += `\`\`\`\n\n`;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
readme += `## API Endpoints\n\n`;
|
|
177
|
+
if (isMicroservice) {
|
|
178
|
+
const servicesList = getServices();
|
|
179
|
+
readme += `All requests go through the API Gateway at \`http://localhost:4000\`\n\n`;
|
|
180
|
+
readme += `### Gateway Endpoints\n`;
|
|
181
|
+
readme += `- **GET** \`/\` - API information and available endpoints\n`;
|
|
182
|
+
readme += `- **GET** \`/health\` - Gateway health check\n\n`;
|
|
183
|
+
readme += `- **GET** \`/api-docs\` - Interactive Swagger UI\n\n`;
|
|
184
|
+
readme += `### Health Service (Proxied through Gateway)\n`;
|
|
185
|
+
readme += `- **GET** \`/api/v1/health\` - Service health check with system metrics\n`;
|
|
186
|
+
readme += ` - Returns: status, uptime, timestamp, memory usage\n\n`;
|
|
187
|
+
if (auth) {
|
|
188
|
+
readme += `### Auth Service (Proxied through Gateway)\n`;
|
|
189
|
+
readme += `- **POST** \`/api/v1/auth/register\` - Register a new user\n`;
|
|
190
|
+
readme += `- **POST** \`/api/v1/auth/login\` - Login user\n\n`;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
readme += `### Direct Service Access (Development Only)\n`;
|
|
194
|
+
servicesList.forEach((service, index) => {
|
|
195
|
+
const port = getPort(servicesList, service, index);
|
|
196
|
+
const basePath = service === "gateway" ? `` : `/api/v1`;
|
|
197
|
+
readme += `- **${service}**: \`http://localhost:${port}${basePath}\`\n`;
|
|
198
|
+
});
|
|
199
|
+
readme += `\n`;
|
|
200
|
+
|
|
201
|
+
readme += `### Example Requests\n`;
|
|
202
|
+
readme += `\`\`\`bash\n`;
|
|
203
|
+
readme += `# Gateway info\n`;
|
|
204
|
+
readme += `curl http://localhost:4000/\n\n`;
|
|
205
|
+
readme += `# Gateway health\n`;
|
|
206
|
+
readme += `curl http://localhost:4000/health\n\n`;
|
|
207
|
+
|
|
208
|
+
servicesList.forEach((service, index) => {
|
|
209
|
+
if (service === "gateway") return;
|
|
210
|
+
const port = getPort(servicesList, service, index);
|
|
211
|
+
readme += `# ${service} (direct access)\n`;
|
|
212
|
+
readme += `curl http://localhost:${port}/api/v1/health\n\n`;
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
if (auth && servicesList.includes("auth-service")) {
|
|
216
|
+
const authPort = getPort(
|
|
217
|
+
servicesList,
|
|
218
|
+
"auth-service",
|
|
219
|
+
servicesList.indexOf("auth-service")
|
|
220
|
+
);
|
|
221
|
+
readme += `# Auth requests (through gateway)\n`;
|
|
222
|
+
readme += `curl -X POST http://localhost:4000/api/v1/auth/register \\\n+ -H "Content-Type: application/json" \\\n+ -d '{"username":"testuser","password":"password123"}'\n\n`;
|
|
223
|
+
readme += `curl -X POST http://localhost:4000/api/v1/auth/login \\\n+ -H "Content-Type: application/json" \\\n+ -d '{"username":"testuser","password":"password123"}'\n\n`;
|
|
224
|
+
readme += `# Auth requests (direct access)\n`;
|
|
225
|
+
readme += `curl -X POST http://localhost:${authPort}/api/v1/auth/register \\\n+ -H "Content-Type: application/json" \\\n+ -d '{"username":"testuser","password":"password123"}'\n\n`;
|
|
226
|
+
readme += `curl -X POST http://localhost:${authPort}/api/v1/auth/login \\\n+ -H "Content-Type: application/json" \\\n+ -d '{"username":"testuser","password":"password123"}'\n\n`;
|
|
227
|
+
}
|
|
228
|
+
readme += `\`\`\`\n\n`;
|
|
229
|
+
} else {
|
|
230
|
+
readme += `Base URL: \`http://localhost:4000\`\n\n`;
|
|
231
|
+
readme += `- **GET** \`/\` - Root endpoint (API info)\n`;
|
|
232
|
+
readme += `- **GET** \`/api/v1/health\` - Health check\n\n`;
|
|
233
|
+
readme += `- **GET** \`/api-docs\` - Interactive Swagger UI\n\n`;
|
|
234
|
+
if (auth) {
|
|
235
|
+
readme += `### Authentication\n`;
|
|
236
|
+
readme += `- **POST** \`/api/v1/auth/register\` - Register a new user\n`;
|
|
237
|
+
readme += `- **POST** \`/api/v1/auth/login\` - Login user\n\n`;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
readme += `### Example Requests\n`;
|
|
241
|
+
readme += `\`\`\`bash\n`;
|
|
242
|
+
readme += `# Root info\n`;
|
|
243
|
+
readme += `curl http://localhost:4000/\n\n`;
|
|
244
|
+
readme += `# Health check\n`;
|
|
245
|
+
readme += `curl http://localhost:4000/api/v1/health\n\n`;
|
|
246
|
+
if (auth) {
|
|
247
|
+
readme += `# Register user\n`;
|
|
248
|
+
readme += `curl -X POST http://localhost:4000/api/v1/auth/register \\\n+ -H "Content-Type: application/json" \\\n+ -d '{"username":"testuser","password":"password123"}'\n\n`;
|
|
249
|
+
readme += `# Login user\n`;
|
|
250
|
+
readme += `curl -X POST http://localhost:4000/api/v1/auth/login \\\n+ -H "Content-Type: application/json" \\\n+ -d '{"username":"testuser","password":"password123"}'\n\n`;
|
|
251
|
+
}
|
|
252
|
+
readme += `\`\`\`\n\n`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
readme += `## Project Structure\n\n`;
|
|
256
|
+
readme += `\`\`\`\n`;
|
|
257
|
+
if (isMicroservice) {
|
|
258
|
+
const servicesList = getServices();
|
|
259
|
+
readme += `${sanitizedName}/\n`;
|
|
260
|
+
readme += `├── shared/ # Shared utilities across services\n`;
|
|
261
|
+
readme += `│ ├── config/ # Database, environment configs\n`;
|
|
262
|
+
readme += `│ └── utils/ # Logger, error handlers\n`;
|
|
263
|
+
readme += `├── services/\n`;
|
|
264
|
+
servicesList.forEach((service) => {
|
|
265
|
+
readme += `│ ├── ${service}/\n`;
|
|
266
|
+
});
|
|
267
|
+
readme += `├── ${
|
|
268
|
+
mode === "docker" ? "docker-compose.yml" : "pm2.config.js"
|
|
269
|
+
}\n`;
|
|
270
|
+
readme += `├── .husky/ # Git hooks\n`;
|
|
271
|
+
readme += `└── package.json # Root package.json\n`;
|
|
272
|
+
} else {
|
|
273
|
+
readme += `${sanitizedName}/\n`;
|
|
274
|
+
if (config.cicd) {
|
|
275
|
+
readme += `├── .github/\n`;
|
|
276
|
+
readme += `│ ├── workflows/\n`;
|
|
277
|
+
readme += `│ │ └── ci-cd.yml # GitHub Actions CI/CD workflow\n`;
|
|
278
|
+
readme += `│ └── pull_request_template.md # PR template\n`;
|
|
279
|
+
}
|
|
280
|
+
readme += `├── .husky/ # Git hooks\n`;
|
|
281
|
+
readme += `├── src/\n`;
|
|
282
|
+
readme += `│ ├── config/ # Configuration files\n`;
|
|
283
|
+
readme += `│ ├── middlewares/ # Custom middlewares\n`;
|
|
284
|
+
readme += `│ ├── modules/ # Feature modules\n`;
|
|
285
|
+
readme += `│ │ └── v1/ # API version 1\n`;
|
|
286
|
+
if (auth) readme += `│ │ ├── auth/ # Auth module\n`;
|
|
287
|
+
readme += `│ │ └── health/ # Health check\n`;
|
|
288
|
+
if (auth) readme += `│ ├── models/ # Database models\n`;
|
|
289
|
+
readme += `│ ├── utils/ # Utility functions\n`;
|
|
290
|
+
readme += `│ ├── app.${monolithFileExt} # Express app setup\n`;
|
|
291
|
+
readme += `│ ├── routes.${monolithFileExt} # Route definitions\n`;
|
|
292
|
+
readme += `│ └── server.${monolithFileExt} # Server entry point\n`;
|
|
293
|
+
readme += `├── .husky/ # Git hooks\n`;
|
|
294
|
+
if (config.cicd)
|
|
295
|
+
readme += `├── CONTRIBUTING.md # Contribution guidelines\n`;
|
|
296
|
+
readme += `├── package.json\n`;
|
|
297
|
+
if (isTypeScript) readme += `└── tsconfig.json\n`;
|
|
298
|
+
}
|
|
299
|
+
readme += `\`\`\`\n\n`;
|
|
300
|
+
|
|
301
|
+
readme += `## Available Scripts\n\n`;
|
|
302
|
+
if (isMicroservice) {
|
|
303
|
+
if (mode === "docker") {
|
|
304
|
+
readme += `- \`npm run dev\` - Start all services\n`;
|
|
305
|
+
readme += `- \`npm stop\` - Stop all services\n`;
|
|
306
|
+
readme += `- \`docker-compose logs -f [service-name]\` - View service logs\n`;
|
|
307
|
+
} else {
|
|
308
|
+
readme += `- \`pm2 start pm2.config.js\` - Start all services\n`;
|
|
309
|
+
readme += `- \`pm2 logs\` - View all service logs\n`;
|
|
310
|
+
readme += `- \`pm2 monit\` - Monitor services\n`;
|
|
311
|
+
readme += `- \`pm2 stop all\` - Stop all services\n`;
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
readme += `- \`npm run dev\` - Start development server with hot reload\n`;
|
|
315
|
+
if (isTypeScript) readme += `- \`npm run build\` - Build for production\n`;
|
|
316
|
+
readme += `- \`npm start\` - Start production server\n`;
|
|
317
|
+
readme += `- \`npm run lint\` - Run ESLint\n`;
|
|
318
|
+
readme += `- \`npm run format\` - Run Prettier\n`;
|
|
319
|
+
}
|
|
320
|
+
readme += `\n`;
|
|
321
|
+
|
|
322
|
+
readme += `## Environment Variables\n\n`;
|
|
323
|
+
readme += `| Variable | Description | Default |\n`;
|
|
324
|
+
readme += `| --- | --- | --- |\n`;
|
|
325
|
+
if (isMicroservice) {
|
|
326
|
+
const envServices = getServices();
|
|
327
|
+
envServices.forEach((service, index) => {
|
|
328
|
+
const port = getPort(envServices, service, index);
|
|
329
|
+
const envVarName = `${service.toUpperCase().replace(/-/g, "_")}_PORT`;
|
|
330
|
+
const description = `${service.replace(/-/g, " ")} service port`;
|
|
331
|
+
readme += `| \`${envVarName}\` | ${description} | \`${port}\` |\n`;
|
|
332
|
+
});
|
|
333
|
+
} else {
|
|
334
|
+
readme += `| \`PORT\` | Server port | \`4000\` |\n`;
|
|
335
|
+
}
|
|
336
|
+
readme += `| \`NODE_ENV\` | Environment | \`development\` |\n`;
|
|
337
|
+
if (features.includes("cors")) {
|
|
338
|
+
readme += `| \`ALLOWED_ORIGIN\` | CORS allowed origin | \`http://localhost:3000\` |\n`;
|
|
339
|
+
}
|
|
340
|
+
if (auth) {
|
|
341
|
+
readme += `| \`MONGO_URI\` | MongoDB connection string | - |\n`;
|
|
342
|
+
readme += `| \`JWT_SECRET\` | JWT secret key | - |\n`;
|
|
343
|
+
}
|
|
344
|
+
readme += `\n`;
|
|
345
|
+
|
|
346
|
+
if (config.cicd && !isMicroservice) {
|
|
347
|
+
readme += `## Generated Files\n\n`;
|
|
348
|
+
readme += `The following files have been automatically generated for team projects:\n\n`;
|
|
349
|
+
readme += `- \`.github/workflows/ci-cd.yml\` - GitHub Actions CI/CD workflow\n`;
|
|
350
|
+
readme += `- \`.github/pull_request_template.md\` - Pull request template\n`;
|
|
351
|
+
readme += `- \`CONTRIBUTING.md\` - Contribution guidelines\n\n`;
|
|
352
|
+
readme += `These files are ready to use and can be customized for your team's needs.\n\n`;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
readme += `## About this Scaffold\n\n`;
|
|
356
|
+
readme += `This project was generated using the @ifecodes/backend-template scaffold. `;
|
|
357
|
+
readme += `You can recreate or customize this scaffold using the CLI:\n\n`;
|
|
358
|
+
readme += `- Run without installing (recommended): \`npx ifecodes-template\`\n`;
|
|
359
|
+
readme += `- Install globally: \`npm i -g @ifecodes/backend-template\` and run \`ifecodes-template\`\n\n`;
|
|
360
|
+
|
|
361
|
+
readme += `## License\n\nMIT\n`;
|
|
362
|
+
|
|
363
|
+
return readme;
|
|
364
|
+
};
|