@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
package/dist/src/cli/index.js
CHANGED
|
@@ -1081,7 +1081,7 @@ import { parse as parseYaml } from "yaml";
|
|
|
1081
1081
|
// src/schema/entity-definition.schema.ts
|
|
1082
1082
|
import { z as z3 } from "zod";
|
|
1083
1083
|
|
|
1084
|
-
// runtime/subsystems/
|
|
1084
|
+
// runtime/subsystems/integration/integration-field-diff.protocol.ts
|
|
1085
1085
|
import { z } from "zod";
|
|
1086
1086
|
var FieldDiffValueSchema = z.object({
|
|
1087
1087
|
from: z.unknown(),
|
|
@@ -1089,7 +1089,7 @@ var FieldDiffValueSchema = z.object({
|
|
|
1089
1089
|
});
|
|
1090
1090
|
var FieldDiffSchema = z.record(z.string(), FieldDiffValueSchema);
|
|
1091
1091
|
|
|
1092
|
-
// runtime/subsystems/
|
|
1092
|
+
// runtime/subsystems/integration/detection-config.schema.ts
|
|
1093
1093
|
import { z as z2 } from "zod";
|
|
1094
1094
|
var FieldMappingSchema = z2.object({
|
|
1095
1095
|
source: z2.string().min(1),
|
|
@@ -1147,21 +1147,21 @@ var DetectionConfigSchema = z2.discriminatedUnion("mode", [
|
|
|
1147
1147
|
WebhookModeSchema
|
|
1148
1148
|
]);
|
|
1149
1149
|
|
|
1150
|
-
// runtime/subsystems/
|
|
1151
|
-
var
|
|
1152
|
-
var
|
|
1153
|
-
var
|
|
1154
|
-
var
|
|
1155
|
-
var
|
|
1156
|
-
var
|
|
1157
|
-
var
|
|
1150
|
+
// runtime/subsystems/integration/integration.tokens.ts
|
|
1151
|
+
var INTEGRATION_CHANGE_SOURCE = "INTEGRATION_CHANGE_SOURCE";
|
|
1152
|
+
var INTEGRATION_CURSOR_STORE = "INTEGRATION_CURSOR_STORE";
|
|
1153
|
+
var INTEGRATION_FIELD_DIFFER = "INTEGRATION_FIELD_DIFFER";
|
|
1154
|
+
var INTEGRATION_SINK = "INTEGRATION_SINK";
|
|
1155
|
+
var INTEGRATION_RUN_RECORDER = "INTEGRATION_RUN_RECORDER";
|
|
1156
|
+
var INTEGRATION_MODULE_OPTIONS = "INTEGRATION_MODULE_OPTIONS";
|
|
1157
|
+
var INTEGRATION_MULTI_TENANT = "INTEGRATION_MULTI_TENANT";
|
|
1158
1158
|
|
|
1159
|
-
// runtime/subsystems/
|
|
1159
|
+
// runtime/subsystems/integration/integration-errors.ts
|
|
1160
1160
|
var MissingTenantIdError = class extends Error {
|
|
1161
1161
|
name = "MissingTenantIdError";
|
|
1162
1162
|
constructor(operation) {
|
|
1163
1163
|
super(
|
|
1164
|
-
`Missing tenantId for
|
|
1164
|
+
`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.`
|
|
1165
1165
|
);
|
|
1166
1166
|
}
|
|
1167
1167
|
};
|
|
@@ -1172,7 +1172,7 @@ function assertTenantId(tenantId, options) {
|
|
|
1172
1172
|
}
|
|
1173
1173
|
}
|
|
1174
1174
|
|
|
1175
|
-
// runtime/subsystems/
|
|
1175
|
+
// runtime/subsystems/integration/integration-audit.schema.ts
|
|
1176
1176
|
import {
|
|
1177
1177
|
pgEnum,
|
|
1178
1178
|
pgTable,
|
|
@@ -1185,39 +1185,39 @@ import {
|
|
|
1185
1185
|
index,
|
|
1186
1186
|
uniqueIndex
|
|
1187
1187
|
} from "drizzle-orm/pg-core";
|
|
1188
|
-
var
|
|
1188
|
+
var integrationRunDirectionEnum = pgEnum("integration_run_direction", [
|
|
1189
1189
|
"inbound",
|
|
1190
1190
|
"outbound"
|
|
1191
1191
|
]);
|
|
1192
|
-
var
|
|
1192
|
+
var integrationRunActionEnum = pgEnum("integration_run_action", [
|
|
1193
1193
|
"poll",
|
|
1194
1194
|
"cdc",
|
|
1195
1195
|
"webhook",
|
|
1196
1196
|
"manual",
|
|
1197
1197
|
"writeback"
|
|
1198
1198
|
]);
|
|
1199
|
-
var
|
|
1199
|
+
var integrationRunStatusEnum = pgEnum("integration_run_status", [
|
|
1200
1200
|
"running",
|
|
1201
1201
|
"success",
|
|
1202
1202
|
"no_changes",
|
|
1203
1203
|
"failed"
|
|
1204
1204
|
]);
|
|
1205
|
-
var
|
|
1205
|
+
var integrationRunItemOperationEnum = pgEnum("integration_run_item_operation", [
|
|
1206
1206
|
"created",
|
|
1207
1207
|
"updated",
|
|
1208
1208
|
"deleted",
|
|
1209
1209
|
"noop"
|
|
1210
1210
|
]);
|
|
1211
|
-
var
|
|
1211
|
+
var integrationRunItemStatusEnum = pgEnum("integration_run_item_status", [
|
|
1212
1212
|
"success",
|
|
1213
1213
|
"failed",
|
|
1214
1214
|
"skipped"
|
|
1215
1215
|
]);
|
|
1216
|
-
var
|
|
1217
|
-
"
|
|
1216
|
+
var integrationSubscriptions = pgTable(
|
|
1217
|
+
"integration_subscriptions",
|
|
1218
1218
|
{
|
|
1219
1219
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
1220
|
-
|
|
1220
|
+
connectionId: text("connection_id").notNull(),
|
|
1221
1221
|
adapter: text("adapter").notNull(),
|
|
1222
1222
|
domain: text("domain").notNull(),
|
|
1223
1223
|
externalRef: text("external_ref"),
|
|
@@ -1232,8 +1232,8 @@ var syncSubscriptions = pgTable(
|
|
|
1232
1232
|
* successful run advances it.
|
|
1233
1233
|
*/
|
|
1234
1234
|
cursor: jsonb("cursor").$type(),
|
|
1235
|
-
|
|
1236
|
-
/** Runtime-enforced when `
|
|
1235
|
+
lastIntegrationAt: timestamp("last_integration_at", { withTimezone: true }),
|
|
1236
|
+
/** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
|
|
1237
1237
|
tenantId: text("tenant_id"),
|
|
1238
1238
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1239
1239
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
@@ -1242,31 +1242,31 @@ var syncSubscriptions = pgTable(
|
|
|
1242
1242
|
/**
|
|
1243
1243
|
* Composite uniqueness per the epic shape. `external_ref` is nullable;
|
|
1244
1244
|
* Postgres treats NULLs as distinct in a UNIQUE constraint, which means
|
|
1245
|
-
* two rows with the same `(
|
|
1245
|
+
* two rows with the same `(connection_id, adapter, domain)` and NULL
|
|
1246
1246
|
* external_ref are allowed. That's intentional — a subscription with
|
|
1247
1247
|
* NULL external_ref covers the full domain, and duplicates there would
|
|
1248
1248
|
* be a consumer-layer modeling issue, not a schema concern.
|
|
1249
1249
|
*/
|
|
1250
|
-
|
|
1251
|
-
t.
|
|
1250
|
+
uqIntegrationSubscriptionTuple: uniqueIndex("uq_integration_subscriptions_tuple").on(
|
|
1251
|
+
t.connectionId,
|
|
1252
1252
|
t.adapter,
|
|
1253
1253
|
t.domain,
|
|
1254
1254
|
t.externalRef
|
|
1255
1255
|
),
|
|
1256
1256
|
/** Scheduling query: list enabled subscriptions ordered by staleness. */
|
|
1257
|
-
|
|
1258
|
-
"
|
|
1259
|
-
).on(t.enabled, t.
|
|
1257
|
+
idxIntegrationSubscriptionsEnabledLastIntegration: index(
|
|
1258
|
+
"idx_integration_subscriptions_enabled_last_integration"
|
|
1259
|
+
).on(t.enabled, t.lastIntegrationAt)
|
|
1260
1260
|
})
|
|
1261
1261
|
);
|
|
1262
|
-
var
|
|
1263
|
-
"
|
|
1262
|
+
var integrationRuns = pgTable(
|
|
1263
|
+
"integration_runs",
|
|
1264
1264
|
{
|
|
1265
1265
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
1266
|
-
subscriptionId: uuid("subscription_id").notNull().references(() =>
|
|
1267
|
-
direction:
|
|
1268
|
-
action:
|
|
1269
|
-
status:
|
|
1266
|
+
subscriptionId: uuid("subscription_id").notNull().references(() => integrationSubscriptions.id, { onDelete: "cascade" }),
|
|
1267
|
+
direction: integrationRunDirectionEnum("direction").notNull(),
|
|
1268
|
+
action: integrationRunActionEnum("action").notNull(),
|
|
1269
|
+
status: integrationRunStatusEnum("status").notNull().default("running"),
|
|
1270
1270
|
recordsFound: integer("records_found").notNull().default(0),
|
|
1271
1271
|
recordsProcessed: integer("records_processed").notNull().default(0),
|
|
1272
1272
|
cursorBefore: jsonb("cursor_before").$type(),
|
|
@@ -1275,31 +1275,31 @@ var syncRuns = pgTable(
|
|
|
1275
1275
|
error: text("error"),
|
|
1276
1276
|
startedAt: timestamp("started_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1277
1277
|
completedAt: timestamp("completed_at", { withTimezone: true }),
|
|
1278
|
-
/** Runtime-enforced when `
|
|
1278
|
+
/** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
|
|
1279
1279
|
tenantId: text("tenant_id")
|
|
1280
1280
|
},
|
|
1281
1281
|
(t) => ({
|
|
1282
1282
|
/** Timeline read: "most recent runs for this subscription". */
|
|
1283
|
-
|
|
1284
|
-
"
|
|
1283
|
+
idxIntegrationRunsSubscriptionStartedAt: index(
|
|
1284
|
+
"idx_integration_runs_subscription_started_at"
|
|
1285
1285
|
).on(t.subscriptionId, t.startedAt),
|
|
1286
1286
|
/** Stale-run sweeper: "runs that started > N minutes ago and are still running". */
|
|
1287
|
-
|
|
1287
|
+
idxIntegrationRunsStatusStartedAt: index("idx_integration_runs_status_started_at").on(
|
|
1288
1288
|
t.status,
|
|
1289
1289
|
t.startedAt
|
|
1290
1290
|
)
|
|
1291
1291
|
})
|
|
1292
1292
|
);
|
|
1293
|
-
var
|
|
1294
|
-
"
|
|
1293
|
+
var integrationRunItems = pgTable(
|
|
1294
|
+
"integration_run_items",
|
|
1295
1295
|
{
|
|
1296
1296
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
1297
|
-
|
|
1297
|
+
integrationRunId: uuid("integration_run_id").notNull().references(() => integrationRuns.id, { onDelete: "cascade" }),
|
|
1298
1298
|
entityType: text("entity_type").notNull(),
|
|
1299
1299
|
externalId: text("external_id").notNull(),
|
|
1300
1300
|
localId: text("local_id"),
|
|
1301
|
-
operation:
|
|
1302
|
-
status:
|
|
1301
|
+
operation: integrationRunItemOperationEnum("operation").notNull(),
|
|
1302
|
+
status: integrationRunItemStatusEnum("status").notNull(),
|
|
1303
1303
|
/**
|
|
1304
1304
|
* Structured per-field diff — ADR-0003 shape enforced by
|
|
1305
1305
|
* `FieldDiffSchema.parse` at the recorder service layer.
|
|
@@ -1313,23 +1313,23 @@ var syncRunItems = pgTable(
|
|
|
1313
1313
|
title: text("title"),
|
|
1314
1314
|
error: text("error"),
|
|
1315
1315
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1316
|
-
/** Runtime-enforced when `
|
|
1316
|
+
/** Runtime-enforced when `INTEGRATION_MULTI_TENANT` is true; see SYNC-6. */
|
|
1317
1317
|
tenantId: text("tenant_id")
|
|
1318
1318
|
},
|
|
1319
1319
|
(t) => ({
|
|
1320
1320
|
/** Ordered timeline within a run. */
|
|
1321
|
-
|
|
1322
|
-
t.
|
|
1321
|
+
idxIntegrationRunItemsRunCreatedAt: index("idx_integration_run_items_run_created_at").on(
|
|
1322
|
+
t.integrationRunId,
|
|
1323
1323
|
t.createdAt
|
|
1324
1324
|
),
|
|
1325
|
-
/** Per-record history: "every
|
|
1326
|
-
|
|
1327
|
-
"
|
|
1325
|
+
/** Per-record history: "every integration that touched opportunity/$extId". */
|
|
1326
|
+
idxIntegrationRunItemsEntityExternal: index(
|
|
1327
|
+
"idx_integration_run_items_entity_external"
|
|
1328
1328
|
).on(t.entityType, t.externalId)
|
|
1329
1329
|
})
|
|
1330
1330
|
);
|
|
1331
1331
|
|
|
1332
|
-
// runtime/subsystems/
|
|
1332
|
+
// runtime/subsystems/integration/integration-cursor-store.memory-backend.ts
|
|
1333
1333
|
import { Injectable } from "@nestjs/common";
|
|
1334
1334
|
var MemoryCursorStore = class {
|
|
1335
1335
|
/**
|
|
@@ -1340,7 +1340,7 @@ var MemoryCursorStore = class {
|
|
|
1340
1340
|
/**
|
|
1341
1341
|
* Seedable subscription metadata for `listAll` — the memory backend
|
|
1342
1342
|
* stores only `subscriptionId → cursor` in its write path, so the
|
|
1343
|
-
* snapshot shape (`
|
|
1343
|
+
* snapshot shape (`connectionId`, `adapter`, `domain`, `externalRef`,
|
|
1344
1344
|
* timestamps) has no natural source without test seeding. Tests populate
|
|
1345
1345
|
* this map; unseeded entries get empty-string metadata and `new Date(0)`
|
|
1346
1346
|
* timestamps so the shape stays stable. Production paths go through the
|
|
@@ -1360,12 +1360,12 @@ var MemoryCursorStore = class {
|
|
|
1360
1360
|
const meta = this.subscriptions.get(subscriptionId);
|
|
1361
1361
|
snapshots.push({
|
|
1362
1362
|
subscriptionId,
|
|
1363
|
-
|
|
1363
|
+
connectionId: meta?.connectionId ?? "",
|
|
1364
1364
|
adapter: meta?.adapter ?? "",
|
|
1365
1365
|
domain: meta?.domain ?? "",
|
|
1366
1366
|
externalRef: meta?.externalRef ?? null,
|
|
1367
1367
|
cursor: cursor ?? null,
|
|
1368
|
-
|
|
1368
|
+
lastIntegrationAt: meta?.lastIntegrationAt ?? null,
|
|
1369
1369
|
updatedAt: meta?.updatedAt ?? /* @__PURE__ */ new Date(0),
|
|
1370
1370
|
tenantId: null
|
|
1371
1371
|
});
|
|
@@ -1384,7 +1384,7 @@ MemoryCursorStore = __decorateClass([
|
|
|
1384
1384
|
Injectable()
|
|
1385
1385
|
], MemoryCursorStore);
|
|
1386
1386
|
|
|
1387
|
-
// runtime/subsystems/
|
|
1387
|
+
// runtime/subsystems/integration/integration-run-recorder.memory-backend.ts
|
|
1388
1388
|
import { Injectable as Injectable2 } from "@nestjs/common";
|
|
1389
1389
|
var MemoryRunRecorder = class {
|
|
1390
1390
|
/**
|
|
@@ -1393,14 +1393,14 @@ var MemoryRunRecorder = class {
|
|
|
1393
1393
|
*/
|
|
1394
1394
|
runs = /* @__PURE__ */ new Map();
|
|
1395
1395
|
/**
|
|
1396
|
-
* Items keyed by `
|
|
1397
|
-
* mirrors the timeline the `(
|
|
1396
|
+
* Items keyed by `integration_run_id`, array order matches insertion order —
|
|
1397
|
+
* mirrors the timeline the `(integration_run_id, created_at)` index produces
|
|
1398
1398
|
* in Postgres.
|
|
1399
1399
|
*/
|
|
1400
1400
|
items = /* @__PURE__ */ new Map();
|
|
1401
1401
|
/**
|
|
1402
1402
|
* Seedable subscription metadata — tests populate this to make
|
|
1403
|
-
* `listRecent` return meaningful `
|
|
1403
|
+
* `listRecent` return meaningful `connectionId` values. The memory
|
|
1404
1404
|
* backend doesn't track subscriptions on its own (only runs + items), so
|
|
1405
1405
|
* this map is the intentional extension point: tests write entries for
|
|
1406
1406
|
* the subscription ids they use, production code never touches it.
|
|
@@ -1429,10 +1429,10 @@ var MemoryRunRecorder = class {
|
|
|
1429
1429
|
}
|
|
1430
1430
|
async recordItem(input) {
|
|
1431
1431
|
FieldDiffSchema.parse(input.changedFields);
|
|
1432
|
-
const bucket = this.items.get(input.
|
|
1432
|
+
const bucket = this.items.get(input.integrationRunId);
|
|
1433
1433
|
if (!bucket) {
|
|
1434
1434
|
throw new Error(
|
|
1435
|
-
`MemoryRunRecorder.recordItem: no run started for id '${input.
|
|
1435
|
+
`MemoryRunRecorder.recordItem: no run started for id '${input.integrationRunId}'. Call startRun(...) first.`
|
|
1436
1436
|
);
|
|
1437
1437
|
}
|
|
1438
1438
|
bucket.push(input);
|
|
@@ -1458,10 +1458,10 @@ var MemoryRunRecorder = class {
|
|
|
1458
1458
|
return filtered.sort((a, b) => b.startedAt.getTime() - a.startedAt.getTime()).slice(0, limit).map((r) => ({
|
|
1459
1459
|
id: r.id,
|
|
1460
1460
|
subscriptionId: r.subscriptionId,
|
|
1461
|
-
//
|
|
1461
|
+
// connectionId is only knowable if the test seeded subscriptions
|
|
1462
1462
|
// metadata; empty string otherwise. The Drizzle backend resolves
|
|
1463
1463
|
// it via JOIN, which is the production path.
|
|
1464
|
-
|
|
1464
|
+
connectionId: this.subscriptions.get(r.subscriptionId)?.connectionId ?? "",
|
|
1465
1465
|
status: r.status,
|
|
1466
1466
|
startedAt: r.startedAt,
|
|
1467
1467
|
completedAt: r.completedAt,
|
|
@@ -1489,7 +1489,7 @@ MemoryRunRecorder = __decorateClass([
|
|
|
1489
1489
|
Injectable2()
|
|
1490
1490
|
], MemoryRunRecorder);
|
|
1491
1491
|
|
|
1492
|
-
// runtime/subsystems/
|
|
1492
|
+
// runtime/subsystems/integration/deep-equal.differ.ts
|
|
1493
1493
|
import { Injectable as Injectable3 } from "@nestjs/common";
|
|
1494
1494
|
var DEFAULT_IGNORE_FIELDS = /* @__PURE__ */ new Set([
|
|
1495
1495
|
"id",
|
|
@@ -1588,9 +1588,9 @@ function deepEqualObject(a, b) {
|
|
|
1588
1588
|
return true;
|
|
1589
1589
|
}
|
|
1590
1590
|
|
|
1591
|
-
// runtime/subsystems/
|
|
1591
|
+
// runtime/subsystems/integration/execute-integration.use-case.ts
|
|
1592
1592
|
import { Inject, Injectable as Injectable4, Logger, Optional } from "@nestjs/common";
|
|
1593
|
-
var
|
|
1593
|
+
var ExecuteIntegrationUseCase = class {
|
|
1594
1594
|
constructor(source, cursors, differ, sink, recorder, multiTenant = false) {
|
|
1595
1595
|
this.source = source;
|
|
1596
1596
|
this.cursors = cursors;
|
|
@@ -1605,7 +1605,7 @@ var ExecuteSyncUseCase = class {
|
|
|
1605
1605
|
sink;
|
|
1606
1606
|
recorder;
|
|
1607
1607
|
multiTenant;
|
|
1608
|
-
logger = new Logger(
|
|
1608
|
+
logger = new Logger(ExecuteIntegrationUseCase.name);
|
|
1609
1609
|
async execute(input) {
|
|
1610
1610
|
assertTenantId(input.tenantId, {
|
|
1611
1611
|
multiTenant: this.multiTenant,
|
|
@@ -1640,10 +1640,10 @@ var ExecuteSyncUseCase = class {
|
|
|
1640
1640
|
recordsFailed++;
|
|
1641
1641
|
const message = err instanceof Error ? err.message : String(err);
|
|
1642
1642
|
this.logger.warn(
|
|
1643
|
-
`
|
|
1643
|
+
`integration item failed: subscription=${input.subscription.id} externalId=${change.externalId}: ${message}`
|
|
1644
1644
|
);
|
|
1645
1645
|
await this.recorder.recordItem({
|
|
1646
|
-
|
|
1646
|
+
integrationRunId: runId,
|
|
1647
1647
|
entityType: input.subscription.domain,
|
|
1648
1648
|
externalId: change.externalId,
|
|
1649
1649
|
operation: change.operation === "deleted" ? "deleted" : "updated",
|
|
@@ -1666,7 +1666,7 @@ var ExecuteSyncUseCase = class {
|
|
|
1666
1666
|
status = "failed";
|
|
1667
1667
|
runError = err instanceof Error ? err.message : String(err);
|
|
1668
1668
|
this.logger.error(
|
|
1669
|
-
`
|
|
1669
|
+
`integration source failed: subscription=${input.subscription.id}: ${runError}`
|
|
1670
1670
|
);
|
|
1671
1671
|
}
|
|
1672
1672
|
if (cursorAdvanced && latestCursor !== null && latestCursor !== void 0) {
|
|
@@ -1711,7 +1711,7 @@ var ExecuteSyncUseCase = class {
|
|
|
1711
1711
|
change.externalId
|
|
1712
1712
|
);
|
|
1713
1713
|
await this.recorder.recordItem({
|
|
1714
|
-
|
|
1714
|
+
integrationRunId: runId,
|
|
1715
1715
|
entityType: input.subscription.domain,
|
|
1716
1716
|
externalId: change.externalId,
|
|
1717
1717
|
localId: result?.id ?? null,
|
|
@@ -1734,7 +1734,7 @@ var ExecuteSyncUseCase = class {
|
|
|
1734
1734
|
if (diff === "noop") {
|
|
1735
1735
|
if (!this.sink.reprojectsOnNoop) {
|
|
1736
1736
|
await this.recorder.recordItem({
|
|
1737
|
-
|
|
1737
|
+
integrationRunId: runId,
|
|
1738
1738
|
entityType: input.subscription.domain,
|
|
1739
1739
|
externalId: change.externalId,
|
|
1740
1740
|
localId: null,
|
|
@@ -1751,7 +1751,7 @@ var ExecuteSyncUseCase = class {
|
|
|
1751
1751
|
input.provider
|
|
1752
1752
|
);
|
|
1753
1753
|
await this.recorder.recordItem({
|
|
1754
|
-
|
|
1754
|
+
integrationRunId: runId,
|
|
1755
1755
|
entityType: input.subscription.domain,
|
|
1756
1756
|
externalId: change.externalId,
|
|
1757
1757
|
localId: noopLocalId,
|
|
@@ -1768,7 +1768,7 @@ var ExecuteSyncUseCase = class {
|
|
|
1768
1768
|
input.provider
|
|
1769
1769
|
);
|
|
1770
1770
|
await this.recorder.recordItem({
|
|
1771
|
-
|
|
1771
|
+
integrationRunId: runId,
|
|
1772
1772
|
entityType: input.subscription.domain,
|
|
1773
1773
|
externalId: change.externalId,
|
|
1774
1774
|
localId,
|
|
@@ -1779,25 +1779,25 @@ var ExecuteSyncUseCase = class {
|
|
|
1779
1779
|
});
|
|
1780
1780
|
}
|
|
1781
1781
|
};
|
|
1782
|
-
|
|
1782
|
+
ExecuteIntegrationUseCase = __decorateClass([
|
|
1783
1783
|
Injectable4(),
|
|
1784
|
-
__decorateParam(0, Inject(
|
|
1785
|
-
__decorateParam(1, Inject(
|
|
1786
|
-
__decorateParam(2, Inject(
|
|
1787
|
-
__decorateParam(3, Inject(
|
|
1788
|
-
__decorateParam(4, Inject(
|
|
1784
|
+
__decorateParam(0, Inject(INTEGRATION_CHANGE_SOURCE)),
|
|
1785
|
+
__decorateParam(1, Inject(INTEGRATION_CURSOR_STORE)),
|
|
1786
|
+
__decorateParam(2, Inject(INTEGRATION_FIELD_DIFFER)),
|
|
1787
|
+
__decorateParam(3, Inject(INTEGRATION_SINK)),
|
|
1788
|
+
__decorateParam(4, Inject(INTEGRATION_RUN_RECORDER)),
|
|
1789
1789
|
__decorateParam(5, Optional()),
|
|
1790
|
-
__decorateParam(5, Inject(
|
|
1791
|
-
],
|
|
1790
|
+
__decorateParam(5, Inject(INTEGRATION_MULTI_TENANT))
|
|
1791
|
+
], ExecuteIntegrationUseCase);
|
|
1792
1792
|
|
|
1793
|
-
// runtime/subsystems/
|
|
1793
|
+
// runtime/subsystems/integration/integration-cursor-store.drizzle-backend.ts
|
|
1794
1794
|
import { Inject as Inject2, Injectable as Injectable5, Optional as Optional2 } from "@nestjs/common";
|
|
1795
1795
|
import { and, desc, eq } from "drizzle-orm";
|
|
1796
1796
|
|
|
1797
1797
|
// runtime/constants/tokens.ts
|
|
1798
1798
|
var DRIZZLE = "DRIZZLE";
|
|
1799
1799
|
|
|
1800
|
-
// runtime/subsystems/
|
|
1800
|
+
// runtime/subsystems/integration/integration-cursor-store.drizzle-backend.ts
|
|
1801
1801
|
var PostgresCursorStore = class {
|
|
1802
1802
|
constructor(db, multiTenant) {
|
|
1803
1803
|
this.db = db;
|
|
@@ -1807,15 +1807,15 @@ var PostgresCursorStore = class {
|
|
|
1807
1807
|
multiTenant;
|
|
1808
1808
|
async get(subscriptionId, tenantId) {
|
|
1809
1809
|
const where = this.buildWhere(subscriptionId, tenantId, "cursor.get");
|
|
1810
|
-
const rows = await this.db.select({ cursor:
|
|
1810
|
+
const rows = await this.db.select({ cursor: integrationSubscriptions.cursor }).from(integrationSubscriptions).where(where).limit(1);
|
|
1811
1811
|
if (rows.length === 0) return null;
|
|
1812
1812
|
return rows[0]?.cursor ?? null;
|
|
1813
1813
|
}
|
|
1814
1814
|
async put(subscriptionId, cursor, tenantId) {
|
|
1815
1815
|
const where = this.buildWhere(subscriptionId, tenantId, "cursor.put");
|
|
1816
|
-
await this.db.update(
|
|
1816
|
+
await this.db.update(integrationSubscriptions).set({
|
|
1817
1817
|
cursor,
|
|
1818
|
-
|
|
1818
|
+
lastIntegrationAt: /* @__PURE__ */ new Date(),
|
|
1819
1819
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1820
1820
|
}).where(where);
|
|
1821
1821
|
}
|
|
@@ -1824,26 +1824,26 @@ var PostgresCursorStore = class {
|
|
|
1824
1824
|
multiTenant: this.multiTenant,
|
|
1825
1825
|
operation: "cursor.listAll"
|
|
1826
1826
|
});
|
|
1827
|
-
const where = this.multiTenant ? eq(
|
|
1827
|
+
const where = this.multiTenant ? eq(integrationSubscriptions.tenantId, tenantId) : void 0;
|
|
1828
1828
|
const rows = await this.db.select({
|
|
1829
|
-
id:
|
|
1830
|
-
|
|
1831
|
-
adapter:
|
|
1832
|
-
domain:
|
|
1833
|
-
externalRef:
|
|
1834
|
-
cursor:
|
|
1835
|
-
|
|
1836
|
-
updatedAt:
|
|
1837
|
-
tenantId:
|
|
1838
|
-
}).from(
|
|
1829
|
+
id: integrationSubscriptions.id,
|
|
1830
|
+
connectionId: integrationSubscriptions.connectionId,
|
|
1831
|
+
adapter: integrationSubscriptions.adapter,
|
|
1832
|
+
domain: integrationSubscriptions.domain,
|
|
1833
|
+
externalRef: integrationSubscriptions.externalRef,
|
|
1834
|
+
cursor: integrationSubscriptions.cursor,
|
|
1835
|
+
lastIntegrationAt: integrationSubscriptions.lastIntegrationAt,
|
|
1836
|
+
updatedAt: integrationSubscriptions.updatedAt,
|
|
1837
|
+
tenantId: integrationSubscriptions.tenantId
|
|
1838
|
+
}).from(integrationSubscriptions).where(where).orderBy(desc(integrationSubscriptions.updatedAt));
|
|
1839
1839
|
return rows.map((row) => ({
|
|
1840
1840
|
subscriptionId: row.id,
|
|
1841
|
-
|
|
1841
|
+
connectionId: row.connectionId,
|
|
1842
1842
|
adapter: row.adapter,
|
|
1843
1843
|
domain: row.domain,
|
|
1844
1844
|
externalRef: row.externalRef,
|
|
1845
1845
|
cursor: row.cursor ?? null,
|
|
1846
|
-
|
|
1846
|
+
lastIntegrationAt: row.lastIntegrationAt,
|
|
1847
1847
|
updatedAt: row.updatedAt,
|
|
1848
1848
|
tenantId: row.tenantId
|
|
1849
1849
|
}));
|
|
@@ -1860,24 +1860,24 @@ var PostgresCursorStore = class {
|
|
|
1860
1860
|
});
|
|
1861
1861
|
if (this.multiTenant) {
|
|
1862
1862
|
return and(
|
|
1863
|
-
eq(
|
|
1864
|
-
eq(
|
|
1863
|
+
eq(integrationSubscriptions.id, subscriptionId),
|
|
1864
|
+
eq(integrationSubscriptions.tenantId, tenantId)
|
|
1865
1865
|
);
|
|
1866
1866
|
}
|
|
1867
|
-
return eq(
|
|
1867
|
+
return eq(integrationSubscriptions.id, subscriptionId);
|
|
1868
1868
|
}
|
|
1869
1869
|
};
|
|
1870
1870
|
PostgresCursorStore = __decorateClass([
|
|
1871
1871
|
Injectable5(),
|
|
1872
1872
|
__decorateParam(0, Inject2(DRIZZLE)),
|
|
1873
1873
|
__decorateParam(1, Optional2()),
|
|
1874
|
-
__decorateParam(1, Inject2(
|
|
1874
|
+
__decorateParam(1, Inject2(INTEGRATION_MULTI_TENANT))
|
|
1875
1875
|
], PostgresCursorStore);
|
|
1876
1876
|
|
|
1877
|
-
// runtime/subsystems/
|
|
1877
|
+
// runtime/subsystems/integration/integration-run-recorder.drizzle-backend.ts
|
|
1878
1878
|
import { Inject as Inject3, Injectable as Injectable6, Optional as Optional3 } from "@nestjs/common";
|
|
1879
1879
|
import { and as and2, desc as desc2, eq as eq2 } from "drizzle-orm";
|
|
1880
|
-
var
|
|
1880
|
+
var DrizzleIntegrationRunRecorder = class {
|
|
1881
1881
|
constructor(db, multiTenant) {
|
|
1882
1882
|
this.db = db;
|
|
1883
1883
|
this.multiTenant = multiTenant ?? false;
|
|
@@ -1889,17 +1889,17 @@ var DrizzleSyncRunRecorder = class {
|
|
|
1889
1889
|
multiTenant: this.multiTenant,
|
|
1890
1890
|
operation: "startRun"
|
|
1891
1891
|
});
|
|
1892
|
-
const rows = await this.db.insert(
|
|
1892
|
+
const rows = await this.db.insert(integrationRuns).values({
|
|
1893
1893
|
subscriptionId: input.subscriptionId,
|
|
1894
1894
|
direction: input.direction,
|
|
1895
1895
|
action: input.action,
|
|
1896
1896
|
status: "running",
|
|
1897
1897
|
cursorBefore: input.cursorBefore ?? null,
|
|
1898
1898
|
tenantId: input.tenantId ?? null
|
|
1899
|
-
}).returning({ id:
|
|
1899
|
+
}).returning({ id: integrationRuns.id });
|
|
1900
1900
|
const id = rows[0]?.id;
|
|
1901
1901
|
if (!id) {
|
|
1902
|
-
throw new Error("
|
|
1902
|
+
throw new Error("DrizzleIntegrationRunRecorder: INSERT RETURNING produced no id");
|
|
1903
1903
|
}
|
|
1904
1904
|
return { id };
|
|
1905
1905
|
}
|
|
@@ -1909,8 +1909,8 @@ var DrizzleSyncRunRecorder = class {
|
|
|
1909
1909
|
operation: "recordItem"
|
|
1910
1910
|
});
|
|
1911
1911
|
FieldDiffSchema.parse(input.changedFields);
|
|
1912
|
-
await this.db.insert(
|
|
1913
|
-
|
|
1912
|
+
await this.db.insert(integrationRunItems).values({
|
|
1913
|
+
integrationRunId: input.integrationRunId,
|
|
1914
1914
|
entityType: input.entityType,
|
|
1915
1915
|
externalId: input.externalId,
|
|
1916
1916
|
localId: input.localId ?? null,
|
|
@@ -1929,29 +1929,29 @@ var DrizzleSyncRunRecorder = class {
|
|
|
1929
1929
|
});
|
|
1930
1930
|
const conditions = [];
|
|
1931
1931
|
if (subscriptionId !== void 0) {
|
|
1932
|
-
conditions.push(eq2(
|
|
1932
|
+
conditions.push(eq2(integrationRuns.subscriptionId, subscriptionId));
|
|
1933
1933
|
}
|
|
1934
1934
|
if (this.multiTenant) {
|
|
1935
|
-
conditions.push(eq2(
|
|
1935
|
+
conditions.push(eq2(integrationRuns.tenantId, tenantId));
|
|
1936
1936
|
}
|
|
1937
1937
|
const where = conditions.length === 0 ? void 0 : conditions.length === 1 ? conditions[0] : and2(...conditions);
|
|
1938
1938
|
const rows = await this.db.select({
|
|
1939
|
-
id:
|
|
1940
|
-
subscriptionId:
|
|
1941
|
-
|
|
1942
|
-
status:
|
|
1943
|
-
startedAt:
|
|
1944
|
-
completedAt:
|
|
1945
|
-
recordsProcessed:
|
|
1946
|
-
tenantId:
|
|
1947
|
-
}).from(
|
|
1948
|
-
|
|
1949
|
-
eq2(
|
|
1950
|
-
).where(where).orderBy(desc2(
|
|
1939
|
+
id: integrationRuns.id,
|
|
1940
|
+
subscriptionId: integrationRuns.subscriptionId,
|
|
1941
|
+
connectionId: integrationSubscriptions.connectionId,
|
|
1942
|
+
status: integrationRuns.status,
|
|
1943
|
+
startedAt: integrationRuns.startedAt,
|
|
1944
|
+
completedAt: integrationRuns.completedAt,
|
|
1945
|
+
recordsProcessed: integrationRuns.recordsProcessed,
|
|
1946
|
+
tenantId: integrationRuns.tenantId
|
|
1947
|
+
}).from(integrationRuns).innerJoin(
|
|
1948
|
+
integrationSubscriptions,
|
|
1949
|
+
eq2(integrationRuns.subscriptionId, integrationSubscriptions.id)
|
|
1950
|
+
).where(where).orderBy(desc2(integrationRuns.startedAt)).limit(limit);
|
|
1951
1951
|
return rows.map((row) => ({
|
|
1952
1952
|
id: row.id,
|
|
1953
1953
|
subscriptionId: row.subscriptionId,
|
|
1954
|
-
|
|
1954
|
+
connectionId: row.connectionId,
|
|
1955
1955
|
status: row.status,
|
|
1956
1956
|
startedAt: row.startedAt,
|
|
1957
1957
|
completedAt: row.completedAt,
|
|
@@ -1960,7 +1960,7 @@ var DrizzleSyncRunRecorder = class {
|
|
|
1960
1960
|
}));
|
|
1961
1961
|
}
|
|
1962
1962
|
async completeRun(runId, input) {
|
|
1963
|
-
await this.db.update(
|
|
1963
|
+
await this.db.update(integrationRuns).set({
|
|
1964
1964
|
status: input.status,
|
|
1965
1965
|
recordsFound: input.recordsFound,
|
|
1966
1966
|
recordsProcessed: input.recordsProcessed,
|
|
@@ -1968,27 +1968,27 @@ var DrizzleSyncRunRecorder = class {
|
|
|
1968
1968
|
durationMs: input.durationMs,
|
|
1969
1969
|
error: input.error ?? null,
|
|
1970
1970
|
completedAt: /* @__PURE__ */ new Date()
|
|
1971
|
-
}).where(eq2(
|
|
1971
|
+
}).where(eq2(integrationRuns.id, runId));
|
|
1972
1972
|
}
|
|
1973
1973
|
};
|
|
1974
|
-
|
|
1974
|
+
DrizzleIntegrationRunRecorder = __decorateClass([
|
|
1975
1975
|
Injectable6(),
|
|
1976
1976
|
__decorateParam(0, Inject3(DRIZZLE)),
|
|
1977
1977
|
__decorateParam(1, Optional3()),
|
|
1978
|
-
__decorateParam(1, Inject3(
|
|
1979
|
-
],
|
|
1978
|
+
__decorateParam(1, Inject3(INTEGRATION_MULTI_TENANT))
|
|
1979
|
+
], DrizzleIntegrationRunRecorder);
|
|
1980
1980
|
|
|
1981
|
-
// runtime/subsystems/
|
|
1981
|
+
// runtime/subsystems/integration/integration.module.ts
|
|
1982
1982
|
import { Module } from "@nestjs/common";
|
|
1983
|
-
var
|
|
1983
|
+
var IntegrationModule = class {
|
|
1984
1984
|
static forRoot(options) {
|
|
1985
1985
|
const multiTenant = options.multiTenant ?? false;
|
|
1986
1986
|
const sharedProviders = [
|
|
1987
|
-
{ provide:
|
|
1988
|
-
{ provide:
|
|
1987
|
+
{ provide: INTEGRATION_MODULE_OPTIONS, useValue: options },
|
|
1988
|
+
{ provide: INTEGRATION_MULTI_TENANT, useValue: multiTenant },
|
|
1989
1989
|
// Default differ — consumers can override by binding a different
|
|
1990
|
-
// `IFieldDiffer<T>` to `
|
|
1991
|
-
{ provide:
|
|
1990
|
+
// `IFieldDiffer<T>` to `INTEGRATION_FIELD_DIFFER` in their feature module.
|
|
1991
|
+
{ provide: INTEGRATION_FIELD_DIFFER, useValue: new DeepEqualDiffer() }
|
|
1992
1992
|
];
|
|
1993
1993
|
const backendProviders = options.backend === "memory" ? [
|
|
1994
1994
|
// Wired as singletons via `useValue` so tests can pull
|
|
@@ -1996,38 +1996,38 @@ var SyncModule = class {
|
|
|
1996
1996
|
// direct assertions. Matches JOB-4 / MemoryJobStore shape.
|
|
1997
1997
|
{ provide: MemoryCursorStore, useValue: new MemoryCursorStore() },
|
|
1998
1998
|
{
|
|
1999
|
-
provide:
|
|
1999
|
+
provide: INTEGRATION_CURSOR_STORE,
|
|
2000
2000
|
useExisting: MemoryCursorStore
|
|
2001
2001
|
},
|
|
2002
2002
|
{ provide: MemoryRunRecorder, useValue: new MemoryRunRecorder() },
|
|
2003
2003
|
{
|
|
2004
|
-
provide:
|
|
2004
|
+
provide: INTEGRATION_RUN_RECORDER,
|
|
2005
2005
|
useExisting: MemoryRunRecorder
|
|
2006
2006
|
}
|
|
2007
2007
|
] : [
|
|
2008
2008
|
// Drizzle backends — injected with DRIZZLE (provided by the
|
|
2009
|
-
// consumer's DrizzleModule) + the
|
|
2009
|
+
// consumer's DrizzleModule) + the INTEGRATION_MULTI_TENANT flag
|
|
2010
2010
|
// we bound above.
|
|
2011
|
-
{ provide:
|
|
2012
|
-
{ provide:
|
|
2011
|
+
{ provide: INTEGRATION_CURSOR_STORE, useClass: PostgresCursorStore },
|
|
2012
|
+
{ provide: INTEGRATION_RUN_RECORDER, useClass: DrizzleIntegrationRunRecorder }
|
|
2013
2013
|
];
|
|
2014
2014
|
return {
|
|
2015
|
-
module:
|
|
2015
|
+
module: IntegrationModule,
|
|
2016
2016
|
global: true,
|
|
2017
2017
|
providers: [...sharedProviders, ...backendProviders],
|
|
2018
2018
|
exports: [
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2019
|
+
INTEGRATION_MODULE_OPTIONS,
|
|
2020
|
+
INTEGRATION_MULTI_TENANT,
|
|
2021
|
+
INTEGRATION_FIELD_DIFFER,
|
|
2022
|
+
INTEGRATION_CURSOR_STORE,
|
|
2023
|
+
INTEGRATION_RUN_RECORDER
|
|
2024
2024
|
]
|
|
2025
2025
|
};
|
|
2026
2026
|
}
|
|
2027
2027
|
};
|
|
2028
|
-
|
|
2028
|
+
IntegrationModule = __decorateClass([
|
|
2029
2029
|
Module({})
|
|
2030
|
-
],
|
|
2030
|
+
], IntegrationModule);
|
|
2031
2031
|
|
|
2032
2032
|
// src/schema/entity-definition.schema.ts
|
|
2033
2033
|
var FieldTypeSchema = z3.enum([
|
|
@@ -2335,21 +2335,21 @@ var AnyQueryDeclarationSchema = z3.union([
|
|
|
2335
2335
|
SearchQueryDeclarationSchema,
|
|
2336
2336
|
QueryDeclarationSchema
|
|
2337
2337
|
]);
|
|
2338
|
-
var
|
|
2338
|
+
var IntegrationDirectionSchema = z3.enum([
|
|
2339
2339
|
"inbound",
|
|
2340
2340
|
"outbound",
|
|
2341
2341
|
"bidirectional"
|
|
2342
2342
|
]);
|
|
2343
|
-
var
|
|
2343
|
+
var ProviderIntegrationSchema = z3.object({
|
|
2344
2344
|
remote_entity: z3.string(),
|
|
2345
|
-
direction:
|
|
2345
|
+
direction: IntegrationDirectionSchema,
|
|
2346
2346
|
cdc: z3.boolean().optional().default(false),
|
|
2347
2347
|
field_mapping: z3.record(z3.string(), z3.string()).optional(),
|
|
2348
2348
|
read_only_fields: z3.array(z3.string()).optional()
|
|
2349
2349
|
});
|
|
2350
|
-
var
|
|
2350
|
+
var IntegrationConfigSchema = z3.object({
|
|
2351
2351
|
electric: z3.boolean().optional().default(false),
|
|
2352
|
-
providers: z3.record(z3.string(),
|
|
2352
|
+
providers: z3.record(z3.string(), ProviderIntegrationSchema).optional()
|
|
2353
2353
|
});
|
|
2354
2354
|
var EventDeclarationSchema = z3.object({
|
|
2355
2355
|
name: z3.string().regex(/^[a-z][a-z0-9_]*$/, "Event name must be snake_case"),
|
|
@@ -2449,20 +2449,20 @@ var EntityDefinitionSchema = z3.object({
|
|
|
2449
2449
|
// v2: Declarative query generation (ADR-005)
|
|
2450
2450
|
// Generates repository + service + use case methods from declarations
|
|
2451
2451
|
queries: z3.array(AnyQueryDeclarationSchema).optional(),
|
|
2452
|
-
// v2: Integration
|
|
2453
|
-
// Electric SQL + provider
|
|
2454
|
-
|
|
2452
|
+
// v2: Integration integration configuration (CODEGEN-EVOLUTION-PLAN Phase 2)
|
|
2453
|
+
// Electric SQL + provider integration (Salesforce, HubSpot, etc.)
|
|
2454
|
+
integration: IntegrationConfigSchema.optional(),
|
|
2455
2455
|
// ADR-033.1: Provider-keyed change-source detection.
|
|
2456
2456
|
//
|
|
2457
2457
|
// Map of provider name → DetectionConfig. Single-provider entities use
|
|
2458
2458
|
// a one-key map; multi-provider entities list each provider as a
|
|
2459
2459
|
// separate key. Each value is an independent `DetectionConfig` (its
|
|
2460
2460
|
// own mode/cursor/mapping/filters) sourced from the canonical schema
|
|
2461
|
-
// in `runtime/subsystems/
|
|
2461
|
+
// in `runtime/subsystems/integration` so this validator and the runtime
|
|
2462
2462
|
// parser stay in lockstep.
|
|
2463
2463
|
//
|
|
2464
2464
|
// Within-file cross-check (ADR-033.1 §6): every key here must also
|
|
2465
|
-
// appear in `
|
|
2465
|
+
// appear in `integration.providers` — see the superRefine on
|
|
2466
2466
|
// `EntityDefinitionSchema` below.
|
|
2467
2467
|
detection: z3.record(z3.string(), DetectionConfigSchema).optional(),
|
|
2468
2468
|
// v2: Domain event declarations (CODEGEN-EVOLUTION-PLAN Phase 2)
|
|
@@ -2492,13 +2492,13 @@ var EntityDefinitionSchema = z3.object({
|
|
|
2492
2492
|
}
|
|
2493
2493
|
).superRefine((entity, ctx) => {
|
|
2494
2494
|
if (!entity.detection) return;
|
|
2495
|
-
const declared = new Set(Object.keys(entity.
|
|
2495
|
+
const declared = new Set(Object.keys(entity.integration?.providers ?? {}));
|
|
2496
2496
|
for (const provider of Object.keys(entity.detection)) {
|
|
2497
2497
|
if (!declared.has(provider)) {
|
|
2498
2498
|
ctx.addIssue({
|
|
2499
2499
|
code: "custom",
|
|
2500
2500
|
path: ["detection", provider],
|
|
2501
|
-
message: `Provider '${provider}' used in detection: but not declared in
|
|
2501
|
+
message: `Provider '${provider}' used in detection: but not declared in integration.providers. Known providers: ${[...declared].join(", ")}`
|
|
2502
2502
|
});
|
|
2503
2503
|
}
|
|
2504
2504
|
}
|
|
@@ -3182,14 +3182,14 @@ function transformToEntity(result) {
|
|
|
3182
3182
|
entity.relationships.set(name, relationship);
|
|
3183
3183
|
}
|
|
3184
3184
|
}
|
|
3185
|
-
if (definition.
|
|
3186
|
-
const
|
|
3187
|
-
const
|
|
3188
|
-
electric:
|
|
3185
|
+
if (definition.integration) {
|
|
3186
|
+
const integrationDef = definition.integration;
|
|
3187
|
+
const parsedIntegration = {
|
|
3188
|
+
electric: integrationDef.electric ?? false
|
|
3189
3189
|
};
|
|
3190
|
-
if (
|
|
3191
|
-
|
|
3192
|
-
for (const [providerName, providerDef] of Object.entries(
|
|
3190
|
+
if (integrationDef.providers) {
|
|
3191
|
+
parsedIntegration.providers = {};
|
|
3192
|
+
for (const [providerName, providerDef] of Object.entries(integrationDef.providers)) {
|
|
3193
3193
|
const parsedProvider = {
|
|
3194
3194
|
remoteEntity: providerDef.remote_entity,
|
|
3195
3195
|
direction: providerDef.direction,
|
|
@@ -3201,10 +3201,10 @@ function transformToEntity(result) {
|
|
|
3201
3201
|
if (providerDef.read_only_fields) {
|
|
3202
3202
|
parsedProvider.readOnlyFields = providerDef.read_only_fields;
|
|
3203
3203
|
}
|
|
3204
|
-
|
|
3204
|
+
parsedIntegration.providers[providerName] = parsedProvider;
|
|
3205
3205
|
}
|
|
3206
3206
|
}
|
|
3207
|
-
entity.
|
|
3207
|
+
entity.integration = parsedIntegration;
|
|
3208
3208
|
}
|
|
3209
3209
|
if (definition.events) {
|
|
3210
3210
|
entity.events = definition.events.map((ev) => ({
|
|
@@ -3833,8 +3833,8 @@ function checkConsistency(graph) {
|
|
|
3833
3833
|
if (entity.queries !== void 0) {
|
|
3834
3834
|
issues.push(...checkQueryFieldReferences(entity));
|
|
3835
3835
|
}
|
|
3836
|
-
if (entity.
|
|
3837
|
-
issues.push(...
|
|
3836
|
+
if (entity.integration !== void 0) {
|
|
3837
|
+
issues.push(...checkIntegrationFieldMappingReferences(entity));
|
|
3838
3838
|
issues.push(...checkExternalIdTrackingCollision(entity));
|
|
3839
3839
|
}
|
|
3840
3840
|
}
|
|
@@ -4070,19 +4070,19 @@ function checkQueryFieldReferences(entity) {
|
|
|
4070
4070
|
}
|
|
4071
4071
|
return issues;
|
|
4072
4072
|
}
|
|
4073
|
-
function
|
|
4073
|
+
function checkIntegrationFieldMappingReferences(entity) {
|
|
4074
4074
|
const issues = [];
|
|
4075
4075
|
const availableFields = getAvailableFieldNames(entity);
|
|
4076
4076
|
const availableSet = new Set(availableFields);
|
|
4077
|
-
for (const [providerName, provider] of Object.entries(entity.
|
|
4077
|
+
for (const [providerName, provider] of Object.entries(entity.integration?.providers ?? {})) {
|
|
4078
4078
|
for (const fieldName of Object.keys(provider.fieldMapping ?? {})) {
|
|
4079
4079
|
if (!availableSet.has(fieldName)) {
|
|
4080
4080
|
issues.push({
|
|
4081
4081
|
severity: "warning",
|
|
4082
|
-
type: "
|
|
4082
|
+
type: "unknown_integration_field_mapping",
|
|
4083
4083
|
entity: entity.name,
|
|
4084
4084
|
field: fieldName,
|
|
4085
|
-
message: `
|
|
4085
|
+
message: `Integration field mapping references unknown field "${fieldName}" for provider "${providerName}" in entity "${entity.name}"`
|
|
4086
4086
|
});
|
|
4087
4087
|
}
|
|
4088
4088
|
}
|
|
@@ -4090,10 +4090,10 @@ function checkSyncFieldMappingReferences(entity) {
|
|
|
4090
4090
|
if (!availableSet.has(fieldName)) {
|
|
4091
4091
|
issues.push({
|
|
4092
4092
|
severity: "warning",
|
|
4093
|
-
type: "
|
|
4093
|
+
type: "unknown_integration_field_mapping",
|
|
4094
4094
|
entity: entity.name,
|
|
4095
4095
|
field: fieldName,
|
|
4096
|
-
message: `
|
|
4096
|
+
message: `Integration field mapping references unknown field "${fieldName}" for provider "${providerName}" in entity "${entity.name}"`
|
|
4097
4097
|
});
|
|
4098
4098
|
}
|
|
4099
4099
|
}
|
|
@@ -4104,14 +4104,14 @@ function checkExternalIdTrackingCollision(entity) {
|
|
|
4104
4104
|
const issues = [];
|
|
4105
4105
|
const hasExternalIdTracking = entity.behaviors.includes("external_id_tracking");
|
|
4106
4106
|
if (!hasExternalIdTracking) return issues;
|
|
4107
|
-
for (const [providerName, provider] of Object.entries(entity.
|
|
4107
|
+
for (const [providerName, provider] of Object.entries(entity.integration?.providers ?? {})) {
|
|
4108
4108
|
if (provider.fieldMapping && "external_id" in provider.fieldMapping) {
|
|
4109
4109
|
issues.push({
|
|
4110
4110
|
severity: "warning",
|
|
4111
4111
|
type: "external_id_tracking_collision",
|
|
4112
4112
|
entity: entity.name,
|
|
4113
4113
|
field: "external_id",
|
|
4114
|
-
message: `Entity "${entity.name}" has external_id_tracking behavior and also maps "external_id" in
|
|
4114
|
+
message: `Entity "${entity.name}" has external_id_tracking behavior and also maps "external_id" in integration field_mapping for provider "${providerName}". The behavior-added field may collide with the mapped field.`
|
|
4115
4115
|
});
|
|
4116
4116
|
}
|
|
4117
4117
|
}
|
|
@@ -5489,30 +5489,30 @@ var MetadataPattern = definePattern({
|
|
|
5489
5489
|
description: "History-tracked metadata rows \u2014 entity-id + type scoped lookups"
|
|
5490
5490
|
});
|
|
5491
5491
|
|
|
5492
|
-
// src/patterns/library/
|
|
5493
|
-
var
|
|
5494
|
-
name: "
|
|
5492
|
+
// src/patterns/library/integrated.pattern.ts
|
|
5493
|
+
var IntegratedPattern = definePattern({
|
|
5494
|
+
name: "Integrated",
|
|
5495
5495
|
extends: ["Base"],
|
|
5496
|
-
repositoryClass: "
|
|
5497
|
-
serviceClass: "
|
|
5498
|
-
repositoryImport: "@shared/base-classes/
|
|
5499
|
-
serviceImport: "@shared/base-classes/
|
|
5496
|
+
repositoryClass: "IntegratedEntityRepository",
|
|
5497
|
+
serviceClass: "IntegratedEntityService",
|
|
5498
|
+
repositoryImport: "@shared/base-classes/integrated-entity-repository",
|
|
5499
|
+
serviceImport: "@shared/base-classes/integrated-entity-service",
|
|
5500
5500
|
repositoryInheritedMethods: [
|
|
5501
5501
|
"findById, findByIds, list, count, exists, create, update, delete, upsertMany",
|
|
5502
5502
|
"findByExternalId, findManyByExternalIds, findAllByUserId, findVisibleByUserId",
|
|
5503
|
-
"
|
|
5503
|
+
"integrationUpsertOne, findByExternalIdProjected, softDeleteByExternalId, integrationUpsert"
|
|
5504
5504
|
],
|
|
5505
5505
|
serviceInheritedMethods: [
|
|
5506
5506
|
"findById, findByIds, list, count, exists, create, update, delete",
|
|
5507
5507
|
"findByExternalId, findAllByUserId, findVisibleByUserId"
|
|
5508
5508
|
],
|
|
5509
5509
|
impliedBehaviors: ["external_id_tracking"],
|
|
5510
|
-
description: "External CRM/system
|
|
5510
|
+
description: "External CRM/system integration columns and integrationUpsert methods"
|
|
5511
5511
|
});
|
|
5512
5512
|
|
|
5513
5513
|
// src/patterns/library/index.ts
|
|
5514
5514
|
registerLibraryPattern(BasePattern);
|
|
5515
|
-
registerLibraryPattern(
|
|
5515
|
+
registerLibraryPattern(IntegratedPattern);
|
|
5516
5516
|
registerLibraryPattern(ActivityPattern);
|
|
5517
5517
|
registerLibraryPattern(KnowledgePattern);
|
|
5518
5518
|
registerLibraryPattern(MetadataPattern);
|
|
@@ -5953,8 +5953,8 @@ var SUBSYSTEMS = [
|
|
|
5953
5953
|
defaultBackend: "local"
|
|
5954
5954
|
},
|
|
5955
5955
|
{
|
|
5956
|
-
name: "
|
|
5957
|
-
description: "External-system
|
|
5956
|
+
name: "integration",
|
|
5957
|
+
description: "External-system integration engine (IChangeSource<T> + orchestrator + audit log)",
|
|
5958
5958
|
backends: ["drizzle", "memory"],
|
|
5959
5959
|
defaultBackend: "drizzle"
|
|
5960
5960
|
},
|
|
@@ -5977,7 +5977,7 @@ var SUBSYSTEMS = [
|
|
|
5977
5977
|
{
|
|
5978
5978
|
// OBS-7 / ADR-025. Combiner subsystem — no schema, no worker, no
|
|
5979
5979
|
// generated/ dir. `ObservabilityModule` composes sibling read ports
|
|
5980
|
-
// (events/jobs/bridge/
|
|
5980
|
+
// (events/jobs/bridge/integration) via @Optional() DI. The `combiner`
|
|
5981
5981
|
// pseudo-backend is parallel to `openapi-config`'s `config-only`.
|
|
5982
5982
|
name: "observability",
|
|
5983
5983
|
description: "Observability combiner \u2014 composes sibling read ports via @Optional() DI (ADR-025)",
|
|
@@ -5999,14 +5999,14 @@ var SUBSYSTEMS = [
|
|
|
5999
5999
|
{
|
|
6000
6000
|
// #287. Auth-integrations starter (PR #290) — vendored from
|
|
6001
6001
|
// `examples/auth-integrations/`, NOT from `runtime/subsystems/`.
|
|
6002
|
-
// Bundles a canonical `
|
|
6003
|
-
//
|
|
6002
|
+
// Bundles a canonical `connection` entity yaml + the three
|
|
6003
|
+
// connection-store-port adapters + the `ConnectionsService`
|
|
6004
6004
|
// facade. Single-backend (drizzle); the runtime adapters call
|
|
6005
|
-
// directly into the codegen-emitted `
|
|
6005
|
+
// directly into the codegen-emitted `ConnectionService` from the
|
|
6006
6006
|
// entity layer. Detection: presence of
|
|
6007
|
-
// `<
|
|
6007
|
+
// `<vendorRoot>/connections/connections-auth.module.ts`.
|
|
6008
6008
|
name: "auth-integrations",
|
|
6009
|
-
description: "Vendored
|
|
6009
|
+
description: "Vendored connection entity + adapters (consumes auth subsystem)",
|
|
6010
6010
|
backends: ["drizzle"],
|
|
6011
6011
|
defaultBackend: "drizzle"
|
|
6012
6012
|
}
|
|
@@ -6017,7 +6017,7 @@ var SUBSYSTEM_MODULE_FILE = {
|
|
|
6017
6017
|
jobs: "jobs-domain.module.ts",
|
|
6018
6018
|
cache: "cache.module.ts",
|
|
6019
6019
|
storage: "storage.module.ts",
|
|
6020
|
-
|
|
6020
|
+
integration: "integration.module.ts",
|
|
6021
6021
|
bridge: "bridge.module.ts",
|
|
6022
6022
|
observability: "observability.module.ts",
|
|
6023
6023
|
auth: "auth.module.ts"
|
|
@@ -6099,11 +6099,8 @@ async function detectSubsystemStatesImpl(ctx) {
|
|
|
6099
6099
|
const pathsAny = ctx.config?.paths;
|
|
6100
6100
|
const modulesConfigured = pathsAny?.modules_dir;
|
|
6101
6101
|
const vendorRoot = typeof modulesConfigured === "string" && modulesConfigured.length > 0 ? path6.resolve(ctx.cwd, modulesConfigured) : path6.resolve(ctx.cwd, backendSrc, "modules");
|
|
6102
|
-
const sharedConfigured = pathsAny?.shared;
|
|
6103
|
-
const sharedRoot = typeof sharedConfigured === "string" && sharedConfigured.length > 0 ? path6.resolve(ctx.cwd, sharedConfigured) : path6.resolve(ctx.cwd, backendSrc, "shared");
|
|
6104
6102
|
const candidates = [
|
|
6105
|
-
path6.join(vendorRoot, "
|
|
6106
|
-
path6.join(sharedRoot, "integrations", "integrations-auth.module.ts")
|
|
6103
|
+
path6.join(vendorRoot, "connections", "connections-auth.module.ts")
|
|
6107
6104
|
];
|
|
6108
6105
|
for (const moduleFile of candidates) {
|
|
6109
6106
|
if (fs4.existsSync(moduleFile)) {
|
|
@@ -6217,24 +6214,24 @@ var COMPOSERS = {
|
|
|
6217
6214
|
]
|
|
6218
6215
|
};
|
|
6219
6216
|
},
|
|
6220
|
-
|
|
6217
|
+
integration: ({ subsystemsRel, cfg }) => {
|
|
6221
6218
|
const backend = cfg?.backend ?? "drizzle";
|
|
6222
6219
|
const multiTenant = Boolean(cfg?.multi_tenant);
|
|
6223
6220
|
return {
|
|
6224
6221
|
imports: [
|
|
6225
|
-
`import {
|
|
6222
|
+
`import { IntegrationModule } from '${subsystemsRel}/integration/integration.module';`
|
|
6226
6223
|
],
|
|
6227
6224
|
calls: [
|
|
6228
|
-
`
|
|
6225
|
+
` IntegrationModule.forRoot(${quoteOpts({ backend, multiTenant })}),`
|
|
6229
6226
|
]
|
|
6230
6227
|
};
|
|
6231
6228
|
}
|
|
6232
6229
|
};
|
|
6233
|
-
var COMPOSABLE_ORDER = ["events", "jobs", "bridge", "
|
|
6230
|
+
var COMPOSABLE_ORDER = ["events", "jobs", "bridge", "integration"];
|
|
6234
6231
|
var HEADER3 = `// AUTO-GENERATED by @pattern-stack/codegen. DO NOT EDIT.
|
|
6235
6232
|
// Subsystem composition barrel \u2014 reflects \`subsystems.install\` in
|
|
6236
6233
|
// codegen.config.yaml and the per-subsystem option blocks
|
|
6237
|
-
// (\`events:\`, \`jobs:\`, \`bridge:\`, \`
|
|
6234
|
+
// (\`events:\`, \`jobs:\`, \`bridge:\`, \`integration:\`).
|
|
6238
6235
|
//
|
|
6239
6236
|
// Wire into AppModule once:
|
|
6240
6237
|
//
|
|
@@ -8627,22 +8624,22 @@ function localsToHygenArgs2(locals) {
|
|
|
8627
8624
|
];
|
|
8628
8625
|
}
|
|
8629
8626
|
|
|
8630
|
-
// src/cli/shared/
|
|
8627
|
+
// src/cli/shared/integration-scaffold-locals.ts
|
|
8631
8628
|
import path16 from "path";
|
|
8632
|
-
function
|
|
8629
|
+
function resolveIntegrationScaffoldLocals(input) {
|
|
8633
8630
|
const { cwd, config } = input;
|
|
8634
8631
|
void input.fileExists;
|
|
8635
|
-
const
|
|
8632
|
+
const integrationBlock = config?.integration ?? {};
|
|
8636
8633
|
const subsystemsRoot = resolveSubsystemsRootFromConfig(cwd, config);
|
|
8637
8634
|
const configPath = path16.resolve(cwd, "codegen.config.yaml");
|
|
8638
8635
|
const schemaPath = path16.resolve(
|
|
8639
8636
|
subsystemsRoot,
|
|
8640
|
-
"
|
|
8641
|
-
"
|
|
8637
|
+
"integration",
|
|
8638
|
+
"integration-audit.schema.ts"
|
|
8642
8639
|
);
|
|
8643
8640
|
return {
|
|
8644
8641
|
appName: path16.basename(cwd),
|
|
8645
|
-
multiTenant: normaliseMultiTenant3(
|
|
8642
|
+
multiTenant: normaliseMultiTenant3(integrationBlock.multi_tenant),
|
|
8646
8643
|
configPath,
|
|
8647
8644
|
schemaPath
|
|
8648
8645
|
};
|
|
@@ -8781,19 +8778,16 @@ function localsToHygenArgs6(locals) {
|
|
|
8781
8778
|
// src/cli/shared/auth-integrations-scaffold-locals.ts
|
|
8782
8779
|
import path20 from "path";
|
|
8783
8780
|
var FALLBACK_BACKEND_SRC4 = "src";
|
|
8784
|
-
var SHARED_DIR_NAME = "shared";
|
|
8785
8781
|
var DEFAULT_MODULES_DIR = "modules";
|
|
8786
8782
|
var DEFAULT_DEFINITIONS_DIR = "definitions/entities";
|
|
8787
8783
|
function resolveAuthIntegrationsScaffoldLocals(input) {
|
|
8788
8784
|
const { cwd, config } = input;
|
|
8789
8785
|
const backendSrc = typeof config?.paths?.backend_src === "string" && config.paths.backend_src.length > 0 ? config.paths.backend_src : FALLBACK_BACKEND_SRC4;
|
|
8790
8786
|
const pathsAny = config?.paths;
|
|
8791
|
-
const sharedConfigured = pathsAny?.shared;
|
|
8792
|
-
const sharedRoot = typeof sharedConfigured === "string" && sharedConfigured.length > 0 ? path20.resolve(cwd, sharedConfigured) : path20.resolve(cwd, backendSrc, SHARED_DIR_NAME);
|
|
8793
8787
|
const modulesConfigured = pathsAny?.modules_dir;
|
|
8794
8788
|
const vendorRoot = typeof modulesConfigured === "string" && modulesConfigured.length > 0 ? path20.resolve(cwd, modulesConfigured) : path20.resolve(cwd, backendSrc, DEFAULT_MODULES_DIR);
|
|
8795
8789
|
const entitiesConfigured = typeof pathsAny?.entities === "string" && pathsAny.entities.length > 0 ? pathsAny.entities : typeof pathsAny?.entities_dir === "string" && pathsAny.entities_dir.length > 0 ? pathsAny.entities_dir : null;
|
|
8796
|
-
const definitionsPath = entitiesConfigured !== null ? path20.resolve(cwd, entitiesConfigured, "
|
|
8790
|
+
const definitionsPath = entitiesConfigured !== null ? path20.resolve(cwd, entitiesConfigured, "connection.yaml") : path20.resolve(cwd, DEFAULT_DEFINITIONS_DIR, "connection.yaml");
|
|
8797
8791
|
const appModulePath = path20.resolve(cwd, backendSrc, "app.module.ts");
|
|
8798
8792
|
let authModuleRegistered = false;
|
|
8799
8793
|
const appModuleSource = input.readFile(appModulePath);
|
|
@@ -8803,7 +8797,6 @@ function resolveAuthIntegrationsScaffoldLocals(input) {
|
|
|
8803
8797
|
return {
|
|
8804
8798
|
appName: path20.basename(cwd),
|
|
8805
8799
|
appModulePath,
|
|
8806
|
-
sharedRoot,
|
|
8807
8800
|
vendorRoot,
|
|
8808
8801
|
definitionsPath,
|
|
8809
8802
|
authModuleRegistered
|
|
@@ -9002,7 +8995,7 @@ function backendFileFilter(backend, subsystemName) {
|
|
|
9002
8995
|
if (subsystemName === "events" && file === "domain-events.schema.ts") {
|
|
9003
8996
|
return false;
|
|
9004
8997
|
}
|
|
9005
|
-
if (subsystemName === "
|
|
8998
|
+
if (subsystemName === "integration" && file === "integration-audit.schema.ts") {
|
|
9006
8999
|
return false;
|
|
9007
9000
|
}
|
|
9008
9001
|
if (subsystemName === "auth" && file === "auth-oauth-state.schema.ts") {
|
|
@@ -9126,7 +9119,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9126
9119
|
json: isJsonMode(),
|
|
9127
9120
|
forceConfig: this.forceConfig
|
|
9128
9121
|
}) : null;
|
|
9129
|
-
const
|
|
9122
|
+
const integrationScaffold = desc3.name === "integration" ? runIntegrationScaffold(ctx.cwd, ctx.config, {
|
|
9130
9123
|
dryRun: this.dryRun,
|
|
9131
9124
|
json: isJsonMode(),
|
|
9132
9125
|
forceConfig: this.forceConfig
|
|
@@ -9158,9 +9151,9 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9158
9151
|
);
|
|
9159
9152
|
return 1;
|
|
9160
9153
|
}
|
|
9161
|
-
if (
|
|
9154
|
+
if (integrationScaffold?.configBlockOutcome === "parse-error") {
|
|
9162
9155
|
printError(
|
|
9163
|
-
"codegen.config.yaml is not valid YAML: refusing to inject
|
|
9156
|
+
"codegen.config.yaml is not valid YAML: refusing to inject integration config block. Fix the YAML and re-run."
|
|
9164
9157
|
);
|
|
9165
9158
|
return 1;
|
|
9166
9159
|
}
|
|
@@ -9198,7 +9191,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9198
9191
|
},
|
|
9199
9192
|
...jobsScaffold ? { scaffold: jobsScaffold } : {},
|
|
9200
9193
|
...eventsScaffold ? { scaffold: eventsScaffold } : {},
|
|
9201
|
-
...
|
|
9194
|
+
...integrationScaffold ? { scaffold: integrationScaffold } : {},
|
|
9202
9195
|
...bridgeScaffold ? { scaffold: bridgeScaffold } : {},
|
|
9203
9196
|
...observabilityScaffold ? { scaffold: observabilityScaffold } : {},
|
|
9204
9197
|
...authScaffold ? { scaffold: authScaffold } : {}
|
|
@@ -9226,11 +9219,11 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9226
9219
|
console.log(` ${theme.muted(icons.arrow)} ${path22.relative(ctx.cwd, p) || p}`);
|
|
9227
9220
|
}
|
|
9228
9221
|
}
|
|
9229
|
-
if (
|
|
9222
|
+
if (integrationScaffold?.planned?.length) {
|
|
9230
9223
|
printInfo(
|
|
9231
|
-
`
|
|
9224
|
+
`Integration scaffold \u2014 ${integrationScaffold.planned.length} template targets`
|
|
9232
9225
|
);
|
|
9233
|
-
for (const p of
|
|
9226
|
+
for (const p of integrationScaffold.planned) {
|
|
9234
9227
|
console.log(` ${theme.muted(icons.arrow)} ${path22.relative(ctx.cwd, p) || p}`);
|
|
9235
9228
|
}
|
|
9236
9229
|
}
|
|
@@ -9289,14 +9282,14 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9289
9282
|
);
|
|
9290
9283
|
}
|
|
9291
9284
|
}
|
|
9292
|
-
if (
|
|
9293
|
-
if (
|
|
9285
|
+
if (integrationScaffold) {
|
|
9286
|
+
if (integrationScaffold.ok) {
|
|
9294
9287
|
printSuccess(
|
|
9295
|
-
`
|
|
9288
|
+
`integration scaffold applied (config block, schema)`
|
|
9296
9289
|
);
|
|
9297
9290
|
} else {
|
|
9298
9291
|
printWarning(
|
|
9299
|
-
`
|
|
9292
|
+
`integration scaffold (Hygen) failed \u2014 runtime files were written; re-run after fixing: ${integrationScaffold.error ?? "unknown error"}`
|
|
9300
9293
|
);
|
|
9301
9294
|
}
|
|
9302
9295
|
}
|
|
@@ -9343,7 +9336,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9343
9336
|
}
|
|
9344
9337
|
if (desc3.name === "observability") {
|
|
9345
9338
|
printInfo(
|
|
9346
|
-
"Register `ObservabilityModule.forRoot()` AFTER Events/Jobs/Bridge/
|
|
9339
|
+
"Register `ObservabilityModule.forRoot()` AFTER Events/Jobs/Bridge/Integration in app.module.ts"
|
|
9347
9340
|
);
|
|
9348
9341
|
} else if (desc3.name === "auth") {
|
|
9349
9342
|
printInfo("auth subsystem installed.");
|
|
@@ -9357,9 +9350,9 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9357
9350
|
`Register ${capitalize(desc3.name)}Module.forRoot({ backend: '${backend}' }) in your app.module.ts`
|
|
9358
9351
|
);
|
|
9359
9352
|
}
|
|
9360
|
-
if (desc3.name === "
|
|
9353
|
+
if (desc3.name === "integration") {
|
|
9361
9354
|
printInfo(
|
|
9362
|
-
`Per-entity: register
|
|
9355
|
+
`Per-entity: register ExecuteIntegrationUseCase + your IChangeSource/IIntegrationSink bindings in a feature module (see IntegrationModule docstring).`
|
|
9363
9356
|
);
|
|
9364
9357
|
}
|
|
9365
9358
|
return 0;
|
|
@@ -9372,7 +9365,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9372
9365
|
* `codegen project init`. This method just invokes the
|
|
9373
9366
|
* `subsystem/openapi-config` Hygen action to inject the `openapi:`
|
|
9374
9367
|
* block into `codegen.config.yaml`, honoring the same `--force-config`
|
|
9375
|
-
* semantics as jobs/events/
|
|
9368
|
+
* semantics as jobs/events/integration/bridge.
|
|
9376
9369
|
*/
|
|
9377
9370
|
async executeOpenApiConfig(ctx) {
|
|
9378
9371
|
const configPath = path22.join(ctx.cwd, "codegen.config.yaml");
|
|
@@ -9435,9 +9428,9 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9435
9428
|
*
|
|
9436
9429
|
* Source is `examples/auth-integrations/`, NOT `runtime/subsystems/`,
|
|
9437
9430
|
* so this method short-circuits the `copyRuntime` flow. It vendors the
|
|
9438
|
-
* adapters tree + the canonical `
|
|
9431
|
+
* adapters tree + the canonical `connection.yaml`, then invokes the
|
|
9439
9432
|
* `subsystem auth-integrations` Hygen action to append the
|
|
9440
|
-
* `
|
|
9433
|
+
* `ConnectionsAuthModule` TODO to `app.module.ts`.
|
|
9441
9434
|
*
|
|
9442
9435
|
* Idempotent: pre-existing files are skipped unless `--force` is set.
|
|
9443
9436
|
*/
|
|
@@ -9485,7 +9478,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9485
9478
|
}
|
|
9486
9479
|
if (this.dryRun) {
|
|
9487
9480
|
printInfo(
|
|
9488
|
-
`Dry run \u2014 auth-integrations would vendor adapters +
|
|
9481
|
+
`Dry run \u2014 auth-integrations would vendor adapters + connection.yaml + append TODO`
|
|
9489
9482
|
);
|
|
9490
9483
|
for (const p of scaffold.planned) {
|
|
9491
9484
|
console.log(
|
|
@@ -9501,14 +9494,14 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9501
9494
|
);
|
|
9502
9495
|
if (scaffold.authModuleRegistered === false) {
|
|
9503
9496
|
printWarning(
|
|
9504
|
-
"AuthModule.forRoot(...) not detected in app.module.ts. Run `cdp subsystem install auth` first \u2014
|
|
9497
|
+
"AuthModule.forRoot(...) not detected in app.module.ts. Run `cdp subsystem install auth` first \u2014 ConnectionsAuthModule requires ENCRYPTION_KEY from it."
|
|
9505
9498
|
);
|
|
9506
9499
|
}
|
|
9507
9500
|
printInfo("auth-integrations starter vendored.");
|
|
9508
9501
|
printInfo("Next steps:");
|
|
9509
|
-
printInfo(" 1. Run `cdp entity new
|
|
9502
|
+
printInfo(" 1. Run `cdp entity new connection` to scaffold the codegen layer (apps/api/src/modules/connections/connection.service) the adapters import.");
|
|
9510
9503
|
printInfo(" 2. Ensure AuthModule.forRoot(...) is registered in AppModule (run `cdp subsystem install auth` if not).");
|
|
9511
|
-
printInfo(" 3. Wire
|
|
9504
|
+
printInfo(" 3. Wire ConnectionsAuthModule into AppModule (see TODO appended to app.module.ts).");
|
|
9512
9505
|
return 0;
|
|
9513
9506
|
}
|
|
9514
9507
|
};
|
|
@@ -9689,8 +9682,8 @@ function runEventsScaffold(cwd, config, opts) {
|
|
|
9689
9682
|
}
|
|
9690
9683
|
return { ok: true, planned, configBlockOutcome };
|
|
9691
9684
|
}
|
|
9692
|
-
function
|
|
9693
|
-
const locals =
|
|
9685
|
+
function runIntegrationScaffold(cwd, config, opts) {
|
|
9686
|
+
const locals = resolveIntegrationScaffoldLocals({
|
|
9694
9687
|
cwd,
|
|
9695
9688
|
config,
|
|
9696
9689
|
fileExists: (p) => fs11.existsSync(p)
|
|
@@ -9701,7 +9694,7 @@ function runSyncScaffold(cwd, config, opts) {
|
|
|
9701
9694
|
];
|
|
9702
9695
|
const configBlockOutcome = planConfigBlockAction(
|
|
9703
9696
|
locals.configPath,
|
|
9704
|
-
"
|
|
9697
|
+
"integration",
|
|
9705
9698
|
opts.forceConfig
|
|
9706
9699
|
);
|
|
9707
9700
|
if (configBlockOutcome === "parse-error") {
|
|
@@ -9712,7 +9705,7 @@ function runSyncScaffold(cwd, config, opts) {
|
|
|
9712
9705
|
}
|
|
9713
9706
|
const result = invokeHygen({
|
|
9714
9707
|
generator: "subsystem",
|
|
9715
|
-
action: "
|
|
9708
|
+
action: "integration",
|
|
9716
9709
|
cwd,
|
|
9717
9710
|
args: localsToHygenArgs3(locals),
|
|
9718
9711
|
// Suppress Hygen stdout in JSON mode so it doesn't corrupt the JSON output.
|
|
@@ -9728,9 +9721,9 @@ function runSyncScaffold(cwd, config, opts) {
|
|
|
9728
9721
|
}
|
|
9729
9722
|
const configResult = runConfigBlockAction({
|
|
9730
9723
|
cwd,
|
|
9731
|
-
actionFolder: "
|
|
9724
|
+
actionFolder: "integration-config",
|
|
9732
9725
|
configPath: locals.configPath,
|
|
9733
|
-
subsystem: "
|
|
9726
|
+
subsystem: "integration",
|
|
9734
9727
|
outcome: configBlockOutcome,
|
|
9735
9728
|
json: opts.json
|
|
9736
9729
|
});
|
|
@@ -9981,18 +9974,18 @@ function runAuthIntegrationsScaffold(cwd, config, opts) {
|
|
|
9981
9974
|
error: `auth-integrations starter source missing: ${examplesRoot}`
|
|
9982
9975
|
};
|
|
9983
9976
|
}
|
|
9984
|
-
const adaptersSrc = path22.join(examplesRoot, "runtime", "
|
|
9985
|
-
const adaptersDest = path22.join(locals.vendorRoot, "
|
|
9986
|
-
const
|
|
9977
|
+
const adaptersSrc = path22.join(examplesRoot, "runtime", "connections");
|
|
9978
|
+
const adaptersDest = path22.join(locals.vendorRoot, "connections");
|
|
9979
|
+
const connectionYamlSrc = path22.join(
|
|
9987
9980
|
examplesRoot,
|
|
9988
9981
|
"definitions",
|
|
9989
9982
|
"entities",
|
|
9990
|
-
"
|
|
9983
|
+
"connection.yaml"
|
|
9991
9984
|
);
|
|
9992
|
-
const
|
|
9985
|
+
const connectionYamlDest = locals.definitionsPath;
|
|
9993
9986
|
const planned = [
|
|
9994
9987
|
adaptersDest,
|
|
9995
|
-
|
|
9988
|
+
connectionYamlDest,
|
|
9996
9989
|
locals.appModulePath
|
|
9997
9990
|
];
|
|
9998
9991
|
if (opts.dryRun) {
|
|
@@ -10012,18 +10005,18 @@ function runAuthIntegrationsScaffold(cwd, config, opts) {
|
|
|
10012
10005
|
let yamlWritten = false;
|
|
10013
10006
|
let yamlSkipped = false;
|
|
10014
10007
|
try {
|
|
10015
|
-
if (fs11.existsSync(
|
|
10008
|
+
if (fs11.existsSync(connectionYamlDest) && !opts.force) {
|
|
10016
10009
|
yamlSkipped = true;
|
|
10017
|
-
} else if (fs11.existsSync(
|
|
10018
|
-
fs11.mkdirSync(path22.dirname(
|
|
10019
|
-
fs11.copyFileSync(
|
|
10010
|
+
} else if (fs11.existsSync(connectionYamlSrc)) {
|
|
10011
|
+
fs11.mkdirSync(path22.dirname(connectionYamlDest), { recursive: true });
|
|
10012
|
+
fs11.copyFileSync(connectionYamlSrc, connectionYamlDest);
|
|
10020
10013
|
yamlWritten = true;
|
|
10021
10014
|
}
|
|
10022
10015
|
} catch (err) {
|
|
10023
10016
|
return {
|
|
10024
10017
|
ok: false,
|
|
10025
10018
|
planned,
|
|
10026
|
-
error: `failed to vendor
|
|
10019
|
+
error: `failed to vendor connection.yaml: ${err instanceof Error ? err.message : String(err)}`,
|
|
10027
10020
|
authModuleRegistered: locals.authModuleRegistered
|
|
10028
10021
|
};
|
|
10029
10022
|
}
|
|
@@ -10039,16 +10032,16 @@ function runAuthIntegrationsScaffold(cwd, config, opts) {
|
|
|
10039
10032
|
ok: false,
|
|
10040
10033
|
planned,
|
|
10041
10034
|
error: result.stderr?.trim() || "hygen exited non-zero",
|
|
10042
|
-
written: adapterCopy.written.concat(yamlWritten ? [
|
|
10043
|
-
skipped: adapterCopy.skipped.concat(yamlSkipped ? [
|
|
10035
|
+
written: adapterCopy.written.concat(yamlWritten ? [connectionYamlDest] : []),
|
|
10036
|
+
skipped: adapterCopy.skipped.concat(yamlSkipped ? [connectionYamlDest] : []),
|
|
10044
10037
|
authModuleRegistered: locals.authModuleRegistered
|
|
10045
10038
|
};
|
|
10046
10039
|
}
|
|
10047
10040
|
return {
|
|
10048
10041
|
ok: true,
|
|
10049
10042
|
planned,
|
|
10050
|
-
written: adapterCopy.written.concat(yamlWritten ? [
|
|
10051
|
-
skipped: adapterCopy.skipped.concat(yamlSkipped ? [
|
|
10043
|
+
written: adapterCopy.written.concat(yamlWritten ? [connectionYamlDest] : []),
|
|
10044
|
+
skipped: adapterCopy.skipped.concat(yamlSkipped ? [connectionYamlDest] : []),
|
|
10052
10045
|
authModuleRegistered: locals.authModuleRegistered
|
|
10053
10046
|
};
|
|
10054
10047
|
}
|
|
@@ -10151,7 +10144,7 @@ var SubsystemRemoveCommand = class extends Command3 {
|
|
|
10151
10144
|
"auth-integrations is vendored under <modules>/integrations/ alongside the codegen-emitted entity layer \u2014 not auto-removable here."
|
|
10152
10145
|
);
|
|
10153
10146
|
printInfo(
|
|
10154
|
-
"To uninstall: remove the integrations/ directory and the
|
|
10147
|
+
"To uninstall: remove the integrations/ directory and the ConnectionsAuthModule registration from app.module.ts by hand."
|
|
10155
10148
|
);
|
|
10156
10149
|
return 1;
|
|
10157
10150
|
}
|
|
@@ -10270,11 +10263,11 @@ var VENDORED_RUNTIME_FILES = [
|
|
|
10270
10263
|
// Ambient tenant scope — imported by base-repository.ts (scopePredicate)
|
|
10271
10264
|
{ runtime: "base-classes/tenant-context.ts", target: "src/shared/base-classes/tenant-context.ts" },
|
|
10272
10265
|
{ runtime: "base-classes/base-service.ts", target: "src/shared/base-classes/base-service.ts" },
|
|
10273
|
-
{ runtime: "base-classes/
|
|
10274
|
-
{ runtime: "base-classes/
|
|
10275
|
-
// Inbound-
|
|
10276
|
-
{ runtime: "base-classes/
|
|
10277
|
-
{ runtime: "base-classes/junction-
|
|
10266
|
+
{ runtime: "base-classes/integrated-entity-repository.ts", target: "src/shared/base-classes/integrated-entity-repository.ts" },
|
|
10267
|
+
{ runtime: "base-classes/integrated-entity-service.ts", target: "src/shared/base-classes/integrated-entity-service.ts" },
|
|
10268
|
+
// Inbound-integration write surface (#374) — deps of integrated/junction repos
|
|
10269
|
+
{ runtime: "base-classes/integration-upsert-config.ts", target: "src/shared/base-classes/integration-upsert-config.ts" },
|
|
10270
|
+
{ runtime: "base-classes/junction-integration-repository.ts", target: "src/shared/base-classes/junction-integration-repository.ts" },
|
|
10278
10271
|
{ runtime: "base-classes/activity-entity-repository.ts", target: "src/shared/base-classes/activity-entity-repository.ts" },
|
|
10279
10272
|
{ runtime: "base-classes/activity-entity-service.ts", target: "src/shared/base-classes/activity-entity-service.ts" },
|
|
10280
10273
|
{ runtime: "base-classes/metadata-entity-repository.ts", target: "src/shared/base-classes/metadata-entity-repository.ts" },
|
|
@@ -10539,7 +10532,7 @@ function exampleEntityYaml() {
|
|
|
10539
10532
|
#
|
|
10540
10533
|
# entity:
|
|
10541
10534
|
# name: account
|
|
10542
|
-
# pattern:
|
|
10535
|
+
# pattern: Integrated # Base | Integrated | Activity | Metadata | Knowledge (or app-defined)
|
|
10543
10536
|
#
|
|
10544
10537
|
# fields:
|
|
10545
10538
|
# name:
|