@pattern-stack/codegen 0.10.1 → 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 +62 -0
- package/README.md +5 -5
- package/consumer-skills/codegen/SKILL.md +2 -2
- 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 +8 -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/index.d.ts +7 -7
- package/dist/runtime/subsystems/index.js +51 -51
- 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/job-worker.module.d.ts +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 +262 -269
- 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/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/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/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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MemoryRunRecorder — in-memory backend for `
|
|
2
|
+
* MemoryRunRecorder — in-memory backend for `IIntegrationRunRecorder` (SYNC-6).
|
|
3
3
|
*
|
|
4
|
-
* Test double so `
|
|
4
|
+
* Test double so `IntegrationModule.forRoot({ backend: 'memory' })` is genuinely
|
|
5
5
|
* end-to-end runnable without Postgres. Mirrors the role of
|
|
6
6
|
* `MemoryCursorStore`: plain keyed state, `clear()` helper for
|
|
7
7
|
* `beforeEach` resets, public inspection surface so tests can assert on
|
|
@@ -27,34 +27,34 @@
|
|
|
27
27
|
import { Injectable } from '@nestjs/common';
|
|
28
28
|
import type {
|
|
29
29
|
CompleteRunInput,
|
|
30
|
-
|
|
30
|
+
IIntegrationRunRecorder,
|
|
31
31
|
RecordItemInput,
|
|
32
32
|
StartRunInput,
|
|
33
|
-
|
|
34
|
-
} from './
|
|
35
|
-
import { FieldDiffSchema } from './
|
|
33
|
+
IntegrationRunSummary,
|
|
34
|
+
} from './integration-run-recorder.protocol';
|
|
35
|
+
import { FieldDiffSchema } from './integration-field-diff.protocol';
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Optional per-subscription metadata a test can seed on the memory backend
|
|
39
|
-
* so `listRecent` can surface `
|
|
39
|
+
* so `listRecent` can surface `connectionId`. The memory recorder's write
|
|
40
40
|
* path never persists subscription rows (it only stores runs + items), so
|
|
41
|
-
* `listRecent` has no way to derive `
|
|
41
|
+
* `listRecent` has no way to derive `connectionId` on its own. Tests that
|
|
42
42
|
* care about the field should populate `subscriptions` before calling
|
|
43
43
|
* `listRecent`; calls that don't seed get an empty string and a stable
|
|
44
44
|
* shape (see `listRecent` below).
|
|
45
45
|
*/
|
|
46
|
-
export interface
|
|
47
|
-
|
|
46
|
+
export interface MemoryIntegrationSubscription {
|
|
47
|
+
connectionId: string;
|
|
48
48
|
adapter: string;
|
|
49
49
|
domain: string;
|
|
50
50
|
externalRef: string | null;
|
|
51
|
-
|
|
51
|
+
lastIntegrationAt?: Date | null;
|
|
52
52
|
updatedAt: Date;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Concrete run row as held in memory. Shape mirrors the interesting
|
|
57
|
-
* columns on `
|
|
57
|
+
* columns on `integration_runs` so assertions read like DB queries.
|
|
58
58
|
*/
|
|
59
59
|
export interface MemoryRunRecord {
|
|
60
60
|
id: string;
|
|
@@ -74,7 +74,7 @@ export interface MemoryRunRecord {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
@Injectable()
|
|
77
|
-
export class MemoryRunRecorder implements
|
|
77
|
+
export class MemoryRunRecorder implements IIntegrationRunRecorder {
|
|
78
78
|
/**
|
|
79
79
|
* All started runs keyed by id. Public so tests can inspect lifecycle
|
|
80
80
|
* transitions without poking through recording methods.
|
|
@@ -82,20 +82,20 @@ export class MemoryRunRecorder implements ISyncRunRecorder {
|
|
|
82
82
|
readonly runs: Map<string, MemoryRunRecord> = new Map();
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
|
-
* Items keyed by `
|
|
86
|
-
* mirrors the timeline the `(
|
|
85
|
+
* Items keyed by `integration_run_id`, array order matches insertion order —
|
|
86
|
+
* mirrors the timeline the `(integration_run_id, created_at)` index produces
|
|
87
87
|
* in Postgres.
|
|
88
88
|
*/
|
|
89
89
|
readonly items: Map<string, RecordItemInput[]> = new Map();
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
92
|
* Seedable subscription metadata — tests populate this to make
|
|
93
|
-
* `listRecent` return meaningful `
|
|
93
|
+
* `listRecent` return meaningful `connectionId` values. The memory
|
|
94
94
|
* backend doesn't track subscriptions on its own (only runs + items), so
|
|
95
95
|
* this map is the intentional extension point: tests write entries for
|
|
96
96
|
* the subscription ids they use, production code never touches it.
|
|
97
97
|
*/
|
|
98
|
-
readonly subscriptions: Map<string,
|
|
98
|
+
readonly subscriptions: Map<string, MemoryIntegrationSubscription> = new Map();
|
|
99
99
|
|
|
100
100
|
async startRun(input: StartRunInput): Promise<{ id: string }> {
|
|
101
101
|
const id = crypto.randomUUID();
|
|
@@ -123,10 +123,10 @@ export class MemoryRunRecorder implements ISyncRunRecorder {
|
|
|
123
123
|
// Same ADR-0003 contract as the Drizzle backend.
|
|
124
124
|
FieldDiffSchema.parse(input.changedFields);
|
|
125
125
|
|
|
126
|
-
const bucket = this.items.get(input.
|
|
126
|
+
const bucket = this.items.get(input.integrationRunId);
|
|
127
127
|
if (!bucket) {
|
|
128
128
|
throw new Error(
|
|
129
|
-
`MemoryRunRecorder.recordItem: no run started for id '${input.
|
|
129
|
+
`MemoryRunRecorder.recordItem: no run started for id '${input.integrationRunId}'. ` +
|
|
130
130
|
`Call startRun(...) first.`,
|
|
131
131
|
);
|
|
132
132
|
}
|
|
@@ -153,7 +153,7 @@ export class MemoryRunRecorder implements ISyncRunRecorder {
|
|
|
153
153
|
limit: number,
|
|
154
154
|
subscriptionId?: string,
|
|
155
155
|
_tenantId?: string | null,
|
|
156
|
-
): Promise<
|
|
156
|
+
): Promise<IntegrationRunSummary[]> {
|
|
157
157
|
// Memory backend accepts tenantId for contract symmetry but does not
|
|
158
158
|
// filter on it — state is process-local and cross-tenant isolation is
|
|
159
159
|
// not meaningful here (matches MemoryCursorStore behavior).
|
|
@@ -168,11 +168,11 @@ export class MemoryRunRecorder implements ISyncRunRecorder {
|
|
|
168
168
|
.map((r) => ({
|
|
169
169
|
id: r.id,
|
|
170
170
|
subscriptionId: r.subscriptionId,
|
|
171
|
-
//
|
|
171
|
+
// connectionId is only knowable if the test seeded subscriptions
|
|
172
172
|
// metadata; empty string otherwise. The Drizzle backend resolves
|
|
173
173
|
// it via JOIN, which is the production path.
|
|
174
|
-
|
|
175
|
-
this.subscriptions.get(r.subscriptionId)?.
|
|
174
|
+
connectionId:
|
|
175
|
+
this.subscriptions.get(r.subscriptionId)?.connectionId ?? '',
|
|
176
176
|
status: r.status,
|
|
177
177
|
startedAt: r.startedAt,
|
|
178
178
|
completedAt: r.completedAt,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Integration subsystem — run-recorder protocol (port)
|
|
3
3
|
*
|
|
4
|
-
* `
|
|
4
|
+
* `IIntegrationRunRecorder` is the write side of the audit log. `ExecuteIntegrationUseCase`
|
|
5
5
|
* (SYNC-5) calls `startRun` at the top of the loop, `recordItem` for each
|
|
6
6
|
* processed change, and `completeRun` in a `finally` block so a run always
|
|
7
7
|
* reaches a terminal status.
|
|
8
8
|
*
|
|
9
|
-
* The Drizzle backend (SYNC-4) persists against `
|
|
9
|
+
* The Drizzle backend (SYNC-4) persists against `integration_runs` / `integration_run_items`
|
|
10
10
|
* from the SYNC-1 schema. Tests use lightweight in-memory fakes — no
|
|
11
11
|
* dedicated memory backend ships; the surface is small enough that inline
|
|
12
12
|
* fakes keep the intent local to each spec.
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
* orchestrator before reaching the recorder, so the recorder's input is
|
|
18
18
|
* always a `FieldDiff`.
|
|
19
19
|
*/
|
|
20
|
-
import type { FieldDiff } from './
|
|
20
|
+
import type { FieldDiff } from './integration-field-diff.protocol';
|
|
21
21
|
|
|
22
22
|
// ============================================================================
|
|
23
23
|
// Lifecycle — inputs
|
|
24
24
|
// ============================================================================
|
|
25
25
|
|
|
26
|
-
/** Args for `startRun`. Mirrors the non-nullable columns on `
|
|
26
|
+
/** Args for `startRun`. Mirrors the non-nullable columns on `integration_runs`. */
|
|
27
27
|
export interface StartRunInput {
|
|
28
28
|
readonly subscriptionId: string;
|
|
29
29
|
readonly direction: 'inbound' | 'outbound';
|
|
@@ -31,16 +31,16 @@ export interface StartRunInput {
|
|
|
31
31
|
/** Cursor snapshot at run start, or `null` if this is the first run. */
|
|
32
32
|
readonly cursorBefore: unknown | null;
|
|
33
33
|
/**
|
|
34
|
-
* Tenant id when `
|
|
34
|
+
* Tenant id when `INTEGRATION_MULTI_TENANT` is enabled. The recorder's own
|
|
35
35
|
* boundary rule (SYNC-6) enforces non-null when the flag is on;
|
|
36
|
-
* orchestrator passes it through from `
|
|
36
|
+
* orchestrator passes it through from `ExecuteIntegrationInput.tenantId`.
|
|
37
37
|
*/
|
|
38
38
|
readonly tenantId?: string | null;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
/** Args for `recordItem`. Mirrors the non-nullable columns on `
|
|
41
|
+
/** Args for `recordItem`. Mirrors the non-nullable columns on `integration_run_items`. */
|
|
42
42
|
export interface RecordItemInput {
|
|
43
|
-
readonly
|
|
43
|
+
readonly integrationRunId: string;
|
|
44
44
|
readonly entityType: string;
|
|
45
45
|
readonly externalId: string;
|
|
46
46
|
readonly localId?: string | null;
|
|
@@ -71,24 +71,24 @@ export interface CompleteRunInput {
|
|
|
71
71
|
// ============================================================================
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
|
-
* Denormalized view of one `
|
|
75
|
-
* `
|
|
74
|
+
* Denormalized view of one `integration_runs` row, JOINed against
|
|
75
|
+
* `integration_subscriptions` to surface `connectionId` in a single read. Consumed
|
|
76
76
|
* by the OBS-5 observability composer (epic #195).
|
|
77
77
|
*
|
|
78
|
-
* `recordsProcessed` is the denormalized column on `
|
|
79
|
-
* count `
|
|
78
|
+
* `recordsProcessed` is the denormalized column on `integration_runs` — it does NOT
|
|
79
|
+
* count `integration_run_items` rows. A correlated subquery per run would be
|
|
80
80
|
* required for a true item count; deferred as a follow-up if needed.
|
|
81
81
|
*
|
|
82
|
-
* Memory backends can't know `
|
|
82
|
+
* Memory backends can't know `connectionId` without subscription metadata
|
|
83
83
|
* — see each memory backend for the seedable `subscriptions` side-map that
|
|
84
84
|
* tests populate. When metadata is missing, memory backends emit an empty
|
|
85
85
|
* string so the shape stays stable (documented in the memory backend).
|
|
86
86
|
*/
|
|
87
|
-
export interface
|
|
87
|
+
export interface IntegrationRunSummary {
|
|
88
88
|
readonly id: string;
|
|
89
89
|
readonly subscriptionId: string;
|
|
90
90
|
/** Resolved by Drizzle via JOIN; empty string from memory if not seeded. */
|
|
91
|
-
readonly
|
|
91
|
+
readonly connectionId: string;
|
|
92
92
|
readonly status: 'running' | 'success' | 'no_changes' | 'failed';
|
|
93
93
|
readonly startedAt: Date;
|
|
94
94
|
readonly completedAt: Date | null;
|
|
@@ -97,14 +97,14 @@ export interface SyncRunSummary {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
// ============================================================================
|
|
100
|
-
//
|
|
100
|
+
// IIntegrationRunRecorder
|
|
101
101
|
// ============================================================================
|
|
102
102
|
|
|
103
|
-
export interface
|
|
104
|
-
/** Opens a new `
|
|
103
|
+
export interface IIntegrationRunRecorder {
|
|
104
|
+
/** Opens a new `integration_runs` row in `status = 'running'`. Returns the run id. */
|
|
105
105
|
startRun(input: StartRunInput): Promise<{ id: string }>;
|
|
106
106
|
|
|
107
|
-
/** Appends one `
|
|
107
|
+
/** Appends one `integration_run_items` row. Throws if `changedFields` is malformed. */
|
|
108
108
|
recordItem(input: RecordItemInput): Promise<void>;
|
|
109
109
|
|
|
110
110
|
/**
|
|
@@ -115,16 +115,16 @@ export interface ISyncRunRecorder {
|
|
|
115
115
|
completeRun(runId: string, input: CompleteRunInput): Promise<void>;
|
|
116
116
|
|
|
117
117
|
/**
|
|
118
|
-
* Recent `
|
|
118
|
+
* Recent `integration_runs` rows ordered by `started_at DESC`, capped at `limit`.
|
|
119
119
|
*
|
|
120
|
-
* Filter is `subscriptionId` — the natural FK on `
|
|
121
|
-
* integration-wide view requires filtering on `
|
|
120
|
+
* Filter is `subscriptionId` — the natural FK on `integration_runs`. An
|
|
121
|
+
* integration-wide view requires filtering on `integration_subscriptions.connection_id`
|
|
122
122
|
* through the JOIN and is deferred as a follow-up (epic #195 OBS-4 spec).
|
|
123
123
|
*
|
|
124
124
|
* @param limit hard cap on rows returned (no implicit default)
|
|
125
125
|
* @param subscriptionId optional FK filter; omit for cross-subscription view
|
|
126
126
|
* @param tenantId required by Drizzle backend when
|
|
127
|
-
* `
|
|
127
|
+
* `INTEGRATION_MULTI_TENANT` is on (throws
|
|
128
128
|
* `MissingTenantIdError` otherwise); memory backend
|
|
129
129
|
* accepts but ignores
|
|
130
130
|
*/
|
|
@@ -132,5 +132,5 @@ export interface ISyncRunRecorder {
|
|
|
132
132
|
limit: number,
|
|
133
133
|
subscriptionId?: string,
|
|
134
134
|
tenantId?: string | null,
|
|
135
|
-
): Promise<
|
|
135
|
+
): Promise<IntegrationRunSummary[]>;
|
|
136
136
|
}
|
package/runtime/subsystems/{sync/sync-sink.protocol.ts → integration/integration-sink.protocol.ts}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Integration subsystem — integration-sink protocol (port)
|
|
3
3
|
*
|
|
4
4
|
* Write surface for the generic orchestrator. One per canonical entity type.
|
|
5
5
|
*
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* Implementations compose the entity's service + (when the entity has EAV)
|
|
14
14
|
* `FieldValueService` inside a single transaction. ADR-13-revised.
|
|
15
15
|
*/
|
|
16
|
-
export interface
|
|
16
|
+
export interface IIntegrationSink<TCanonical> {
|
|
17
17
|
/**
|
|
18
18
|
* Canonical-shaped view of local state, or `null` when no local row exists.
|
|
19
19
|
* Called once per change to source the diff's "before" side.
|
|
@@ -32,11 +32,11 @@ export interface ISyncSink<TCanonical> {
|
|
|
32
32
|
* - tolerate re-entry (same record twice in a window = no-op)
|
|
33
33
|
*
|
|
34
34
|
* Returns the local row id and the canonical projection of the saved row
|
|
35
|
-
* (so the orchestrator can record it on `
|
|
35
|
+
* (so the orchestrator can record it on `integration_run_items.local_id`).
|
|
36
36
|
*
|
|
37
37
|
* `provider` is the adapter domain string (e.g. `'salesforce-crm'`,
|
|
38
38
|
* `'hubspot-crm'`) persisted on the DB row. Passed from
|
|
39
|
-
* `
|
|
39
|
+
* `ExecuteIntegrationInput.provider`.
|
|
40
40
|
*/
|
|
41
41
|
upsertByExternalId(
|
|
42
42
|
userId: string,
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* wiring the
|
|
2
|
+
* IntegrationModule — `DynamicModule.forRoot({ backend, multiTenant? })` factory
|
|
3
|
+
* wiring the integration subsystem's substrate (SYNC-6, ADR-008 subsystem pattern).
|
|
4
4
|
*
|
|
5
5
|
* ## What this module provides
|
|
6
6
|
*
|
|
7
|
-
* - `
|
|
8
|
-
* - `
|
|
9
|
-
* - `
|
|
10
|
-
* - `
|
|
11
|
-
* - `
|
|
7
|
+
* - `INTEGRATION_CURSOR_STORE` — Drizzle or Memory cursor store
|
|
8
|
+
* - `INTEGRATION_RUN_RECORDER` — Drizzle or Memory run recorder
|
|
9
|
+
* - `INTEGRATION_FIELD_DIFFER` — default `DeepEqualDiffer`
|
|
10
|
+
* - `INTEGRATION_MULTI_TENANT` — resolved boolean flag (defaults to false)
|
|
11
|
+
* - `INTEGRATION_MODULE_OPTIONS` — the options object itself, for backends
|
|
12
12
|
* that need to inspect config at construction time
|
|
13
13
|
*
|
|
14
14
|
* ## What this module does NOT provide
|
|
15
15
|
*
|
|
16
|
-
* - `
|
|
17
|
-
* their feature module (e.g. `
|
|
16
|
+
* - `INTEGRATION_CHANGE_SOURCE` — per-provider per-entity; consumer binds in
|
|
17
|
+
* their feature module (e.g. `OpportunityIntegrationModule` provides a
|
|
18
18
|
* `SalesforceOpportunityChangeSource`). Loopback suppression — when
|
|
19
19
|
* needed — is composed into the primitive's middleware chain via
|
|
20
20
|
* `createLoopbackMiddleware(store)` (#226-5 / ADR-033); the
|
|
21
21
|
* orchestrator no longer accepts a fingerprint store directly.
|
|
22
|
-
* - `
|
|
22
|
+
* - `INTEGRATION_SINK` — per canonical entity; consumer binds in their feature
|
|
23
23
|
* module.
|
|
24
|
-
* - `
|
|
24
|
+
* - `ExecuteIntegrationUseCase` — registered by the feature module alongside
|
|
25
25
|
* its source + sink bindings. Providing the orchestrator here would
|
|
26
|
-
* force Nest to resolve
|
|
26
|
+
* force Nest to resolve INTEGRATION_CHANGE_SOURCE + INTEGRATION_SINK at module
|
|
27
27
|
* compile time, which fails when the feature module hasn't been
|
|
28
|
-
* imported yet. Consumers register `
|
|
28
|
+
* imported yet. Consumers register `ExecuteIntegrationUseCase` in the same
|
|
29
29
|
* `providers` array as their source + sink so resolution is local
|
|
30
30
|
* to where all three are bound.
|
|
31
31
|
*
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
* ```ts
|
|
39
39
|
* // AppModule — single source of truth for backend + multi-tenancy.
|
|
40
40
|
* @Module({
|
|
41
|
-
* imports: [
|
|
41
|
+
* imports: [IntegrationModule.forRoot({ backend: 'drizzle' })],
|
|
42
42
|
* })
|
|
43
43
|
* export class AppModule {}
|
|
44
44
|
*
|
|
@@ -46,36 +46,36 @@
|
|
|
46
46
|
* // orchestrator for free.
|
|
47
47
|
* @Module({
|
|
48
48
|
* providers: [
|
|
49
|
-
* { provide:
|
|
50
|
-
* { provide:
|
|
51
|
-
*
|
|
49
|
+
* { provide: INTEGRATION_CHANGE_SOURCE, useClass: SalesforceOpportunitySource },
|
|
50
|
+
* { provide: INTEGRATION_SINK, useClass: OpportunityIntegrationSink },
|
|
51
|
+
* ExecuteIntegrationUseCase,
|
|
52
52
|
* ],
|
|
53
53
|
* })
|
|
54
|
-
* export class
|
|
54
|
+
* export class OpportunityIntegrationModule {
|
|
55
55
|
* constructor(
|
|
56
|
-
* private readonly execute:
|
|
56
|
+
* private readonly execute: ExecuteIntegrationUseCase<CanonicalOpportunity>,
|
|
57
57
|
* ) {}
|
|
58
58
|
* }
|
|
59
59
|
* ```
|
|
60
60
|
*
|
|
61
61
|
* `global: true` means feature modules do not need to re-import
|
|
62
|
-
* `
|
|
62
|
+
* `IntegrationModule` — the substrate tokens are available project-wide.
|
|
63
63
|
*/
|
|
64
64
|
import { Module, type DynamicModule, type Provider } from '@nestjs/common';
|
|
65
65
|
import {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
} from './
|
|
72
|
-
import { MemoryCursorStore } from './
|
|
73
|
-
import { MemoryRunRecorder } from './
|
|
74
|
-
import { PostgresCursorStore } from './
|
|
75
|
-
import {
|
|
66
|
+
INTEGRATION_CURSOR_STORE,
|
|
67
|
+
INTEGRATION_FIELD_DIFFER,
|
|
68
|
+
INTEGRATION_MODULE_OPTIONS,
|
|
69
|
+
INTEGRATION_MULTI_TENANT,
|
|
70
|
+
INTEGRATION_RUN_RECORDER,
|
|
71
|
+
} from './integration.tokens';
|
|
72
|
+
import { MemoryCursorStore } from './integration-cursor-store.memory-backend';
|
|
73
|
+
import { MemoryRunRecorder } from './integration-run-recorder.memory-backend';
|
|
74
|
+
import { PostgresCursorStore } from './integration-cursor-store.drizzle-backend';
|
|
75
|
+
import { DrizzleIntegrationRunRecorder } from './integration-run-recorder.drizzle-backend';
|
|
76
76
|
import { DeepEqualDiffer } from './deep-equal.differ';
|
|
77
77
|
|
|
78
|
-
export interface
|
|
78
|
+
export interface IntegrationModuleOptions {
|
|
79
79
|
/**
|
|
80
80
|
* Backend selection. `drizzle` wires the Postgres cursor store +
|
|
81
81
|
* run-log recorder; `memory` wires in-memory doubles suitable for
|
|
@@ -103,16 +103,16 @@ export interface SyncModuleOptions {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
@Module({})
|
|
106
|
-
export class
|
|
107
|
-
static forRoot(options:
|
|
106
|
+
export class IntegrationModule {
|
|
107
|
+
static forRoot(options: IntegrationModuleOptions): DynamicModule {
|
|
108
108
|
const multiTenant = options.multiTenant ?? false;
|
|
109
109
|
|
|
110
110
|
const sharedProviders: Provider[] = [
|
|
111
|
-
{ provide:
|
|
112
|
-
{ provide:
|
|
111
|
+
{ provide: INTEGRATION_MODULE_OPTIONS, useValue: options },
|
|
112
|
+
{ provide: INTEGRATION_MULTI_TENANT, useValue: multiTenant },
|
|
113
113
|
// Default differ — consumers can override by binding a different
|
|
114
|
-
// `IFieldDiffer<T>` to `
|
|
115
|
-
{ provide:
|
|
114
|
+
// `IFieldDiffer<T>` to `INTEGRATION_FIELD_DIFFER` in their feature module.
|
|
115
|
+
{ provide: INTEGRATION_FIELD_DIFFER, useValue: new DeepEqualDiffer() },
|
|
116
116
|
];
|
|
117
117
|
|
|
118
118
|
const backendProviders: Provider[] =
|
|
@@ -123,33 +123,33 @@ export class SyncModule {
|
|
|
123
123
|
// direct assertions. Matches JOB-4 / MemoryJobStore shape.
|
|
124
124
|
{ provide: MemoryCursorStore, useValue: new MemoryCursorStore() },
|
|
125
125
|
{
|
|
126
|
-
provide:
|
|
126
|
+
provide: INTEGRATION_CURSOR_STORE,
|
|
127
127
|
useExisting: MemoryCursorStore,
|
|
128
128
|
},
|
|
129
129
|
{ provide: MemoryRunRecorder, useValue: new MemoryRunRecorder() },
|
|
130
130
|
{
|
|
131
|
-
provide:
|
|
131
|
+
provide: INTEGRATION_RUN_RECORDER,
|
|
132
132
|
useExisting: MemoryRunRecorder,
|
|
133
133
|
},
|
|
134
134
|
]
|
|
135
135
|
: [
|
|
136
136
|
// Drizzle backends — injected with DRIZZLE (provided by the
|
|
137
|
-
// consumer's DrizzleModule) + the
|
|
137
|
+
// consumer's DrizzleModule) + the INTEGRATION_MULTI_TENANT flag
|
|
138
138
|
// we bound above.
|
|
139
|
-
{ provide:
|
|
140
|
-
{ provide:
|
|
139
|
+
{ provide: INTEGRATION_CURSOR_STORE, useClass: PostgresCursorStore },
|
|
140
|
+
{ provide: INTEGRATION_RUN_RECORDER, useClass: DrizzleIntegrationRunRecorder },
|
|
141
141
|
];
|
|
142
142
|
|
|
143
143
|
return {
|
|
144
|
-
module:
|
|
144
|
+
module: IntegrationModule,
|
|
145
145
|
global: true,
|
|
146
146
|
providers: [...sharedProviders, ...backendProviders],
|
|
147
147
|
exports: [
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
INTEGRATION_MODULE_OPTIONS,
|
|
149
|
+
INTEGRATION_MULTI_TENANT,
|
|
150
|
+
INTEGRATION_FIELD_DIFFER,
|
|
151
|
+
INTEGRATION_CURSOR_STORE,
|
|
152
|
+
INTEGRATION_RUN_RECORDER,
|
|
153
153
|
],
|
|
154
154
|
};
|
|
155
155
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration subsystem — DI tokens
|
|
3
|
+
*
|
|
4
|
+
* String constants (not Symbols) so they match by value across import
|
|
5
|
+
* boundaries — same convention as the events subsystem (`EVENT_BUS`). The
|
|
6
|
+
* jobs subsystem uses Symbols for its analogous tokens; events and integration
|
|
7
|
+
* stay internally consistent with strings.
|
|
8
|
+
*
|
|
9
|
+
* Usage in use cases:
|
|
10
|
+
* ```ts
|
|
11
|
+
* constructor(
|
|
12
|
+
* @Inject(INTEGRATION_CHANGE_SOURCE) private readonly source: IChangeSource<CanonicalOpportunity>,
|
|
13
|
+
* @Inject(INTEGRATION_CURSOR_STORE) private readonly cursors: ICursorStore,
|
|
14
|
+
* @Inject(INTEGRATION_FIELD_DIFFER) private readonly differ: IFieldDiffer<CanonicalOpportunity>,
|
|
15
|
+
* @Inject(INTEGRATION_SINK) private readonly sink: IIntegrationSink<CanonicalOpportunity>,
|
|
16
|
+
* @Inject(INTEGRATION_RUN_RECORDER) private readonly recorder: IIntegrationRunRecorder,
|
|
17
|
+
* ) {}
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* Concrete bindings are registered by `IntegrationModule.forRoot(...)` (SYNC-6).
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export const INTEGRATION_CHANGE_SOURCE = 'INTEGRATION_CHANGE_SOURCE' as const;
|
|
24
|
+
export const INTEGRATION_CURSOR_STORE = 'INTEGRATION_CURSOR_STORE' as const;
|
|
25
|
+
export const INTEGRATION_FIELD_DIFFER = 'INTEGRATION_FIELD_DIFFER' as const;
|
|
26
|
+
export const INTEGRATION_SINK = 'INTEGRATION_SINK' as const;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Run-recorder token (SYNC-5). Backed by `IIntegrationRunRecorder`. Drizzle impl
|
|
30
|
+
* lands in SYNC-4; tests provide inline fakes.
|
|
31
|
+
*/
|
|
32
|
+
export const INTEGRATION_RUN_RECORDER = 'INTEGRATION_RUN_RECORDER' as const;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Injection token for the resolved `IntegrationModuleOptions` object (SYNC-6).
|
|
36
|
+
*
|
|
37
|
+
* Backends that need to observe module configuration (e.g. `multiTenant`
|
|
38
|
+
* flag, pool filters) inject via this token. Provided automatically by
|
|
39
|
+
* `IntegrationModule.forRoot(...)` / `IntegrationModule.forRootAsync(...)`.
|
|
40
|
+
*/
|
|
41
|
+
export const INTEGRATION_MODULE_OPTIONS = 'INTEGRATION_MODULE_OPTIONS' as const;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Injection token for the resolved multi-tenancy flag (SYNC-6).
|
|
45
|
+
*
|
|
46
|
+
* Provided by `IntegrationModule.forRoot(...)` as `options.multiTenant ?? false`.
|
|
47
|
+
* Consumed by `ExecuteIntegrationUseCase` to enforce the tenantId-is-required rule.
|
|
48
|
+
*/
|
|
49
|
+
export const INTEGRATION_MULTI_TENANT = 'INTEGRATION_MULTI_TENANT' as const;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Integration subsystem — loopback `ChangeMiddleware` factory (#226-5, ADR-033).
|
|
3
3
|
*
|
|
4
|
-
* Replaces the prior orchestrator-side `@Optional()
|
|
4
|
+
* Replaces the prior orchestrator-side `@Optional() INTEGRATION_LOOPBACK_FINGERPRINT_STORE`
|
|
5
5
|
* branch. Consumers that need to suppress echoes of their own outbound
|
|
6
6
|
* writes compose `createLoopbackMiddleware(store)` into a primitive's
|
|
7
7
|
* middleware chain — typically alongside `PollChangeSource<T>` — instead
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
* their store or layer a counting middleware alongside this one.
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
-
import type { Change } from './
|
|
31
|
+
import type { Change } from './integration-change-source.protocol';
|
|
32
32
|
import type {
|
|
33
33
|
ChangeIterator,
|
|
34
34
|
ChangeMiddleware,
|
|
35
|
-
} from './
|
|
36
|
-
import type { ILoopbackFingerprintStore } from './
|
|
35
|
+
} from './integration-middleware.protocol';
|
|
36
|
+
import type { ILoopbackFingerprintStore } from './integration-loopback.protocol';
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* Build a `ChangeMiddleware<T>` that suppresses changes whose fingerprint
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Integration subsystem — `PollChangeSource<T>` primitive (#226-3, ADR-033).
|
|
3
3
|
*
|
|
4
4
|
* Generic poll-mode `IChangeSource<T>` implementation parameterized by a
|
|
5
5
|
* parsed `DetectionConfig` (poll mode) and a consumer-supplied
|
|
@@ -36,12 +36,12 @@ import type {
|
|
|
36
36
|
Change,
|
|
37
37
|
ChangeSource,
|
|
38
38
|
IChangeSource,
|
|
39
|
-
|
|
40
|
-
} from './
|
|
39
|
+
IntegrationSubscriptionView,
|
|
40
|
+
} from './integration-change-source.protocol';
|
|
41
41
|
import type {
|
|
42
42
|
ChangeIterator,
|
|
43
43
|
ChangeMiddleware,
|
|
44
|
-
} from './
|
|
44
|
+
} from './integration-middleware.protocol';
|
|
45
45
|
|
|
46
46
|
// ============================================================================
|
|
47
47
|
// Cursor + adapter callback shapes
|
|
@@ -60,7 +60,7 @@ export type PollCursor = unknown;
|
|
|
60
60
|
* NOT here on purpose.
|
|
61
61
|
*/
|
|
62
62
|
export interface PollFetchContext {
|
|
63
|
-
readonly subscription:
|
|
63
|
+
readonly subscription: IntegrationSubscriptionView;
|
|
64
64
|
readonly cursor: PollCursor | null;
|
|
65
65
|
readonly filters: readonly ResolvedFilter[];
|
|
66
66
|
}
|
|
@@ -174,14 +174,14 @@ export class PollChangeSource<T> implements IChangeSource<T> {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
listChanges(
|
|
177
|
-
subscription:
|
|
177
|
+
subscription: IntegrationSubscriptionView,
|
|
178
178
|
cursor: unknown | null,
|
|
179
179
|
): AsyncIterable<Change<T>> {
|
|
180
180
|
return this.composed(subscription, cursor);
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
private async *fetch(
|
|
184
|
-
subscription:
|
|
184
|
+
subscription: IntegrationSubscriptionView,
|
|
185
185
|
cursor: unknown | null,
|
|
186
186
|
): AsyncIterable<Change<T>> {
|
|
187
187
|
const ctx: PollFetchContext = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Integration subsystem — `WebhookChangeSource<T>` primitive (#226-4, ADR-033).
|
|
3
3
|
*
|
|
4
4
|
* Generic webhook-mode `IChangeSource<T>` implementation parameterized by a
|
|
5
5
|
* parsed `DetectionConfig` (webhook mode) and a consumer-supplied
|
|
@@ -40,12 +40,12 @@ import type { DetectionConfig } from './detection-config.schema';
|
|
|
40
40
|
import type {
|
|
41
41
|
Change,
|
|
42
42
|
IChangeSource,
|
|
43
|
-
|
|
44
|
-
} from './
|
|
43
|
+
IntegrationSubscriptionView,
|
|
44
|
+
} from './integration-change-source.protocol';
|
|
45
45
|
import type {
|
|
46
46
|
ChangeIterator,
|
|
47
47
|
ChangeMiddleware,
|
|
48
|
-
} from './
|
|
48
|
+
} from './integration-middleware.protocol';
|
|
49
49
|
|
|
50
50
|
// ============================================================================
|
|
51
51
|
// Cursor + queue callback shapes
|
|
@@ -65,7 +65,7 @@ export type WebhookCursor = unknown;
|
|
|
65
65
|
* `userId` / `tenantId`.
|
|
66
66
|
*/
|
|
67
67
|
export interface WebhookFetchContext {
|
|
68
|
-
readonly subscription:
|
|
68
|
+
readonly subscription: IntegrationSubscriptionView;
|
|
69
69
|
readonly cursor: WebhookCursor | null;
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -162,14 +162,14 @@ export class WebhookChangeSource<T> implements IChangeSource<T> {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
listChanges(
|
|
165
|
-
subscription:
|
|
165
|
+
subscription: IntegrationSubscriptionView,
|
|
166
166
|
cursor: unknown | null,
|
|
167
167
|
): AsyncIterable<Change<T>> {
|
|
168
168
|
return this.composed(subscription, cursor);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
private async *fetch(
|
|
172
|
-
subscription:
|
|
172
|
+
subscription: IntegrationSubscriptionView,
|
|
173
173
|
cursor: unknown | null,
|
|
174
174
|
): AsyncIterable<Change<T>> {
|
|
175
175
|
const ctx: WebhookFetchContext = {
|