@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.js CHANGED
@@ -1008,6 +1008,118 @@ export default {
1008
1008
  }
1009
1009
  `;
1010
1010
  }
1011
+ /**
1012
+ * Generate workers configuration for job queue system
1013
+ */
1014
+ static generateWorkersConfig(level = "basic") {
1015
+ switch (level) {
1016
+ case "advanced":
1017
+ return this.generateAdvancedWorkersConfig();
1018
+ case "production":
1019
+ return this.generateProductionWorkersConfig();
1020
+ default:
1021
+ return this.generateBasicWorkersConfig();
1022
+ }
1023
+ }
1024
+ /**
1025
+ * Generate basic workers configuration
1026
+ */
1027
+ static generateBasicWorkersConfig() {
1028
+ return ` /**
1029
+ * Workers Configuration
1030
+ *
1031
+ * Manages job execution in isolated worker threads.
1032
+ * Automatically selects best available runtime (Bun or Node.js).
1033
+ */
1034
+ workers: {
1035
+ // Runtime environment: 'auto' | 'bun' | 'node'
1036
+ runtime: process.env.WORKERS_RUNTIME as 'auto' | 'bun' | 'node' ?? 'auto',
1037
+
1038
+ pool: {
1039
+ poolSize: Number.parseInt(process.env.WORKERS_POOL_SIZE ?? '4', 10),
1040
+ minWorkers: Number.parseInt(process.env.WORKERS_MIN_WORKERS ?? '0', 10),
1041
+ healthCheckInterval: 30000,
1042
+ },
1043
+
1044
+ execution: {
1045
+ maxExecutionTime: Number.parseInt(process.env.WORKERS_MAX_EXECUTION_TIME ?? '30000', 10),
1046
+ maxMemory: Number.parseInt(process.env.WORKERS_MAX_MEMORY ?? '0', 10),
1047
+ idleTimeout: Number.parseInt(process.env.WORKERS_IDLE_TIMEOUT ?? '60000', 10),
1048
+ isolateContexts: process.env.WORKERS_ISOLATE_CONTEXTS === 'true',
1049
+ },
1050
+ },`;
1051
+ }
1052
+ /**
1053
+ * Generate advanced workers configuration with Bun optimizations
1054
+ */
1055
+ static generateAdvancedWorkersConfig() {
1056
+ return ` /**
1057
+ * Workers Configuration (Advanced)
1058
+ *
1059
+ * Manages job execution in isolated worker threads.
1060
+ * Includes Bun-specific optimizations for enhanced performance.
1061
+ *
1062
+ * Performance characteristics:
1063
+ * - Bun: 2-241x faster message passing, 20-30% less memory (smol mode)
1064
+ * - Node.js: Stable, widely tested, compatible
1065
+ */
1066
+ workers: {
1067
+ runtime: process.env.WORKERS_RUNTIME as 'auto' | 'bun' | 'node' ?? 'auto',
1068
+
1069
+ pool: {
1070
+ poolSize: Number.parseInt(process.env.WORKERS_POOL_SIZE ?? '4', 10),
1071
+ minWorkers: Number.parseInt(process.env.WORKERS_MIN_WORKERS ?? '1', 10),
1072
+ healthCheckInterval: 30000,
1073
+ },
1074
+
1075
+ execution: {
1076
+ maxExecutionTime: Number.parseInt(process.env.WORKERS_MAX_EXECUTION_TIME ?? '30000', 10),
1077
+ maxMemory: Number.parseInt(process.env.WORKERS_MAX_MEMORY ?? '0', 10),
1078
+ idleTimeout: Number.parseInt(process.env.WORKERS_IDLE_TIMEOUT ?? '60000', 10),
1079
+ isolateContexts: process.env.WORKERS_ISOLATE_CONTEXTS === 'true',
1080
+ },
1081
+
1082
+ // Bun-specific optimizations
1083
+ bun: {
1084
+ smol: process.env.WORKERS_BUN_SMOL === 'true',
1085
+ preload: process.env.WORKERS_BUN_PRELOAD
1086
+ ? process.env.WORKERS_BUN_PRELOAD.split(',').map((p) => p.trim())
1087
+ : undefined,
1088
+ inspectPort: process.env.WORKERS_BUN_INSPECT_PORT
1089
+ ? Number.parseInt(process.env.WORKERS_BUN_INSPECT_PORT, 10)
1090
+ : undefined,
1091
+ },
1092
+ },`;
1093
+ }
1094
+ /**
1095
+ * Generate production-optimized workers configuration
1096
+ */
1097
+ static generateProductionWorkersConfig() {
1098
+ return ` /**
1099
+ * Workers Configuration (Production Optimized)
1100
+ */
1101
+ workers: {
1102
+ runtime: 'auto' as const,
1103
+
1104
+ pool: {
1105
+ poolSize: Number.parseInt(process.env.WORKERS_POOL_SIZE ?? '8', 10),
1106
+ minWorkers: 2,
1107
+ healthCheckInterval: 30000,
1108
+ },
1109
+
1110
+ execution: {
1111
+ maxExecutionTime: 30000,
1112
+ maxMemory: Number.parseInt(process.env.WORKERS_MAX_MEMORY ?? '512', 10),
1113
+ idleTimeout: 60000,
1114
+ isolateContexts: false,
1115
+ },
1116
+
1117
+ bun: {
1118
+ smol: true,
1119
+ preload: process.env.WORKERS_BUN_PRELOAD?.split(',').map((p) => p.trim()),
1120
+ },
1121
+ },`;
1122
+ }
1011
1123
  };
1012
1124
 
1013
1125
  // src/utils/ServiceProviderGenerator.ts
@@ -2395,6 +2507,30 @@ var ModuleGenerator = class {
2395
2507
  ]
2396
2508
  }
2397
2509
  ]
2510
+ },
2511
+ // UserInterface Layer
2512
+ {
2513
+ type: "directory",
2514
+ name: "UserInterface",
2515
+ children: [
2516
+ {
2517
+ type: "directory",
2518
+ name: "Http",
2519
+ children: [
2520
+ {
2521
+ type: "directory",
2522
+ name: "Controllers",
2523
+ children: [
2524
+ {
2525
+ type: "file",
2526
+ name: `${name}Controller.ts`,
2527
+ content: this.generateController(name)
2528
+ }
2529
+ ]
2530
+ }
2531
+ ]
2532
+ }
2533
+ ]
2398
2534
  }
2399
2535
  ]
2400
2536
  };
@@ -2410,17 +2546,13 @@ import { ${name}Created } from '../../Events/${name}Created'
2410
2546
  import { ${name}Status } from './${name}Status'
2411
2547
 
2412
2548
  export interface ${name}Props {
2413
- // Add properties here
2414
2549
  status: ${name}Status
2415
2550
  createdAt: Date
2416
2551
  }
2417
2552
 
2418
2553
  export class ${name} extends AggregateRoot<Id> {
2419
- private props: ${name}Props
2420
-
2421
- private constructor(id: Id, props: ${name}Props) {
2554
+ private constructor(id: Id, private props: ${name}Props) {
2422
2555
  super(id)
2423
- this.props = props
2424
2556
  }
2425
2557
 
2426
2558
  static create(id: Id): ${name} {
@@ -2438,7 +2570,12 @@ export class ${name} extends AggregateRoot<Id> {
2438
2570
  return this.props.status
2439
2571
  }
2440
2572
 
2441
- // Add domain methods here
2573
+ /**
2574
+ * Complete the ${name} process
2575
+ */
2576
+ complete(): void {
2577
+ this.props.status = ${name}Status.COMPLETED
2578
+ }
2442
2579
  }
2443
2580
  `;
