atomic-queues 2.0.2 → 2.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.
Files changed (53) hide show
  1. package/README.md +134 -14
  2. package/dist/cli/generators/classes.d.ts +12 -0
  3. package/dist/cli/generators/classes.d.ts.map +1 -0
  4. package/dist/cli/generators/classes.js +141 -0
  5. package/dist/cli/generators/classes.js.map +1 -0
  6. package/dist/cli/generators/typescript.d.ts.map +1 -1
  7. package/dist/cli/generators/typescript.js +35 -0
  8. package/dist/cli/generators/typescript.js.map +1 -1
  9. package/dist/cli/index.js +170 -23
  10. package/dist/cli/index.js.map +1 -1
  11. package/dist/domain/interfaces/config.interfaces.d.ts +4 -0
  12. package/dist/domain/interfaces/config.interfaces.d.ts.map +1 -1
  13. package/dist/domain/interfaces/index.d.ts +1 -0
  14. package/dist/domain/interfaces/index.d.ts.map +1 -1
  15. package/dist/domain/interfaces/index.js +1 -0
  16. package/dist/domain/interfaces/index.js.map +1 -1
  17. package/dist/domain/interfaces/reply.types.d.ts +27 -0
  18. package/dist/domain/interfaces/reply.types.d.ts.map +1 -0
  19. package/dist/domain/interfaces/reply.types.js +19 -0
  20. package/dist/domain/interfaces/reply.types.js.map +1 -0
  21. package/dist/services/actor-registry/actor-registry.service.d.ts.map +1 -1
  22. package/dist/services/actor-registry/actor-registry.service.js +7 -3
  23. package/dist/services/actor-registry/actor-registry.service.js.map +1 -1
  24. package/dist/services/executor-pool/executor-pool.service.d.ts +7 -0
  25. package/dist/services/executor-pool/executor-pool.service.d.ts.map +1 -1
  26. package/dist/services/executor-pool/executor-pool.service.js +34 -1
  27. package/dist/services/executor-pool/executor-pool.service.js.map +1 -1
  28. package/dist/services/handler-executor/handler-executor.service.d.ts +1 -0
  29. package/dist/services/handler-executor/handler-executor.service.d.ts.map +1 -1
  30. package/dist/services/handler-executor/handler-executor.service.js +16 -0
  31. package/dist/services/handler-executor/handler-executor.service.js.map +1 -1
  32. package/dist/services/queue-bus/cluster-contracts.d.ts +77 -0
  33. package/dist/services/queue-bus/cluster-contracts.d.ts.map +1 -0
  34. package/dist/services/queue-bus/cluster-contracts.js +118 -0
  35. package/dist/services/queue-bus/cluster-contracts.js.map +1 -0
  36. package/dist/services/queue-bus/index.d.ts +1 -0
  37. package/dist/services/queue-bus/index.d.ts.map +1 -1
  38. package/dist/services/queue-bus/index.js +1 -0
  39. package/dist/services/queue-bus/index.js.map +1 -1
  40. package/dist/services/queue-bus/queue-bus.service.d.ts +42 -13
  41. package/dist/services/queue-bus/queue-bus.service.d.ts.map +1 -1
  42. package/dist/services/queue-bus/queue-bus.service.js +77 -21
  43. package/dist/services/queue-bus/queue-bus.service.js.map +1 -1
  44. package/dist/services/registry/registry.service.d.ts.map +1 -1
  45. package/dist/services/registry/registry.service.js +6 -1
  46. package/dist/services/registry/registry.service.js.map +1 -1
  47. package/dist/services/registry/registry.types.d.ts +1 -0
  48. package/dist/services/registry/registry.types.d.ts.map +1 -1
  49. package/dist/services/scheduler/scheduler.service.d.ts +1 -1
  50. package/dist/services/scheduler/scheduler.service.d.ts.map +1 -1
  51. package/dist/services/scheduler/scheduler.service.js +36 -14
  52. package/dist/services/scheduler/scheduler.service.js.map +1 -1
  53. package/package.json +1 -1
package/README.md CHANGED
@@ -159,12 +159,20 @@ The library auto-discovers `@CommandHandler` and `@QueryHandler` classes at boot
159
159
  // Fire-and-forget
160
160
  await queueBus.enqueue(new WithdrawCommand(accountId, 100));
161
161
 
