@pattern-stack/codegen 0.10.1 → 0.12.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 +122 -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 +11 -7
- package/dist/runtime/subsystems/index.js +1041 -67
- 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/integration/entity-change-source-registry.memory.d.ts +25 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.js +34 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.js.map +1 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.d.ts +53 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.js +13 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.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 +30 -0
- package/dist/runtime/subsystems/{sync → integration}/index.js +206 -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 +60 -0
- package/dist/runtime/subsystems/integration/integration.tokens.js +20 -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 +1336 -376
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.d.ts +70 -22
- package/dist/src/index.js +290 -194
- 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 +9 -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 +26 -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/integration/entity-change-source-registry.memory.ts +40 -0
- package/runtime/subsystems/integration/entity-change-source-registry.protocol.ts +59 -0
- package/runtime/subsystems/{sync/execute-sync.use-case.ts → integration/execute-integration.use-case.ts} +40 -40
- package/runtime/subsystems/{sync → integration}/index.ts +56 -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 +63 -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/clean-lite-ps/entity.ejs.t +12 -3
- package/templates/entity/new/clean-lite-ps/module.ejs.t +1 -1
- package/templates/entity/new/clean-lite-ps/prompt-extension.js +243 -60
- 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/entity/new/backend/modules/core/sync-source.providers.ejs.t +0 -18
- 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
|
@@ -9,7 +9,7 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
9
9
|
if (kind && result) __defProp(target, key, result);
|
|
10
10
|
return result;
|
|
11
11
|
};
|
|
12
|
-
var __decorateParam = (
|
|
12
|
+
var __decorateParam = (index4, decorator) => (target, key) => decorator(target, key, index4);
|
|
13
13
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
14
14
|
|
|
15
15
|
// runtime/subsystems/events/events.tokens.ts
|
|
@@ -4016,23 +4016,29 @@ import { Module as Module6 } from "@nestjs/common";
|
|
|
4016
4016
|
// runtime/subsystems/observability/observability.service.ts
|
|
4017
4017
|
import { Inject as Inject13, Injectable as Injectable14, Optional as Optional7 } from "@nestjs/common";
|
|
4018
4018
|
|
|
4019
|
-
// runtime/subsystems/
|
|
4020
|
-
var
|
|
4021
|
-
var
|
|
4019
|
+
// runtime/subsystems/integration/integration.tokens.ts
|
|
4020
|
+
var INTEGRATION_CHANGE_SOURCE = "INTEGRATION_CHANGE_SOURCE";
|
|
4021
|
+
var INTEGRATION_CURSOR_STORE = "INTEGRATION_CURSOR_STORE";
|
|
4022
|
+
var INTEGRATION_FIELD_DIFFER = "INTEGRATION_FIELD_DIFFER";
|
|
4023
|
+
var INTEGRATION_SINK = "INTEGRATION_SINK";
|
|
4024
|
+
var INTEGRATION_RUN_RECORDER = "INTEGRATION_RUN_RECORDER";
|
|
4025
|
+
var INTEGRATION_MODULE_OPTIONS = "INTEGRATION_MODULE_OPTIONS";
|
|
4026
|
+
var INTEGRATION_MULTI_TENANT = "INTEGRATION_MULTI_TENANT";
|
|
4027
|
+
var ENTITY_CHANGE_SOURCE_REGISTRY = "ENTITY_CHANGE_SOURCE_REGISTRY";
|
|
4022
4028
|
|
|
4023
4029
|
// runtime/subsystems/observability/observability.service.ts
|
|
4024
4030
|
var MAX_TIMELINE_PAGES = 50;
|
|
4025
4031
|
var ObservabilityService = class {
|
|
4026
|
-
constructor(jobRuns2, bridge,
|
|
4032
|
+
constructor(jobRuns2, bridge, integrationRuns2, cursors, events) {
|
|
4027
4033
|
this.jobRuns = jobRuns2;
|
|
4028
4034
|
this.bridge = bridge;
|
|
4029
|
-
this.
|
|
4035
|
+
this.integrationRuns = integrationRuns2;
|
|
4030
4036
|
this.cursors = cursors;
|
|
4031
4037
|
this.events = events;
|
|
4032
4038
|
}
|
|
4033
4039
|
jobRuns;
|
|
4034
4040
|
bridge;
|
|
4035
|
-
|
|
4041
|
+
integrationRuns;
|
|
4036
4042
|
cursors;
|
|
4037
4043
|
events;
|
|
4038
4044
|
async getPoolDepths(tenantId) {
|
|
@@ -4047,9 +4053,9 @@ var ObservabilityService = class {
|
|
|
4047
4053
|
if (!this.bridge) return { ...ObservabilityService.EMPTY_HISTOGRAM };
|
|
4048
4054
|
return this.bridge.getStatusHistogram(windowHours, tenantId);
|
|
4049
4055
|
}
|
|
4050
|
-
async
|
|
4051
|
-
if (!this.
|
|
4052
|
-
return this.
|
|
4056
|
+
async getRecentIntegrationRuns(limit, subscriptionId, tenantId) {
|
|
4057
|
+
if (!this.integrationRuns) return [];
|
|
4058
|
+
return this.integrationRuns.listRecent(limit, subscriptionId, tenantId);
|
|
4053
4059
|
}
|
|
4054
4060
|
async getCursors(tenantId) {
|
|
4055
4061
|
if (!this.cursors) return [];
|
|
@@ -4173,9 +4179,9 @@ ObservabilityService = __decorateClass([
|
|
|
4173
4179
|
__decorateParam(1, Optional7()),
|
|
4174
4180
|
__decorateParam(1, Inject13(BRIDGE_DELIVERY_REPO)),
|
|
4175
4181
|
__decorateParam(2, Optional7()),
|
|
4176
|
-
__decorateParam(2, Inject13(
|
|
4182
|
+
__decorateParam(2, Inject13(INTEGRATION_RUN_RECORDER)),
|
|
4177
4183
|
__decorateParam(3, Optional7()),
|
|
4178
|
-
__decorateParam(3, Inject13(
|
|
4184
|
+
__decorateParam(3, Inject13(INTEGRATION_CURSOR_STORE)),
|
|
4179
4185
|
__decorateParam(4, Optional7()),
|
|
4180
4186
|
__decorateParam(4, Inject13(EVENT_READ_PORT))
|
|
4181
4187
|
], ObservabilityService);
|
|
@@ -4287,6 +4293,971 @@ var ObservabilityError = class extends Error {
|
|
|
4287
4293
|
cause;
|
|
4288
4294
|
};
|
|
4289
4295
|
|
|
4296
|
+
// runtime/subsystems/integration/integration-field-diff.protocol.ts
|
|
4297
|
+
import { z as z2 } from "zod";
|
|
4298
|
+
var FieldDiffValueSchema = z2.object({
|
|
4299
|
+
from: z2.unknown(),
|
|
4300
|
+
to: z2.unknown()
|
|
4301
|
+
});
|
|
4302
|
+
var FieldDiffSchema = z2.record(z2.string(), FieldDiffValueSchema);
|
|
4303
|
+
|
|
4304
|
+
// runtime/subsystems/integration/entity-change-source-registry.protocol.ts
|
|
4305
|
+
var UnknownEntityError = class extends Error {
|
|
4306
|
+
constructor(entity, available) {
|
|
4307
|
+
super(
|
|
4308
|
+
`No change source registered for entity '${entity}'. Available: ${available.join(", ")}`
|
|
4309
|
+
);
|
|
4310
|
+
this.name = "UnknownEntityError";
|
|
4311
|
+
}
|
|
4312
|
+
};
|
|
4313
|
+
|
|
4314
|
+
// runtime/subsystems/integration/entity-change-source-registry.memory.ts
|
|
4315
|
+
var MemoryEntityChangeSourceRegistry = class {
|
|
4316
|
+
constructor(sources) {
|
|
4317
|
+
this.sources = sources;
|
|
4318
|
+
}
|
|
4319
|
+
sources;
|
|
4320
|
+
get(name) {
|
|
4321
|
+
const source = this.sources.get(name);
|
|
4322
|
+
if (!source) {
|
|
4323
|
+
throw new UnknownEntityError(name, [...this.sources.keys()]);
|
|
4324
|
+
}
|
|
4325
|
+
return source;
|
|
4326
|
+
}
|
|
4327
|
+
has(name) {
|
|
4328
|
+
return this.sources.has(name);
|
|
4329
|
+
}
|
|
4330
|
+
entities() {
|
|
4331
|
+
return [...this.sources.keys()];
|
|
4332
|
+
}
|
|
4333
|
+
};
|
|
4334
|
+
|
|
4335
|
+
// runtime/subsystems/integration/detection-config.schema.ts
|
|
4336
|
+
import { z as z3 } from "zod";
|
|
4337
|
+
var FieldMappingSchema = z3.object({
|
|
4338
|
+
source: z3.string().min(1),
|
|
4339
|
+
target: z3.string().min(1),
|
|
4340
|
+
transform: z3.string().min(1).optional()
|
|
4341
|
+
});
|
|
4342
|
+
var ResolvedFilterSchema = z3.object({
|
|
4343
|
+
field: z3.string().min(1),
|
|
4344
|
+
op: z3.enum(["eq", "neq", "in", "nin", "gt", "gte", "lt", "lte"]),
|
|
4345
|
+
value: z3.unknown()
|
|
4346
|
+
});
|
|
4347
|
+
var SystemModstampCursorSchema = z3.object({
|
|
4348
|
+
kind: z3.literal("systemModstamp"),
|
|
4349
|
+
field: z3.string().min(1)
|
|
4350
|
+
});
|
|
4351
|
+
var ReplayIdCursorSchema = z3.object({
|
|
4352
|
+
kind: z3.literal("replayId"),
|
|
4353
|
+
field: z3.string().min(1)
|
|
4354
|
+
});
|
|
4355
|
+
var TimestampCursorSchema = z3.object({
|
|
4356
|
+
kind: z3.literal("timestamp"),
|
|
4357
|
+
field: z3.string().min(1)
|
|
4358
|
+
});
|
|
4359
|
+
var EventIdCursorSchema = z3.object({
|
|
4360
|
+
kind: z3.literal("eventId"),
|
|
4361
|
+
field: z3.string().min(1)
|
|
4362
|
+
});
|
|
4363
|
+
var CursorStrategySchema = z3.discriminatedUnion("kind", [
|
|
4364
|
+
SystemModstampCursorSchema,
|
|
4365
|
+
ReplayIdCursorSchema,
|
|
4366
|
+
TimestampCursorSchema,
|
|
4367
|
+
EventIdCursorSchema
|
|
4368
|
+
]);
|
|
4369
|
+
var PollDetectionSchema = z3.object({
|
|
4370
|
+
cursor: CursorStrategySchema,
|
|
4371
|
+
provenance: z3.enum(["poll", "cdc"]).optional()
|
|
4372
|
+
});
|
|
4373
|
+
var WebhookDetectionSchema = z3.object({
|
|
4374
|
+
eventIdField: z3.string().min(1)
|
|
4375
|
+
});
|
|
4376
|
+
var PollModeSchema = z3.object({
|
|
4377
|
+
mode: z3.literal("poll"),
|
|
4378
|
+
poll: PollDetectionSchema,
|
|
4379
|
+
mapping: z3.array(FieldMappingSchema).min(1),
|
|
4380
|
+
filters: z3.array(ResolvedFilterSchema).default([])
|
|
4381
|
+
});
|
|
4382
|
+
var WebhookModeSchema = z3.object({
|
|
4383
|
+
mode: z3.literal("webhook"),
|
|
4384
|
+
webhook: WebhookDetectionSchema,
|
|
4385
|
+
mapping: z3.array(FieldMappingSchema).min(1),
|
|
4386
|
+
filters: z3.array(ResolvedFilterSchema).default([])
|
|
4387
|
+
});
|
|
4388
|
+
var DetectionConfigSchema = z3.discriminatedUnion("mode", [
|
|
4389
|
+
PollModeSchema,
|
|
4390
|
+
WebhookModeSchema
|
|
4391
|
+
]);
|
|
4392
|
+
|
|
4393
|
+
// runtime/subsystems/integration/integration-errors.ts
|
|
4394
|
+
var MissingTenantIdError3 = class extends Error {
|
|
4395
|
+
name = "MissingTenantIdError";
|
|
4396
|
+
constructor(operation) {
|
|
4397
|
+
super(
|
|
4398
|
+
`Missing tenantId for integration operation '${operation}'. IntegrationModule is configured with multiTenant: true \u2014 every call must include a non-null tenantId. Either pass the tenantId or disable multi-tenancy on the module.`
|
|
4399
|
+
);
|
|
4400
|
+
}
|
|
4401
|
+
};
|
|
4402
|
+
function assertTenantId(tenantId, options) {
|
|
4403
|
+
if (!options.multiTenant) return;
|
|
4404
|
+
if (tenantId === void 0 || tenantId === null) {
|
|
4405
|
+
throw new MissingTenantIdError3(options.operation);
|
|
4406
|
+
}
|
|
4407
|
+
}
|
|
4408
|
+
|
|
4409
|
+
// runtime/subsystems/integration/integration-audit.schema.ts
|
|
4410
|
+
import {
|
|
4411
|
+
pgEnum as pgEnum2,
|
|
4412
|
+
pgTable as pgTable4,
|
|
4413
|
+
uuid as uuid3,
|
|
4414
|
+
text as text4,
|
|
4415
|
+
jsonb as jsonb4,
|
|
4416
|
+
integer as integer2,
|
|
4417
|
+
boolean,
|
|
4418
|
+
timestamp as timestamp4,
|
|
4419
|
+
index as index3,
|
|
4420
|
+
uniqueIndex as uniqueIndex2
|
|
4421
|
+
} from "drizzle-orm/pg-core";
|
|
4422
|
+
var integrationRunDirectionEnum = pgEnum2("integration_run_direction", [
|
|
4423
|
+
"inbound",
|
|
4424
|
+
"outbound"
|
|
4425
|
+
]);
|
|
4426
|
+
var integrationRunActionEnum = pgEnum2("integration_run_action", [
|
|
4427
|
+
"poll",
|
|
4428
|
+
"cdc",
|
|
4429
|
+
"webhook",
|
|
4430
|
+
"manual",
|
|
4431
|
+
"writeback"
|
|
4432
|
+
]);
|
|
4433
|
+
var integrationRunStatusEnum = pgEnum2("integration_run_status", [
|
|
4434
|
+
"running",
|
|
4435
|
+
"success",
|
|
4436
|
+
"no_changes",
|
|
4437
|
+
"failed"
|
|
4438
|
+
]);
|
|
4439
|
+
var integrationRunItemOperationEnum = pgEnum2("integration_run_item_operation", [
|
|
4440
|
+
"created",
|
|
4441
|
+
"updated",
|
|
4442
|
+
"deleted",
|
|
4443
|
+
"noop"
|
|
4444
|
+
]);
|
|
4445
|
+
var integrationRunItemStatusEnum = pgEnum2("integration_run_item_status", [
|
|
4446
|
+
"success",
|
|
4447
|
+
"failed",
|
|
4448
|
+
"skipped"
|
|
4449
|
+
]);
|
|
4450
|
+
var integrationSubscriptions = pgTable4(
|
|
4451
|
+
"integration_subscriptions",
|
|
4452
|
+
{
|
|
4453
|
+
id: uuid3("id").primaryKey().defaultRandom(),
|
|
4454
|
+
connectionId: text4("connection_id").notNull(),
|
|
4455
|
+
adapter: text4("adapter").notNull(),
|
|
4456
|
+
domain: text4("domain").notNull(),
|
|
4457
|
+
externalRef: text4("external_ref"),
|
|
4458
|
+
enabled: boolean("enabled").notNull().default(true),
|
|
4459
|
+
/**
|
|
4460
|
+
* Per-subscription configuration bag. Strategies type it internally;
|
|
4461
|
+
* e.g. polling strategies stash `{ batchSize, highWatermark }` here.
|
|
4462
|
+
*/
|
|
4463
|
+
config: jsonb4("config").notNull().default({}).$type(),
|
|
4464
|
+
/**
|
|
4465
|
+
* Opaque cursor persisted by `ICursorStore.put()`. NULL until the first
|
|
4466
|
+
* successful run advances it.
|
|
4467
|
+
*/
|
|
4468
|
+
cursor: jsonb4("cursor").$type(),
|
|
4469
|
+
lastIntegrationAt: timestamp4("last_integration_at", { withTimezone: true }),
|
|
4470
|
+
/** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
|
|
4471
|
+
tenantId: text4("tenant_id"),
|
|
4472
|
+
createdAt: timestamp4("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
4473
|
+
updatedAt: timestamp4("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
4474
|
+
},
|
|
4475
|
+
(t) => ({
|
|
4476
|
+
/**
|
|
4477
|
+
* Composite uniqueness per the epic shape. `external_ref` is nullable;
|
|
4478
|
+
* Postgres treats NULLs as distinct in a UNIQUE constraint, which means
|
|
4479
|
+
* two rows with the same `(connection_id, adapter, domain)` and NULL
|
|
4480
|
+
* external_ref are allowed. That's intentional — a subscription with
|
|
4481
|
+
* NULL external_ref covers the full domain, and duplicates there would
|
|
4482
|
+
* be a consumer-layer modeling issue, not a schema concern.
|
|
4483
|
+
*/
|
|
4484
|
+
uqIntegrationSubscriptionTuple: uniqueIndex2("uq_integration_subscriptions_tuple").on(
|
|
4485
|
+
t.connectionId,
|
|
4486
|
+
t.adapter,
|
|
4487
|
+
t.domain,
|
|
4488
|
+
t.externalRef
|
|
4489
|
+
),
|
|
4490
|
+
/** Scheduling query: list enabled subscriptions ordered by staleness. */
|
|
4491
|
+
idxIntegrationSubscriptionsEnabledLastIntegration: index3(
|
|
4492
|
+
"idx_integration_subscriptions_enabled_last_integration"
|
|
4493
|
+
).on(t.enabled, t.lastIntegrationAt)
|
|
4494
|
+
})
|
|
4495
|
+
);
|
|
4496
|
+
var integrationRuns = pgTable4(
|
|
4497
|
+
"integration_runs",
|
|
4498
|
+
{
|
|
4499
|
+
id: uuid3("id").primaryKey().defaultRandom(),
|
|
4500
|
+
subscriptionId: uuid3("subscription_id").notNull().references(() => integrationSubscriptions.id, { onDelete: "cascade" }),
|
|
4501
|
+
direction: integrationRunDirectionEnum("direction").notNull(),
|
|
4502
|
+
action: integrationRunActionEnum("action").notNull(),
|
|
4503
|
+
status: integrationRunStatusEnum("status").notNull().default("running"),
|
|
4504
|
+
recordsFound: integer2("records_found").notNull().default(0),
|
|
4505
|
+
recordsProcessed: integer2("records_processed").notNull().default(0),
|
|
4506
|
+
cursorBefore: jsonb4("cursor_before").$type(),
|
|
4507
|
+
cursorAfter: jsonb4("cursor_after").$type(),
|
|
4508
|
+
durationMs: integer2("duration_ms"),
|
|
4509
|
+
error: text4("error"),
|
|
4510
|
+
startedAt: timestamp4("started_at", { withTimezone: true }).notNull().defaultNow(),
|
|
4511
|
+
completedAt: timestamp4("completed_at", { withTimezone: true }),
|
|
4512
|
+
/** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
|
|
4513
|
+
tenantId: text4("tenant_id")
|
|
4514
|
+
},
|
|
4515
|
+
(t) => ({
|
|
4516
|
+
/** Timeline read: "most recent runs for this subscription". */
|
|
4517
|
+
idxIntegrationRunsSubscriptionStartedAt: index3(
|
|
4518
|
+
"idx_integration_runs_subscription_started_at"
|
|
4519
|
+
).on(t.subscriptionId, t.startedAt),
|
|
4520
|
+
/** Stale-run sweeper: "runs that started > N minutes ago and are still running". */
|
|
4521
|
+
idxIntegrationRunsStatusStartedAt: index3("idx_integration_runs_status_started_at").on(
|
|
4522
|
+
t.status,
|
|
4523
|
+
t.startedAt
|
|
4524
|
+
)
|
|
4525
|
+
})
|
|
4526
|
+
);
|
|
4527
|
+
var integrationRunItems = pgTable4(
|
|
4528
|
+
"integration_run_items",
|
|
4529
|
+
{
|
|
4530
|
+
id: uuid3("id").primaryKey().defaultRandom(),
|
|
4531
|
+
integrationRunId: uuid3("integration_run_id").notNull().references(() => integrationRuns.id, { onDelete: "cascade" }),
|
|
4532
|
+
entityType: text4("entity_type").notNull(),
|
|
4533
|
+
externalId: text4("external_id").notNull(),
|
|
4534
|
+
localId: text4("local_id"),
|
|
4535
|
+
operation: integrationRunItemOperationEnum("operation").notNull(),
|
|
4536
|
+
status: integrationRunItemStatusEnum("status").notNull(),
|
|
4537
|
+
/**
|
|
4538
|
+
* Structured per-field diff — ADR-0003 shape enforced by
|
|
4539
|
+
* `FieldDiffSchema.parse` at the recorder service layer.
|
|
4540
|
+
*
|
|
4541
|
+
* Shape: `{ [fieldName]: { from: unknown, to: unknown } }`.
|
|
4542
|
+
* Empty `{}` for `noop` items; `{ [field]: { from: null, to: <value> } }`
|
|
4543
|
+
* for created items; `{ [field]: { from: <value>, to: null } }` for
|
|
4544
|
+
* deleted items.
|
|
4545
|
+
*/
|
|
4546
|
+
changedFields: jsonb4("changed_fields").notNull().default({}).$type(),
|
|
4547
|
+
title: text4("title"),
|
|
4548
|
+
error: text4("error"),
|
|
4549
|
+
createdAt: timestamp4("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
4550
|
+
/** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
|
|
4551
|
+
tenantId: text4("tenant_id")
|
|
4552
|
+
},
|
|
4553
|
+
(t) => ({
|
|
4554
|
+
/** Ordered timeline within a run. */
|
|
4555
|
+
idxIntegrationRunItemsRunCreatedAt: index3("idx_integration_run_items_run_created_at").on(
|
|
4556
|
+
t.integrationRunId,
|
|
4557
|
+
t.createdAt
|
|
4558
|
+
),
|
|
4559
|
+
/** Per-record history: "every integration that touched opportunity/$extId". */
|
|
4560
|
+
idxIntegrationRunItemsEntityExternal: index3(
|
|
4561
|
+
"idx_integration_run_items_entity_external"
|
|
4562
|
+
).on(t.entityType, t.externalId)
|
|
4563
|
+
})
|
|
4564
|
+
);
|
|
4565
|
+
|
|
4566
|
+
// runtime/subsystems/integration/integration-cursor-store.memory-backend.ts
|
|
4567
|
+
import { Injectable as Injectable16 } from "@nestjs/common";
|
|
4568
|
+
var MemoryCursorStore = class {
|
|
4569
|
+
/**
|
|
4570
|
+
* Subscription-id → last persisted cursor. Public so tests can inspect
|
|
4571
|
+
* or pre-seed state; production callers MUST go through `get`/`put`.
|
|
4572
|
+
*/
|
|
4573
|
+
cursors = /* @__PURE__ */ new Map();
|
|
4574
|
+
/**
|
|
4575
|
+
* Seedable subscription metadata for `listAll` — the memory backend
|
|
4576
|
+
* stores only `subscriptionId → cursor` in its write path, so the
|
|
4577
|
+
* snapshot shape (`connectionId`, `adapter`, `domain`, `externalRef`,
|
|
4578
|
+
* timestamps) has no natural source without test seeding. Tests populate
|
|
4579
|
+
* this map; unseeded entries get empty-string metadata and `new Date(0)`
|
|
4580
|
+
* timestamps so the shape stays stable. Production paths go through the
|
|
4581
|
+
* Drizzle backend.
|
|
4582
|
+
*/
|
|
4583
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
4584
|
+
async get(subscriptionId, _tenantId) {
|
|
4585
|
+
const value = this.cursors.get(subscriptionId);
|
|
4586
|
+
return value === void 0 ? null : value;
|
|
4587
|
+
}
|
|
4588
|
+
async put(subscriptionId, cursor, _tenantId) {
|
|
4589
|
+
this.cursors.set(subscriptionId, cursor);
|
|
4590
|
+
}
|
|
4591
|
+
async listAll(_tenantId) {
|
|
4592
|
+
const snapshots = [];
|
|
4593
|
+
for (const [subscriptionId, cursor] of this.cursors.entries()) {
|
|
4594
|
+
const meta = this.subscriptions.get(subscriptionId);
|
|
4595
|
+
snapshots.push({
|
|
4596
|
+
subscriptionId,
|
|
4597
|
+
connectionId: meta?.connectionId ?? "",
|
|
4598
|
+
adapter: meta?.adapter ?? "",
|
|
4599
|
+
domain: meta?.domain ?? "",
|
|
4600
|
+
externalRef: meta?.externalRef ?? null,
|
|
4601
|
+
cursor: cursor ?? null,
|
|
4602
|
+
lastIntegrationAt: meta?.lastIntegrationAt ?? null,
|
|
4603
|
+
updatedAt: meta?.updatedAt ?? /* @__PURE__ */ new Date(0),
|
|
4604
|
+
tenantId: null
|
|
4605
|
+
});
|
|
4606
|
+
}
|
|
4607
|
+
return snapshots.sort(
|
|
4608
|
+
(a, b) => b.updatedAt.getTime() - a.updatedAt.getTime()
|
|
4609
|
+
);
|
|
4610
|
+
}
|
|
4611
|
+
/** Reset state. Tests call this in `beforeEach`. */
|
|
4612
|
+
clear() {
|
|
4613
|
+
this.cursors.clear();
|
|
4614
|
+
this.subscriptions.clear();
|
|
4615
|
+
}
|
|
4616
|
+
};
|
|
4617
|
+
MemoryCursorStore = __decorateClass([
|
|
4618
|
+
Injectable16()
|
|
4619
|
+
], MemoryCursorStore);
|
|
4620
|
+
|
|
4621
|
+
// runtime/subsystems/integration/integration-run-recorder.memory-backend.ts
|
|
4622
|
+
import { Injectable as Injectable17 } from "@nestjs/common";
|
|
4623
|
+
var MemoryRunRecorder = class {
|
|
4624
|
+
/**
|
|
4625
|
+
* All started runs keyed by id. Public so tests can inspect lifecycle
|
|
4626
|
+
* transitions without poking through recording methods.
|
|
4627
|
+
*/
|
|
4628
|
+
runs = /* @__PURE__ */ new Map();
|
|
4629
|
+
/**
|
|
4630
|
+
* Items keyed by `integration_run_id`, array order matches insertion order —
|
|
4631
|
+
* mirrors the timeline the `(integration_run_id, created_at)` index produces
|
|
4632
|
+
* in Postgres.
|
|
4633
|
+
*/
|
|
4634
|
+
items = /* @__PURE__ */ new Map();
|
|
4635
|
+
/**
|
|
4636
|
+
* Seedable subscription metadata — tests populate this to make
|
|
4637
|
+
* `listRecent` return meaningful `connectionId` values. The memory
|
|
4638
|
+
* backend doesn't track subscriptions on its own (only runs + items), so
|
|
4639
|
+
* this map is the intentional extension point: tests write entries for
|
|
4640
|
+
* the subscription ids they use, production code never touches it.
|
|
4641
|
+
*/
|
|
4642
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
4643
|
+
async startRun(input) {
|
|
4644
|
+
const id = crypto.randomUUID();
|
|
4645
|
+
this.runs.set(id, {
|
|
4646
|
+
id,
|
|
4647
|
+
subscriptionId: input.subscriptionId,
|
|
4648
|
+
direction: input.direction,
|
|
4649
|
+
action: input.action,
|
|
4650
|
+
status: "running",
|
|
4651
|
+
cursorBefore: input.cursorBefore ?? null,
|
|
4652
|
+
cursorAfter: null,
|
|
4653
|
+
recordsFound: 0,
|
|
4654
|
+
recordsProcessed: 0,
|
|
4655
|
+
durationMs: null,
|
|
4656
|
+
error: null,
|
|
4657
|
+
tenantId: input.tenantId ?? null,
|
|
4658
|
+
startedAt: /* @__PURE__ */ new Date(),
|
|
4659
|
+
completedAt: null
|
|
4660
|
+
});
|
|
4661
|
+
this.items.set(id, []);
|
|
4662
|
+
return { id };
|
|
4663
|
+
}
|
|
4664
|
+
async recordItem(input) {
|
|
4665
|
+
FieldDiffSchema.parse(input.changedFields);
|
|
4666
|
+
const bucket = this.items.get(input.integrationRunId);
|
|
4667
|
+
if (!bucket) {
|
|
4668
|
+
throw new Error(
|
|
4669
|
+
`MemoryRunRecorder.recordItem: no run started for id '${input.integrationRunId}'. Call startRun(...) first.`
|
|
4670
|
+
);
|
|
4671
|
+
}
|
|
4672
|
+
bucket.push(input);
|
|
4673
|
+
}
|
|
4674
|
+
async completeRun(runId, input) {
|
|
4675
|
+
const run = this.runs.get(runId);
|
|
4676
|
+
if (!run) {
|
|
4677
|
+
throw new Error(
|
|
4678
|
+
`MemoryRunRecorder.completeRun: no run started for id '${runId}'.`
|
|
4679
|
+
);
|
|
4680
|
+
}
|
|
4681
|
+
run.status = input.status;
|
|
4682
|
+
run.recordsFound = input.recordsFound;
|
|
4683
|
+
run.recordsProcessed = input.recordsProcessed;
|
|
4684
|
+
run.cursorAfter = input.cursorAfter ?? null;
|
|
4685
|
+
run.durationMs = input.durationMs;
|
|
4686
|
+
run.error = input.error ?? null;
|
|
4687
|
+
run.completedAt = /* @__PURE__ */ new Date();
|
|
4688
|
+
}
|
|
4689
|
+
async listRecent(limit, subscriptionId, _tenantId) {
|
|
4690
|
+
const all = Array.from(this.runs.values());
|
|
4691
|
+
const filtered = subscriptionId === void 0 ? all : all.filter((r) => r.subscriptionId === subscriptionId);
|
|
4692
|
+
return filtered.sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime()).slice(0, limit).map((r) => ({
|
|
4693
|
+
id: r.id,
|
|
4694
|
+
subscriptionId: r.subscriptionId,
|
|
4695
|
+
// connectionId is only knowable if the test seeded subscriptions
|
|
4696
|
+
// metadata; empty string otherwise. The Drizzle backend resolves
|
|
4697
|
+
// it via JOIN, which is the production path.
|
|
4698
|
+
connectionId: this.subscriptions.get(r.subscriptionId)?.connectionId ?? "",
|
|
4699
|
+
status: r.status,
|
|
4700
|
+
startedAt: r.startedAt,
|
|
4701
|
+
completedAt: r.completedAt,
|
|
4702
|
+
recordsProcessed: r.recordsProcessed,
|
|
4703
|
+
tenantId: r.tenantId
|
|
4704
|
+
}));
|
|
4705
|
+
}
|
|
4706
|
+
/** Reset state. Tests call this in `beforeEach`. */
|
|
4707
|
+
clear() {
|
|
4708
|
+
this.runs.clear();
|
|
4709
|
+
this.items.clear();
|
|
4710
|
+
this.subscriptions.clear();
|
|
4711
|
+
}
|
|
4712
|
+
// ─── test ergonomics ─────────────────────────────────────────────────
|
|
4713
|
+
/** All runs for a subscription, newest first. Timeline reads. */
|
|
4714
|
+
getRunsForSubscription(subscriptionId) {
|
|
4715
|
+
return Array.from(this.runs.values()).filter((r) => r.subscriptionId === subscriptionId).sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime());
|
|
4716
|
+
}
|
|
4717
|
+
/** All item rows for a run, insertion-ordered. */
|
|
4718
|
+
getItemsForRun(runId) {
|
|
4719
|
+
return this.items.get(runId) ?? [];
|
|
4720
|
+
}
|
|
4721
|
+
};
|
|
4722
|
+
MemoryRunRecorder = __decorateClass([
|
|
4723
|
+
Injectable17()
|
|
4724
|
+
], MemoryRunRecorder);
|
|
4725
|
+
|
|
4726
|
+
// runtime/subsystems/integration/deep-equal.differ.ts
|
|
4727
|
+
import { Injectable as Injectable18 } from "@nestjs/common";
|
|
4728
|
+
var DEFAULT_IGNORE_FIELDS = /* @__PURE__ */ new Set([
|
|
4729
|
+
"id",
|
|
4730
|
+
"createdAt",
|
|
4731
|
+
"updatedAt",
|
|
4732
|
+
"deletedAt",
|
|
4733
|
+
"type",
|
|
4734
|
+
"lastModifiedAt",
|
|
4735
|
+
"fields",
|
|
4736
|
+
"external_id",
|
|
4737
|
+
"externalId",
|
|
4738
|
+
"provider",
|
|
4739
|
+
"provider_metadata",
|
|
4740
|
+
"providerMetadata"
|
|
4741
|
+
]);
|
|
4742
|
+
var DeepEqualDiffer = class {
|
|
4743
|
+
ignore;
|
|
4744
|
+
constructor(opts = {}) {
|
|
4745
|
+
if (opts.ignore && opts.ignore.length > 0) {
|
|
4746
|
+
this.ignore = /* @__PURE__ */ new Set([...DEFAULT_IGNORE_FIELDS, ...opts.ignore]);
|
|
4747
|
+
} else {
|
|
4748
|
+
this.ignore = DEFAULT_IGNORE_FIELDS;
|
|
4749
|
+
}
|
|
4750
|
+
}
|
|
4751
|
+
diff(existing, incoming, providerChangedFields) {
|
|
4752
|
+
if (existing === null) {
|
|
4753
|
+
const out2 = {};
|
|
4754
|
+
for (const key of Object.keys(incoming)) {
|
|
4755
|
+
if (this.ignore.has(key)) continue;
|
|
4756
|
+
const value = incoming[key];
|
|
4757
|
+
if (value === null || value === void 0) continue;
|
|
4758
|
+
out2[key] = { from: null, to: value };
|
|
4759
|
+
}
|
|
4760
|
+
return Object.keys(out2).length === 0 ? "noop" : out2;
|
|
4761
|
+
}
|
|
4762
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
4763
|
+
if (providerChangedFields && providerChangedFields.length > 0) {
|
|
4764
|
+
for (const key of providerChangedFields) {
|
|
4765
|
+
if (!this.ignore.has(key)) candidates.add(key);
|
|
4766
|
+
}
|
|
4767
|
+
} else {
|
|
4768
|
+
for (const key of Object.keys(incoming)) {
|
|
4769
|
+
if (!this.ignore.has(key)) candidates.add(key);
|
|
4770
|
+
}
|
|
4771
|
+
for (const key of Object.keys(existing)) {
|
|
4772
|
+
if (this.ignore.has(key)) continue;
|
|
4773
|
+
if (!(key in incoming)) continue;
|
|
4774
|
+
candidates.add(key);
|
|
4775
|
+
}
|
|
4776
|
+
}
|
|
4777
|
+
const out = {};
|
|
4778
|
+
for (const key of candidates) {
|
|
4779
|
+
const before = existing[key];
|
|
4780
|
+
const after = incoming[key];
|
|
4781
|
+
if (!isEqual(before, after)) {
|
|
4782
|
+
out[key] = { from: before ?? null, to: after ?? null };
|
|
4783
|
+
}
|
|
4784
|
+
}
|
|
4785
|
+
return Object.keys(out).length === 0 ? "noop" : out;
|
|
4786
|
+
}
|
|
4787
|
+
};
|
|
4788
|
+
DeepEqualDiffer = __decorateClass([
|
|
4789
|
+
Injectable18()
|
|
4790
|
+
], DeepEqualDiffer);
|
|
4791
|
+
function isEqual(a, b) {
|
|
4792
|
+
if (a === b) return true;
|
|
4793
|
+
const na = normalize(a);
|
|
4794
|
+
const nb = normalize(b);
|
|
4795
|
+
if (na === nb) return true;
|
|
4796
|
+
if (typeof na === "object" && typeof nb === "object" && na !== null && nb !== null) {
|
|
4797
|
+
return deepEqualObject(na, nb);
|
|
4798
|
+
}
|
|
4799
|
+
const numericEqual = maybeNumericEqual(na, nb) || maybeNumericEqual(nb, na);
|
|
4800
|
+
return numericEqual;
|
|
4801
|
+
}
|
|
4802
|
+
function normalize(value) {
|
|
4803
|
+
if (value instanceof Date) return value.toISOString();
|
|
4804
|
+
return value;
|
|
4805
|
+
}
|
|
4806
|
+
function maybeNumericEqual(a, b) {
|
|
4807
|
+
if (typeof a !== "string" || typeof b !== "number") return false;
|
|
4808
|
+
if (a.trim() === "") return false;
|
|
4809
|
+
const parsed = Number(a);
|
|
4810
|
+
if (!Number.isFinite(parsed)) return false;
|
|
4811
|
+
return parsed === b;
|
|
4812
|
+
}
|
|
4813
|
+
function deepEqualObject(a, b) {
|
|
4814
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
4815
|
+
const aKeys = Object.keys(a);
|
|
4816
|
+
const bKeys = Object.keys(b);
|
|
4817
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
4818
|
+
for (const key of aKeys) {
|
|
4819
|
+
if (!(key in b)) return false;
|
|
4820
|
+
if (!isEqual(a[key], b[key])) return false;
|
|
4821
|
+
}
|
|
4822
|
+
return true;
|
|
4823
|
+
}
|
|
4824
|
+
|
|
4825
|
+
// runtime/subsystems/integration/execute-integration.use-case.ts
|
|
4826
|
+
import { Inject as Inject15, Injectable as Injectable19, Logger as Logger8, Optional as Optional8 } from "@nestjs/common";
|
|
4827
|
+
var ExecuteIntegrationUseCase = class {
|
|
4828
|
+
constructor(source, cursors, differ, sink, recorder, multiTenant = false) {
|
|
4829
|
+
this.source = source;
|
|
4830
|
+
this.cursors = cursors;
|
|
4831
|
+
this.differ = differ;
|
|
4832
|
+
this.sink = sink;
|
|
4833
|
+
this.recorder = recorder;
|
|
4834
|
+
this.multiTenant = multiTenant;
|
|
4835
|
+
}
|
|
4836
|
+
source;
|
|
4837
|
+
cursors;
|
|
4838
|
+
differ;
|
|
4839
|
+
sink;
|
|
4840
|
+
recorder;
|
|
4841
|
+
multiTenant;
|
|
4842
|
+
logger = new Logger8(ExecuteIntegrationUseCase.name);
|
|
4843
|
+
async execute(input) {
|
|
4844
|
+
assertTenantId(input.tenantId, {
|
|
4845
|
+
multiTenant: this.multiTenant,
|
|
4846
|
+
operation: "execute"
|
|
4847
|
+
});
|
|
4848
|
+
const source = input.sourceOverride ?? this.source;
|
|
4849
|
+
const startedAt = Date.now();
|
|
4850
|
+
const cursorBefore = await this.cursors.get(input.subscription.id, input.tenantId);
|
|
4851
|
+
const { id: runId } = await this.recorder.startRun({
|
|
4852
|
+
subscriptionId: input.subscription.id,
|
|
4853
|
+
direction: input.direction,
|
|
4854
|
+
action: input.action,
|
|
4855
|
+
cursorBefore,
|
|
4856
|
+
tenantId: input.tenantId
|
|
4857
|
+
});
|
|
4858
|
+
let recordsFound = 0;
|
|
4859
|
+
let recordsProcessed = 0;
|
|
4860
|
+
let recordsFailed = 0;
|
|
4861
|
+
let latestCursor = cursorBefore;
|
|
4862
|
+
let cursorAdvanced = false;
|
|
4863
|
+
let runError = null;
|
|
4864
|
+
let status = "no_changes";
|
|
4865
|
+
try {
|
|
4866
|
+
for await (const change of source.listChanges(input.subscription, cursorBefore)) {
|
|
4867
|
+
recordsFound++;
|
|
4868
|
+
latestCursor = change.cursor;
|
|
4869
|
+
cursorAdvanced = true;
|
|
4870
|
+
try {
|
|
4871
|
+
await this.processChange(runId, input, change);
|
|
4872
|
+
recordsProcessed++;
|
|
4873
|
+
} catch (err) {
|
|
4874
|
+
recordsFailed++;
|
|
4875
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4876
|
+
this.logger.warn(
|
|
4877
|
+
`integration item failed: subscription=${input.subscription.id} externalId=${change.externalId}: ${message}`
|
|
4878
|
+
);
|
|
4879
|
+
await this.recorder.recordItem({
|
|
4880
|
+
integrationRunId: runId,
|
|
4881
|
+
entityType: input.subscription.domain,
|
|
4882
|
+
externalId: change.externalId,
|
|
4883
|
+
operation: change.operation === "deleted" ? "deleted" : "updated",
|
|
4884
|
+
status: "failed",
|
|
4885
|
+
changedFields: {},
|
|
4886
|
+
error: message,
|
|
4887
|
+
tenantId: input.tenantId
|
|
4888
|
+
});
|
|
4889
|
+
}
|
|
4890
|
+
}
|
|
4891
|
+
if (recordsFailed > 0 && recordsProcessed === 0 && recordsFound > 0) {
|
|
4892
|
+
status = "failed";
|
|
4893
|
+
runError = `all ${recordsFailed} records failed`;
|
|
4894
|
+
} else if (recordsFound === 0) {
|
|
4895
|
+
status = "no_changes";
|
|
4896
|
+
} else {
|
|
4897
|
+
status = "success";
|
|
4898
|
+
}
|
|
4899
|
+
} catch (err) {
|
|
4900
|
+
status = "failed";
|
|
4901
|
+
runError = err instanceof Error ? err.message : String(err);
|
|
4902
|
+
this.logger.error(
|
|
4903
|
+
`integration source failed: subscription=${input.subscription.id}: ${runError}`
|
|
4904
|
+
);
|
|
4905
|
+
}
|
|
4906
|
+
if (cursorAdvanced && latestCursor !== null && latestCursor !== void 0) {
|
|
4907
|
+
try {
|
|
4908
|
+
await this.cursors.put(input.subscription.id, latestCursor, input.tenantId);
|
|
4909
|
+
} catch (err) {
|
|
4910
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4911
|
+
this.logger.error(
|
|
4912
|
+
`cursor put failed: subscription=${input.subscription.id}: ${message}`
|
|
4913
|
+
);
|
|
4914
|
+
if (status !== "failed") {
|
|
4915
|
+
status = "failed";
|
|
4916
|
+
runError = `cursor put failed: ${message}`;
|
|
4917
|
+
}
|
|
4918
|
+
}
|
|
4919
|
+
}
|
|
4920
|
+
const durationMs = Date.now() - startedAt;
|
|
4921
|
+
await this.recorder.completeRun(runId, {
|
|
4922
|
+
status,
|
|
4923
|
+
recordsFound,
|
|
4924
|
+
recordsProcessed,
|
|
4925
|
+
cursorAfter: cursorAdvanced ? latestCursor : cursorBefore,
|
|
4926
|
+
durationMs,
|
|
4927
|
+
error: runError
|
|
4928
|
+
});
|
|
4929
|
+
return {
|
|
4930
|
+
runId,
|
|
4931
|
+
status,
|
|
4932
|
+
recordsFound,
|
|
4933
|
+
recordsProcessed,
|
|
4934
|
+
recordsFailed,
|
|
4935
|
+
cursorBefore,
|
|
4936
|
+
cursorAfter: cursorAdvanced ? latestCursor : cursorBefore,
|
|
4937
|
+
durationMs,
|
|
4938
|
+
error: runError
|
|
4939
|
+
};
|
|
4940
|
+
}
|
|
4941
|
+
async processChange(runId, input, change) {
|
|
4942
|
+
if (change.operation === "deleted") {
|
|
4943
|
+
const result = await this.sink.softDeleteByExternalId(
|
|
4944
|
+
input.userId,
|
|
4945
|
+
change.externalId
|
|
4946
|
+
);
|
|
4947
|
+
await this.recorder.recordItem({
|
|
4948
|
+
integrationRunId: runId,
|
|
4949
|
+
entityType: input.subscription.domain,
|
|
4950
|
+
externalId: change.externalId,
|
|
4951
|
+
localId: result?.id ?? null,
|
|
4952
|
+
operation: result ? "deleted" : "noop",
|
|
4953
|
+
status: "success",
|
|
4954
|
+
changedFields: {},
|
|
4955
|
+
tenantId: input.tenantId
|
|
4956
|
+
});
|
|
4957
|
+
return;
|
|
4958
|
+
}
|
|
4959
|
+
const existing = await this.sink.findByExternalId(
|
|
4960
|
+
input.userId,
|
|
4961
|
+
change.externalId
|
|
4962
|
+
);
|
|
4963
|
+
const diff = this.differ.diff(
|
|
4964
|
+
existing,
|
|
4965
|
+
change.record,
|
|
4966
|
+
change.providerChangedFields
|
|
4967
|
+
);
|
|
4968
|
+
if (diff === "noop") {
|
|
4969
|
+
if (!this.sink.reprojectsOnNoop) {
|
|
4970
|
+
await this.recorder.recordItem({
|
|
4971
|
+
integrationRunId: runId,
|
|
4972
|
+
entityType: input.subscription.domain,
|
|
4973
|
+
externalId: change.externalId,
|
|
4974
|
+
localId: null,
|
|
4975
|
+
operation: "noop",
|
|
4976
|
+
status: "success",
|
|
4977
|
+
changedFields: {},
|
|
4978
|
+
tenantId: input.tenantId
|
|
4979
|
+
});
|
|
4980
|
+
return;
|
|
4981
|
+
}
|
|
4982
|
+
const { id: noopLocalId } = await this.sink.upsertByExternalId(
|
|
4983
|
+
input.userId,
|
|
4984
|
+
change.record,
|
|
4985
|
+
input.provider
|
|
4986
|
+
);
|
|
4987
|
+
await this.recorder.recordItem({
|
|
4988
|
+
integrationRunId: runId,
|
|
4989
|
+
entityType: input.subscription.domain,
|
|
4990
|
+
externalId: change.externalId,
|
|
4991
|
+
localId: noopLocalId,
|
|
4992
|
+
operation: "noop",
|
|
4993
|
+
status: "success",
|
|
4994
|
+
changedFields: {},
|
|
4995
|
+
tenantId: input.tenantId
|
|
4996
|
+
});
|
|
4997
|
+
return;
|
|
4998
|
+
}
|
|
4999
|
+
const { id: localId } = await this.sink.upsertByExternalId(
|
|
5000
|
+
input.userId,
|
|
5001
|
+
change.record,
|
|
5002
|
+
input.provider
|
|
5003
|
+
);
|
|
5004
|
+
await this.recorder.recordItem({
|
|
5005
|
+
integrationRunId: runId,
|
|
5006
|
+
entityType: input.subscription.domain,
|
|
5007
|
+
externalId: change.externalId,
|
|
5008
|
+
localId,
|
|
5009
|
+
operation: existing === null ? "created" : "updated",
|
|
5010
|
+
status: "success",
|
|
5011
|
+
changedFields: diff,
|
|
5012
|
+
tenantId: input.tenantId
|
|
5013
|
+
});
|
|
5014
|
+
}
|
|
5015
|
+
};
|
|
5016
|
+
ExecuteIntegrationUseCase = __decorateClass([
|
|
5017
|
+
Injectable19(),
|
|
5018
|
+
__decorateParam(0, Inject15(INTEGRATION_CHANGE_SOURCE)),
|
|
5019
|
+
__decorateParam(1, Inject15(INTEGRATION_CURSOR_STORE)),
|
|
5020
|
+
__decorateParam(2, Inject15(INTEGRATION_FIELD_DIFFER)),
|
|
5021
|
+
__decorateParam(3, Inject15(INTEGRATION_SINK)),
|
|
5022
|
+
__decorateParam(4, Inject15(INTEGRATION_RUN_RECORDER)),
|
|
5023
|
+
__decorateParam(5, Optional8()),
|
|
5024
|
+
__decorateParam(5, Inject15(INTEGRATION_MULTI_TENANT))
|
|
5025
|
+
], ExecuteIntegrationUseCase);
|
|
5026
|
+
|
|
5027
|
+
// runtime/subsystems/integration/integration-cursor-store.drizzle-backend.ts
|
|
5028
|
+
import { Inject as Inject16, Injectable as Injectable20, Optional as Optional9 } from "@nestjs/common";
|
|
5029
|
+
import { and as and6, desc as desc5, eq as eq7 } from "drizzle-orm";
|
|
5030
|
+
var PostgresCursorStore = class {
|
|
5031
|
+
constructor(db, multiTenant) {
|
|
5032
|
+
this.db = db;
|
|
5033
|
+
this.multiTenant = multiTenant ?? false;
|
|
5034
|
+
}
|
|
5035
|
+
db;
|
|
5036
|
+
multiTenant;
|
|
5037
|
+
async get(subscriptionId, tenantId) {
|
|
5038
|
+
const where = this.buildWhere(subscriptionId, tenantId, "cursor.get");
|
|
5039
|
+
const rows = await this.db.select({ cursor: integrationSubscriptions.cursor }).from(integrationSubscriptions).where(where).limit(1);
|
|
5040
|
+
if (rows.length === 0) return null;
|
|
5041
|
+
return rows[0]?.cursor ?? null;
|
|
5042
|
+
}
|
|
5043
|
+
async put(subscriptionId, cursor, tenantId) {
|
|
5044
|
+
const where = this.buildWhere(subscriptionId, tenantId, "cursor.put");
|
|
5045
|
+
await this.db.update(integrationSubscriptions).set({
|
|
5046
|
+
cursor,
|
|
5047
|
+
lastIntegrationAt: /* @__PURE__ */ new Date(),
|
|
5048
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
5049
|
+
}).where(where);
|
|
5050
|
+
}
|
|
5051
|
+
async listAll(tenantId) {
|
|
5052
|
+
assertTenantId(tenantId, {
|
|
5053
|
+
multiTenant: this.multiTenant,
|
|
5054
|
+
operation: "cursor.listAll"
|
|
5055
|
+
});
|
|
5056
|
+
const where = this.multiTenant ? eq7(integrationSubscriptions.tenantId, tenantId) : void 0;
|
|
5057
|
+
const rows = await this.db.select({
|
|
5058
|
+
id: integrationSubscriptions.id,
|
|
5059
|
+
connectionId: integrationSubscriptions.connectionId,
|
|
5060
|
+
adapter: integrationSubscriptions.adapter,
|
|
5061
|
+
domain: integrationSubscriptions.domain,
|
|
5062
|
+
externalRef: integrationSubscriptions.externalRef,
|
|
5063
|
+
cursor: integrationSubscriptions.cursor,
|
|
5064
|
+
lastIntegrationAt: integrationSubscriptions.lastIntegrationAt,
|
|
5065
|
+
updatedAt: integrationSubscriptions.updatedAt,
|
|
5066
|
+
tenantId: integrationSubscriptions.tenantId
|
|
5067
|
+
}).from(integrationSubscriptions).where(where).orderBy(desc5(integrationSubscriptions.updatedAt));
|
|
5068
|
+
return rows.map((row) => ({
|
|
5069
|
+
subscriptionId: row.id,
|
|
5070
|
+
connectionId: row.connectionId,
|
|
5071
|
+
adapter: row.adapter,
|
|
5072
|
+
domain: row.domain,
|
|
5073
|
+
externalRef: row.externalRef,
|
|
5074
|
+
cursor: row.cursor ?? null,
|
|
5075
|
+
lastIntegrationAt: row.lastIntegrationAt,
|
|
5076
|
+
updatedAt: row.updatedAt,
|
|
5077
|
+
tenantId: row.tenantId
|
|
5078
|
+
}));
|
|
5079
|
+
}
|
|
5080
|
+
/**
|
|
5081
|
+
* Centralized WHERE clause — `get` and `put` share identical semantics.
|
|
5082
|
+
* Drift here would let a caller read under one tenancy rule and write
|
|
5083
|
+
* under another.
|
|
5084
|
+
*/
|
|
5085
|
+
buildWhere(subscriptionId, tenantId, operation) {
|
|
5086
|
+
assertTenantId(tenantId, {
|
|
5087
|
+
multiTenant: this.multiTenant,
|
|
5088
|
+
operation
|
|
5089
|
+
});
|
|
5090
|
+
if (this.multiTenant) {
|
|
5091
|
+
return and6(
|
|
5092
|
+
eq7(integrationSubscriptions.id, subscriptionId),
|
|
5093
|
+
eq7(integrationSubscriptions.tenantId, tenantId)
|
|
5094
|
+
);
|
|
5095
|
+
}
|
|
5096
|
+
return eq7(integrationSubscriptions.id, subscriptionId);
|
|
5097
|
+
}
|
|
5098
|
+
};
|
|
5099
|
+
PostgresCursorStore = __decorateClass([
|
|
5100
|
+
Injectable20(),
|
|
5101
|
+
__decorateParam(0, Inject16(DRIZZLE)),
|
|
5102
|
+
__decorateParam(1, Optional9()),
|
|
5103
|
+
__decorateParam(1, Inject16(INTEGRATION_MULTI_TENANT))
|
|
5104
|
+
], PostgresCursorStore);
|
|
5105
|
+
|
|
5106
|
+
// runtime/subsystems/integration/integration-run-recorder.drizzle-backend.ts
|
|
5107
|
+
import { Inject as Inject17, Injectable as Injectable21, Optional as Optional10 } from "@nestjs/common";
|
|
5108
|
+
import { and as and7, desc as desc6, eq as eq8 } from "drizzle-orm";
|
|
5109
|
+
var DrizzleIntegrationRunRecorder = class {
|
|
5110
|
+
constructor(db, multiTenant) {
|
|
5111
|
+
this.db = db;
|
|
5112
|
+
this.multiTenant = multiTenant ?? false;
|
|
5113
|
+
}
|
|
5114
|
+
db;
|
|
5115
|
+
multiTenant;
|
|
5116
|
+
async startRun(input) {
|
|
5117
|
+
assertTenantId(input.tenantId, {
|
|
5118
|
+
multiTenant: this.multiTenant,
|
|
5119
|
+
operation: "startRun"
|
|
5120
|
+
});
|
|
5121
|
+
const rows = await this.db.insert(integrationRuns).values({
|
|
5122
|
+
subscriptionId: input.subscriptionId,
|
|
5123
|
+
direction: input.direction,
|
|
5124
|
+
action: input.action,
|
|
5125
|
+
status: "running",
|
|
5126
|
+
cursorBefore: input.cursorBefore ?? null,
|
|
5127
|
+
tenantId: input.tenantId ?? null
|
|
5128
|
+
}).returning({ id: integrationRuns.id });
|
|
5129
|
+
const id = rows[0]?.id;
|
|
5130
|
+
if (!id) {
|
|
5131
|
+
throw new Error("DrizzleIntegrationRunRecorder: INSERT RETURNING produced no id");
|
|
5132
|
+
}
|
|
5133
|
+
return { id };
|
|
5134
|
+
}
|
|
5135
|
+
async recordItem(input) {
|
|
5136
|
+
assertTenantId(input.tenantId, {
|
|
5137
|
+
multiTenant: this.multiTenant,
|
|
5138
|
+
operation: "recordItem"
|
|
5139
|
+
});
|
|
5140
|
+
FieldDiffSchema.parse(input.changedFields);
|
|
5141
|
+
await this.db.insert(integrationRunItems).values({
|
|
5142
|
+
integrationRunId: input.integrationRunId,
|
|
5143
|
+
entityType: input.entityType,
|
|
5144
|
+
externalId: input.externalId,
|
|
5145
|
+
localId: input.localId ?? null,
|
|
5146
|
+
operation: input.operation,
|
|
5147
|
+
status: input.status,
|
|
5148
|
+
changedFields: input.changedFields,
|
|
5149
|
+
title: input.title ?? null,
|
|
5150
|
+
error: input.error ?? null,
|
|
5151
|
+
tenantId: input.tenantId ?? null
|
|
5152
|
+
});
|
|
5153
|
+
}
|
|
5154
|
+
async listRecent(limit, subscriptionId, tenantId) {
|
|
5155
|
+
assertTenantId(tenantId, {
|
|
5156
|
+
multiTenant: this.multiTenant,
|
|
5157
|
+
operation: "listRecent"
|
|
5158
|
+
});
|
|
5159
|
+
const conditions = [];
|
|
5160
|
+
if (subscriptionId !== void 0) {
|
|
5161
|
+
conditions.push(eq8(integrationRuns.subscriptionId, subscriptionId));
|
|
5162
|
+
}
|
|
5163
|
+
if (this.multiTenant) {
|
|
5164
|
+
conditions.push(eq8(integrationRuns.tenantId, tenantId));
|
|
5165
|
+
}
|
|
5166
|
+
const where = conditions.length === 0 ? void 0 : conditions.length === 1 ? conditions[0] : and7(...conditions);
|
|
5167
|
+
const rows = await this.db.select({
|
|
5168
|
+
id: integrationRuns.id,
|
|
5169
|
+
subscriptionId: integrationRuns.subscriptionId,
|
|
5170
|
+
connectionId: integrationSubscriptions.connectionId,
|
|
5171
|
+
status: integrationRuns.status,
|
|
5172
|
+
startedAt: integrationRuns.startedAt,
|
|
5173
|
+
completedAt: integrationRuns.completedAt,
|
|
5174
|
+
recordsProcessed: integrationRuns.recordsProcessed,
|
|
5175
|
+
tenantId: integrationRuns.tenantId
|
|
5176
|
+
}).from(integrationRuns).innerJoin(
|
|
5177
|
+
integrationSubscriptions,
|
|
5178
|
+
eq8(integrationRuns.subscriptionId, integrationSubscriptions.id)
|
|
5179
|
+
).where(where).orderBy(desc6(integrationRuns.startedAt)).limit(limit);
|
|
5180
|
+
return rows.map((row) => ({
|
|
5181
|
+
id: row.id,
|
|
5182
|
+
subscriptionId: row.subscriptionId,
|
|
5183
|
+
connectionId: row.connectionId,
|
|
5184
|
+
status: row.status,
|
|
5185
|
+
startedAt: row.startedAt,
|
|
5186
|
+
completedAt: row.completedAt,
|
|
5187
|
+
recordsProcessed: row.recordsProcessed,
|
|
5188
|
+
tenantId: row.tenantId
|
|
5189
|
+
}));
|
|
5190
|
+
}
|
|
5191
|
+
async completeRun(runId, input) {
|
|
5192
|
+
await this.db.update(integrationRuns).set({
|
|
5193
|
+
status: input.status,
|
|
5194
|
+
recordsFound: input.recordsFound,
|
|
5195
|
+
recordsProcessed: input.recordsProcessed,
|
|
5196
|
+
cursorAfter: input.cursorAfter ?? null,
|
|
5197
|
+
durationMs: input.durationMs,
|
|
5198
|
+
error: input.error ?? null,
|
|
5199
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
5200
|
+
}).where(eq8(integrationRuns.id, runId));
|
|
5201
|
+
}
|
|
5202
|
+
};
|
|
5203
|
+
DrizzleIntegrationRunRecorder = __decorateClass([
|
|
5204
|
+
Injectable21(),
|
|
5205
|
+
__decorateParam(0, Inject17(DRIZZLE)),
|
|
5206
|
+
__decorateParam(1, Optional10()),
|
|
5207
|
+
__decorateParam(1, Inject17(INTEGRATION_MULTI_TENANT))
|
|
5208
|
+
], DrizzleIntegrationRunRecorder);
|
|
5209
|
+
|
|
5210
|
+
// runtime/subsystems/integration/integration.module.ts
|
|
5211
|
+
import { Module as Module7 } from "@nestjs/common";
|
|
5212
|
+
var IntegrationModule = class {
|
|
5213
|
+
static forRoot(options) {
|
|
5214
|
+
const multiTenant = options.multiTenant ?? false;
|
|
5215
|
+
const sharedProviders = [
|
|
5216
|
+
{ provide: INTEGRATION_MODULE_OPTIONS, useValue: options },
|
|
5217
|
+
{ provide: INTEGRATION_MULTI_TENANT, useValue: multiTenant },
|
|
5218
|
+
// Default differ — consumers can override by binding a different
|
|
5219
|
+
// `IFieldDiffer<T>` to `INTEGRATION_FIELD_DIFFER` in their feature module.
|
|
5220
|
+
{ provide: INTEGRATION_FIELD_DIFFER, useValue: new DeepEqualDiffer() }
|
|
5221
|
+
];
|
|
5222
|
+
const backendProviders = options.backend === "memory" ? [
|
|
5223
|
+
// Wired as singletons via `useValue` so tests can pull
|
|
5224
|
+
// them out via `moduleRef.get(MemoryCursorStore)` for
|
|
5225
|
+
// direct assertions. Matches JOB-4 / MemoryJobStore shape.
|
|
5226
|
+
{ provide: MemoryCursorStore, useValue: new MemoryCursorStore() },
|
|
5227
|
+
{
|
|
5228
|
+
provide: INTEGRATION_CURSOR_STORE,
|
|
5229
|
+
useExisting: MemoryCursorStore
|
|
5230
|
+
},
|
|
5231
|
+
{ provide: MemoryRunRecorder, useValue: new MemoryRunRecorder() },
|
|
5232
|
+
{
|
|
5233
|
+
provide: INTEGRATION_RUN_RECORDER,
|
|
5234
|
+
useExisting: MemoryRunRecorder
|
|
5235
|
+
}
|
|
5236
|
+
] : [
|
|
5237
|
+
// Drizzle backends — injected with DRIZZLE (provided by the
|
|
5238
|
+
// consumer's DrizzleModule) + the INTEGRATION_MULTI_TENANT flag
|
|
5239
|
+
// we bound above.
|
|
5240
|
+
{ provide: INTEGRATION_CURSOR_STORE, useClass: PostgresCursorStore },
|
|
5241
|
+
{ provide: INTEGRATION_RUN_RECORDER, useClass: DrizzleIntegrationRunRecorder }
|
|
5242
|
+
];
|
|
5243
|
+
return {
|
|
5244
|
+
module: IntegrationModule,
|
|
5245
|
+
global: true,
|
|
5246
|
+
providers: [...sharedProviders, ...backendProviders],
|
|
5247
|
+
exports: [
|
|
5248
|
+
INTEGRATION_MODULE_OPTIONS,
|
|
5249
|
+
INTEGRATION_MULTI_TENANT,
|
|
5250
|
+
INTEGRATION_FIELD_DIFFER,
|
|
5251
|
+
INTEGRATION_CURSOR_STORE,
|
|
5252
|
+
INTEGRATION_RUN_RECORDER
|
|
5253
|
+
]
|
|
5254
|
+
};
|
|
5255
|
+
}
|
|
5256
|
+
};
|
|
5257
|
+
IntegrationModule = __decorateClass([
|
|
5258
|
+
Module7({})
|
|
5259
|
+
], IntegrationModule);
|
|
5260
|
+
|
|
4290
5261
|
// runtime/subsystems/auth/protocols/oauth-state-store.ts
|
|
4291
5262
|
var OAuthStateError = class extends Error {
|
|
4292
5263
|
constructor(message, reason) {
|
|
@@ -4300,25 +5271,25 @@ var OAuthStateError = class extends Error {
|
|
|
4300
5271
|
// runtime/subsystems/auth/auth.tokens.ts
|
|
4301
5272
|
var ENCRYPTION_KEY = /* @__PURE__ */ Symbol("ENCRYPTION_KEY");
|
|
4302
5273
|
var OAUTH_STATE_STORE = /* @__PURE__ */ Symbol("OAUTH_STATE_STORE");
|
|
4303
|
-
var
|
|
4304
|
-
var
|
|
4305
|
-
var
|
|
5274
|
+
var AUTH_CONNECTION_READER = /* @__PURE__ */ Symbol("AUTH_CONNECTION_READER");
|
|
5275
|
+
var AUTH_CONNECTION_TOKEN_WRITER = /* @__PURE__ */ Symbol("AUTH_CONNECTION_TOKEN_WRITER");
|
|
5276
|
+
var AUTH_CONNECTION_GRANT_SINK = /* @__PURE__ */ Symbol("AUTH_CONNECTION_GRANT_SINK");
|
|
4306
5277
|
var AUTH_USER_CONTEXT = /* @__PURE__ */ Symbol("AUTH_USER_CONTEXT");
|
|
4307
5278
|
var STRATEGY_REGISTRY = /* @__PURE__ */ Symbol("STRATEGY_REGISTRY");
|
|
4308
5279
|
var AUTH_OPTIONS = /* @__PURE__ */ Symbol("AUTH_OPTIONS");
|
|
4309
5280
|
|
|
4310
|
-
// runtime/subsystems/auth/runtime/
|
|
4311
|
-
var
|
|
4312
|
-
constructor(
|
|
5281
|
+
// runtime/subsystems/auth/runtime/connection-broken.error.ts
|
|
5282
|
+
var ConnectionBrokenError = class extends Error {
|
|
5283
|
+
constructor(connectionId, errorCode, errorDescription) {
|
|
4313
5284
|
super(
|
|
4314
|
-
`
|
|
5285
|
+
`Connection ${connectionId} broken: ${errorCode} - ${errorDescription}`
|
|
4315
5286
|
);
|
|
4316
|
-
this.
|
|
5287
|
+
this.connectionId = connectionId;
|
|
4317
5288
|
this.errorCode = errorCode;
|
|
4318
5289
|
this.errorDescription = errorDescription;
|
|
4319
|
-
this.name = "
|
|
5290
|
+
this.name = "ConnectionBrokenError";
|
|
4320
5291
|
}
|
|
4321
|
-
|
|
5292
|
+
connectionId;
|
|
4322
5293
|
errorCode;
|
|
4323
5294
|
errorDescription;
|
|
4324
5295
|
};
|
|
@@ -4326,53 +5297,53 @@ var IntegrationBrokenError = class extends Error {
|
|
|
4326
5297
|
// runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts
|
|
4327
5298
|
var REFRESH_SAFETY_MS = 5 * 60 * 1e3;
|
|
4328
5299
|
var OAuth2RefreshStrategy = class {
|
|
4329
|
-
|
|
5300
|
+
connectionReader;
|
|
4330
5301
|
tokenWriter;
|
|
4331
5302
|
fetchImpl;
|
|
4332
5303
|
now;
|
|
4333
5304
|
constructor(opts) {
|
|
4334
|
-
this.
|
|
5305
|
+
this.connectionReader = opts.connectionReader;
|
|
4335
5306
|
this.tokenWriter = opts.tokenWriter;
|
|
4336
5307
|
this.fetchImpl = opts.fetch ?? fetch;
|
|
4337
5308
|
this.now = opts.now ?? Date.now;
|
|
4338
5309
|
}
|
|
4339
|
-
async resolve(
|
|
4340
|
-
const
|
|
4341
|
-
if (!
|
|
4342
|
-
throw new Error(`
|
|
5310
|
+
async resolve(connectionId, opts = {}) {
|
|
5311
|
+
const connection = await this.connectionReader.findByIdDecrypted(connectionId);
|
|
5312
|
+
if (!connection) {
|
|
5313
|
+
throw new Error(`Connection ${connectionId} not found`);
|
|
4343
5314
|
}
|
|
4344
|
-
if (
|
|
5315
|
+
if (connection.provider !== this.provider) {
|
|
4345
5316
|
throw new Error(
|
|
4346
|
-
`${this.constructor.name} called for non-${this.provider}
|
|
5317
|
+
`${this.constructor.name} called for non-${this.provider} connection ${connectionId} (provider=${connection.provider})`
|
|
4347
5318
|
);
|
|
4348
5319
|
}
|
|
4349
|
-
const needsRefresh = opts.forceRefresh || this.isExpiring(
|
|
5320
|
+
const needsRefresh = opts.forceRefresh || this.isExpiring(connection.expiresAt) || !connection.accessToken;
|
|
4350
5321
|
if (!needsRefresh) {
|
|
4351
|
-
return this.buildCredentials(
|
|
5322
|
+
return this.buildCredentials(connection.accessToken, connection);
|
|
4352
5323
|
}
|
|
4353
|
-
if (!
|
|
4354
|
-
throw new
|
|
4355
|
-
|
|
5324
|
+
if (!connection.refreshToken) {
|
|
5325
|
+
throw new ConnectionBrokenError(
|
|
5326
|
+
connectionId,
|
|
4356
5327
|
"no_refresh_token",
|
|
4357
|
-
"
|
|
5328
|
+
"Connection has no refresh token; user must reconnect"
|
|
4358
5329
|
);
|
|
4359
5330
|
}
|
|
4360
5331
|
const { parsed, raw } = await this.executeRefresh(
|
|
4361
|
-
|
|
4362
|
-
|
|
5332
|
+
connectionId,
|
|
5333
|
+
connection.refreshToken
|
|
4363
5334
|
);
|
|
4364
5335
|
const newExpiresAt = new Date(
|
|
4365
5336
|
this.now() + (parsed.expiresInSec ?? this.defaultExpiresInSec) * 1e3
|
|
4366
5337
|
);
|
|
4367
5338
|
await this.tokenWriter.persistRefresh({
|
|
4368
|
-
|
|
5339
|
+
connectionId,
|
|
4369
5340
|
accessToken: parsed.accessToken,
|
|
4370
5341
|
refreshToken: parsed.refreshToken ?? void 0,
|
|
4371
5342
|
expiresAt: newExpiresAt
|
|
4372
5343
|
});
|
|
4373
|
-
return this.buildCredentials(parsed.accessToken,
|
|
5344
|
+
return this.buildCredentials(parsed.accessToken, connection, raw);
|
|
4374
5345
|
}
|
|
4375
|
-
async executeRefresh(
|
|
5346
|
+
async executeRefresh(connectionId, refreshToken) {
|
|
4376
5347
|
const body = new URLSearchParams({
|
|
4377
5348
|
grant_type: "refresh_token",
|
|
4378
5349
|
refresh_token: refreshToken,
|
|
@@ -4386,8 +5357,8 @@ var OAuth2RefreshStrategy = class {
|
|
|
4386
5357
|
if (!response.ok) {
|
|
4387
5358
|
const err = await safeJson(response);
|
|
4388
5359
|
if (response.status === 400 && (err.error === "invalid_grant" || err.error === "invalid_token")) {
|
|
4389
|
-
throw new
|
|
4390
|
-
|
|
5360
|
+
throw new ConnectionBrokenError(
|
|
5361
|
+
connectionId,
|
|
4391
5362
|
err.error ?? "invalid_grant",
|
|
4392
5363
|
err.error_description ?? err.message ?? "refresh token rejected"
|
|
4393
5364
|
);
|
|
@@ -4430,25 +5401,25 @@ function isSessionExpiredError(err) {
|
|
|
4430
5401
|
}
|
|
4431
5402
|
|
|
4432
5403
|
// runtime/subsystems/auth/runtime/with-auth-retry.ts
|
|
4433
|
-
async function withAuthRetry(authStrategy,
|
|
5404
|
+
async function withAuthRetry(authStrategy, connectionId, op, options = {}) {
|
|
4434
5405
|
const classify = options.isSessionExpired ?? isSessionExpiredError;
|
|
4435
|
-
let creds = await authStrategy.resolve(
|
|
5406
|
+
let creds = await authStrategy.resolve(connectionId);
|
|
4436
5407
|
try {
|
|
4437
5408
|
return await op(creds);
|
|
4438
5409
|
} catch (e) {
|
|
4439
5410
|
if (!classify(e)) throw e;
|
|
4440
|
-
creds = await authStrategy.resolve(
|
|
5411
|
+
creds = await authStrategy.resolve(connectionId, { forceRefresh: true });
|
|
4441
5412
|
return op(creds);
|
|
4442
5413
|
}
|
|
4443
5414
|
}
|
|
4444
5415
|
|
|
4445
5416
|
// runtime/subsystems/auth/auth-oauth-state.schema.ts
|
|
4446
|
-
import { pgTable as
|
|
4447
|
-
var authOAuthState =
|
|
4448
|
-
state:
|
|
4449
|
-
userId:
|
|
4450
|
-
redirect:
|
|
4451
|
-
expiresAt:
|
|
5417
|
+
import { pgTable as pgTable5, text as text5, timestamp as timestamp5 } from "drizzle-orm/pg-core";
|
|
5418
|
+
var authOAuthState = pgTable5("auth_oauth_state", {
|
|
5419
|
+
state: text5("state").primaryKey(),
|
|
5420
|
+
userId: text5("user_id").notNull(),
|
|
5421
|
+
redirect: text5("redirect"),
|
|
5422
|
+
expiresAt: timestamp5("expires_at", { withTimezone: true }).notNull()
|
|
4452
5423
|
});
|
|
4453
5424
|
|
|
4454
5425
|
// runtime/subsystems/auth/backends/encryption-key/env.ts
|
|
@@ -4539,7 +5510,7 @@ var MemoryOAuthStateStore = class {
|
|
|
4539
5510
|
|
|
4540
5511
|
// runtime/subsystems/auth/backends/state-store.drizzle-backend.ts
|
|
4541
5512
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
4542
|
-
import { eq as
|
|
5513
|
+
import { eq as eq9 } from "drizzle-orm";
|
|
4543
5514
|
var DrizzleOAuthStateStore = class {
|
|
4544
5515
|
constructor(db, opts = {}) {
|
|
4545
5516
|
this.db = db;
|
|
@@ -4563,7 +5534,7 @@ var DrizzleOAuthStateStore = class {
|
|
|
4563
5534
|
return state;
|
|
4564
5535
|
}
|
|
4565
5536
|
async consume(state) {
|
|
4566
|
-
const rows = await this.db.delete(authOAuthState).where(
|
|
5537
|
+
const rows = await this.db.delete(authOAuthState).where(eq9(authOAuthState.state, state)).returning();
|
|
4567
5538
|
const row = rows[0];
|
|
4568
5539
|
if (!row) {
|
|
4569
5540
|
throw new OAuthStateError(
|
|
@@ -4585,7 +5556,7 @@ var DrizzleOAuthStateStore = class {
|
|
|
4585
5556
|
import {
|
|
4586
5557
|
Controller,
|
|
4587
5558
|
Get,
|
|
4588
|
-
Inject as
|
|
5559
|
+
Inject as Inject18,
|
|
4589
5560
|
Param,
|
|
4590
5561
|
Query,
|
|
4591
5562
|
Req,
|
|
@@ -4647,7 +5618,7 @@ var AuthController = class {
|
|
|
4647
5618
|
});
|
|
4648
5619
|
return res.redirect(
|
|
4649
5620
|
HttpStatus.FOUND,
|
|
4650
|
-
redirect ?? `/settings/
|
|
5621
|
+
redirect ?? `/settings/connections?connected=${encodeURIComponent(slug)}`
|
|
4651
5622
|
);
|
|
4652
5623
|
}
|
|
4653
5624
|
requireStrategy(slug) {
|
|
@@ -4687,11 +5658,11 @@ __decorateClass([
|
|
|
4687
5658
|
], AuthController.prototype, "callback", 1);
|
|
4688
5659
|
AuthController = __decorateClass([
|
|
4689
5660
|
Controller("auth"),
|
|
4690
|
-
__decorateParam(0,
|
|
4691
|
-
__decorateParam(1,
|
|
4692
|
-
__decorateParam(2,
|
|
4693
|
-
__decorateParam(3,
|
|
4694
|
-
__decorateParam(4,
|
|
5661
|
+
__decorateParam(0, Inject18(STRATEGY_REGISTRY)),
|
|
5662
|
+
__decorateParam(1, Inject18(AUTH_USER_CONTEXT)),
|
|
5663
|
+
__decorateParam(2, Inject18(OAUTH_STATE_STORE)),
|
|
5664
|
+
__decorateParam(3, Inject18(AUTH_CONNECTION_GRANT_SINK)),
|
|
5665
|
+
__decorateParam(4, Inject18(AUTH_OPTIONS))
|
|
4695
5666
|
], AuthController);
|
|
4696
5667
|
|
|
4697
5668
|
// runtime/base-classes/tenant-context.ts
|
|
@@ -4699,7 +5670,7 @@ import { AsyncLocalStorage } from "async_hooks";
|
|
|
4699
5670
|
var als = new AsyncLocalStorage();
|
|
4700
5671
|
|
|
4701
5672
|
// runtime/subsystems/auth/auth.module.ts
|
|
4702
|
-
import { Module as
|
|
5673
|
+
import { Module as Module8 } from "@nestjs/common";
|
|
4703
5674
|
function resolveEncryptionKeyProvider(choice) {
|
|
4704
5675
|
if (choice === "env") {
|
|
4705
5676
|
return { provide: ENCRYPTION_KEY, useClass: EnvEncryptionKey };
|
|
@@ -4759,28 +5730,30 @@ var AuthModule = class {
|
|
|
4759
5730
|
}
|
|
4760
5731
|
};
|
|
4761
5732
|
AuthModule = __decorateClass([
|
|
4762
|
-
|
|
5733
|
+
Module8({})
|
|
4763
5734
|
], AuthModule);
|
|
4764
5735
|
export {
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
5736
|
+
AUTH_CONNECTION_GRANT_SINK,
|
|
5737
|
+
AUTH_CONNECTION_READER,
|
|
5738
|
+
AUTH_CONNECTION_TOKEN_WRITER,
|
|
4768
5739
|
AUTH_OPTIONS,
|
|
4769
5740
|
AUTH_USER_CONTEXT,
|
|
4770
5741
|
AuthController,
|
|
4771
5742
|
AuthModule,
|
|
4772
5743
|
CACHE,
|
|
4773
5744
|
CacheModule,
|
|
5745
|
+
ConnectionBrokenError,
|
|
4774
5746
|
DrizzleCacheService,
|
|
4775
5747
|
DrizzleEventBus,
|
|
4776
5748
|
DrizzleOAuthStateStore,
|
|
4777
5749
|
ENCRYPTION_KEY,
|
|
5750
|
+
ENTITY_CHANGE_SOURCE_REGISTRY,
|
|
4778
5751
|
EVENT_BUS,
|
|
4779
5752
|
EnvEncryptionKey,
|
|
4780
5753
|
EventsModule,
|
|
4781
|
-
IntegrationBrokenError,
|
|
4782
5754
|
LocalStorageBackend,
|
|
4783
5755
|
MemoryCacheService,
|
|
5756
|
+
MemoryEntityChangeSourceRegistry,
|
|
4784
5757
|
MemoryEventBus,
|
|
4785
5758
|
MemoryOAuthStateStore,
|
|
4786
5759
|
MemoryStorageBackend,
|
|
@@ -4795,6 +5768,7 @@ export {
|
|
|
4795
5768
|
STRATEGY_REGISTRY,
|
|
4796
5769
|
SessionExpiredError,
|
|
4797
5770
|
StorageModule,
|
|
5771
|
+
UnknownEntityError,
|
|
4798
5772
|
authOAuthState,
|
|
4799
5773
|
collisionModeEnum,
|
|
4800
5774
|
isSessionExpiredError,
|