2444
2581
  }
@@ -2463,17 +2600,13 @@ export enum ${name}Status {
2463
2600
  import { DomainEvent } from '@gravito/enterprise'
2464
2601
 
2465
2602
  export class ${name}Created extends DomainEvent {
2466
- constructor(public readonly ${name.toLowerCase()}Id: string) {
2603
+ constructor(public readonly aggregateId: string) {
2467
2604
  super()
2468
2605
  }
2469
2606
 
2470
2607
  override get eventName(): string {
2471
2608
  return '${name.toLowerCase()}.created'
2472
2609
  }
2473
-
2474
- get aggregateId(): string {
2475
- return this.${name.toLowerCase()}Id
2476
- }
2477
2610
  }
2478
2611
  `;
2479
2612
  }
@@ -2500,7 +2633,6 @@ import { Command } from '@gravito/enterprise'
2500
2633
 
2501
2634
  export class Create${name}Command extends Command {
2502
2635
  constructor(
2503
- // Add command properties
2504
2636
  public readonly id?: string
2505
2637
  ) {
2506
2638
  super()
@@ -2555,13 +2687,15 @@ export class Get${name}ByIdQuery extends Query {
2555
2687
  import { QueryHandler } from '@gravito/enterprise'
2556
2688
  import type { I${name}Repository } from '../../../Domain/Repositories/I${name}Repository'
2557
2689
  import type { ${name}DTO } from '../../DTOs/${name}DTO'
2690
+ import { Id } from '../../../../../Shared/Domain/ValueObjects/Id'
2558
2691
  import type { Get${name}ByIdQuery } from './Get${name}ByIdQuery'
2559
2692
 
2560
2693
  export class Get${name}ByIdHandler implements QueryHandler<Get${name}ByIdQuery, ${name}DTO | null> {
2561
2694
  constructor(private repository: I${name}Repository) {}
2562
2695
 
2563
2696
  async handle(query: Get${name}ByIdQuery): Promise<${name}DTO | null> {
2564
- const aggregate = await this.repository.findById(query.id as any) // Simplified for demo
2697
+ const id = Id.from(query.id)
2698
+ const aggregate = await this.repository.findById(id)
2565
2699
  if (!aggregate) return null
2566
2700
 
2567
2701
  return {
@@ -2582,7 +2716,6 @@ import type { ${name}Status } from '../../Domain/Aggregates/${name}/${name}Statu
2582
2716
  export interface ${name}DTO {
2583
2717
  id: string
2584
2718
  status: ${name}Status
2585
- // Add more fields
2586
2719
  }
2587
2720
  `;
2588
2721
  }
@@ -2593,29 +2726,29 @@ export interface ${name}DTO {
2593
2726
 
2594
2727
  import type { ${name} } from '../../Domain/Aggregates/${name}/${name}'
2595
2728
  import type { I${name}Repository } from '../../Domain/Repositories/I${name}Repository'
2596
- import type { Id } from '../../../../../Shared/Domain/ValueObjects/Id'
2597
-
2598
- const store = new Map<string, ${name}>()
2729
+ import { Id } from '../../../../../Shared/Domain/ValueObjects/Id'
2599
2730
 
2600
2731
  export class ${name}Repository implements I${name}Repository {
2732
+ private store = new Map<string, ${name}>()
2733
+
2601
2734
  async findById(id: Id): Promise<${name} | null> {
2602
- return store.get(id.value) ?? null
2735
+ return this.store.get(id.value) ?? null
2603
2736
  }
2604
2737
 
2605
2738
  async save(aggregate: ${name}): Promise<void> {
2606
- store.set(aggregate.id.value, aggregate)
2739
+ this.store.set(aggregate.id.value, aggregate)
2607
2740
  }
2608
2741
 
2609
2742
  async delete(id: Id): Promise<void> {
2610
- store.delete(id.value)
2743
+ this.store.delete(id.value)
2611
2744
  }
2612
2745
 
2613
2746
  async findAll(): Promise<${name}[]> {
2614
- return Array.from(store.values())
2747
+ return Array.from(this.store.values())
2615
2748
  }
2616
2749
 
2617
2750
  async exists(id: Id): Promise<boolean> {
2618
- return store.has(id.value)
2751
+ return this.store.has(id.value)
2619
2752
  }
2620
2753
  }
2621
2754
  `;
@@ -2637,6 +2770,37 @@ export class ${name}ServiceProvider extends ServiceProvider {
2637
2770
  console.log('[${name}] Module loaded')
2638
2771
  }
2639
2772
  }
2773
+ `;
2774
+ }
2775
+ generateController(name) {
2776
+ return `/**
2777
+ * ${name} Controller
2778
+ */
2779
+
2780
+ import type { GravitoContext } from '@gravito/core'
2781
+
2782
+ export class ${name}Controller {
2783
+ /**
2784
+ * GET /${name.toLowerCase()}
2785
+ */
2786
+ async index(ctx: GravitoContext) {
2787
+ return ctx.json({
2788
+ success: true,
2789
+ data: []
2790
+ })
2791
+ }
2792
+
2793
+ /**
2794
+ * GET /${name.toLowerCase()}/:id
2795
+ */
2796
+ async show(ctx: GravitoContext) {
2797
+ const id = ctx.req.param('id')
2798
+ return ctx.json({
2799
+ success: true,
2800
+ data: { id }
2801
+ })
2802
+ }
2803
+ }
2640
2804
  `;
2641
2805
  }
2642
2806
  };
