@pattern-stack/codegen 0.14.1 → 0.15.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/CHANGELOG.md CHANGED
@@ -4,6 +4,94 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.15.0] — 2026-06-02
8
+
9
+ Package-mode consumer **events** — the seam that lets a project consuming the
10
+ runtime from the package (`runtime: package`, ADR-037) declare its own
11
+ `events/*.yaml`, get a typed `TypedEventBus`, and publish typed domain events.
12
+ Completes the package-mode story alongside 0.14.2's bridge fixes. Vendored mode
13
+ is byte-stable; everything here is additive.
14
+
15
+ ### Added
16
+
17
+ - **`EventsModuleOptions.typedBus?: Type<unknown>`** — binds a consumer-supplied
18
+ `TypedEventBus` class to `TYPED_EVENT_BUS` (via `forRoot`). Omitted ⇒ falls
19
+ back to the bundled `./generated/bus` (which IS the consumer's generated file
20
+ in a vendored tree), so existing consumers and tests are unaffected. Nest
21
+ constructs the supplied class with this module's `EVENT_BUS` +
22
+ `EVENTS_MULTI_TENANT` providers (string-valued tokens match across the package
23
+ boundary).
24
+
25
+ ### Fixed
26
+
27
+ - **Event codegen is package-mode-aware.** Previously `entity new --all` in
28
+ package mode wrote the five generated event files
29
+ (`types/schemas/registry/bus/index.ts`) into a stray
30
+ `src/shared/subsystems/events/generated/` tree whose `../event-bus.protocol` /
31
+ `../events.tokens` / `../events-errors` imports don't exist in package mode —
32
+ the tree didn't typecheck and was orphaned (the bundled empty `TypedEventBus`
33
+ won at runtime). Now in package mode the files land in the consumer's
34
+ `src/generated/events/`, those three runtime imports resolve through the
35
+ published `@pattern-stack/codegen/runtime/subsystems/events/index` barrel, and
36
+ the subsystem barrel threads the generated `TypedEventBus` into
37
+ `EventsModule.forRoot({ typedBus })`. A package-mode consumer's typed
38
+ `publish<'…'>()` now resolves against THEIR event union and stamps the right
39
+ `pool` / `direction`.
40
+ - **Scope-entity-type is package-mode-aware** — relocated to
41
+ `src/generated/scope-entity-type.ts` (a self-contained zod-only union) instead
42
+ of the stray vendored `jobs/generated/` path.
43
+ - **Package-mode bridge trigger validation now runs.** Because the consumer's
44
+ event registry now exists at a real path (`src/generated/events/registry.ts`),
45
+ the bridge registry generator validates `@JobHandler.triggers` event types
46
+ against it (the 0.14.2 "known gap"). `subsystem install events` drops an
47
+ empty-set `src/generated/events/` stub so the barrel's `./events/bus` import
48
+ never dangles before the next `entity new`.
49
+
50
+ ## [0.14.2] — 2026-06-02
51
+
52
+ Package-mode bridge fixes — the two gaps that left the event→job bridge wired but
53
+ inert when the runtime is consumed from the package (`runtime: package`, ADR-037)
54
+ rather than vendored. Both are follow-ons to 0.14.1's package-mode subsystem
55
+ support. Vendored mode is unchanged; these are additive.
56
+
57
+ ### Fixed
58
+
59
+ - **Embedded worker now drains the reserved `events_*` bridge pools.** The
60
+ subsystem barrel emitted `JobWorkerModule.forRoot({ mode: 'embedded' })` with no
61
+ pool list, so the in-process worker polled only `interactive` + `batch` and
62
+ bridge wrappers sat pending forever (the BRIDGE-8 footgun, just past the boot
63
+ guard). When `bridge` is in `subsystems.install`, the embedded worker now
64
+ defaults to `allPools: true` (every lane in-process — exactly the knob
65
+ `BridgeModule`'s reserved-pool guard short-circuits on).
66
+ - **A package-mode consumer's `@JobHandler.triggers` now bind.** Previously
67
+ `BridgeModule` hardwired the bundled `./generated/registry` placeholder (frozen
68
+ `{}` inside the package), and the registry generator skipped entirely in package
69
+ mode (it gated on a vendored `bridge.protocol.ts` that doesn't exist), so no
70
+ event ever routed to a job. The registry is now generated into the consumer's
71
+ `src/generated/bridge-registry.ts` (type imported from
72
+ `@pattern-stack/codegen/runtime/subsystems/bridge/index`, install gated on
73
+ `subsystems.install`) and threaded into `BridgeModule.forRoot({ registry })` by
74
+ the barrel. `subsystem install bridge` drops an empty-registry stub so the
75
+ import never dangles before the next `entity new`.
76
+
77
+ ### Added
78
+
79
+ - **`BridgeModuleOptions.registry?: BridgeRegistry`** — lets the generated barrel
80
+ supply the consumer's scanned registry. Omitted ⇒ falls back to the bundled
81
+ `./generated/registry` (which IS the consumer's generated file in vendored
82
+ mode), so existing consumers and tests are unaffected.
83
+ - **`jobs.worker_pools: string[]` and `jobs.all_pools: true`** config knobs on the
84
+ embedded worker. Precedence: explicit `worker_pools` (→ `pools: [...]`) >
85
+ `all_pools` (→ `allPools: true`) > bridge-installed default (`allPools: true`) >
86
+ the non-reserved default (unchanged).
87
+
88
+ ### Known gaps
89
+
90
+ - Package-mode trigger-event **validation** against the events registry is skipped
91
+ (the event codegen generator is not yet mode-aware, so its registry isn't found
92
+ under the package-mode generated path). Triggers still generate and bind; only
93
+ the build-time "unknown event" check is inert. Tracked for a follow-on.
94
+
7
95
  ## [0.13.0] — 2026-05-31
8
96
 
9
97
  Track D round-2/3 — the integration codegen now emits the **full** integration
@@ -1,5 +1,6 @@
1
1
  import { OnModuleInit, DynamicModule } from '@nestjs/common';
2
2
  import { JobWorkerModuleOptions } from '../jobs/job-worker.module.js';
3
+ import { BridgeRegistry } from './bridge.protocol.js';
3
4
  import '@nestjs/core';
4
5
  import '../../types/drizzle.js';
5
6
  import 'drizzle-orm/node-postgres';
@@ -15,6 +16,7 @@ import '../events/generated/types.js';
15
16
  import '../jobs/job-run-service.protocol.js';
16
17
  import '../jobs/job-step-service.protocol.js';
17
18
  import '../jobs/job-worker.js';
19
+ import './bridge-delivery.schema.js';
18
20
 
19
21
  /**
20
22
  * BridgeModule — `DynamicModule.forRoot({ backend, multiTenant })`
@@ -75,6 +77,26 @@ interface BridgeModuleOptions {
75
77
  * `null` always passes (cross-tenant work). Defaults to `false`.
76
78
  */
77
79
  multiTenant?: boolean;
80
+ /**
81
+ * The codegen-emitted `Record<EventTypeName, BridgeTriggerEntry[]>` that
82
+ * drives outbox-drain trigger lookup (BRIDGE-4) and the facade's Case B
83
+ * dedup (BRIDGE-7).
84
+ *
85
+ * **Package mode (ADR-037).** When the runtime is imported from
86
+ * `@pattern-stack/codegen` (not vendored), the bundled
87
+ * `./generated/registry` is a frozen empty placeholder (`{}`) — a
88
+ * consumer's `@JobHandler.triggers` are scanned into a registry that lives
89
+ * in THEIR `src/generated/bridge-registry.ts`, which the package can't
90
+ * import. The generated subsystem barrel therefore threads that registry in
91
+ * here: `BridgeModule.forRoot({ ..., registry: bridgeRegistry })`. Omitted
92
+ * (vendored mode / tests) ⇒ falls back to the bundled `./generated/registry`,
93
+ * which in vendored mode IS the consumer's freshly-generated file.
94
+ *
95
+ * Without this, package-mode consumers' triggers never bind and the bridge
96
+ * routes nothing (the "wrappers sit pending" footgun's silent twin —
97
+ * nothing is ever enqueued in the first place).
98
+ */
99
+ registry?: BridgeRegistry;
78
100
  }
79
101
  declare class BridgeModule implements OnModuleInit {
80
102
  private readonly workerOpts?;
@@ -3427,7 +3427,11 @@ var BridgeModule = class {
3427
3427
  providers: [
3428
3428
  { provide: BRIDGE_MODULE_OPTIONS, useValue: opts },
3429
3429
  { provide: BRIDGE_MULTI_TENANT, useValue: opts.multiTenant ?? false },
3430
- { provide: BRIDGE_REGISTRY, useValue: bridgeRegistry },
3430
+ // Package mode threads the consumer's generated registry through
3431
+ // `opts.registry`; vendored mode omits it and we fall back to the
3432
+ // bundled `./generated/registry` (which IS the consumer's generated
3433
+ // file in a vendored tree). See `BridgeModuleOptions.registry`.
3434
+ { provide: BRIDGE_REGISTRY, useValue: opts.registry ?? bridgeRegistry },
3431
3435
  repoProvider,
3432
3436
  // Drain hook — always wired; `DrizzleEventBus` consumes it via
3433
3437
  // `@Optional()`, so non-bridge mounts simply see `undefined`.