create-coreback 1.0.3 → 1.0.5

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 (186) hide show
  1. package/.github/workflows/publish.yml +13 -10
  2. package/README.md +30 -1
  3. package/dist/generators/docker.d.ts.map +1 -1
  4. package/dist/generators/docker.js +61 -4
  5. package/dist/generators/docker.js.map +1 -1
  6. package/dist/generators/envExample.d.ts.map +1 -1
  7. package/dist/generators/envExample.js +26 -0
  8. package/dist/generators/envExample.js.map +1 -1
  9. package/dist/generators/eslint.d.ts.map +1 -1
  10. package/dist/generators/eslint.js +25 -27
  11. package/dist/generators/eslint.js.map +1 -1
  12. package/dist/generators/index.js +1 -1
  13. package/dist/generators/index.js.map +1 -1
  14. package/dist/generators/packageJson.d.ts.map +1 -1
  15. package/dist/generators/packageJson.js +41 -5
  16. package/dist/generators/packageJson.js.map +1 -1
  17. package/dist/generators/sourceFiles/controllers/index.d.ts +3 -0
  18. package/dist/generators/sourceFiles/controllers/index.d.ts.map +1 -0
  19. package/dist/generators/sourceFiles/controllers/index.js +147 -0
  20. package/dist/generators/sourceFiles/controllers/index.js.map +1 -0
  21. package/dist/generators/sourceFiles/core/configFiles.d.ts +3 -0
  22. package/dist/generators/sourceFiles/core/configFiles.d.ts.map +1 -0
  23. package/dist/generators/sourceFiles/core/configFiles.js +148 -0
  24. package/dist/generators/sourceFiles/core/configFiles.js.map +1 -0
  25. package/dist/generators/sourceFiles/core/index.d.ts +3 -0
  26. package/dist/generators/sourceFiles/core/index.d.ts.map +1 -0
  27. package/dist/generators/sourceFiles/core/index.js +17 -0
  28. package/dist/generators/sourceFiles/core/index.js.map +1 -0
  29. package/dist/generators/sourceFiles/core/indexFile.d.ts +3 -0
  30. package/dist/generators/sourceFiles/core/indexFile.d.ts.map +1 -0
  31. package/dist/generators/sourceFiles/core/indexFile.js +47 -0
  32. package/dist/generators/sourceFiles/core/indexFile.js.map +1 -0
  33. package/dist/generators/sourceFiles/core/middlewares.d.ts +3 -0
  34. package/dist/generators/sourceFiles/core/middlewares.d.ts.map +1 -0
  35. package/dist/generators/sourceFiles/core/middlewares.js +123 -0
  36. package/dist/generators/sourceFiles/core/middlewares.js.map +1 -0
  37. package/dist/generators/sourceFiles/core/routes.d.ts +3 -0
  38. package/dist/generators/sourceFiles/core/routes.d.ts.map +1 -0
  39. package/dist/generators/sourceFiles/core/routes.js +281 -0
  40. package/dist/generators/sourceFiles/core/routes.js.map +1 -0
  41. package/dist/generators/sourceFiles/core/tests.d.ts +3 -0
  42. package/dist/generators/sourceFiles/core/tests.d.ts.map +1 -0
  43. package/dist/generators/sourceFiles/core/tests.js +48 -0
  44. package/dist/generators/sourceFiles/core/tests.js.map +1 -0
  45. package/dist/generators/sourceFiles/core/types.d.ts +2 -0
  46. package/dist/generators/sourceFiles/core/types.d.ts.map +1 -0
  47. package/dist/generators/sourceFiles/core/types.js +13 -0
  48. package/dist/generators/sourceFiles/core/types.js.map +1 -0
  49. package/dist/generators/sourceFiles/core/utils.d.ts +2 -0
  50. package/dist/generators/sourceFiles/core/utils.d.ts.map +1 -0
  51. package/dist/generators/sourceFiles/core/utils.js +173 -0
  52. package/dist/generators/sourceFiles/core/utils.js.map +1 -0
  53. package/dist/generators/sourceFiles/core/validators.d.ts +3 -0
  54. package/dist/generators/sourceFiles/core/validators.d.ts.map +1 -0
  55. package/dist/generators/sourceFiles/core/validators.js +37 -0
  56. package/dist/generators/sourceFiles/core/validators.js.map +1 -0
  57. package/dist/generators/sourceFiles/features/fileUpload.d.ts +3 -0
  58. package/dist/generators/sourceFiles/features/fileUpload.d.ts.map +1 -0
  59. package/dist/generators/sourceFiles/features/fileUpload.js +229 -0
  60. package/dist/generators/sourceFiles/features/fileUpload.js.map +1 -0
  61. package/dist/generators/sourceFiles/features/queue.d.ts +3 -0
  62. package/dist/generators/sourceFiles/features/queue.d.ts.map +1 -0
  63. package/dist/generators/sourceFiles/features/queue.js +211 -0
  64. package/dist/generators/sourceFiles/features/queue.js.map +1 -0
  65. package/dist/generators/sourceFiles/features/redis.d.ts +3 -0
  66. package/dist/generators/sourceFiles/features/redis.d.ts.map +1 -0
  67. package/dist/generators/sourceFiles/features/redis.js +68 -0
  68. package/dist/generators/sourceFiles/features/redis.js.map +1 -0
  69. package/dist/generators/sourceFiles/index.d.ts +3 -0
  70. package/dist/generators/sourceFiles/index.d.ts.map +1 -0
  71. package/dist/generators/sourceFiles/index.js +99 -0
  72. package/dist/generators/sourceFiles/index.js.map +1 -0
  73. package/dist/generators/sourceFiles/phase1/cliGenerators.d.ts +2 -0
  74. package/dist/generators/sourceFiles/phase1/cliGenerators.d.ts.map +1 -0
  75. package/dist/generators/sourceFiles/phase1/cliGenerators.js +336 -0
  76. package/dist/generators/sourceFiles/phase1/cliGenerators.js.map +1 -0
  77. package/dist/generators/sourceFiles/phase1/seedersFactories.d.ts +3 -0
  78. package/dist/generators/sourceFiles/phase1/seedersFactories.d.ts.map +1 -0
  79. package/dist/generators/sourceFiles/phase1/seedersFactories.js +89 -0
  80. package/dist/generators/sourceFiles/phase1/seedersFactories.js.map +1 -0
  81. package/dist/generators/sourceFiles/phase2/dtos.d.ts +2 -0
  82. package/dist/generators/sourceFiles/phase2/dtos.d.ts.map +1 -0
  83. package/dist/generators/sourceFiles/phase2/dtos.js +59 -0
  84. package/dist/generators/sourceFiles/phase2/dtos.js.map +1 -0
  85. package/dist/generators/sourceFiles/phase2/events.d.ts +2 -0
  86. package/dist/generators/sourceFiles/phase2/events.d.ts.map +1 -0
  87. package/dist/generators/sourceFiles/phase2/events.js +76 -0
  88. package/dist/generators/sourceFiles/phase2/events.js.map +1 -0
  89. package/dist/generators/sourceFiles/phase2/exceptionHandling.d.ts +2 -0
  90. package/dist/generators/sourceFiles/phase2/exceptionHandling.d.ts.map +1 -0
  91. package/dist/generators/sourceFiles/phase2/exceptionHandling.js +107 -0
  92. package/dist/generators/sourceFiles/phase2/exceptionHandling.js.map +1 -0
  93. package/dist/generators/sourceFiles/phase2/guards.d.ts +2 -0
  94. package/dist/generators/sourceFiles/phase2/guards.d.ts.map +1 -0
  95. package/dist/generators/sourceFiles/phase2/guards.js +98 -0
  96. package/dist/generators/sourceFiles/phase2/guards.js.map +1 -0
  97. package/dist/generators/sourceFiles/phase2/healthChecks.d.ts +3 -0
  98. package/dist/generators/sourceFiles/phase2/healthChecks.d.ts.map +1 -0
  99. package/dist/generators/sourceFiles/phase2/healthChecks.js +73 -0
  100. package/dist/generators/sourceFiles/phase2/healthChecks.js.map +1 -0
  101. package/dist/generators/sourceFiles/phase2/scheduledTasks.d.ts +2 -0
  102. package/dist/generators/sourceFiles/phase2/scheduledTasks.d.ts.map +1 -0
  103. package/dist/generators/sourceFiles/phase2/scheduledTasks.js +56 -0
  104. package/dist/generators/sourceFiles/phase2/scheduledTasks.js.map +1 -0
  105. package/dist/generators/sourceFiles/phase3/apiVersioning.d.ts +3 -0
  106. package/dist/generators/sourceFiles/phase3/apiVersioning.d.ts.map +1 -0
  107. package/dist/generators/sourceFiles/phase3/apiVersioning.js +72 -0
  108. package/dist/generators/sourceFiles/phase3/apiVersioning.js.map +1 -0
  109. package/dist/generators/sourceFiles/phase3/cliCommands.d.ts +2 -0
  110. package/dist/generators/sourceFiles/phase3/cliCommands.d.ts.map +1 -0
  111. package/dist/generators/sourceFiles/phase3/cliCommands.js +102 -0
  112. package/dist/generators/sourceFiles/phase3/cliCommands.js.map +1 -0
  113. package/dist/generators/sourceFiles/phase3/configSystem.d.ts +2 -0
  114. package/dist/generators/sourceFiles/phase3/configSystem.d.ts.map +1 -0
  115. package/dist/generators/sourceFiles/phase3/configSystem.js +57 -0
  116. package/dist/generators/sourceFiles/phase3/configSystem.js.map +1 -0
  117. package/dist/generators/sourceFiles/phase3/dependencyInjection.d.ts +2 -0
  118. package/dist/generators/sourceFiles/phase3/dependencyInjection.d.ts.map +1 -0
  119. package/dist/generators/sourceFiles/phase3/dependencyInjection.js +153 -0
  120. package/dist/generators/sourceFiles/phase3/dependencyInjection.js.map +1 -0
  121. package/dist/generators/sourceFiles/phase3/moduleSystem.d.ts +2 -0
  122. package/dist/generators/sourceFiles/phase3/moduleSystem.d.ts.map +1 -0
  123. package/dist/generators/sourceFiles/phase3/moduleSystem.js +166 -0
  124. package/dist/generators/sourceFiles/phase3/moduleSystem.js.map +1 -0
  125. package/dist/generators/sourceFiles/phase3/structuredLogging.d.ts +3 -0
  126. package/dist/generators/sourceFiles/phase3/structuredLogging.d.ts.map +1 -0
  127. package/dist/generators/sourceFiles/phase3/structuredLogging.js +155 -0
  128. package/dist/generators/sourceFiles/phase3/structuredLogging.js.map +1 -0
  129. package/dist/generators/sourceFiles/repositories/index.d.ts +3 -0
  130. package/dist/generators/sourceFiles/repositories/index.d.ts.map +1 -0
  131. package/dist/generators/sourceFiles/repositories/index.js +109 -0
  132. package/dist/generators/sourceFiles/repositories/index.js.map +1 -0
  133. package/dist/generators/sourceFiles/services/index.d.ts +3 -0
  134. package/dist/generators/sourceFiles/services/index.d.ts.map +1 -0
  135. package/dist/generators/sourceFiles/services/index.js +353 -0
  136. package/dist/generators/sourceFiles/services/index.js.map +1 -0
  137. package/dist/generators/sourceFiles.d.ts +1 -2
  138. package/dist/generators/sourceFiles.d.ts.map +1 -1
  139. package/dist/generators/sourceFiles.js +2 -1238
  140. package/dist/generators/sourceFiles.js.map +1 -1
  141. package/dist/prompts.d.ts.map +1 -1
  142. package/dist/prompts.js +35 -0
  143. package/dist/prompts.js.map +1 -1
  144. package/dist/types.d.ts +5 -0
  145. package/dist/types.d.ts.map +1 -1
  146. package/jest.config.js +21 -0
  147. package/package.json +4 -1
  148. package/src/generators/docker.ts +61 -4
  149. package/src/generators/envExample.ts +28 -0
  150. package/src/generators/eslint.ts +21 -24
  151. package/src/generators/index.ts +1 -1
  152. package/src/generators/packageJson.ts +45 -6
  153. package/src/generators/sourceFiles/controllers/index.ts +157 -0
  154. package/src/generators/sourceFiles/core/configFiles.ts +158 -0
  155. package/src/generators/sourceFiles/core/index.ts +28 -0
  156. package/src/generators/sourceFiles/core/indexFile.ts +49 -0
  157. package/src/generators/sourceFiles/core/middlewares.ts +129 -0
  158. package/src/generators/sourceFiles/core/routes.ts +295 -0
  159. package/src/generators/sourceFiles/core/tests.ts +62 -0
  160. package/src/generators/sourceFiles/core/types.ts +14 -0
  161. package/src/generators/sourceFiles/core/utils.ts +178 -0
  162. package/src/generators/sourceFiles/core/validators.ts +39 -0
  163. package/src/generators/sourceFiles/features/fileUpload.ts +241 -0
  164. package/src/generators/sourceFiles/features/queue.ts +226 -0
  165. package/src/generators/sourceFiles/features/redis.ts +73 -0
  166. package/src/generators/sourceFiles/index.ts +125 -0
  167. package/src/generators/sourceFiles/phase1/cliGenerators.ts +338 -0
  168. package/src/generators/sourceFiles/phase1/seedersFactories.ts +97 -0
  169. package/src/generators/sourceFiles/phase2/dtos.ts +60 -0
  170. package/src/generators/sourceFiles/phase2/events.ts +80 -0
  171. package/src/generators/sourceFiles/phase2/exceptionHandling.ts +111 -0
  172. package/src/generators/sourceFiles/phase2/guards.ts +99 -0
  173. package/src/generators/sourceFiles/phase2/healthChecks.ts +81 -0
  174. package/src/generators/sourceFiles/phase2/scheduledTasks.ts +58 -0
  175. package/src/generators/sourceFiles/phase3/apiVersioning.ts +77 -0
  176. package/src/generators/sourceFiles/phase3/cliCommands.ts +110 -0
  177. package/src/generators/sourceFiles/phase3/configSystem.ts +64 -0
  178. package/src/generators/sourceFiles/phase3/dependencyInjection.ts +155 -0
  179. package/src/generators/sourceFiles/phase3/moduleSystem.ts +170 -0
  180. package/src/generators/sourceFiles/phase3/structuredLogging.ts +160 -0
  181. package/src/generators/sourceFiles/repositories/index.ts +114 -0
  182. package/src/generators/sourceFiles/services/index.ts +363 -0
  183. package/src/generators/sourceFiles.ts +2 -1317
  184. package/src/prompts.ts +36 -1
  185. package/src/types.ts +5 -0
  186. package/tests/integration.test.ts +233 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tests.d.ts","sourceRoot":"","sources":["../../../../src/generators/sourceFiles/core/tests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIlD,wBAAsB,aAAa,CACjC,YAAY,EAAE,MAAM,EACpB,mBAAmB,EAAE,MAAM,EAC3B,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAqDf"}
