@pattern-stack/codegen 0.4.2 → 0.4.4

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 (31) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/runtime/subsystems/bridge/bridge.module.d.ts +1 -0
  3. package/dist/runtime/subsystems/bridge/bridge.module.js +42 -23
  4. package/dist/runtime/subsystems/bridge/bridge.module.js.map +1 -1
  5. package/dist/runtime/subsystems/bridge/index.d.ts +1 -0
  6. package/dist/runtime/subsystems/bridge/index.js +33 -14
  7. package/dist/runtime/subsystems/bridge/index.js.map +1 -1
  8. package/dist/runtime/subsystems/index.js +35 -16
  9. package/dist/runtime/subsystems/index.js.map +1 -1
  10. package/dist/runtime/subsystems/jobs/index.d.ts +1 -0
  11. package/dist/runtime/subsystems/jobs/index.js +31 -12
  12. package/dist/runtime/subsystems/jobs/index.js.map +1 -1
  13. package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.d.ts +3 -1
  14. package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js +10 -4
  15. package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js.map +1 -1
  16. package/dist/runtime/subsystems/jobs/job-worker.d.ts +3 -1
  17. package/dist/runtime/subsystems/jobs/job-worker.js +7 -2
  18. package/dist/runtime/subsystems/jobs/job-worker.js.map +1 -1
  19. package/dist/runtime/subsystems/jobs/job-worker.module.d.ts +3 -1
  20. package/dist/runtime/subsystems/jobs/job-worker.module.js +31 -12
  21. package/dist/runtime/subsystems/jobs/job-worker.module.js.map +1 -1
  22. package/dist/runtime/subsystems/jobs/jobs-domain.module.js +10 -4
  23. package/dist/runtime/subsystems/jobs/jobs-domain.module.js.map +1 -1
  24. package/dist/src/cli/index.js +71 -7
  25. package/dist/src/cli/index.js.map +1 -1
  26. package/dist/src/index.js +27 -2
  27. package/dist/src/index.js.map +1 -1
  28. package/package.json +1 -1
  29. package/runtime/subsystems/jobs/job-orchestrator.memory-backend.ts +16 -2
  30. package/runtime/subsystems/jobs/job-worker.module.ts +20 -2
  31. package/runtime/subsystems/jobs/job-worker.ts +18 -3
package/CHANGELOG.md CHANGED
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.4.4] — 2026-04-23
8
+
9
+ ### Fixed
10
+
11
+ - **`fix(jobs)` #197 — SEVERITY: silent pool-level outage.** `JobWorkerModule` was passing `def.queue` (e.g. `'jobs-crm-sync'`) as the worker's claim-filter pool, but the orchestrator writes the logical `poolName` (e.g. `'crm_sync'`) into `job_run.pool` from `@JobHandler.meta.pool`. As a result, **no job in any stack using `@JobHandler` was ever claimed by a worker** — the claim query never matched a row, zero exceptions were raised, and the pool sat idle. Every consumer of the jobs subsystem since pools-and-queues diverged was affected. Fixed by passing `poolName` as the worker's `pool`. If you ran 0.4.0–0.4.3 with `@JobHandler` handlers: any jobs enqueued in that window are still pending in `job_run` with `status='pending'` and will now claim on next worker tick.
12
+ - **`fix(jobs)` #197 — cross-module handler DI scope.** `moduleRef.create(HandlerClass)` only instantiates within `JobWorkerModule`'s scope, so any handler with a cross-module `@Inject` dep (e.g. a sync job injecting a factory from a feature module) crashed at claim time with "not a provider of the current module". The 0.4.3 `ModuleRef` fix was necessary but not sufficient. Switched to `moduleRef.get(HandlerClass, { strict: false })` in both the Drizzle worker and the in-memory orchestrator, which walks the whole DI graph. **New hard requirement**: handler classes MUST be registered as providers in their owning `@Module`. `@JobHandler` registers with the job registry, not with Nest DI — both registrations are required. Documented in `.claude/skills/jobs/handler-authoring.md`.
13
+
14
+ ### Added
15
+
16
+ - **`feat(events)` #198 — `type: array` payload field.** Closes a silent validation hole. Payloads with list-shaped fields had no well-typed representation; the only option was `type: json`, which emits `Record<string, unknown>` / `z.record(z.unknown())`. At publish time the runtime Zod validator rejected actual arrays, the event was dropped, and downstream `bridge_delivery` rows never landed — with no surfaced error. Now: `type: array` with a required scalar `items:` (`uuid | string | number | boolean | date`) emits `T[]` + `z.array(T)`. Nested arrays / nested json inside an array are deliberately rejected — payloads are a wire format, not an embedded schema. Consumer migration: change any list-shaped payload field from `type: json` to `type: array, items: <scalar>`, re-run `codegen events`, drop any `as unknown as Record<string, unknown>` publish-site casts.
17
+
18
+ ## [0.4.3] — 2026-04-22
19
+
20
+ ### Fixed
21
+ - **`fix(jobs)`** — handlers are now instantiated via `ModuleRef` so `@Inject()`-annotated constructor parameters resolve correctly. Applies to both the Drizzle and in-memory job backends. Before this fix, handlers with DI-injected dependencies would fail at runtime because the worker constructed them outside Nest's container. (commits e7348cd, c685a63)
22
+ - **`fix(bridge)` #193** — bridge registry codegen is gated on the bridge subsystem being installed (PR #192), and `bridgeHandlersDir` now resolves under `paths.backend_src` instead of hard-coding `src/jobs` (PR #194). Together these close the "stray `src/shared/subsystems/bridge/generated/registry.ts` with broken `../bridge.protocol` import" bug for both the "bridge declared in config but not installed" case and the "installed with non-default backend_src so triggers were never scanned" case.
23
+
7
24
  ## [0.4.1] — 2026-04-21
