fragment-ts 1.0.2 → 1.0.3

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 (304) hide show
  1. package/README.md +401 -0
  2. package/USAGE.md +1439 -0
  3. package/bin/fragment.js +2 -0
  4. package/dist/ai/ai.module.d.ts +27 -0
  5. package/dist/ai/ai.module.d.ts.map +1 -0
  6. package/dist/ai/ai.module.js +77 -0
  7. package/dist/ai/ai.module.js.map +1 -0
  8. package/dist/auth/auth.module.d.ts +18 -0
  9. package/dist/auth/auth.module.d.ts.map +1 -0
  10. package/dist/auth/auth.module.js +89 -0
  11. package/dist/auth/auth.module.js.map +1 -0
  12. package/dist/cli/commands/build.command.d.ts +6 -1
  13. package/dist/cli/commands/build.command.d.ts.map +1 -0
  14. package/dist/cli/commands/build.command.js +130 -10
  15. package/dist/cli/commands/build.command.js.map +1 -1
  16. package/dist/cli/commands/diagnostics.command.d.ts +16 -0
  17. package/dist/cli/commands/diagnostics.command.d.ts.map +1 -0
  18. package/dist/cli/commands/diagnostics.command.js +419 -0
  19. package/dist/cli/commands/diagnostics.command.js.map +1 -0
  20. package/dist/cli/commands/generate.command.d.ts +13 -6
  21. package/dist/cli/commands/generate.command.d.ts.map +1 -0
  22. package/dist/cli/commands/generate.command.js +200 -128
  23. package/dist/cli/commands/generate.command.js.map +1 -1
  24. package/dist/cli/commands/init.command.d.ts +11 -5
  25. package/dist/cli/commands/init.command.d.ts.map +1 -0
  26. package/dist/cli/commands/init.command.js +267 -305
  27. package/dist/cli/commands/init.command.js.map +1 -1
  28. package/dist/cli/commands/migrate.command.d.ts +12 -5
  29. package/dist/cli/commands/migrate.command.d.ts.map +1 -0
  30. package/dist/cli/commands/migrate.command.js +211 -83
  31. package/dist/cli/commands/migrate.command.js.map +1 -1
  32. package/dist/cli/commands/serve.command.d.ts +5 -4
  33. package/dist/cli/commands/serve.command.d.ts.map +1 -0
  34. package/dist/cli/commands/serve.command.js +178 -21
  35. package/dist/cli/commands/serve.command.js.map +1 -1
  36. package/dist/cli/index.d.ts +2 -0
  37. package/dist/cli/index.d.ts.map +1 -0
  38. package/dist/cli/index.js +22 -0
  39. package/dist/cli/index.js.map +1 -0
  40. package/dist/core/container/di-container.d.ts +13 -7
  41. package/dist/core/container/di-container.d.ts.map +1 -0
  42. package/dist/core/container/di-container.js +75 -25
  43. package/dist/core/container/di-container.js.map +1 -1
  44. package/dist/core/decorators/application.decorator.d.ts +8 -0
  45. package/dist/core/decorators/application.decorator.d.ts.map +1 -0
  46. package/dist/core/decorators/application.decorator.js +16 -0
  47. package/dist/core/decorators/application.decorator.js.map +1 -0
  48. package/dist/core/decorators/auto-configuration.decorator.d.ts +2 -0
  49. package/dist/core/decorators/auto-configuration.decorator.d.ts.map +1 -0
  50. package/dist/core/decorators/auto-configuration.decorator.js +19 -0
  51. package/dist/core/decorators/auto-configuration.decorator.js.map +1 -0
  52. package/dist/core/decorators/conditional.decorators.d.ts +4 -0
  53. package/dist/core/decorators/conditional.decorators.d.ts.map +1 -0
  54. package/dist/core/decorators/conditional.decorators.js +22 -0
  55. package/dist/core/decorators/conditional.decorators.js.map +1 -0
  56. package/dist/core/decorators/controller.decorator.d.ts +1 -3
  57. package/dist/core/decorators/controller.decorator.d.ts.map +1 -0
  58. package/dist/core/decorators/controller.decorator.js +12 -9
  59. package/dist/core/decorators/controller.decorator.js.map +1 -1
  60. package/dist/core/decorators/http.decorators.d.ts +12 -0
  61. package/dist/core/decorators/http.decorators.d.ts.map +1 -0
  62. package/dist/core/decorators/http.decorators.js +52 -0
  63. package/dist/core/decorators/http.decorators.js.map +1 -0
  64. package/dist/core/decorators/injectable.decorator.d.ts +3 -3
  65. package/dist/core/decorators/injectable.decorator.d.ts.map +1 -0
  66. package/dist/core/decorators/injectable.decorator.js +11 -8
  67. package/dist/core/decorators/injectable.decorator.js.map +1 -1
  68. package/dist/core/decorators/injection.decorators.d.ts +5 -0
  69. package/dist/core/decorators/injection.decorators.d.ts.map +1 -0
  70. package/dist/core/decorators/injection.decorators.js +29 -0
  71. package/dist/core/decorators/injection.decorators.js.map +1 -0
  72. package/dist/core/decorators/repository.decorator.d.ts +1 -0
  73. package/dist/core/decorators/repository.decorator.d.ts.map +1 -0
  74. package/dist/core/decorators/repository.decorator.js +12 -1
  75. package/dist/core/decorators/repository.decorator.js.map +1 -1
  76. package/dist/core/decorators/service.decorator.d.ts +1 -0
  77. package/dist/core/decorators/service.decorator.d.ts.map +1 -0
  78. package/dist/core/decorators/service.decorator.js +12 -1
  79. package/dist/core/decorators/service.decorator.js.map +1 -1
  80. package/dist/core/index.d.ts +13 -0
  81. package/dist/core/index.d.ts.map +1 -0
  82. package/dist/core/index.js +29 -0
  83. package/dist/core/index.js.map +1 -0
  84. package/dist/core/loader/file-loader.d.ts +5 -0
  85. package/dist/core/loader/file-loader.d.ts.map +1 -0
  86. package/dist/core/loader/file-loader.js +85 -0
  87. package/dist/core/loader/file-loader.js.map +1 -0
  88. package/dist/core/metadata/metadata-keys.d.ts +20 -0
  89. package/dist/core/metadata/metadata-keys.d.ts.map +1 -0
  90. package/dist/core/metadata/metadata-keys.js +23 -0
  91. package/dist/core/metadata/metadata-keys.js.map +1 -0
  92. package/dist/core/metadata/metadata-storage.d.ts +36 -0
  93. package/dist/core/metadata/metadata-storage.d.ts.map +1 -0
  94. package/dist/core/metadata/metadata-storage.js +53 -0
  95. package/dist/core/metadata/metadata-storage.js.map +1 -0
  96. package/dist/core/scanner/component-scanner.d.ts +16 -0
  97. package/dist/core/scanner/component-scanner.d.ts.map +1 -0
  98. package/dist/core/scanner/component-scanner.js +147 -0
  99. package/dist/core/scanner/component-scanner.js.map +1 -0
  100. package/dist/index.d.ts +22 -0
  101. package/dist/index.d.ts.map +1 -0
  102. package/dist/index.js +60 -0
  103. package/dist/index.js.map +1 -0
  104. package/dist/plugins/plugin-manager.d.ts +14 -0
  105. package/dist/plugins/plugin-manager.d.ts.map +1 -0
  106. package/dist/{cli/utils/file-generator.js → plugins/plugin-manager.js} +32 -24
  107. package/dist/plugins/plugin-manager.js.map +1 -0
  108. package/dist/shared/errors.d.ts +18 -0
  109. package/dist/shared/errors.d.ts.map +1 -0
  110. package/dist/shared/errors.js +41 -0
  111. package/dist/shared/errors.js.map +1 -0
  112. package/dist/testing/runner.d.ts +26 -0
  113. package/dist/testing/runner.d.ts.map +1 -0
  114. package/dist/testing/runner.js +143 -0
  115. package/dist/testing/runner.js.map +1 -0
  116. package/dist/typeorm/typeorm-module.d.ts +36 -0
  117. package/dist/typeorm/typeorm-module.d.ts.map +1 -0
  118. package/dist/typeorm/typeorm-module.js +150 -0
  119. package/dist/typeorm/typeorm-module.js.map +1 -0
  120. package/dist/web/application.d.ts +29 -0
  121. package/dist/web/application.d.ts.map +1 -0
  122. package/dist/web/application.js +301 -0
  123. package/dist/web/application.js.map +1 -0
  124. package/dist/web/interfaces.d.ts +14 -0
  125. package/dist/web/interfaces.d.ts.map +1 -0
  126. package/dist/{auth/dto/login.dto.js → web/interfaces.js} +1 -1
  127. package/dist/web/interfaces.js.map +1 -0
  128. package/examples/blog-api/fragment.json +14 -0
  129. package/examples/blog-api/package-lock.json +3405 -0
  130. package/examples/blog-api/package.json +19 -0
  131. package/examples/blog-api/src/controllers/app.controller.ts +9 -0
  132. package/examples/blog-api/src/controllers/auth.controller.ts +17 -0
  133. package/examples/blog-api/src/controllers/category.controller.ts +29 -0
  134. package/examples/blog-api/src/controllers/comment.controller.ts +31 -0
  135. package/examples/blog-api/src/controllers/post.controller.ts +46 -0
  136. package/examples/blog-api/src/dto/create-category.dto.ts +6 -0
  137. package/examples/blog-api/src/dto/create-comment.dto.ts +6 -0
  138. package/examples/blog-api/src/dto/create-post.dto.ts +6 -0
  139. package/examples/blog-api/src/entities/category.entity.ts +16 -0
  140. package/examples/blog-api/src/entities/comment.entity.ts +29 -0
  141. package/examples/blog-api/src/entities/post.entity.ts +42 -0
  142. package/examples/blog-api/src/entities/user.entity.ts +25 -0
  143. package/examples/blog-api/src/main.ts +16 -0
  144. package/examples/blog-api/src/migrations/1767737463842-InitialSchema.ts +60 -0
  145. package/examples/blog-api/src/repositories/category.repository.ts +25 -0
  146. package/examples/blog-api/src/repositories/comment.repository.ts +25 -0
  147. package/examples/blog-api/src/repositories/post.repository.ts +29 -0
  148. package/examples/blog-api/src/seeds/SampleData.seed.ts +41 -0
  149. package/examples/blog-api/src/services/app.service.ts +8 -0
  150. package/examples/blog-api/src/services/auth.service.ts +15 -0
  151. package/examples/blog-api/src/services/category.service.ts +27 -0
  152. package/examples/blog-api/src/services/comment.service.ts +31 -0
  153. package/examples/blog-api/src/services/post.service.ts +35 -0
  154. package/examples/blog-api/tsconfig.json +23 -0
  155. package/package.json +55 -33
  156. package/src/ai/ai.module.ts +110 -0
  157. package/src/auth/auth.module.ts +77 -0
  158. package/src/cli/commands/build.command.ts +123 -13
  159. package/src/cli/commands/diagnostics.command.ts +438 -0
  160. package/src/cli/commands/generate.command.ts +206 -137
  161. package/src/cli/commands/init.command.ts +337 -349
  162. package/src/cli/commands/migrate.command.ts +203 -88
  163. package/src/cli/commands/serve.command.ts +176 -24
  164. package/src/cli/index.ts +23 -0
  165. package/src/core/container/di-container.ts +83 -26
  166. package/src/core/decorators/application.decorator.ts +26 -0
  167. package/src/core/decorators/auto-configuration.decorator.ts +17 -0
  168. package/src/core/decorators/conditional.decorators.ts +19 -0
  169. package/src/core/decorators/controller.decorator.ts +14 -11
  170. package/src/core/decorators/http.decorators.ts +71 -0
  171. package/src/core/decorators/injectable.decorator.ts +14 -9
  172. package/src/core/decorators/injection.decorators.ts +26 -0
  173. package/src/core/decorators/repository.decorator.ts +13 -2
  174. package/src/core/decorators/service.decorator.ts +13 -2
  175. package/src/core/index.ts +13 -0
  176. package/src/core/loader/file-loader.ts +55 -0
  177. package/src/core/metadata/metadata-keys.ts +19 -0
  178. package/src/core/metadata/metadata-storage.ts +91 -0
  179. package/src/core/scanner/component-scanner.ts +129 -0
  180. package/src/index.ts +45 -0
  181. package/src/plugins/plugin-manager.ts +52 -0
  182. package/src/shared/errors.ts +34 -0
  183. package/src/testing/runner.ts +143 -0
  184. package/src/typeorm/typeorm-module.ts +216 -0
  185. package/src/web/application.ts +348 -0
  186. package/src/web/interfaces.ts +17 -0
  187. package/tsconfig.json +8 -6
  188. package/.env.example +0 -0
  189. package/base.ts +0 -1810
  190. package/base2.ts +0 -968
  191. package/bin/frg.ts +0 -5
  192. package/config/fragment.lock.yaml +0 -0
  193. package/config/fragment.yaml +0 -0
  194. package/dist/app.d.ts +0 -15
  195. package/dist/app.js +0 -91
  196. package/dist/app.js.map +0 -1
  197. package/dist/auth/auth.controller.d.ts +0 -10
  198. package/dist/auth/auth.controller.js +0 -88
  199. package/dist/auth/auth.controller.js.map +0 -1
  200. package/dist/auth/auth.middleware.d.ts +0 -2
  201. package/dist/auth/auth.middleware.js +0 -25
  202. package/dist/auth/auth.middleware.js.map +0 -1
  203. package/dist/auth/auth.service.d.ts +0 -20
  204. package/dist/auth/auth.service.js +0 -144
  205. package/dist/auth/auth.service.js.map +0 -1
  206. package/dist/auth/dto/login.dto.d.ts +0 -9
  207. package/dist/auth/dto/login.dto.js.map +0 -1
  208. package/dist/cli/cli.d.ts +0 -12
  209. package/dist/cli/cli.js +0 -187
  210. package/dist/cli/cli.js.map +0 -1
  211. package/dist/cli/commands/config.command.d.ts +0 -6
  212. package/dist/cli/commands/config.command.js +0 -285
  213. package/dist/cli/commands/config.command.js.map +0 -1
  214. package/dist/cli/templates/controller.template.d.ts +0 -1
  215. package/dist/cli/templates/controller.template.js +0 -53
  216. package/dist/cli/templates/controller.template.js.map +0 -1
  217. package/dist/cli/templates/entity.template.d.ts +0 -1
  218. package/dist/cli/templates/entity.template.js +0 -24
  219. package/dist/cli/templates/entity.template.js.map +0 -1
  220. package/dist/cli/templates/repository.template.d.ts +0 -1
  221. package/dist/cli/templates/repository.template.js +0 -44
  222. package/dist/cli/templates/repository.template.js.map +0 -1
  223. package/dist/cli/templates/service.template.d.ts +0 -1
  224. package/dist/cli/templates/service.template.js +0 -44
  225. package/dist/cli/templates/service.template.js.map +0 -1
  226. package/dist/cli/utils/file-generator.d.ts +0 -9
  227. package/dist/cli/utils/file-generator.js.map +0 -1
  228. package/dist/cli/utils/logger.d.ts +0 -14
  229. package/dist/cli/utils/logger.js +0 -50
  230. package/dist/cli/utils/logger.js.map +0 -1
  231. package/dist/controllers/health.controller.d.ts +0 -13
  232. package/dist/controllers/health.controller.js +0 -51
  233. package/dist/controllers/health.controller.js.map +0 -1
  234. package/dist/core/config/config-loader.d.ts +0 -31
  235. package/dist/core/config/config-loader.js +0 -99
  236. package/dist/core/config/config-loader.js.map +0 -1
  237. package/dist/core/decorators/auth-guard.decorator.d.ts +0 -3
  238. package/dist/core/decorators/auth-guard.decorator.js +0 -19
  239. package/dist/core/decorators/auth-guard.decorator.js.map +0 -1
  240. package/dist/core/decorators/autowire.decorator.d.ts +0 -3
  241. package/dist/core/decorators/autowire.decorator.js +0 -18
  242. package/dist/core/decorators/autowire.decorator.js.map +0 -1
  243. package/dist/core/decorators/middleware.decorator.d.ts +0 -3
  244. package/dist/core/decorators/middleware.decorator.js +0 -21
  245. package/dist/core/decorators/middleware.decorator.js.map +0 -1
  246. package/dist/core/decorators/route.decorator.d.ts +0 -14
  247. package/dist/core/decorators/route.decorator.js +0 -33
  248. package/dist/core/decorators/route.decorator.js.map +0 -1
  249. package/dist/core/openai/openai-client.d.ts +0 -12
  250. package/dist/core/openai/openai-client.js +0 -94
  251. package/dist/core/openai/openai-client.js.map +0 -1
  252. package/dist/database/data-source.d.ts +0 -4
  253. package/dist/database/data-source.js +0 -27
  254. package/dist/database/data-source.js.map +0 -1
  255. package/dist/entities/session.entity.d.ts +0 -9
  256. package/dist/entities/session.entity.js +0 -46
  257. package/dist/entities/session.entity.js.map +0 -1
  258. package/dist/entities/user.entity.d.ts +0 -10
  259. package/dist/entities/user.entity.js +0 -49
  260. package/dist/entities/user.entity.js.map +0 -1
  261. package/dist/middlewares/logging.middleware.d.ts +0 -2
  262. package/dist/middlewares/logging.middleware.js +0 -29
  263. package/dist/middlewares/logging.middleware.js.map +0 -1
  264. package/dist/repositories/session.repository.d.ts +0 -9
  265. package/dist/repositories/session.repository.js +0 -51
  266. package/dist/repositories/session.repository.js.map +0 -1
  267. package/dist/repositories/user.repository.d.ts +0 -10
  268. package/dist/repositories/user.repository.js +0 -44
  269. package/dist/repositories/user.repository.js.map +0 -1
  270. package/dist/server.d.ts +0 -1
  271. package/dist/server.js +0 -31
  272. package/dist/server.js.map +0 -1
  273. package/dist/services/health.service.d.ts +0 -13
  274. package/dist/services/health.service.js +0 -45
  275. package/dist/services/health.service.js.map +0 -1
  276. package/readme.md +0 -120
  277. package/src/app.ts +0 -121
  278. package/src/auth/auth.controller.ts +0 -52
  279. package/src/auth/auth.middleware.ts +0 -27
  280. package/src/auth/auth.service.ts +0 -110
  281. package/src/auth/dto/login.dto.ts +0 -11
  282. package/src/cli/cli.ts +0 -212
  283. package/src/cli/commands/config.command.ts +0 -280
  284. package/src/cli/templates/controller.template.ts +0 -51
  285. package/src/cli/templates/entity.template.ts +0 -22
  286. package/src/cli/templates/repository.template.ts +0 -42
  287. package/src/cli/templates/service.template.ts +0 -42
  288. package/src/cli/utils/file-generator.ts +0 -37
  289. package/src/cli/utils/logger.ts +0 -52
  290. package/src/controllers/health.controller.ts +0 -24
  291. package/src/core/config/config-loader.ts +0 -98
  292. package/src/core/decorators/auth-guard.decorator.ts +0 -15
  293. package/src/core/decorators/autowire.decorator.ts +0 -18
  294. package/src/core/decorators/middleware.decorator.ts +0 -18
  295. package/src/core/decorators/route.decorator.ts +0 -33
  296. package/src/core/openai/openai-client.ts +0 -99
  297. package/src/database/data-source.ts +0 -29
  298. package/src/entities/session.entity.ts +0 -25
  299. package/src/entities/user.entity.ts +0 -27
  300. package/src/middlewares/logging.middleware.ts +0 -28
  301. package/src/repositories/session.repository.ts +0 -42
  302. package/src/repositories/user.repository.ts +0 -37
  303. package/src/server.ts +0 -32
  304. package/src/services/health.service.ts +0 -29
