@el-j/magic-helix-plugins 4.0.0-beta.1 → 4.0.0-beta.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 (120) hide show
  1. package/dist/architecture/codeowners.md +123 -0
  2. package/dist/architecture/monorepo.md +146 -0
  3. package/dist/architecture/nx.md +122 -0
  4. package/dist/architecture/turborepo.md +114 -0
  5. package/dist/ci/github-actions.md +268 -0
  6. package/dist/ci/gitlab-ci.md +330 -0
  7. package/dist/containers/docker-multistage.md +120 -0
  8. package/dist/containers/kubernetes-deploy.md +210 -0
  9. package/dist/cpp/index.cjs +79 -0
  10. package/dist/cpp/index.mjs +209 -0
  11. package/dist/csharp/index.cjs +2 -2
  12. package/dist/csharp/{index.js → index.mjs} +17 -11
  13. package/dist/csharp/templates/framework-aspnetcore.md +205 -0
  14. package/dist/csharp/templates/framework-blazor.md +271 -0
  15. package/dist/csharp/templates/lang-csharp.md +162 -0
  16. package/dist/devops/docker-compose.md +111 -0
  17. package/dist/devops/docker-dockerfile.md +94 -0
  18. package/dist/devops/github-actions.md +160 -0
  19. package/dist/devops/gitlab-ci.md +210 -0
  20. package/dist/generic/lang-typescript.md +57 -0
  21. package/dist/generic/state-redux.md +21 -0
  22. package/dist/generic/state-rxjs.md +6 -0
  23. package/dist/generic/style-mui.md +23 -0
  24. package/dist/generic/style-tailwind.md +76 -0
  25. package/dist/generic/test-cypress.md +21 -0
  26. package/dist/generic/test-jest.md +20 -0
  27. package/dist/generic/test-playwright.md +21 -0
  28. package/dist/generic/test-vitest.md +131 -0
  29. package/dist/go/index.cjs +3 -3
  30. package/dist/go/{index.js → index.mjs} +18 -15
  31. package/dist/go/templates/lang-go.md +571 -0
  32. package/dist/index.cjs +1 -1
  33. package/dist/index.mjs +24 -0
  34. package/dist/java/index.cjs +2 -2
  35. package/dist/java/{index.js → index.mjs} +25 -19
  36. package/dist/java/templates/build-gradle.md +102 -0
  37. package/dist/java/templates/build-maven.md +86 -0
  38. package/dist/java/templates/framework-spring-boot.md +179 -0
  39. package/dist/java/templates/lang-java.md +78 -0
  40. package/dist/java/templates/lang-kotlin.md +88 -0
  41. package/dist/meta/magic-helix-meta.md +213 -0
  42. package/dist/meta/meta-debug.md +459 -0
  43. package/dist/meta/meta-implement.md +450 -0
  44. package/dist/meta/meta-roadmap.md +265 -0
  45. package/dist/nodejs/templates/angular-core.md +19 -0
  46. package/dist/nodejs/templates/lang-typescript.md +57 -0
  47. package/dist/nodejs/templates/nestjs-core.md +7 -0
  48. package/dist/nodejs/templates/react-core.md +677 -0
  49. package/dist/nodejs/templates/react-zustand.md +7 -0
  50. package/dist/nodejs/templates/state-redux.md +21 -0
  51. package/dist/nodejs/templates/state-rxjs.md +6 -0
  52. package/dist/nodejs/templates/style-primevue.md +6 -0
  53. package/dist/nodejs/templates/style-quasar.md +22 -0
  54. package/dist/nodejs/templates/style-tailwind.md +76 -0
  55. package/dist/nodejs/templates/test-cypress.md +21 -0
  56. package/dist/nodejs/templates/test-jest.md +20 -0
  57. package/dist/nodejs/templates/test-playwright.md +21 -0
  58. package/dist/nodejs/templates/test-vitest.md +131 -0
  59. package/dist/nodejs/templates/vue-core.md +108 -0
  60. package/dist/nodejs/templates/vue-pinia.md +5 -0
  61. package/dist/patterns/architecture/clean-architecture.md +469 -0
  62. package/dist/patterns/architecture/dependency-injection.md +517 -0
  63. package/dist/patterns/architecture/domain-driven-design.md +621 -0
  64. package/dist/patterns/architecture/layered-architecture.md +382 -0
  65. package/dist/patterns/architecture/repository-pattern.md +408 -0
  66. package/dist/patterns/domain-expertise/nextjs-rules.md +115 -0
  67. package/dist/patterns/domain-expertise/react-patterns.md +181 -0
  68. package/dist/patterns/domain-expertise/server-components.md +212 -0
  69. package/dist/patterns/domain-expertise/shadcn-ui.md +52 -0
  70. package/dist/patterns/domain-expertise/tailwind-patterns.md +52 -0
  71. package/dist/patterns/environment/container-awareness.md +17 -0
  72. package/dist/patterns/environment/ide-features.md +17 -0
  73. package/dist/patterns/environment/os-commands.md +17 -0
  74. package/dist/patterns/organization/heading-hierarchy.md +103 -0
  75. package/dist/patterns/organization/sequential-workflows.md +102 -0
  76. package/dist/patterns/organization/xml-rule-groups.md +64 -0
  77. package/dist/patterns/reasoning/agent-loop.md +151 -0
  78. package/dist/patterns/reasoning/confirmation-gates.md +141 -0
  79. package/dist/patterns/reasoning/dependency-analysis.md +132 -0
  80. package/dist/patterns/reasoning/one-tool-per-iteration.md +152 -0
  81. package/dist/patterns/reasoning/preview-before-action.md +194 -0
  82. package/dist/patterns/reasoning/reflection-checkpoints.md +166 -0
  83. package/dist/patterns/reasoning/result-verification.md +157 -0
  84. package/dist/patterns/reasoning/subtask-breakdown.md +131 -0
  85. package/dist/patterns/reasoning/thinking-tags.md +100 -0
  86. package/dist/patterns/role-definition/capability-declarations.md +72 -0
  87. package/dist/patterns/role-definition/expert-identity.md +45 -0
  88. package/dist/patterns/role-definition/scope-boundaries.md +61 -0
  89. package/dist/patterns/safety/code-safety-rules.md +17 -0
  90. package/dist/patterns/safety/credential-handling.md +17 -0
  91. package/dist/patterns/safety/destructive-warnings.md +17 -0
  92. package/dist/patterns/safety/refusal-messages.md +17 -0
  93. package/dist/patterns/tone/adaptive-tone.md +17 -0
  94. package/dist/patterns/tone/concise-communication.md +17 -0
  95. package/dist/patterns/tone/forbidden-phrases.md +17 -0
  96. package/dist/patterns/tool-guidelines/function-schemas.md +143 -0
  97. package/dist/patterns/tool-guidelines/parameter-examples.md +137 -0
  98. package/dist/patterns/tool-guidelines/usage-policies.md +105 -0
  99. package/dist/php/index.cjs +2 -2
  100. package/dist/php/{index.js → index.mjs} +12 -6
  101. package/dist/php/templates/framework-laravel.md +112 -0
  102. package/dist/php/templates/lang-php.md +94 -0
  103. package/dist/python/index.cjs +4 -4
  104. package/dist/python/{index.js → index.mjs} +10 -7
  105. package/dist/python/templates/lang-python.md +508 -0
  106. package/dist/ruby/index.cjs +2 -2
  107. package/dist/ruby/{index.js → index.mjs} +16 -10
  108. package/dist/ruby/templates/framework-rails.md +309 -0
  109. package/dist/ruby/templates/framework-sinatra.md +227 -0
  110. package/dist/ruby/templates/lang-ruby.md +216 -0
  111. package/dist/rust/index.cjs +3 -3
  112. package/dist/rust/{index.js → index.mjs} +24 -18
  113. package/dist/rust/templates/lang-rust.md +89 -0
  114. package/dist/swift/index.cjs +32 -0
  115. package/dist/swift/index.mjs +112 -0
  116. package/dist/swift/templates/framework-vapor.md +352 -0
  117. package/dist/swift/templates/lang-swift.md +291 -0
  118. package/package.json +31 -21
  119. package/dist/index.js +0 -20
  120. /package/dist/nodejs/{index.js → index.mjs} +0 -0