@@ -0,0 +1,48 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ export async function generateTests(unitTestsDir, integrationTestsDir, config) {
4
+ // Unit test example
5
+ const unitTestContent = `import { healthController } from '../../src/controllers/health.controller.js';
6
+
7
+ describe('Health Controller', () => {
8
+ it('should return ok status', () => {
9
+ const mockReq = {} as any;
10
+ const mockRes = {
11
+ json: jest.fn(),
12
+ } as any;
13
+
14
+ healthController.check(mockReq, mockRes);
15
+
16
+ expect(mockRes.json).toHaveBeenCalledWith({
17
+ status: 'ok',
18
+ timestamp: expect.any(String),
19
+ });
20
+ });
21
+ });
22
+ `;
23
+ await fs.writeFile(path.join(unitTestsDir, 'health.controller.test.ts'), unitTestContent);
24
+ // Integration test example
25
+ const integrationTestContent = `import request from 'supertest';
26
+ import express from 'express';
27
+ import { setupRoutes } from '../../src/routes/index.js';
28
+ import { setupMiddlewares } from '../../src/config/middlewares.js';
29
+ import { errorHandler } from '../../src/middlewares/errorHandler.js';
30
+
31
+ const app = express();
32
+ setupMiddlewares(app);
33
+ setupRoutes(app);
34
+ app.use(errorHandler);
35
+
36
+ describe('Health API', () => {
37
+ it('GET /api/health should return 200', async () => {
38
+ const response = await request(app).get('/api/health');
39
+
40
+ expect(response.status).toBe(200);
41
+ expect(response.body).toHaveProperty('status', 'ok');
42
+ expect(response.body).toHaveProperty('timestamp');
43
+ });
44
+ });
45
+ `;
46
+ await fs.writeFile(path.join(integrationTestsDir, 'health.api.test.ts'), integrationTestContent);
47
+ }
48
+ //# sourceMappingURL=tests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tests.js","sourceRoot":"","sources":["../../../../src/generators/sourceFiles/core/tests.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,YAAoB,EACpB,mBAA2B,EAC3B,MAAqB;IAErB,oBAAoB;IACpB,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;CAiBzB,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,2BAA2B,CAAC,EACpD,eAAe,CAChB,CAAC;IAEF,2BAA2B;IAC3B,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;CAoBhC,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,oBAAoB,CAAC,EACpD,sBAAsB,CACvB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function generateTypes(typesDir: string): Promise<void>;
2
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/generators/sourceFiles/core/types.ts"],"names":[],"mappings":"AAGA,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnE"}
@@ -0,0 +1,13 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ export async function generateTypes(typesDir) {
4
+ const indexContent = `export interface ApiResponse<T = unknown> {
5
+ status: 'success' | 'error';
6
+ data?: T;
7
+ message?: string;
8
+ errors?: unknown[];
9
+ }
10
+ `;
11
+ await fs.writeFile(path.join(typesDir, 'index.ts'), indexContent);
12
+ }
13
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/generators/sourceFiles/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,MAAM,YAAY,GAAG;;;;;;CAMtB,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function generateUtils(utilsDir: string): Promise<void>;
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/generators/sourceFiles/core/utils.ts"],"names":[],"mappings":"AAGA,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8KnE"}
@@ -0,0 +1,173 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ export async function generateUtils(utilsDir) {
4
+ // Logger will be generated by generateStructuredLogging in Phase 3
5
+ // Generate a basic logger placeholder that will be replaced
6
+ const loggerContent = `import winston from 'winston';
7
+ import { config } from '../config/env.js';
8
+ import fs from 'fs-extra';
9
+ import path from 'path';
10
+
11
+ // Ensure logs directory exists
12
+ const logsDir = path.join(process.cwd(), 'logs');
13
+ fs.ensureDirSync(logsDir);
14
+
15
+ const logFormat = winston.format.combine(
16
+ winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
17
+ winston.format.errors({ stack: true }),
18
+ winston.format.splat(),
19
+ winston.format.json()
20
+ );
21
+
22
+ export const logger = winston.createLogger({
23
+ level: config.NODE_ENV === 'production' ? 'info' : 'debug',
24
+ format: logFormat,
25
+ defaultMeta: { service: 'coreback-api' },
26
+ transports: [
27
+ new winston.transports.File({ filename: path.join(logsDir, 'error.log'), level: 'error' }),
28
+ new winston.transports.File({ filename: path.join(logsDir, 'combined.log') }),
29
+ ],
30
+ });
31
+
32
+ if (config.NODE_ENV !== 'production') {
33
+ logger.add(
34
+ new winston.transports.Console({
35
+ format: winston.format.combine(
36
+ winston.format.colorize(),
37
+ winston.format.simple()
38
+ ),
39
+ })
40
+ );
41
+ }
42
+ `;
43
+ await fs.writeFile(path.join(utilsDir, 'logger.ts'), loggerContent);
44
+ // pagination.ts
45
+ const paginationContent = `export interface PaginationOptions {
46
+ page?: number;
47
+ limit?: number;
48
+ }
49
+
50
+ export interface PaginationMeta {
51
+ page: number;
52
+ limit: number;
53
+ total: number;
54
+ totalPages: number;
55
+ hasNext: boolean;
56
+ hasPrev: boolean;
57
+ }
58
+
59
+ export interface PaginatedResponse<T> {
60
+ data: T[];
61
+ meta: PaginationMeta;
62
+ }
63
+
64
+ export function paginate<T>(
65
+ data: T[],
66
+ page: number = 1,
67
+ limit: number = 10
68
+ ): PaginatedResponse<T> {
69
+ const total = data.length;
70
+ const totalPages = Math.ceil(total / limit);
71
+ const startIndex = (page - 1) * limit;
72
+ const endIndex = startIndex + limit;
73
+ const paginatedData = data.slice(startIndex, endIndex);
74
+
75
+ return {
76
+ data: paginatedData,
77
+ meta: {
78
+ page,
79
+ limit,
80
+ total,
81
+ totalPages,
82
+ hasNext: page < totalPages,
83
+ hasPrev: page > 1,
84
+ },
85
+ };
86
+ }
87
+
88
+ export async function paginateQuery<T>(
89
+ queryFn: (skip: number, take: number) => Promise<{ data: T[]; total: number }>,
90
+ page: number = 1,
91
+ limit: number = 10
92
+ ): Promise<PaginatedResponse<T>> {
93
+ const skip = (page - 1) * limit;
94
+ const { data, total } = await queryFn(skip, limit);
95
+ const totalPages = Math.ceil(total / limit);
96
+
97
+ return {
98
+ data,
99
+ meta: {
100
+ page,
101
+ limit,
102
+ total,
103
+ totalPages,
104
+ hasNext: page < totalPages,
105
+ hasPrev: page > 1,
106
+ },
107
+ };
108
+ }
109
+ `;
110
+ await fs.writeFile(path.join(utilsDir, 'pagination.ts'), paginationContent);
111
+ // resource.ts
112
+ const resourceContent = `export interface ResourceTransformer<T, R = T> {
113
+ (data: T): R;
114
+ }
115
+
116
+ export class Resource<T, R = T> {
117
+ constructor(
118
+ private data: T | T[],
119
+ private transformer?: ResourceTransformer<T, R>
120
+ ) {}
121
+
122
+ static make<T, R = T>(
123
+ data: T | T[],
124
+ transformer?: ResourceTransformer<T, R>
125
+ ): Resource<T, R> {
126
+ return new Resource(data, transformer);
127
+ }
128
+
129
+ toJSON(): R | R[] {
130
+ if (Array.isArray(this.data)) {
131
+ return this.data.map((item) =>
132
+ this.transformer ? this.transformer(item) : (item as unknown as R)
133
+ );
134
+ }
135
+ return this.transformer
136
+ ? this.transformer(this.data)
137
+ : (this.data as unknown as R);
138
+ }
139
+
140
+ static collection<T, R = T>(
141
+ data: T[],
142
+ transformer?: ResourceTransformer<T, R>
143
+ ): R[] {
144
+ return data.map((item) =>
145
+ transformer ? transformer(item) : (item as unknown as R)
146
+ );
147
+ }
148
+
149
+ static single<T, R = T>(
150
+ data: T,
151
+ transformer?: ResourceTransformer<T, R>
152
+ ): R {
153
+ return transformer
154
+ ? transformer(data)
155
+ : (data as unknown as R);
156
+ }
157
+ }
158
+
159
+ export function transformResponse<T, R = T>(
160
+ data: T | T[],
161
+ transformer?: ResourceTransformer<T, R>
162
+ ): R | R[] {
163
+ if (Array.isArray(data)) {
164
+ return data.map((item) =>
165
+ transformer ? transformer(item) : (item as unknown as R)
166
+ );
167
+ }
168
+ return transformer ? transformer(data) : (data as unknown as R);
169
+ }
170
+ `;
171
+ await fs.writeFile(path.join(utilsDir, 'resource.ts'), resourceContent);
172
+ }
173
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/generators/sourceFiles/core/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,mEAAmE;IACnE,4DAA4D;IAC5D,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCvB,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,aAAa,CAAC,CAAC;IAEpE,gBAAgB;IAChB,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgE3B,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAE5E,cAAc;IACd,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DzB,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,eAAe,CAAC,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { ProjectConfig } from '../../../types.js';
2
+ export declare function generateValidators(validatorsDir: string, config: ProjectConfig): Promise<void>;
3
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../../src/generators/sourceFiles/core/validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIlD,wBAAsB,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCpG"}
@@ -0,0 +1,37 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ export async function generateValidators(validatorsDir, config) {
4
+ if (config.includeAuth) {
5
+ const authValidatorContent = `import { z } from 'zod';
6
+
7
+ export const registerSchema = z.object({
8
+ body: z.object({
9
+ email: z.string().email('Invalid email format'),
10
+ password: z.string().min(8, 'Password must be at least 8 characters'),
11
+ name: z.string().optional(),
12
+ }),
13
+ });
14
+
15
+ export const loginSchema = z.object({
16
+ body: z.object({
17
+ email: z.string().email('Invalid email format'),
18
+ password: z.string().min(1, 'Password is required'),
19
+ }),
20
+ });
21
+
22
+ export const emailSchema = z.object({
23
+ body: z.object({
24
+ email: z.string().email('Invalid email format'),
25
+ }),
26
+ });
27
+
28
+ export const resetPasswordSchema = z.object({
29
+ body: z.object({
30
+ password: z.string().min(8, 'Password must be at least 8 characters'),
31
+ }),
32
+ });
33
+ `;
34
+ await fs.writeFile(path.join(validatorsDir, 'auth.validator.ts'), authValidatorContent);
35
+ }
36
+ }
37
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../../../src/generators/sourceFiles/core/validators.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,aAAqB,EAAE,MAAqB;IACnF,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BhC,CAAC;QAEE,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,mBAAmB,CAAC,EAAE,oBAAoB,CAAC,CAAC;IAC1F,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { ProjectConfig } from '../../../types.js';
2
+ export declare function generateFileUpload(controllersDir: string, servicesDir: string, routesDir: string, validatorsDir: string, config: ProjectConfig): Promise<void>;
3
+ //# sourceMappingURL=fileUpload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileUpload.d.ts","sourceRoot":"","sources":["../../../../src/generators/sourceFiles/features/fileUpload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIlD,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAsOf"}
@@ -0,0 +1,229 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ export async function generateFileUpload(controllersDir, servicesDir, routesDir, validatorsDir, config) {
4
+ // File upload service
5
+ const fileUploadServiceContent = `import multer from 'multer';
6
+ import path from 'path';
7
+ import fs from 'fs-extra';
8
+ import { config as envConfig } from '../config/env.js';
9
+ ${config.fileStorage === 's3' ? `import { S3Client, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';
10
+ import multerS3 from 'multer-s3';` : ''}
11
+ import { logger } from '../utils/logger.js';
12
+
13
+ ${config.fileStorage === 's3' ? `const s3Client = new S3Client({
14
+ region: envConfig.AWS_REGION,
15
+ credentials: envConfig.AWS_ACCESS_KEY_ID && envConfig.AWS_SECRET_ACCESS_KEY ? {
16
+ accessKeyId: envConfig.AWS_ACCESS_KEY_ID,
17
+ secretAccessKey: envConfig.AWS_SECRET_ACCESS_KEY,
18
+ } : undefined,
19
+ });` : ''}
20
+
21
+ const allowedTypes = envConfig.ALLOWED_FILE_TYPES.split(',').map(t => t.trim());
22
+
23
+ ${config.fileStorage === 's3' ? `const storage = multerS3({
24
+ s3: s3Client,
25
+ bucket: envConfig.AWS_S3_BUCKET || '',
26
+ acl: 'public-read',
27
+ key: (req, file, cb) => {
28
+ const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
29
+ cb(null, \`uploads/\${uniqueSuffix}-\${file.originalname}\`);
30
+ },
31
+ });` : `const storage = multer.diskStorage({
32
+ destination: async (req, file, cb) => {
33
+ const uploadDir = path.join(process.cwd(), envConfig.UPLOAD_DIR);
34
+ await fs.ensureDir(uploadDir);
35
+ cb(null, uploadDir);
36
+ },
37
+ filename: (req, file, cb) => {
38
+ const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
39
+ cb(null, \`\${uniqueSuffix}-\${file.originalname}\`);
40
+ },
41
+ });`}
42
+
43
+ export const upload = multer({
44
+ storage,
45
+ limits: {
46
+ fileSize: envConfig.MAX_FILE_SIZE,
47
+ },
48
+ fileFilter: (req, file, cb) => {
49
+ if (allowedTypes.includes(file.mimetype)) {
50
+ cb(null, true);
51
+ } else {
52
+ cb(new Error(\`File type \${file.mimetype} not allowed. Allowed types: \${allowedTypes.join(', ')}\`));
53
+ }
54
+ },
55
+ });
56
+
57
+ export interface UploadedFile {
58
+ filename: string;
59
+ originalname: string;
60
+ mimetype: string;
61
+ size: number;
62
+ ${config.fileStorage === 's3' ? `location: string;` : `path: string;`}
63
+ }
64
+
65
+ export const fileUploadService = {
66
+ async deleteFile(filename: string): Promise<void> {
67
+ try {
68
+ ${config.fileStorage === 's3' ? `if (envConfig.AWS_S3_BUCKET) {
69
+ await s3Client.send(new DeleteObjectCommand({
70
+ Bucket: envConfig.AWS_S3_BUCKET,
71
+ Key: filename,
72
+ }));
73
+ }` : `const filePath = path.join(process.cwd(), envConfig.UPLOAD_DIR, filename);
74
+ await fs.remove(filePath);`}
75
+ logger.info(\`File deleted: \${filename}\`);
76
+ } catch (error) {
77
+ logger.error(\`Error deleting file \${filename}:\`, error);
78
+ throw error;
79
+ }
80
+ },
81
+ };
82
+ `;
83
+ await fs.writeFile(path.join(servicesDir, 'fileUpload.service.ts'), fileUploadServiceContent);
84
+ // File upload controller
85
+ const fileUploadControllerContent = `import { Request, Response } from 'express';
86
+ import { upload, UploadedFile, fileUploadService } from '../services/fileUpload.service.js';
87
+ import { AppError } from '../middlewares/errorHandler.js';
88
+
89
+ /**
90
+ * @swagger
91
+ * /api/files/upload:
92
+ * post:
93
+ * summary: Upload a file
94
+ * tags: [Files]
95
+ * security:
96
+ * - bearerAuth: []
97
+ * requestBody:
98
+ * required: true
99
+ * content:
100
+ * multipart/form-data:
101
+ * schema:
102
+ * type: object
103
+ * properties:
104
+ * file:
105
+ * type: string
106
+ * format: binary
107
+ * responses:
108
+ * 200:
109
+ * description: File uploaded successfully
110
+ * 400:
111
+ * description: Invalid file type or size
112
+ */
113
+ export const uploadFile = async (req: Request, res: Response): Promise<void> => {
114
+ if (!req.file) {
115
+ throw new AppError(400, 'No file uploaded');
116
+ }
117
+
118
+ const file = req.file as unknown as UploadedFile;
119
+
120
+ res.status(200).json({
121
+ status: 'success',
122
+ data: {
123
+ filename: file.filename,
124
+ originalname: file.originalname,
125
+ mimetype: file.mimetype,
126
+ size: file.size,
127
+ ${config.fileStorage === 's3' ? `url: file.location,` : `url: \`/api/files/\${file.filename}\`,`}
128
+ },
129
+ });
130
+ };
131
+
132
+ /**
133
+ * @swagger
134
+ * /api/files/{filename}:
135
+ * delete:
136
+ * summary: Delete a file
137
+ * tags: [Files]
138
+ * security:
139
+ * - bearerAuth: []
140
+ * parameters:
141
+ * - in: path
142
+ * name: filename
143
+ * required: true
144
+ * schema:
145
+ * type: string
146
+ * responses:
147
+ * 200:
148
+ * description: File deleted successfully
149
+ * 404:
150
+ * description: File not found
151
+ */
152
+ export const deleteFile = async (req: Request, res: Response): Promise<void> => {
153
+ const { filename } = req.params;
154
+
155
+ await fileUploadService.deleteFile(filename);
156
+
157
+ res.status(200).json({
158
+ status: 'success',
159
+ message: 'File deleted successfully',
160
+ });
161
+ };
162
+
163
+ /**
164
+ * @swagger
165
+ * /api/files/{filename}:
166
+ * get:
167
+ * summary: Get a file
168
+ * tags: [Files]
169
+ * parameters:
170
+ * - in: path
171
+ * name: filename
172
+ * required: true
173
+ * schema:
174
+ * type: string
175
+ * responses:
176
+ * 200:
177
+ * description: File retrieved successfully
178
+ * 404:
179
+ * description: File not found
180
+ */
181
+ export const getFile = async (req: Request, res: Response): Promise<void> => {
182
+ const { filename } = req.params;
183
+ ${config.fileStorage === 's3' ? `// For S3, redirect to the S3 URL
184
+ // In production, you might want to generate a signed URL
185
+ res.status(404).json({
186
+ status: 'error',
187
+ message: 'Direct file access not available for S3. Use the URL from upload response.',
188
+ });` : `const path = require('path');
189
+ const fs = require('fs-extra');
190
+ const { config } = require('../config/env.js');
191
+
192
+ const filePath = path.join(process.cwd(), config.UPLOAD_DIR, filename);
193
+
194
+ if (!(await fs.pathExists(filePath))) {
195
+ res.status(404).json({
196
+ status: 'error',
197
+ message: 'File not found',
198
+ });
199
+ return;
200
+ }
201
+
202
+ res.sendFile(filePath);`}
203
+ };
204
+ `;
205
+ await fs.writeFile(path.join(controllersDir, 'fileUpload.controller.ts'), fileUploadControllerContent);
206
+ // File upload routes
207
+ const fileUploadRoutesContent = `import { Router } from 'express';
208
+ import { uploadFile, deleteFile, getFile } from '../controllers/fileUpload.controller.js';
209
+ import { upload } from '../services/fileUpload.service.js';
210
+ ${config.includeAuth ? `import { authenticate } from '../middlewares/auth.js';` : ''}
211
+
212
+ const router = Router();
213
+
214
+ /**
215
+ * @swagger
216
+ * tags:
217
+ * name: Files
218
+ * description: File upload and management endpoints
219
+ */
220
+ ${config.includeAuth ? `router.post('/upload', authenticate, upload.single('file'), uploadFile);
221
+ router.delete('/:filename', authenticate, deleteFile);` : `router.post('/upload', upload.single('file'), uploadFile);
222
+ router.delete('/:filename', deleteFile);`}
223
+ router.get('/:filename', getFile);
224
+
225
+ export { router as fileUploadRoutes };
226
+ `;
227
+ await fs.writeFile(path.join(routesDir, 'fileUpload.routes.ts'), fileUploadRoutesContent);
228
+ }
229
+ //# sourceMappingURL=fileUpload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileUpload.js","sourceRoot":"","sources":["../../../../src/generators/sourceFiles/features/fileUpload.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,cAAsB,EACtB,WAAmB,EACnB,SAAiB,EACjB,aAAqB,EACrB,MAAqB;IAErB,sBAAsB;IACtB,MAAM,wBAAwB,GAAG;;;;EAIjC,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC;kCACE,CAAC,CAAC,CAAC,EAAE;;;EAGrC,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC;;;;;;IAM5B,CAAC,CAAC,CAAC,EAAE;;;;EAIP,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC;;;;;;;;IAQ5B,CAAC,CAAC,CAAC;;;;;;;;;;IAUH;;;;;;;;;;;;;;;;;;;;;IAqBA,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,eAAe;;;;;;QAM/D,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC;;;;;QAK9B,CAAC,CAAC,CAAC;iCACsB;;;;;;;;CAQhC,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE,wBAAwB,CAAC,CAAC;IAE9F,yBAAyB;IACzB,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA0C9B,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,wCAAwC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAwDlG,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC;;;;;MAK5B,CAAC,CAAC,CAAC;;;;;;;;;;;;;;0BAciB;;CAEzB,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,0BAA0B,CAAC,EAAE,2BAA2B,CAAC,CAAC;IAEvG,qBAAqB;IACrB,MAAM,uBAAuB,GAAG;;;EAGhC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,wDAAwD,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;EAUlF,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;uDACgC,CAAC,CAAC,CAAC;yCACjB;;;;CAIxC,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,sBAAsB,CAAC,EAAE,uBAAuB,CAAC,CAAC;AAC5F,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { ProjectConfig } from '../../../types.js';
2
+ export declare function generateQueueSystem(queueDir: string, routesDir: string, config: ProjectConfig): Promise<void>;
3
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../../src/generators/sourceFiles/features/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIlD,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAwNf"}