@pattern-stack/codegen 0.14.2 → 0.15.1

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 (66) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/dist/{job-orchestrator.protocol-CARhMLCO.d.ts → job-orchestrator.protocol-DubMVbm9.d.ts} +1 -1
  3. package/dist/runtime/subsystems/bridge/bridge-delivery-handler.d.ts +2 -2
  4. package/dist/runtime/subsystems/bridge/bridge-delivery-handler.js.map +1 -1
  5. package/dist/runtime/subsystems/bridge/bridge-delivery.drizzle-backend.d.ts +1 -1
  6. package/dist/runtime/subsystems/bridge/bridge-delivery.memory-backend.d.ts +1 -1
  7. package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.d.ts +1 -1
  8. package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.js.map +1 -1
  9. package/dist/runtime/subsystems/bridge/bridge.module.d.ts +2 -2
  10. package/dist/runtime/subsystems/bridge/bridge.module.js.map +1 -1
  11. package/dist/runtime/subsystems/bridge/bridge.protocol.d.ts +1 -1
  12. package/dist/runtime/subsystems/bridge/event-flow.service.d.ts +2 -2
  13. package/dist/runtime/subsystems/bridge/event-flow.service.js.map +1 -1
  14. package/dist/runtime/subsystems/bridge/generated/registry.d.ts +1 -1
  15. package/dist/runtime/subsystems/bridge/index.d.ts +2 -2
  16. package/dist/runtime/subsystems/bridge/index.js.map +1 -1
  17. package/dist/runtime/subsystems/events/event-bus.drizzle-backend.d.ts +1 -1
  18. package/dist/runtime/subsystems/events/event-registry.d.ts +77 -0
  19. package/dist/runtime/subsystems/events/event-registry.js +1 -0
  20. package/dist/runtime/subsystems/events/event-registry.js.map +1 -0
  21. package/dist/runtime/subsystems/events/events.module.d.ts +26 -1
  22. package/dist/runtime/subsystems/events/events.module.js +6 -5
  23. package/dist/runtime/subsystems/events/events.module.js.map +1 -1
  24. package/dist/runtime/subsystems/events/index.d.ts +1 -0
  25. package/dist/runtime/subsystems/events/index.js +6 -5
  26. package/dist/runtime/subsystems/events/index.js.map +1 -1
  27. package/dist/runtime/subsystems/index.d.ts +2 -2
  28. package/dist/runtime/subsystems/index.js +6 -5
  29. package/dist/runtime/subsystems/index.js.map +1 -1
  30. package/dist/runtime/subsystems/jobs/index.d.ts +2 -2
  31. package/dist/runtime/subsystems/jobs/index.js.map +1 -1
  32. package/dist/runtime/subsystems/jobs/job-handler.base.d.ts +2 -2
  33. package/dist/runtime/subsystems/jobs/job-handler.base.js.map +1 -1
  34. package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.d.ts +2 -2
  35. package/dist/runtime/subsystems/jobs/job-orchestrator.drizzle-backend.d.ts +2 -2
  36. package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.d.ts +2 -2
  37. package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js.map +1 -1
  38. package/dist/runtime/subsystems/jobs/job-orchestrator.protocol.d.ts +2 -2
  39. package/dist/runtime/subsystems/jobs/job-run-keyset-cursor.d.ts +2 -2
  40. package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.d.ts +2 -2
  41. package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.d.ts +2 -2
  42. package/dist/runtime/subsystems/jobs/job-run-service.protocol.d.ts +2 -2
  43. package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.d.ts +2 -2
  44. package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js.map +1 -1
  45. package/dist/runtime/subsystems/jobs/job-worker.d.ts +2 -2
  46. package/dist/runtime/subsystems/jobs/job-worker.js.map +1 -1
  47. package/dist/runtime/subsystems/jobs/job-worker.module.d.ts +2 -2
  48. package/dist/runtime/subsystems/jobs/job-worker.module.js.map +1 -1
  49. package/dist/runtime/subsystems/jobs/jobs-domain.module.js.map +1 -1
  50. package/dist/runtime/subsystems/jobs/jobs-errors.d.ts +2 -2
  51. package/dist/runtime/subsystems/observability/index.d.ts +2 -2
  52. package/dist/runtime/subsystems/observability/observability.protocol.d.ts +2 -2
  53. package/dist/runtime/subsystems/observability/observability.service.d.ts +2 -2
  54. package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.d.ts +2 -2
  55. package/dist/runtime/subsystems/observability/reporters/index.d.ts +2 -2
  56. package/dist/src/cli/index.js +1332 -1274
  57. package/dist/src/cli/index.js.map +1 -1
  58. package/package.json +1 -1
  59. package/runtime/subsystems/bridge/bridge-delivery-handler.ts +1 -1
  60. package/runtime/subsystems/bridge/bridge-outbox-drain-hook.ts +1 -1
  61. package/runtime/subsystems/bridge/bridge.protocol.ts +1 -1
  62. package/runtime/subsystems/bridge/event-flow.service.ts +1 -1
  63. package/runtime/subsystems/events/event-registry.ts +77 -0
  64. package/runtime/subsystems/events/events.module.ts +39 -6
  65. package/runtime/subsystems/events/index.ts +12 -0
  66. package/runtime/subsystems/jobs/job-handler.base.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pattern-stack/codegen",