@@ -0,0 +1,517 @@
1
+ # Dependency Injection Pattern
2
+
3
+ ## Purpose
4
+ Remove hard dependencies between components. Inject dependencies from outside rather than creating them internally. Improves testability, flexibility, and maintainability.
5
+
6
+ ## Core Principle
7
+
8
+ **"Don't create dependencies, receive them."**
9
+
10
+ ```typescript
11
+ // ❌ Bad: Hard dependency (tight coupling)
12
+ class UserService {
13
+ private repository = new PostgresUserRepository(); // Creates its own dependency
14
+
15
+ async getUser(id: string) {
16
+ return this.repository.findById(id);
17
+ }
18
+ }
19
+
20
+ // ✅ Good: Dependency injection (loose coupling)
21
+ class UserService {
22
+ constructor(private repository: IUserRepository) {} // Receives dependency
23
+
24
+ async getUser(id: string) {
25
+ return this.repository.findById(id);
26
+ }
27
+ }
28
+ ```
29
+
30
+ ## Dependency Injection Methods
31
+
32
+ ### 1. Constructor Injection (Recommended)
33
+
34
+ ```typescript
35
+ // ✅ Inject dependencies via constructor
36
+ export class OrderService {
37
+ constructor(
38
+ private orderRepository: IOrderRepository,
39
+ private paymentService: IPaymentService,
40
+ private emailService: IEmailService
41
+ ) {}
42
+
43
+ async createOrder(items: Item[]): Promise<Order> {
44
+ const order = new Order(items);
45
+ await this.orderRepository.save(order);
46
+ await this.paymentService.charge(order.total);
47
+ await this.emailService.sendOrderConfirmation(order);
48
+ return order;
49
+ }
50
+ }
51
+
52
+ // Usage (manual wiring)
53
+ const orderService = new OrderService(
54
+ new PostgresOrderRepository(db),
55
+ new StripePaymentService(apiKey),
56
+ new SendGridEmailService(sendGridKey)
57
+ );
58
+ ```
59
+
60
+ **Pros:**
61
+ - Dependencies are explicit and immutable
62
+ - Easy to test (pass mocks in constructor)
63
+ - Compiler enforces all dependencies are provided
64
+
65
+ ### 2. Property Injection
66
+
67
+ ```typescript
68
+ // ⚠️ Less common: Inject via properties
69
+ export class UserService {
70
+ public repository!: IUserRepository; // Set externally
71
+
72
+ async getUser(id: string) {
73
+ return this.repository.findById(id);
74
+ }
75
+ }
76
+
77
+ // Usage
78
+ const service = new UserService();
79
+ service.repository = new PostgresUserRepository(db);
80
+ ```
81
+
82
+ **Pros:**
83
+ - Optional dependencies
84
+ - Circular dependency resolution
85
+
86
+ **Cons:**
87
+ - Dependencies not explicit
88
+ - Can forget to set properties
89
+ - Harder to test
90
+
91
+ ### 3. Method Injection
92
+
93
+ ```typescript
94
+ // ⚠️ Rare: Inject per method call
95
+ export class ReportGenerator {
96
+ generateReport(data: Data, formatter: IReportFormatter): string {
97
+ return formatter.format(data);
98
+ }
99
+ }
100
+
101
+ // Usage
102
+ const generator = new ReportGenerator();
103
+ const pdf = generator.generateReport(data, new PdfFormatter());
104
+ const excel = generator.generateReport(data, new ExcelFormatter());
105
+ ```
106
+
107
+ **Use when:** Dependency varies per call
108
+
109
+ ## Inversion of Control (IoC) Containers
110
+
111
+ ### Manual Wiring (Simple Projects)
112
+
113
+ ```typescript
114
+ // ✅ composition-root.ts - Wire dependencies manually
115
+ export function createApp() {
116
+ // Infrastructure
117
+ const db = new PostgresDatabase(config.dbUrl);
118
+ const redis = new Redis(config.redisUrl);
119
+
120
+ // Repositories
121
+ const userRepo = new PostgresUserRepository(db);
122
+ const orderRepo = new PostgresOrderRepository(db);
123
+
124
+ // Services
125
+ const emailService = new SendGridEmailService(config.sendGridKey);
126
+ const paymentService = new StripePaymentService(config.stripeKey);
127
+
128
+ // Use Cases / Services
129
+ const userService = new UserService(userRepo, emailService);
130
+ const orderService = new OrderService(orderRepo, paymentService, emailService);
131
+
132
+ // Controllers
133
+ const userController = new UserController(userService);
134
+ const orderController = new OrderController(orderService);
135
+
136
+ return {
137
+ userController,
138
+ orderController,
139
+ };
140
+ }
141
+ ```
142
+
143
+ ### IoC Container (Larger Projects)
144
+
145
+ #### TypeScript with InversifyJS
146
+
147
+ ```typescript
148
+ import { Container, injectable, inject } from 'inversify';
149
+ import 'reflect-metadata';
150
+
151
+ // ✅ Define identifiers
152
+ const TYPES = {
153
+ UserRepository: Symbol.for('IUserRepository'),
154
+ EmailService: Symbol.for('IEmailService'),
155
+ UserService: Symbol.for('UserService'),
156
+ };
157
+
158
+ // ✅ Mark classes as injectable
159
+ @injectable()
160
+ class PostgresUserRepository implements IUserRepository {
161
+ constructor(@inject(TYPES.Database) private db: Database) {}
162
+ // ...
163
+ }
164
+
165
+ @injectable()
166
+ class SendGridEmailService implements IEmailService {
167
+ // ...
168
+ }
169
+
170
+ @injectable()
171
+ class UserService {
172
+ constructor(
173
+ @inject(TYPES.UserRepository) private userRepo: IUserRepository,
174
+ @inject(TYPES.EmailService) private emailService: IEmailService
175
+ ) {}
176
+ // ...
177
+ }
178
+
179
+ // ✅ Configure container
180
+ const container = new Container();
181
+ container.bind<IUserRepository>(TYPES.UserRepository).to(PostgresUserRepository);
182
+ container.bind<IEmailService>(TYPES.EmailService).to(SendGridEmailService);
183
+ container.bind<UserService>(TYPES.UserService).to(UserService);
184
+
185
+ // ✅ Resolve dependencies
186
+ const userService = container.get<UserService>(TYPES.UserService);
187
+ ```
188
+
189
+ #### NestJS (Built-in DI)
190
+
191
+ ```typescript
192
+ // ✅ NestJS uses decorators for DI
193
+ @Injectable()
194
+ export class UserService {
195
+ constructor(
196
+ @Inject('IUserRepository') private userRepo: IUserRepository,
197
+ private emailService: EmailService // Auto-resolves by type
198
+ ) {}
199
+ }
200
+
201
+ // ✅ Register in module
202
+ @Module({
203
+ providers: [
204
+ UserService,
205
+ EmailService,
206
+ {
207
+ provide: 'IUserRepository',
208
+ useClass: PostgresUserRepository,
209
+ },
210
+ ],
211
+ })
212
+ export class UserModule {}
213
+ ```
214
+
215
+ #### Python with dependency-injector
216
+
217
+ ```python
218
+ from dependency_injector import containers, providers
219
+
220
+ # ✅ Define container
221
+ class Container(containers.DeclarativeContainer):
222
+ config = providers.Configuration()
223
+
224
+ # Infrastructure
225
+ database = providers.Singleton(
226
+ PostgresDatabase,
227
+ connection_string=config.db_url
228
+ )
229
+
230
+ # Repositories
231
+ user_repository = providers.Factory(
232
+ PostgresUserRepository,
233
+ db=database
234
+ )
235
+
236
+ # Services
237
+ email_service = providers.Singleton(
238
+ SendGridEmailService,
239
+ api_key=config.sendgrid_key
240
+ )
241
+
242
+ user_service = providers.Factory(
243
+ UserService,
244
+ user_repository=user_repository,
245
+ email_service=email_service
246
+ )
247
+
248
+ # ✅ Usage
249
+ container = Container()
250
+ container.config.from_yaml('config.yaml')
251
+
252
+ user_service = container.user_service()
253
+ ```
254
+
255
+ #### Go (Manual DI recommended)
256
+
257
+ ```go
258
+ // ✅ Go uses explicit dependency passing
259
+ type UserService struct {
260
+ userRepo UserRepository
261
+ emailService EmailService
262
+ }
263
+
264
+ func NewUserService(repo UserRepository, email EmailService) *UserService {
265
+ return &UserService{
266
+ userRepo: repo,
267
+ emailService: email,
268
+ }
269
+ }
270
+
271
+ // ✅ Wire dependencies in main
272
+ func main() {
273
+ db := postgres.NewDatabase(connString)
274
+ userRepo := postgres.NewUserRepository(db)
275
+ emailService := sendgrid.NewEmailService(apiKey)
276
+
277
+ userService := NewUserService(userRepo, emailService)
278
+
279
+ // ...
280
+ }
281
+
282
+ // Or use wire.go for compile-time DI
283
+ ```
284
+
285
+ ## Service Locator (Anti-Pattern, Avoid)
286
+
287
+ ```typescript
288
+ // ❌ Service Locator (looks like DI but isn't)
289
+ class ServiceLocator {
290
+ private services = new Map<string, any>();
291
+
292
+ register(name: string, service: any) {
293
+ this.services.set(name, service);
294
+ }
295
+
296
+ get<T>(name: string): T {
297
+ return this.services.get(name);
298
+ }
299
+ }
300
+
301
+ // ❌ Hidden dependency (bad)
302
+ class UserService {
303
+ async getUser(id: string) {
304
+ // Dependency hidden inside method - hard to test
305
+ const repo = ServiceLocator.get<IUserRepository>('UserRepository');
306
+ return repo.findById(id);
307
+ }
308
+ }
309
+ ```
310
+
311
+ **Why it's bad:**
312
+ - Hidden dependencies (not visible in constructor)
313
+ - Runtime errors if service not registered
314
+ - Hard to test
315
+ - Hard to understand dependencies
316
+
317
+ **Use constructor injection instead!**
318
+
319
+ ## Testing with DI
320
+
321
+ ```typescript
322
+ // ✅ Easy to test with constructor injection
323
+ describe('UserService', () => {
324
+ it('sends email after creating user', async () => {
325
+ // Create mocks
326
+ const mockRepo: IUserRepository = {
327
+ save: jest.fn(),
328
+ findByEmail: jest.fn().mockResolvedValue(null),
329
+ };
330
+ const mockEmail: IEmailService = {
331
+ send: jest.fn(),
332
+ };
333
+
334
+ // Inject mocks
335
+ const service = new UserService(mockRepo, mockEmail);
336
+
337
+ // Test
338
+ await service.createUser('test@example.com', 'password');
339
+
340
+ expect(mockEmail.send).toHaveBeenCalledWith(
341
+ expect.objectContaining({ to: 'test@example.com' })
342
+ );
343
+ });
344
+ });
345
+ ```
346
+
347
+ ## Lifetime Management
348
+
349
+ ### Singleton (One instance for application)
350
+
351
+ ```typescript
352
+ // ✅ Singleton: Shared instance
353
+ class DatabaseConnection {
354
+ private static instance: DatabaseConnection;
355
+
356
+ private constructor(private connectionString: string) {}
357
+
358
+ static getInstance(connectionString: string): DatabaseConnection {
359
+ if (!DatabaseConnection.instance) {
360
+ DatabaseConnection.instance = new DatabaseConnection(connectionString);
361
+ }
362
+ return DatabaseConnection.instance;
363
+ }
364
+ }
365
+
366
+ // Or use IoC container
367
+ container.bind<Database>(TYPES.Database).toSingleton(PostgresDatabase);
368
+ ```
369
+
370
+ **Use for:** Database connections, configuration, caching services
371
+
372
+ ### Transient (New instance per request)
373
+
374
+ ```typescript
375
+ // ✅ Transient: New instance every time
376
+ container.bind<IUserService>(TYPES.UserService).toTransient(UserService);
377
+
378
+ // Every call creates new instance
379
+ const service1 = container.get<IUserService>(TYPES.UserService);
380
+ const service2 = container.get<IUserService>(TYPES.UserService);
381
+ // service1 !== service2
382
+ ```
383
+
384
+ **Use for:** Stateful services, request handlers
385
+
386
+ ### Scoped (One instance per scope/request)
387
+
388
+ ```typescript
389
+ // ✅ Scoped: One instance per HTTP request
390
+ container.bind<IUserService>(TYPES.UserService).toScoped(UserService);
391
+
392
+ // In HTTP middleware
393
+ app.use((req, res, next) => {
394
+ req.container = container.createChild(); // New scope
395
+ next();
396
+ });
397
+
398
+ app.get('/users', (req, res) => {
399
+ const service = req.container.get<IUserService>(TYPES.UserService);
400
+ // Same instance within this request
401
+ });
402
+ ```
403
+
404
+ **Use for:** Request-scoped data (current user, transaction)
405
+
406
+ ## Best Practices
407
+
408
+ ### 1. Depend on Interfaces, Not Implementations
409
+
410
+ ```typescript
411
+ // ✅ Good: Depend on interface
412
+ class UserService {
413
+ constructor(private repository: IUserRepository) {} // Interface
414
+ }
415
+
416
+ // ❌ Bad: Depend on concrete class
417
+ class UserService {
418
+ constructor(private repository: PostgresUserRepository) {} // Concrete
419
+ }
420
+ ```
421
+
422
+ ### 2. Keep Dependencies Explicit
423
+
424
+ ```typescript
425
+ // ✅ Good: All dependencies in constructor
426
+ class OrderService {
427
+ constructor(
428
+ private orderRepo: IOrderRepository,
429
+ private paymentService: IPaymentService,
430
+ private emailService: IEmailService,
431
+ private logger: ILogger
432
+ ) {}
433
+ }
434
+
435
+ // ❌ Bad: Hidden service locator
436
+ class OrderService {
437
+ async createOrder() {
438
+ const logger = ServiceLocator.get('Logger'); // Hidden!
439
+ }
440
+ }
441
+ ```
442
+
443
+ ### 3. Don't Inject Configuration Objects
444
+
445
+ ```typescript
446
+ // ❌ Bad: Inject entire config
447
+ class EmailService {
448
+ constructor(private config: AppConfig) {
449
+ this.apiKey = config.sendGrid.apiKey; // Knows too much
450
+ }
451
+ }
452
+
453
+ // ✅ Good: Inject only what's needed
454
+ class EmailService {
455
+ constructor(private apiKey: string) {}
456
+ }
457
+ ```
458
+
459
+ ### 4. Avoid Circular Dependencies
460
+
461
+ ```typescript
462
+ // ❌ Bad: Circular dependency
463
+ class UserService {
464
+ constructor(private orderService: OrderService) {}
465
+ }
466
+
467
+ class OrderService {
468
+ constructor(private userService: UserService) {} // Circular!
469
+ }
470
+
471
+ // ✅ Good: Extract shared logic to new service
472
+ class UserService {
473
+ constructor(private notificationService: NotificationService) {}
474
+ }
475
+
476
+ class OrderService {
477
+ constructor(private notificationService: NotificationService) {}
478
+ }
479
+ ```
480
+
481
+ ## File Organization
482
+
483
+ ```
484
+ src/
485
+ ├── core/
486
+ │ ├── interfaces/ # Dependency interfaces
487
+ │ │ ├── IUserRepository.ts
488
+ │ │ ├── IEmailService.ts
489
+ │ │ └── IPaymentService.ts
490
+ │ └── services/
491
+ │ ├── UserService.ts # Depends on interfaces
492
+ │ └── OrderService.ts
493
+
494
+ ├── infrastructure/
495
+ │ ├── repositories/ # Interface implementations
496
+ │ │ └── PostgresUserRepository.ts
497
+ │ ├── services/
498
+ │ │ ├── SendGridEmailService.ts
499
+ │ │ └── StripePaymentService.ts
500
+ │ └── di/ # DI configuration
501
+ │ └── container.ts
502
+
503
+ └── composition-root.ts # Wire dependencies
504
+ ```
505
+
506
+ ## Rules Summary
507
+
508
+ - **ALWAYS** use constructor injection for required dependencies
509
+ - **ALWAYS** depend on interfaces, not concrete classes
510
+ - **ALWAYS** keep dependencies explicit (visible in constructor)
511
+ - **ALWAYS** wire dependencies at composition root (e.g., main.ts, app.ts)
512
+ - **NEVER** use service locator pattern
513
+ - **NEVER** create dependencies inside classes (new SomeDependency())
514
+ - **NEVER** access global state from classes
515
+ - **PREFER** manual DI for simple projects, IoC containers for complex ones
516
+ - **PREFER** immutable dependencies (constructor injection)
517
+ - **CONSIDER** property injection only for optional dependencies or circular refs