@pattern-stack/codegen 0.23.0 → 0.25.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 +51 -1
- package/consumer-skills/integration/SKILL.md +11 -3
- package/dist/{chunk-XKWOJZZ4.js → chunk-37PILMIT.js} +4 -4
- package/dist/{chunk-2VHZ7EKC.js → chunk-5AAA4LTE.js} +2 -2
- package/dist/{chunk-42763UEE.js → chunk-6M6LZEP6.js} +2 -2
- package/dist/{chunk-AS3NAZB6.js → chunk-B7SC2V45.js} +2 -2
- package/dist/{chunk-W72PRNJY.js → chunk-BPYZCEHS.js} +2 -2
- package/dist/{chunk-FIUC6QB5.js → chunk-CKLM57IE.js} +10 -10
- package/dist/{chunk-KYR3B3OW.js → chunk-DAHWN63L.js} +26 -5
- package/dist/chunk-DAHWN63L.js.map +1 -0
- package/dist/{chunk-SH76CFAY.js → chunk-ENAR3F5S.js} +2 -2
- package/dist/{chunk-RFH7N6EP.js → chunk-FCPTHS42.js} +2 -2
- package/dist/{chunk-FFUDEIFF.js → chunk-HN5HT5WL.js} +2 -2
- package/dist/{chunk-4M66MQYA.js → chunk-K4BQQ2NN.js} +4 -2
- package/dist/chunk-K4BQQ2NN.js.map +1 -0
- package/dist/{chunk-QFUIE37H.js → chunk-KFXXOFDC.js} +4 -4
- package/dist/{chunk-O2A6XHGD.js → chunk-LLDJS7PJ.js} +2 -2
- package/dist/{chunk-JOBQ6RUU.js → chunk-LQZESSM3.js} +28 -1
- package/dist/chunk-LQZESSM3.js.map +1 -0
- package/dist/{chunk-JRQO2IOF.js → chunk-MU54DZCC.js} +27 -1
- package/dist/chunk-MU54DZCC.js.map +1 -0
- package/dist/{chunk-INO47JXD.js → chunk-PBENHIN2.js} +3 -3
- package/dist/{chunk-CLWBNXKF.js → chunk-PLUJEQLU.js} +2 -2
- package/dist/{chunk-S7C6TIIF.js → chunk-S5G3HO7N.js} +3 -1
- package/dist/chunk-S5G3HO7N.js.map +1 -0
- package/dist/{chunk-JYBFPNBJ.js → chunk-SJGEBMJT.js} +2 -2
- package/dist/{chunk-6XP2Q5SS.js → chunk-WZOPWQN2.js} +2 -2
- package/dist/{chunk-TDEHU73T.js → chunk-YIVQ7KLS.js} +46 -5
- package/dist/chunk-YIVQ7KLS.js.map +1 -0
- package/dist/runtime/base-classes/activity-entity-service.js +3 -3
- package/dist/runtime/base-classes/base-service.js +2 -2
- package/dist/runtime/base-classes/index.js +20 -20
- package/dist/runtime/base-classes/integrated-entity-service.js +3 -3
- package/dist/runtime/base-classes/knowledge-entity-service.js +3 -3
- package/dist/runtime/base-classes/lifecycle-events.js +1 -1
- package/dist/runtime/base-classes/metadata-entity-service.js +3 -3
- package/dist/runtime/subsystems/auth/auth.module.js +1 -1
- package/dist/runtime/subsystems/auth/index.js +3 -3
- package/dist/runtime/subsystems/bridge/bridge.module.js +6 -6
- package/dist/runtime/subsystems/bridge/index.js +6 -6
- package/dist/runtime/subsystems/events/events.module.js +4 -4
- package/dist/runtime/subsystems/events/generated/bus.js +3 -3
- package/dist/runtime/subsystems/events/generated/index.d.ts +2 -2
- package/dist/runtime/subsystems/events/generated/index.js +9 -3
- package/dist/runtime/subsystems/events/generated/registry.d.ts +36 -0
- package/dist/runtime/subsystems/events/generated/registry.js +1 -1
- package/dist/runtime/subsystems/events/generated/schemas.d.ts +109 -1
- package/dist/runtime/subsystems/events/generated/schemas.js +7 -1
- package/dist/runtime/subsystems/events/generated/types.d.ts +48 -2
- package/dist/runtime/subsystems/events/index.js +4 -4
- package/dist/runtime/subsystems/index.d.ts +3 -2
- package/dist/runtime/subsystems/index.js +25 -21
- package/dist/runtime/subsystems/integration/execute-integration.use-case.d.ts +11 -1
- package/dist/runtime/subsystems/integration/execute-integration.use-case.js +2 -2
- package/dist/runtime/subsystems/integration/index.d.ts +2 -1
- package/dist/runtime/subsystems/integration/index.js +10 -8
- package/dist/runtime/subsystems/integration/integration-change-emitter.protocol.d.ts +106 -0
- package/dist/runtime/subsystems/integration/integration-change-emitter.protocol.js +1 -0
- package/dist/runtime/subsystems/integration/integration-change-emitter.protocol.js.map +1 -0
- package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js +2 -2
- package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js +2 -2
- package/dist/runtime/subsystems/integration/integration.module.js +4 -4
- package/dist/runtime/subsystems/integration/integration.tokens.d.ts +11 -1
- package/dist/runtime/subsystems/integration/integration.tokens.js +3 -1
- package/dist/runtime/subsystems/jobs/index.js +11 -11
- package/dist/runtime/subsystems/jobs/job-worker.module.js +5 -5
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js +4 -4
- package/dist/runtime/subsystems/observability/index.js +3 -3
- package/dist/runtime/subsystems/observability/observability.module.js +3 -3
- package/dist/runtime/subsystems/observability/observability.service.js +2 -2
- package/dist/src/cli/index.js +300 -53
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.d.ts +13 -0
- package/dist/src/index.js +7 -7
- package/package.json +1 -1
- package/runtime/base-classes/lifecycle-events.ts +39 -6
- package/runtime/subsystems/events/generated/registry.ts +27 -0
- package/runtime/subsystems/events/generated/schemas.ts +26 -0
- package/runtime/subsystems/events/generated/types.ts +52 -0
- package/runtime/subsystems/index.ts +23 -0
- package/runtime/subsystems/integration/execute-integration.use-case.ts +69 -1
- package/runtime/subsystems/integration/index.ts +6 -0
- package/runtime/subsystems/integration/integration-change-emitter.protocol.ts +107 -0
- package/runtime/subsystems/integration/integration.tokens.ts +11 -0
- package/templates/subsystem/jobs/job-orchestration.schema.ejs.t +1 -0
- package/templates/subsystem/jobs/main-hook.ejs.t +1 -1
- package/templates/subsystem/jobs/prompt.js +40 -2
- package/templates/subsystem/jobs/worker.ejs.t +47 -35
- package/dist/chunk-4M66MQYA.js.map +0 -1
- package/dist/chunk-JOBQ6RUU.js.map +0 -1
- package/dist/chunk-JRQO2IOF.js.map +0 -1
- package/dist/chunk-KYR3B3OW.js.map +0 -1
- package/dist/chunk-S7C6TIIF.js.map +0 -1
- package/dist/chunk-TDEHU73T.js.map +0 -1
- /package/dist/{chunk-XKWOJZZ4.js.map → chunk-37PILMIT.js.map} +0 -0
- /package/dist/{chunk-2VHZ7EKC.js.map → chunk-5AAA4LTE.js.map} +0 -0
- /package/dist/{chunk-42763UEE.js.map → chunk-6M6LZEP6.js.map} +0 -0
- /package/dist/{chunk-AS3NAZB6.js.map → chunk-B7SC2V45.js.map} +0 -0
- /package/dist/{chunk-W72PRNJY.js.map → chunk-BPYZCEHS.js.map} +0 -0
- /package/dist/{chunk-FIUC6QB5.js.map → chunk-CKLM57IE.js.map} +0 -0
- /package/dist/{chunk-SH76CFAY.js.map → chunk-ENAR3F5S.js.map} +0 -0
- /package/dist/{chunk-RFH7N6EP.js.map → chunk-FCPTHS42.js.map} +0 -0
- /package/dist/{chunk-FFUDEIFF.js.map → chunk-HN5HT5WL.js.map} +0 -0
- /package/dist/{chunk-QFUIE37H.js.map → chunk-KFXXOFDC.js.map} +0 -0
- /package/dist/{chunk-O2A6XHGD.js.map → chunk-LLDJS7PJ.js.map} +0 -0
- /package/dist/{chunk-INO47JXD.js.map → chunk-PBENHIN2.js.map} +0 -0
- /package/dist/{chunk-CLWBNXKF.js.map → chunk-PLUJEQLU.js.map} +0 -0
- /package/dist/{chunk-JYBFPNBJ.js.map → chunk-SJGEBMJT.js.map} +0 -0
- /package/dist/{chunk-6XP2Q5SS.js.map → chunk-WZOPWQN2.js.map} +0 -0
|
@@ -9,9 +9,10 @@
|
|
|
9
9
|
* Invoked via:
|
|
10
10
|
* bunx hygen subsystem jobs \
|
|
11
11
|
* --workerPath <abs> --workerExists <'true'|''> \
|
|
12
|
+
* --jobWorkerModuleImport <specifier> --workerForRootOpts <ts-literal> \
|
|
12
13
|
* --mainTsPath <abs> --configPath <abs> --schemaPath <abs> \
|
|
13
14
|
* --multiTenant <'true'|'false'> --workerMode <embedded|standalone> \
|
|
14
|
-
* --appName <string>
|
|
15
|
+
* --skipSchema <'true'|''> --appName <string>
|
|
15
16
|
*/
|
|
16
17
|
|
|
17
18
|
import { renderGeneratedBanner } from "../../_shared/generated-banner.mjs";
|
|
@@ -23,6 +24,28 @@ function coerceBool(raw) {
|
|
|
23
24
|
return false;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
// #513: the CLI base64-encodes --workerForRootOpts because Hygen's yargs parser
|
|
28
|
+
// mangles a raw `{ mode: 'standalone', … }` TS literal (the braces/colons are
|
|
29
|
+
// read as nested object syntax). Decode it back to the source string here. A
|
|
30
|
+
// direct hygen invocation that passes a non-encoded value (or omits it) falls
|
|
31
|
+
// back to the plain default below.
|
|
32
|
+
function decodeWorkerForRootOpts(raw) {
|
|
33
|
+
if (typeof raw !== "string" || raw.length === 0) {
|
|
34
|
+
return "{ mode: 'standalone', allPools: true }";
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const decoded = Buffer.from(raw, "base64").toString("utf-8");
|
|
38
|
+
// Re-encoding round-trips iff `raw` was valid base64 of the decoded bytes;
|
|
39
|
+
// guards against a hand-passed plain literal being treated as base64.
|
|
40
|
+
if (Buffer.from(decoded, "utf-8").toString("base64") === raw) {
|
|
41
|
+
return decoded;
|
|
42
|
+
}
|
|
43
|
+
} catch {
|
|
44
|
+
/* fall through to raw */
|
|
45
|
+
}
|
|
46
|
+
return raw;
|
|
47
|
+
}
|
|
48
|
+
|
|
26
49
|
export default {
|
|
27
50
|
prompt: async ({ args }) => {
|
|
28
51
|
return {
|
|
@@ -34,9 +57,24 @@ export default {
|
|
|
34
57
|
// Hygen's skip_if treats any non-empty string as truthy, so we send an
|
|
35
58
|
// empty string when the file doesn't exist (CLI already does this).
|
|
36
59
|
workerExists: args.workerExists ?? "",
|
|
37
|
-
|
|
60
|
+
// #513: the worker lands at `src/worker.ts` (inside the default tsconfig
|
|
61
|
+
// include, next to `app.module.ts`); the CLI always passes an absolute
|
|
62
|
+
// --workerPath, this fallback only guards a direct hygen invocation.
|
|
63
|
+
workerPath: args.workerPath ?? "src/worker.ts",
|
|
64
|
+
// #513: mode-aware JobWorkerModule import + the pre-serialised
|
|
65
|
+
// forRoot(<opts>) literal (the only mode-dependent import the worker
|
|
66
|
+
// carries — AppModule is imported relatively).
|
|
67
|
+
jobWorkerModuleImport:
|
|
68
|
+
args.jobWorkerModuleImport ??
|
|
69
|
+
"@pattern-stack/codegen/runtime/subsystems/jobs/index",
|
|
70
|
+
workerForRootOpts: decodeWorkerForRootOpts(args.workerForRootOpts),
|
|
38
71
|
schemaPath:
|
|
39
72
|
args.schemaPath ?? "shared/subsystems/jobs/job-orchestration.schema.ts",
|
|
73
|
+
// #517: package mode skips the schema template (the schema ships in the
|
|
74
|
+
// package, re-exported via the schema barrel). Hygen's skip_if treats any
|
|
75
|
+
// non-empty string as truthy, so the CLI sends '' in vendored mode and
|
|
76
|
+
// 'true' in package mode. Default '' so a direct hygen invocation renders.
|
|
77
|
+
skipSchema: args.skipSchema ?? "",
|
|
40
78
|
// @generated DO-NOT-EDIT banner — the jobs subsystem schema is
|
|
41
79
|
// force-overwritten on every `subsystem install`.
|
|
42
80
|
generatedBanner: renderGeneratedBanner({
|
|
@@ -5,31 +5,42 @@ unless_exists: true
|
|
|
5
5
|
/**
|
|
6
6
|
* Standalone job worker entrypoint — emitted by `codegen subsystem install jobs`.
|
|
7
7
|
*
|
|
8
|
-
* Boots a Nest application context (NO HTTP listener)
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* allPools: true })`. Run with:
|
|
8
|
+
* Boots a Nest application context (NO HTTP listener) that composes the
|
|
9
|
+
* consumer's root `AppModule` plus `JobWorkerModule.forRoot({ mode:
|
|
10
|
+
* 'standalone', allPools: true, … })`. Run with:
|
|
12
11
|
*
|
|
13
|
-
* bun worker.ts
|
|
12
|
+
* bun src/worker.ts
|
|
14
13
|
*
|
|
15
|
-
* Why
|
|
16
|
-
* -
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
14
|
+
* Why import `AppModule` whole:
|
|
15
|
+
* - Job handlers are Nest providers registered by the consumer's handler
|
|
16
|
+
* modules (and the subsystem barrel). Composing around `AppModule` gives
|
|
17
|
+
* this worker the SAME DI graph as the HTTP process — every `@JobHandler`
|
|
18
|
+
* resolves its dependencies here exactly as it would in the API. A bare
|
|
19
|
+
* `SUBSYSTEM_MODULES`-only worker boots with an empty handler surface.
|
|
20
|
+
* - `AppModule` already wires `DatabaseModule` + `SUBSYSTEM_MODULES` (events +
|
|
21
|
+
* jobs + bridge + integration, dependency-ordered), so the worker needs no
|
|
22
|
+
* mode-aware barrel import — only `JobWorkerModule` itself.
|
|
23
|
+
*
|
|
24
|
+
* Why `allPools: true`:
|
|
25
|
+
* - The events subsystem's outbox drain and the bridge's fanout wrappers run
|
|
26
|
+
* as `job_run` rows in the RESERVED `events_*` pools. A worker that only
|
|
27
|
+
* polls the non-reserved pools (`interactive`, `batch`, …) strands those
|
|
28
|
+
* lanes — `BridgeDeliveryHandler` never fires and durable event→job fanout
|
|
29
|
+
* silently stops.
|
|
21
30
|
* - `allPools: true` activates every pool in the resolved config, reserved
|
|
22
31
|
* lanes included, so this single standalone process drains both user work
|
|
23
32
|
* and the framework's reserved lanes.
|
|
24
|
-
* - Importing `SUBSYSTEM_MODULES` (rather than `JobsDomainModule` alone)
|
|
25
|
-
* registers `EVENT_BUS` / `JOB_ORCHESTRATOR` / `BRIDGE_*` so the
|
|
26
|
-
* framework `@framework/bridge_delivery` handler resolves its DI deps.
|
|
27
|
-
* `BridgeModule`'s reserved-pool guard short-circuits to pass because
|
|
28
|
-
* `allPools` is set.
|
|
29
33
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
34
|
+
* STANDALONE ONLY: this entrypoint is for `jobs.worker_mode: standalone`. In
|
|
35
|
+
* embedded mode the worker already runs inside `AppModule` (via the
|
|
36
|
+
* `JobWorkerModule.forRoot({ mode: 'embedded' })` the barrel composes), so
|
|
37
|
+
* booting this file too would double-spawn the worker against the same pools.
|
|
38
|
+
*
|
|
39
|
+
* DO NOT boot `AppModule` twice in one process: a consumer `AppModule`
|
|
40
|
+
* registers an OpenAPI document against the per-process `OpenApiRegistry`
|
|
41
|
+
* singleton, which throws `DuplicateSchemaError` on the second registration.
|
|
42
|
+
* Multi-rung boot validation (e.g. "does the worker boot AND does the API
|
|
43
|
+
* boot?") must spawn CHILD PROCESSES, not import both modules into one.
|
|
33
44
|
*
|
|
34
45
|
* SIGTERM triggers graceful shutdown bounded by SHUTDOWN_TIMEOUT_MS; after the
|
|
35
46
|
* timeout the process exits hard so orchestrators (systemd, Kubernetes) can
|
|
@@ -39,26 +50,23 @@ import 'reflect-metadata';
|
|
|
39
50
|
import { Logger, Module } from '@nestjs/common';
|
|
40
51
|
import { NestFactory } from '@nestjs/core';
|
|
41
52
|
|
|
42
|
-
import {
|
|
43
|
-
import { JobWorkerModule } from '
|
|
44
|
-
import { SUBSYSTEM_MODULES } from '@generated/subsystems';
|
|
53
|
+
import { AppModule } from './app.module';
|
|
54
|
+
import { JobWorkerModule } from '<%= jobWorkerModuleImport %>';
|
|
45
55
|
|
|
46
56
|
const SHUTDOWN_TIMEOUT_MS = 30_000;
|
|
47
57
|
|
|
48
58
|
@Module({
|
|
49
59
|
imports: [
|
|
50
|
-
DatabaseModule
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
// same way in both processes.
|
|
55
|
-
...SUBSYSTEM_MODULES,
|
|
60
|
+
// Consumer root — DatabaseModule + SUBSYSTEM_MODULES + handler modules.
|
|
61
|
+
// Importing it whole keeps the worker's DI graph identical to the HTTP app's
|
|
62
|
+
// so every `@JobHandler` resolves the same way in both processes.
|
|
63
|
+
AppModule,
|
|
56
64
|
// `allPools: true` drains the reserved `events_*` lanes (events outbox +
|
|
57
65
|
// bridge wrappers) alongside the user pools.
|
|
58
|
-
JobWorkerModule.forRoot(
|
|
66
|
+
JobWorkerModule.forRoot(<%- workerForRootOpts %>),
|
|
59
67
|
],
|
|
60
68
|
})
|
|
61
|
-
class WorkerAppModule {}
|
|
69
|
+
export class WorkerAppModule {}
|
|
62
70
|
|
|
63
71
|
async function bootstrap(): Promise<void> {
|
|
64
72
|
const logger = new Logger('JobWorker');
|
|
@@ -98,8 +106,12 @@ async function bootstrap(): Promise<void> {
|
|
|
98
106
|
logger.log('job worker started (standalone mode, all pools)');
|
|
99
107
|
}
|
|
100
108
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
109
|
+
// Gated so the module can be imported by boot-checks / e2e without spawning a
|
|
110
|
+
// worker; `bun src/worker.ts` runs it as the entrypoint.
|
|
111
|
+
if (import.meta.main) {
|
|
112
|
+
bootstrap().catch((err) => {
|
|
113
|
+
// eslint-disable-next-line no-console
|
|
114
|
+
console.error('failed to bootstrap job worker', err);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
});
|
|
117
|
+
}
|