@@ -0,0 +1,348 @@
1
+ import express, { Express, Request, Response, NextFunction } from "express";
2
+ import helmet from "helmet";
3
+ import cors from "cors";
4
+ import compression from "compression";
5
+ import * as fs from "fs";
6
+ import * as path from "path";
7
+ import { DIContainer } from "../core/container/di-container";
8
+ import { MetadataStorage } from "../core/metadata/metadata-storage";
9
+ import { METADATA_KEYS } from "../core/metadata/metadata-keys";
10
+ import { ComponentScanner } from "../core/scanner/component-scanner";
11
+
12
+ export class FragmentWebApplication {
13
+ private app: Express;
14
+ private container: DIContainer;
15
+ private metadataStorage: MetadataStorage;
16
+
17
+ constructor() {
18
+ this.app = express();
19
+ this.container = DIContainer.getInstance();
20
+ this.metadataStorage = MetadataStorage.getInstance();
21
+ this.setupMiddleware();
22
+ }
23
+
24
+ private setupMiddleware(): void {
25
+ this.app.use(helmet());
26
+ this.app.use(cors());
27
+ this.app.use(compression());
28
+ this.app.use(express.json());
29
+ this.app.use(express.urlencoded({ extended: true }));
30
+ }
31
+
32
+ async bootstrap(appClass: any): Promise<void> {
33
+ const appMetadata = Reflect.getMetadata(
34
+ METADATA_KEYS.APPLICATION,
35
+ appClass,
36
+ );
37
+
38
+ // CRITICAL: Scan and load all component files first
39
+ // This triggers decorator execution
40
+ if (appMetadata?.autoScan !== false) {
41
+ console.log("🔍 Scanning for components...");
42
+ await this.scanComponents();
43
+ }
44
+
45
+ // Now metadata storage will be populated
46
+ this.discoverAndRegisterComponents();
47
+ this.registerRoutes();
48
+
49
+ const port = appMetadata?.port || 3000;
50
+ const host = appMetadata?.host || "0.0.0.0";
51
+
52
+ this.app.use(this.errorHandler.bind(this));
53
+
54
+ this.app.listen(port, host, () => {
55
+ console.log(`✨ Fragment application running on http://${host}:${port}`);
56
+ });
57
+ }
58
+
59
+ /**
60
+ * Detects environment and scans appropriate files
61
+ */
62
+ private async scanComponents(): Promise<void> {
63
+ const cwd = process.cwd();
64
+ const distExists = fs.existsSync(path.join(cwd, "dist"));
65
+ const srcExists = fs.existsSync(path.join(cwd, "src"));
66
+
67
+ // Determine if we're running TypeScript directly (dev) or compiled JS (prod)
68
+ const isDevMode = this.isRunningTypeScript();
69
+
70
+ if (isDevMode && srcExists) {
71
+ // Development mode: scan TypeScript source files
72
+ console.log(" 📝 Development mode: scanning TypeScript files");
73
+ await ComponentScanner.scanSource();
74
+ } else if (distExists) {
75
+ // Production mode: scan compiled JavaScript files
76
+ console.log(" 📦 Production mode: scanning compiled files");
77
+ await ComponentScanner.scan();
78
+ } else {
79
+ console.warn(" ⚠️ Warning: No src/ or dist/ directory found");
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Detects if we're running TypeScript directly (ts-node or similar)
85
+ */
86
+ private isRunningTypeScript(): boolean {
87
+ // Check if ts-node is in require.extensions
88
+ if (require.extensions[".ts"]) {
89
+ return true;
90
+ }
91
+
92
+ // Check if process is running with ts-node or tsx
93
+ const execPath = process.argv[0];
94
+ const scriptPath = process.argv[1] || "";
95
+
96
+ if (
97
+ execPath.includes("ts-node") ||
98
+ execPath.includes("tsx") ||
99
+ scriptPath.includes("ts-node") ||
100
+ scriptPath.includes("tsx")
101
+ ) {
102
+ return true;
103
+ }
104
+
105
+ // Check if main module has .ts extension
106
+ if (require.main?.filename.endsWith(".ts")) {
107
+ return true;
108
+ }
109
+
110
+ // Check NODE_ENV or explicit flag
111
+ if (process.env.FRAGMENT_DEV_MODE === "true") {
112
+ return true;
113
+ }
114
+
115
+ return false;
116
+ }
117
+
118
+ private discoverAndRegisterComponents(): void {
119
+ const classes = this.metadataStorage.getAllClasses();
120
+
121
+ // Group by type
122
+ const grouped = classes.reduce(
123
+ (acc, cls) => {
124
+ if (!acc[cls.type]) acc[cls.type] = [];
125
+ acc[cls.type].push(cls);
126
+ return acc;
127
+ },
128
+ {} as Record<string, any[]>,
129
+ );
130
+
131
+ const total = classes.length;
132
+ const registered = classes.filter((m) =>
133
+ this.shouldRegister(m.target),
134
+ ).length;
135
+
136
+ console.log(`\n📦 Discovered ${total} component(s)`);
137
+
138
+ Object.entries(grouped).forEach(([type, items]) => {
139
+ const icon = this.getTypeIcon(type);
140
+ console.log(` ${icon} ${items.length} ${type}(s)`);
141
+ });
142
+
143
+ let count = 0;
144
+ classes.forEach((metadata) => {
145
+ if (this.shouldRegister(metadata.target)) {
146
+ if (!this.container.has(metadata.target)) {
147
+ this.container.register(metadata.target);
148
+ count++;
149
+ }
150
+ }
151
+ });
152
+
153
+ console.log(` ✓ Registered ${count}/${total} component(s)\n`);
154
+ }
155
+
156
+ private getTypeIcon(type: string): string {
157
+ const icons: Record<string, string> = {
158
+ controller: "🎮",
159
+ service: "⚙️",
160
+ repository: "💾",
161
+ injectable: "💉",
162
+ "auto-configuration": "🔧",
163
+ };
164
+ return icons[type] || "📌";
165
+ }
166
+
167
+ private shouldRegister(target: any): boolean {
168
+ const conditionalClass = Reflect.getMetadata(
169
+ METADATA_KEYS.CONDITIONAL_ON_CLASS,
170
+ target,
171
+ );
172
+ if (conditionalClass && !this.isClassAvailable(conditionalClass)) {
173
+ return false;
174
+ }
175
+
176
+ const conditionalMissingBean = Reflect.getMetadata(
177
+ METADATA_KEYS.CONDITIONAL_ON_MISSING_BEAN,
178
+ target,
179
+ );
180
+ if (conditionalMissingBean && this.container.has(conditionalMissingBean)) {
181
+ return false;
182
+ }
183
+
184
+ const conditionalProperty = Reflect.getMetadata(
185
+ METADATA_KEYS.CONDITIONAL_ON_PROPERTY,
186
+ target,
187
+ );
188
+ if (conditionalProperty) {
189
+ const value = process.env[conditionalProperty.key];
190
+ if (
191
+ conditionalProperty.expectedValue !== undefined &&
192
+ value !== conditionalProperty.expectedValue
193
+ ) {
194
+ return false;
195
+ }
196
+ if (!value) {
197
+ return false;
198
+ }
199
+ }
200
+
201
+ return true;
202
+ }
203
+
204
+ private isClassAvailable(classRef: any): boolean {
205
+ try {
206
+ return typeof classRef === "function";
207
+ } catch {
208
+ return false;
209
+ }
210
+ }
211
+
212
+ private registerRoutes(): void {
213
+ const controllers = this.metadataStorage
214
+ .getAllClasses()
215
+ .filter((c) => c.type === "controller");
216
+
217
+ if (controllers.length === 0) {
218
+ console.log("🛣️ No routes to register\n");
219
+ return;
220
+ }
221
+
222
+ let totalRoutes = 0;
223
+ console.log(`🛣️ Registering routes...\n`);
224
+
225
+ controllers.forEach((controllerMetadata) => {
226
+ const controller = this.container.resolve(controllerMetadata.target);
227
+ const basePath = controllerMetadata.path || "";
228
+ const methods = this.metadataStorage
229
+ .getAllMethods()
230
+ .filter((m) => m.target === controllerMetadata.target);
231
+
232
+ if (methods.length > 0) {
233
+ const controllerName = controllerMetadata.target.name;
234
+ console.log(` 📍 ${controllerName}`);
235
+
236
+ methods.forEach((methodMetadata) => {
237
+ const fullPath = this.normalizePath(basePath + methodMetadata.path);
238
+ const httpMethod = methodMetadata.method.toLowerCase();
239
+ const methodColor = this.getMethodColor(httpMethod);
240
+ const methodIcon = this.getMethodIcon(httpMethod);
241
+
242
+ console.log(
243
+ ` ${methodIcon} ${methodColor}${httpMethod.toUpperCase().padEnd(7)}\x1b[0m ${fullPath}`,
244
+ );
245
+ totalRoutes++;
246
+
247
+ (this.app as any)[httpMethod](
248
+ fullPath,
249
+ async (req: Request, res: Response, next: NextFunction) => {
250
+ try {
251
+ const args = this.resolveMethodParameters(
252
+ methodMetadata,
253
+ req,
254
+ res,
255
+ );
256
+ const result = await (controller as any)[
257
+ methodMetadata.propertyKey
258
+ ](...args);
259
+ if (!res.headersSent) {
260
+ res.json(result);
261
+ }
262
+ } catch (error) {
263
+ next(error);
264
+ }
265
+ },
266
+ );
267
+ });
268
+ console.log("");
269
+ }
270
+ });
271
+
272
+ console.log(` ✓ Registered ${totalRoutes} route(s)\n`);
273
+ }
274
+
275
+ private getMethodColor(method: string): string {
276
+ const colors: Record<string, string> = {
277
+ get: "\x1b[32m", // Green
278
+ post: "\x1b[33m", // Yellow
279
+ put: "\x1b[34m", // Blue
280
+ delete: "\x1b[31m", // Red
281
+ patch: "\x1b[35m", // Magenta
282
+ };
283
+ return colors[method] || "\x1b[37m"; // White default
284
+ }
285
+
286
+ private getMethodIcon(method: string): string {
287
+ const icons: Record<string, string> = {
288
+ get: "🔍",
289
+ post: "➕",
290
+ put: "✏️",
291
+ delete: "🗑️",
292
+ patch: "🔧",
293
+ };
294
+ return icons[method] || "•";
295
+ }
296
+
297
+ private resolveMethodParameters(
298
+ methodMetadata: any,
299
+ req: Request,
300
+ res: Response,
301
+ ): any[] {
302
+ const params = methodMetadata.paramMetadata.sort(
303
+ (a: any, b: any) => a.index - b.index,
304
+ );
305
+
306
+ return params.map((param: any) => {
307
+ switch (param.type) {
308
+ case "body":
309
+ return req.body;
310
+ case "param":
311
+ return param.paramName ? req.params[param.paramName] : req.params;
312
+ case "query":
313
+ return param.paramName ? req.query[param.paramName] : req.query;
314
+ case "header":
315
+ return param.paramName
316
+ ? req.headers[param.paramName.toLowerCase()]
317
+ : req.headers;
318
+ case "req":
319
+ return req;
320
+ case "res":
321
+ return res;
322
+ default:
323
+ return undefined;
324
+ }
325
+ });
326
+ }
327
+
328
+ private normalizePath(path: string): string {
329
+ return "/" + path.split("/").filter(Boolean).join("/");
330
+ }
331
+
332
+ private errorHandler(
333
+ err: Error,
334
+ req: Request,
335
+ res: Response,
336
+ next: NextFunction,
337
+ ): void {
338
+ console.error(err.stack);
339
+ res.status(500).json({
340
+ error: "Internal Server Error",
341
+ message: err.message,
342
+ });
343
+ }
344
+
345
+ getExpressApp(): Express {
346
+ return this.app;
347
+ }
348
+ }
@@ -0,0 +1,17 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ export interface Middleware {
4
+ use(req: Request, res: Response, next: NextFunction): void | Promise<void>;
5
+ }
6
+
7
+ export interface Guard {
8
+ canActivate(req: Request): boolean | Promise<boolean>;
9
+ }
10
+
11
+ export interface Interceptor {
12
+ intercept(req: Request, res: Response, next: NextFunction): void | Promise<void>;
13
+ }
14
+
15
+ export interface ExceptionFilter {
16
+ catch(exception: Error, req: Request, res: Response): void;
17
+ }
package/tsconfig.json CHANGED
@@ -5,17 +5,19 @@
5
5
  "lib": ["ES2020"],
6
6
  "outDir": "./dist",
7
7
  "rootDir": "./src",
8
+ "declaration": true,
9
+ "declarationMap": true,
10
+ "sourceMap": true,
8
11
  "strict": true,
9
12
  "esModuleInterop": true,
10
13
  "skipLibCheck": true,
11
14
  "forceConsistentCasingInFileNames": true,
15
+ "moduleResolution": "node",
16
+ "resolveJsonModule": true,
12
17
  "experimentalDecorators": true,
13
18
  "emitDecoratorMetadata": true,
14
- "resolveJsonModule": true,
15
- "moduleResolution": "node",
16
- "declaration": true,
17
- "sourceMap": true
19
+ "allowSyntheticDefaultImports": true
18
20
  },
19
21
  "include": ["src/**/*"],
20
- "exclude": ["node_modules", "dist", "examples", "tests"]
21
- }
22
+ "exclude": ["node_modules", "dist", "**/*.spec.ts"]
23
+ }
package/.env.example DELETED
File without changes