@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.
- package/CHANGELOG.md +17 -0
- package/dist/runtime/subsystems/bridge/bridge.module.d.ts +1 -0
- package/dist/runtime/subsystems/bridge/bridge.module.js +42 -23
- package/dist/runtime/subsystems/bridge/bridge.module.js.map +1 -1
- package/dist/runtime/subsystems/bridge/index.d.ts +1 -0
- package/dist/runtime/subsystems/bridge/index.js +33 -14
- package/dist/runtime/subsystems/bridge/index.js.map +1 -1
- package/dist/runtime/subsystems/index.js +35 -16
- package/dist/runtime/subsystems/index.js.map +1 -1
- package/dist/runtime/subsystems/jobs/index.d.ts +1 -0
- package/dist/runtime/subsystems/jobs/index.js +31 -12
- package/dist/runtime/subsystems/jobs/index.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.d.ts +3 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js +10 -4
- package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.d.ts +3 -1
- package/dist/runtime/subsystems/jobs/job-worker.js +7 -2
- package/dist/runtime/subsystems/jobs/job-worker.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.module.d.ts +3 -1
- package/dist/runtime/subsystems/jobs/job-worker.module.js +31 -12
- package/dist/runtime/subsystems/jobs/job-worker.module.js.map +1 -1
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js +10 -4
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js.map +1 -1
- package/dist/src/cli/index.js +71 -7
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.js +27 -2
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
- package/runtime/subsystems/jobs/job-orchestrator.memory-backend.ts +16 -2
- package/runtime/subsystems/jobs/job-worker.module.ts +20 -2
- 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
|
|
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 =
|
|
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 =
|
|
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:
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
2931
|
+
__decorateParam(4, Optional6()),
|
|
2913
2932
|
__decorateParam(4, Inject11(BRIDGE_REGISTRY)),
|
|
2914
|
-
__decorateParam(5,
|
|
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,
|
|
3011
|
+
__decorateParam(0, Optional7()),
|
|
2993
3012
|
__decorateParam(0, Inject12(JOB_WORKER_MODULE_OPTIONS))
|
|
2994
3013
|
], BridgeModule);
|
|
2995
3014
|
export {
|