fragment-ts 1.0.17 → 1.0.18

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 (33) hide show
  1. package/SETUP.md +570 -0
  2. package/changes/1.md +420 -0
  3. package/dist/cli/commands/init.command.js +4 -4
  4. package/dist/cli/commands/init.command.js.map +1 -1
  5. package/dist/cli/commands/test.command.d.ts +6 -0
  6. package/dist/cli/commands/test.command.d.ts.map +1 -0
  7. package/dist/cli/commands/test.command.js +311 -0
  8. package/dist/cli/commands/test.command.js.map +1 -0
  9. package/dist/cli/index.js +6 -3
  10. package/dist/cli/index.js.map +1 -1
  11. package/dist/core/container/di-container.d.ts +5 -0
  12. package/dist/core/container/di-container.d.ts.map +1 -1
  13. package/dist/core/container/di-container.js +121 -21
  14. package/dist/core/container/di-container.js.map +1 -1
  15. package/dist/core/decorators/controller.decorator.js +5 -5
  16. package/dist/core/decorators/injection.decorators.d.ts +44 -1
  17. package/dist/core/decorators/injection.decorators.d.ts.map +1 -1
  18. package/dist/core/decorators/injection.decorators.js +92 -1
  19. package/dist/core/decorators/injection.decorators.js.map +1 -1
  20. package/dist/core/metadata/metadata-keys.d.ts +29 -17
  21. package/dist/core/metadata/metadata-keys.d.ts.map +1 -1
  22. package/dist/core/metadata/metadata-keys.js +35 -17
  23. package/dist/core/metadata/metadata-keys.js.map +1 -1
  24. package/package.json +1 -1
  25. package/src/cli/commands/init.command.ts +4 -4
  26. package/src/cli/commands/test.command.ts +289 -0
  27. package/src/cli/index.ts +16 -11
  28. package/src/core/container/di-container.ts +166 -31
  29. package/src/core/decorators/DECORATOR_USAGE.md +326 -0
  30. package/src/core/decorators/controller.decorator.ts +9 -9
  31. package/src/core/decorators/injection.decorators.ts +129 -5
  32. package/src/core/metadata/metadata-keys.ts +44 -18
  33. package/src/testing/TEST.md +321 -0
