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,80 +1,80 @@
1
- import { Request, Response } from "express";
2
- import { z } from "zod";
3
- import { sendSuccess } from "../../utils/response.ts";
4
- import { asyncHandler } from "../../middlewares/errorHandler.ts";
5
-
6
- /**
7
- * @swagger
8
- * /api/health:
9
- * get:
10
- * summary: Health check endpoint
11
- * description: Returns the health status of the API
12
- * tags:
13
- * - Health
14
- * responses:
15
- * 200:
16
- * $ref: '#/components/responses/Success'
17
- */
18
- export const getHealth = asyncHandler(async (req: Request, res: Response) => {
19
- sendSuccess(
20
- res,
21
- {
22
- status: "healthy" as const,
23
- uptime: process.uptime(),
24
- timestamp: new Date().toISOString(),
25
- },
26
- 200,
27
- "Service is healthy",
28
- );
29
- });
30
-
31
- /**
32
- * Example POST endpoint with validation
33
- * Demonstrates proper error handling with Zod validation
34
- */
35
- export const createItemSchema = z.object({
36
- body: z.object({
37
- name: z.string().min(1, "Name is required").max(100),
38
- description: z.string().optional(),
39
- }),
40
- });
41
-
42
- /**
43
- * @swagger
44
- * /api/items:
45
- * post:
46
- * summary: Create a new item
47
- * description: Example endpoint demonstrating validation with Zod
48
- * tags:
49
- * - Items
50
- * requestBody:
51
- * required: true
52
- * content:
53
- * application/json:
54
- * schema:
55
- * $ref: '#/components/schemas/createItemSchema'
56
- * responses:
57
- * 201:
58
- * $ref: '#/components/responses/Success'
59
- * 400:
60
- * $ref: '#/components/responses/ValidationError'
61
- */
62
- export const createItem = asyncHandler(async (req: Request, res: Response) => {
63
- const parsed = createItemSchema.parse({ body: req.body });
64
- const { name, description } = parsed.body;
65
-
66
- // Simulate some async work
67
- await new Promise((resolve) => setTimeout(resolve, 10));
68
-
69
- sendSuccess(
70
- res,
71
- {
72
- id: Math.random().toString(36).substr(2, 9),
73
- name,
74
- description: description || null,
75
- createdAt: new Date().toISOString(),
76
- },
77
- 201,
78
- "Item created successfully",
79
- );
80
- });
1
+ import { Request, Response } from "express";
2
+ import { z } from "zod";
3
+ import { sendSuccess } from "../../utils/response.ts";
4
+ import { asyncHandler } from "../../middlewares/errorHandler.ts";
5
+
6
+ /**
7
+ * @swagger
8
+ * /api/health:
9
+ * get:
10
+ * summary: Health check endpoint
11
+ * description: Returns the health status of the API
12
+ * tags:
13
+ * - Health
14
+ * responses:
15
+ * 200:
16
+ * $ref: '#/components/responses/Success'
17
+ */
18
+ export const getHealth = asyncHandler(async (req: Request, res: Response) => {
19
+ sendSuccess(
20
+ res,
21
+ {
22
+ status: "healthy" as const,
23
+ uptime: process.uptime(),
24
+ timestamp: new Date().toISOString(),
25
+ },
26
+ 200,
27
+ "Service is healthy",
28
+ );
29
+ });
30
+
31
+ /**
32
+ * Example POST endpoint with validation
33
+ * Demonstrates proper error handling with Zod validation
34
+ */
35
+ export const createItemSchema = z.object({
36
+ body: z.object({
37
+ name: z.string().min(1, "Name is required").max(100),
38
+ description: z.string().optional(),
39
+ }),
40
+ });
41
+
42
+ /**
43
+ * @swagger
44
+ * /api/items:
45
+ * post:
46
+ * summary: Create a new item
47
+ * description: Example endpoint demonstrating validation with Zod
48
+ * tags:
49
+ * - Items
50
+ * requestBody:
51
+ * required: true
52
+ * content:
53
+ * application/json:
54
+ * schema:
55
+ * $ref: '#/components/schemas/createItemSchema'
56
+ * responses:
57
+ * 201:
58
+ * $ref: '#/components/responses/Success'
59
+ * 400:
60
+ * $ref: '#/components/responses/ValidationError'
61
+ */
62
+ export const createItem = asyncHandler(async (req: Request, res: Response) => {
63
+ const parsed = createItemSchema.parse({ body: req.body });
64
+ const { name, description } = parsed.body;
65
+
66
+ // Simulate some async work
67
+ await new Promise((resolve) => setTimeout(resolve, 10));
68
+
69
+ sendSuccess(
70
+ res,
71
+ {
72
+ id: Math.random().toString(36).substr(2, 9),
73
+ name,
74
+ description: description || null,
75
+ createdAt: new Date().toISOString(),
76
+ },
77
+ 201,
78
+ "Item created successfully",
79
+ );
80
+ });
@@ -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,33 +1,33 @@
1
- import { randomUUID } from "crypto";
2
- import type { User } from "../modules/auth/auth.schemas.ts";
3
-
4
- const users: User[] = [];
5
-
6
- type CreateUserData = {
7
- email: string;
8
- name: string;
9
- passwordHash: string;
10
- };
11
-
12
- export const userRepo = {
13
- async findByEmail(email: string): Promise<User | undefined> {
14
- return users.find((u) => u.email === email);
15
- },
16
-
17
- async create(data: CreateUserData): Promise<User> {
18
- const user: User = {
19
- id: randomUUID(),
20
- email: data.email,
21
- name: data.name,
22
- passwordHash: data.passwordHash,
23
- role: "user",
24
- provider: "credentials",
25
- isEmailVerified: false,
26
- createdAt: new Date(),
27
- updatedAt: new Date(),
28
- };
29
-
30
- users.push(user);
31
- return user;
32
- },
33
- };
1
+ import { randomUUID } from "crypto";
2
+ import type { User } from "../modules/auth/auth.schemas.ts";
3
+
4
+ const users: User[] = [];
5
+
6
+ type CreateUserData = {
7
+ email: string;
8
+ name: string;
9
+ passwordHash: string;
10
+ };
11
+
12
+ export const userRepo = {
13
+ async findByEmail(email: string): Promise<User | undefined> {
14
+ return users.find((u) => u.email === email);
15
+ },
16
+
17
+ async create(data: CreateUserData): Promise<User> {
18
+ const user: User = {
19
+ id: randomUUID(),
20
+ email: data.email,
21
+ name: data.name,
22
+ passwordHash: data.passwordHash,
23
+ role: "user",
24
+ provider: "credentials",
25
+ isEmailVerified: false,
26
+ createdAt: new Date(),
27
+ updatedAt: new Date(),
28
+ };
29
+
30
+ users.push(user);
31
+ return user;
32
+ },
33
+ };
@@ -1,24 +1,24 @@
1
- import { Router } from "express";
2
- import {
3
- getHealth,
4
- createItem,
5
- createItemSchema,
6
- } from "../modules/health/controller.ts";
7
- import { validateRequest } from "../middlewares/validateRequest.ts";
8
- import protectedRoutes from "./protected.ts";
9
- import authRoutes from "../modules/auth/auth.routes.ts";
10
- const router = Router();
11
-
12
- // Health check
13
- router.get("/health", getHealth);
14
-
15
- // Example: Create item with validation
16
- router.post("/items", validateRequest(createItemSchema), createItem);
17
-
18
- // 🔐 Auth routes
19
- router.use("/auth", authRoutes);
20
-
21
- // 🔐 Protected routes (REQUIRED BEARER TOKEN FOR THEM)
22
- router.use("/protected", protectedRoutes);
23
-
24
- export default router;
1
+ import { Router } from "express";
2
+ import {
3
+ getHealth,
4
+ createItem,
5
+ createItemSchema,
6
+ } from "../modules/health/controller.ts";
7
+ import { validateRequest } from "../middlewares/validateRequest.ts";
8
+ import protectedRoutes from "./protected.ts";
9
+ import authRoutes from "../modules/auth/auth.routes.ts";
10
+ const router = Router();
11
+
12
+ // Health check
13
+ router.get("/health", getHealth);
14
+
15
+ // Example: Create item with validation
16
+ router.post("/items", validateRequest(createItemSchema), createItem);
17
+
18
+ // 🔐 Auth routes
19
+ router.use("/auth", authRoutes);
20
+
21
+ // 🔐 Protected routes (REQUIRED BEARER TOKEN FOR THEM)
22
+ router.use("/protected", protectedRoutes);
23
+
24
+ export default router;
@@ -1,46 +1,46 @@
1
- import { Router } from "express";
2
- import { requireAuth } from "../modules/auth/auth.middlewares.ts";
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
- */
39
- router.get("/me", requireAuth, (req, res) => {
40
- res.json({
41
- message: "You are authenticated",
42
- user: req.user,
43
- });
44
- });
45
-
46
- export default router;
1
+ import { Router } from "express";
2
+ import { requireAuth } from "../modules/auth/auth.middlewares.ts";
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
+ */
39
+ router.get("/me", requireAuth, (req, res) => {
40
+ res.json({
41
+ message: "You are authenticated",
42
+ user: req.user,
43
+ });
44
+ });
45
+
46
+ export default router;
@@ -1,41 +1,41 @@
1
- import "dotenv/config";
2
- import { app } from "./app.ts";
3
- import { env } from "./config/env.ts";
4
- import { logger } from "./utils/logger.ts";
5
-
6
- const PORT = env.PORT;
7
-
8
- const server = app.listen(PORT, () => {
9
- logger.info(`🔥 Server running in ${env.NODE_ENV} mode`, {
10
- url: `http://localhost:${PORT}`,
11
- port: PORT,
12
- });
13
- });
14
-
15
- const gracefulShutdown = (signal: string): void => {
16
- logger.warn(`${signal} signal received: closing HTTP server`);
17
-
18
- server.close(() => {
19
- logger.info("HTTP server closed");
20
- process.exit(0);
21
- });
22
- };
23
-
24
- process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
25
- process.on("SIGINT", () => gracefulShutdown("SIGINT"));
26
-
27
- process.on(
28
- "unhandledRejection",
29
- (reason: unknown, promise: Promise<unknown>) => {
30
- logger.error("Unhandled Rejection at:", { promise, reason });
31
- process.exit(1);
32
- },
33
- );
34
-
35
- process.on("uncaughtException", (error: Error) => {
36
- logger.error("Uncaught Exception:", {
37
- message: error.message,
38
- stack: error.stack,
39
- });
40
- process.exit(1);
41
- });
1
+ import "dotenv/config";
2
+ import { app } from "./app.ts";
3
+ import { env } from "./config/env.ts";
4
+ import { logger } from "./utils/logger.ts";
5
+
6
+ const PORT = env.PORT;
7
+
8
+ const server = app.listen(PORT, () => {
9
+ logger.info(`🔥 Server running in ${env.NODE_ENV} mode`, {
10
+ url: `http://localhost:${PORT}`,
11
+ port: PORT,
12
+ });
13
+ });
14
+
15
+ const gracefulShutdown = (signal: string): void => {
16
+ logger.warn(`${signal} signal received: closing HTTP server`);
17
+
18
+ server.close(() => {
19
+ logger.info("HTTP server closed");
20
+ process.exit(0);
21
+ });
22
+ };
23
+
24
+ process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
25
+ process.on("SIGINT", () => gracefulShutdown("SIGINT"));
26
+
27
+ process.on(
28
+ "unhandledRejection",
29
+ (reason: unknown, promise: Promise<unknown>) => {
30
+ logger.error("Unhandled Rejection at:", { promise, reason });
31
+ process.exit(1);
32
+ },
33
+ );
34
+
35
+ process.on("uncaughtException", (error: Error) => {
36
+ logger.error("Uncaught Exception:", {
37
+ message: error.message,
38
+ stack: error.stack,
39
+ });
40
+ process.exit(1);
41
+ });
@@ -1,9 +1,9 @@
1
- import { Request } from "express";
2
-
3
- declare global {
4
- namespace Express {
5
- interface Request {
6
- validatedData?: Record<string, any>;
7
- }
8
- }
9
- }
1
+ import { Request } from "express";
2
+
3
+ declare global {
4
+ namespace Express {
5
+ interface Request {
6
+ validatedData?: Record<string, any>;
7
+ }
8
+ }
9
+ }