3
- "version": "0.14.2",
3
+ "version": "0.15.1",
4
4
  "description": "Entity-driven code generation for full-stack TypeScript applications",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -64,7 +64,7 @@ import {
64
64
 
65
65
  import { EVENT_BUS } from '../events/events.tokens';
66
66
  import type { IEventBus, DomainEvent } from '../events/event-bus.protocol';
67
- import type { EventTypeName } from '../events/generated/types';
67
+ import type { EventTypeName } from '../events/event-registry';
68
68
 
69
69
  import {
70
70
  BRIDGE_DELIVERY_REPO,
@@ -45,7 +45,7 @@ import type {
45
45
  IBridgeOutboxDrainHook,
46
46
  } from './bridge.protocol';
47
47
  import { BRIDGE_DELIVERY_JOB_TYPE } from './bridge-delivery-handler';
48
- import type { EventTypeName } from '../events/generated/types';
48
+ import type { EventTypeName } from '../events/event-registry';
49
49
 
50
50
  /** Reserved pools the wrapper rows route into; ADR-022 / ADR-024. */
51
51
  const POOL_BY_DIRECTION: Record<string, string> = {
@@ -29,7 +29,7 @@ import type { DrizzleTransaction, DomainEvent } from '../events/event-bus.protoc
29
29
  import type {
30
30
  EventOfType,
31
31
  EventTypeName,
32
- } from '../events/generated/types';
32
+ } from '../events/event-registry';
33
33
 
34
34
  import type {
35
35
  BridgeDeliveryRecord,
@@ -52,7 +52,7 @@ import type {
52
52
  import type {
53
53
  EventOfType,
54
54
  EventTypeName,
55
- } from '../events/generated/types';
55
+ } from '../events/event-registry';
56
56
 
57
57
  import { JOB_ORCHESTRATOR } from '../jobs/jobs-domain.tokens';
58
58
  import type { IJobOrchestrator } from '../jobs/job-orchestrator.protocol';
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Augmentable domain-event registry (ADR-037, package-mode trigger typing).
3
+ *
4
+ * This is the seam that lets the bridge + job-trigger types see a PACKAGE-MODE
5
+ * consumer's OWN events with full per-event payload typing — without the
6
+ * package shipping (and leaking) its internal test-fixture event union.
7
+ *
8
+ * ── The problem ──────────────────────────────────────────────────────────────
9
+ * In vendored mode, `bridge.protocol.ts` / `job-handler.base.ts` could import
10
+ * `EventTypeName` / `EventOfType` straight from the consumer's vendored
11
+ * `./generated/types` (a sibling file). In package mode the runtime is consumed
12
+ * from the published `@pattern-stack/codegen`, whose bundled
13
+ * `events/generated/types.ts` is the codegen-patterns repo's OWN fixture union
14
+ * (`contact_created`, `deal_created`, …). Keying the bridge/trigger types off
15
+ * THAT union rejects the consumer's events (`'inbound_webhook_received' is not
16
+ * assignable to '"contact_created" | …'`).
17
+ *
18
+ * ── The fix ──────────────────────────────────────────────────────────────────
19
+ * `EventTypeName` (as used by the bridge/trigger types) derives from an EMPTY,
20
+ * augmentable `DomainEventRegistry` interface instead of the bundled concrete
21
+ * union. A package-mode consumer's generated events code emits a
22
+ * `declare module '@pattern-stack/codegen/runtime/subsystems/events/index' {
23
+ * interface DomainEventRegistry { <their_event>: <TheirEvent>; … } }`
24
+ * augmentation, so in the consumer's tsc program `keyof DomainEventRegistry`
25
+ * picks up THEIR events and `EventOfType<T>` resolves THEIR concrete payloads.
26
+ *
27
+ * In the package's OWN program (and any consumer that authors no events) the
28
+ * interface is never augmented, so `keyof DomainEventRegistry` is `never` and
29
+ * `EventTypeName` falls back to `string` — the bridge/trigger types degrade to
30
+ * `Record<string, …>` / `(event: DomainEvent) => …`, exactly the loose-but-
31
+ * sound shape that keeps the package's fixture-based runtime tests green.
32
+ *
33
+ * The bundled `events/generated/{types,bus,schemas}.ts` keep their concrete
34
+ * fixture union locally (the bundled `TypedEventBus` keys off `./types`, NOT
35
+ * this file), so they do NOT augment `DomainEventRegistry` and never leak the
36
+ * fixtures into a consumer's `EventTypeName` — even though the consumer pulls
37
+ * `generated/types.d.ts` in transitively via the events index barrel.
38
+ */
39
+ import type { DomainEvent } from './event-bus.protocol';
40
+
41
+ /**
42
+ * Empty marker interface, augmented by a consumer's generated events code via
43
+ * declaration merging on the events index module specifier
44
+ * (`@pattern-stack/codegen/runtime/subsystems/events/index`). Each key is an
45
+ * event `type` literal; each value is the event's concrete interface (extends
46
+ * `DomainEvent`). Empty in the package and in any project that declares no
47
+ * `events/*.yaml`.
48
+ *
49
+ * Intentionally NOT augmented by the package's own bundled
50
+ * `events/generated/types.ts` — those fixtures stay local to the bundled
51
+ * `TypedEventBus` so they never widen a consumer's `EventTypeName`.
52
+ *
53
+ * Must be an `interface` (only interfaces merge across module boundaries) and
54
+ * empty by design — a consumer augments it via declaration merging.
55
+ */
56
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
57
+ export interface DomainEventRegistry {}
58
+
59
+ /**
60
+ * Union of registered event `type` literals. When the registry is augmented
61
+ * (package-mode consumer with events) this is their event-type union; when it's
62
+ * empty (the package itself, or a no-events project) it falls back to `string`
63
+ * so the bridge/trigger types stay sound rather than collapsing to `never`.
64
+ */
65
+ export type EventTypeName = keyof DomainEventRegistry extends never
66
+ ? string
67
+ : keyof DomainEventRegistry & string;
68
+
69
+ /**
70
+ * The concrete event interface for a given `type`. Resolves to the consumer's
71
+ * registered interface when the registry knows `T`; otherwise (the fallback
72
+ * `string` case, or an unregistered literal) widens to the structural
73
+ * `DomainEvent` base so `event.type` / `event.id` / `event.payload` are still
74
+ * typed (payloads as `Record<string, unknown>`).
75
+ */
76
+ export type EventOfType<T extends EventTypeName> =
77
+ T extends keyof DomainEventRegistry ? DomainEventRegistry[T] : DomainEvent;
@@ -44,7 +44,7 @@
44
44
  * `new Class()` which silently left `db` / `redisUrl` undefined
45
45
  * (issue #108).
46
46
  */
47
- import { Module, type DynamicModule, type Provider } from '@nestjs/common';
47
+ import { Module, type DynamicModule, type Provider, type Type } from '@nestjs/common';
48
48
  import {
49
49
  EVENT_BUS,
50
50
  EVENT_READ_PORT,
@@ -112,6 +112,31 @@ export interface EventsModuleOptions {
112
112
  * Defaults to `false`.
113
113
  */
114
114
  multiTenant?: boolean;
115
+ /**
116
+ * The generated `TypedEventBus` class to bind to `TYPED_EVENT_BUS`.
117
+ *
118
+ * **Package mode (ADR-037).** When the runtime is imported from
119
+ * `@pattern-stack/codegen` (not vendored), the bundled `./generated/bus`
120
+ * `TypedEventBus` is typed to an EMPTY event union and reads the bundled
121
+ * empty `eventRegistry` — a consumer's `events/*.yaml` are scanned into
122
+ * `src/generated/events/bus.ts` (typed to THEIR union, reading THEIR
123
+ * registry), which the package can't import. The generated subsystem barrel
124
+ * therefore threads that class in here:
125
+ * `EventsModule.forRoot({ ..., typedBus: TypedEventBus })`. Nest constructs
126
+ * it with this module's `EVENT_BUS` + `EVENTS_MULTI_TENANT` providers (the
127
+ * generated class injects the same string-valued tokens, which match across
128
+ * the package boundary).
129
+ *
130
+ * Omitted (vendored mode / tests) ⇒ falls back to the bundled
131
+ * `./generated/bus`, which in a vendored tree IS the consumer's generated
132
+ * file. Without this, a package-mode consumer's typed `publish<'…'>()` calls
133
+ * resolve against the empty union and their events never get the right
134
+ * `pool` / `direction` stamped.
135
+ *
136
+ * Only consulted by `forRoot` (the path the barrel emits); `forRootAsync`
137
+ * keeps the bundled bus.
138
+ */
139
+ typedBus?: Type<unknown>;
115
140
  }
116
141
 
117
142
  export interface EventsModuleAsyncOptions {
@@ -125,10 +150,18 @@ export interface EventsModuleAsyncOptions {
125
150
  * binding, and the resolved `EVENTS_MULTI_TENANT` flag. Returned from one
126
151
  * place so every `forRoot` branch and `forRootAsync` agree.
127
152
  */
128
- function buildTypedBusProviders(multiTenant: boolean): Provider[] {
153
+ function buildTypedBusProviders(
154
+ multiTenant: boolean,
155
+ typedBus?: Type<unknown>,
156
+ ): Provider[] {
157
+ // Package mode threads the consumer's generated `TypedEventBus` (typed to
158
+ // their event union, reading their registry) via `typedBus`; vendored mode
159
+ // omits it and we fall back to the bundled `./generated/bus` (which IS the
160
+ // consumer's generated file in a vendored tree). See `EventsModuleOptions.typedBus`.
161
+ const BusClass = typedBus ?? TypedEventBus;
129
162
  return [
130
- TypedEventBus,
131
- { provide: TYPED_EVENT_BUS, useExisting: TypedEventBus },
163
+ BusClass,
164
+ { provide: TYPED_EVENT_BUS, useExisting: BusClass },
132
165
  { provide: EVENTS_MULTI_TENANT, useValue: multiTenant },
133
166
  ];
134
167
  }
@@ -249,7 +282,7 @@ export class EventsModule {
249
282
  },
250
283
  inject: [REDIS_URL],
251
284
  },
252
- ...buildTypedBusProviders(multiTenant),
285
+ ...buildTypedBusProviders(multiTenant, options.typedBus),
253
286
  ],
254
287
  exports: [EVENT_BUS, TYPED_EVENT_BUS, EVENTS_MULTI_TENANT],
255
288
  };
@@ -270,7 +303,7 @@ export class EventsModule {
270
303
  // IEventReadPort on the same instance as EVENT_BUS. The redis
271
304
  // backend retains no history and does not provide this token.
272
305
  { provide: EVENT_READ_PORT, useExisting: EVENT_BUS },
273
- ...buildTypedBusProviders(multiTenant),
306
+ ...buildTypedBusProviders(multiTenant, options.typedBus),
274
307
  ],
275
308
  exports: [EVENT_BUS, EVENT_READ_PORT, TYPED_EVENT_BUS, EVENTS_MULTI_TENANT],
276
309
  };
@@ -4,6 +4,18 @@
4
4
  * Import the module in AppModule, inject the bus via EVENT_BUS token.
5
5
  */
6
6
  export type { DomainEvent, IEventBus, DrizzleTransaction } from './event-bus.protocol';
7
+ // Augmentable event registry (ADR-037, package-mode trigger typing). A
8
+ // package-mode consumer's generated events code augments `DomainEventRegistry`
9
+ // via `declare module '@pattern-stack/codegen/runtime/subsystems/events/index'`
10
+ // so the bridge + job-trigger types pick up THEIR events with full payload
11
+ // typing. `EventTypeName` / `EventOfType` are re-exported here (the public
12
+ // barrel is the stable augmentation target); they derive from the registry, NOT
13
+ // the bundled fixture union the generated `./generated/types` re-export carries.
14
+ export type {
15
+ DomainEventRegistry,
16
+ EventTypeName,
17
+ EventOfType,
18
+ } from './event-registry';
7
19
  export type {
8
20
  IEventReadPort,
9
21
  ListEventsQuery,
@@ -17,7 +17,7 @@
17
17
  // TODO(logging-subsystem): swap to ILogger once ADR-028 lands
18
18
  import type { Logger } from '@nestjs/common';
19
19
  import { tokenKey } from '../token-key';
20
- import type { EventOfType, EventTypeName } from '../events/generated/types';
20
+ import type { EventOfType, EventTypeName } from '../events/event-registry';
21
21
  import type { JobRun } from './job-orchestrator.protocol';
22
22
 
23
23
  // ─── ParentClosePolicy ──────────────────────────────────────────────────────