fragment-ts 1.0.0

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 (123) hide show
  1. package/.env.example +0 -0
  2. package/base.ts +1810 -0
  3. package/base2.ts +968 -0
  4. package/bin/frg.ts +5 -0
  5. package/config/fragment.lock.yaml +0 -0
  6. package/config/fragment.yaml +0 -0
  7. package/dist/app.d.ts +15 -0
  8. package/dist/app.js +90 -0
  9. package/dist/auth/auth.controller.d.ts +10 -0
  10. package/dist/auth/auth.controller.js +87 -0
  11. package/dist/auth/auth.middleware.d.ts +2 -0
  12. package/dist/auth/auth.middleware.js +24 -0
  13. package/dist/auth/auth.service.d.ts +20 -0
  14. package/dist/auth/auth.service.js +143 -0
  15. package/dist/auth/dto/login.dto.d.ts +9 -0
  16. package/dist/auth/dto/login.dto.js +2 -0
  17. package/dist/cli/cli.d.ts +12 -0
  18. package/dist/cli/cli.js +186 -0
  19. package/dist/cli/commands/build.command.d.ts +3 -0
  20. package/dist/cli/commands/build.command.js +23 -0
  21. package/dist/cli/commands/config.command.d.ts +6 -0
  22. package/dist/cli/commands/config.command.js +284 -0
  23. package/dist/cli/commands/generate.command.d.ts +8 -0
  24. package/dist/cli/commands/generate.command.js +180 -0
  25. package/dist/cli/commands/init.command.d.ts +7 -0
  26. package/dist/cli/commands/init.command.js +380 -0
  27. package/dist/cli/commands/migrate.command.d.ts +7 -0
  28. package/dist/cli/commands/migrate.command.js +116 -0
  29. package/dist/cli/commands/serve.command.d.ts +6 -0
  30. package/dist/cli/commands/serve.command.js +31 -0
  31. package/dist/cli/templates/controller.template.d.ts +1 -0
  32. package/dist/cli/templates/controller.template.js +52 -0
  33. package/dist/cli/templates/entity.template.d.ts +1 -0
  34. package/dist/cli/templates/entity.template.js +23 -0
  35. package/dist/cli/templates/repository.template.d.ts +1 -0
  36. package/dist/cli/templates/repository.template.js +43 -0
  37. package/dist/cli/templates/service.template.d.ts +1 -0
  38. package/dist/cli/templates/service.template.js +43 -0
  39. package/dist/cli/utils/file-generator.d.ts +9 -0
  40. package/dist/cli/utils/file-generator.js +67 -0
  41. package/dist/cli/utils/logger.d.ts +14 -0
  42. package/dist/cli/utils/logger.js +49 -0
  43. package/dist/controllers/health.controller.d.ts +13 -0
  44. package/dist/controllers/health.controller.js +50 -0
  45. package/dist/core/config/config-loader.d.ts +31 -0
  46. package/dist/core/config/config-loader.js +98 -0
  47. package/dist/core/container/di-container.d.ts +9 -0
  48. package/dist/core/container/di-container.js +37 -0
  49. package/dist/core/decorators/auth-guard.decorator.d.ts +3 -0
  50. package/dist/core/decorators/auth-guard.decorator.js +18 -0
  51. package/dist/core/decorators/autowire.decorator.d.ts +3 -0
  52. package/dist/core/decorators/autowire.decorator.js +17 -0
  53. package/dist/core/decorators/controller.decorator.d.ts +4 -0
  54. package/dist/core/decorators/controller.decorator.js +16 -0
  55. package/dist/core/decorators/injectable.decorator.d.ts +3 -0
  56. package/dist/core/decorators/injectable.decorator.js +14 -0
  57. package/dist/core/decorators/middleware.decorator.d.ts +3 -0
  58. package/dist/core/decorators/middleware.decorator.js +20 -0
  59. package/dist/core/decorators/repository.decorator.d.ts +1 -0
  60. package/dist/core/decorators/repository.decorator.js +7 -0
  61. package/dist/core/decorators/route.decorator.d.ts +14 -0
  62. package/dist/core/decorators/route.decorator.js +32 -0
  63. package/dist/core/decorators/service.decorator.d.ts +1 -0
  64. package/dist/core/decorators/service.decorator.js +7 -0
  65. package/dist/core/openai/openai-client.d.ts +12 -0
  66. package/dist/core/openai/openai-client.js +93 -0
  67. package/dist/database/data-source.d.ts +4 -0
  68. package/dist/database/data-source.js +26 -0
  69. package/dist/entities/session.entity.d.ts +9 -0
  70. package/dist/entities/session.entity.js +45 -0
  71. package/dist/entities/user.entity.d.ts +10 -0
  72. package/dist/entities/user.entity.js +48 -0
  73. package/dist/middlewares/logging.middleware.d.ts +2 -0
  74. package/dist/middlewares/logging.middleware.js +28 -0
  75. package/dist/repositories/session.repository.d.ts +9 -0
  76. package/dist/repositories/session.repository.js +50 -0
  77. package/dist/repositories/user.repository.d.ts +10 -0
  78. package/dist/repositories/user.repository.js +43 -0
  79. package/dist/server.d.ts +1 -0
  80. package/dist/server.js +30 -0
  81. package/dist/services/health.service.d.ts +13 -0
  82. package/dist/services/health.service.js +44 -0
  83. package/package.json +46 -0
  84. package/readme.md +120 -0
  85. package/src/app.ts +121 -0
  86. package/src/auth/auth.controller.ts +52 -0
  87. package/src/auth/auth.middleware.ts +27 -0
  88. package/src/auth/auth.service.ts +110 -0
  89. package/src/auth/dto/login.dto.ts +11 -0
  90. package/src/cli/cli.ts +212 -0
  91. package/src/cli/commands/build.command.ts +24 -0
  92. package/src/cli/commands/config.command.ts +280 -0
  93. package/src/cli/commands/generate.command.ts +170 -0
  94. package/src/cli/commands/init.command.ts +395 -0
  95. package/src/cli/commands/migrate.command.ts +118 -0
  96. package/src/cli/commands/serve.command.ts +37 -0
  97. package/src/cli/templates/controller.template.ts +51 -0
  98. package/src/cli/templates/entity.template.ts +22 -0
  99. package/src/cli/templates/repository.template.ts +42 -0
  100. package/src/cli/templates/service.template.ts +42 -0
  101. package/src/cli/utils/file-generator.ts +37 -0
  102. package/src/cli/utils/logger.ts +52 -0
  103. package/src/controllers/health.controller.ts +24 -0
  104. package/src/core/config/config-loader.ts +98 -0
  105. package/src/core/container/di-container.ts +43 -0
  106. package/src/core/decorators/auth-guard.decorator.ts +15 -0
  107. package/src/core/decorators/autowire.decorator.ts +18 -0
  108. package/src/core/decorators/controller.decorator.ts +15 -0
  109. package/src/core/decorators/injectable.decorator.ts +13 -0
  110. package/src/core/decorators/middleware.decorator.ts +18 -0
  111. package/src/core/decorators/repository.decorator.ts +6 -0
  112. package/src/core/decorators/route.decorator.ts +33 -0
  113. package/src/core/decorators/service.decorator.ts +6 -0
  114. package/src/core/openai/openai-client.ts +99 -0
  115. package/src/database/data-source.ts +29 -0
  116. package/src/entities/session.entity.ts +25 -0
  117. package/src/entities/user.entity.ts +27 -0
  118. package/src/middlewares/logging.middleware.ts +28 -0
  119. package/src/repositories/session.repository.ts +42 -0
  120. package/src/repositories/user.repository.ts +37 -0
  121. package/src/server.ts +32 -0
  122. package/src/services/health.service.ts +29 -0
  123. package/tsconfig.json +20 -0
