@gravito/scaffold 4.0.0 → 4.1.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.
package/dist/index.cjs CHANGED
@@ -1055,6 +1055,118 @@ export default {
1055
1055
  }
1056
1056
  `;
1057
1057
  }
1058
+ /**
1059
+ * Generate workers configuration for job queue system
1060
+ */
1061
+ static generateWorkersConfig(level = "basic") {
1062
+ switch (level) {
1063
+ case "advanced":
1064
+ return this.generateAdvancedWorkersConfig();
1065
+ case "production":
1066
+ return this.generateProductionWorkersConfig();
1067
+ default:
1068
+ return this.generateBasicWorkersConfig();
1069
+ }
1070
+ }
1071
+ /**
1072
+ * Generate basic workers configuration
1073
+ */
1074
+ static generateBasicWorkersConfig() {
1075
+ return ` /**
1076
+ * Workers Configuration
1077
+ *
1078
+ * Manages job execution in isolated worker threads.
1079
+ * Automatically selects best available runtime (Bun or Node.js).
1080
+ */
1081
+ workers: {
1082
+ // Runtime environment: 'auto' | 'bun' | 'node'
1083
+ runtime: process.env.WORKERS_RUNTIME as 'auto' | 'bun' | 'node' ?? 'auto',
1084
+
1085
+ pool: {
1086
+ poolSize: Number.parseInt(process.env.WORKERS_POOL_SIZE ?? '4', 10),
1087
+ minWorkers: Number.parseInt(process.env.WORKERS_MIN_WORKERS ?? '0', 10),
1088
+ healthCheckInterval: 30000,
1089
+ },
1090
+
1091
+ execution: {
1092
+ maxExecutionTime: Number.parseInt(process.env.WORKERS_MAX_EXECUTION_TIME ?? '30000', 10),
1093
+ maxMemory: Number.parseInt(process.env.WORKERS_MAX_MEMORY ?? '0', 10),
1094
+ idleTimeout: Number.parseInt(process.env.WORKERS_IDLE_TIMEOUT ?? '60000', 10),
1095
+ isolateContexts: process.env.WORKERS_ISOLATE_CONTEXTS === 'true',
1096
+ },
1097
+ },`;
1098
+ }
1099
+ /**
1100
+ * Generate advanced workers configuration with Bun optimizations
1101
+ */
1102
+ static generateAdvancedWorkersConfig() {
1103
+ return ` /**
1104
+ * Workers Configuration (Advanced)
1105
+ *
1106
+ * Manages job execution in isolated worker threads.
1107
+ * Includes Bun-specific optimizations for enhanced performance.
1108
+ *
1109
+ * Performance characteristics:
1110
+ * - Bun: 2-241x faster message passing, 20-30% less memory (smol mode)
1111
+ * - Node.js: Stable, widely tested, compatible
1112
+ */
1113
+ workers: {
1114
+ runtime: process.env.WORKERS_RUNTIME as 'auto' | 'bun' | 'node' ?? 'auto',
1115
+
1116
+ pool: {
1117
+ poolSize: Number.parseInt(process.env.WORKERS_POOL_SIZE ?? '4', 10),
1118
+ minWorkers: Number.parseInt(process.env.WORKERS_MIN_WORKERS ?? '1', 10),
1119
+ healthCheckInterval: 30000,
1120
+ },
1121
+
1122
+ execution: {
1123
+ maxExecutionTime: Number.parseInt(process.env.WORKERS_MAX_EXECUTION_TIME ?? '30000', 10),
1124
+ maxMemory: Number.parseInt(process.env.WORKERS_MAX_MEMORY ?? '0', 10),
1125
+ idleTimeout: Number.parseInt(process.env.WORKERS_IDLE_TIMEOUT ?? '60000', 10),
1126
+ isolateContexts: process.env.WORKERS_ISOLATE_CONTEXTS === 'true',
1127
+ },
1128
+
1129
+ // Bun-specific optimizations
1130
+ bun: {
1131
+ smol: process.env.WORKERS_BUN_SMOL === 'true',
1132
+ preload: process.env.WORKERS_BUN_PRELOAD
1133
+ ? process.env.WORKERS_BUN_PRELOAD.split(',').map((p) => p.trim())
1134
+ : undefined,
1135
+ inspectPort: process.env.WORKERS_BUN_INSPECT_PORT
1136
+ ? Number.parseInt(process.env.WORKERS_BUN_INSPECT_PORT, 10)
1137
+ : undefined,
1138
+ },
1139
+ },`;
1140
+ }
1141
+ /**
1142
+ * Generate production-optimized workers configuration
1143
+ */
1144
+ static generateProductionWorkersConfig() {
1145
+ return ` /**
1146
+ * Workers Configuration (Production Optimized)
1147
+ */
1148
+ workers: {
1149
+ runtime: 'auto' as const,
1150
+
1151
+ pool: {
1152
+ poolSize: Number.parseInt(process.env.WORKERS_POOL_SIZE ?? '8', 10),
1153
+ minWorkers: 2,
1154
+ healthCheckInterval: 30000,
1155
+ },
1156
+
1157
+ execution: {
1158
+ maxExecutionTime: 30000,
1159
+ maxMemory: Number.parseInt(process.env.WORKERS_MAX_MEMORY ?? '512', 10),
1160
+ idleTimeout: 60000,
1161
+ isolateContexts: false,
1162
+ },
1163
+
1164
+ bun: {
1165
+ smol: true,
1166
+ preload: process.env.WORKERS_BUN_PRELOAD?.split(',').map((p) => p.trim()),
1167
+ },
1168
+ },`;
1169
+ }
1058
1170
  };
1059
1171
 
1060
1172
  // src/utils/ServiceProviderGenerator.ts
@@ -2442,6 +2554,30 @@ var ModuleGenerator = class {
2442
2554
  ]
2443
2555
  }
2444
2556
  ]
2557
+ },
2558
+ // UserInterface Layer
2559
+ {
2560
+ type: "directory",
2561
+ name: "UserInterface",
2562
+ children: [
2563
+ {
2564
+ type: "directory",
2565
+ name: "Http",
2566
+ children: [
2567
+ {
2568
+ type: "directory",
2569
+ name: "Controllers",
2570
+ children: [
2571
+ {
2572
+ type: "file",
2573
+ name: `${name}Controller.ts`,
2574
+ content: this.generateController(name)
2575
+ }
2576
+ ]
2577
+ }
2578
+ ]
2579
+ }
2580
+ ]
2445
2581
  }
2446
2582
  ]
2447
2583
  };
@@ -2457,17 +2593,13 @@ import { ${name}Created } from '../../Events/${name}Created'
2457
2593
  import { ${name}Status } from './${name}Status'
2458
2594
 
2459
2595
  export interface ${name}Props {
2460
- // Add properties here
2461
2596
  status: ${name}Status
2462
2597
  createdAt: Date
2463
2598
  }
2464
2599
 
2465
2600
  export class ${name} extends AggregateRoot<Id> {
2466
- private props: ${name}Props
2467
-
2468
- private constructor(id: Id, props: ${name}Props) {
2601
+ private constructor(id: Id, private props: ${name}Props) {
2469
2602
  super(id)
2470
- this.props = props
2471
2603
  }
2472
2604
 
2473
2605
  static create(id: Id): ${name} {
@@ -2485,7 +2617,12 @@ export class ${name} extends AggregateRoot<Id> {
2485
2617
  return this.props.status
2486
2618
  }
2487
2619
 
2488
- // Add domain methods here
2620
+ /**
2621
+ * Complete the ${name} process
2622
+ */
2623
+ complete(): void {
2624
+ this.props.status = ${name}Status.COMPLETED
2625
+ }
2489
2626
  }
2490
2627
  `;
