create-charcole 2.2.0 → 2.2.2

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.
Files changed (77) hide show
  1. package/.github/workflows/release.yml +26 -26
  2. package/CHANGELOG.md +301 -301
  3. package/LICENSE +21 -21
  4. package/README.md +357 -354
  5. package/bin/index.js +494 -444
  6. package/bin/lib/pkgManager.js +49 -49
  7. package/bin/lib/templateHandler.js +33 -33
  8. package/package.json +42 -27
  9. package/packages/swagger/BACKWARD_COMPATIBILITY.md +1 -1
  10. package/packages/swagger/CHANGELOG.md +1 -1
  11. package/packages/swagger/README.md +3 -3
  12. package/packages/swagger/package.json +57 -44
  13. package/packages/swagger/src/index.d.ts +126 -126
  14. package/packages/swagger/src/index.js +12 -12
  15. package/packages/swagger/src/setup.js +100 -100
  16. package/template/js/.env.example +16 -15
  17. package/template/js/README.md +982 -978
  18. package/template/js/basePackage.json +26 -26
  19. package/template/js/src/app.js +81 -81
  20. package/template/js/src/config/constants.js +20 -20
  21. package/template/js/src/config/env.js +26 -26
  22. package/template/js/src/config/swagger.config.js +15 -15
  23. package/template/js/src/lib/swagger/SWAGGER_GUIDE.md +3 -3
  24. package/template/js/src/middlewares/errorHandler.js +180 -180
  25. package/template/js/src/middlewares/requestLogger.js +33 -33
  26. package/template/js/src/middlewares/validateRequest.js +42 -42
  27. package/template/js/src/modules/auth/auth.constants.js +3 -3
  28. package/template/js/src/modules/auth/auth.controller.js +29 -29
  29. package/template/js/src/modules/auth/auth.middlewares.js +19 -19
  30. package/template/js/src/modules/auth/auth.routes.js +131 -131
  31. package/template/js/src/modules/auth/auth.schemas.js +60 -60
  32. package/template/js/src/modules/auth/auth.service.js +67 -67
  33. package/template/js/src/modules/auth/package.json +6 -6
  34. package/template/js/src/modules/health/controller.js +151 -151
  35. package/template/js/src/modules/swagger/package.json +5 -5
  36. package/template/js/src/repositories/user.repo.js +19 -19
  37. package/template/js/src/routes/index.js +25 -25
  38. package/template/js/src/routes/protected.js +57 -57
  39. package/template/js/src/server.js +38 -38
  40. package/template/js/src/utils/AppError.js +182 -182
  41. package/template/js/src/utils/logger.js +73 -73
  42. package/template/js/src/utils/response.js +51 -51
  43. package/template/ts/.env.example +16 -15
  44. package/template/ts/README.md +982 -978
  45. package/template/ts/basePackage.json +36 -36
  46. package/template/ts/build.js +46 -46
  47. package/template/ts/src/app.ts +71 -71
  48. package/template/ts/src/config/constants.ts +27 -27
  49. package/template/ts/src/config/env.ts +40 -40
  50. package/template/ts/src/config/swagger.config.ts +30 -30
  51. package/template/ts/src/lib/swagger/SWAGGER_GUIDE.md +2 -2
  52. package/template/ts/src/middlewares/errorHandler.ts +201 -201
  53. package/template/ts/src/middlewares/requestLogger.ts +38 -38
  54. package/template/ts/src/middlewares/validateRequest.ts +46 -46
  55. package/template/ts/src/modules/auth/auth.constants.ts +6 -6
  56. package/template/ts/src/modules/auth/auth.controller.ts +32 -32
  57. package/template/ts/src/modules/auth/auth.middlewares.ts +46 -46
  58. package/template/ts/src/modules/auth/auth.routes.ts +52 -52
  59. package/template/ts/src/modules/auth/auth.schemas.ts +73 -73
  60. package/template/ts/src/modules/auth/auth.service.ts +106 -106
  61. package/template/ts/src/modules/auth/package.json +10 -10
  62. package/template/ts/src/modules/health/controller.ts +80 -80
  63. package/template/ts/src/modules/swagger/package.json +5 -5
  64. package/template/ts/src/repositories/user.repo.ts +33 -33
  65. package/template/ts/src/routes/index.ts +24 -24
  66. package/template/ts/src/routes/protected.ts +46 -46
  67. package/template/ts/src/server.ts +41 -41
  68. package/template/ts/src/types/express.d.ts +9 -9
  69. package/template/ts/src/utils/AppError.ts +220 -220
  70. package/template/ts/src/utils/logger.ts +55 -55
  71. package/template/ts/src/utils/response.ts +100 -100
  72. package/template/ts/tsconfig.json +26 -26
  73. package/packages/swagger/package-lock.json +0 -1715
  74. package/tmpclaude-1049-cwd +0 -1
  75. package/tmpclaude-3e37-cwd +0 -1
  76. package/tmpclaude-4d73-cwd +0 -1
  77. package/tmpclaude-8a8e-cwd +0 -1