@@ -0,0 +1,380 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.InitCommand = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const child_process_1 = require("child_process");
43
+ const logger_1 = require("../utils/logger");
44
+ const file_generator_1 = require("../utils/file-generator");
45
+ const inquirer_1 = __importDefault(require("inquirer"));
46
+ const chalk_1 = __importDefault(require("chalk"));
47
+ class InitCommand {
48
+ async execute(projectName) {
49
+ logger_1.CLILogger.title('🔷 Fragment Framework Initializer');
50
+ const answers = await inquirer_1.default.prompt([
51
+ {
52
+ type: 'input',
53
+ name: 'projectName',
54
+ message: 'Project name:',
55
+ default: projectName || 'my-fragment-app',
56
+ validate: (input) => {
57
+ if (!/^[a-z0-9-]+$/.test(input)) {
58
+ return 'Project name must contain only lowercase letters, numbers, and hyphens';
59
+ }
60
+ return true;
61
+ }
62
+ },
63
+ {
64
+ type: 'list',
65
+ name: 'database',
66
+ message: 'Select database:',
67
+ choices: ['PostgreSQL', 'MySQL', 'SQLite', 'MongoDB'],
68
+ default: 'PostgreSQL'
69
+ },
70
+ {
71
+ type: 'confirm',
72
+ name: 'useOpenAI',
73
+ message: 'Enable OpenAI integration?',
74
+ default: true
75
+ },
76
+ {
77
+ type: 'confirm',
78
+ name: 'useAuth',
79
+ message: 'Include authentication system?',
80
+ default: true
81
+ },
82
+ {
83
+ type: 'list',
84
+ name: 'packageManager',
85
+ message: 'Package manager:',
86
+ choices: ['npm', 'yarn', 'pnpm'],
87
+ default: 'npm'
88
+ }
89
+ ]);
90
+ const projectPath = path.join(process.cwd(), answers.projectName);
91
+ if (fs.existsSync(projectPath)) {
92
+ logger_1.CLILogger.error(`Directory ${answers.projectName} already exists`);
93
+ return;
94
+ }
95
+ const spinner = logger_1.CLILogger.spinner('Creating project structure...');
96
+ try {
97
+ // Create project directory
98
+ file_generator_1.FileGenerator.createDirectory(projectPath);
99
+ // Create directory structure
100
+ const dirs = [
101
+ 'src/controllers',
102
+ 'src/services',
103
+ 'src/repositories',
104
+ 'src/entities',
105
+ 'src/middlewares',
106
+ 'src/core/decorators',
107
+ 'src/core/container',
108
+ 'src/core/config',
109
+ 'src/database',
110
+ 'config'
111
+ ];
112
+ if (answers.useOpenAI) {
113
+ dirs.push('src/core/openai');
114
+ }
115
+ if (answers.useAuth) {
116
+ dirs.push('src/auth', 'src/auth/dto');
117
+ }
118
+ dirs.forEach(dir => {
119
+ file_generator_1.FileGenerator.createDirectory(path.join(projectPath, dir));
120
+ });
121
+ spinner.text = 'Generating configuration files...';
122
+ // Generate package.json
123
+ const packageJson = {
124
+ name: answers.projectName,
125
+ version: '1.0.0',
126
+ description: 'Fragment Framework Application',
127
+ main: 'dist/server.js',
128
+ scripts: {
129
+ dev: 'ts-node-dev --respawn --transpile-only src/server.ts',
130
+ build: 'tsc',
131
+ start: 'node dist/server.js',
132
+ 'frg:generate': 'frg generate',
133
+ 'frg:migrate': 'frg migrate'
134
+ },
135
+ dependencies: {
136
+ express: '^4.18.2',
137
+ typeorm: '^0.3.17',
138
+ 'reflect-metadata': '^0.1.13',
139
+ bcrypt: '^5.1.1',
140
+ 'js-yaml': '^4.1.0',
141
+ pino: '^8.16.0',
142
+ 'pino-pretty': '^10.2.3'
143
+ },
144
+ devDependencies: {
145
+ '@types/express': '^4.17.20',
146
+ '@types/node': '^20.9.0',
147
+ '@types/bcrypt': '^5.0.2',
148
+ '@types/js-yaml': '^4.0.9',
149
+ typescript: '^5.2.2',
150
+ 'ts-node': '^10.9.1',
151
+ 'ts-node-dev': '^2.0.0'
152
+ }
153
+ };
154
+ // Add database driver
155
+ const dbDrivers = {
156
+ 'PostgreSQL': 'pg@^8.11.3',
157
+ 'MySQL': 'mysql2@^3.6.5',
158
+ 'SQLite': 'sqlite3@^5.1.6',
159
+ 'MongoDB': 'mongodb@^6.3.0'
160
+ };
161
+ packageJson.dependencies = {
162
+ ...packageJson.dependencies,
163
+ [dbDrivers[answers.database].split('@')[0]]: dbDrivers[answers.database].split('@')[1]
164
+ };
165
+ file_generator_1.FileGenerator.writeFile(path.join(projectPath, 'package.json'), JSON.stringify(packageJson, null, 2));
166
+ // Generate tsconfig.json
167
+ const tsConfig = {
168
+ compilerOptions: {
169
+ target: 'ES2020',
170
+ module: 'commonjs',
171
+ lib: ['ES2020'],
172
+ outDir: './dist',
173
+ rootDir: './src',
174
+ strict: true,
175
+ esModuleInterop: true,
176
+ skipLibCheck: true,
177
+ forceConsistentCasingInFileNames: true,
178
+ resolveJsonModule: true,
179
+ experimentalDecorators: true,
180
+ emitDecoratorMetadata: true,
181
+ moduleResolution: 'node',
182
+ allowSyntheticDefaultImports: true
183
+ },
184
+ include: ['src/**/*'],
185
+ exclude: ['node_modules', 'dist']
186
+ };
187
+ file_generator_1.FileGenerator.writeFile(path.join(projectPath, 'tsconfig.json'), JSON.stringify(tsConfig, null, 2));
188
+ // Generate fragment.yaml
189
+ const dbConfig = this.getDatabaseConfig(answers.database);
190
+ const fragmentConfig = `app:
191
+ name: ${answers.projectName}
192
+ port: 3000
193
+ env: development
194
+
195
+ database:
196
+ ${dbConfig}
197
+
198
+ ${answers.useOpenAI ? `openai:
199
+ apiKey: \${OPENAI_API_KEY}
200
+ model: gpt-4
201
+ ` : ''}
202
+ ${answers.useAuth ? `auth:
203
+ tokenExpiry: 7d
204
+ sessionExpiry: 30d
205
+ ` : ''}`;
206
+ file_generator_1.FileGenerator.writeFile(path.join(projectPath, 'config/fragment.yaml'), fragmentConfig);
207
+ // Generate .env.example
208
+ let envExample = `NODE_ENV=development
209
+ PORT=3000
210
+
211
+ ${this.getEnvTemplate(answers.database)}`;
212
+ if (answers.useOpenAI) {
213
+ envExample += '\nOPENAI_API_KEY=sk-your-openai-api-key';
214
+ }
215
+ file_generator_1.FileGenerator.writeFile(path.join(projectPath, '.env.example'), envExample);
216
+ // Generate .gitignore
217
+ const gitignore = `node_modules/
218
+ dist/
219
+ .env
220
+ *.log
221
+ .DS_Store
222
+ config/fragment.lock.yaml`;
223
+ file_generator_1.FileGenerator.writeFile(path.join(projectPath, '.gitignore'), gitignore);
224
+ // Generate README.md
225
+ const readme = this.generateReadme(answers.projectName, answers);
226
+ file_generator_1.FileGenerator.writeFile(path.join(projectPath, 'README.md'), readme);
227
+ spinner.text = 'Copying core framework files...';
228
+ // Copy all core files (decorators, container, config, etc.)
229
+ await this.copyFrameworkCore(projectPath, answers);
230
+ spinner.succeed('Project structure created');
231
+ // Install dependencies
232
+ const installSpinner = logger_1.CLILogger.spinner(`Installing dependencies with ${answers.packageManager}...`);
233
+ try {
234
+ (0, child_process_1.execSync)(`cd ${projectPath} && ${answers.packageManager} install`, {
235
+ stdio: 'pipe'
236
+ });
237
+ installSpinner.succeed('Dependencies installed');
238
+ }
239
+ catch (error) {
240
+ installSpinner.fail('Failed to install dependencies');
241
+ logger_1.CLILogger.warning('You can install them manually by running:');
242
+ console.log(` cd ${answers.projectName} && ${answers.packageManager} install`);
243
+ }
244
+ // Success message
245
+ logger_1.CLILogger.box('🎉 Project Created Successfully!', [
246
+ `Project: ${answers.projectName}`,
247
+ `Location: ${projectPath}`,
248
+ `Database: ${answers.database}`,
249
+ `OpenAI: ${answers.useOpenAI ? 'Enabled' : 'Disabled'}`,
250
+ `Auth: ${answers.useAuth ? 'Enabled' : 'Disabled'}`
251
+ ]);
252
+ console.log(chalk_1.default.bold('\nNext steps:'));
253
+ console.log(` 1. cd ${answers.projectName}`);
254
+ console.log(` 2. cp .env.example .env`);
255
+ console.log(` 3. Configure your database in .env`);
256
+ if (answers.useOpenAI) {
257
+ console.log(` 4. Add your OpenAI API key to .env`);
258
+ }
259
+ console.log(` ${answers.useOpenAI ? '5' : '4'}. ${answers.packageManager} run dev`);
260
+ logger_1.CLILogger.section('Available Commands:');
261
+ logger_1.CLILogger.table({
262
+ 'frg generate controller <name>': 'Generate a new controller',
263
+ 'frg generate service <name>': 'Generate a new service',
264
+ 'frg generate resource <name>': 'Generate controller, service, repository & entity',
265
+ 'frg config ai': 'Configure OpenAI settings',
266
+ 'frg migrate': 'Run database migrations',
267
+ 'frg serve': 'Start development server'
268
+ });
269
+ }
270
+ catch (error) {
271
+ spinner.fail('Failed to create project');
272
+ logger_1.CLILogger.error(error.message);
273
+ }
274
+ }
275
+ getDatabaseConfig(database) {
276
+ const configs = {
277
+ 'PostgreSQL': ` type: postgres
278
+ host: \${DB_HOST:localhost}
279
+ port: \${DB_PORT:5432}
280
+ username: \${DB_USERNAME:postgres}
281
+ password: \${DB_PASSWORD:postgres}
282
+ database: \${DB_DATABASE:fragment_db}
283
+ synchronize: true
284
+ logging: false`,
285
+ 'MySQL': ` type: mysql
286
+ host: \${DB_HOST:localhost}
287
+ port: \${DB_PORT:3306}
288
+ username: \${DB_USERNAME:root}
289
+ password: \${DB_PASSWORD:root}
290
+ database: \${DB_DATABASE:fragment_db}
291
+ synchronize: true
292
+ logging: false`,
293
+ 'SQLite': ` type: sqlite
294
+ database: \${DB_DATABASE:database.sqlite}
295
+ synchronize: true
296
+ logging: false`,
297
+ 'MongoDB': ` type: mongodb
298
+ host: \${DB_HOST:localhost}
299
+ port: \${DB_PORT:27017}
300
+ database: \${DB_DATABASE:fragment_db}
301
+ synchronize: true
302
+ logging: false`
303
+ };
304
+ return configs[database];
305
+ }
306
+ getEnvTemplate(database) {
307
+ if (database === 'SQLite') {
308
+ return 'DB_DATABASE=database.sqlite';
309
+ }
310
+ return `DB_HOST=localhost
311
+ DB_PORT=${database === 'PostgreSQL' ? '5432' : database === 'MySQL' ? '3306' : '27017'}
312
+ DB_USERNAME=${database === 'PostgreSQL' ? 'postgres' : 'root'}
313
+ DB_PASSWORD=${database === 'PostgreSQL' ? 'postgres' : 'root'}
314
+ DB_DATABASE=fragment_db`;
315
+ }
316
+ generateReadme(projectName, answers) {
317
+ return `# ${projectName}
318
+
319
+ A Fragment Framework application.
320
+
321
+ ## Getting Started
322
+
323
+ \`\`\`bash
324
+ # Install dependencies
325
+ ${answers.packageManager} install
326
+
327
+ # Configure environment
328
+ cp .env.example .env
329
+
330
+ # Start development server
331
+ ${answers.packageManager} run dev
332
+ \`\`\`
333
+
334
+ ## Fragment CLI Commands
335
+
336
+ \`\`\`bash
337
+ # Generate resources
338
+ frg generate controller <name> # Generate controller
339
+ frg generate service <name> # Generate service
340
+ frg generate repository <name> # Generate repository
341
+ frg generate entity <name> # Generate entity
342
+ frg generate resource <name> # Generate all of the above
343
+
344
+ # Configuration
345
+ frg config ai # Configure OpenAI settings
346
+ frg config db # Configure database settings
347
+
348
+ # Database
349
+ frg migrate # Run migrations
350
+
351
+ # Development
352
+ frg serve # Start development server
353
+ frg build # Build for production
354
+ \`\`\`
355
+
356
+ ## Project Structure
357
+
358
+ \`\`\`
359
+ src/
360
+ ├── controllers/ # HTTP request handlers
361
+ ├── services/ # Business logic
362
+ ├── repositories/ # Data access layer
363
+ ├── entities/ # Database models
364
+ ├── middlewares/ # Express middlewares
365
+ └── core/ # Framework core
366
+ \`\`\`
367
+
368
+ ## Documentation
369
+
370
+ Visit [Fragment Framework Documentation](https://fragment-framework.dev) for more information.
371
+ `;
372
+ }
373
+ async copyFrameworkCore(projectPath, answers) {
374
+ // This would copy all the core framework files
375
+ // For brevity, I'll show the structure
376
+ // In a real implementation, these would be actual file copies
377
+ logger_1.CLILogger.info('Core framework files copied');
378
+ }
379
+ }
380
+ exports.InitCommand = InitCommand;
@@ -0,0 +1,7 @@
1
+ export declare class MigrateCommand {
2
+ execute(action?: string): Promise<void>;
3
+ private runMigrations;
4
+ private generateMigration;
5
+ private revertMigration;
6
+ private showMigrations;
7
+ }
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MigrateCommand = void 0;
7
+ const child_process_1 = require("child_process");
8
+ const logger_1 = require("../utils/logger");
9
+ const inquirer_1 = __importDefault(require("inquirer"));
10
+ class MigrateCommand {
11
+ async execute(action) {
12
+ if (!action) {
13
+ const answer = await inquirer_1.default.prompt([
14
+ {
15
+ type: 'list',
16
+ name: 'action',
17
+ message: 'Select migration action:',
18
+ choices: [
19
+ { name: 'Run pending migrations', value: 'run' },
20
+ { name: 'Generate new migration', value: 'generate' },
21
+ { name: 'Revert last migration', value: 'revert' },
22
+ { name: 'Show migration status', value: 'show' }
23
+ ]
24
+ }
25
+ ]);
26
+ action = answer.action;
27
+ }
28
+ switch (action) {
29
+ case 'run':
30
+ await this.runMigrations();
31
+ break;
32
+ case 'generate':
33
+ await this.generateMigration();
34
+ break;
35
+ case 'revert':
36
+ await this.revertMigration();
37
+ break;
38
+ case 'show':
39
+ await this.showMigrations();
40
+ break;
41
+ default:
42
+ logger_1.CLILogger.error(`Unknown action: ${action}`);
43
+ }
44
+ }
45
+ async runMigrations() {
46
+ logger_1.CLILogger.title('📦 Running Migrations');
47
+ const spinner = logger_1.CLILogger.spinner('Executing migrations...');
48
+ try {
49
+ (0, child_process_1.execSync)('npm run typeorm migration:run', { stdio: 'pipe' });
50
+ spinner.succeed('Migrations executed successfully');
51
+ }
52
+ catch (error) {
53
+ spinner.fail('Migration failed');
54
+ logger_1.CLILogger.error(error.message);
55
+ }
56
+ }
57
+ async generateMigration() {
58
+ const answer = await inquirer_1.default.prompt([
59
+ {
60
+ type: 'input',
61
+ name: 'name',
62
+ message: 'Migration name:',
63
+ validate: (input) => {
64
+ if (!input)
65
+ return 'Name is required';
66
+ return true;
67
+ }
68
+ }
69
+ ]);
70
+ logger_1.CLILogger.title(`📝 Generating Migration: ${answer.name}`);
71
+ const spinner = logger_1.CLILogger.spinner('Creating migration file...');
72
+ try {
73
+ (0, child_process_1.execSync)(`npm run typeorm migration:generate -- -n ${answer.name}`, { stdio: 'pipe' });
74
+ spinner.succeed('Migration generated successfully');
75
+ }
76
+ catch (error) {
77
+ spinner.fail('Failed to generate migration');
78
+ logger_1.CLILogger.error(error.message);
79
+ }
80
+ }
81
+ async revertMigration() {
82
+ const confirm = await inquirer_1.default.prompt([
83
+ {
84
+ type: 'confirm',
85
+ name: 'confirmed',
86
+ message: 'Are you sure you want to revert the last migration?',
87
+ default: false
88
+ }
89
+ ]);
90
+ if (!confirm.confirmed) {
91
+ logger_1.CLILogger.info('Migration revert cancelled');
92
+ return;
93
+ }
94
+ logger_1.CLILogger.title('⏪ Reverting Migration');
95
+ const spinner = logger_1.CLILogger.spinner('Reverting last migration...');
96
+ try {
97
+ (0, child_process_1.execSync)('npm run typeorm migration:revert', { stdio: 'pipe' });
98
+ spinner.succeed('Migration reverted successfully');
99
+ }
100
+ catch (error) {
101
+ spinner.fail('Failed to revert migration');
102
+ logger_1.CLILogger.error(error.message);
103
+ }
104
+ }
105
+ async showMigrations() {
106
+ logger_1.CLILogger.title('📋 Migration Status');
107
+ try {
108
+ const output = (0, child_process_1.execSync)('npm run typeorm migration:show', { encoding: 'utf-8' });
109
+ console.log(output);
110
+ }
111
+ catch (error) {
112
+ logger_1.CLILogger.error('Failed to show migrations');
113
+ }
114
+ }
115
+ }
116
+ exports.MigrateCommand = MigrateCommand;
@@ -0,0 +1,6 @@
1
+ export declare class ServeCommand {
2
+ execute(options: {
3
+ port?: number;
4
+ watch?: boolean;
5
+ }): Promise<void>;
6
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ServeCommand = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const logger_1 = require("../utils/logger");
6
+ class ServeCommand {
7
+ async execute(options) {
8
+ logger_1.CLILogger.title('🚀 Starting Fragment Application');
9
+ const port = options.port || process.env.PORT || 3000;
10
+ const args = ['--respawn', '--transpile-only'];
11
+ if (options.watch !== false) {
12
+ args.push('--watch');
13
+ }
14
+ args.push('src/server.ts');
15
+ const env = { ...process.env, PORT: port.toString() };
16
+ logger_1.CLILogger.info(`Starting server on port ${port}...`);
17
+ const child = (0, child_process_1.spawn)('ts-node-dev', args, {
18
+ env,
19
+ stdio: 'inherit'
20
+ });
21
+ child.on('error', (error) => {
22
+ logger_1.CLILogger.error(`Failed to start server: ${error.message}`);
23
+ });
24
+ child.on('close', (code) => {
25
+ if (code !== 0) {
26
+ logger_1.CLILogger.error(`Server exited with code ${code}`);
27
+ }
28
+ });
29
+ }
30
+ }
31
+ exports.ServeCommand = ServeCommand;
@@ -0,0 +1 @@
1
+ export declare function controllerTemplate(name: string, route: string): string;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.controllerTemplate = controllerTemplate;
4
+ function controllerTemplate(name, route) {
5
+ const className = name.endsWith('Controller') ? name : `${name}Controller`;
6
+ const serviceName = name.replace('Controller', '') + 'Service';
7
+ return `import { Controller } from '../core/decorators/controller.decorator';
8
+ import { Get, Post, Put, Delete } from '../core/decorators/route.decorator';
9
+ import { Injectable } from '../core/decorators/injectable.decorator';
10
+ import { Autowire } from '../core/decorators/autowire.decorator';
11
+ import { ${serviceName} } from '../services/${name.toLowerCase()}.service';
12
+ import { Request, Response } from 'express';
13
+
14
+ @Controller('${route}')
15
+ @Injectable()
16
+ export class ${className} {
17
+ constructor(
18
+ @Autowire() private ${serviceName.charAt(0).toLowerCase() + serviceName.slice(1)}: ${serviceName}
19
+ ) {}
20
+
21
+ @Get('/')
22
+ async findAll(req: Request, res: Response) {
23
+ const items = await this.${serviceName.charAt(0).toLowerCase() + serviceName.slice(1)}.findAll();
24
+ return res.json(items);
25
+ }
26
+
27
+ @Get('/:id')
28
+ async findOne(req: Request, res: Response) {
29
+ const item = await this.${serviceName.charAt(0).toLowerCase() + serviceName.slice(1)}.findById(parseInt(req.params.id));
30
+ return res.json(item);
31
+ }
32
+
33
+ @Post('/')
34
+ async create(req: Request, res: Response) {
35
+ const item = await this.${serviceName.charAt(0).toLowerCase() + serviceName.slice(1)}.create(req.body);
36
+ return res.status(201).json(item);
37
+ }
38
+
39
+ @Put('/:id')
40
+ async update(req: Request, res: Response) {
41
+ const item = await this.${serviceName.charAt(0).toLowerCase() + serviceName.slice(1)}.update(parseInt(req.params.id), req.body);
42
+ return res.json(item);
43
+ }
44
+
45
+ @Delete('/:id')
46
+ async delete(req: Request, res: Response) {
47
+ await this.${serviceName.charAt(0).toLowerCase() + serviceName.slice(1)}.delete(parseInt(req.params.id));
48
+ return res.status(204).send();
49
+ }
50
+ }
51
+ `;
52
+ }
@@ -0,0 +1 @@
1
+ export declare function entityTemplate(name: string): string;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.entityTemplate = entityTemplate;
4
+ function entityTemplate(name) {
5
+ const className = name.endsWith('Entity') ? name.replace('Entity', '') : name;
6
+ return `import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
7
+
8
+ @Entity('${className.toLowerCase()}s')
9
+ export class ${className} {
10
+ @PrimaryGeneratedColumn()
11
+ id!: number;
12
+
13
+ @Column({ length: 255 })
14
+ name!: string;
15
+
16
+ @CreateDateColumn()
17
+ createdAt!: Date;
18
+
19
+ @UpdateDateColumn()
20
+ updatedAt!: Date;
21
+ }
22
+ `;
23
+ }
@@ -0,0 +1 @@
1
+ export declare function repositoryTemplate(name: string, entityName: string): string;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.repositoryTemplate = repositoryTemplate;
4
+ function repositoryTemplate(name, entityName) {
5
+ const className = name.endsWith('Repository') ? name : `${name}Repository`;
6
+ return `import { Repository as TypeORMRepository } from 'typeorm';
7
+ import { Repository } from '../core/decorators/repository.decorator';
8
+ import { ${entityName} } from '../entities/${entityName.toLowerCase()}.entity';
9
+ import { AppDataSource } from '../database/data-source';
10
+
11
+ @Repository()
12
+ export class ${className} {
13
+ private repository: TypeORMRepository<${entityName}>;
14
+
15
+ constructor() {
16
+ this.repository = AppDataSource.getRepository(${entityName});
17
+ }
18
+
19
+ async findAll(): Promise<${entityName}[]> {
20
+ return await this.repository.find();
21
+ }
22
+
23
+ async findById(id: number): Promise<${entityName} | null> {
24
+ return await this.repository.findOne({ where: { id } });
25
+ }
26
+
27
+ async create(data: Partial<${entityName}>): Promise<${entityName}> {
28
+ const entity = this.repository.create(data);
29
+ return await this.repository.save(entity);
30
+ }
31
+
32
+ async update(id: number, data: Partial<${entityName}>): Promise<${entityName} | null> {
33
+ await this.repository.update(id, data);
34
+ return await this.findById(id);
35
+ }
36
+
37
+ async delete(id: number): Promise<boolean> {
38
+ const result = await this.repository.delete(id);
39
+ return result.affected ? result.affected > 0 : false;
40
+ }
41
+ }
42
+ `;
43
+ }
@@ -0,0 +1 @@
1
+ export declare function serviceTemplate(name: string): string;