2491
2628
  }
@@ -2510,17 +2647,13 @@ export enum ${name}Status {
2510
2647
  import { DomainEvent } from '@gravito/enterprise'
2511
2648
 
2512
2649
  export class ${name}Created extends DomainEvent {
2513
- constructor(public readonly ${name.toLowerCase()}Id: string) {
2650
+ constructor(public readonly aggregateId: string) {
2514
2651
  super()
2515
2652
  }
2516
2653
 
2517
2654
  override get eventName(): string {
2518
2655
  return '${name.toLowerCase()}.created'
2519
2656
  }
2520
-
2521
- get aggregateId(): string {
2522
- return this.${name.toLowerCase()}Id
2523
- }
2524
2657
  }
2525
2658
  `;
2526
2659
  }
@@ -2547,7 +2680,6 @@ import { Command } from '@gravito/enterprise'
2547
2680
 
2548
2681
  export class Create${name}Command extends Command {
2549
2682
  constructor(
2550
- // Add command properties
2551
2683
  public readonly id?: string
2552
2684
  ) {
2553
2685
  super()
@@ -2602,13 +2734,15 @@ export class Get${name}ByIdQuery extends Query {
2602
2734
  import { QueryHandler } from '@gravito/enterprise'
2603
2735
  import type { I${name}Repository } from '../../../Domain/Repositories/I${name}Repository'
2604
2736
  import type { ${name}DTO } from '../../DTOs/${name}DTO'
2737
+ import { Id } from '../../../../../Shared/Domain/ValueObjects/Id'
2605
2738
  import type { Get${name}ByIdQuery } from './Get${name}ByIdQuery'
2606
2739
 
2607
2740
  export class Get${name}ByIdHandler implements QueryHandler<Get${name}ByIdQuery, ${name}DTO | null> {
2608
2741
  constructor(private repository: I${name}Repository) {}
2609
2742
 
2610
2743
  async handle(query: Get${name}ByIdQuery): Promise<${name}DTO | null> {
2611
- const aggregate = await this.repository.findById(query.id as any) // Simplified for demo
2744
+ const id = Id.from(query.id)
2745
+ const aggregate = await this.repository.findById(id)
2612
2746
  if (!aggregate) return null
2613
2747
 
2614
2748
  return {
@@ -2629,7 +2763,6 @@ import type { ${name}Status } from '../../Domain/Aggregates/${name}/${name}Statu
2629
2763
  export interface ${name}DTO {
2630
2764
  id: string
2631
2765
  status: ${name}Status
2632
- // Add more fields
2633
2766
  }
2634
2767
  `;
2635
2768
  }
@@ -2640,29 +2773,29 @@ export interface ${name}DTO {
2640
2773
 
2641
2774
  import type { ${name} } from '../../Domain/Aggregates/${name}/${name}'
2642
2775
  import type { I${name}Repository } from '../../Domain/Repositories/I${name}Repository'
2643
- import type { Id } from '../../../../../Shared/Domain/ValueObjects/Id'
2644
-
2645
- const store = new Map<string, ${name}>()
2776
+ import { Id } from '../../../../../Shared/Domain/ValueObjects/Id'
2646
2777
 
2647
2778
  export class ${name}Repository implements I${name}Repository {
2779
+ private store = new Map<string, ${name}>()
2780
+
2648
2781
  async findById(id: Id): Promise<${name} | null> {
2649
- return store.get(id.value) ?? null
2782
+ return this.store.get(id.value) ?? null
2650
2783
  }
2651
2784
 
2652
2785
  async save(aggregate: ${name}): Promise<void> {
2653
- store.set(aggregate.id.value, aggregate)
2786
+ this.store.set(aggregate.id.value, aggregate)
2654
2787
  }
2655
2788
 
2656
2789
  async delete(id: Id): Promise<void> {
2657
- store.delete(id.value)
2790
+ this.store.delete(id.value)
2658
2791
  }
2659
2792
 
2660
2793
  async findAll(): Promise<${name}[]> {
2661
- return Array.from(store.values())
2794
+ return Array.from(this.store.values())
2662
2795
  }
2663
2796
 
2664
2797
  async exists(id: Id): Promise<boolean> {
2665
- return store.has(id.value)
2798
+ return this.store.has(id.value)
2666
2799
  }
2667
2800
  }
2668
2801
  `;
@@ -2684,6 +2817,37 @@ export class ${name}ServiceProvider extends ServiceProvider {
2684
2817
  console.log('[${name}] Module loaded')
2685
2818
  }
2686
2819
  }
2820
+ `;
2821
+ }
2822
+ generateController(name) {
2823
+ return `/**
2824
+ * ${name} Controller
2825
+ */
2826
+
2827
+ import type { GravitoContext } from '@gravito/core'
2828
+
2829
+ export class ${name}Controller {
2830
+ /**
2831
+ * GET /${name.toLowerCase()}
2832
+ */
2833
+ async index(ctx: GravitoContext) {
2834
+ return ctx.json({
2835
+ success: true,
2836
+ data: []
2837
+ })
2838
+ }
2839
+
2840
+ /**
2841
+ * GET /${name.toLowerCase()}/:id
2842
+ */
2843
+ async show(ctx: GravitoContext) {
2844
+ const id = ctx.req.param('id')
2845
+ return ctx.json({
2846
+ success: true,
2847
+ data: { id }
2848
+ })
2849
+ }
2850
+ }
2687
2851
  `;
2688
2852
  }
2689
2853
  };