8
25
 
9
26
  ### Added
@@ -1,5 +1,6 @@
1
1
  import { OnModuleInit, DynamicModule } from '@nestjs/common';
2
2
  import { JobWorkerModuleOptions } from '../jobs/job-worker.module.js';
3
+ import '@nestjs/core';
3
4
  import '../../types/drizzle.js';
4
5
  import 'drizzle-orm/node-postgres';
5
6
  import '../jobs/jobs-domain.module.js';
@@ -14,7 +14,7 @@ var __decorateParam = (index4, decorator) => (target, key2) => decorator(target,
14
14
  import {
15
15
  Inject as Inject12,
16
16
  Module as Module3,
17
- Optional as Optional6
17
+ Optional as Optional7
18
18
  } from "@nestjs/common";
19
19
 
20
20
  // runtime/subsystems/jobs/job-worker.module.ts
@@ -23,7 +23,7 @@ import {
23
23
  Injectable as Injectable8,
24
24
  Logger as Logger4,
25
25
  Module as Module2,
26
- Optional
26
+ Optional as Optional2
27
27
  } from "@nestjs/common";
28
28
 
29
29
  // runtime/constants/tokens.ts
@@ -797,7 +797,7 @@ DrizzleJobStepService = __decorateClass([
797
797
 
798
798
  // runtime/subsystems/jobs/job-orchestrator.memory-backend.ts
799
799
  import { randomUUID as randomUUID2 } from "crypto";
800
- import { Inject as Inject4, Injectable as Injectable4, Logger as Logger2 } from "@nestjs/common";
800
+ import { Inject as Inject4, Injectable as Injectable4, Logger as Logger2, Optional } from "@nestjs/common";
801
801
  var QUEUED_RUN_AT = /* @__PURE__ */ new Date(864e13);
802
802
  var TERMINAL_STATUSES2 = [
803
803
  "completed",
@@ -834,14 +834,16 @@ var PromiseMutex = class {
834
834
  }
835
835
  };
836
836
  var MemoryJobOrchestrator = class {
837
- constructor(store, stepService, multiTenant) {
837
+ constructor(store, stepService, multiTenant, moduleRef) {
838
838
  this.store = store;
839
839
  this.stepService = stepService;
840
840
  this.multiTenant = multiTenant;
841
+ this.moduleRef = moduleRef;
841
842
  }
842
843
  store;
843
844
  stepService;
844
845
  multiTenant;
846
+ moduleRef;
845
847
  logger = new Logger2(MemoryJobOrchestrator.name);
846
848
  mutex = new PromiseMutex();
847
849
  handlerRegistry = /* @__PURE__ */ new Map();
@@ -1182,7 +1184,10 @@ var MemoryJobOrchestrator = class {
1182
1184
  }
1183
1185
  const meta = registration.meta;
1184
1186
  const HandlerClass = registration.handlerClass;
1185
- const handler = new HandlerClass();
1187
+ const handler = this.moduleRef ? this.moduleRef.get(
1188
+ HandlerClass,
1189
+ { strict: false }
1190
+ ) : new HandlerClass();
1186
1191
  const ctx = {
1187
1192
  input: run.input,
1188
1193
  run,
@@ -1362,7 +1367,8 @@ var MemoryJobOrchestrator = class {
1362
1367
  };
1363
1368
  MemoryJobOrchestrator = __decorateClass([
1364
1369
  Injectable4(),
1365
- __decorateParam(2, Inject4(JOBS_MULTI_TENANT))
1370
+ __decorateParam(2, Inject4(JOBS_MULTI_TENANT)),
1371
+ __decorateParam(3, Optional())
1366
1372
  ], MemoryJobOrchestrator);
1367
1373
  function classifyError(err, policy, currentAttempts) {
1368
1374
  if (!policy) return "fail";
@@ -1826,12 +1832,13 @@ function serialiseError2(err, attempt, retryable) {
1826
1832
  };
1827
1833
  }
1828
1834
  var JobWorker = class {
1829
- constructor(db, orchestrator, runService, stepService, options) {
1835
+ constructor(db, orchestrator, runService, stepService, options, moduleRef) {
1830
1836
  this.db = db;
1831
1837
  this.orchestrator = orchestrator;
1832
1838
  this.runService = runService;
1833
1839
  this.stepService = stepService;
1834
1840
  this.options = options;
1841
+ this.moduleRef = moduleRef;
1835
1842
  this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
1836
1843
  this.staleSweeperIntervalMs = options.staleSweeperIntervalMs ?? DEFAULT_STALE_SWEEPER_INTERVAL_MS;
1837
1844
  this.staleThresholdMs = options.staleThresholdMs ?? DEFAULT_STALE_THRESHOLD_MS;
@@ -1848,6 +1855,7 @@ var JobWorker = class {
1848
1855
  runService;
1849
1856
  stepService;
1850
1857
  options;
1858
+ moduleRef;
1851
1859
  logger = new Logger3(JobWorker.name);
1852
1860
  shuttingDown = false;
1853
1861
  inFlight = /* @__PURE__ */ new Set();
@@ -2019,7 +2027,10 @@ var JobWorker = class {
2019
2027
  }
2020
2028
  const meta = registryEntry.meta;
2021
2029
  const HandlerClass = registryEntry.handlerClass;
2022
- const handler = new HandlerClass();
2030
+ const handler = this.moduleRef.get(
2031
+ HandlerClass,
2032
+ { strict: false }
2033
+ );
2023
2034
  const ctx = {
2024
2035
  input: claimed.input,
2025
2036
  run: claimed,
@@ -2179,18 +2190,20 @@ JobWorker = __decorateClass([
2179
2190
  var DEFAULT_SHUTDOWN_TIMEOUT_MS2 = 3e4;
2180
2191
  var JOB_WORKER_MODULE_OPTIONS = /* @__PURE__ */ Symbol("JOB_WORKER_MODULE_OPTIONS");
2181
2192
  var JobWorkerOrchestrator = class {
2182
- constructor(orchestrator, runService, stepService, options, db = null) {
2193
+ constructor(orchestrator, runService, stepService, options, db = null, moduleRef) {
2183
2194
  this.orchestrator = orchestrator;
2184
2195
  this.runService = runService;
2185
2196
  this.stepService = stepService;
2186
2197
  this.options = options;
2187
2198
  this.db = db;
2199
+ this.moduleRef = moduleRef;
2188
2200
  }
2189
2201
  orchestrator;
2190
2202
  runService;
2191
2203
  stepService;
2192
2204
  options;
2193
2205
  db;
2206
+ moduleRef;
2194
2207
  logger = new Logger4(JobWorkerOrchestrator.name);
2195
2208
  workers = [];
2196
2209
  // ============================================================================
@@ -2217,7 +2230,7 @@ var JobWorkerOrchestrator = class {
2217
2230
  );
2218
2231
  }
2219
2232
  const workerOptions = {
2220
- pool: def.queue,
2233
+ pool: poolName,
2221
2234
  concurrency: def.concurrency,
2222
2235
  shutdownTimeoutMs: this.options.shutdownTimeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS2
2223
2236
  };
@@ -2225,7 +2238,7 @@ var JobWorkerOrchestrator = class {
2225
2238
  worker.onModuleInit();
2226
2239
  this.workers.push(worker);
2227
2240
  this.logger.log(
2228
- `JobWorker started: pool='${def.queue}' concurrency=${def.concurrency}`
2241
+ `JobWorker started: pool='${poolName}' (queue='${def.queue}') concurrency=${def.concurrency}`
2229
2242
  );
2230
2243
  }
2231
2244
  }
@@ -2289,12 +2302,18 @@ var JobWorkerOrchestrator = class {
2289
2302
  `JobWorkerModule: in-process worker spawning requires the Drizzle backend (no DRIZZLE provider available). Memory-mode tests must pass 'workerFactory' to inject a stub.`
2290
2303
  );
2291
2304
  }
2305
+ if (!this.moduleRef) {
2306
+ throw new Error(
2307
+ `JobWorkerModule: ModuleRef not available \u2014 cannot construct JobWorker with handler DI support. Ensure the orchestrator is resolved through the Nest container (not instantiated manually in tests).`
2308
+ );
2309
+ }
2292
2310
  return new JobWorker(
2293
2311
  this.db,
2294
2312
  this.orchestrator,
2295
2313
  this.runService,
2296
2314
  this.stepService,
2297
- workerOptions
2315
+ workerOptions,
2316
+ this.moduleRef
2298
2317
  );
2299
2318
  }
2300
2319
  };
@@ -2304,7 +2323,7 @@ JobWorkerOrchestrator = __decorateClass([
2304
2323
  __decorateParam(1, Inject7(JOB_RUN_SERVICE)),
2305
2324
  __decorateParam(2, Inject7(JOB_STEP_SERVICE)),
2306
2325
  __decorateParam(3, Inject7(JOB_WORKER_MODULE_OPTIONS)),
2307
- __decorateParam(4, Optional()),
2326
+ __decorateParam(4, Optional2()),
2308
2327
  __decorateParam(4, Inject7(DRIZZLE))
2309
2328
  ], JobWorkerOrchestrator);
2310
2329
  var JobWorkerModule = class {
@@ -2456,7 +2475,7 @@ var MemoryBridgeDeliveryRepo = class {
2456
2475
  };
2457
2476
 
2458
2477
  // runtime/subsystems/bridge/bridge-delivery.drizzle-backend.ts
2459
- import { Inject as Inject8, Injectable as Injectable9, Optional as Optional2 } from "@nestjs/common";
2478
+ import { Inject as Inject8, Injectable as Injectable9, Optional as Optional3 } from "@nestjs/common";
2460
2479
  import { eq as eq5, and as and5 } from "drizzle-orm";
2461
2480
 
2462
2481
  // runtime/subsystems/bridge/bridge-delivery.schema.ts
@@ -2649,16 +2668,16 @@ var DrizzleBridgeDeliveryRepo = class {
2649
2668
  DrizzleBridgeDeliveryRepo = __decorateClass([
2650
2669
  Injectable9(),
2651
2670
  __decorateParam(0, Inject8(DRIZZLE)),
2652
- __decorateParam(1, Optional2()),
2671
+ __decorateParam(1, Optional3()),
2653
2672
  __decorateParam(1, Inject8(BRIDGE_MULTI_TENANT))
2654
2673
  ], DrizzleBridgeDeliveryRepo);
2655
2674
 
2656
2675
  // runtime/subsystems/bridge/bridge-outbox-drain-hook.ts
2657
- import { Inject as Inject10, Injectable as Injectable11, Logger as Logger6, Optional as Optional4 } from "@nestjs/common";
2676
+ import { Inject as Inject10, Injectable as Injectable11, Logger as Logger6, Optional as Optional5 } from "@nestjs/common";
2658
2677
  import { randomUUID as randomUUID5 } from "crypto";
2659
2678
 
2660
2679
  // runtime/subsystems/bridge/bridge-delivery-handler.ts
2661
- import { Inject as Inject9, Injectable as Injectable10, Logger as Logger5, Optional as Optional3 } from "@nestjs/common";
2680
+ import { Inject as Inject9, Injectable as Injectable10, Logger as Logger5, Optional as Optional4 } from "@nestjs/common";
2662
2681
 
2663
2682
  // runtime/subsystems/events/events.tokens.ts
2664
2683
  var EVENT_BUS = "EVENT_BUS";
@@ -2751,7 +2770,7 @@ BridgeDeliveryHandler = __decorateClass([
2751
2770
  __decorateParam(1, Inject9(JOB_ORCHESTRATOR)),
2752
2771
  __decorateParam(2, Inject9(EVENT_BUS)),
2753
2772
  __decorateParam(3, Inject9(BRIDGE_REGISTRY)),
2754
- __decorateParam(4, Optional3()),
2773
+ __decorateParam(4, Optional4()),
2755
2774
  __decorateParam(4, Inject9(BRIDGE_MULTI_TENANT))
2756
2775
  ], BridgeDeliveryHandler);
2757
2776
 
@@ -2828,12 +2847,12 @@ var BridgeOutboxDrainHook = class {
2828
2847
  };
2829
2848
  BridgeOutboxDrainHook = __decorateClass([
2830
2849
  Injectable11(),
2831
- __decorateParam(0, Optional4()),
2850
+ __decorateParam(0, Optional5()),
2832
2851
  __decorateParam(0, Inject10(BRIDGE_REGISTRY))
2833
2852
  ], BridgeOutboxDrainHook);
2834
2853
 
2835
2854
  // runtime/subsystems/bridge/event-flow.service.ts
2836
- import { Inject as Inject11, Injectable as Injectable12, Optional as Optional5 } from "@nestjs/common";
2855
+ import { Inject as Inject11, Injectable as Injectable12, Optional as Optional6 } from "@nestjs/common";
2837
2856
  var EventFlowService = class {
2838
2857
  constructor(db, eventBus, orchestrator, bridgeRepo, registry = {}, multiTenant = false) {
2839
2858
  this.db = db;
@@ -2909,9 +2928,9 @@ EventFlowService = __decorateClass([
2909
2928
  __decorateParam(1, Inject11(EVENT_BUS)),
2910
2929
  __decorateParam(2, Inject11(JOB_ORCHESTRATOR)),
2911
2930
  __decorateParam(3, Inject11(BRIDGE_DELIVERY_REPO)),
2912
- __decorateParam(4, Optional5()),
2931
+ __decorateParam(4, Optional6()),
2913
2932
  __decorateParam(4, Inject11(BRIDGE_REGISTRY)),
2914
- __decorateParam(5, Optional5()),
2933
+ __decorateParam(5, Optional6()),
2915
2934
  __decorateParam(5, Inject11(BRIDGE_MULTI_TENANT))
2916
2935
  ], EventFlowService);
2917
2936
 
@@ -2989,7 +3008,7 @@ var BridgeModule = class {
2989
3008
  };
2990
3009
  BridgeModule = __decorateClass([
2991
3010
  Module3({}),
2992
- __decorateParam(0, Optional6()),
3011
+ __decorateParam(0, Optional7()),
2993
3012
  __decorateParam(0, Inject12(JOB_WORKER_MODULE_OPTIONS))
2994
3013
  ], BridgeModule);
2995
3014
  export {