@pattern-stack/codegen 0.22.0 → 0.24.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 +56 -1
- package/consumer-skills/integration/SKILL.md +11 -3
- package/dist/{chunk-XKWOJZZ4.js → chunk-37PILMIT.js} +4 -4
- package/dist/{chunk-NR7QQ6ZI.js → chunk-6M6LZEP6.js} +3 -3
- package/dist/{chunk-VDL5CJ5C.js → chunk-7B7MMDOJ.js} +54 -1
- package/dist/chunk-7B7MMDOJ.js.map +1 -0
- package/dist/{chunk-NXHL5YII.js → chunk-7LKAMLV4.js} +4 -4
- package/dist/{chunk-6DQEIXYU.js → chunk-CKLM57IE.js} +10 -10
- package/dist/chunk-CKLM57IE.js.map +1 -0
- package/dist/{chunk-QXVCRA23.js → chunk-ENAR3F5S.js} +9 -4
- package/dist/chunk-ENAR3F5S.js.map +1 -0
- package/dist/{chunk-FFUDEIFF.js → chunk-HN5HT5WL.js} +2 -2
- package/dist/{chunk-6ECCJVYW.js → chunk-K4BQQ2NN.js} +46 -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-DB5UXJC3.js → chunk-PNCOUFFI.js} +4 -2
- package/dist/chunk-PNCOUFFI.js.map +1 -0
- package/dist/{chunk-S7C6TIIF.js → chunk-S5G3HO7N.js} +3 -1
- package/dist/chunk-S5G3HO7N.js.map +1 -0
- package/dist/{chunk-FNHNSFIJ.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/subsystems/auth/auth.module.js +2 -2
- package/dist/runtime/subsystems/auth/index.js +4 -4
- package/dist/runtime/subsystems/bridge/bridge.module.js +7 -7
- package/dist/runtime/subsystems/bridge/index.js +7 -7
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +1 -1
- package/dist/runtime/subsystems/events/events.module.js +5 -5
- 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 +5 -5
- package/dist/runtime/subsystems/index.d.ts +3 -2
- package/dist/runtime/subsystems/index.js +29 -25
- 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 +12 -12
- package/dist/runtime/subsystems/jobs/job-worker.d.ts +592 -4
- package/dist/runtime/subsystems/jobs/job-worker.js +3 -1
- package/dist/runtime/subsystems/jobs/job-worker.module.js +6 -6
- package/dist/runtime/subsystems/jobs/jobs-domain.module.d.ts +19 -0
- 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 +413 -85
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.d.ts +490 -1
- package/dist/src/index.js +7 -7
- package/package.json +1 -1
- package/runtime/subsystems/events/event-bus.drizzle-backend.ts +23 -7
- 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/runtime/subsystems/jobs/job-worker.module.ts +5 -0
- package/runtime/subsystems/jobs/job-worker.ts +126 -12
- package/runtime/subsystems/jobs/jobs-domain.module.ts +19 -0
- package/templates/entity/new/clean-lite-ps/prompt-extension.js +59 -10
- package/templates/subsystem/jobs-config/codegen-config-jobs-block.ejs.t +11 -0
- package/dist/chunk-6DQEIXYU.js.map +0 -1
- package/dist/chunk-6ECCJVYW.js.map +0 -1
- package/dist/chunk-DB5UXJC3.js.map +0 -1
- package/dist/chunk-JOBQ6RUU.js.map +0 -1
- package/dist/chunk-JRQO2IOF.js.map +0 -1
- package/dist/chunk-QXVCRA23.js.map +0 -1
- package/dist/chunk-S7C6TIIF.js.map +0 -1
- package/dist/chunk-TDEHU73T.js.map +0 -1
- package/dist/chunk-VDL5CJ5C.js.map +0 -1
- /package/dist/{chunk-XKWOJZZ4.js.map → chunk-37PILMIT.js.map} +0 -0
- /package/dist/{chunk-NR7QQ6ZI.js.map → chunk-6M6LZEP6.js.map} +0 -0
- /package/dist/{chunk-NXHL5YII.js.map → chunk-7LKAMLV4.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-FNHNSFIJ.js.map → chunk-WZOPWQN2.js.map} +0 -0
|
@@ -852,6 +852,29 @@ function processSearchQueries(queriesBlock, processedFields, belongsTo, entityNa
|
|
|
852
852
|
// Integration write-surface derivation (#374)
|
|
853
853
|
// ============================================================================
|
|
854
854
|
|
|
855
|
+
/**
|
|
856
|
+
* Shared delete-knob → softDelete boolean mapping rule (#490).
|
|
857
|
+
*
|
|
858
|
+
* Applied at BOTH derivations (repo config + sink body) so the two always agree:
|
|
859
|
+
* soft → true (set deletedAt)
|
|
860
|
+
* tombstone → false (null externalId/provider)
|
|
861
|
+
* absent → !!hasSoftDelete (preserve today's default)
|
|
862
|
+
* noop → !!hasSoftDelete (repo config irrelevant for noop — sink short-circuits)
|
|
863
|
+
*
|
|
864
|
+
* The sink only needs 'delegate' | 'noop' for its body decision; this helper
|
|
865
|
+
* is for the REPO config boolean. Mirrored verbatim in buildSinkInput caller
|
|
866
|
+
* (adapter-emission-generator.ts) for the contract test (spec Tests §3d).
|
|
867
|
+
*
|
|
868
|
+
* @param {'soft'|'tombstone'|'noop'|undefined} deleteKnob
|
|
869
|
+
* @param {boolean} hasSoftDelete
|
|
870
|
+
* @returns {boolean}
|
|
871
|
+
*/
|
|
872
|
+
export function resolveSoftDeleteBoolean(deleteKnob, hasSoftDelete) {
|
|
873
|
+
if (deleteKnob === 'soft') return true;
|
|
874
|
+
if (deleteKnob === 'tombstone') return false;
|
|
875
|
+
return !!hasSoftDelete; // absent OR noop → preserve current default
|
|
876
|
+
}
|
|
877
|
+
|
|
855
878
|
/**
|
|
856
879
|
* Pre-compute the inbound-integration write surface for a `pattern: Integrated` entity.
|
|
857
880
|
* Keeps the EJS thin + unit-testable: the template hand-emits the integrationConfig
|
|
@@ -866,14 +889,27 @@ function processSearchQueries(queriesBlock, processedFields, belongsTo, entityNa
|
|
|
866
889
|
* @param {boolean} hasTimestamps
|
|
867
890
|
* @param {boolean} eavEnabled
|
|
868
891
|
* @param {boolean} hasSoftDelete
|
|
892
|
+
* @param {object} [fields] raw entity fields (for FK strict detection)
|
|
893
|
+
* @param {object} [sinkPolicy] integration.sink knobs {delete?, exclude_fields?}
|
|
869
894
|
*/
|
|
870
|
-
export function buildIntegrationSurface(patternName, processedFields, belongsTo, hasTimestamps, eavEnabled, hasSoftDelete, fields) {
|
|
895
|
+
export function buildIntegrationSurface(patternName, processedFields, belongsTo, hasTimestamps, eavEnabled, hasSoftDelete, fields, sinkPolicy) {
|
|
871
896
|
if (patternName !== 'Integrated') return null;
|
|
872
897
|
|
|
898
|
+
// Per-field exclusion (#490): drop declared-excluded fields from copy-through.
|
|
899
|
+
// Exclusion targets copy-through scalars only (FK columns and user_id are
|
|
900
|
+
// rejected at schema validation — the schema superRefine guards both).
|
|
901
|
+
// Match on snake_case `name` (how processedFields.name is keyed) so a
|
|
902
|
+
// multi-word field like `conversation_external_id` matches correctly.
|
|
903
|
+
const excludeSet = new Set(sinkPolicy?.exclude_fields ?? []);
|
|
904
|
+
|
|
873
905
|
// Copy-through columns: every non-FK declared field. external_id_tracking
|
|
874
906
|
// columns (external_id/provider/provider_metadata) are injected by the
|
|
875
907
|
// behavior, NOT present in processedFields, so they're already excluded.
|
|
876
|
-
|
|
908
|
+
// Excluded fields (#490) are also dropped here — they are removed from the
|
|
909
|
+
// copy-through write surface so integrationUpsertOne never clobbers them.
|
|
910
|
+
const writeColumns = processedFields
|
|
911
|
+
.filter((f) => !excludeSet.has(f.name))
|
|
912
|
+
.map((f) => f.camelName);
|
|
877
913
|
|
|
878
914
|
// FK resolvers — one per belongs_to. writeKey = `${relationKey}ExternalId`
|
|
879
915
|
// (Decision 4). refTable is the string 'self' for self-FKs, else the parent
|
|
@@ -896,12 +932,15 @@ export function buildIntegrationSurface(patternName, processedFields, belongsTo,
|
|
|
896
932
|
importPath: rel.importPath,
|
|
897
933
|
}));
|
|
898
934
|
|
|
899
|
-
// Projection columns: id + externalId + copy-through + local FK
|
|
900
|
-
// timestamps. Omits provider/provider_metadata.
|
|
935
|
+
// Projection columns: id + externalId + ALL copy-through columns + local FK
|
|
936
|
+
// columns + timestamps. Omits provider/provider_metadata.
|
|
937
|
+
// Projection keeps excluded fields (#490) — exclusion is write-surface only.
|
|
938
|
+
// The find VIEW also keeps them (bare passthroughs); diff-soundness holds via
|
|
939
|
+
// the differ's `key in incoming` guard, not by omitting them from the view.
|
|
901
940
|
const projectionColumns = [
|
|
902
941
|
'id',
|
|
903
942
|
'externalId',
|
|
904
|
-
...
|
|
943
|
+
...processedFields.map((f) => f.camelName),
|
|
905
944
|
...belongsTo.map((rel) => rel.camelField),
|
|
906
945
|
...(hasTimestamps ? ['createdAt', 'updatedAt'] : []),
|
|
907
946
|
];
|
|
@@ -909,20 +948,26 @@ export function buildIntegrationSurface(patternName, processedFields, belongsTo,
|
|
|
909
948
|
// The integrationConfig object literal the template hand-emits. fkResolvers carry a
|
|
910
949
|
// sentinel so the template can swap `refTable` to either 'self' or the live
|
|
911
950
|
// table identifier.
|
|
951
|
+
// softDelete: use resolveSoftDeleteBoolean (delete knob takes precedence over
|
|
952
|
+
// !!hasSoftDelete default; noop/absent both preserve !!hasSoftDelete, spec §Delete).
|
|
912
953
|
const integrationConfig = {
|
|
913
954
|
conflictTarget: ['provider', 'externalId'],
|
|
914
955
|
writeColumns,
|
|
915
956
|
projectionColumns,
|
|
916
957
|
eav: !!eavEnabled,
|
|
917
|
-
softDelete:
|
|
958
|
+
softDelete: resolveSoftDeleteBoolean(sinkPolicy?.delete, hasSoftDelete),
|
|
918
959
|
};
|
|
919
960
|
|
|
920
961
|
// TIntegrationWrite fields: externalId:string, copy-through (typed, nullable-aware),
|
|
921
962
|
// one `<writeKey>?: string | null` per FK, fields?: Record<string, unknown>.
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
963
|
+
// Excluded fields (#490) are dropped from writeFields too — same exclusion set
|
|
964
|
+
// as writeColumns. The projection keeps them (projectionFields below).
|
|
965
|
+
const writeFields = processedFields
|
|
966
|
+
.filter((f) => !excludeSet.has(f.name))
|
|
967
|
+
.map((f) => ({
|
|
968
|
+
camelName: f.camelName,
|
|
969
|
+
tsType: f.nullable ? `${f.tsType} | null` : f.tsType,
|
|
970
|
+
}));
|
|
926
971
|
const writeFkFields = fkResolvers.map((fk) => ({
|
|
927
972
|
name: fk.writeKey,
|
|
928
973
|
tsType: 'string | null',
|
|
@@ -1336,6 +1381,9 @@ export function buildCleanLitePsLocals(definition, baseLocals) {
|
|
|
1336
1381
|
}));
|
|
1337
1382
|
|
|
1338
1383
|
// Integration write-surface derivation (#374) — null unless pattern: Integrated.
|
|
1384
|
+
// Pass sinkPolicy (#490) so the delete knob and exclude_fields knob are applied
|
|
1385
|
+
// at this derivation (repo config) as well as buildSinkInput (sink derivation).
|
|
1386
|
+
const sinkPolicy = definition.integration?.sink ?? null;
|
|
1339
1387
|
const integrationSurface = buildIntegrationSurface(
|
|
1340
1388
|
patternName,
|
|
1341
1389
|
nonFkFields,
|
|
@@ -1344,6 +1392,7 @@ export function buildCleanLitePsLocals(definition, baseLocals) {
|
|
|
1344
1392
|
eavEnabled,
|
|
1345
1393
|
hasSoftDelete,
|
|
1346
1394
|
fields,
|
|
1395
|
+
sinkPolicy,
|
|
1347
1396
|
);
|
|
1348
1397
|
|
|
1349
1398
|
// EVT-7: emits locals flow through from baseLocals (prompt.js computed them
|
|
@@ -30,6 +30,17 @@ jobs:
|
|
|
30
30
|
# # are simply never received and the worker
|
|
31
31
|
# # degrades to polling.
|
|
32
32
|
poll_interval_ms: 1000 # interval-poll heartbeat (the wake fallback)
|
|
33
|
+
# ── Claim lease / heartbeat (CLAIM-HB-1) ──
|
|
34
|
+
# A live worker renews `claimed_at` for its in-flight runs every
|
|
35
|
+
# `claim_heartbeat_interval_ms`, so a legitimately long-running handler is
|
|
36
|
+
# NEVER swept; only a row whose worker died ages past
|
|
37
|
+
# `stale_threshold_ms` and is reset to `pending` by the sweeper. Raise the
|
|
38
|
+
# threshold only if you expect worker-crash recovery to wait longer; the
|
|
39
|
+
# heartbeat (not the threshold) is what protects long handlers.
|
|
40
|
+
# stale_threshold_ms: 300000 # dead-worker recovery window (5 min)
|
|
41
|
+
# stale_sweeper_interval_ms: 60000 # how often the sweeper scans
|
|
42
|
+
# claim_heartbeat_interval_ms: 100000 # lease renewal cadence
|
|
43
|
+
# # (default = stale_threshold_ms / 3)
|
|
33
44
|
# bullmq: # Example shape for Phase 6+ BullMQ backend.
|
|
34
45
|
# bull_board: # Mount Bull Board admin UI.
|
|
35
46
|
# enabled: true
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../runtime/subsystems/jobs/jobs-domain.module.ts"],"sourcesContent":["/**\n * JobsDomainModule — `DynamicModule.forRoot({ backend })` factory wiring\n * the three jobs-domain protocol tokens to a backend implementation\n * (ADR-022, JOB-5).\n *\n * Mirrors `EventsModule.forRoot()` exactly:\n * - `global: true` so consumer entity modules don't have to import this\n * individually — `JOB_ORCHESTRATOR` / `JOB_RUN_SERVICE` /\n * `JOB_STEP_SERVICE` are available project-wide.\n * - One backend at a time (Drizzle for production, Memory for tests).\n *\n * Backend swappability follows the core/extension protocol from CLAUDE.md:\n * the three tokens are the **core contract**; backend-specific tunables\n * live under `extensions.<backend>` so opting into a feature is explicit\n * and the type system reserves the slot.\n */\nimport { Module, type DynamicModule, type Provider } from '@nestjs/common';\nimport { DRIZZLE } from '../../constants/tokens';\nimport {\n JOB_ORCHESTRATOR,\n JOB_RUN_SERVICE,\n JOB_STEP_SERVICE,\n JOBS_MULTI_TENANT,\n JOBS_LISTEN_NOTIFY,\n} from './jobs-domain.tokens';\nimport { DrizzleJobOrchestrator } from './job-orchestrator.drizzle-backend';\nimport { DrizzleJobRunService } from './job-run-service.drizzle-backend';\nimport { DrizzleJobStepService } from './job-step-service.drizzle-backend';\n// #6 — `BullMQJobOrchestrator` is lazy-loaded only when `backend: 'bullmq'`\n// is selected. The backend file is filtered out of drizzle/memory installs\n// (see `backendFileFilter`); a non-literal dynamic import below sidesteps\n// consumer-side tsc resolution of an absent file.\nimport { MemoryJobOrchestrator } from './job-orchestrator.memory-backend';\nimport { MemoryJobRunService } from './job-run-service.memory-backend';\nimport { MemoryJobStepService } from './job-step-service.memory-backend';\nimport { MemoryJobStore } from './memory-job-store';\nimport {\n BULLMQ_CONNECTION,\n BULLMQ_RESOLVED_CONFIG,\n resolveBullMqConfig,\n type BullMqExtensionsConfig,\n} from './bullmq.config';\n\n/**\n * Drizzle backend extensions surface (LISTEN-NOTIFY-1 wires both fields).\n *\n * - `listenNotify` → provided as `JOBS_LISTEN_NOTIFY` so the orchestrator emits\n * in-tx `pg_notify` on enqueue, and threaded into each spawned `JobWorker`\n * (which holds the listener connection). Off by default.\n * - `pollIntervalMs` → threaded into the spawned `JobWorker`'s\n * `JobWorkerOptions.pollIntervalMs` (the worker already honored this; it just\n * never received a config value). Default 1000.\n *\n * Both run ALONGSIDE interval polling — `listenNotify` only adds an early wake;\n * polling remains the durability heartbeat.\n */\nexport interface DrizzleBackendExtensions {\n /** Use Postgres LISTEN/NOTIFY to wake the polling loop. Default false. */\n listenNotify?: boolean;\n /** Polling interval (ms). Default 1000. */\n pollIntervalMs?: number;\n}\n\nexport interface JobsDomainModuleOptions {\n backend: 'drizzle' | 'memory' | 'bullmq';\n /**\n * Backend-specific extensions. Only the matching backend's extensions\n * are read at boot; non-matching keys are ignored. This is the\n * core/extension protocol surface — see CLAUDE.md.\n */\n extensions?: {\n drizzle?: DrizzleBackendExtensions;\n /**\n * BullMQ backend extensions (BULLMQ-1). Snake_case mirrors the YAML\n * under `jobs.extensions.bullmq`. `redis_url` falls back to\n * `process.env.REDIS_URL` then `redis://localhost:6379`.\n */\n bullmq?: BullMqExtensionsConfig;\n };\n /** Multi-tenancy opt-in. Wired by JOB-8; module signature stays stable. */\n multiTenant?: boolean;\n}\n\n@Module({})\nexport class JobsDomainModule {\n static forRoot(opts: JobsDomainModuleOptions): DynamicModule {\n const multiTenant = opts.multiTenant ?? false;\n // LISTEN-NOTIFY-1 — drizzle-only extension. `listen_notify` is meaningless\n // for memory (no DB) and redundant for bullmq (native wakeups); only the\n // drizzle backend's orchestrator reads it.\n const listenNotify =\n opts.backend === 'drizzle' && Boolean(opts.extensions?.drizzle?.listenNotify);\n\n const providers: Provider[] = [\n // JOB-8 — boolean provider consumed by the four service-layer backends.\n // Always provided (even when `multiTenant === false`) so `@Inject`\n // always resolves; backends short-circuit the enforcement path when\n // the value is `false`. See `jobs-domain.tokens.ts` for the claim-loop\n // cross-tenant-by-design decision.\n { provide: JOBS_MULTI_TENANT, useValue: multiTenant },\n // LISTEN-NOTIFY-1 — always provided so the orchestrator's `@Inject`\n // resolves; the orchestrator skips the `pg_notify` emit when `false`.\n { provide: JOBS_LISTEN_NOTIFY, useValue: listenNotify },\n ];\n\n if (opts.backend === 'memory') {\n // The store is a plain class — wired as a singleton `useValue` so\n // unit tests can pull it out via `.get(MemoryJobStore)` for direct\n // assertions (matches the access pattern in JOB-4 specs).\n const store = new MemoryJobStore();\n providers.push({ provide: MemoryJobStore, useValue: store });\n providers.push(MemoryJobStepService);\n providers.push({ provide: JOB_STEP_SERVICE, useExisting: MemoryJobStepService });\n providers.push(MemoryJobOrchestrator);\n providers.push({ provide: JOB_ORCHESTRATOR, useExisting: MemoryJobOrchestrator });\n providers.push(MemoryJobRunService);\n providers.push({ provide: JOB_RUN_SERVICE, useExisting: MemoryJobRunService });\n } else if (opts.backend === 'bullmq') {\n // BULLMQ-1 — BullMQ orchestrator over a Postgres source of truth. The\n // run/step services stay Drizzle (domain reads + `listForScope` are\n // Postgres queries, unchanged per spec). Only the orchestrator's\n // claim/dispatch half swaps to BullMQ.\n //\n // #6 — the bullmq backend module is filtered out of drizzle/memory\n // installs (no `bullmq` peer dep, no consumer-side tsc compile of an\n // unused file). The factory below dynamic-imports it via a non-literal\n // specifier so TS treats the module type as `any` and never tries to\n // resolve the absent file on a drizzle/memory consumer.\n const resolved = resolveBullMqConfig(opts.extensions?.bullmq);\n providers.push({ provide: BULLMQ_CONNECTION, useValue: resolved.connection });\n providers.push({ provide: BULLMQ_RESOLVED_CONFIG, useValue: resolved });\n providers.push({\n provide: JOB_ORCHESTRATOR,\n useFactory: async (...args: unknown[]): Promise<object> => {\n const specifier = './job-orchestrator.bullmq-backend';\n const mod = (await import(specifier)) as {\n BullMQJobOrchestrator: new (...args: unknown[]) => object;\n };\n return new mod.BullMQJobOrchestrator(...args);\n },\n // The bullmq orchestrator constructor mirrors DrizzleJobOrchestrator's\n // injection list: DRIZZLE + JOBS_MULTI_TENANT + the resolved BullMQ\n // tokens. Importing token references would force a static dep on the\n // tokens file in this module's import graph; using the existing\n // symbols already in scope is sufficient.\n inject: [DRIZZLE, JOBS_MULTI_TENANT, BULLMQ_CONNECTION, BULLMQ_RESOLVED_CONFIG],\n });\n providers.push({ provide: JOB_RUN_SERVICE, useClass: DrizzleJobRunService });\n providers.push({ provide: JOB_STEP_SERVICE, useClass: DrizzleJobStepService });\n } else {\n providers.push({ provide: JOB_ORCHESTRATOR, useClass: DrizzleJobOrchestrator });\n providers.push({ provide: JOB_RUN_SERVICE, useClass: DrizzleJobRunService });\n providers.push({ provide: JOB_STEP_SERVICE, useClass: DrizzleJobStepService });\n }\n\n const exports = [\n JOB_ORCHESTRATOR,\n JOB_RUN_SERVICE,\n JOB_STEP_SERVICE,\n JOBS_MULTI_TENANT,\n JOBS_LISTEN_NOTIFY,\n ];\n // BULLMQ-1 — only export the BullMQ tokens when they were actually\n // provided. Nest throws \"exported but not provided\" otherwise. Exported so\n // JobWorkerModule (which imports this module) can read the resolved\n // connection/config to spawn BullMQ workers.\n if (opts.backend === 'bullmq') {\n exports.push(BULLMQ_CONNECTION, BULLMQ_RESOLVED_CONFIG);\n }\n\n return {\n module: JobsDomainModule,\n global: true,\n providers,\n exports,\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,SAAS,cAAiD;AAoEnD,IAAM,mBAAN,MAAuB;AAAA,EAC5B,OAAO,QAAQ,MAA8C;AAC3D,UAAM,cAAc,KAAK,eAAe;AAIxC,UAAM,eACJ,KAAK,YAAY,aAAa,QAAQ,KAAK,YAAY,SAAS,YAAY;AAE9E,UAAM,YAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAM5B,EAAE,SAAS,mBAAmB,UAAU,YAAY;AAAA;AAAA;AAAA,MAGpD,EAAE,SAAS,oBAAoB,UAAU,aAAa;AAAA,IACxD;AAEA,QAAI,KAAK,YAAY,UAAU;AAI7B,YAAM,QAAQ,IAAI,eAAe;AACjC,gBAAU,KAAK,EAAE,SAAS,gBAAgB,UAAU,MAAM,CAAC;AAC3D,gBAAU,KAAK,oBAAoB;AACnC,gBAAU,KAAK,EAAE,SAAS,kBAAkB,aAAa,qBAAqB,CAAC;AAC/E,gBAAU,KAAK,qBAAqB;AACpC,gBAAU,KAAK,EAAE,SAAS,kBAAkB,aAAa,sBAAsB,CAAC;AAChF,gBAAU,KAAK,mBAAmB;AAClC,gBAAU,KAAK,EAAE,SAAS,iBAAiB,aAAa,oBAAoB,CAAC;AAAA,IAC/E,WAAW,KAAK,YAAY,UAAU;AAWpC,YAAM,WAAW,oBAAoB,KAAK,YAAY,MAAM;AAC5D,gBAAU,KAAK,EAAE,SAAS,mBAAmB,UAAU,SAAS,WAAW,CAAC;AAC5E,gBAAU,KAAK,EAAE,SAAS,wBAAwB,UAAU,SAAS,CAAC;AACtE,gBAAU,KAAK;AAAA,QACb,SAAS;AAAA,QACT,YAAY,UAAU,SAAqC;AACzD,gBAAM,YAAY;AAClB,gBAAM,MAAO,MAAM,OAAO;AAG1B,iBAAO,IAAI,IAAI,sBAAsB,GAAG,IAAI;AAAA,QAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,QAAQ,CAAC,SAAS,mBAAmB,mBAAmB,sBAAsB;AAAA,MAChF,CAAC;AACD,gBAAU,KAAK,EAAE,SAAS,iBAAiB,UAAU,qBAAqB,CAAC;AAC3E,gBAAU,KAAK,EAAE,SAAS,kBAAkB,UAAU,sBAAsB,CAAC;AAAA,IAC/E,OAAO;AACL,gBAAU,KAAK,EAAE,SAAS,kBAAkB,UAAU,uBAAuB,CAAC;AAC9E,gBAAU,KAAK,EAAE,SAAS,iBAAiB,UAAU,qBAAqB,CAAC;AAC3E,gBAAU,KAAK,EAAE,SAAS,kBAAkB,UAAU,sBAAsB,CAAC;AAAA,IAC/E;AAEA,UAAM,UAAU;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAKA,QAAI,KAAK,YAAY,UAAU;AAC7B,cAAQ,KAAK,mBAAmB,sBAAsB;AAAA,IACxD;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AA7Fa,mBAAN;AAAA,EADN,OAAO,CAAC,CAAC;AAAA,GACG;","names":[]}
|