@@ -2858,24 +3022,39 @@ export class Email extends ValueObject<EmailProps> {
2858
3022
 
2859
3023
  import type { DomainEvent } from '@gravito/enterprise'
2860
3024
 
2861
- type EventHandler = (event: DomainEvent) => void | Promise<void>
3025
+ type EventHandler<T extends DomainEvent = any> = (event: T) => void | Promise<void>
2862
3026
 
2863
3027
  export class EventDispatcher {
2864
3028
  private handlers: Map<string, EventHandler[]> = new Map()
2865
3029
 
2866
- subscribe(eventName: string, handler: EventHandler): void {
3030
+ /**
3031
+ * Subscribe to an event
3032
+ */
3033
+ subscribe<T extends DomainEvent>(eventName: string, handler: EventHandler<T>): void {
2867
3034
  const handlers = this.handlers.get(eventName) ?? []
2868
3035
  handlers.push(handler)
2869
3036
  this.handlers.set(eventName, handlers)
2870
3037
  }
2871
3038
 
3039
+ /**
3040
+ * Dispatch a single event
3041
+ */
2872
3042
  async dispatch(event: DomainEvent): Promise<void> {
2873
3043
  const handlers = this.handlers.get(event.eventName) ?? []
2874
- for (const handler of handlers) {
2875
- await handler(event)
2876
- }
3044
+ const promises = handlers.map(handler => {
3045
+ try {
3046
+ return handler(event)
3047
+ } catch (error) {
3048
+ console.error(\`[EventDispatcher] Error in handler for \${event.eventName}:\`, error)
3049
+ }
3050
+ })
3051
+
3052
+ await Promise.all(promises)
2877
3053
  }
2878
3054
 
3055
+ /**
3056
+ * Dispatch multiple events sequentially
3057
+ */
2879
3058
  async dispatchAll(events: DomainEvent[]): Promise<void> {
2880
3059
  for (const event of events) {
2881
3060
  await this.dispatch(event)
@@ -3985,9 +4164,9 @@ var SatelliteGenerator = class extends BaseGenerator {
3985
4164
  children: [
3986
4165
  {
3987
4166
  type: "directory",
3988
- name: "Entities",
4167
+ name: "Aggregates",
3989
4168
  children: [
3990
- { type: "file", name: `${name}.ts`, content: this.generateEntity(name) }
4169
+ { type: "file", name: `${name}.ts`, content: this.generateAggregate(name) }
3991
4170
  ]
3992
4171
  },
3993
4172
  {
@@ -4001,8 +4180,24 @@ var SatelliteGenerator = class extends BaseGenerator {
4001
4180
  }
4002
4181
  ]
4003
4182
  },
4004
- { type: "directory", name: "ValueObjects", children: [] },
4005
- { type: "directory", name: "Events", children: [] }
4183
+ {
4184
+ type: "directory",
4185
+ name: "ValueObjects",
4186
+ children: [
4187
+ { type: "file", name: `${name}Id.ts`, content: this.generateIdValueObject(name) }
4188
+ ]
4189
+ },
4190
+ {
4191
+ type: "directory",
4192
+ name: "Events",
4193
+ children: [
4194
+ {
4195
+ type: "file",
4196
+ name: `${name}Created.ts`,
4197
+ content: this.generateCreatedEvent(name)
4198
+ }
4199
+ ]
4200
+ }
4006
4201
  ]
4007
4202
  },
4008
4203
  // Application Layer
@@ -4043,6 +4238,31 @@ var SatelliteGenerator = class extends BaseGenerator {
4043
4238
  }
4044
4239
  ]
4045
4240
  },
4241
+ // Interface Layer (HTTP/API)
4242
+ {
4243
+ type: "directory",
4244
+ name: "Interface",
4245
+ children: [
4246
+ {
4247
+ type: "directory",
4248
+ name: "Http",
4249
+ children: [
4250
+ {
4251
+ type: "directory",
4252
+ name: "Controllers",
4253
+ children: [
4254
+ {
4255
+ type: "file",
4256
+ name: `${name}Controller.ts`,
4257
+ content: this.generateController(name)
4258
+ }
4259
+ ]
4260
+ },
4261
+ { type: "directory", name: "Middleware", children: [] }
4262
+ ]
4263
+ }
4264
+ ]
4265
+ },
4046
4266
  // Entry Point
4047
4267
  { type: "file", name: "index.ts", content: this.generateEntryPoint(name) },
4048
4268
  {
@@ -4060,13 +4280,12 @@ var SatelliteGenerator = class extends BaseGenerator {
4060
4280
  {
4061
4281
  type: "file",
4062
4282
  name: "unit.test.ts",
4063
- content: `import { describe, it, expect } from "bun:test";
4064
-
4065
- describe("${name}", () => {
4066
- it("should work", () => {
4067
- expect(true).toBe(true);
4068
- });
4069
- });`
4283
+ content: this.generateUnitTest(name)
4284
+ },
4285
+ {
4286
+ type: "file",
4287
+ name: "integration.test.ts",
4288
+ content: this.generateIntegrationTest(name)
4070
4289
  }
4071
4290
  ]
4072
4291
  }
@@ -4075,35 +4294,76 @@ describe("${name}", () => {
4075
4294
  // ─────────────────────────────────────────────────────────────
4076
4295
  // Domain Templates
4077
4296
  // ─────────────────────────────────────────────────────────────
4078
- generateEntity(name) {
4079
- return `import { Entity } from '@gravito/enterprise'
4297
+ generateIdValueObject(name) {
4298
+ return `import { ValueObject } from '@gravito/enterprise'
4299
+
4300
+ interface IdProps {
4301
+ value: string
4302
+ }
4303
+
4304
+ export class ${name}Id extends ValueObject<IdProps> {
4305
+ constructor(value: string) {
4306
+ super({ value })
4307
+ }
4308
+
4309
+ static create(): ${name}Id {
4310
+ return new ${name}Id(crypto.randomUUID())
4311
+ }
4312
+
4313
+ get value(): string { return this.props.value }
4314
+ }
4315
+ `;
4316
+ }
4317
+ generateAggregate(name) {
4318
+ return `import { AggregateRoot } from '@gravito/enterprise'
4319
+ import { ${name}Id } from '../ValueObjects/${name}Id'
4320
+ import { ${name}Created } from '../Events/${name}Created'
4080
4321
 
4081
4322
  export interface ${name}Props {
4082
4323
  name: string
4083
4324
  createdAt: Date
4084
4325
  }
4085
4326
 
4086
- export class ${name} extends Entity<string> {
4087
- constructor(id: string, private props: ${name}Props) {
4327
+ export class ${name} extends AggregateRoot<${name}Id> {
4328
+ constructor(id: ${name}Id, private props: ${name}Props) {
4088
4329
  super(id)
4089
4330
  }
4090
4331
 
4091
- static create(id: string, name: string): ${name} {
4092
- return new ${name}(id, {
4332
+ static create(id: ${name}Id, name: string): ${name} {
4333
+ const aggregate = new ${name}(id, {
4093
4334
  name,
4094
4335
  createdAt: new Date()
4095
4336
  })
4337
+
4338
+ aggregate.addDomainEvent(new ${name}Created(id.value))
4339
+
4340
+ return aggregate
4096
4341
  }
4097
4342
 
4098
4343
  get name() { return this.props.name }
4099
4344
  }
4345
+ `;
4346
+ }
4347
+ generateCreatedEvent(name) {
4348
+ return `import { DomainEvent } from '@gravito/enterprise'
4349
+
4350
+ export class ${name}Created extends DomainEvent {
4351
+ constructor(public readonly aggregateId: string) {
4352
+ super()
4353
+ }
4354
+
4355
+ get eventName(): string {
4356
+ return '${this.context?.nameKebabCase}.created'
4357
+ }
4358
+ }
4100
4359
  `;
4101
4360
  }
4102
4361
  generateRepositoryInterface(name) {
4103
4362
  return `import { Repository } from '@gravito/enterprise'
4104
- import { ${name} } from '../Entities/${name}'
4363
+ import { ${name} } from '../Aggregates/${name}'
4364
+ import { ${name}Id } from '../ValueObjects/${name}Id'
4105
4365
 
4106
- export interface I${name}Repository extends Repository<${name}, string> {
4366
+ export interface I${name}Repository extends Repository<${name}, ${name}Id> {
4107
4367
  // Add custom methods here
4108
4368
  }
4109
4369
  `;
@@ -4114,7 +4374,8 @@ export interface I${name}Repository extends Repository<${name}, string> {
4114
4374
  generateUseCase(name) {
4115
4375
  return `import { UseCase } from '@gravito/enterprise'
4116
4376
  import { I${name}Repository } from '../../Domain/Contracts/I${name}Repository'
4117
- import { ${name} } from '../../Domain/Entities/${name}'
4377
+ import { ${name} } from '../../Domain/Aggregates/${name}'
4378
+ import { ${name}Id } from '../../Domain/ValueObjects/${name}Id'
4118
4379
 
4119
4380
  export interface Create${name}Input {
4120
4381
  name: string
@@ -4126,12 +4387,12 @@ export class Create${name} extends UseCase<Create${name}Input, string> {
4126
4387
  }
4127
4388
 
4128
4389
  async execute(input: Create${name}Input): Promise<string> {
4129
- const id = crypto.randomUUID()
4390
+ const id = ${name}Id.create()
4130
4391
  const entity = ${name}.create(id, input.name)
4131
4392
 
4132
4393
  await this.repository.save(entity)
4133
4394
 
4134
- return id
4395
+ return id.value
4135
4396
  }
4136
4397
  }
4137
4398
  `;
@@ -4141,17 +4402,16 @@ export class Create${name} extends UseCase<Create${name}Input, string> {
4141
4402
  // ─────────────────────────────────────────────────────────────
4142
4403
  generateAtlasRepository(name) {
4143
4404
  return `import { I${name}Repository } from '../../Domain/Contracts/I${name}Repository'
4144
- import { ${name} } from '../../Domain/Entities/${name}'
4145
- import { DB } from '@gravito/atlas'
4405
+ import { ${name} } from '../../Domain/Aggregates/${name}'
4406
+ import { ${name}Id } from '../../Domain/ValueObjects/${name}Id'
4146
4407
 
4147
4408
  export class Atlas${name}Repository implements I${name}Repository {
4148
4409
  async save(entity: ${name}): Promise<void> {
4149
- // Dogfooding: Use @gravito/atlas for persistence
4150
- console.log('[Atlas] Saving entity:', entity.id)
4151
- // await DB.table('${name.toLowerCase()}s').insert({ ... })
4410
+ // Implementation using @gravito/atlas
4411
+ console.log('[Atlas] Saving aggregate:', entity.id.value)
4152
4412
  }
4153
4413
 
4154
- async findById(id: string): Promise<${name} | null> {
4414
+ async findById(id: ${name}Id): Promise<${name} | null> {
4155
4415
  return null
4156
4416
  }
4157
4417
 
@@ -4159,12 +4419,77 @@ export class Atlas${name}Repository implements I${name}Repository {
4159
4419
  return []
4160
4420
  }
4161
4421
 
4162
- async delete(id: string): Promise<void> {}
4422
+ async delete(id: ${name}Id): Promise<void> {}
4163
4423
 
4164
- async exists(id: string): Promise<boolean> {
4424
+ async exists(id: ${name}Id): Promise<boolean> {
4165
4425
  return false
4166
4426
  }
4167
4427
  }
4428
+ `;
4429
+ }
4430
+ // ─────────────────────────────────────────────────────────────
4431
+ // Test Templates
4432
+ // ─────────────────────────────────────────────────────────────
4433
+ generateUnitTest(name) {
4434
+ return `import { describe, it, expect } from "bun:test";
4435
+ import { ${name} } from "../src/Domain/Aggregates/${name}";
4436
+ import { ${name}Id } from "../src/Domain/ValueObjects/${name}Id";
4437
+
4438
+ describe("${name} Aggregate", () => {
4439
+ it("should create a new aggregate with a domain event", () => {
4440
+ const id = ${name}Id.create();
4441
+ const aggregate = ${name}.create(id, "Test Name");
4442
+
4443
+ expect(aggregate.id).toBe(id);
4444
+ expect(aggregate.name).toBe("Test Name");
4445
+ expect(aggregate.pullDomainEvents()).toHaveLength(1);
4446
+ });
4447
+ });`;
4448
+ }
4449
+ generateIntegrationTest(name) {
4450
+ return `import { describe, it, expect, beforeAll } from "bun:test";
4451
+ import { PlanetCore } from "@gravito/core";
4452
+
4453
+ describe("${name} Integration", () => {
4454
+ let core: PlanetCore;
4455
+
4456
+ beforeAll(async () => {
4457
+ core = new PlanetCore();
4458
+ // Setup dependencies here
4459
+ });
4460
+
4461
+ it("should handle the creation flow", async () => {
4462
+ expect(true).toBe(true); // Placeholder for actual integration logic
4463
+ });
4464
+ });`;
4465
+ }
4466
+ // ─────────────────────────────────────────────────────────────
4467
+ // Interface Templates
4468
+ // ─────────────────────────────────────────────────────────────
4469
+ generateController(name) {
4470
+ return `import type { GravitoContext } from '@gravito/core'
4471
+ import { Create${name} } from '../../../Application/UseCases/Create${name}'
4472
+
4473
+ export class ${name}Controller {
4474
+ constructor(private createUseCase: Create${name}) {}
4475
+
4476
+ async store(ctx: GravitoContext) {
4477
+ const body = await ctx.req.json()
4478
+ const id = await this.createUseCase.execute({ name: body.name })
4479
+
4480
+ return ctx.json({
4481
+ success: true,
4482
+ data: { id }
4483
+ }, 201)
4484
+ }
4485
+
4486
+ async index(ctx: GravitoContext) {
4487
+ return ctx.json({
4488
+ success: true,
4489
+ data: []
4490
+ })
4491
+ }
4492
+ }
4168
4493
  `;
4169
4494
  }
4170
4495
  // ─────────────────────────────────────────────────────────────
@@ -4173,17 +4498,22 @@ export class Atlas${name}Repository implements I${name}Repository {
4173
4498
  generateEntryPoint(name) {
4174
4499
  return `import { ServiceProvider, type Container } from '@gravito/core'
4175
4500
  import { Atlas${name}Repository } from './Infrastructure/Persistence/Atlas${name}Repository'
4501
+ import { Create${name} } from './Application/UseCases/Create${name}'
4502
+ import { ${name}Controller } from './Interface/Http/Controllers/${name}Controller'
4176
4503
 
4177
4504
  export class ${name}ServiceProvider extends ServiceProvider {
4178
4505
  register(container: Container): void {
4179
- // Bind Repository
4506
+ // 1. Bind Repository (Infrastructure)
4180
4507
  container.singleton('${name.toLowerCase()}.repo', () => new Atlas${name}Repository())
4181
4508
 
4182
- // Bind UseCases
4183
- container.singleton('${name.toLowerCase()}.create', () => {
4184
- return new (require('./Application/UseCases/Create${name}').Create${name})(
4185
- container.make('${name.toLowerCase()}.repo')
4186
- )
4509
+ // 2. Bind UseCases (Application)
4510
+ container.singleton('${name.toLowerCase()}.usecase.create', (c) => {
4511
+ return new Create${name}(c.make('${name.toLowerCase()}.repo'))
4512
+ })
4513
+
4514
+ // 3. Bind Controllers (Interface)
4515
+ container.singleton('${name.toLowerCase()}.controller', (c) => {
4516
+ return new ${name}Controller(c.make('${name.toLowerCase()}.usecase.create'))
4187
4517
  })
4188
4518
  }
4189
4519
 
@@ -4294,7 +4624,9 @@ var ProfileResolver = class _ProfileResolver {
4294
4624
  storage: "local",
4295
4625
  session: "file"
4296
4626
  },
4297
- features: []
4627
+ features: [],
4628
+ workers: "basic"
4629
+ // Basic workers configuration for core profile
4298
4630
  },
4299
4631
  scale: {
4300
4632
  drivers: {
@@ -4304,7 +4636,9 @@ var ProfileResolver = class _ProfileResolver {
4304
4636
  storage: "s3",
4305
4637
  session: "redis"
4306
4638
  },
4307
- features: ["stream", "nebula"]
4639
+ features: ["stream", "nebula"],
4640
+ workers: "advanced"
4641
+ // Advanced workers with Bun optimizations
4308
4642
  },
4309
4643
  enterprise: {
4310
4644
  drivers: {
@@ -4314,14 +4648,17 @@ var ProfileResolver = class _ProfileResolver {
4314
4648
  storage: "s3",
4315
4649
  session: "redis"
4316
4650
  },
4317
- features: ["stream", "nebula", "monitor", "sentinel", "fortify"]
4651
+ features: ["stream", "nebula", "monitor", "sentinel", "fortify"],
4652
+ workers: "production"
4653
+ // Production-optimized workers
4318
4654
  }
4319
4655
  };
4320
4656
  resolve(profile = "core", withFeatures = []) {
4321
4657
  const base = _ProfileResolver.DEFAULTS[profile] || _ProfileResolver.DEFAULTS.core;
4322
4658
  const config = {
4323
4659
  drivers: { ...base.drivers },
4324
- features: [...base.features]
4660
+ features: [...base.features],
4661
+ workers: base.workers
4325
4662
  };
4326
4663
  for (const feature of withFeatures) {
4327
4664
  this.applyFeature(config, feature);