create-wabck 1.0.0 → 1.1.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 +5 -1
- package/package.json +2 -6
- package/src/generator.js +8 -1
- package/src/index.js +4 -3
- package/src/prompts.js +10 -2
- package/src/templates/base.js +403 -387
- package/src/templates/config.js +1 -55
- package/src/templates/index.js +6 -0
- package/src/templates/routes.js +178 -12
- package/src/templates/swagger.js +601 -0
- package/src/utils/pkg.js +10 -2
package/src/templates/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
-
// Config Templates — db.js
|
|
2
|
+
// Config Templates — db.js & env.js
|
|
3
3
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
4
4
|
|
|
5
5
|
/** Generate src/config/db.js or db.ts */
|
|
@@ -215,57 +215,3 @@ ${database === 'mongodb' ? " mongoUri: process.env.MONGODB_URI || '',\n" : '
|
|
|
215
215
|
`;
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
/** Generate src/config/swagger.js */
|
|
219
|
-
export function swagger(options) {
|
|
220
|
-
const { projectName, language } = options;
|
|
221
|
-
const isTS = language === 'typescript';
|
|
222
|
-
|
|
223
|
-
return `import swaggerJsdoc from 'swagger-jsdoc';
|
|
224
|
-
import { readFileSync } from 'fs';
|
|
225
|
-
import { fileURLToPath } from 'url';
|
|
226
|
-
import path from 'path';
|
|
227
|
-
|
|
228
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
229
|
-
const __dirname = path.dirname(__filename);
|
|
230
|
-
|
|
231
|
-
// Read version from package.json
|
|
232
|
-
let version = '1.0.0';
|
|
233
|
-
try {
|
|
234
|
-
const pkg = JSON.parse(readFileSync(path.join(__dirname, '..', '..', 'package.json'), 'utf-8'));
|
|
235
|
-
version = pkg.version;
|
|
236
|
-
} catch { /* use default */ }
|
|
237
|
-
|
|
238
|
-
const options = {
|
|
239
|
-
definition: {
|
|
240
|
-
openapi: '3.0.0',
|
|
241
|
-
info: {
|
|
242
|
-
title: '${projectName} API',
|
|
243
|
-
version,
|
|
244
|
-
description: 'Auto-generated API documentation for ${projectName}',
|
|
245
|
-
license: { name: 'MIT' },
|
|
246
|
-
contact: { name: '${projectName} Support' },
|
|
247
|
-
},
|
|
248
|
-
servers: [
|
|
249
|
-
{ url: \`http://localhost:\${process.env.PORT || 5000}/api/v1\`, description: 'Development' },
|
|
250
|
-
],
|
|
251
|
-
components: {
|
|
252
|
-
securitySchemes: {
|
|
253
|
-
bearerAuth: {
|
|
254
|
-
type: 'http',
|
|
255
|
-
scheme: 'bearer',
|
|
256
|
-
bearerFormat: 'JWT',
|
|
257
|
-
},
|
|
258
|
-
},
|
|
259
|
-
},
|
|
260
|
-
security: [{ bearerAuth: [] }],
|
|
261
|
-
},
|
|
262
|
-
// Pick up JSDoc @swagger annotations from all route files
|
|
263
|
-
apis: [
|
|
264
|
-
path.join(__dirname, '../routes/*.js'),
|
|
265
|
-
path.join(__dirname, '../routes/*.ts'),
|
|
266
|
-
],
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
export const swaggerSpec = swaggerJsdoc(options);
|
|
270
|
-
`;
|
|
271
|
-
}
|
package/src/templates/index.js
CHANGED
package/src/templates/routes.js
CHANGED
|
@@ -27,11 +27,41 @@ export default router;
|
|
|
27
27
|
|
|
28
28
|
/** Generate src/routes/health.route.js */
|
|
29
29
|
export function healthRoute(options) {
|
|
30
|
-
const { language, database, projectName } = options;
|
|
30
|
+
const { language, database, projectName, swagger } = options;
|
|
31
31
|
const isTS = language === 'typescript';
|
|
32
32
|
|
|
33
33
|
const typeImports = isTS ? `import { Request, Response } from 'express';\n` : '';
|
|
34
34
|
|
|
35
|
+
const swaggerDoc = swagger
|
|
36
|
+
? `/**
|
|
37
|
+
* @swagger
|
|
38
|
+
* /health:
|
|
39
|
+
* get:
|
|
40
|
+
* summary: Health check & uptime
|
|
41
|
+
* tags: [Health]
|
|
42
|
+
* responses:
|
|
43
|
+
* 200:
|
|
44
|
+
* description: Service metrics, uptime, version, and memory usage
|
|
45
|
+
* content:
|
|
46
|
+
* application/json:
|
|
47
|
+
* schema:
|
|
48
|
+
* type: object
|
|
49
|
+
* properties:
|
|
50
|
+
* status: { type: string, example: ok }
|
|
51
|
+
* uptime: { type: integer, example: 120 }
|
|
52
|
+
* version: { type: string, example: 1.0.0 }
|
|
53
|
+
* env: { type: string, example: development }
|
|
54
|
+
* timestamp: { type: string, example: "2026-01-01T00:00:00.000Z" }
|
|
55
|
+
*/
|
|
56
|
+
`
|
|
57
|
+
: `/**
|
|
58
|
+
* GET /api/v1/health
|
|
59
|
+
*
|
|
60
|
+
* Returns the current health status of the API including uptime,
|
|
61
|
+
* version, environment, and timestamp.
|
|
62
|
+
*/
|
|
63
|
+
`;
|
|
64
|
+
|
|
35
65
|
return `${typeImports}import { Router } from 'express';
|
|
36
66
|
import { readFileSync } from 'fs';
|
|
37
67
|
import { fileURLToPath } from 'url';
|
|
@@ -48,13 +78,7 @@ try {
|
|
|
48
78
|
|
|
49
79
|
const router = Router();
|
|
50
80
|
|
|
51
|
-
|
|
52
|
-
* GET /api/v1/health
|
|
53
|
-
*
|
|
54
|
-
* Returns the current health status of the API including uptime,
|
|
55
|
-
* version, environment, and timestamp.
|
|
56
|
-
*/
|
|
57
|
-
router.get('/', (_req${isTS ? ': Request' : ''}, res${isTS ? ': Response' : ''}) => {
|
|
81
|
+
${swaggerDoc}router.get('/', (_req${isTS ? ': Request' : ''}, res${isTS ? ': Response' : ''}) => {
|
|
58
82
|
res.status(200).json({
|
|
59
83
|
status: 'ok',
|
|
60
84
|
uptime: Math.floor(process.uptime()),
|
|
@@ -74,7 +98,7 @@ export default router;
|
|
|
74
98
|
|
|
75
99
|
/** Generate src/routes/user.route.js */
|
|
76
100
|
export function userRoute(options) {
|
|
77
|
-
const { auth, language, validation } = options;
|
|
101
|
+
const { auth, language, validation, swagger } = options;
|
|
78
102
|
const isTS = language === 'typescript';
|
|
79
103
|
const hasJwt = auth === 'jwt';
|
|
80
104
|
const hasValidation = validation && validation !== 'none';
|
|
@@ -106,6 +130,85 @@ export function userRoute(options) {
|
|
|
106
130
|
}
|
|
107
131
|
}
|
|
108
132
|
|
|
133
|
+
const swaggerDoc = swagger
|
|
134
|
+
? `/**
|
|
135
|
+
* @swagger
|
|
136
|
+
* /users:
|
|
137
|
+
* get:
|
|
138
|
+
* summary: Retrieve all users
|
|
139
|
+
* tags: [Users]
|
|
140
|
+
* responses:
|
|
141
|
+
* 200:
|
|
142
|
+
* description: List of users retrieved successfully
|
|
143
|
+
* post:
|
|
144
|
+
* summary: Create a new user
|
|
145
|
+
* tags: [Users]
|
|
146
|
+
* requestBody:
|
|
147
|
+
* required: true
|
|
148
|
+
* content:
|
|
149
|
+
* application/json:
|
|
150
|
+
* schema:
|
|
151
|
+
* type: object
|
|
152
|
+
* required: [name, email]
|
|
153
|
+
* properties:
|
|
154
|
+
* name: { type: string, example: "Alex Smith" }
|
|
155
|
+
* email: { type: string, example: "alex@example.com" }
|
|
156
|
+
* password: { type: string, example: "SecurePass123!" }
|
|
157
|
+
* responses:
|
|
158
|
+
* 201:
|
|
159
|
+
* description: User created
|
|
160
|
+
*
|
|
161
|
+
* /users/{id}:
|
|
162
|
+
* get:
|
|
163
|
+
* summary: Get user by ID
|
|
164
|
+
* tags: [Users]
|
|
165
|
+
* parameters:
|
|
166
|
+
* - in: path
|
|
167
|
+
* name: id
|
|
168
|
+
* required: true
|
|
169
|
+
* schema: { type: string }
|
|
170
|
+
* responses:
|
|
171
|
+
* 200:
|
|
172
|
+
* description: User found
|
|
173
|
+
* 404:
|
|
174
|
+
* description: User not found
|
|
175
|
+
* put:
|
|
176
|
+
* summary: Update user by ID
|
|
177
|
+
* tags: [Users]
|
|
178
|
+
* parameters:
|
|
179
|
+
* - in: path
|
|
180
|
+
* name: id
|
|
181
|
+
* required: true
|
|
182
|
+
* schema: { type: string }
|
|
183
|
+
* requestBody:
|
|
184
|
+
* required: true
|
|
185
|
+
* content:
|
|
186
|
+
* application/json:
|
|
187
|
+
* schema:
|
|
188
|
+
* type: object
|
|
189
|
+
* properties:
|
|
190
|
+
* name: { type: string }
|
|
191
|
+
* email: { type: string }
|
|
192
|
+
* responses:
|
|
193
|
+
* 200:
|
|
194
|
+
* description: User updated
|
|
195
|
+
* delete:
|
|
196
|
+
* summary: Delete user by ID
|
|
197
|
+
* tags: [Users]
|
|
198
|
+
* security:
|
|
199
|
+
* - bearerAuth: []
|
|
200
|
+
* parameters:
|
|
201
|
+
* - in: path
|
|
202
|
+
* name: id
|
|
203
|
+
* required: true
|
|
204
|
+
* schema: { type: string }
|
|
205
|
+
* responses:
|
|
206
|
+
* 200:
|
|
207
|
+
* description: User deleted
|
|
208
|
+
*/
|
|
209
|
+
`
|
|
210
|
+
: '';
|
|
211
|
+
|
|
109
212
|
return `import { Router } from 'express';
|
|
110
213
|
import {
|
|
111
214
|
getAllUsers,
|
|
@@ -120,7 +223,7 @@ const router = Router();
|
|
|
120
223
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
121
224
|
// User Routes — /api/v1/users
|
|
122
225
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
123
|
-
|
|
226
|
+
${swaggerDoc}
|
|
124
227
|
router.get('/', ${guardStart}getAllUsers);
|
|
125
228
|
router.post('/', ${guardStart}${validateCreate}createUser);
|
|
126
229
|
router.get('/:id', ${guardStart}getUserById);
|
|
@@ -133,7 +236,7 @@ export default router;
|
|
|
133
236
|
|
|
134
237
|
/** Generate src/routes/auth.route.js (JWT only) */
|
|
135
238
|
export function authRoute(options) {
|
|
136
|
-
const { language, validation } = options;
|
|
239
|
+
const { language, validation, swagger } = options;
|
|
137
240
|
const isTS = language === 'typescript';
|
|
138
241
|
const hasValidation = validation && validation !== 'none';
|
|
139
242
|
|
|
@@ -153,6 +256,69 @@ export function authRoute(options) {
|
|
|
153
256
|
}
|
|
154
257
|
}
|
|
155
258
|
|
|
259
|
+
const swaggerDoc = swagger
|
|
260
|
+
? `/**
|
|
261
|
+
* @swagger
|
|
262
|
+
* /auth/register:
|
|
263
|
+
* post:
|
|
264
|
+
* summary: Register a new user account
|
|
265
|
+
* tags: [Auth]
|
|
266
|
+
* requestBody:
|
|
267
|
+
* required: true
|
|
268
|
+
* content:
|
|
269
|
+
* application/json:
|
|
270
|
+
* schema:
|
|
271
|
+
* type: object
|
|
272
|
+
* required: [name, email, password]
|
|
273
|
+
* properties:
|
|
274
|
+
* name: { type: string, example: "Jane Doe" }
|
|
275
|
+
* email: { type: string, example: "jane@example.com" }
|
|
276
|
+
* password: { type: string, example: "Secret123!" }
|
|
277
|
+
* responses:
|
|
278
|
+
* 201:
|
|
279
|
+
* description: Registered successfully
|
|
280
|
+
*
|
|
281
|
+
* /auth/login:
|
|
282
|
+
* post:
|
|
283
|
+
* summary: Authenticate user & get JWT tokens
|
|
284
|
+
* tags: [Auth]
|
|
285
|
+
* requestBody:
|
|
286
|
+
* required: true
|
|
287
|
+
* content:
|
|
288
|
+
* application/json:
|
|
289
|
+
* schema:
|
|
290
|
+
* type: object
|
|
291
|
+
* required: [email, password]
|
|
292
|
+
* properties:
|
|
293
|
+
* email: { type: string, example: "jane@example.com" }
|
|
294
|
+
* password: { type: string, example: "Secret123!" }
|
|
295
|
+
* responses:
|
|
296
|
+
* 200:
|
|
297
|
+
* description: Login successful
|
|
298
|
+
*
|
|
299
|
+
* /auth/logout:
|
|
300
|
+
* post:
|
|
301
|
+
* summary: Invalidate user session
|
|
302
|
+
* tags: [Auth]
|
|
303
|
+
* security:
|
|
304
|
+
* - bearerAuth: []
|
|
305
|
+
* responses:
|
|
306
|
+
* 200:
|
|
307
|
+
* description: Logged out
|
|
308
|
+
*
|
|
309
|
+
* /auth/me:
|
|
310
|
+
* get:
|
|
311
|
+
* summary: Get profile of logged-in user
|
|
312
|
+
* tags: [Auth]
|
|
313
|
+
* security:
|
|
314
|
+
* - bearerAuth: []
|
|
315
|
+
* responses:
|
|
316
|
+
* 200:
|
|
317
|
+
* description: Current user profile
|
|
318
|
+
*/
|
|
319
|
+
`
|
|
320
|
+
: '';
|
|
321
|
+
|
|
156
322
|
return `import { Router } from 'express';
|
|
157
323
|
import {
|
|
158
324
|
register,
|
|
@@ -168,7 +334,7 @@ const router = Router();
|
|
|
168
334
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
169
335
|
// Auth Routes — /api/v1/auth
|
|
170
336
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
171
|
-
|
|
337
|
+
${swaggerDoc}
|
|
172
338
|
router.post('/register', authRateLimiter, ${validateRegister}register);
|
|
173
339
|
router.post('/login', authRateLimiter, ${validateLogin}login);
|
|
174
340
|
router.post('/logout', authenticate, logout);
|