package/SETUP.md ADDED
@@ -0,0 +1,570 @@
1
+ # Fragment Framework - Complete Setup Guide
2
+
3
+ ## Overview
4
+
5
+ Fragment is a TypeScript framework inspired by Spring Boot that provides:
6
+ - Dependency Injection with decorators
7
+ - TypeORM integration
8
+ - RESTful API support
9
+ - Built-in testing framework
10
+ - CLI tools for development
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install fragment-ts reflect-metadata typeorm
16
+ ```
17
+
18
+ ## Project Setup
19
+
20
+ ### 1. Initialize Project
21
+
22
+ ```bash
23
+ fragment init
24
+ ```
25
+
26
+ This creates:
27
+ ```
28
+ project/
29
+ ├── src/
30
+ │ ├── app.ts
31
+ │ ├── controllers/
32
+ │ ├── services/
33
+ │ ├── repositories/
34
+ │ └── entities/
35
+ ├── fragment.json
36
+ ├── tsconfig.json
37
+ └── package.json
38
+ ```
39
+
40
+ ### 2. Configure tsconfig.json
41
+
42
+ ```json
43
+ {
44
+ "compilerOptions": {
45
+ "target": "ES2020",
46
+ "module": "commonjs",
47
+ "lib": ["ES2020"],
48
+ "experimentalDecorators": true,
49
+ "emitDecoratorMetadata": true,
50
+ "outDir": "./dist",
51
+ "rootDir": "./src",
52
+ "strict": true,
53
+ "esModuleInterop": true,
54
+ "skipLibCheck": true,
55
+ "forceConsistentCasingInFileNames": true
56
+ },
57
+ "include": ["src/**/*"],
58
+ "exclude": ["node_modules", "dist"]
59
+ }
60
+ ```
61
+
62
+ ### 3. Configure fragment.json
63
+
64
+ ```json
65
+ {
66
+ "port": 3000,
67
+ "host": "0.0.0.0",
68
+ "database": {
69
+ "type": "postgres",
70
+ "host": "${DB_HOST:localhost}",
71
+ "port": 5432,
72
+ "username": "${DB_USER:postgres}",
73
+ "password": "${DB_PASSWORD}",
74
+ "database": "${DB_NAME:myapp}",
75
+ "entities": ["dist/**/*.entity.js"],
76
+ "synchronize": false,
77
+ "logging": false
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### 4. Create .env file
83
+
84
+ ```bash
85
+ DB_HOST=localhost
86
+ DB_USER=postgres
87
+ DB_PASSWORD=secret
88
+ DB_NAME=myapp
89
+ EMAIL_FROM=noreply@example.com
90
+ EMAIL_ENABLED=true
91
+ MAX_USERS=1000
92
+ ```
93
+
94
+ ## Available Decorators
95
+
96
+ ### Class Decorators
97
+
98
+ #### @FragmentApplication
99
+ Application entry point decorator.
100
+
101
+ ```typescript
102
+ @FragmentApplication({
103
+ port: 3000,
104
+ host: '0.0.0.0',
105
+ })
106
+ export class App {}
107
+ ```
108
+
109
+ #### @Controller
110
+ Defines a REST controller.
111
+
112
+ ```typescript
113
+ @Controller('/api/users')
114
+ export class UserController {
115
+ // Routes defined here
116
+ }
117
+ ```
118
+
119
+ #### @Service
120
+ Business logic layer.
121
+
122
+ ```typescript
123
+ @Service()
124
+ export class UserService {
125
+ // Service methods
126
+ }
127
+ ```
128
+
129
+ #### @Repository
130
+ Data access layer.
131
+
132
+ ```typescript
133
+ @Repository()
134
+ export class UserRepository {
135
+ @InjectRepository(User)
136
+ private repo!: Repository<User>;
137
+ }
138
+ ```
139
+
140
+ #### @Injectable
141
+ General purpose injectable component.
142
+
143
+ ```typescript
144
+ @Injectable()
145
+ export class EmailService {
146
+ // Utility methods
147
+ }
148
+ ```
149
+
150
+ #### @AutoConfiguration
151
+ Auto-configuration component (conditional beans).
152
+
153
+ ```typescript
154
+ @AutoConfiguration()
155
+ @ConditionalOnProperty('REDIS_ENABLED', 'true')
156
+ export class RedisConfig {
157
+ // Redis setup
158
+ }
159
+ ```
160
+
161
+ ### Property Decorators
162
+
163
+ #### @Autowired
164
+ Automatic dependency injection by type.
165
+
166
+ ```typescript
167
+ @Service()
168
+ export class UserService {
169
+ @Autowired()
170
+ private userRepository!: UserRepository;
171
+
172
+ @Autowired()
173
+ private emailService!: EmailService;
174
+ }
175
+ ```
176
+
177
+ #### @InjectRepository
178
+ Inject TypeORM repository.
179
+
180
+ ```typescript
181
+ @Repository()
182
+ export class UserRepository {
183
+ @InjectRepository(User)
184
+ private userRepo!: Repository<User>;
185
+ }
186
+ ```
187
+
188
+ #### @Value
189
+ Inject configuration values from environment.
190
+
191
+ ```typescript
192
+ @Service()
193
+ export class AppService {
194
+ @Value('${PORT:3000}')
195
+ private port!: number;
196
+
197
+ @Value('${API_KEY}')
198
+ private apiKey!: string;
199
+ }
200
+ ```
201
+
202
+ #### @Inject
203
+ Inject dependency by token.
204
+
205
+ ```typescript
206
+ @Service()
207
+ export class MyService {
208
+ @Inject('DATABASE_CONNECTION')
209
+ private db!: DatabaseConnection;
210
+ }
211
+ ```
212
+
213
+ #### @Qualifier
214
+ Specify which bean to inject.
215
+
216
+ ```typescript
217
+ @Service()
218
+ export class MyService {
219
+ @Qualifier('primary')
220
+ @Autowired()
221
+ private cache!: CacheService;
222
+ }
223
+ ```
224
+
225
+ ### Method Decorators
226
+
227
+ #### HTTP Method Decorators
228
+ Route handlers: `@Get`, `@Post`, `@Put`, `@Delete`, `@Patch`
229
+
230
+ ```typescript
231
+ @Controller('/api/users')
232
+ export class UserController {
233
+ @Get('/')
234
+ getAllUsers() {
235
+ return { users: [] };
236
+ }
237
+
238
+ @Get('/:id')
239
+ getUserById(@Param('id') id: string) {
240
+ return { id };
241
+ }
242
+
243
+ @Post('/')
244
+ createUser(@Body() data: any) {
245
+ return { created: true };
246
+ }
247
+ }
248
+ ```
249
+
250
+ #### @PostConstruct
251
+ Called after dependency injection.
252
+
253
+ ```typescript
254
+ @Service()
255
+ export class MyService {
256
+ @PostConstruct()
257
+ init() {
258
+ console.log('Service initialized');
259
+ }
260
+ }
261
+ ```
262
+
263
+ #### @PreDestroy
264
+ Called before bean destruction.
265
+
266
+ ```typescript
267
+ @Service()
268
+ export class MyService {
269
+ @PreDestroy()
270
+ cleanup() {
271
+ console.log('Cleaning up resources');
272
+ }
273
+ }
274
+ ```
275
+
276
+ ### Parameter Decorators
277
+
278
+ #### @Body
279
+ Extract request body.
280
+
281
+ ```typescript
282
+ @Post('/')
283
+ createUser(@Body() userData: CreateUserDto) {
284
+ // userData contains request body
285
+ }
286
+ ```
287
+
288
+ #### @Param
289
+ Extract route parameter.
290
+
291
+ ```typescript
292
+ @Get('/:id')
293
+ getUser(@Param('id') id: string) {
294
+ // id from route parameter
295
+ }
296
+ ```
297
+
298
+ #### @Query
299
+ Extract query parameter.
300
+
301
+ ```typescript
302
+ @Get('/')
303
+ getUsers(@Query('page') page: string, @Query('limit') limit: string) {
304
+ // page and limit from query string
305
+ }
306
+ ```
307
+
308
+ #### @Header
309
+ Extract header value.
310
+
311
+ ```typescript
312
+ @Get('/')
313
+ getData(@Header('authorization') auth: string) {
314
+ // auth from Authorization header
315
+ }
316
+ ```
317
+
318
+ #### @Req, @Res
319
+ Access raw request/response objects.
320
+
321
+ ```typescript
322
+ @Get('/')
323
+ getData(@Req() req: Request, @Res() res: Response) {
324
+ // Full Express request/response
325
+ }
326
+ ```
327
+
328
+ ## CLI Commands
329
+
330
+ ### Development
331
+
332
+ ```bash
333
+ # Start development server (watches TypeScript files)
334
+ fragment serve
335
+
336
+ # Or with specific host/port
337
+ fragment serve --host 0.0.0.0 --port 3000
338
+ ```
339
+
340
+ ### Build
341
+
342
+ ```bash
343
+ # Compile TypeScript to JavaScript
344
+ fragment build
345
+
346
+ # Build and watch for changes
347
+ fragment build --watch
348
+ ```
349
+
350
+ ### Testing
351
+
352
+ ```bash
353
+ # Run all tests
354
+ fragment test
355
+
356
+ # Run tests in watch mode
357
+ fragment test --watch
358
+
359
+ # Run specific test pattern
360
+ fragment test --pattern "**/*.spec.ts"
361
+
362
+ # Run tests in production mode (compiled)
363
+ fragment test --env prod
364
+ ```
365
+
366
+ ### Database Migrations
367
+
368
+ ```bash
369
+ # Generate migration
370
+ fragment migrate:generate CreateUsers
371
+
372
+ # Run migrations
373
+ fragment migrate:run
374
+
375
+ # Revert last migration
376
+ fragment migrate:revert
377
+
378
+ # Show migration status
379
+ fragment migrate:show
380
+ ```
381
+
382
+ ### Diagnostics
383
+
384
+ ```bash
385
+ # List all routes
386
+ fragment routes
387
+
388
+ # List all beans (components)
389
+ fragment beans
390
+
391
+ # Show as tree
392
+ fragment beans --tree
393
+
394
+ # Show application info
395
+ fragment info
396
+
397
+ # Show configuration
398
+ fragment config
399
+
400
+ # Show version
401
+ fragment version
402
+ ```
403
+
404
+ ### Code Generation
405
+
406
+ ```bash
407
+ # Generate controller
408
+ fragment generate controller User
409
+
410
+ # Generate service
411
+ fragment generate service User
412
+
413
+ # Generate repository
414
+ fragment generate repository User
415
+
416
+ # Generate entity
417
+ fragment generate entity User
418
+
419
+ # Generate complete CRUD module
420
+ fragment generate module User
421
+ ```
422
+
423
+ ## Testing Guide
424
+
425
+ ### Writing Tests
426
+
427
+ Create test files with `.spec.ts` extension:
428
+
429
+ ```typescript
430
+ // user.service.spec.ts
431
+ import 'reflect-metadata';
432
+ import { UserService } from './user.service';
433
+ import { DIContainer } from 'fragment-ts';
434
+
435
+ describe('UserService', () => {
436
+ let service: UserService;
437
+ let container: DIContainer;
438
+
439
+ beforeEach(() => {
440
+ container = DIContainer.getInstance();
441
+ container.reset();
442
+ service = container.resolve(UserService);
443
+ });
444
+
445
+ it('should create user', async () => {
446
+ const user = await service.createUser({
447
+ name: 'Test',
448
+ email: 'test@example.com'
449
+ });
450
+
451
+ expect(user.name).toBe('Test');
452
+ expect(user.email).toBe('test@example.com');
453
+ });
454
+ });
455
+ ```
456
+
457
+ ### Test Functions
458
+
459
+ - `describe(name, fn)` - Test suite
460
+ - `it(name, fn)` - Test case
461
+ - `expect(value)` - Assertion
462
+ - `.toBe(expected)` - Strict equality
463
+ - `.toEqual(expected)` - Deep equality
464
+ - `.toBeTruthy()` - Truthy check
465
+ - `.toBeFalsy()` - Falsy check
466
+ - `.toThrow()` - Function throws
467
+ - `.toBeInstanceOf(class)` - Instance check
468
+ - `.toContain(value)` - Array/string contains
469
+ - `.toHaveProperty(prop, value?)` - Object has property
470
+ - `.toBeNull()` - Null check
471
+ - `.toBeUndefined()` - Undefined check
472
+ - `.toHaveLength(n)` - Length check
473
+
474
+ ## Troubleshooting
475
+
476
+ ### @Autowired not working
477
+
478
+ **Problem:** Properties are undefined after injection.
479
+
480
+ **Solution:**
481
+ 1. Ensure `emitDecoratorMetadata: true` in tsconfig.json
482
+ 2. Import `reflect-metadata` at app entry point
483
+ 3. Make sure the dependency is registered in DI container
484
+ 4. Check that decorators are applied in correct order
485
+
486
+ ```typescript
487
+ import 'reflect-metadata'; // Add this at the top of main file
488
+
489
+ @Service() // Must be before class
490
+ export class MyService {
491
+ @Autowired() // Property decorator
492
+ private dep!: MyDependency; // Use ! for definite assignment
493
+ }
494
+ ```
495
+
496
+ ### TypeORM Repository not injected
497
+
498
+ **Problem:** Repository is undefined in @Repository classes.
499
+
500
+ **Solution:**
501
+ 1. Make sure TypeORM is initialized before app bootstrap
502
+ 2. Use @InjectRepository with the entity class
503
+ 3. Entity must be decorated with @Entity
504
+
505
+ ```typescript
506
+ @Entity()
507
+ export class User {
508
+ @PrimaryGeneratedColumn()
509
+ id!: number;
510
+ }
511
+
512
+ @Repository()
513
+ export class UserRepository {
514
+ @InjectRepository(User) // Pass entity class
515
+ private repo!: Repository<User>;
516
+ }
517
+ ```
518
+
519
+ ### Tests not running
520
+
521
+ **Problem:** `fragment test` finds no tests.
522
+
523
+ **Solution:**
524
+ 1. Test files must end with `.spec.ts`
525
+ 2. Place tests in `src/` directory
526
+ 3. Use correct test pattern: `--pattern "**/*.spec.ts"`
527
+
528
+ ### Environment variables not loading
529
+
530
+ **Problem:** @Value decorator returns empty string.
531
+
532
+ **Solution:**
533
+ 1. Create `.env` file in project root
534
+ 2. Use correct syntax: `${VAR_NAME}` or `${VAR_NAME:default}`
535
+ 3. Install dotenv: `npm install dotenv`
536
+
537
+ ## Best Practices
538
+
539
+ 1. **Single Responsibility** - Each service should have one clear purpose
540
+ 2. **Dependency Injection** - Use @Autowired instead of creating instances
541
+ 3. **Type Safety** - Always define types for method parameters and returns
542
+ 4. **Error Handling** - Use try-catch blocks in controllers
543
+ 5. **Testing** - Write tests for all services and repositories
544
+ 6. **Environment Config** - Never hardcode secrets, use .env files
545
+ 7. **Migrations** - Always use migrations, never synchronize in production
546
+
547
+ ## Example Project Structure
548
+
549
+ ```
550
+ my-app/
551
+ ├── src/
552
+ │ ├── app.ts # Application entry
553
+ │ ├── entities/
554
+ │ │ └── user.entity.ts # TypeORM entities
555
+ │ ├── repositories/
556
+ │ │ └── user.repository.ts # Data access layer
557
+ │ ├── services/
558
+ │ │ ├── user.service.ts # Business logic
559
+ │ │ └── email.service.ts # Utilities
560
+ │ ├── controllers/
561
+ │ │ └── user.controller.ts # REST endpoints
562
+ │ └── __tests__/
563
+ │ └── user.service.spec.ts # Tests
564
+ ├── dist/ # Compiled output
565
+ ├── migrations/ # Database migrations
566
+ ├── .env # Environment variables
567
+ ├── fragment.json # Framework config
568
+ ├── tsconfig.json # TypeScript config
569
+ └── package.json # Dependencies
570
+ ```