@pattern-stack/codegen 0.10.0 → 0.11.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 +135 -0
- package/README.md +5 -5
- package/consumer-skills/codegen/SKILL.md +2 -2
- package/consumer-skills/events/typed-bus-and-outbox.md +1 -1
- package/consumer-skills/{sync → integration}/SKILL.md +29 -29
- package/consumer-skills/{sync → integration}/audit-and-detection.md +22 -22
- package/consumer-skills/{sync → integration}/change-sources-and-sinks.md +60 -60
- package/consumer-skills/subsystems/SKILL.md +64 -8
- package/consumer-skills/subsystems/wiring-and-order.md +7 -7
- package/dist/runtime/base-classes/index.d.ts +4 -4
- package/dist/runtime/base-classes/index.js +35 -35
- package/dist/runtime/base-classes/index.js.map +1 -1
- package/dist/runtime/base-classes/{synced-entity-repository.d.ts → integrated-entity-repository.d.ts} +15 -15
- package/dist/runtime/base-classes/{synced-entity-repository.js → integrated-entity-repository.js} +21 -21
- package/dist/runtime/base-classes/integrated-entity-repository.js.map +1 -0
- package/dist/runtime/base-classes/{synced-entity-service.d.ts → integrated-entity-service.d.ts} +6 -6
- package/dist/runtime/base-classes/{synced-entity-service.js → integrated-entity-service.js} +4 -4
- package/dist/runtime/base-classes/integrated-entity-service.js.map +1 -0
- package/dist/runtime/base-classes/{sync-upsert-config.d.ts → integration-upsert-config.d.ts} +13 -13
- package/dist/runtime/base-classes/integration-upsert-config.js +1 -0
- package/dist/runtime/base-classes/{junction-sync-repository.d.ts → junction-integration-repository.d.ts} +11 -11
- package/dist/runtime/base-classes/{junction-sync-repository.js → junction-integration-repository.js} +15 -15
- package/dist/runtime/base-classes/junction-integration-repository.js.map +1 -0
- package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.module.d.ts +4 -4
- package/dist/runtime/subsystems/auth/auth.module.js +3 -3
- package/dist/runtime/subsystems/auth/auth.module.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.tokens.d.ts +8 -8
- package/dist/runtime/subsystems/auth/auth.tokens.js +6 -6
- package/dist/runtime/subsystems/auth/auth.tokens.js.map +1 -1
- package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/auth/controllers/auth.controller.d.ts +2 -2
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js +3 -3
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js.map +1 -1
- package/dist/runtime/subsystems/auth/index.d.ts +3 -3
- package/dist/runtime/subsystems/auth/index.js +40 -40
- package/dist/runtime/subsystems/auth/index.js.map +1 -1
- package/dist/runtime/subsystems/auth/middleware/requester-context.js.map +1 -1
- package/dist/runtime/subsystems/auth/protocols/auth-strategy.d.ts +3 -3
- package/dist/runtime/subsystems/auth/protocols/{integration-store.d.ts → connection-store.d.ts} +20 -20
- package/dist/runtime/subsystems/auth/protocols/connection-store.js +1 -0
- package/dist/runtime/subsystems/auth/protocols/provider-strategy.d.ts +3 -3
- package/dist/runtime/subsystems/auth/runtime/{integration-broken.error.d.ts → connection-broken.error.d.ts} +5 -5
- package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js +19 -0
- package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js.map +1 -0
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.d.ts +10 -10
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js +28 -28
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js.map +1 -1
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.d.ts +1 -1
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js +3 -3
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge.module.d.ts +0 -1
- package/dist/runtime/subsystems/bridge/bridge.module.js +294 -710
- package/dist/runtime/subsystems/bridge/bridge.module.js.map +1 -1
- package/dist/runtime/subsystems/bridge/index.d.ts +0 -1
- package/dist/runtime/subsystems/bridge/index.js +248 -664
- package/dist/runtime/subsystems/bridge/index.js.map +1 -1
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +18 -10
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/events/events.module.js +43 -244
- package/dist/runtime/subsystems/events/events.module.js.map +1 -1
- package/dist/runtime/subsystems/events/index.d.ts +0 -1
- package/dist/runtime/subsystems/events/index.js +39 -241
- package/dist/runtime/subsystems/events/index.js.map +1 -1
- package/dist/runtime/subsystems/index.d.ts +7 -7
- package/dist/runtime/subsystems/index.js +222 -839
- package/dist/runtime/subsystems/index.js.map +1 -1
- package/dist/runtime/subsystems/{sync → integration}/build-change-source.d.ts +3 -3
- package/dist/runtime/subsystems/{sync → integration}/build-change-source.js +3 -3
- package/dist/runtime/subsystems/integration/build-change-source.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/deep-equal.differ.d.ts +2 -2
- package/dist/runtime/subsystems/{sync → integration}/deep-equal.differ.js +1 -1
- package/dist/runtime/subsystems/integration/deep-equal.differ.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/detection-config.schema.d.ts +3 -3
- package/dist/runtime/subsystems/{sync → integration}/detection-config.schema.js +1 -1
- package/dist/runtime/subsystems/integration/detection-config.schema.js.map +1 -0
- package/dist/runtime/subsystems/{sync/execute-sync.use-case.d.ts → integration/execute-integration.use-case.d.ts} +13 -13
- package/dist/runtime/subsystems/{sync/execute-sync.use-case.js → integration/execute-integration.use-case.js} +30 -30
- package/dist/runtime/subsystems/integration/execute-integration.use-case.js.map +1 -0
- package/dist/runtime/subsystems/integration/index.d.ts +28 -0
- package/dist/runtime/subsystems/{sync → integration}/index.js +171 -171
- package/dist/runtime/subsystems/integration/index.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-audit.schema.d.ts → integration/integration-audit.schema.d.ts} +64 -64
- package/dist/runtime/subsystems/{sync/sync-audit.schema.js → integration/integration-audit.schema.js} +47 -47
- package/dist/runtime/subsystems/integration/integration-audit.schema.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-change-source.protocol.d.ts → integration/integration-change-source.protocol.d.ts} +10 -10
- package/dist/runtime/subsystems/integration/integration-change-source.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.d.ts → integration/integration-cursor-store.drizzle-backend.d.ts} +1 -1
- package/dist/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.js → integration/integration-cursor-store.drizzle-backend.js} +65 -65
- package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.memory-backend.d.ts → integration/integration-cursor-store.memory-backend.d.ts} +6 -6
- package/dist/runtime/subsystems/{sync/sync-cursor-store.memory-backend.js → integration/integration-cursor-store.memory-backend.js} +5 -5
- package/dist/runtime/subsystems/integration/integration-cursor-store.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.protocol.d.ts → integration/integration-cursor-store.protocol.d.ts} +13 -13
- package/dist/runtime/subsystems/integration/integration-cursor-store.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-errors.d.ts → integration/integration-errors.d.ts} +2 -2
- package/dist/runtime/subsystems/{sync/sync-errors.js → integration/integration-errors.js} +3 -3
- package/dist/runtime/subsystems/integration/integration-errors.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-field-diff.protocol.d.ts → integration/integration-field-diff.protocol.d.ts} +2 -2
- package/dist/runtime/subsystems/{sync/sync-field-diff.protocol.js → integration/integration-field-diff.protocol.js} +2 -2
- package/dist/runtime/subsystems/integration/integration-field-diff.protocol.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-loopback.protocol.d.ts → integration/integration-loopback.protocol.d.ts} +2 -2
- package/dist/runtime/subsystems/integration/integration-loopback.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-middleware.protocol.d.ts → integration/integration-middleware.protocol.d.ts} +5 -5
- package/dist/runtime/subsystems/integration/integration-middleware.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.d.ts → integration/integration-run-recorder.drizzle-backend.d.ts} +5 -5
- package/dist/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.js → integration/integration-run-recorder.drizzle-backend.js} +73 -73
- package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.memory-backend.d.ts → integration/integration-run-recorder.memory-backend.d.ts} +15 -15
- package/dist/runtime/subsystems/{sync/sync-run-recorder.memory-backend.js → integration/integration-run-recorder.memory-backend.js} +11 -11
- package/dist/runtime/subsystems/integration/integration-run-recorder.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.protocol.d.ts → integration/integration-run-recorder.protocol.d.ts} +25 -25
- package/dist/runtime/subsystems/integration/integration-run-recorder.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-sink.protocol.d.ts → integration/integration-sink.protocol.d.ts} +5 -5
- package/dist/runtime/subsystems/integration/integration-sink.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync.module.d.ts → integration/integration.module.d.ts} +24 -24
- package/dist/runtime/subsystems/{sync/sync.module.js → integration/integration.module.js} +132 -132
- package/dist/runtime/subsystems/integration/integration.module.js.map +1 -0
- package/dist/runtime/subsystems/integration/integration.tokens.d.ts +47 -0
- package/dist/runtime/subsystems/integration/integration.tokens.js +18 -0
- package/dist/runtime/subsystems/integration/integration.tokens.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/loopback.middleware.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/loopback.middleware.js +1 -1
- package/dist/runtime/subsystems/integration/loopback.middleware.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/poll-change-source.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/poll-change-source.js +1 -1
- package/dist/runtime/subsystems/integration/poll-change-source.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/webhook-change-source.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/webhook-change-source.js +1 -1
- package/dist/runtime/subsystems/integration/webhook-change-source.js.map +1 -0
- package/dist/runtime/subsystems/jobs/bullmq.config.d.ts +22 -3
- package/dist/runtime/subsystems/jobs/bullmq.config.js.map +1 -1
- package/dist/runtime/subsystems/jobs/index.d.ts +1 -4
- package/dist/runtime/subsystems/jobs/index.js +87 -506
- package/dist/runtime/subsystems/jobs/index.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js +3 -0
- package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.module.d.ts +10 -3
- package/dist/runtime/subsystems/jobs/job-worker.module.js +248 -664
- package/dist/runtime/subsystems/jobs/job-worker.module.js.map +1 -1
- package/dist/runtime/subsystems/jobs/jobs-domain.module.d.ts +0 -1
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js +89 -391
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js.map +1 -1
- package/dist/runtime/subsystems/observability/index.d.ts +4 -4
- package/dist/runtime/subsystems/observability/index.js +11 -11
- package/dist/runtime/subsystems/observability/index.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.module.d.ts +2 -2
- package/dist/runtime/subsystems/observability/observability.module.js +11 -11
- package/dist/runtime/subsystems/observability/observability.module.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.protocol.d.ts +11 -11
- package/dist/runtime/subsystems/observability/observability.service.d.ts +6 -6
- package/dist/runtime/subsystems/observability/observability.service.js +11 -11
- package/dist/runtime/subsystems/observability/observability.service.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.tokens.d.ts +1 -1
- package/dist/runtime/subsystems/observability/observability.tokens.js.map +1 -1
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.d.ts +3 -3
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.js.map +1 -1
- package/dist/runtime/subsystems/observability/reporters/index.d.ts +3 -3
- package/dist/runtime/subsystems/observability/reporters/index.js.map +1 -1
- package/dist/src/cli/index.js +412 -302
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.d.ts +22 -22
- package/dist/src/index.js +191 -191
- package/dist/src/index.js.map +1 -1
- package/examples/auth-integrations/README.md +32 -32
- package/examples/auth-integrations/definitions/entities/{integration.yaml → connection.yaml} +10 -10
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-grant-sink.adapter.ts → connections/adapters/connection-grant-sink.adapter.ts} +7 -7
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-reader.adapter.ts → connections/adapters/connection-reader.adapter.ts} +10 -10
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-token-writer.adapter.ts → connections/adapters/connection-token-writer.adapter.ts} +11 -11
- package/examples/auth-integrations/runtime/connections/connections-auth.module.ts +81 -0
- package/examples/auth-integrations/runtime/{integrations/facade/integrations.service.ts → connections/facade/connections.service.ts} +35 -35
- package/examples/auth-integrations/runtime/{integrations → connections}/oauth/use-cases/create-or-update-from-oauth-grant.use-case.ts +11 -11
- package/examples/auth-integrations/runtime/{integrations/oauth/use-cases/disconnect-integration.use-case.ts → connections/oauth/use-cases/disconnect-connection.use-case.ts} +6 -6
- package/examples/auth-integrations/runtime/connections/oauth/use-cases/list-user-connections.use-case.ts +21 -0
- package/examples/auth-integrations/runtime/connections/oauth/use-cases/mark-connection-requires-reauth.use-case.ts +21 -0
- package/package.json +1 -1
- package/runtime/base-classes/index.ts +8 -8
- package/runtime/base-classes/{synced-entity-repository.ts → integrated-entity-repository.ts} +36 -36
- package/runtime/base-classes/{synced-entity-service.ts → integrated-entity-service.ts} +6 -6
- package/runtime/base-classes/{sync-upsert-config.ts → integration-upsert-config.ts} +12 -12
- package/runtime/base-classes/{junction-sync-repository.ts → junction-integration-repository.ts} +28 -28
- package/runtime/subsystems/auth/auth-oauth-state.schema.ts +1 -1
- package/runtime/subsystems/auth/auth.module.ts +4 -4
- package/runtime/subsystems/auth/auth.tokens.ts +7 -7
- package/runtime/subsystems/auth/controllers/auth.controller.ts +7 -7
- package/runtime/subsystems/auth/index.ts +19 -19
- package/runtime/subsystems/auth/protocols/auth-strategy.ts +3 -3
- package/runtime/subsystems/auth/protocols/{integration-store.ts → connection-store.ts} +19 -19
- package/runtime/subsystems/auth/protocols/provider-strategy.ts +2 -2
- package/runtime/subsystems/auth/runtime/{integration-broken.error.ts → connection-broken.error.ts} +5 -5
- package/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts +35 -35
- package/runtime/subsystems/auth/runtime/with-auth-retry.ts +3 -3
- package/runtime/subsystems/events/event-bus.drizzle-backend.ts +32 -10
- package/runtime/subsystems/events/events.module.ts +38 -6
- package/runtime/subsystems/events/index.ts +7 -1
- package/runtime/subsystems/index.ts +11 -11
- package/runtime/subsystems/{sync → integration}/build-change-source.ts +3 -3
- package/runtime/subsystems/{sync → integration}/deep-equal.differ.ts +7 -7
- package/runtime/subsystems/{sync → integration}/detection-config.schema.ts +3 -3
- package/runtime/subsystems/{sync/execute-sync.use-case.ts → integration/execute-integration.use-case.ts} +40 -40
- package/runtime/subsystems/{sync → integration}/index.ts +47 -47
- package/runtime/subsystems/{sync/sync-audit.schema.ts → integration/integration-audit.schema.ts} +61 -61
- package/runtime/subsystems/{sync/sync-change-source.protocol.ts → integration/integration-change-source.protocol.ts} +9 -9
- package/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.ts → integration/integration-cursor-store.drizzle-backend.ts} +30 -30
- package/runtime/subsystems/{sync/sync-cursor-store.memory-backend.ts → integration/integration-cursor-store.memory-backend.ts} +9 -9
- package/runtime/subsystems/{sync/sync-cursor-store.protocol.ts → integration/integration-cursor-store.protocol.ts} +13 -13
- package/runtime/subsystems/{sync/sync-errors.ts → integration/integration-errors.ts} +3 -3
- package/runtime/subsystems/{sync/sync-field-diff.protocol.ts → integration/integration-field-diff.protocol.ts} +2 -2
- package/runtime/subsystems/{sync/sync-loopback.protocol.ts → integration/integration-loopback.protocol.ts} +2 -2
- package/runtime/subsystems/{sync/sync-middleware.protocol.ts → integration/integration-middleware.protocol.ts} +6 -6
- package/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.ts → integration/integration-run-recorder.drizzle-backend.ts} +39 -39
- package/runtime/subsystems/{sync/sync-run-recorder.memory-backend.ts → integration/integration-run-recorder.memory-backend.ts} +23 -23
- package/runtime/subsystems/{sync/sync-run-recorder.protocol.ts → integration/integration-run-recorder.protocol.ts} +25 -25
- package/runtime/subsystems/{sync/sync-sink.protocol.ts → integration/integration-sink.protocol.ts} +4 -4
- package/runtime/subsystems/{sync/sync.module.ts → integration/integration.module.ts} +48 -48
- package/runtime/subsystems/integration/integration.tokens.ts +49 -0
- package/runtime/subsystems/{sync → integration}/loopback.middleware.ts +5 -5
- package/runtime/subsystems/{sync → integration}/poll-change-source.ts +7 -7
- package/runtime/subsystems/{sync → integration}/webhook-change-source.ts +7 -7
- package/runtime/subsystems/jobs/bullmq.config.ts +23 -3
- package/runtime/subsystems/jobs/index.ts +13 -8
- package/runtime/subsystems/jobs/job-worker.bullmq-backend.ts +5 -2
- package/runtime/subsystems/jobs/job-worker.module.ts +27 -7
- package/runtime/subsystems/jobs/jobs-domain.module.ts +27 -2
- package/runtime/subsystems/observability/index.ts +1 -1
- package/runtime/subsystems/observability/observability.module.ts +2 -2
- package/runtime/subsystems/observability/observability.protocol.ts +11 -11
- package/runtime/subsystems/observability/observability.service.ts +13 -13
- package/runtime/subsystems/observability/observability.tokens.ts +1 -1
- package/src/patterns/library/index.ts +4 -4
- package/src/patterns/library/{synced.pattern.ts → integrated.pattern.ts} +12 -12
- package/src/patterns/library/junction.pattern.ts +1 -1
- package/src/patterns/pattern-definition.ts +3 -3
- package/templates/entity/new/backend/modules/core/{sync-source.ejs.t → integration-source.ejs.t} +6 -6
- package/templates/entity/new/backend/modules/core/{sync-source.providers.ejs.t → integration-source.providers.ejs.t} +2 -2
- package/templates/entity/new/clean-lite-ps/entity.ejs.t +1 -1
- package/templates/entity/new/clean-lite-ps/module.ejs.t +1 -1
- package/templates/entity/new/clean-lite-ps/prompt-extension.js +33 -33
- package/templates/entity/new/clean-lite-ps/repository.ejs.t +27 -27
- package/templates/entity/new/frontend/collections/collection.ejs.t +26 -1
- package/templates/entity/new/frontend/collections/collections-base.ejs.t +11 -0
- package/templates/entity/new/frontend/entity/combined.ejs.t +31 -1
- package/templates/entity/new/prompt.js +27 -15
- package/templates/junction/new/entity.ejs.t +1 -1
- package/templates/junction/new/prompt.js +24 -24
- package/templates/junction/new/repository.ejs.t +19 -19
- package/templates/subsystem/auth/auth-oauth-state.schema.ejs.t +2 -2
- package/templates/subsystem/auth-config/prompt.js +1 -1
- package/templates/subsystem/auth-integrations/app-module-hook.ejs.t +5 -5
- package/templates/subsystem/bridge/prompt.js +1 -1
- package/templates/subsystem/events/domain-events.schema.ejs.t +43 -2
- package/templates/subsystem/integration/integration-audit.schema.ejs.t +192 -0
- package/templates/subsystem/{sync → integration}/prompt.js +12 -12
- package/templates/subsystem/{sync-config/codegen-config-sync-block.ejs.t → integration-config/codegen-config-integration-block.ejs.t} +7 -7
- package/templates/subsystem/integration-config/prompt.js +22 -0
- package/templates/subsystem/jobs/worker.ejs.t +2 -2
- package/templates/subsystem/observability/main-hook.ejs.t +1 -1
- package/templates/subsystem/observability/prompt.js +1 -1
- package/templates/subsystem/openapi-config/prompt.js +1 -1
- package/dist/runtime/base-classes/junction-sync-repository.js.map +0 -1
- package/dist/runtime/base-classes/sync-upsert-config.js +0 -1
- package/dist/runtime/base-classes/synced-entity-repository.js.map +0 -1
- package/dist/runtime/base-classes/synced-entity-service.js.map +0 -1
- package/dist/runtime/subsystems/auth/protocols/integration-store.js +0 -1
- package/dist/runtime/subsystems/auth/runtime/integration-broken.error.js +0 -19
- package/dist/runtime/subsystems/auth/runtime/integration-broken.error.js.map +0 -1
- package/dist/runtime/subsystems/sync/build-change-source.js.map +0 -1
- package/dist/runtime/subsystems/sync/deep-equal.differ.js.map +0 -1
- package/dist/runtime/subsystems/sync/detection-config.schema.js.map +0 -1
- package/dist/runtime/subsystems/sync/execute-sync.use-case.js.map +0 -1
- package/dist/runtime/subsystems/sync/index.d.ts +0 -28
- package/dist/runtime/subsystems/sync/index.js.map +0 -1
- package/dist/runtime/subsystems/sync/loopback.middleware.js.map +0 -1
- package/dist/runtime/subsystems/sync/poll-change-source.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-audit.schema.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-change-source.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.drizzle-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.memory-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-errors.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-field-diff.protocol.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-loopback.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-middleware.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.drizzle-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.memory-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-sink.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync.module.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync.tokens.d.ts +0 -47
- package/dist/runtime/subsystems/sync/sync.tokens.js +0 -18
- package/dist/runtime/subsystems/sync/sync.tokens.js.map +0 -1
- package/dist/runtime/subsystems/sync/webhook-change-source.js.map +0 -1
- package/examples/auth-integrations/runtime/integrations/integrations-auth.module.ts +0 -81
- package/examples/auth-integrations/runtime/integrations/oauth/use-cases/list-user-integrations.use-case.ts +0 -21
- package/examples/auth-integrations/runtime/integrations/oauth/use-cases/mark-integration-requires-reauth.use-case.ts +0 -21
- package/runtime/subsystems/sync/sync.tokens.ts +0 -49
- package/templates/subsystem/sync/sync-audit.schema.ejs.t +0 -192
- package/templates/subsystem/sync-config/prompt.js +0 -22
- /package/dist/runtime/base-classes/{sync-upsert-config.js.map → integration-upsert-config.js.map} +0 -0
- /package/dist/runtime/subsystems/auth/protocols/{integration-store.js.map → connection-store.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-change-source.protocol.js.map → integration/integration-change-source.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-cursor-store.protocol.js.map → integration/integration-cursor-store.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-loopback.protocol.js.map → integration/integration-loopback.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-middleware.protocol.js.map → integration/integration-middleware.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-run-recorder.protocol.js.map → integration/integration-run-recorder.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-sink.protocol.js.map → integration/integration-sink.protocol.js.map} +0 -0
|
@@ -2,71 +2,71 @@
|
|
|
2
2
|
|
|
3
3
|
# Change sources, sinks, and feature-module wiring
|
|
4
4
|
|
|
5
|
-
How you wire a
|
|
6
|
-
`IChangeSource<T>` adapter, the `
|
|
5
|
+
How you wire a integration integration end to end: the per-entity feature module, the
|
|
6
|
+
`IChangeSource<T>` adapter, the `IIntegrationSink<T>` write surface, the entity-YAML
|
|
7
7
|
`detection:` block, triggering runs, multi-tenancy, loopback, and testing.
|
|
8
8
|
|
|
9
|
-
Everything imports from `@shared/subsystems/
|
|
9
|
+
Everything imports from `@shared/subsystems/integration`.
|
|
10
10
|
|
|
11
11
|
## The per-entity feature module
|
|
12
12
|
|
|
13
|
-
`
|
|
13
|
+
`IntegrationModule.forRoot(...)` in `AppModule` wires the substrate (cursor store, run
|
|
14
14
|
recorder, field differ, multi-tenant flag). For **each canonical entity you
|
|
15
|
-
|
|
15
|
+
integration**, write a feature module that binds:
|
|
16
16
|
|
|
17
|
-
- `
|
|
18
|
-
- `
|
|
19
|
-
- `
|
|
20
|
-
- optionally `
|
|
21
|
-
`
|
|
17
|
+
- `INTEGRATION_CHANGE_SOURCE` — your adapter (one per `(provider, detection-mode, entity)`)
|
|
18
|
+
- `INTEGRATION_SINK` — your sink (one per canonical entity)
|
|
19
|
+
- `ExecuteIntegrationUseCase` — the orchestrator class itself
|
|
20
|
+
- optionally `INTEGRATION_FIELD_DIFFER` (custom diff rules) and/or
|
|
21
|
+
`INTEGRATION_LOOPBACK_FINGERPRINT_STORE`
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
24
|
import { Module } from '@nestjs/common';
|
|
25
25
|
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
ExecuteIntegrationUseCase,
|
|
27
|
+
INTEGRATION_CHANGE_SOURCE,
|
|
28
|
+
INTEGRATION_SINK,
|
|
29
|
+
INTEGRATION_FIELD_DIFFER,
|
|
30
30
|
DeepEqualDiffer,
|
|
31
|
-
} from '@shared/subsystems/
|
|
31
|
+
} from '@shared/subsystems/integration';
|
|
32
32
|
|
|
33
33
|
@Module({
|
|
34
34
|
providers: [
|
|
35
|
-
{ provide:
|
|
36
|
-
{ provide:
|
|
35
|
+
{ provide: INTEGRATION_CHANGE_SOURCE, useClass: SalesforceOpportunityChangeSource },
|
|
36
|
+
{ provide: INTEGRATION_SINK, useClass: OpportunityIntegrationSink },
|
|
37
37
|
// Override the differ per-entity when you need a wider ignore list:
|
|
38
38
|
{
|
|
39
|
-
provide:
|
|
40
|
-
useValue: new DeepEqualDiffer({ ignore: ['
|
|
39
|
+
provide: INTEGRATION_FIELD_DIFFER,
|
|
40
|
+
useValue: new DeepEqualDiffer({ ignore: ['integration_version', 'internal_notes'] }),
|
|
41
41
|
},
|
|
42
|
-
|
|
42
|
+
ExecuteIntegrationUseCase,
|
|
43
43
|
],
|
|
44
|
-
exports: [
|
|
44
|
+
exports: [ExecuteIntegrationUseCase],
|
|
45
45
|
})
|
|
46
|
-
export class
|
|
46
|
+
export class OpportunityIntegrationModule {}
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
**Why `
|
|
50
|
-
orchestrator depends on `
|
|
49
|
+
**Why `ExecuteIntegrationUseCase` lives here and not in `IntegrationModule`:** the
|
|
50
|
+
orchestrator depends on `INTEGRATION_CHANGE_SOURCE` + `INTEGRATION_SINK`, which are
|
|
51
51
|
per-feature. Nest resolves providers at module compile time; putting the
|
|
52
|
-
orchestrator in the global `
|
|
52
|
+
orchestrator in the global `IntegrationModule` would require those tokens globally,
|
|
53
53
|
which fails until your feature module is imported.
|
|
54
54
|
|
|
55
|
-
Inject `
|
|
55
|
+
Inject `ExecuteIntegrationUseCase<CanonicalOpportunity>` wherever you trigger a run —
|
|
56
56
|
a scheduled job, a CLI command, a webhook handler, an operator UI button.
|
|
57
57
|
|
|
58
58
|
## Writing an `IChangeSource<T>`
|
|
59
59
|
|
|
60
60
|
The one port every adapter implements. The signature is
|
|
61
|
-
`listChanges(subscription, cursor):
|
|
61
|
+
`listChanges(subscription, cursor): AintegrationIterable<Change<T>>`:
|
|
62
62
|
|
|
63
63
|
```ts
|
|
64
64
|
interface IChangeSource<T> {
|
|
65
65
|
readonly label: string; // e.g. 'salesforce-poll-opportunity'
|
|
66
66
|
listChanges(
|
|
67
|
-
subscription:
|
|
67
|
+
subscription: IntegrationSubscriptionView,
|
|
68
68
|
cursor: unknown | null,
|
|
69
|
-
):
|
|
69
|
+
): AintegrationIterable<Change<T>>;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
interface Change<T> {
|
|
@@ -84,7 +84,7 @@ A worked poll adapter:
|
|
|
84
84
|
|
|
85
85
|
```ts
|
|
86
86
|
import { Injectable } from '@nestjs/common';
|
|
87
|
-
import type { IChangeSource, Change,
|
|
87
|
+
import type { IChangeSource, Change, IntegrationSubscriptionView } from '@shared/subsystems/integration';
|
|
88
88
|
|
|
89
89
|
@Injectable()
|
|
90
90
|
export class SalesforceOpportunityChangeSource
|
|
@@ -98,9 +98,9 @@ export class SalesforceOpportunityChangeSource
|
|
|
98
98
|
) {}
|
|
99
99
|
|
|
100
100
|
async *listChanges(
|
|
101
|
-
sub:
|
|
101
|
+
sub: IntegrationSubscriptionView,
|
|
102
102
|
cursor: unknown | null,
|
|
103
|
-
):
|
|
103
|
+
): AintegrationIterable<Change<CanonicalOpportunity>> {
|
|
104
104
|
const typed = cursor as { systemModstamp?: string } | null;
|
|
105
105
|
const since = typed?.systemModstamp ?? '1970-01-01T00:00:00Z';
|
|
106
106
|
|
|
@@ -151,14 +151,14 @@ export class SalesforceOpportunityChangeSource
|
|
|
151
151
|
methods** to `IChangeSource`; if a new mode emerges, add a value to the
|
|
152
152
|
`source` union and a metadata field, not a new port.
|
|
153
153
|
|
|
154
|
-
## Writing an `
|
|
154
|
+
## Writing an `IIntegrationSink<T>`
|
|
155
155
|
|
|
156
156
|
One sink per canonical entity. It speaks the *canonical* shape externally;
|
|
157
157
|
internal mapping (canonical → local columns, EAV dual-write, FK resolution)
|
|
158
158
|
stays inside:
|
|
159
159
|
|
|
160
160
|
```ts
|
|
161
|
-
interface
|
|
161
|
+
interface IIntegrationSink<TCanonical> {
|
|
162
162
|
findByExternalId(userId: string, externalId: string): Promise<TCanonical | null>;
|
|
163
163
|
upsertByExternalId(userId: string, record: TCanonical, provider: string): Promise<{ id: string; saved: TCanonical }>;
|
|
164
164
|
softDeleteByExternalId(userId: string, externalId: string): Promise<{ id: string } | null>;
|
|
@@ -167,7 +167,7 @@ interface ISyncSink<TCanonical> {
|
|
|
167
167
|
|
|
168
168
|
```ts
|
|
169
169
|
@Injectable()
|
|
170
|
-
export class
|
|
170
|
+
export class OpportunityIntegrationSink implements IIntegrationSink<CanonicalOpportunity> {
|
|
171
171
|
constructor(
|
|
172
172
|
@Inject(DRIZZLE) private readonly db: DrizzleClient,
|
|
173
173
|
private readonly opportunities: OpportunityService,
|
|
@@ -208,7 +208,7 @@ export class OpportunitySyncSink implements ISyncSink<CanonicalOpportunity> {
|
|
|
208
208
|
dual-write (canonical columns + custom-field rows), `user_id` + `provider`
|
|
209
209
|
stamping all happen inside its transaction. The subsystem never reaches around
|
|
210
210
|
the sink to write local tables. **Return the local id** so the orchestrator
|
|
211
|
-
can record it on `
|
|
211
|
+
can record it on `integration_run_items.local_id`.
|
|
212
212
|
- **Re-entry tolerance is the sink's job.** A webhook retry or polling overlap
|
|
213
213
|
can deliver the same record twice — make the upsert idempotent (typically
|
|
214
214
|
`ON CONFLICT (external_id) DO UPDATE` with no-op semantics when nothing
|
|
@@ -222,7 +222,7 @@ integration provider:
|
|
|
222
222
|
|
|
223
223
|
```yaml
|
|
224
224
|
# entities/opportunity.yaml
|
|
225
|
-
|
|
225
|
+
integration:
|
|
226
226
|
providers:
|
|
227
227
|
hubspot-crm: { remote_entity: deal, direction: inbound }
|
|
228
228
|
salesforce-crm: { remote_entity: Opportunity, direction: inbound }
|
|
@@ -240,7 +240,7 @@ detection:
|
|
|
240
240
|
filters: [ ... ]
|
|
241
241
|
```
|
|
242
242
|
|
|
243
|
-
Codegen emits exactly one `<entity>-
|
|
243
|
+
Codegen emits exactly one `<entity>-integration-source.module.ts` per entity,
|
|
244
244
|
regardless of provider count. It exports two runtime symbols (plus the module
|
|
245
245
|
class):
|
|
246
246
|
|
|
@@ -260,13 +260,13 @@ Wire your fetch callbacks in a feature module:
|
|
|
260
260
|
import {
|
|
261
261
|
OPPORTUNITY_POLL_FETCH_REGISTRY,
|
|
262
262
|
OPPORTUNITY_CHANGE_SOURCES,
|
|
263
|
-
|
|
264
|
-
} from '@modules/opportunity-
|
|
265
|
-
import type { OpportunityProvider } from '@modules/opportunity-
|
|
263
|
+
OpportunityIntegrationSourceModule,
|
|
264
|
+
} from '@modules/opportunity-integration-source.module';
|
|
265
|
+
import type { OpportunityProvider } from '@modules/opportunity-integration-source.providers';
|
|
266
266
|
import { hubspotFetchOpportunities, salesforceFetchOpportunities } from './my-fetches';
|
|
267
267
|
|
|
268
268
|
@Module({
|
|
269
|
-
imports: [
|
|
269
|
+
imports: [OpportunityIntegrationSourceModule],
|
|
270
270
|
providers: [
|
|
271
271
|
{
|
|
272
272
|
provide: OPPORTUNITY_POLL_FETCH_REGISTRY,
|
|
@@ -277,10 +277,10 @@ import { hubspotFetchOpportunities, salesforceFetchOpportunities } from './my-fe
|
|
|
277
277
|
},
|
|
278
278
|
],
|
|
279
279
|
})
|
|
280
|
-
export class
|
|
280
|
+
export class OpportunityIntegrationWiringModule {}
|
|
281
281
|
```
|
|
282
282
|
|
|
283
|
-
The sibling `<entity>-
|
|
283
|
+
The sibling `<entity>-integration-source.providers.ts` artifact exports the
|
|
284
284
|
`<EntityName>Provider` literal-union type — using `Record<OpportunityProvider, …>`
|
|
285
285
|
(or the `satisfies` form above) turns a provider-key typo into a compile error.
|
|
286
286
|
|
|
@@ -291,7 +291,7 @@ services.
|
|
|
291
291
|
|
|
292
292
|
## Triggering a run
|
|
293
293
|
|
|
294
|
-
`
|
|
294
|
+
`ExecuteIntegrationUseCase` does not schedule itself. Common triggers:
|
|
295
295
|
|
|
296
296
|
**Scheduled job (typical polling)** — wrap the use case in a normal background
|
|
297
297
|
job on one of *your own* pools (never a reserved `events_*` pool — those belong
|
|
@@ -299,14 +299,14 @@ to the event/bridge machinery and throw at boot) and give it a cron trigger
|
|
|
299
299
|
(see the `jobs` skill for the handler shape + scheduling):
|
|
300
300
|
|
|
301
301
|
```ts
|
|
302
|
-
@JobHandler<{ subscriptionId: string; tenantId?: string }>('
|
|
302
|
+
@JobHandler<{ subscriptionId: string; tenantId?: string }>('integration_opportunity_poll', {
|
|
303
303
|
pool: 'batch',
|
|
304
304
|
})
|
|
305
|
-
export class
|
|
305
|
+
export class IntegrationOpportunityPollHandler extends JobHandlerBase<{
|
|
306
306
|
subscriptionId: string;
|
|
307
307
|
tenantId?: string;
|
|
308
308
|
}> {
|
|
309
|
-
constructor(private readonly execute:
|
|
309
|
+
constructor(private readonly execute: ExecuteIntegrationUseCase<CanonicalOpportunity>) {
|
|
310
310
|
super();
|
|
311
311
|
}
|
|
312
312
|
|
|
@@ -347,7 +347,7 @@ await this.execute.execute({
|
|
|
347
347
|
});
|
|
348
348
|
```
|
|
349
349
|
|
|
350
|
-
## Emitting events on successful
|
|
350
|
+
## Emitting events on successful integration
|
|
351
351
|
|
|
352
352
|
The orchestrator does not emit events — wire `TypedEventBus.publish(...)`
|
|
353
353
|
inside your sink's `upsertByExternalId` transaction, after the row is saved, so
|
|
@@ -372,18 +372,18 @@ consumers subscribe via their own handlers. See the `events` skill.
|
|
|
372
372
|
|
|
373
373
|
Three things change when `multi_tenant: true`:
|
|
374
374
|
|
|
375
|
-
1. **`
|
|
375
|
+
1. **`IntegrationModule.forRoot({ backend: 'drizzle', multiTenant: true })`** in
|
|
376
376
|
`AppModule` — binds the multi-tenant flag the orchestrator and Drizzle
|
|
377
377
|
backends inject.
|
|
378
378
|
2. **Every `execute()` call passes `tenantId`.** Missing/null throws
|
|
379
|
-
`MissingTenantIdError` at entry, *before* a `
|
|
379
|
+
`MissingTenantIdError` at entry, *before* a `integration_runs` row is opened (no
|
|
380
380
|
dangling `status=running` rows). The Drizzle backends re-validate at their
|
|
381
381
|
write boundary (defense in depth); all sites share one helper so error
|
|
382
382
|
messages match. Explicit `null` is allowed only for deliberate cross-tenant
|
|
383
383
|
work.
|
|
384
|
-
3. **Schema gains `tenant_id` columns** on all three
|
|
385
|
-
`
|
|
386
|
-
`subsystem install
|
|
384
|
+
3. **Schema gains `tenant_id` columns** on all three integration tables. Flip
|
|
385
|
+
`integration.multi_tenant: true` in `codegen.config.yaml`, re-run
|
|
386
|
+
`subsystem install integration --force --force-config` to re-emit the schema, then
|
|
387
387
|
apply the migration **before** flipping the module flag — otherwise the
|
|
388
388
|
Drizzle backends throw `column "tenant_id" does not exist` on every write.
|
|
389
389
|
|
|
@@ -402,7 +402,7 @@ interface ILoopbackFingerprintStore<T = unknown> {
|
|
|
402
402
|
isEchoOfOwnWrite(entityType: string, externalId: string, record: T): Promise<boolean>;
|
|
403
403
|
}
|
|
404
404
|
|
|
405
|
-
{ provide:
|
|
405
|
+
{ provide: INTEGRATION_LOOPBACK_FINGERPRINT_STORE, useClass: RedisLoopbackStore }
|
|
406
406
|
```
|
|
407
407
|
|
|
408
408
|
Record a fingerprint (hash of the canonicalized record, TTL **shorter than the
|
|
@@ -414,20 +414,20 @@ verify suppression in the audit log; the sink is never called.
|
|
|
414
414
|
|
|
415
415
|
## Testing
|
|
416
416
|
|
|
417
|
-
`
|
|
417
|
+
`IntegrationModule.forRoot({ backend: 'memory' })` plus memory feature-module fakes
|
|
418
418
|
gives an end-to-end test with no Postgres:
|
|
419
419
|
|
|
420
420
|
```ts
|
|
421
|
-
import {
|
|
421
|
+
import { IntegrationModule, MemoryRunRecorder } from '@shared/subsystems/integration';
|
|
422
422
|
|
|
423
423
|
const moduleRef = await Test.createTestingModule({
|
|
424
424
|
imports: [
|
|
425
|
-
|
|
426
|
-
|
|
425
|
+
IntegrationModule.forRoot({ backend: 'memory' }),
|
|
426
|
+
OpportunityIntegrationTestModule, // same shape as the real feature module, with fakes
|
|
427
427
|
],
|
|
428
428
|
}).compile();
|
|
429
429
|
|
|
430
|
-
const orch = moduleRef.get(
|
|
430
|
+
const orch = moduleRef.get(ExecuteIntegrationUseCase);
|
|
431
431
|
const recorder = moduleRef.get(MemoryRunRecorder);
|
|
432
432
|
|
|
433
433
|
await orch.execute({ /* ... */ });
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: subsystems
|
|
3
3
|
description: >-
|
|
4
4
|
Load when installing or wiring an infrastructure subsystem in a project that
|
|
5
|
-
uses @pattern-stack/codegen — events, jobs, cache, storage,
|
|
5
|
+
uses @pattern-stack/codegen — events, jobs, cache, storage, integration, bridge,
|
|
6
6
|
observability, auth, or the OpenAPI config. Covers `codegen subsystem
|
|
7
7
|
install`, the `forRoot` registration ORDER in app.module.ts, which subsystems
|
|
8
8
|
depend on which, and multi-tenancy opt-in. Get the order wrong and the bridge
|
|
@@ -17,7 +17,7 @@ user-invocable: false
|
|
|
17
17
|
# Infrastructure subsystems
|
|
18
18
|
|
|
19
19
|
Subsystems are the generated infrastructure your use cases call: an event bus,
|
|
20
|
-
a job queue, a cache, file storage, an external-
|
|
20
|
+
a job queue, a cache, file storage, an external-integration engine, the event-to-job
|
|
21
21
|
bridge, a read-only observability facade, and OAuth auth. Each follows one
|
|
22
22
|
pattern — **Protocol (port) → Backend (adapter) → Factory (`DynamicModule.
|
|
23
23
|
forRoot`)** — and each is `global: true`, so you register it once in
|
|
@@ -33,7 +33,7 @@ forRoot`)** — and each is `global: true`, so you register it once in
|
|
|
33
33
|
(Postgres) production backend and a memory backend for tests. Swap via the
|
|
34
34
|
`forRoot({ backend })` arg — app code is unchanged.
|
|
35
35
|
- **Order matters.** Some subsystems consume others. The bridge consumes events
|
|
36
|
-
+ jobs; observability composes events/jobs/bridge/
|
|
36
|
+
+ jobs; observability composes events/jobs/bridge/integration read ports via
|
|
37
37
|
optional DI. Registering them in the wrong order means a silently idle bridge
|
|
38
38
|
or an observability facade that reports nothing. See `wiring-and-order.md`.
|
|
39
39
|
|
|
@@ -45,11 +45,11 @@ forRoot`)** — and each is `global: true`, so you register it once in
|
|
|
45
45
|
| jobs | `JobsDomainModule` + `JobWorkerModule` | `subsystem install jobs` | — |
|
|
46
46
|
| cache | `CacheModule` | `subsystem install cache` | jobs (optional, for cleanup) |
|
|
47
47
|
| storage | `StorageModule` | `subsystem install storage` | — |
|
|
48
|
-
|
|
|
48
|
+
| integration | `IntegrationModule` | `subsystem install integration` | — |
|
|
49
49
|
| bridge | `BridgeModule` | `subsystem install bridge` | **events + jobs** |
|
|
50
|
-
| observability | `ObservabilityModule` | `subsystem install observability` | composes events/jobs/bridge/
|
|
50
|
+
| observability | `ObservabilityModule` | `subsystem install observability` | composes events/jobs/bridge/integration (optional) |
|
|
51
51
|
| auth | `AuthModule` | `subsystem install auth` | — |
|
|
52
|
-
| auth-integrations | `
|
|
52
|
+
| auth-integrations | `ConnectionsAuthModule` | `subsystem install auth-integrations` | **auth** |
|
|
53
53
|
| openapi | (config only) | `subsystem install openapi-config` | registry vendored at init |
|
|
54
54
|
|
|
55
55
|
## Registration order (authoritative)
|
|
@@ -60,13 +60,13 @@ In `app.module.ts`, import in this order (omit what you haven't installed):
|
|
|
60
60
|
2. `OpenApiModule` — the registry singleton (vendored at init).
|
|
61
61
|
3. `EventsModule.forRoot(...)`
|
|
62
62
|
4. `JobsDomainModule.forRoot(...)` **and** `JobWorkerModule.forRoot(...)`
|
|
63
|
-
5. `CacheModule` / `StorageModule` / `
|
|
63
|
+
5. `CacheModule` / `StorageModule` / `IntegrationModule.forRoot(...)`
|
|
64
64
|
6. `BridgeModule.forRoot(...)` — **after** events + jobs.
|
|
65
65
|
7. `ObservabilityModule.forRoot(...)` — **last** of the subsystems (composes the
|
|
66
66
|
ones above via optional DI).
|
|
67
67
|
8. `...GENERATED_MODULES` — your entity modules.
|
|
68
68
|
|
|
69
|
-
For auth: register `AuthModule.forRoot(...)` before the `
|
|
69
|
+
For auth: register `AuthModule.forRoot(...)` before the `ConnectionsAuthModule`
|
|
70
70
|
that depends on it. Full per-subsystem `forRoot` signatures, the bridge reserved
|
|
71
71
|
pools, and multi-tenancy are in `wiring-and-order.md`.
|
|
72
72
|
|
|
@@ -87,8 +87,42 @@ pools, and multi-tenancy are in `wiring-and-order.md`.
|
|
|
87
87
|
must be registered after them.
|
|
88
88
|
- **Multi-tenancy is a config flip + a `forRoot` flag + a migration** — never a
|
|
89
89
|
runtime-only toggle. See `wiring-and-order.md`.
|
|
90
|
+
- **`subsystem list` can report `incomplete`, and that's usually fine.**
|
|
91
|
+
Installing one subsystem may vendor *stub* files of another — e.g. installing
|
|
92
|
+
`events` drops `bridge/bridge.protocol.ts` + `bridge.tokens.ts` because the
|
|
93
|
+
events Drizzle backend imports them. That `bridge/` directory has the protocol
|
|
94
|
+
stubs but no `bridge.module.ts`, so `subsystem list` shows it `incomplete`. It
|
|
95
|
+
is **not** registered in the generated `subsystems.ts` barrel (the barrel only
|
|
96
|
+
emits a `forRoot()` for subsystems whose `<name>.module.ts` exists), so it
|
|
97
|
+
won't break your `tsc`. Run `subsystem install bridge` to promote it to
|
|
98
|
+
`installed` when you actually want the bridge.
|
|
90
99
|
- **`--backend memory`** is for tests; the scaffolded default is `drizzle`
|
|
91
100
|
(`local` for storage).
|
|
101
|
+
- **Install vendors only the selected backend.** Alternate-backend source
|
|
102
|
+
files are pruned: a `--backend drizzle` events install does NOT vendor
|
|
103
|
+
`event-bus.redis-backend.ts`, and a drizzle/memory jobs install does NOT
|
|
104
|
+
vendor `job-orchestrator.bullmq-backend.ts`, `job-worker.bullmq-backend.ts`,
|
|
105
|
+
or `bullmq.config.ts`. The module files (`events.module.ts`,
|
|
106
|
+
`jobs-domain.module.ts`, `job-worker.module.ts`) lazy-load the chosen
|
|
107
|
+
backend via dynamic `import()` with a non-literal specifier, so the unused
|
|
108
|
+
backends never drag their peer deps (`ioredis`, `bullmq`) into your `tsc`
|
|
109
|
+
graph. `bullmq` and `ioredis` are declared as **optional peer
|
|
110
|
+
dependencies** — install them ONLY if you actually select that backend.
|
|
111
|
+
**Drizzle installs no longer drag `bullmq` / `ioredis` into your consumer
|
|
112
|
+
peer-deps**; if your `package.json` carries them only as workarounds for
|
|
113
|
+
earlier 0.10.x scaffolds, you can drop them.
|
|
114
|
+
- **Bundler caveat.** The dynamic-import specifier is captured in a variable
|
|
115
|
+
(e.g. `const spec = './event-bus.redis-backend'; await import(spec)`) on
|
|
116
|
+
purpose — that's what makes `tsc` treat it as `any` and skip resolving the
|
|
117
|
+
pruned file. A bundler (webpack / esbuild / rollup) won't static-analyse a
|
|
118
|
+
non-literal specifier either, so it won't include the dynamically-imported
|
|
119
|
+
file in its output bundle. In practice this is fine: when the file isn't
|
|
120
|
+
vendored (drizzle install) there's nothing to bundle; when it IS vendored
|
|
121
|
+
(redis / bullmq install) consumers typically run Node/Bun directly against
|
|
122
|
+
the source tree. If you bundle a redis/bullmq build for deployment, ensure
|
|
123
|
+
your bundler is configured to include the vendored
|
|
124
|
+
`<subsystems-root>/<name>/` tree (e.g. mark it as external + ship alongside)
|
|
125
|
+
or pin the dynamic-import path to a literal in your own wrapper.
|
|
92
126
|
|
|
93
127
|
## Do not
|
|
94
128
|
|
|
@@ -103,3 +137,25 @@ pools, and multi-tenancy are in `wiring-and-order.md`.
|
|
|
103
137
|
runtime source, not the tenancy-gated Drizzle schema files. If a schema shape
|
|
104
138
|
changed across versions, re-run `subsystem install <name> --force
|
|
105
139
|
--force-config`.
|
|
140
|
+
|
|
141
|
+
## Removing a subsystem
|
|
142
|
+
|
|
143
|
+
`codegen subsystem remove <name>` deletes the vendored
|
|
144
|
+
`<subsystems-root>/<name>/` directory and regenerates
|
|
145
|
+
`src/generated/subsystems.ts` so the removed subsystem drops out of the
|
|
146
|
+
`SUBSYSTEM_MODULES` barrel. Git-safety gated like install (warns on
|
|
147
|
+
uncommitted changes; `--force` overrides). `--yes`/`-y` is accepted for flag
|
|
148
|
+
parity with `install`.
|
|
149
|
+
|
|
150
|
+
What removal does NOT do (intentionally — explicit beats silent rewrites):
|
|
151
|
+
|
|
152
|
+
- It does **not** strip the `<name>:` block from `codegen.config.yaml`.
|
|
153
|
+
- It does **not** remove the `<Name>Module.forRoot(...)` line from
|
|
154
|
+
`app.module.ts`.
|
|
155
|
+
- It does **not** strip shared runtime deps (`src/shared/types/drizzle.ts`,
|
|
156
|
+
`src/shared/constants/tokens.ts`) — other subsystems may still need them.
|
|
157
|
+
|
|
158
|
+
The CLI prints the two follow-up edits on success. `openapi-config` (a
|
|
159
|
+
config-only pseudo-subsystem) and `auth-integrations` (vendored outside the
|
|
160
|
+
subsystems root, alongside the codegen-emitted entity layer) are not
|
|
161
|
+
auto-removable — the command errors with the right manual next-step.
|
|
@@ -17,7 +17,7 @@ import { EventsModule } from '@shared/subsystems/events';
|
|
|
17
17
|
import { JobsDomainModule, JobWorkerModule } from '@shared/subsystems/jobs';
|
|
18
18
|
import { CacheModule } from '@shared/subsystems/cache';
|
|
19
19
|
import { StorageModule } from '@shared/subsystems/storage';
|
|
20
|
-
import {
|
|
20
|
+
import { IntegrationModule } from '@shared/subsystems/integration';
|
|
21
21
|
import { BridgeModule, BRIDGE_RESERVED_POOLS } from '@shared/subsystems/bridge';
|
|
22
22
|
import { ObservabilityModule } from '@shared/subsystems/observability';
|
|
23
23
|
|
|
@@ -44,10 +44,10 @@ class OpenApiModule {}
|
|
|
44
44
|
// include the bridge's reserved pools so wrappers actually drain:
|
|
45
45
|
pools: ['interactive', 'batch', ...BRIDGE_RESERVED_POOLS],
|
|
46
46
|
}),
|
|
47
|
-
// 5. cache / storage /
|
|
47
|
+
// 5. cache / storage / integration
|
|
48
48
|
CacheModule.forRoot({ backend: 'drizzle' }),
|
|
49
49
|
StorageModule.forRoot({ backend: 'local' }),
|
|
50
|
-
|
|
50
|
+
IntegrationModule.forRoot({ backend: 'drizzle' }),
|
|
51
51
|
// 6. bridge — AFTER events + jobs
|
|
52
52
|
BridgeModule.forRoot({ backend: 'drizzle', multiTenant: false }),
|
|
53
53
|
// 7. observability — LAST (composes the siblings above)
|
|
@@ -68,10 +68,10 @@ export class AppModule {}
|
|
|
68
68
|
| `JobWorkerModule` | `forRoot({ mode, backend?, pools?, allPools?, shutdownTimeoutMs? })` | `mode: 'embedded' \| 'standalone'`. `pools` = active pool names this process drains (defaults to all non-reserved). `allPools: true` drains every pool incl. reserved. |
|
|
69
69
|
| `CacheModule` | `forRoot({ backend })` | optionally registers a cleanup job when jobs is present. |
|
|
70
70
|
| `StorageModule` | `forRoot({ backend })` | `backend: 'local' \| 'memory'`. Implement S3/GCS by implementing the storage protocol. |
|
|
71
|
-
| `
|
|
71
|
+
| `IntegrationModule` | `forRoot({ backend, multiTenant? })` | wires the cursor store / run recorder / differ ports — NOT the orchestrator (that's per-entity; see the `integration` skill). |
|
|
72
72
|
| `BridgeModule` | `forRoot({ backend, multiTenant? })` | must come after events + jobs; fails fast at boot if reserved pools aren't polled. |
|
|
73
73
|
| `ObservabilityModule` | `forRoot({ reporters? })` | read-only facade; `reporters.bridgeMetrics: true` opts into the 60s bridge sampler. Register last. |
|
|
74
|
-
| `AuthModule` | `forRoot({ encryptionKey, oauthStateStore })` | `global: true`; provides `ENCRYPTION_KEY` + `OAUTH_STATE_STORE`. Register before `
|
|
74
|
+
| `AuthModule` | `forRoot({ encryptionKey, oauthStateStore })` | `global: true`; provides `ENCRYPTION_KEY` + `OAUTH_STATE_STORE`. Register before `ConnectionsAuthModule`. |
|
|
75
75
|
|
|
76
76
|
## Pool configuration (jobs)
|
|
77
77
|
|
|
@@ -90,7 +90,7 @@ jobs:
|
|
|
90
90
|
`JobWorkerModule.forRoot({ pools })` then names which of those a given worker
|
|
91
91
|
process drains — scale horizontally by running one worker per pool subset.
|
|
92
92
|
|
|
93
|
-
## Multi-tenancy opt-in (events / jobs /
|
|
93
|
+
## Multi-tenancy opt-in (events / jobs / integration / bridge)
|
|
94
94
|
|
|
95
95
|
Three coordinated steps — never a runtime-only toggle:
|
|
96
96
|
|
|
@@ -110,7 +110,7 @@ tenant-less / cross-tenant work).
|
|
|
110
110
|
- **bridge → events + jobs.** The bridge claims `domain_events` rows and starts
|
|
111
111
|
wrapper job runs in the reserved pools. Without events + jobs registered (and
|
|
112
112
|
the reserved pools polled) it has nothing to consume and nowhere to write.
|
|
113
|
-
- **observability → events/jobs/bridge/
|
|
113
|
+
- **observability → events/jobs/bridge/integration (optional).** It composes the read
|
|
114
114
|
ports of whatever siblings exist, via optional DI. Register it last so those
|
|
115
115
|
ports are already bound; missing siblings are simply omitted from its output.
|
|
116
116
|
- **auth-integrations → auth.** The integration adapters need the encryption key
|
|
@@ -3,13 +3,13 @@ export { RequesterContext, RequesterScope, requireRequester, requireRequesterSco
|
|
|
3
3
|
export { BaseService, IBaseRepository } from './base-service.js';
|
|
4
4
|
export { EventCategory, buildChangeEvents, buildLifecycleEvent, diffSnapshots, emitSafely, entitySnapshot } from './lifecycle-events.js';
|
|
5
5
|
export { BaseFindByIdUseCase, BaseListUseCase, IFindByIdService, IListService } from './base-read-use-cases.js';
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
6
|
+
export { IntegrationFkResolver, IntegrationUpsertConfig } from './integration-upsert-config.js';
|
|
7
|
+
export { IntegratedEntityRepository } from './integrated-entity-repository.js';
|
|
8
|
+
export { JunctionIntegrationConfig, JunctionIntegrationRepository, buildCompositeExternalId, parseCompositeExternalId } from './junction-integration-repository.js';
|
|
9
9
|
export { ActivityEntityRepository } from './activity-entity-repository.js';
|
|
10
10
|
export { MetadataEntityRepository } from './metadata-entity-repository.js';
|
|
11
11
|
export { KnowledgeEntityRepository } from './knowledge-entity-repository.js';
|
|
12
|
-
export {
|
|
12
|
+
export { IIntegratedEntityRepository, IntegratedEntityService } from './integrated-entity-service.js';
|
|
13
13
|
export { ActivityEntityService, IActivityEntityRepository } from './activity-entity-service.js';
|
|
14
14
|
export { IMetadataEntityRepository, MetadataEntityService } from './metadata-entity-service.js';
|
|
15
15
|
export { KnowledgeEntityService } from './knowledge-entity-service.js';
|