@@ -2811,24 +2975,39 @@ export class Email extends ValueObject<EmailProps> {
2811
2975
 
2812
2976
  import type { DomainEvent } from '@gravito/enterprise'
2813
2977
 
2814
- type EventHandler = (event: DomainEvent) => void | Promise<void>
2978
+ type EventHandler<T extends DomainEvent = any> = (event: T) => void | Promise<void>
2815
2979
 
2816
2980
  export class EventDispatcher {
2817
2981
  private handlers: Map<string, EventHandler[]> = new Map()
2818
2982
 
2819
- subscribe(eventName: string, handler: EventHandler): void {
2983
+ /**
2984
+ * Subscribe to an event
2985
+ */
2986
+ subscribe<T extends DomainEvent>(eventName: string, handler: EventHandler<T>): void {
2820
2987
  const handlers = this.handlers.get(eventName) ?? []
2821
2988
  handlers.push(handler)
2822
2989
  this.handlers.set(eventName, handlers)
2823
2990
  }
2824
2991
 
2992
+ /**
2993
+ * Dispatch a single event
2994
+ */
2825
2995
  async dispatch(event: DomainEvent): Promise<void> {
2826
2996
  const handlers = this.handlers.get(event.eventName) ?? []
2827
- for (const handler of handlers) {
2828
- await handler(event)
2829
- }
2997
+ const promises = handlers.map(handler => {
2998
+ try {
2999
+ return handler(event)
3000
+ } catch (error) {
3001
+ console.error(\`[EventDispatcher] Error in handler for \${event.eventName}:\`, error)
3002
+ }
3003
+ })
3004
+
3005
+ await Promise.all(promises)
2830
3006
  }
2831
3007
 
3008
+ /**
3009
+ * Dispatch multiple events sequentially
3010
+ */
2832
3011
  async dispatchAll(events: DomainEvent[]): Promise<void> {
2833
3012
  for (const event of events) {
2834
3013
  await this.dispatch(event)
@@ -3938,9 +4117,9 @@ var SatelliteGenerator = class extends BaseGenerator {
3938
4117
  children: [
3939
4118
  {
3940
4119
  type: "directory",
3941
- name: "Entities",
4120
+ name: "Aggregates",
3942
4121
  children: [
3943
- { type: "file", name: `${name}.ts`, content: this.generateEntity(name) }
4122
+ { type: "file", name: `${name}.ts`, content: this.generateAggregate(name) }
3944
4123
  ]
3945
4124
  },
3946
4125
  {
@@ -3954,8 +4133,24 @@ var SatelliteGenerator = class extends BaseGenerator {
3954
4133
  }
3955
4134
  ]
3956
4135
  },
3957
- { type: "directory", name: "ValueObjects", children: [] },
3958
- { type: "directory", name: "Events", children: [] }
4136
+ {
4137
+ type: "directory",
4138
+ name: "ValueObjects",
4139
+ children: [
4140
+ { type: "file", name: `${name}Id.ts`, content: this.generateIdValueObject(name) }
4141
+ ]
4142
+ },
4143
+ {
4144
+ type: "directory",
4145
+ name: "Events",
4146
+ children: [
4147
+ {
4148
+ type: "file",
4149
+ name: `${name}Created.ts`,
4150
+ content: this.generateCreatedEvent(name)
4151
+ }
4152
+ ]
4153
+ }
3959
4154
  ]
3960
4155
  },
3961
4156
  // Application Layer
@@ -3996,6 +4191,31 @@ var SatelliteGenerator = class extends BaseGenerator {
3996
4191
  }
3997
4192
  ]
3998
4193
  },
4194
+ // Interface Layer (HTTP/API)
4195
+ {
4196
+ type: "directory",
4197
+ name: "Interface",
4198
+ children: [
4199
+ {
4200
+ type: "directory",
4201
+ name: "Http",
4202
+ children: [
4203
+ {
4204
+ type: "directory",
4205
+ name: "Controllers",
4206
+ children: [
4207
+ {
4208
+ type: "file",
4209
+ name: `${name}Controller.ts`,
4210
+ content: this.generateController(name)
4211
+ }
4212
+ ]
4213
+ },
4214
+ { type: "directory", name: "Middleware", children: [] }
4215
+ ]
4216
+ }
4217
+ ]
4218
+ },
3999
4219
  // Entry Point
4000
4220
  { type: "file", name: "index.ts", content: this.generateEntryPoint(name) },
4001
4221
  {
@@ -4013,13 +4233,12 @@ var SatelliteGenerator = class extends BaseGenerator {
4013
4233
  {
4014
4234
  type: "file",
4015
4235
  name: "unit.test.ts",
4016
- content: `import { describe, it, expect } from "bun:test";
4017
-
4018
- describe("${name}", () => {
4019
- it("should work", () => {
4020
- expect(true).toBe(true);
4021
- });
4022
- });`
4236
+ content: this.generateUnitTest(name)
4237
+ },
4238
+ {
4239
+ type: "file",
4240
+ name: "integration.test.ts",
4241
+ content: this.generateIntegrationTest(name)
4023
4242
  }
4024
4243
  ]
4025
4244
  }
@@ -4028,35 +4247,76 @@ describe("${name}", () => {
4028
4247
  // ─────────────────────────────────────────────────────────────
4029
4248
  // Domain Templates
4030
4249
  // ─────────────────────────────────────────────────────────────
4031
- generateEntity(name) {
4032
- return `import { Entity } from '@gravito/enterprise'
4250
+ generateIdValueObject(name) {
4251
+ return `import { ValueObject } from '@gravito/enterprise'
4252
+
4253
+ interface IdProps {
4254
+ value: string
4255
+ }
4256
+
4257
+ export class ${name}Id extends ValueObject<IdProps> {
4258
+ constructor(value: string) {
4259
+ super({ value })
4260
+ }
4261
+
4262
+ static create(): ${name}Id {
4263
+ return new ${name}Id(crypto.randomUUID())
4264
+ }
4265
+
4266
+ get value(): string { return this.props.value }
4267
+ }
4268
+ `;
4269
+ }
4270
+ generateAggregate(name) {
4271
+ return `import { AggregateRoot } from '@gravito/enterprise'
4272
+ import { ${name}Id } from '../ValueObjects/${name}Id'
4273
+ import { ${name}Created } from '../Events/${name}Created'
4033
4274
 
4034
4275
  export interface ${name}Props {
4035
4276
  name: string
4036
4277
  createdAt: Date
4037
4278
  }
4038
4279
 
4039
- export class ${name} extends Entity<string> {
4040
- constructor(id: string, private props: ${name}Props) {
4280
+ export class ${name} extends AggregateRoot<${name}Id> {
4281
+ constructor(id: ${name}Id, private props: ${name}Props) {
4041
4282
  super(id)
4042
4283
  }
4043
4284
 
4044
- static create(id: string, name: string): ${name} {
4045
- return new ${name}(id, {
4285
+ static create(id: ${name}Id, name: string): ${name} {
4286
+ const aggregate = new ${name}(id, {
4046
4287
  name,
4047
4288
  createdAt: new Date()
4048
4289
  })
4290
+
4291
+ aggregate.addDomainEvent(new ${name}Created(id.value))
4292
+
4293
+ return aggregate
4049
4294
  }
4050
4295
 
4051
4296
  get name() { return this.props.name }
4052
4297
  }
4298
+ `;
4299
+ }
4300
+ generateCreatedEvent(name) {
4301
+ return `import { DomainEvent } from '@gravito/enterprise'
4302
+
4303
+ export class ${name}Created extends DomainEvent {
4304
+ constructor(public readonly aggregateId: string) {
4305
+ super()
4306
+ }
4307
+
4308
+ get eventName(): string {
4309
+ return '${this.context?.nameKebabCase}.created'
4310
+ }
4311
+ }
4053
4312
  `;
4054
4313
  }
4055
4314
  generateRepositoryInterface(name) {
4056
4315
  return `import { Repository } from '@gravito/enterprise'
4057
- import { ${name} } from '../Entities/${name}'
4316
+ import { ${name} } from '../Aggregates/${name}'
4317
+ import { ${name}Id } from '../ValueObjects/${name}Id'
4058
4318
 
4059
- export interface I${name}Repository extends Repository<${name}, string> {
4319
+ export interface I${name}Repository extends Repository<${name}, ${name}Id> {
4060
4320
  // Add custom methods here
4061
4321
  }
4062
4322
  `;
@@ -4067,7 +4327,8 @@ export interface I${name}Repository extends Repository<${name}, string> {
4067
4327
  generateUseCase(name) {
4068
4328
  return `import { UseCase } from '@gravito/enterprise'
4069
4329
  import { I${name}Repository } from '../../Domain/Contracts/I${name}Repository'
4070
- import { ${name} } from '../../Domain/Entities/${name}'
4330
+ import { ${name} } from '../../Domain/Aggregates/${name}'
4331
+ import { ${name}Id } from '../../Domain/ValueObjects/${name}Id'
4071
4332
 
4072
4333
  export interface Create${name}Input {
4073
4334
  name: string
@@ -4079,12 +4340,12 @@ export class Create${name} extends UseCase<Create${name}Input, string> {
4079
4340
  }
4080
4341
 
4081
4342
  async execute(input: Create${name}Input): Promise<string> {
4082
- const id = crypto.randomUUID()
4343
+ const id = ${name}Id.create()
4083
4344
  const entity = ${name}.create(id, input.name)
4084
4345
 
4085
4346
  await this.repository.save(entity)
4086
4347
 
4087
- return id
4348
+ return id.value
4088
4349
  }
4089
4350
  }
4090
4351
  `;
@@ -4094,17 +4355,16 @@ export class Create${name} extends UseCase<Create${name}Input, string> {
4094
4355
  // ─────────────────────────────────────────────────────────────
4095
4356
  generateAtlasRepository(name) {
4096
4357
  return `import { I${name}Repository } from '../../Domain/Contracts/I${name}Repository'
4097
- import { ${name} } from '../../Domain/Entities/${name}'
4098
- import { DB } from '@gravito/atlas'
4358
+ import { ${name} } from '../../Domain/Aggregates/${name}'
4359
+ import { ${name}Id } from '../../Domain/ValueObjects/${name}Id'
4099
4360
 
4100
4361
  export class Atlas${name}Repository implements I${name}Repository {
4101
4362
  async save(entity: ${name}): Promise<void> {
4102
- // Dogfooding: Use @gravito/atlas for persistence
4103
- console.log('[Atlas] Saving entity:', entity.id)
4104
- // await DB.table('${name.toLowerCase()}s').insert({ ... })
4363
+ // Implementation using @gravito/atlas
4364
+ console.log('[Atlas] Saving aggregate:', entity.id.value)
4105
4365
  }
4106
4366
 
4107
- async findById(id: string): Promise<${name} | null> {
4367
+ async findById(id: ${name}Id): Promise<${name} | null> {
4108
4368
  return null
4109
4369
  }
4110
4370
 
@@ -4112,12 +4372,77 @@ export class Atlas${name}Repository implements I${name}Repository {
4112
4372
  return []
4113
4373
  }
4114
4374
 
4115
- async delete(id: string): Promise<void> {}
4375
+ async delete(id: ${name}Id): Promise<void> {}
4116
4376
 
4117
- async exists(id: string): Promise<boolean> {
4377
+ async exists(id: ${name}Id): Promise<boolean> {
4118
4378
  return false
4119
4379
  }
4120
4380
  }
4381
+ `;
4382
+ }
4383
+ // ─────────────────────────────────────────────────────────────
4384
+ // Test Templates
4385
+ // ─────────────────────────────────────────────────────────────
4386
+ generateUnitTest(name) {
4387
+ return `import { describe, it, expect } from "bun:test";
4388
+ import { ${name} } from "../src/Domain/Aggregates/${name}";
4389
+ import { ${name}Id } from "../src/Domain/ValueObjects/${name}Id";
4390
+
4391
+ describe("${name} Aggregate", () => {
4392
+ it("should create a new aggregate with a domain event", () => {
4393
+ const id = ${name}Id.create();
4394
+ const aggregate = ${name}.create(id, "Test Name");
4395
+
4396
+ expect(aggregate.id).toBe(id);
4397
+ expect(aggregate.name).toBe("Test Name");
4398
+ expect(aggregate.pullDomainEvents()).toHaveLength(1);
4399
+ });
4400
+ });`;
4401
+ }
4402
+ generateIntegrationTest(name) {
4403
+ return `import { describe, it, expect, beforeAll } from "bun:test";
4404
+ import { PlanetCore } from "@gravito/core";
4405
+
4406
+ describe("${name} Integration", () => {
4407
+ let core: PlanetCore;
4408
+
4409
+ beforeAll(async () => {
4410
+ core = new PlanetCore();
4411
+ // Setup dependencies here
4412
+ });
4413
+
4414
+ it("should handle the creation flow", async () => {
4415
+ expect(true).toBe(true); // Placeholder for actual integration logic
4416
+ });
4417
+ });`;
4418
+ }
4419
+ // ─────────────────────────────────────────────────────────────
4420
+ // Interface Templates
4421
+ // ─────────────────────────────────────────────────────────────
4422
+ generateController(name) {
4423
+ return `import type { GravitoContext } from '@gravito/core'
4424
+ import { Create${name} } from '../../../Application/UseCases/Create${name}'
4425
+
4426
+ export class ${name}Controller {
4427
+ constructor(private createUseCase: Create${name}) {}
4428
+
4429
+ async store(ctx: GravitoContext) {
4430
+ const body = await ctx.req.json()
4431
+ const id = await this.createUseCase.execute({ name: body.name })
4432
+
4433
+ return ctx.json({
4434
+ success: true,
4435
+ data: { id }
4436
+ }, 201)
4437
+ }
4438
+
4439
+ async index(ctx: GravitoContext) {
4440
+ return ctx.json({
4441
+ success: true,
4442
+ data: []
4443
+ })
4444
+ }
4445
+ }
4121
4446
  `;
4122
4447
  }
4123
4448
  // ─────────────────────────────────────────────────────────────
@@ -4126,17 +4451,22 @@ export class Atlas${name}Repository implements I${name}Repository {
4126
4451
  generateEntryPoint(name) {
4127
4452
  return `import { ServiceProvider, type Container } from '@gravito/core'
4128
4453
  import { Atlas${name}Repository } from './Infrastructure/Persistence/Atlas${name}Repository'
4454
+ import { Create${name} } from './Application/UseCases/Create${name}'
4455
+ import { ${name}Controller } from './Interface/Http/Controllers/${name}Controller'
4129
4456
 
4130
4457
  export class ${name}ServiceProvider extends ServiceProvider {
4131
4458
  register(container: Container): void {
4132
- // Bind Repository
4459
+ // 1. Bind Repository (Infrastructure)
4133
4460
  container.singleton('${name.toLowerCase()}.repo', () => new Atlas${name}Repository())
4134
4461
 
4135
- // Bind UseCases
4136
- container.singleton('${name.toLowerCase()}.create', () => {
4137
- return new (require('./Application/UseCases/Create${name}').Create${name})(
4138
- container.make('${name.toLowerCase()}.repo')
4139
- )
4462
+ // 2. Bind UseCases (Application)
4463
+ container.singleton('${name.toLowerCase()}.usecase.create', (c) => {
4464
+ return new Create${name}(c.make('${name.toLowerCase()}.repo'))
4465
+ })
4466
+
4467
+ // 3. Bind Controllers (Interface)
4468
+ container.singleton('${name.toLowerCase()}.controller', (c) => {
4469
+ return new ${name}Controller(c.make('${name.toLowerCase()}.usecase.create'))
4140
4470
  })
4141
4471
  }
4142
4472
 
@@ -4247,7 +4577,9 @@ var ProfileResolver = class _ProfileResolver {
4247
4577
  storage: "local",
4248
4578
  session: "file"
4249
4579
  },
4250
- features: []
4580
+ features: [],
4581
+ workers: "basic"
4582
+ // Basic workers configuration for core profile
4251
4583
  },
4252
4584
  scale: {
4253
4585
  drivers: {
@@ -4257,7 +4589,9 @@ var ProfileResolver = class _ProfileResolver {
4257
4589
  storage: "s3",
4258
4590
  session: "redis"
4259
4591
  },
4260
- features: ["stream", "nebula"]
4592
+ features: ["stream", "nebula"],
4593
+ workers: "advanced"
4594
+ // Advanced workers with Bun optimizations
4261
4595
  },
4262
4596
  enterprise: {
4263
4597
  drivers: {
@@ -4267,14 +4601,17 @@ var ProfileResolver = class _ProfileResolver {
4267
4601
  storage: "s3",
4268
4602
  session: "redis"
4269
4603
  },
4270
- features: ["stream", "nebula", "monitor", "sentinel", "fortify"]
4604
+ features: ["stream", "nebula", "monitor", "sentinel", "fortify"],
4605
+ workers: "production"
4606
+ // Production-optimized workers
4271
4607
  }
4272
4608
  };
4273
4609
  resolve(profile = "core", withFeatures = []) {
4274
4610
  const base = _ProfileResolver.DEFAULTS[profile] || _ProfileResolver.DEFAULTS.core;
4275
4611
  const config = {
4276
4612
  drivers: { ...base.drivers },
4277
- features: [...base.features]
4613
+ features: [...base.features],
4614
+ workers: base.workers
4278
4615
  };
4279
4616
  for (const feature of withFeatures) {
4280
4617
  this.applyFeature(config, feature);