@@ -1,151 +1,151 @@
1
- import { z } from "zod";
2
- import { sendSuccess } from "../../utils/response.js";
3
- import { asyncHandler } from "../../middlewares/errorHandler.js";
4
-
5
- /**
6
- * @swagger
7
- * /api/health:
8
- * get:
9
- * summary: Health check endpoint
10
- * description: Returns the health status of the API
11
- * tags:
12
- * - Health
13
- * responses:
14
- * 200:
15
- * description: Service is healthy
16
- * content:
17
- * application/json:
18
- * schema:
19
- * type: object
20
- * properties:
21
- * success:
22
- * type: boolean
23
- * example: true
24
- * message:
25
- * type: string
26
- * example: Service is healthy
27
- * data:
28
- * type: object
29
- * properties:
30
- * status:
31
- * type: string
32
- * example: healthy
33
- * uptime:
34
- * type: number
35
- * example: 123.45
36
- * timestamp:
37
- * type: string
38
- * format: date-time
39
- */
40
- export const getHealth = asyncHandler(async (req, res) => {
41
- sendSuccess(
42
- res,
43
- {
44
- status: "healthy",
45
- uptime: process.uptime(),
46
- timestamp: new Date().toISOString(),
47
- },
48
- 200,
49
- "Service is healthy",
50
- );
51
- });
52
-
53
- /**
54
- * Example POST endpoint with validation
55
- * Demonstrates proper error handling with Zod validation
56
- */
57
- export const createItemSchema = z.object({
58
- body: z.object({
59
- name: z.string().min(1, "Name is required").max(100),
60
- description: z.string().optional(),
61
- }),
62
- });
63
-
64
- /**
65
- * @swagger
66
- * /api/items:
67
- * post:
68
- * summary: Create a new item
69
- * description: Example endpoint demonstrating validation with Zod
70
- * tags:
71
- * - Items
72
- * requestBody:
73
- * required: true
74
- * content:
75
- * application/json:
76
- * schema:
77
- * type: object
78
- * required:
79
- * - name
80
- * properties:
81
- * name:
82
- * type: string
83
- * minLength: 1
84
- * maxLength: 100
85
- * example: My Item
86
- * description:
87
- * type: string
88
- * example: This is an example item
89
- * responses:
90
- * 201:
91
- * description: Item created successfully
92
- * content:
93
- * application/json:
94
- * schema:
95
- * type: object
96
- * properties:
97
- * success:
98
- * type: boolean
99
- * example: true
100
- * message:
101
- * type: string
102
- * example: Item created successfully
103
- * data:
104
- * type: object
105
- * properties:
106
- * id:
107
- * type: string
108
- * example: abc123def
109
- * name:
110
- * type: string
111
- * example: My Item
112
- * description:
113
- * type: string
114
- * nullable: true
115
- * example: This is an example item
116
- * createdAt:
117
- * type: string
118
- * format: date-time
119
- * 400:
120
- * description: Validation error
121
- * content:
122
- * application/json:
123
- * schema:
124
- * type: object
125
- * properties:
126
- * success:
127
- * type: boolean
128
- * example: false
129
- * message:
130
- * type: string
131
- * example: Validation failed
132
- */
133
- export const createItem = asyncHandler(async (req, res) => {
134
- const parsedData = createItemSchema.parse({ body: req.body });
135
- const { name, description } = parsedData.body;
136
-
137
- // Simulate some async work
138
- await new Promise((resolve) => setTimeout(resolve, 10));
139
-
140
- sendSuccess(
141
- res,
142
- {
143
- id: Math.random().toString(36).substr(2, 9),
144
- name,
145
- description: description || null,
146
- createdAt: new Date().toISOString(),
147
- },
148
- 201,
149
- "Item created successfully",
150
- );
151
- });
1
+ import { z } from "zod";
2
+ import { sendSuccess } from "../../utils/response.js";
3
+ import { asyncHandler } from "../../middlewares/errorHandler.js";
4
+
5
+ /**
6
+ * @swagger
7
+ * /api/health:
8
+ * get:
9
+ * summary: Health check endpoint
10
+ * description: Returns the health status of the API
11
+ * tags:
12
+ * - Health
13
+ * responses:
14
+ * 200:
15
+ * description: Service is healthy
16
+ * content:
17
+ * application/json:
18
+ * schema:
19
+ * type: object
20
+ * properties:
21
+ * success:
22
+ * type: boolean
23
+ * example: true
24
+ * message:
25
+ * type: string
26
+ * example: Service is healthy
27
+ * data:
28
+ * type: object
29
+ * properties:
30
+ * status:
31
+ * type: string
32
+ * example: healthy
33
+ * uptime:
34
+ * type: number
35
+ * example: 123.45
36
+ * timestamp:
37
+ * type: string
38
+ * format: date-time
39
+ */
40
+ export const getHealth = asyncHandler(async (req, res) => {
41
+ sendSuccess(
42
+ res,
43
+ {
44
+ status: "healthy",
45
+ uptime: process.uptime(),
46
+ timestamp: new Date().toISOString(),
47
+ },
48
+ 200,
49
+ "Service is healthy",
50
+ );
51
+ });
52
+
53
+ /**
54
+ * Example POST endpoint with validation
55
+ * Demonstrates proper error handling with Zod validation
56
+ */
57
+ export const createItemSchema = z.object({
58
+ body: z.object({
59
+ name: z.string().min(1, "Name is required").max(100),
60
+ description: z.string().optional(),
61
+ }),
62
+ });
63
+
64
+ /**
65
+ * @swagger
66
+ * /api/items:
67
+ * post:
68
+ * summary: Create a new item
69
+ * description: Example endpoint demonstrating validation with Zod
70
+ * tags:
71
+ * - Items
72
+ * requestBody:
73
+ * required: true
74
+ * content:
75
+ * application/json:
76
+ * schema:
77
+ * type: object
78
+ * required:
79
+ * - name
80
+ * properties:
81
+ * name:
82
+ * type: string
83
+ * minLength: 1
84
+ * maxLength: 100
85
+ * example: My Item
86
+ * description:
87
+ * type: string
88
+ * example: This is an example item
89
+ * responses:
90
+ * 201:
91
+ * description: Item created successfully
92
+ * content:
93
+ * application/json:
94
+ * schema:
95
+ * type: object
96
+ * properties:
97
+ * success:
98
+ * type: boolean
99
+ * example: true
100
+ * message:
101
+ * type: string
102
+ * example: Item created successfully
103
+ * data:
104
+ * type: object
105
+ * properties:
106
+ * id:
107
+ * type: string
108
+ * example: abc123def
109
+ * name:
110
+ * type: string
111
+ * example: My Item
112
+ * description:
113
+ * type: string
114
+ * nullable: true
115
+ * example: This is an example item
116
+ * createdAt:
117
+ * type: string
118
+ * format: date-time
119
+ * 400:
120
+ * description: Validation error
121
+ * content:
122
+ * application/json:
123
+ * schema:
124
+ * type: object
125
+ * properties:
126
+ * success:
127
+ * type: boolean
128
+ * example: false
129
+ * message:
130
+ * type: string
131
+ * example: Validation failed
132
+ */
133
+ export const createItem = asyncHandler(async (req, res) => {
134
+ const parsedData = createItemSchema.parse({ body: req.body });
135
+ const { name, description } = parsedData.body;
136
+
137
+ // Simulate some async work
138
+ await new Promise((resolve) => setTimeout(resolve, 10));
139
+
140
+ sendSuccess(
141
+ res,
142
+ {
143
+ id: Math.random().toString(36).substr(2, 9),
144
+ name,
145
+ description: description || null,
146
+ createdAt: new Date().toISOString(),
147
+ },
148
+ 201,
149
+ "Item created successfully",
150
+ );
151
+ });
@@ -1,5 +1,5 @@
1
- {
2
- "dependencies": {
3
- "@charcoles/swagger": "file:./charcole-swagger-1.0.0.tgz"
4
- }
5
- }
1
+ {
2
+ "dependencies": {
3
+ "@charcoles/swagger": "file:./charcole-swagger-1.0.1.tgz"
4
+ }
5
+ }
@@ -1,19 +1,19 @@
1
- import { randomUUID } from "crypto";
2
-
3
- const users = [];
4
-
5
- export const userRepo = {
6
- async findByEmail(email) {
7
- return users.find((u) => u.email === email);
8
- },
9
-
10
- async create(data) {
11
- const user = {
12
- id: randomUUID(),
13
- role: "user",
14
- ...data,
15
- };
16
- users.push(user);
17
- return user;
18
- },
19
- };
1
+ import { randomUUID } from "crypto";
2
+
3
+ const users = [];
4
+
5
+ export const userRepo = {
6
+ async findByEmail(email) {
7
+ return users.find((u) => u.email === email);
8
+ },
9
+
10
+ async create(data) {
11
+ const user = {
12
+ id: randomUUID(),
13
+ role: "user",
14
+ ...data,
15
+ };
16
+ users.push(user);
17
+ return user;
18
+ },
19
+ };
@@ -1,25 +1,25 @@
1
- import { Router } from "express";
2
- import {
3
- getHealth,
4
- createItem,
5
- createItemSchema,
6
- } from "../modules/health/controller.js";
7
- import { validateRequest } from "../middlewares/validateRequest.js";
8
- import { requireAuth } from "../modules/auth/auth.middlewares.js";
9
- import protectedRoutes from "./protected.js";
10
- import authRoutes from "../modules/auth/auth.routes.js";
11
- const router = Router();
12
-
13
- // Health check
14
- router.get("/health", getHealth);
15
-
16
- // Example: Create item with validation
17
- router.post("/items", validateRequest(createItemSchema), createItem);
18
-
19
- // 🔐 Auth routes
20
- router.use("/auth", authRoutes);
21
-
22
- // 🔐 Protected routes (REQUIRED BEARER TOKEN FOR THEM)
23
- router.use("/protected", protectedRoutes);
24
-
25
- export default router;
1
+ import { Router } from "express";
2
+ import {
3
+ getHealth,
4
+ createItem,
5
+ createItemSchema,
6
+ } from "../modules/health/controller.js";
7
+ import { validateRequest } from "../middlewares/validateRequest.js";
8
+ import { requireAuth } from "../modules/auth/auth.middlewares.js";
9
+ import protectedRoutes from "./protected.js";
10
+ import authRoutes from "../modules/auth/auth.routes.js";
11
+ const router = Router();
12
+
13
+ // Health check
14
+ router.get("/health", getHealth);
15
+
16
+ // Example: Create item with validation
17
+ router.post("/items", validateRequest(createItemSchema), createItem);
18
+
19
+ // 🔐 Auth routes
20
+ router.use("/auth", authRoutes);
21
+
22
+ // 🔐 Protected routes (REQUIRED BEARER TOKEN FOR THEM)
23
+ router.use("/protected", protectedRoutes);
24
+
25
+ export default router;
@@ -1,57 +1,57 @@
1
- import { Router } from "express";
2
- import { requireAuth } from "../modules/auth/auth.middlewares.js";
3
-
4
- const router = Router();
5
-
6
- /**
7
- * @swagger
8
- * /api/protected/me:
9
- * get:
10
- * summary: Get current user profile
11
- * description: Returns the authenticated user's information
12
- * tags:
13
- * - Protected
14
- * security:
15
- * - bearerAuth: []
16
- * responses:
17
- * 200:
18
- * description: User profile retrieved successfully
19
- * content:
20
- * application/json:
21
- * schema:
22
- * type: object
23
- * properties:
24
- * message:
25
- * type: string
26
- * example: You are authenticated
27
- * user:
28
- * type: object
29
- * properties:
30
- * id:
31
- * type: string
32
- * example: user_123abc
33
- * email:
34
- * type: string
35
- * example: user@example.com
36
- * 401:
37
- * description: Unauthorized - Invalid or missing token
38
- * content:
39
- * application/json:
40
- * schema:
41
- * type: object
42
- * properties:
43
- * success:
44
- * type: boolean
45
- * example: false
46
- * message:
47
- * type: string
48
- * example: Unauthorized
49
- */
50
- router.get("/me", requireAuth, (req, res) => {
51
- res.json({
52
- message: "You are authenticated",
53
- user: req.user,
54
- });
55
- });
56
-
57
- export default router;
1
+ import { Router } from "express";
2
+ import { requireAuth } from "../modules/auth/auth.middlewares.js";
3
+
4
+ const router = Router();
5
+
6
+ /**
7
+ * @swagger
8
+ * /api/protected/me:
9
+ * get:
10
+ * summary: Get current user profile
11
+ * description: Returns the authenticated user's information
12
+ * tags:
13
+ * - Protected
14
+ * security:
15
+ * - bearerAuth: []
16
+ * responses:
17
+ * 200:
18
+ * description: User profile retrieved successfully
19
+ * content:
20
+ * application/json:
21
+ * schema:
22
+ * type: object
23
+ * properties:
24
+ * message:
25
+ * type: string
26
+ * example: You are authenticated
27
+ * user:
28
+ * type: object
29
+ * properties:
30
+ * id:
31
+ * type: string
32
+ * example: user_123abc
33
+ * email:
34
+ * type: string
35
+ * example: user@example.com
36
+ * 401:
37
+ * description: Unauthorized - Invalid or missing token
38
+ * content:
39
+ * application/json:
40
+ * schema:
41
+ * type: object
42
+ * properties:
43
+ * success:
44
+ * type: boolean
45
+ * example: false
46
+ * message:
47
+ * type: string
48
+ * example: Unauthorized
49
+ */
50
+ router.get("/me", requireAuth, (req, res) => {
51
+ res.json({
52
+ message: "You are authenticated",
53
+ user: req.user,
54
+ });
55
+ });
56
+
57
+ export default router;
@@ -1,38 +1,38 @@
1
- import "dotenv/config";
2
-
3
- import { app } from "./app.js";
4
- import { env } from "./config/env.js";
5
- import { logger } from "./utils/logger.js";
6
-
7
- const PORT = env.PORT;
8
-
9
- const server = app.listen(PORT, () => {
10
- logger.info(`🔥 Server running in ${env.NODE_ENV} mode`, {
11
- url: `http://localhost:${PORT}`,
12
- port: PORT,
13
- });
14
- });
15
-
16
- // Graceful shutdown
17
- const gracefulShutdown = (signal) => {
18
- logger.warn(`${signal} signal received: closing HTTP server`);
19
- server.close(() => {
20
- logger.info("HTTP server closed");
21
- process.exit(0);
22
- });
23
- };
24
-
25
- process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
26
- process.on("SIGINT", () => gracefulShutdown("SIGINT"));
27
-
28
- // Unhandled promise rejections
29
- process.on("unhandledRejection", (reason, promise) => {
30
- logger.error("Unhandled Rejection at:", { promise, reason });
31
- process.exit(1);
32
- });
33
-
34
- // Uncaught exceptions
35
- process.on("uncaughtException", (error) => {
36
- logger.error("Uncaught Exception:", { error: error.message });
37
- process.exit(1);
38
- });
1
+ import "dotenv/config";
2
+
3
+ import { app } from "./app.js";
4
+ import { env } from "./config/env.js";
5
+ import { logger } from "./utils/logger.js";
6
+
7
+ const PORT = env.PORT;
8
+
9
+ const server = app.listen(PORT, () => {
10
+ logger.info(`🔥 Server running in ${env.NODE_ENV} mode`, {
11
+ url: `http://localhost:${PORT}`,
12
+ port: PORT,
13
+ });
14
+ });
15
+
16
+ // Graceful shutdown
17
+ const gracefulShutdown = (signal) => {
18
+ logger.warn(`${signal} signal received: closing HTTP server`);
19
+ server.close(() => {
20
+ logger.info("HTTP server closed");
21
+ process.exit(0);
22
+ });
23
+ };
24
+
25
+ process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
26
+ process.on("SIGINT", () => gracefulShutdown("SIGINT"));
27
+
28
+ // Unhandled promise rejections
29
+ process.on("unhandledRejection", (reason, promise) => {
30
+ logger.error("Unhandled Rejection at:", { promise, reason });
31
+ process.exit(1);
32
+ });
33
+
34
+ // Uncaught exceptions
35
+ process.on("uncaughtException", (error) => {
36
+ logger.error("Uncaught Exception:", { error: error.message });
37
+ process.exit(1);
38
+ });