162
- // Enqueue and block until result
162
+ // Enqueue and block until result — return type inferred from Reply<T> brand
163
163
  const balance = await queueBus.enqueueAndWait(new GetBalanceQuery(accountId));
164
164
 
165
165
  // Scoped to an entity type
166
166
  await queueBus.forEntity('account').enqueueBulk([charge1, charge2, charge3]);
167
167
 
168
+ // Cross-service: string-based API — no class import needed
169
+ await queueBus.enqueue('warehouse', 'ReserveStockCommand', 'SKU-001', { sku: 'SKU-001', quantity: 50 });
170
+ const stock = await queueBus.enqueueAndWait('warehouse', 'GetStockQuery', 'SKU-001', { sku: 'SKU-001' });
171
+
172
+ // Scoped cross-service
173
+ const warehouse = queueBus.forEntity('warehouse');
174
+ await warehouse.enqueue('ReserveStockCommand', 'SKU-001', { sku: 'SKU-001', quantity: 50 });
175
+
168
176
  // Actor-style direct send
169
177
  await actorSystem.send('account', accountId, new DepositCommand(100));
170
178
  const balance = await actorSystem.sendAndWait('account', accountId, new GetBalanceQuery());
@@ -228,17 +236,23 @@ atomic-queues replaces all of that with Redis.
228
236
  Enable the distributed registry and any service connected to the same Redis instance can send typed messages to any entity — regardless of which service owns the handler.
229
237
 
230
238
  ```typescript
231
- // billing-service: defines and handles the entity
239
+ // warehouse-service: defines and handles the entity
232
240
  AtomicQueuesModule.forRoot({
233
241
  redis: { url: process.env.REDIS_URL },
234
- registry: { enabled: true, serviceName: 'billing-service' },
242
+ registry: { enabled: true, serviceName: 'warehouse-service' },
235
243
  })
236
244
 
237
- // payments-service: sends to it (shared Redis, no code dependency on billing)
238
- await queueBus.enqueue(new WithdrawCommand(accountId, 100));
245
+ // order-service: generate classes from the live registry, then use them like local CQRS
246
+ import { ReserveStockCommand, GetStockQuery } from './generated';
247
+
248
+ await queueBus.enqueue(new ReserveStockCommand({ sku: 'SKU-001', quantity: 50 }));
249
+ const stock = await queueBus.enqueueAndWait(new GetStockQuery({ sku: 'SKU-001' }));
250
+ stock.available; // fully typed — no string API, no explicit timeout, no code dependency on warehouse-service
239
251
  ```
240
252
 
241
- When `billing-service` starts, it scans its own `@Actor`, `@CommandHandler`, and `@QueryHandler` classes and publishes **entity contracts** to Redis — a JSON document listing the entity type, accepted messages, and optional JSON schemas, refreshed via heartbeat TTL. When `payments-service` enqueues a message, the registry validates it at the call site *before* it enters the log: entity type exists, message name is accepted, payload matches schema. Errors are immediate and descriptive — not silent dead letters discovered hours later in a DLQ dashboard.
253
+ When `warehouse-service` starts, it scans its own `@Actor`, `@CommandHandler`, and `@QueryHandler` classes and publishes **entity contracts** to Redis — a JSON document listing the entity type, accepted messages, optional JSON schemas, and reply schemas, refreshed via heartbeat TTL. When `order-service` enqueues a message, the registry validates it at the call site *before* it enters the log: entity type exists, message name is accepted, payload matches schema. Errors are immediate and descriptive — not silent dead letters discovered hours later in a DLQ dashboard.
254
+
255
+ The Lua scheduler ensures each node only dispatches messages for entity types it owns handlers for. Services that don't own any handlers (API gateways, pure producers) participate in the registry without stealing messages from handler-owning nodes.
242
256
 
243
257
  ### What this replaces
244
258
 
@@ -252,7 +266,7 @@ Think about what you no longer need:
252
266
 
253
267
  **No service discovery.** The registry *is* service discovery. When a service starts, it publishes what it handles. When a service stops, its registrations TTL out. Other services discover capabilities by reading the registry.
254
268
 
