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
@@ -1,395 +1,383 @@
1
-
2
- import * as fs from 'fs';
3
- import * as path from 'path';
4
- import { execSync } from 'child_process';
5
- import { CLILogger } from '../utils/logger';
6
- import { FileGenerator } from '../utils/file-generator';
7
- import inquirer from 'inquirer';
8
- import chalk from 'chalk';
1
+ import { Command } from "commander";
2
+ import * as fs from "fs-extra";
3
+ import * as path from "path";
4
+ import inquirer from "inquirer";
5
+ import ora from "ora";
6
+ import chalk from "chalk";
7
+ import { execSync } from "child_process";
9
8
 
10
9
  export class InitCommand {
11
- async execute(projectName?: string): Promise<void> {
12
- CLILogger.title('🔷 Fragment Framework Initializer');
13
-
14
- const answers = await inquirer.prompt([
15
- {
16
- type: 'input',
17
- name: 'projectName',
18
- message: 'Project name:',
19
- default: projectName || 'my-fragment-app',
20
- validate: (input: string) => {
21
- if (!/^[a-z0-9-]+$/.test(input)) {
22
- return 'Project name must contain only lowercase letters, numbers, and hyphens';
23
- }
24
- return true;
10
+ static register(program: Command): void {
11
+ program
12
+ .command("init [directory]")
13
+ .description("Initialize a new Fragment project")
14
+ .option("-t, --template <template>", "Project template", "api")
15
+ .option(
16
+ "-f, --features <features>",
17
+ "Features to include (comma-separated)",
18
+ )
19
+ .option("--skip-install", "Skip npm install")
20
+ .action(async (directory, options) => {
21
+ await InitCommand.execute(directory || ".", options);
22
+ });
23
+ }
24
+
25
+ static async execute(directory: string, options: any): Promise<void> {
26
+ const spinner = ora();
27
+
28
+ try {
29
+ const projectPath = path.resolve(process.cwd(), directory);
30
+ const projectName = path.basename(projectPath);
31
+
32
+ spinner.start("Creating project directory...");
33
+ await fs.ensureDir(projectPath);
34
+ spinner.succeed();
35
+
36
+ const answers = await inquirer.prompt([
37
+ {
38
+ type: "input",
39
+ name: "name",
40
+ message: "Project name:",
41
+ default: projectName,
42
+ },
43
+ {
44
+ type: "input",
45
+ name: "description",
46
+ message: "Project description:",
47
+ default: "A Fragment Framework project",
48
+ },
49
+ {
50
+ type: "checkbox",
51
+ name: "features",
52
+ message: "Select features:",
53
+ choices: [
54
+ { name: "Authentication", value: "auth", checked: true },
55
+ { name: "Database (TypeORM)", value: "database", checked: true },
56
+ { name: "AI Integration", value: "ai", checked: false },
57
+ { name: "Testing", value: "testing", checked: true },
58
+ ],
59
+ },
60
+ ]);
61
+
62
+ const features = options.features
63
+ ? options.features.split(",").map((f: string) => f.trim())
64
+ : answers.features;
65
+
66
+ spinner.start("Generating project files...");
67
+ await this.generateProjectStructure(projectPath, {
68
+ name: answers.name,
69
+ description: answers.description,
70
+ template: options.template,
71
+ features,
72
+ });
73
+ spinner.succeed();
74
+
75
+ spinner.start("Creating configuration files...");
76
+ await this.createConfigFiles(projectPath, answers.name, features);
77
+ spinner.succeed();
78
+
79
+ if (!options.skipInstall) {
80
+ spinner.start("Installing dependencies...");
81
+ try {
82
+ execSync("npm install", { cwd: projectPath, stdio: "ignore" });
83
+ spinner.succeed();
84
+ } catch (error) {
85
+ spinner.fail("Failed to install dependencies");
86
+ console.log(
87
+ chalk.yellow(
88
+ "You can install them manually by running: npm install",
89
+ ),
90
+ );
25
91
  }
26
- },
27
- {
28
- type: 'list',
29
- name: 'database',
30
- message: 'Select database:',
31
- choices: ['PostgreSQL', 'MySQL', 'SQLite', 'MongoDB'],
32
- default: 'PostgreSQL'
33
- },
34
- {
35
- type: 'confirm',
36
- name: 'useOpenAI',
37
- message: 'Enable OpenAI integration?',
38
- default: true
39
- },
40
- {
41
- type: 'confirm',
42
- name: 'useAuth',
43
- message: 'Include authentication system?',
44
- default: true
45
- },
46
- {
47
- type: 'list',
48
- name: 'packageManager',
49
- message: 'Package manager:',
50
- choices: ['npm', 'yarn', 'pnpm'],
51
- default: 'npm'
52
92
  }
53
- ]);
54
93
 
55
- const projectPath = path.join(process.cwd(), answers.projectName);
94
+ console.log("\n" + chalk.green("✨ Project created successfully!"));
95
+ console.log("\nNext steps:");
96
+ if (directory !== ".") {
97
+ console.log(chalk.cyan(` cd ${directory}`));
98
+ }
99
+ if (options.skipInstall) {
100
+ console.log(chalk.cyan(" npm install"));
101
+ }
102
+ console.log(chalk.cyan(" fragment serve"));
103
+ console.log("");
104
+ } catch (error) {
105
+ spinner.fail("Failed to initialize project");
106
+ console.error(chalk.red(error));
107
+ process.exit(1);
108
+ }
109
+ }
56
110
 
57
- if (fs.existsSync(projectPath)) {
58
- CLILogger.error(`Directory ${answers.projectName} already exists`);
59
- return;
111
+ private static async generateProjectStructure(
112
+ projectPath: string,
113
+ config: any,
114
+ ): Promise<void> {
115
+ const dirs = [
116
+ "src",
117
+ "src/controllers",
118
+ "src/services",
119
+ "src/entities",
120
+ "src/dto",
121
+ "src/repositories",
122
+ "src/middlewares",
123
+ "src/config",
124
+ ];
125
+
126
+ if (config.features.includes("database")) {
127
+ dirs.push("src/migrations");
128
+ dirs.push("src/seeds");
60
129
  }
61
130
 
62
- const spinner = CLILogger.spinner('Creating project structure...');
131
+ if (config.features.includes("testing")) {
132
+ dirs.push("test");
133
+ }
63
134
 
64
- try {
65
- // Create project directory
66
- FileGenerator.createDirectory(projectPath);
67
-
68
- // Create directory structure
69
- const dirs = [
70
- 'src/controllers',
71
- 'src/services',
72
- 'src/repositories',
73
- 'src/entities',
74
- 'src/middlewares',
75
- 'src/core/decorators',
76
- 'src/core/container',
77
- 'src/core/config',
78
- 'src/database',
79
- 'config'
80
- ];
81
-
82
- if (answers.useOpenAI) {
83
- dirs.push('src/core/openai');
84
- }
135
+ for (const dir of dirs) {
136
+ await fs.ensureDir(path.join(projectPath, dir));
137
+ }
85
138
 
86
- if (answers.useAuth) {
87
- dirs.push('src/auth', 'src/auth/dto');
88
- }
139
+ await this.generateMainFile(projectPath, config);
140
+ await this.generateExampleController(projectPath);
141
+ await this.generateExampleService(projectPath);
89
142
 
90
- dirs.forEach(dir => {
91
- FileGenerator.createDirectory(path.join(projectPath, dir));
92
- });
143
+ if (config.features.includes("database")) {
144
+ await this.generateExampleEntity(projectPath);
145
+ }
93
146
 
94
- spinner.text = 'Generating configuration files...';
95
-
96
- // Generate package.json
97
- const packageJson = {
98
- name: answers.projectName,
99
- version: '1.0.0',
100
- description: 'Fragment Framework Application',
101
- main: 'dist/server.js',
102
- scripts: {
103
- dev: 'ts-node-dev --respawn --transpile-only src/server.ts',
104
- build: 'tsc',
105
- start: 'node dist/server.js',
106
- 'frg:generate': 'frg generate',
107
- 'frg:migrate': 'frg migrate'
108
- },
109
- dependencies: {
110
- express: '^4.18.2',
111
- typeorm: '^0.3.17',
112
- 'reflect-metadata': '^0.1.13',
113
- bcrypt: '^5.1.1',
114
- 'js-yaml': '^4.1.0',
115
- pino: '^8.16.0',
116
- 'pino-pretty': '^10.2.3'
117
- },
118
- devDependencies: {
119
- '@types/express': '^4.17.20',
120
- '@types/node': '^20.9.0',
121
- '@types/bcrypt': '^5.0.2',
122
- '@types/js-yaml': '^4.0.9',
123
- typescript: '^5.2.2',
124
- 'ts-node': '^10.9.1',
125
- 'ts-node-dev': '^2.0.0'
126
- }
127
- };
147
+ if (config.features.includes("auth")) {
148
+ await this.generateAuthFiles(projectPath);
149
+ }
150
+ }
128
151
 
129
- // Add database driver
130
- const dbDrivers: { [key: string]: string } = {
131
- 'PostgreSQL': 'pg@^8.11.3',
132
- 'MySQL': 'mysql2@^3.6.5',
133
- 'SQLite': 'sqlite3@^5.1.6',
134
- 'MongoDB': 'mongodb@^6.3.0'
135
- };
136
- packageJson.dependencies = {
137
- ...packageJson.dependencies,
138
- [dbDrivers[answers.database].split('@')[0]]: dbDrivers[answers.database].split('@')[1]
139
- };
152
+ private static async createConfigFiles(
153
+ projectPath: string,
154
+ projectName: string,
155
+ features: string[],
156
+ ): Promise<void> {
157
+ const packageJson = {
158
+ name: projectName,
159
+ version: "1.0.0",
160
+ main: "dist/main.js",
161
+ scripts: {
162
+ start: "node dist/main.js",
163
+ dev: "fragment serve",
164
+ build: "fragment build",
165
+ test: "fragment test",
166
+ },
167
+ dependencies: {
168
+ fragment: "^1.0.0",
169
+ "reflect-metadata": "^0.1.13",
170
+ },
171
+ devDependencies: {
172
+ typescript: "^5.3.3",
173
+ "@types/node": "^20.10.5",
174
+ },
175
+ };
140
176
 
141
- FileGenerator.writeFile(
142
- path.join(projectPath, 'package.json'),
143
- JSON.stringify(packageJson, null, 2)
144
- );
145
-
146
- // Generate tsconfig.json
147
- const tsConfig = {
148
- compilerOptions: {
149
- target: 'ES2020',
150
- module: 'commonjs',
151
- lib: ['ES2020'],
152
- outDir: './dist',
153
- rootDir: './src',
154
- strict: true,
155
- esModuleInterop: true,
156
- skipLibCheck: true,
157
- forceConsistentCasingInFileNames: true,
158
- resolveJsonModule: true,
159
- experimentalDecorators: true,
160
- emitDecoratorMetadata: true,
161
- moduleResolution: 'node',
162
- allowSyntheticDefaultImports: true
163
- },
164
- include: ['src/**/*'],
165
- exclude: ['node_modules', 'dist']
166
- };
177
+ await fs.writeJSON(path.join(projectPath, "package.json"), packageJson, {
178
+ spaces: 2,
179
+ });
180
+
181
+ const tsConfig = {
182
+ compilerOptions: {
183
+ target: "ES2020",
184
+ module: "commonjs",
185
+ lib: ["ES2020"],
186
+ outDir: "./dist",
187
+ rootDir: "./src",
188
+ strict: true,
189
+ esModuleInterop: true,
190
+ experimentalDecorators: true,
191
+ emitDecoratorMetadata: true,
192
+ skipLibCheck: true,
193
+ },
194
+ include: ["src/**/*"],
195
+ exclude: ["node_modules", "dist"],
196
+ };
167
197
 
168
- FileGenerator.writeFile(
169
- path.join(projectPath, 'tsconfig.json'),
170
- JSON.stringify(tsConfig, null, 2)
171
- );
172
-
173
- // Generate fragment.yaml
174
- const dbConfig = this.getDatabaseConfig(answers.database);
175
- const fragmentConfig = `app:
176
- name: ${answers.projectName}
177
- port: 3000
178
- env: development
179
-
180
- database:
181
- ${dbConfig}
182
-
183
- ${answers.useOpenAI ? `openai:
184
- apiKey: \${OPENAI_API_KEY}
185
- model: gpt-4
186
- ` : ''}
187
- ${answers.useAuth ? `auth:
188
- tokenExpiry: 7d
189
- sessionExpiry: 30d
190
- ` : ''}`;
191
-
192
- FileGenerator.writeFile(
193
- path.join(projectPath, 'config/fragment.yaml'),
194
- fragmentConfig
195
- );
196
-
197
- // Generate .env.example
198
- let envExample = `NODE_ENV=development
199
- PORT=3000
198
+ await fs.writeJSON(path.join(projectPath, "tsconfig.json"), tsConfig, {
199
+ spaces: 2,
200
+ });
200
201
 
201
- ${this.getEnvTemplate(answers.database)}`;
202
+ const fragmentConfig: any = {
203
+ server: {
204
+ port: 3000,
205
+ host: "0.0.0.0",
206
+ },
207
+ };
202
208
 
203
- if (answers.useOpenAI) {
204
- envExample += '\nOPENAI_API_KEY=sk-your-openai-api-key';
205
- }
209
+ if (features.includes("database")) {
210
+ fragmentConfig.database = {
211
+ type: "sqlite",
212
+ database: "database.sqlite",
213
+ synchronize: true,
214
+ logging: false,
215
+ entities: ["dist/**/*.entity.js"],
216
+ migrations: ["dist/migrations/**/*.js"],
217
+ };
218
+ }
206
219
 
207
- FileGenerator.writeFile(
208
- path.join(projectPath, '.env.example'),
209
- envExample
210
- );
211
-
212
- // Generate .gitignore
213
- const gitignore = `node_modules/
214
- dist/
215
- .env
216
- *.log
217
- .DS_Store
218
- config/fragment.lock.yaml`;
219
-
220
- FileGenerator.writeFile(
221
- path.join(projectPath, '.gitignore'),
222
- gitignore
223
- );
224
-
225
- // Generate README.md
226
- const readme = this.generateReadme(answers.projectName, answers);
227
- FileGenerator.writeFile(
228
- path.join(projectPath, 'README.md'),
229
- readme
230
- );
231
-
232
- spinner.text = 'Copying core framework files...';
233
-
234
- // Copy all core files (decorators, container, config, etc.)
235
- await this.copyFrameworkCore(projectPath, answers);
236
-
237
- spinner.succeed('Project structure created');
238
-
239
- // Install dependencies
240
- const installSpinner = CLILogger.spinner(`Installing dependencies with ${answers.packageManager}...`);
241
-
242
- try {
243
- execSync(`cd ${projectPath} && ${answers.packageManager} install`, {
244
- stdio: 'pipe'
245
- });
246
- installSpinner.succeed('Dependencies installed');
247
- } catch (error) {
248
- installSpinner.fail('Failed to install dependencies');
249
- CLILogger.warning('You can install them manually by running:');
250
- console.log(` cd ${answers.projectName} && ${answers.packageManager} install`);
251
- }
220
+ await fs.writeJSON(
221
+ path.join(projectPath, "fragment.json"),
222
+ fragmentConfig,
223
+ { spaces: 2 },
224
+ );
252
225
 
253
- // Success message
254
- CLILogger.box('🎉 Project Created Successfully!', [
255
- `Project: ${answers.projectName}`,
256
- `Location: ${projectPath}`,
257
- `Database: ${answers.database}`,
258
- `OpenAI: ${answers.useOpenAI ? 'Enabled' : 'Disabled'}`,
259
- `Auth: ${answers.useAuth ? 'Enabled' : 'Disabled'}`
260
- ]);
226
+ const envContent = `NODE_ENV=development
227
+ PORT=3000
228
+ JWT_SECRET=your-secret-key-change-this
229
+ ${features.includes("database") ? "DATABASE_URL=sqlite:database.sqlite" : ""}
230
+ `;
261
231
 
262
- console.log(chalk.bold('\nNext steps:'));
263
- console.log(` 1. cd ${answers.projectName}`);
264
- console.log(` 2. cp .env.example .env`);
265
- console.log(` 3. Configure your database in .env`);
266
- if (answers.useOpenAI) {
267
- console.log(` 4. Add your OpenAI API key to .env`);
268
- }
269
- console.log(` ${answers.useOpenAI ? '5' : '4'}. ${answers.packageManager} run dev`);
270
-
271
- CLILogger.section('Available Commands:');
272
- CLILogger.table({
273
- 'frg generate controller <name>': 'Generate a new controller',
274
- 'frg generate service <name>': 'Generate a new service',
275
- 'frg generate resource <name>': 'Generate controller, service, repository & entity',
276
- 'frg config ai': 'Configure OpenAI settings',
277
- 'frg migrate': 'Run database migrations',
278
- 'frg serve': 'Start development server'
279
- });
232
+ await fs.writeFile(path.join(projectPath, ".env"), envContent);
233
+ await fs.writeFile(
234
+ path.join(projectPath, ".gitignore"),
235
+ "node_modules/\ndist/\n.env\n*.sqlite\n",
236
+ );
237
+ }
280
238
 
281
- } catch (error: any) {
282
- spinner.fail('Failed to create project');
283
- CLILogger.error(error.message);
239
+ // In the generateMainFile method, update to:
240
+ private static async generateMainFile(
241
+ projectPath: string,
242
+ config: any,
243
+ ): Promise<void> {
244
+ const content = `import 'reflect-metadata';
245
+ import { FragmentApplication } from 'fragment-ts';
246
+ import { FragmentWebApplication } from 'fragment-ts';
247
+ import { AppController } from './controllers/app.controller';
248
+
249
+ @FragmentApplication({
250
+ port: 3000,
251
+ autoScan: true
252
+ })
253
+ class Application {
254
+ constructor() {
255
+ console.log('Fragment application initialized');
284
256
  }
285
257
  }
286
258
 
287
- private getDatabaseConfig(database: string): string {
288
- const configs: { [key: string]: string } = {
289
- 'PostgreSQL': ` type: postgres
290
- host: \${DB_HOST:localhost}
291
- port: \${DB_PORT:5432}
292
- username: \${DB_USERNAME:postgres}
293
- password: \${DB_PASSWORD:postgres}
294
- database: \${DB_DATABASE:fragment_db}
295
- synchronize: true
296
- logging: false`,
297
- 'MySQL': ` type: mysql
298
- host: \${DB_HOST:localhost}
299
- port: \${DB_PORT:3306}
300
- username: \${DB_USERNAME:root}
301
- password: \${DB_PASSWORD:root}
302
- database: \${DB_DATABASE:fragment_db}
303
- synchronize: true
304
- logging: false`,
305
- 'SQLite': ` type: sqlite
306
- database: \${DB_DATABASE:database.sqlite}
307
- synchronize: true
308
- logging: false`,
309
- 'MongoDB': ` type: mongodb
310
- host: \${DB_HOST:localhost}
311
- port: \${DB_PORT:27017}
312
- database: \${DB_DATABASE:fragment_db}
313
- synchronize: true
314
- logging: false`
315
- };
316
- return configs[database];
259
+ async function bootstrap() {
260
+ console.log('Starting Fragment application...');
261
+ const app = new FragmentWebApplication();
262
+ await app.bootstrap(Application);
317
263
  }
318
264
 
319
- private getEnvTemplate(database: string): string {
320
- if (database === 'SQLite') {
321
- return 'DB_DATABASE=database.sqlite';
322
- }
323
- return `DB_HOST=localhost
324
- DB_PORT=${database === 'PostgreSQL' ? '5432' : database === 'MySQL' ? '3306' : '27017'}
325
- DB_USERNAME=${database === 'PostgreSQL' ? 'postgres' : 'root'}
326
- DB_PASSWORD=${database === 'PostgreSQL' ? 'postgres' : 'root'}
327
- DB_DATABASE=fragment_db`;
265
+ bootstrap().catch(console.error);
266
+ `;
267
+
268
+ await fs.writeFile(path.join(projectPath, "src", "main.ts"), content);
328
269
  }
329
270
 
330
- private generateReadme(projectName: string, answers: any): string {
331
- return `# ${projectName}
271
+ private static async generateExampleController(
272
+ projectPath: string,
273
+ ): Promise<void> {
274
+ const content = `import { Controller, Get } from 'fragment-ts';
332
275
 
333
- A Fragment Framework application.
276
+ @Controller('/api')
277
+ export class AppController {
278
+ @Get('/health')
279
+ health() {
280
+ return { status: 'ok', timestamp: new Date().toISOString() };
281
+ }
282
+ }
283
+ `;
334
284
 
335
- ## Getting Started
285
+ await fs.writeFile(
286
+ path.join(projectPath, "src", "controllers", "app.controller.ts"),
287
+ content,
288
+ );
289
+ }
336
290
 
337
- \`\`\`bash
338
- # Install dependencies
339
- ${answers.packageManager} install
291
+ private static async generateExampleService(
292
+ projectPath: string,
293
+ ): Promise<void> {
294
+ const content = `import { Service } from 'fragment-ts';
340
295
 
341
- # Configure environment
342
- cp .env.example .env
296
+ @Service()
297
+ export class AppService {
298
+ getMessage(): string {
299
+ return 'Welcome to Fragment Framework!';
300
+ }
301
+ }
302
+ `;
343
303
 
344
- # Start development server
345
- ${answers.packageManager} run dev
346
- \`\`\`
304
+ await fs.writeFile(
305
+ path.join(projectPath, "src", "services", "app.service.ts"),
306
+ content,
307
+ );
308
+ }
347
309
 
348
- ## Fragment CLI Commands
310
+ private static async generateExampleEntity(
311
+ projectPath: string,
312
+ ): Promise<void> {
313
+ const content = `import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
349
314
 
350
- \`\`\`bash
351
- # Generate resources
352
- frg generate controller <name> # Generate controller
353
- frg generate service <name> # Generate service
354
- frg generate repository <name> # Generate repository
355
- frg generate entity <name> # Generate entity
356
- frg generate resource <name> # Generate all of the above
315
+ @Entity()
316
+ export class User {
317
+ @PrimaryGeneratedColumn()
318
+ id: number;
357
319
 
358
- # Configuration
359
- frg config ai # Configure OpenAI settings
360
- frg config db # Configure database settings
320
+ @Column()
321
+ email: string;
361
322
 
362
- # Database
363
- frg migrate # Run migrations
323
+ @Column()
324
+ name: string;
364
325
 
365
- # Development
366
- frg serve # Start development server
367
- frg build # Build for production
368
- \`\`\`
326
+ @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
327
+ createdAt: Date;
328
+ }
329
+ `;
369
330
 
370
- ## Project Structure
331
+ await fs.writeFile(
332
+ path.join(projectPath, "src", "entities", "user.entity.ts"),
333
+ content,
334
+ );
335
+ }
336
+
337
+ private static async generateAuthFiles(projectPath: string): Promise<void> {
338
+ const controllerContent = `import { Controller, Post, Body } from 'fragment-ts';
339
+ import { AuthService } from '../services/auth.service';
371
340
 
372
- \`\`\`
373
- src/
374
- ├── controllers/ # HTTP request handlers
375
- ├── services/ # Business logic
376
- ├── repositories/ # Data access layer
377
- ├── entities/ # Database models
378
- ├── middlewares/ # Express middlewares
379
- └── core/ # Framework core
380
- \`\`\`
341
+ @Controller('/auth')
342
+ export class AuthController {
343
+ constructor(private authService: AuthService) {}
381
344
 
382
- ## Documentation
345
+ @Post('/login')
346
+ async login(@Body() body: any) {
347
+ return this.authService.login(body.email, body.password);
348
+ }
383
349
 
384
- Visit [Fragment Framework Documentation](https://fragment-framework.dev) for more information.
350
+ @Post('/register')
351
+ async register(@Body() body: any) {
352
+ return this.authService.register(body);
353
+ }
354
+ }
385
355
  `;
356
+
357
+ const serviceContent = `import { Service } from 'fragment-ts';
358
+ import { AuthModule } from 'fragment-ts';
359
+
360
+ @Service()
361
+ export class AuthService {
362
+ async login(email: string, password: string) {
363
+ const token = AuthModule.generateToken({ userId: '1', email });
364
+ return { token };
365
+ }
366
+
367
+ async register(userData: any) {
368
+ const hashedPassword = await AuthModule.hashPassword(userData.password);
369
+ return { message: 'User registered successfully' };
386
370
  }
371
+ }
372
+ `;
387
373
 
388
- private async copyFrameworkCore(projectPath: string, answers: any): Promise<void> {
389
- // This would copy all the core framework files
390
- // For brevity, I'll show the structure
391
- // In a real implementation, these would be actual file copies
392
-
393
- CLILogger.info('Core framework files copied');
374
+ await fs.writeFile(
375
+ path.join(projectPath, "src", "controllers", "auth.controller.ts"),
376
+ controllerContent,
377
+ );
378
+ await fs.writeFile(
379
+ path.join(projectPath, "src", "services", "auth.service.ts"),
380
+ serviceContent,
381
+ );
394
382
  }
395
- }
383
+ }