255
- **No serialization framework.** Messages are JSON. The wire protocol is three Redis commands. No Protobuf compilation step, no `.proto` files, no code generation from IDL. (Though atomic-queues does offer codegen from the live registry — it generates TypeScript interfaces so Service A gets compile-time type safety for messages destined to Service B, without importing Service B's code.)
269
+ **No serialization framework.** Messages are JSON. The wire protocol is three Redis commands. No Protobuf compilation step, no `.proto` files, no code generation from IDL. (Though atomic-queues does offer codegen from the live registry — it generates decorated TypeScript classes so Service A gets compile-time type safety for messages destined to Service B, without importing Service B's code.)
256
270
 
257
271
  **No separate dead-letter infrastructure.** Failed messages are dead-lettered per entity type in Redis, queryable via the same connection.
258
272
 
@@ -281,15 +295,118 @@ The Zod schema serializes to JSON Schema and stores in the registry. Every servi
281
295
 
282
296
  Multiple services can handle different message types on the same entity. Service A handles `DepositCommand` and `WithdrawCommand` on the `account` entity type. Service B handles `FreezeAccountCommand` on the same entity type. The registry merges their contracts automatically. The dispatch gate still ensures single-writer semantics per entity instance, regardless of which service's executor picks up the message.
283
297
 
284
- ### Contract codegen
298
+ ### Runtime introspection
299
+
300
+ Any service can discover what the cluster offers at runtime — no config files, no shared code:
301
+
302
+ ```typescript
303
+ const contracts = await queueBus.introspect();
304
+
305
+ contracts.entityTypes(); // ['account', 'warehouse', ...]
306
+ contracts.hasEntity('warehouse'); // true
307
+ contracts.messagesFor('warehouse'); // ['ReserveStockCommand', 'GetStockQuery']
308
+ contracts.accepts('warehouse', 'ReserveStockCommand'); // true
309
+ contracts.schemaFor('warehouse', 'ReserveStockCommand'); // { properties: { sku: ..., quantity: ... } }
310
+ contracts.replySchemaFor('warehouse', 'GetStockQuery'); // { properties: { sku: ..., available: ... } }
311
+
312
+ // Human-readable summary for logging/debugging
313
+ console.log(contracts.toString());
314
+ ```
315
+
316
+ ### Raw cross-service API
317
+
318
+ For quick prototyping or dynamic dispatch, you can also use the string-based API — no classes, no codegen, no imports:
319
+
320
+ ```typescript
321
+ // Fire-and-forget
322
+ await queueBus.enqueue('warehouse', 'ReserveStockCommand', 'SKU-001', {
323
+ sku: 'SKU-001',
324
+ quantity: 50,
325
+ });
326
+
327
+ // Request-reply
328
+ const stock = await queueBus.enqueueAndWait('warehouse', 'GetStockQuery', 'SKU-001', {
329
+ sku: 'SKU-001',
330
+ });
331
+
332
+ // Scoped to an entity type
333
+ const warehouse = queueBus.forEntity('warehouse');
334
+ await warehouse.enqueue('ReserveStockCommand', 'SKU-001', { sku: 'SKU-001', quantity: 50 });
335
+ const stock = await warehouse.enqueueAndWait('GetStockQuery', 'SKU-001', { sku: 'SKU-001' });
336
+ ```
337
+
338
+ This works out of the box — the registry validates entity type and message name at the call site. For production services, class codegen gives you full type safety.
285
339
 
286
- Generate typed interfaces from the live registry:
340
+ ### Class codegen (recommended)
341
+
342
+ Generate fully decorated TypeScript classes from the live registry — import them and use them like local CQRS classes with full autocomplete, type safety, and zero string APIs:
287
343
 
288
344
  ```bash
289
- REDIS_URL=redis://localhost:6379 npx atomic-queues generate --ts --output ./generated/contracts.ts
345
+ npx atomic-queues generate --classes -o src/generated
346
+ ```
347
+
348
+ This produces one file per entity type plus a barrel `index.ts`:
349
+
350
+ ```
351
+ src/generated/
352
+ warehouse.ts # ReserveStockCommand, GetStockQuery, data interfaces, reply interfaces
353
+ billing.ts # ChargeCommand, GetInvoiceQuery, ...
354
+ index.ts # export * from './warehouse'; export * from './billing';
355
+ ```
356
+
357
+ Then use them exactly like local command/query classes:
358
+
359
+ ```typescript
360
+ import { ReserveStockCommand, GetStockQuery } from './generated';
361
+
362
+ // Fire-and-forget — full autocomplete on constructor fields
363
+ await queueBus.enqueue(new ReserveStockCommand({ sku: 'SKU-001', quantity: 50 }));
364
+
365
+ // Request-reply — return type inferred from Reply<T> brand, no explicit timeout
366
+ const stock = await queueBus.enqueueAndWait(new GetStockQuery({ sku: 'SKU-001' }));
367
+ stock.available; // typed as number — full IDE support
368
+ ```
369
+
370
+ Generated query classes implement `Reply<T>` via a phantom type brand, so `enqueueAndWait` infers the return type at compile time with zero runtime cost. No explicit generics, no timeout parameter — timeouts are resolved from config.
371
+
372
+ You can also filter to specific entity types:
373
+
374
+ ```bash
375
+ npx atomic-queues generate --classes -o src/generated --entities warehouse,billing
376
+ ```
377
+
378
+ ### Other codegen formats
379
+
380
+ ```bash
381
+ # TypeScript interfaces + DispatchMap (for typed string-based API)
382
+ npx atomic-queues generate --ts --output ./generated/contracts.ts
383
+
384
+ # JSON Schema (language-agnostic)
385
+ npx atomic-queues generate --json-schema --output ./generated/schema.json
386
+
387
+ # Full registry snapshot
388
+ npx atomic-queues generate --snapshot --output ./generated/snapshot.json
389
+ ```
390
+
391
+ ### Config-driven timeouts
392
+
393
+ `enqueueAndWait` resolves timeouts automatically — you never need to pass one explicitly:
394
+
395
+ ```typescript
396
+ AtomicQueuesModule.forRoot({
397
+ executor: {
398
+ gateTTL: 30,
399
+ defaultReplyTimeout: 15000, // global fallback: 15s
400
+ },
401
+ entities: {
402
+ warehouse: {
403
+ replyTimeout: 5000, // warehouse-specific: 5s
404
+ },
405
+ },
406
+ })
290
407
  ```
291
408
 
292
- Also supports `--json-schema` for language-agnostic schema export and `--snapshot` for full registry dumps.
409
+ Resolution chain: explicit arg → per-entity `replyTimeout` global `defaultReplyTimeout` `gateTTL * 2 * 1000`. If nothing is configured, defaults to 60s.
293
410
 
294
411
  ---
295
412
 
@@ -368,8 +485,9 @@ AtomicQueuesModule.forRoot({
368
485
  redis: { host: 'localhost', port: 6379 },
369
486
 
370
487
  executor: {
371
- poolSize: 1, // concurrent executors per node
372
- gateTTL: 30, // seconds before gate expires (safety net)
488
+ poolSize: 1, // concurrent executors per node
489
+ gateTTL: 30, // seconds before gate expires (safety net)
490
+ defaultReplyTimeout: 15000, // global default for enqueueAndWait (ms)
373
491
  },
374
492
 
375
493
  entities: {
@@ -379,6 +497,7 @@ AtomicQueuesModule.forRoot({
379
497
  retry: { maxAttempts: 5, backoff: 'exponential', backoffDelay: 2000 },
380
498
  actorIdleTimeout: 120000,
381
499
  statePersistence: true,
500
+ replyTimeout: 5000, // per-entity enqueueAndWait timeout (ms)
382
501
  },
383
502
  },
384
503
 
@@ -446,6 +565,7 @@ npm install zod zod-to-json-schema # for schema validation in the registry
446
565
  | `@Actor('type')` | Declare a virtual actor class |
447
566
  | `@On(MessageClass)` | Handle a message type on an actor |
448
567
  | `@Schema(zodSchema)` | Attach a Zod schema for registry validation |
568
+ | `@ReplySchema(zodSchema)` | Attach a reply schema for query codegen |
449
569
 
450
570
  ---
451
571
 
@@ -457,7 +577,7 @@ V2 is a full rewrite of the internals. BullMQ is removed. Workers are removed. T
457
577
 
458
578
  **What's removed**: `@WorkerProcessor`, `@JobHandler`, `@EntityScaler`, `@OnSpawnWorker`, `@OnTerminateWorker`, `@GetActiveEntities`, `@GetDesiredWorkerCount`, `.forProcessor()`. All worker and scaling concepts are gone.
459
579
 
460
- **What's new**: `@Actor`, `@On`, `@Schema`, `ActorSystem`, `RegistryService`, distributed registry, codegen CLI.
580
+ **What's new**: `@Actor`, `@On`, `@Schema`, `@ReplySchema`, `ActorSystem`, `RegistryService`, distributed registry, runtime introspection (`queueBus.introspect()`), cross-service string-based API, `Reply<T>` phantom type, class codegen CLI (`--classes`), config-driven timeouts.
461
581
 
462
582
  **Migration steps**: (1) remove all `@WorkerProcessor` classes — replace with `@Actor` or configure entity defaults in module config; (2) remove all scaling decorators; (3) run the data migration script to drain in-flight BullMQ jobs to the new log format; (4) remove `bullmq` and `@nestjs/bullmq` from your dependencies.
463
583
 
@@ -0,0 +1,12 @@
1
+ import { RegistrySnapshot } from '../../services/registry/registry.types';
2
+ export interface GeneratedFile {
3
+ filename: string;
4
+ content: string;
5
+ }
6
+ /**
7
+ * Generates instantiable TypeScript classes from the registry snapshot.
8
+ * Each entity type gets its own file with decorated command/query classes
9
+ * that work directly with `queueBus.enqueue()` and `queueBus.enqueueAndWait()`.
10
+ */
11
+ export declare function generateClasses(snapshot: RegistrySnapshot): GeneratedFile[];
12
+ //# sourceMappingURL=classes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classes.d.ts","sourceRoot":"","sources":["../../../src/cli/generators/classes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA+B,MAAM,wCAAwC,CAAC;AAEvG,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,gBAAgB,GAAG,aAAa,EAAE,CAqB3E"}
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateClasses = generateClasses;
4
+ /**
5
+ * Generates instantiable TypeScript classes from the registry snapshot.
6
+ * Each entity type gets its own file with decorated command/query classes
7
+ * that work directly with `queueBus.enqueue()` and `queueBus.enqueueAndWait()`.
8
+ */
9
+ function generateClasses(snapshot) {
10
+ const files = [];
11
+ for (const entity of snapshot.entities) {
12
+ const filename = `${kebabCase(entity.entityType)}.ts`;
13
+ const content = generateEntityFile(entity, snapshot);
14
+ files.push({ filename, content });
15
+ }
16
+ // Barrel index
17
+ const barrelLines = [
18
+ header(snapshot),
19
+ '',
20
+ ];
21
+ for (const entity of snapshot.entities) {
22
+ barrelLines.push(`export * from './${kebabCase(entity.entityType)}';`);
23
+ }
24
+ barrelLines.push('');
25
+ files.push({ filename: 'index.ts', content: barrelLines.join('\n') });
26
+ return files;
27
+ }
28
+ function generateEntityFile(entity, snapshot) {
29
+ const lines = [];
30
+ const messages = Object.entries(entity.messages);
31
+ const hasReply = messages.some(([, spec]) => spec.kind === 'query' && spec.replySchema?.properties);
32
+ lines.push(header(snapshot));
33
+ lines.push(`// Entity: ${entity.entityType} (service: ${entity.serviceName})`);
34
+ lines.push('');
35
+ // Imports
36
+ const imports = ['EntityType'];
37
+ const hasEntityId = messages.some(([, spec]) => spec.entityIdField);
38
+ if (hasEntityId)
39
+ imports.push('QueueEntityId');
40
+ lines.push(`import { ${imports.join(', ')} } from 'atomic-queues';`);
41
+ if (hasReply) {
42
+ lines.push(`import type { Reply } from 'atomic-queues';`);
43
+ }
44
+ lines.push('');
45
+ for (const [msgName, spec] of messages) {
46
+ lines.push(generateMessage(entity.entityType, msgName, spec));
47
+ lines.push('');
48
+ }
49
+ return lines.join('\n');
50
+ }
51
+ function generateMessage(entityType, msgName, spec) {
52
+ const lines = [];
53
+ const fields = extractFields(spec);
54
+ const hasReplySchema = !!spec.replySchema?.properties;
55
+ // Data interface
56
+ const dataInterfaceName = `${msgName}Data`;
57
+ lines.push(`export interface ${dataInterfaceName} {`);
58
+ for (const field of fields) {
59
+ lines.push(` ${field.name}${field.required ? '' : '?'}: ${field.tsType};`);
60
+ }
61
+ lines.push('}');
62
+ lines.push('');
63
+ // Reply interface (for queries with reply schemas)
64
+ if (hasReplySchema) {
65
+ const replyFields = extractFieldsFromSchema(spec.replySchema);
66
+ const replyName = `${msgName}Reply`;
67
+ lines.push(`export interface ${replyName} {`);
68
+ for (const field of replyFields) {
69
+ lines.push(` ${field.name}${field.required ? '' : '?'}: ${field.tsType};`);
70
+ }
71
+ lines.push('}');
72
+ lines.push('');
73
+ }
74
+ // Class
75
+ const replyImpl = hasReplySchema ? ` implements Reply<${msgName}Reply>` : '';
76
+ lines.push(`@EntityType('${entityType}')`);
77
+ lines.push(`export class ${msgName}${replyImpl} {`);
78
+ // Phantom reply brand (type-only)
79
+ if (hasReplySchema) {
80
+ lines.push(` declare readonly __reply: ${msgName}Reply;`);
81
+ lines.push('');
82
+ }
83
+ // Fields with @QueueEntityId on the entity ID field
84
+ for (const field of fields) {
85
+ if (field.name === spec.entityIdField) {
86
+ lines.push(` @QueueEntityId() readonly ${field.name}!: ${field.tsType};`);
87
+ }
88
+ else {
89
+ lines.push(` readonly ${field.name}${field.required ? '!' : '?'}: ${field.tsType};`);
90
+ }
91
+ }
92
+ // Constructor
93
+ lines.push('');
94
+ lines.push(` constructor(data: ${dataInterfaceName}) {`);
95
+ lines.push(' Object.assign(this, data);');
96
+ lines.push(' }');
97
+ lines.push('}');
98
+ return lines.join('\n');
99
+ }
100
+ function extractFields(spec) {
101
+ return extractFieldsFromSchema(spec.schema);
102
+ }
103
+ function extractFieldsFromSchema(schema) {
104
+ if (!schema?.properties)
105
+ return [];
106
+ const required = new Set(schema.required ?? []);
107
+ return Object.entries(schema.properties).map(([name, propSchema]) => ({
108
+ name,
109
+ tsType: jsonSchemaTypeToTS(propSchema),
110
+ required: required.has(name),
111
+ }));
112
+ }
113
+ function jsonSchemaTypeToTS(schema) {
114
+ if (!schema.type)
115
+ return 'any';
116
+ switch (schema.type) {
117
+ case 'string': return schema.enum ? schema.enum.map((v) => `'${v}'`).join(' | ') : 'string';
118
+ case 'number':
119
+ case 'integer': return 'number';
120
+ case 'boolean': return 'boolean';
121
+ case 'array': return schema.items ? `${jsonSchemaTypeToTS(schema.items)}[]` : 'any[]';
122
+ case 'object': return 'Record<string, any>';
123
+ case 'null': return 'null';
124
+ default: return 'any';
125
+ }
126
+ }
127
+ function header(snapshot) {
128
+ return [
129
+ '// Auto-generated by atomic-queues — do not edit',
130
+ `// Source: Redis registry (prefix: '${snapshot.keyPrefix}')`,
131
+ `// Generated: ${new Date(snapshot.generatedAt).toISOString()}`,
132
+ '// Regenerate: npx atomic-queues generate --classes',
133
+ ].join('\n');
134
+ }
135
+ function kebabCase(str) {
136
+ return str
137
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
138
+ .replace(/[\s_]+/g, '-')
139
+ .toLowerCase();
140
+ }
141
+ //# sourceMappingURL=classes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classes.js","sourceRoot":"","sources":["../../../src/cli/generators/classes.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../../src/cli/generators/typescript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAE1E,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CA6CrE"}
1
+ {"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../../src/cli/generators/typescript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAE1E,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAiGrE"}
@@ -8,6 +8,7 @@ function generateTypeScript(snapshot) {
8
8
  lines.push(`// Generated: ${new Date(snapshot.generatedAt).toISOString()}`);
9
9
  lines.push('// DO NOT EDIT — regenerate with: npx atomic-queues generate --ts');
10
10
  lines.push('');
11
+ // ── Per-entity namespaces with message interfaces ──────────────────────
11
12
  for (const entity of snapshot.entities) {
12
13
  const namespace = pascalCase(entity.entityType) + 'Entity';
13
14
  lines.push(`export namespace ${namespace} {`);
@@ -37,6 +38,40 @@ function generateTypeScript(snapshot) {
37
38
  lines.push('}');
38
39
  lines.push('');
39
40
  }
41
+ // ── DispatchMap — maps entity type → message name → payload type ───────
42
+ lines.push('// ── Dispatch type maps (for use with TypedDispatch / TypedDispatchAndWait) ──');
43
+ lines.push('');
44
+ lines.push('export interface DispatchMap {');
45
+ for (const entity of snapshot.entities) {
46
+ const namespace = pascalCase(entity.entityType) + 'Entity';
47
+ lines.push(` '${entity.entityType}': {`);
48
+ for (const [msgName, spec] of Object.entries(entity.messages)) {
49
+ const hasSchema = spec.schema?.properties && Object.keys(spec.schema.properties).length > 0;
50
+ const type = hasSchema ? `${namespace}.${msgName}` : 'Record<string, any>';
51
+ lines.push(` '${msgName}': ${type};`);
52
+ }
53
+ lines.push(' };');
54
+ }
55
+ lines.push('}');
56
+ lines.push('');
57
+ // ── ReplyMap — maps entity type → query name → reply type ─────────────
58
+ const hasAnyReply = snapshot.entities.some(e => Object.values(e.messages).some(m => m.kind === 'query' && m.replySchema?.properties));
59
+ if (hasAnyReply) {
60
+ lines.push('export interface ReplyMap {');
61
+ for (const entity of snapshot.entities) {
62
+ const namespace = pascalCase(entity.entityType) + 'Entity';
63
+ const queries = Object.entries(entity.messages).filter(([, spec]) => spec.kind === 'query' && spec.replySchema?.properties);
64
+ if (queries.length > 0) {
65
+ lines.push(` '${entity.entityType}': {`);
66
+ for (const [msgName] of queries) {
67
+ lines.push(` '${msgName}': ${namespace}.${msgName}Reply;`);
68
+ }
69
+ lines.push(' };');
70
+ }
71
+ }
72
+ lines.push('}');
73
+ lines.push('');
74
+ }
40
75
  return lines.join('\n');
41
76
  }
42
77
  function jsonSchemaTypeToTS(schema) {
@@ -1 +1 @@
1
- {"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../../src/cli/generators/typescript.ts"],"names":[],"mappings":";;AAEA,gDA6CC;AA7CD,SAAgB,kBAAkB,CAAC,QAA0B;IAC3D,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACrD,KAAK,CAAC,IAAI,CAAC,uCAAuC,QAAQ,CAAC,SAAS,IAAI,CAAC,CAAC;IAC1E,KAAK,CAAC,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC5E,KAAK,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;IAChF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,oBAAoB,SAAS,IAAI,CAAC,CAAC;QAE9C,KAAK,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9D,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,eAAe,MAAM,CAAC,WAAW,KAAK,CAAC,CAAC;YACrE,KAAK,CAAC,IAAI,CAAC,sBAAsB,OAAO,IAAI,CAAC,CAAC;YAE9C,IAAI,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;gBAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;oBACxE,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAiB,CAAC,CAAC;oBACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;oBAC/D,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,GAAG,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEf,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC;gBAC1D,KAAK,CAAC,IAAI,CAAC,sBAAsB,OAAO,SAAS,CAAC,CAAC;gBACnD,KAAK,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC7E,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAiB,CAAC,CAAC;oBACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;oBACpE,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,GAAG,CAAC,CAAC;gBAC9D,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAoD;IAC9E,IAAI,CAAC,MAAM,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/B,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,QAAQ,CAAC,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACjG,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS,CAAC,CAAC,OAAO,QAAQ,CAAC;QAChC,KAAK,SAAS,CAAC,CAAC,OAAO,SAAS,CAAC;QACjC,KAAK,OAAO,CAAC,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;QACtF,KAAK,QAAQ,CAAC,CAAC,OAAO,qBAAqB,CAAC;QAC5C,KAAK,MAAM,CAAC,CAAC,OAAO,MAAM,CAAC;QAC3B,OAAO,CAAC,CAAC,OAAO,KAAK,CAAC;IACxB,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,KAAK,CAAC,SAAS,CAAC;SAChB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SACvE,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../../src/cli/generators/typescript.ts"],"names":[],"mappings":"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"}