@pattern-stack/codegen 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +135 -0
- package/README.md +5 -5
- package/consumer-skills/codegen/SKILL.md +2 -2
- package/consumer-skills/events/typed-bus-and-outbox.md +1 -1
- package/consumer-skills/{sync → integration}/SKILL.md +29 -29
- package/consumer-skills/{sync → integration}/audit-and-detection.md +22 -22
- package/consumer-skills/{sync → integration}/change-sources-and-sinks.md +60 -60
- package/consumer-skills/subsystems/SKILL.md +64 -8
- package/consumer-skills/subsystems/wiring-and-order.md +7 -7
- package/dist/runtime/base-classes/index.d.ts +4 -4
- package/dist/runtime/base-classes/index.js +35 -35
- package/dist/runtime/base-classes/index.js.map +1 -1
- package/dist/runtime/base-classes/{synced-entity-repository.d.ts → integrated-entity-repository.d.ts} +15 -15
- package/dist/runtime/base-classes/{synced-entity-repository.js → integrated-entity-repository.js} +21 -21
- package/dist/runtime/base-classes/integrated-entity-repository.js.map +1 -0
- package/dist/runtime/base-classes/{synced-entity-service.d.ts → integrated-entity-service.d.ts} +6 -6
- package/dist/runtime/base-classes/{synced-entity-service.js → integrated-entity-service.js} +4 -4
- package/dist/runtime/base-classes/integrated-entity-service.js.map +1 -0
- package/dist/runtime/base-classes/{sync-upsert-config.d.ts → integration-upsert-config.d.ts} +13 -13
- package/dist/runtime/base-classes/integration-upsert-config.js +1 -0
- package/dist/runtime/base-classes/{junction-sync-repository.d.ts → junction-integration-repository.d.ts} +11 -11
- package/dist/runtime/base-classes/{junction-sync-repository.js → junction-integration-repository.js} +15 -15
- package/dist/runtime/base-classes/junction-integration-repository.js.map +1 -0
- package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.module.d.ts +4 -4
- package/dist/runtime/subsystems/auth/auth.module.js +3 -3
- package/dist/runtime/subsystems/auth/auth.module.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.tokens.d.ts +8 -8
- package/dist/runtime/subsystems/auth/auth.tokens.js +6 -6
- package/dist/runtime/subsystems/auth/auth.tokens.js.map +1 -1
- package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/auth/controllers/auth.controller.d.ts +2 -2
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js +3 -3
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js.map +1 -1
- package/dist/runtime/subsystems/auth/index.d.ts +3 -3
- package/dist/runtime/subsystems/auth/index.js +40 -40
- package/dist/runtime/subsystems/auth/index.js.map +1 -1
- package/dist/runtime/subsystems/auth/middleware/requester-context.js.map +1 -1
- package/dist/runtime/subsystems/auth/protocols/auth-strategy.d.ts +3 -3
- package/dist/runtime/subsystems/auth/protocols/{integration-store.d.ts → connection-store.d.ts} +20 -20
- package/dist/runtime/subsystems/auth/protocols/connection-store.js +1 -0
- package/dist/runtime/subsystems/auth/protocols/provider-strategy.d.ts +3 -3
- package/dist/runtime/subsystems/auth/runtime/{integration-broken.error.d.ts → connection-broken.error.d.ts} +5 -5
- package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js +19 -0
- package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js.map +1 -0
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.d.ts +10 -10
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js +28 -28
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js.map +1 -1
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.d.ts +1 -1
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js +3 -3
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge.module.d.ts +0 -1
- package/dist/runtime/subsystems/bridge/bridge.module.js +294 -710
- package/dist/runtime/subsystems/bridge/bridge.module.js.map +1 -1
- package/dist/runtime/subsystems/bridge/index.d.ts +0 -1
- package/dist/runtime/subsystems/bridge/index.js +248 -664
- package/dist/runtime/subsystems/bridge/index.js.map +1 -1
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +18 -10
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/events/events.module.js +43 -244
- package/dist/runtime/subsystems/events/events.module.js.map +1 -1
- package/dist/runtime/subsystems/events/index.d.ts +0 -1
- package/dist/runtime/subsystems/events/index.js +39 -241
- package/dist/runtime/subsystems/events/index.js.map +1 -1
- package/dist/runtime/subsystems/index.d.ts +7 -7
- package/dist/runtime/subsystems/index.js +222 -839
- package/dist/runtime/subsystems/index.js.map +1 -1
- package/dist/runtime/subsystems/{sync → integration}/build-change-source.d.ts +3 -3
- package/dist/runtime/subsystems/{sync → integration}/build-change-source.js +3 -3
- package/dist/runtime/subsystems/integration/build-change-source.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/deep-equal.differ.d.ts +2 -2
- package/dist/runtime/subsystems/{sync → integration}/deep-equal.differ.js +1 -1
- package/dist/runtime/subsystems/integration/deep-equal.differ.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/detection-config.schema.d.ts +3 -3
- package/dist/runtime/subsystems/{sync → integration}/detection-config.schema.js +1 -1
- package/dist/runtime/subsystems/integration/detection-config.schema.js.map +1 -0
- package/dist/runtime/subsystems/{sync/execute-sync.use-case.d.ts → integration/execute-integration.use-case.d.ts} +13 -13
- package/dist/runtime/subsystems/{sync/execute-sync.use-case.js → integration/execute-integration.use-case.js} +30 -30
- package/dist/runtime/subsystems/integration/execute-integration.use-case.js.map +1 -0
- package/dist/runtime/subsystems/integration/index.d.ts +28 -0
- package/dist/runtime/subsystems/{sync → integration}/index.js +171 -171
- package/dist/runtime/subsystems/integration/index.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-audit.schema.d.ts → integration/integration-audit.schema.d.ts} +64 -64
- package/dist/runtime/subsystems/{sync/sync-audit.schema.js → integration/integration-audit.schema.js} +47 -47
- package/dist/runtime/subsystems/integration/integration-audit.schema.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-change-source.protocol.d.ts → integration/integration-change-source.protocol.d.ts} +10 -10
- package/dist/runtime/subsystems/integration/integration-change-source.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.d.ts → integration/integration-cursor-store.drizzle-backend.d.ts} +1 -1
- package/dist/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.js → integration/integration-cursor-store.drizzle-backend.js} +65 -65
- package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.memory-backend.d.ts → integration/integration-cursor-store.memory-backend.d.ts} +6 -6
- package/dist/runtime/subsystems/{sync/sync-cursor-store.memory-backend.js → integration/integration-cursor-store.memory-backend.js} +5 -5
- package/dist/runtime/subsystems/integration/integration-cursor-store.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.protocol.d.ts → integration/integration-cursor-store.protocol.d.ts} +13 -13
- package/dist/runtime/subsystems/integration/integration-cursor-store.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-errors.d.ts → integration/integration-errors.d.ts} +2 -2
- package/dist/runtime/subsystems/{sync/sync-errors.js → integration/integration-errors.js} +3 -3
- package/dist/runtime/subsystems/integration/integration-errors.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-field-diff.protocol.d.ts → integration/integration-field-diff.protocol.d.ts} +2 -2
- package/dist/runtime/subsystems/{sync/sync-field-diff.protocol.js → integration/integration-field-diff.protocol.js} +2 -2
- package/dist/runtime/subsystems/integration/integration-field-diff.protocol.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-loopback.protocol.d.ts → integration/integration-loopback.protocol.d.ts} +2 -2
- package/dist/runtime/subsystems/integration/integration-loopback.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-middleware.protocol.d.ts → integration/integration-middleware.protocol.d.ts} +5 -5
- package/dist/runtime/subsystems/integration/integration-middleware.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.d.ts → integration/integration-run-recorder.drizzle-backend.d.ts} +5 -5
- package/dist/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.js → integration/integration-run-recorder.drizzle-backend.js} +73 -73
- package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.memory-backend.d.ts → integration/integration-run-recorder.memory-backend.d.ts} +15 -15
- package/dist/runtime/subsystems/{sync/sync-run-recorder.memory-backend.js → integration/integration-run-recorder.memory-backend.js} +11 -11
- package/dist/runtime/subsystems/integration/integration-run-recorder.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.protocol.d.ts → integration/integration-run-recorder.protocol.d.ts} +25 -25
- package/dist/runtime/subsystems/integration/integration-run-recorder.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-sink.protocol.d.ts → integration/integration-sink.protocol.d.ts} +5 -5
- package/dist/runtime/subsystems/integration/integration-sink.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync.module.d.ts → integration/integration.module.d.ts} +24 -24
- package/dist/runtime/subsystems/{sync/sync.module.js → integration/integration.module.js} +132 -132
- package/dist/runtime/subsystems/integration/integration.module.js.map +1 -0
- package/dist/runtime/subsystems/integration/integration.tokens.d.ts +47 -0
- package/dist/runtime/subsystems/integration/integration.tokens.js +18 -0
- package/dist/runtime/subsystems/integration/integration.tokens.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/loopback.middleware.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/loopback.middleware.js +1 -1
- package/dist/runtime/subsystems/integration/loopback.middleware.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/poll-change-source.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/poll-change-source.js +1 -1
- package/dist/runtime/subsystems/integration/poll-change-source.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/webhook-change-source.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/webhook-change-source.js +1 -1
- package/dist/runtime/subsystems/integration/webhook-change-source.js.map +1 -0
- package/dist/runtime/subsystems/jobs/bullmq.config.d.ts +22 -3
- package/dist/runtime/subsystems/jobs/bullmq.config.js.map +1 -1
- package/dist/runtime/subsystems/jobs/index.d.ts +1 -4
- package/dist/runtime/subsystems/jobs/index.js +87 -506
- package/dist/runtime/subsystems/jobs/index.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js +3 -0
- package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.module.d.ts +10 -3
- package/dist/runtime/subsystems/jobs/job-worker.module.js +248 -664
- package/dist/runtime/subsystems/jobs/job-worker.module.js.map +1 -1
- package/dist/runtime/subsystems/jobs/jobs-domain.module.d.ts +0 -1
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js +89 -391
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js.map +1 -1
- package/dist/runtime/subsystems/observability/index.d.ts +4 -4
- package/dist/runtime/subsystems/observability/index.js +11 -11
- package/dist/runtime/subsystems/observability/index.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.module.d.ts +2 -2
- package/dist/runtime/subsystems/observability/observability.module.js +11 -11
- package/dist/runtime/subsystems/observability/observability.module.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.protocol.d.ts +11 -11
- package/dist/runtime/subsystems/observability/observability.service.d.ts +6 -6
- package/dist/runtime/subsystems/observability/observability.service.js +11 -11
- package/dist/runtime/subsystems/observability/observability.service.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.tokens.d.ts +1 -1
- package/dist/runtime/subsystems/observability/observability.tokens.js.map +1 -1
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.d.ts +3 -3
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.js.map +1 -1
- package/dist/runtime/subsystems/observability/reporters/index.d.ts +3 -3
- package/dist/runtime/subsystems/observability/reporters/index.js.map +1 -1
- package/dist/src/cli/index.js +412 -302
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.d.ts +22 -22
- package/dist/src/index.js +191 -191
- package/dist/src/index.js.map +1 -1
- package/examples/auth-integrations/README.md +32 -32
- package/examples/auth-integrations/definitions/entities/{integration.yaml → connection.yaml} +10 -10
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-grant-sink.adapter.ts → connections/adapters/connection-grant-sink.adapter.ts} +7 -7
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-reader.adapter.ts → connections/adapters/connection-reader.adapter.ts} +10 -10
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-token-writer.adapter.ts → connections/adapters/connection-token-writer.adapter.ts} +11 -11
- package/examples/auth-integrations/runtime/connections/connections-auth.module.ts +81 -0
- package/examples/auth-integrations/runtime/{integrations/facade/integrations.service.ts → connections/facade/connections.service.ts} +35 -35
- package/examples/auth-integrations/runtime/{integrations → connections}/oauth/use-cases/create-or-update-from-oauth-grant.use-case.ts +11 -11
- package/examples/auth-integrations/runtime/{integrations/oauth/use-cases/disconnect-integration.use-case.ts → connections/oauth/use-cases/disconnect-connection.use-case.ts} +6 -6
- package/examples/auth-integrations/runtime/connections/oauth/use-cases/list-user-connections.use-case.ts +21 -0
- package/examples/auth-integrations/runtime/connections/oauth/use-cases/mark-connection-requires-reauth.use-case.ts +21 -0
- package/package.json +1 -1
- package/runtime/base-classes/index.ts +8 -8
- package/runtime/base-classes/{synced-entity-repository.ts → integrated-entity-repository.ts} +36 -36
- package/runtime/base-classes/{synced-entity-service.ts → integrated-entity-service.ts} +6 -6
- package/runtime/base-classes/{sync-upsert-config.ts → integration-upsert-config.ts} +12 -12
- package/runtime/base-classes/{junction-sync-repository.ts → junction-integration-repository.ts} +28 -28
- package/runtime/subsystems/auth/auth-oauth-state.schema.ts +1 -1
- package/runtime/subsystems/auth/auth.module.ts +4 -4
- package/runtime/subsystems/auth/auth.tokens.ts +7 -7
- package/runtime/subsystems/auth/controllers/auth.controller.ts +7 -7
- package/runtime/subsystems/auth/index.ts +19 -19
- package/runtime/subsystems/auth/protocols/auth-strategy.ts +3 -3
- package/runtime/subsystems/auth/protocols/{integration-store.ts → connection-store.ts} +19 -19
- package/runtime/subsystems/auth/protocols/provider-strategy.ts +2 -2
- package/runtime/subsystems/auth/runtime/{integration-broken.error.ts → connection-broken.error.ts} +5 -5
- package/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts +35 -35
- package/runtime/subsystems/auth/runtime/with-auth-retry.ts +3 -3
- package/runtime/subsystems/events/event-bus.drizzle-backend.ts +32 -10
- package/runtime/subsystems/events/events.module.ts +38 -6
- package/runtime/subsystems/events/index.ts +7 -1
- package/runtime/subsystems/index.ts +11 -11
- package/runtime/subsystems/{sync → integration}/build-change-source.ts +3 -3
- package/runtime/subsystems/{sync → integration}/deep-equal.differ.ts +7 -7
- package/runtime/subsystems/{sync → integration}/detection-config.schema.ts +3 -3
- package/runtime/subsystems/{sync/execute-sync.use-case.ts → integration/execute-integration.use-case.ts} +40 -40
- package/runtime/subsystems/{sync → integration}/index.ts +47 -47
- package/runtime/subsystems/{sync/sync-audit.schema.ts → integration/integration-audit.schema.ts} +61 -61
- package/runtime/subsystems/{sync/sync-change-source.protocol.ts → integration/integration-change-source.protocol.ts} +9 -9
- package/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.ts → integration/integration-cursor-store.drizzle-backend.ts} +30 -30
- package/runtime/subsystems/{sync/sync-cursor-store.memory-backend.ts → integration/integration-cursor-store.memory-backend.ts} +9 -9
- package/runtime/subsystems/{sync/sync-cursor-store.protocol.ts → integration/integration-cursor-store.protocol.ts} +13 -13
- package/runtime/subsystems/{sync/sync-errors.ts → integration/integration-errors.ts} +3 -3
- package/runtime/subsystems/{sync/sync-field-diff.protocol.ts → integration/integration-field-diff.protocol.ts} +2 -2
- package/runtime/subsystems/{sync/sync-loopback.protocol.ts → integration/integration-loopback.protocol.ts} +2 -2
- package/runtime/subsystems/{sync/sync-middleware.protocol.ts → integration/integration-middleware.protocol.ts} +6 -6
- package/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.ts → integration/integration-run-recorder.drizzle-backend.ts} +39 -39
- package/runtime/subsystems/{sync/sync-run-recorder.memory-backend.ts → integration/integration-run-recorder.memory-backend.ts} +23 -23
- package/runtime/subsystems/{sync/sync-run-recorder.protocol.ts → integration/integration-run-recorder.protocol.ts} +25 -25
- package/runtime/subsystems/{sync/sync-sink.protocol.ts → integration/integration-sink.protocol.ts} +4 -4
- package/runtime/subsystems/{sync/sync.module.ts → integration/integration.module.ts} +48 -48
- package/runtime/subsystems/integration/integration.tokens.ts +49 -0
- package/runtime/subsystems/{sync → integration}/loopback.middleware.ts +5 -5
- package/runtime/subsystems/{sync → integration}/poll-change-source.ts +7 -7
- package/runtime/subsystems/{sync → integration}/webhook-change-source.ts +7 -7
- package/runtime/subsystems/jobs/bullmq.config.ts +23 -3
- package/runtime/subsystems/jobs/index.ts +13 -8
- package/runtime/subsystems/jobs/job-worker.bullmq-backend.ts +5 -2
- package/runtime/subsystems/jobs/job-worker.module.ts +27 -7
- package/runtime/subsystems/jobs/jobs-domain.module.ts +27 -2
- package/runtime/subsystems/observability/index.ts +1 -1
- package/runtime/subsystems/observability/observability.module.ts +2 -2
- package/runtime/subsystems/observability/observability.protocol.ts +11 -11
- package/runtime/subsystems/observability/observability.service.ts +13 -13
- package/runtime/subsystems/observability/observability.tokens.ts +1 -1
- package/src/patterns/library/index.ts +4 -4
- package/src/patterns/library/{synced.pattern.ts → integrated.pattern.ts} +12 -12
- package/src/patterns/library/junction.pattern.ts +1 -1
- package/src/patterns/pattern-definition.ts +3 -3
- package/templates/entity/new/backend/modules/core/{sync-source.ejs.t → integration-source.ejs.t} +6 -6
- package/templates/entity/new/backend/modules/core/{sync-source.providers.ejs.t → integration-source.providers.ejs.t} +2 -2
- package/templates/entity/new/clean-lite-ps/entity.ejs.t +1 -1
- package/templates/entity/new/clean-lite-ps/module.ejs.t +1 -1
- package/templates/entity/new/clean-lite-ps/prompt-extension.js +33 -33
- package/templates/entity/new/clean-lite-ps/repository.ejs.t +27 -27
- package/templates/entity/new/frontend/collections/collection.ejs.t +26 -1
- package/templates/entity/new/frontend/collections/collections-base.ejs.t +11 -0
- package/templates/entity/new/frontend/entity/combined.ejs.t +31 -1
- package/templates/entity/new/prompt.js +27 -15
- package/templates/junction/new/entity.ejs.t +1 -1
- package/templates/junction/new/prompt.js +24 -24
- package/templates/junction/new/repository.ejs.t +19 -19
- package/templates/subsystem/auth/auth-oauth-state.schema.ejs.t +2 -2
- package/templates/subsystem/auth-config/prompt.js +1 -1
- package/templates/subsystem/auth-integrations/app-module-hook.ejs.t +5 -5
- package/templates/subsystem/bridge/prompt.js +1 -1
- package/templates/subsystem/events/domain-events.schema.ejs.t +43 -2
- package/templates/subsystem/integration/integration-audit.schema.ejs.t +192 -0
- package/templates/subsystem/{sync → integration}/prompt.js +12 -12
- package/templates/subsystem/{sync-config/codegen-config-sync-block.ejs.t → integration-config/codegen-config-integration-block.ejs.t} +7 -7
- package/templates/subsystem/integration-config/prompt.js +22 -0
- package/templates/subsystem/jobs/worker.ejs.t +2 -2
- package/templates/subsystem/observability/main-hook.ejs.t +1 -1
- package/templates/subsystem/observability/prompt.js +1 -1
- package/templates/subsystem/openapi-config/prompt.js +1 -1
- package/dist/runtime/base-classes/junction-sync-repository.js.map +0 -1
- package/dist/runtime/base-classes/sync-upsert-config.js +0 -1
- package/dist/runtime/base-classes/synced-entity-repository.js.map +0 -1
- package/dist/runtime/base-classes/synced-entity-service.js.map +0 -1
- package/dist/runtime/subsystems/auth/protocols/integration-store.js +0 -1
- package/dist/runtime/subsystems/auth/runtime/integration-broken.error.js +0 -19
- package/dist/runtime/subsystems/auth/runtime/integration-broken.error.js.map +0 -1
- package/dist/runtime/subsystems/sync/build-change-source.js.map +0 -1
- package/dist/runtime/subsystems/sync/deep-equal.differ.js.map +0 -1
- package/dist/runtime/subsystems/sync/detection-config.schema.js.map +0 -1
- package/dist/runtime/subsystems/sync/execute-sync.use-case.js.map +0 -1
- package/dist/runtime/subsystems/sync/index.d.ts +0 -28
- package/dist/runtime/subsystems/sync/index.js.map +0 -1
- package/dist/runtime/subsystems/sync/loopback.middleware.js.map +0 -1
- package/dist/runtime/subsystems/sync/poll-change-source.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-audit.schema.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-change-source.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.drizzle-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.memory-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-errors.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-field-diff.protocol.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-loopback.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-middleware.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.drizzle-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.memory-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-sink.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync.module.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync.tokens.d.ts +0 -47
- package/dist/runtime/subsystems/sync/sync.tokens.js +0 -18
- package/dist/runtime/subsystems/sync/sync.tokens.js.map +0 -1
- package/dist/runtime/subsystems/sync/webhook-change-source.js.map +0 -1
- package/examples/auth-integrations/runtime/integrations/integrations-auth.module.ts +0 -81
- package/examples/auth-integrations/runtime/integrations/oauth/use-cases/list-user-integrations.use-case.ts +0 -21
- package/examples/auth-integrations/runtime/integrations/oauth/use-cases/mark-integration-requires-reauth.use-case.ts +0 -21
- package/runtime/subsystems/sync/sync.tokens.ts +0 -49
- package/templates/subsystem/sync/sync-audit.schema.ejs.t +0 -192
- package/templates/subsystem/sync-config/prompt.js +0 -22
- /package/dist/runtime/base-classes/{sync-upsert-config.js.map → integration-upsert-config.js.map} +0 -0
- /package/dist/runtime/subsystems/auth/protocols/{integration-store.js.map → connection-store.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-change-source.protocol.js.map → integration/integration-change-source.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-cursor-store.protocol.js.map → integration/integration-cursor-store.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-loopback.protocol.js.map → integration/integration-loopback.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-middleware.protocol.js.map → integration/integration-middleware.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-run-recorder.protocol.js.map → integration/integration-run-recorder.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-sink.protocol.js.map → integration/integration-sink.protocol.js.map} +0 -0
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,19 +5999,32 @@ 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
|
}
|
|
6013
6013
|
];
|
|
6014
6014
|
var KNOWN_NAMES = SUBSYSTEMS.map((s) => s.name);
|
|
6015
|
+
var SUBSYSTEM_MODULE_FILE = {
|
|
6016
|
+
events: "events.module.ts",
|
|
6017
|
+
jobs: "jobs-domain.module.ts",
|
|
6018
|
+
cache: "cache.module.ts",
|
|
6019
|
+
storage: "storage.module.ts",
|
|
6020
|
+
integration: "integration.module.ts",
|
|
6021
|
+
bridge: "bridge.module.ts",
|
|
6022
|
+
observability: "observability.module.ts",
|
|
6023
|
+
auth: "auth.module.ts"
|
|
6024
|
+
};
|
|
6025
|
+
function subsystemModuleFile(name) {
|
|
6026
|
+
return SUBSYSTEM_MODULE_FILE[name] ?? null;
|
|
6027
|
+
}
|
|
6015
6028
|
function candidateRoots(cwd, configured) {
|
|
6016
6029
|
const roots = [
|
|
6017
6030
|
...configured ? [path6.resolve(cwd, configured)] : [],
|
|
@@ -6034,7 +6047,7 @@ function inferBackend(dir, name) {
|
|
|
6034
6047
|
if (hasMemory) return "memory";
|
|
6035
6048
|
return "unknown";
|
|
6036
6049
|
}
|
|
6037
|
-
async function
|
|
6050
|
+
async function detectSubsystemStatesImpl(ctx) {
|
|
6038
6051
|
const configured = ctx.config?.paths?.subsystems;
|
|
6039
6052
|
const roots = candidateRoots(ctx.cwd, configured);
|
|
6040
6053
|
const found = [];
|
|
@@ -6048,16 +6061,16 @@ async function detectInstalledSubsystems(ctx) {
|
|
|
6048
6061
|
const dir = path6.join(root, name);
|
|
6049
6062
|
if (!fs4.existsSync(dir) || !fs4.statSync(dir).isDirectory()) continue;
|
|
6050
6063
|
const files = fs4.readdirSync(dir);
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
if (!hasProtocol) continue;
|
|
6064
|
+
const moduleFile = subsystemModuleFile(name);
|
|
6065
|
+
const hasModule = moduleFile ? files.includes(moduleFile) : false;
|
|
6066
|
+
const present = name === "auth" ? hasModule : files.some((f) => f.endsWith(".protocol.ts")) || hasModule;
|
|
6067
|
+
if (!present) continue;
|
|
6056
6068
|
seen.add(name);
|
|
6057
6069
|
found.push({
|
|
6058
6070
|
name,
|
|
6059
6071
|
path: dir,
|
|
6060
|
-
backend: inferBackend(dir, name)
|
|
6072
|
+
backend: inferBackend(dir, name),
|
|
6073
|
+
status: hasModule ? "installed" : "incomplete"
|
|
6061
6074
|
});
|
|
6062
6075
|
}
|
|
6063
6076
|
}
|
|
@@ -6073,7 +6086,8 @@ async function detectInstalledSubsystems(ctx) {
|
|
|
6073
6086
|
found.push({
|
|
6074
6087
|
name: "openapi-config",
|
|
6075
6088
|
path: configPath,
|
|
6076
|
-
backend: "config-only"
|
|
6089
|
+
backend: "config-only",
|
|
6090
|
+
status: "installed"
|
|
6077
6091
|
});
|
|
6078
6092
|
}
|
|
6079
6093
|
} catch {
|
|
@@ -6085,18 +6099,16 @@ async function detectInstalledSubsystems(ctx) {
|
|
|
6085
6099
|
const pathsAny = ctx.config?.paths;
|
|
6086
6100
|
const modulesConfigured = pathsAny?.modules_dir;
|
|
6087
6101
|
const vendorRoot = typeof modulesConfigured === "string" && modulesConfigured.length > 0 ? path6.resolve(ctx.cwd, modulesConfigured) : path6.resolve(ctx.cwd, backendSrc, "modules");
|
|
6088
|
-
const sharedConfigured = pathsAny?.shared;
|
|
6089
|
-
const sharedRoot = typeof sharedConfigured === "string" && sharedConfigured.length > 0 ? path6.resolve(ctx.cwd, sharedConfigured) : path6.resolve(ctx.cwd, backendSrc, "shared");
|
|
6090
6102
|
const candidates = [
|
|
6091
|
-
path6.join(vendorRoot, "
|
|
6092
|
-
path6.join(sharedRoot, "integrations", "integrations-auth.module.ts")
|
|
6103
|
+
path6.join(vendorRoot, "connections", "connections-auth.module.ts")
|
|
6093
6104
|
];
|
|
6094
6105
|
for (const moduleFile of candidates) {
|
|
6095
6106
|
if (fs4.existsSync(moduleFile)) {
|
|
6096
6107
|
found.push({
|
|
6097
6108
|
name: "auth-integrations",
|
|
6098
6109
|
path: path6.dirname(moduleFile),
|
|
6099
|
-
backend: "drizzle"
|
|
6110
|
+
backend: "drizzle",
|
|
6111
|
+
status: "installed"
|
|
6100
6112
|
});
|
|
6101
6113
|
break;
|
|
6102
6114
|
}
|
|
@@ -6104,6 +6116,13 @@ async function detectInstalledSubsystems(ctx) {
|
|
|
6104
6116
|
}
|
|
6105
6117
|
return found;
|
|
6106
6118
|
}
|
|
6119
|
+
async function detectSubsystemStates(ctx) {
|
|
6120
|
+
return detectSubsystemStatesImpl(ctx);
|
|
6121
|
+
}
|
|
6122
|
+
async function detectInstalledSubsystems(ctx) {
|
|
6123
|
+
const states = await detectSubsystemStatesImpl(ctx);
|
|
6124
|
+
return states.filter((s) => s.status === "installed");
|
|
6125
|
+
}
|
|
6107
6126
|
|
|
6108
6127
|
// src/cli/shared/subsystems-path.ts
|
|
6109
6128
|
import path7 from "path";
|
|
@@ -6195,24 +6214,24 @@ var COMPOSERS = {
|
|
|
6195
6214
|
]
|
|
6196
6215
|
};
|
|
6197
6216
|
},
|
|
6198
|
-
|
|
6217
|
+
integration: ({ subsystemsRel, cfg }) => {
|
|
6199
6218
|
const backend = cfg?.backend ?? "drizzle";
|
|
6200
6219
|
const multiTenant = Boolean(cfg?.multi_tenant);
|
|
6201
6220
|
return {
|
|
6202
6221
|
imports: [
|
|
6203
|
-
`import {
|
|
6222
|
+
`import { IntegrationModule } from '${subsystemsRel}/integration/integration.module';`
|
|
6204
6223
|
],
|
|
6205
6224
|
calls: [
|
|
6206
|
-
`
|
|
6225
|
+
` IntegrationModule.forRoot(${quoteOpts({ backend, multiTenant })}),`
|
|
6207
6226
|
]
|
|
6208
6227
|
};
|
|
6209
6228
|
}
|
|
6210
6229
|
};
|
|
6211
|
-
var COMPOSABLE_ORDER = ["events", "jobs", "bridge", "
|
|
6230
|
+
var COMPOSABLE_ORDER = ["events", "jobs", "bridge", "integration"];
|
|
6212
6231
|
var HEADER3 = `// AUTO-GENERATED by @pattern-stack/codegen. DO NOT EDIT.
|
|
6213
6232
|
// Subsystem composition barrel \u2014 reflects \`subsystems.install\` in
|
|
6214
6233
|
// codegen.config.yaml and the per-subsystem option blocks
|
|
6215
|
-
// (\`events:\`, \`jobs:\`, \`bridge:\`, \`
|
|
6234
|
+
// (\`events:\`, \`jobs:\`, \`bridge:\`, \`integration:\`).
|
|
6216
6235
|
//
|
|
6217
6236
|
// Wire into AppModule once:
|
|
6218
6237
|
//
|
|
@@ -6223,7 +6242,8 @@ var HEADER3 = `// AUTO-GENERATED by @pattern-stack/codegen. DO NOT EDIT.
|
|
|
6223
6242
|
|
|
6224
6243
|
`;
|
|
6225
6244
|
function buildSubsystemBarrel(installed, config, subsystemsRel) {
|
|
6226
|
-
const
|
|
6245
|
+
const actable = installed.filter((i) => i.status !== "incomplete");
|
|
6246
|
+
const installedNames = new Set(actable.map((i) => i.name));
|
|
6227
6247
|
const emitted = [];
|
|
6228
6248
|
const skipped = [];
|
|
6229
6249
|
const allImports = [`import type { DynamicModule } from '@nestjs/common';`];
|
|
@@ -6241,25 +6261,17 @@ function buildSubsystemBarrel(installed, config, subsystemsRel) {
|
|
|
6241
6261
|
allCalls.push(...out.calls);
|
|
6242
6262
|
emitted.push(name);
|
|
6243
6263
|
}
|
|
6244
|
-
for (const inst of
|
|
6264
|
+
for (const inst of actable) {
|
|
6245
6265
|
if (!COMPOSABLE_ORDER.includes(inst.name) && !COMPOSERS[inst.name]) {
|
|
6246
6266
|
skipped.push(inst.name);
|
|
6247
6267
|
}
|
|
6248
6268
|
}
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
content: HEADER3 + `export const SUBSYSTEM_MODULES: DynamicModule[] = [];
|
|
6252
|
-
`,
|
|
6253
|
-
emitted,
|
|
6254
|
-
skipped
|
|
6255
|
-
};
|
|
6256
|
-
}
|
|
6257
|
-
const body = allImports.join("\n") + `
|
|
6258
|
-
|
|
6259
|
-
export const SUBSYSTEM_MODULES: DynamicModule[] = [
|
|
6269
|
+
const exportLine = allCalls.length === 0 ? `export const SUBSYSTEM_MODULES: DynamicModule[] = [];
|
|
6270
|
+
` : `export const SUBSYSTEM_MODULES: DynamicModule[] = [
|
|
6260
6271
|
${allCalls.join("\n")}
|
|
6261
6272
|
];
|
|
6262
6273
|
`;
|
|
6274
|
+
const body = allImports.join("\n") + "\n\n" + exportLine;
|
|
6263
6275
|
return { content: HEADER3 + body, emitted, skipped };
|
|
6264
6276
|
}
|
|
6265
6277
|
async function regenerateSubsystemBarrel(opts) {
|
|
@@ -8612,22 +8624,22 @@ function localsToHygenArgs2(locals) {
|
|
|
8612
8624
|
];
|
|
8613
8625
|
}
|
|
8614
8626
|
|
|
8615
|
-
// src/cli/shared/
|
|
8627
|
+
// src/cli/shared/integration-scaffold-locals.ts
|
|
8616
8628
|
import path16 from "path";
|
|
8617
|
-
function
|
|
8629
|
+
function resolveIntegrationScaffoldLocals(input) {
|
|
8618
8630
|
const { cwd, config } = input;
|
|
8619
8631
|
void input.fileExists;
|
|
8620
|
-
const
|
|
8632
|
+
const integrationBlock = config?.integration ?? {};
|
|
8621
8633
|
const subsystemsRoot = resolveSubsystemsRootFromConfig(cwd, config);
|
|
8622
8634
|
const configPath = path16.resolve(cwd, "codegen.config.yaml");
|
|
8623
8635
|
const schemaPath = path16.resolve(
|
|
8624
8636
|
subsystemsRoot,
|
|
8625
|
-
"
|
|
8626
|
-
"
|
|
8637
|
+
"integration",
|
|
8638
|
+
"integration-audit.schema.ts"
|
|
8627
8639
|
);
|
|
8628
8640
|
return {
|
|
8629
8641
|
appName: path16.basename(cwd),
|
|
8630
|
-
multiTenant: normaliseMultiTenant3(
|
|
8642
|
+
multiTenant: normaliseMultiTenant3(integrationBlock.multi_tenant),
|
|
8631
8643
|
configPath,
|
|
8632
8644
|
schemaPath
|
|
8633
8645
|
};
|
|
@@ -8766,19 +8778,16 @@ function localsToHygenArgs6(locals) {
|
|
|
8766
8778
|
// src/cli/shared/auth-integrations-scaffold-locals.ts
|
|
8767
8779
|
import path20 from "path";
|
|
8768
8780
|
var FALLBACK_BACKEND_SRC4 = "src";
|
|
8769
|
-
var SHARED_DIR_NAME = "shared";
|
|
8770
8781
|
var DEFAULT_MODULES_DIR = "modules";
|
|
8771
8782
|
var DEFAULT_DEFINITIONS_DIR = "definitions/entities";
|
|
8772
8783
|
function resolveAuthIntegrationsScaffoldLocals(input) {
|
|
8773
8784
|
const { cwd, config } = input;
|
|
8774
8785
|
const backendSrc = typeof config?.paths?.backend_src === "string" && config.paths.backend_src.length > 0 ? config.paths.backend_src : FALLBACK_BACKEND_SRC4;
|
|
8775
8786
|
const pathsAny = config?.paths;
|
|
8776
|
-
const sharedConfigured = pathsAny?.shared;
|
|
8777
|
-
const sharedRoot = typeof sharedConfigured === "string" && sharedConfigured.length > 0 ? path20.resolve(cwd, sharedConfigured) : path20.resolve(cwd, backendSrc, SHARED_DIR_NAME);
|
|
8778
8787
|
const modulesConfigured = pathsAny?.modules_dir;
|
|
8779
8788
|
const vendorRoot = typeof modulesConfigured === "string" && modulesConfigured.length > 0 ? path20.resolve(cwd, modulesConfigured) : path20.resolve(cwd, backendSrc, DEFAULT_MODULES_DIR);
|
|
8780
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;
|
|
8781
|
-
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");
|
|
8782
8791
|
const appModulePath = path20.resolve(cwd, backendSrc, "app.module.ts");
|
|
8783
8792
|
let authModuleRegistered = false;
|
|
8784
8793
|
const appModuleSource = input.readFile(appModulePath);
|
|
@@ -8788,7 +8797,6 @@ function resolveAuthIntegrationsScaffoldLocals(input) {
|
|
|
8788
8797
|
return {
|
|
8789
8798
|
appName: path20.basename(cwd),
|
|
8790
8799
|
appModulePath,
|
|
8791
|
-
sharedRoot,
|
|
8792
8800
|
vendorRoot,
|
|
8793
8801
|
definitionsPath,
|
|
8794
8802
|
authModuleRegistered
|
|
@@ -8987,12 +8995,14 @@ function backendFileFilter(backend, subsystemName) {
|
|
|
8987
8995
|
if (subsystemName === "events" && file === "domain-events.schema.ts") {
|
|
8988
8996
|
return false;
|
|
8989
8997
|
}
|
|
8990
|
-
if (subsystemName === "
|
|
8998
|
+
if (subsystemName === "integration" && file === "integration-audit.schema.ts") {
|
|
8991
8999
|
return false;
|
|
8992
9000
|
}
|
|
8993
9001
|
if (subsystemName === "auth" && file === "auth-oauth-state.schema.ts") {
|
|
8994
9002
|
return false;
|
|
8995
9003
|
}
|
|
9004
|
+
if (file.endsWith(".redis-backend.ts") && backend !== "redis") return false;
|
|
9005
|
+
if (file.endsWith(".bullmq-backend.ts") && backend !== "bullmq") return false;
|
|
8996
9006
|
if (backend === "memory") {
|
|
8997
9007
|
if (file.endsWith(".drizzle-backend.ts")) return false;
|
|
8998
9008
|
if (file.endsWith(".schema.ts")) return false;
|
|
@@ -9109,7 +9119,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9109
9119
|
json: isJsonMode(),
|
|
9110
9120
|
forceConfig: this.forceConfig
|
|
9111
9121
|
}) : null;
|
|
9112
|
-
const
|
|
9122
|
+
const integrationScaffold = desc3.name === "integration" ? runIntegrationScaffold(ctx.cwd, ctx.config, {
|
|
9113
9123
|
dryRun: this.dryRun,
|
|
9114
9124
|
json: isJsonMode(),
|
|
9115
9125
|
forceConfig: this.forceConfig
|
|
@@ -9141,9 +9151,9 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9141
9151
|
);
|
|
9142
9152
|
return 1;
|
|
9143
9153
|
}
|
|
9144
|
-
if (
|
|
9154
|
+
if (integrationScaffold?.configBlockOutcome === "parse-error") {
|
|
9145
9155
|
printError(
|
|
9146
|
-
"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."
|
|
9147
9157
|
);
|
|
9148
9158
|
return 1;
|
|
9149
9159
|
}
|
|
@@ -9181,7 +9191,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9181
9191
|
},
|
|
9182
9192
|
...jobsScaffold ? { scaffold: jobsScaffold } : {},
|
|
9183
9193
|
...eventsScaffold ? { scaffold: eventsScaffold } : {},
|
|
9184
|
-
...
|
|
9194
|
+
...integrationScaffold ? { scaffold: integrationScaffold } : {},
|
|
9185
9195
|
...bridgeScaffold ? { scaffold: bridgeScaffold } : {},
|
|
9186
9196
|
...observabilityScaffold ? { scaffold: observabilityScaffold } : {},
|
|
9187
9197
|
...authScaffold ? { scaffold: authScaffold } : {}
|
|
@@ -9209,11 +9219,11 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9209
9219
|
console.log(` ${theme.muted(icons.arrow)} ${path22.relative(ctx.cwd, p) || p}`);
|
|
9210
9220
|
}
|
|
9211
9221
|
}
|
|
9212
|
-
if (
|
|
9222
|
+
if (integrationScaffold?.planned?.length) {
|
|
9213
9223
|
printInfo(
|
|
9214
|
-
`
|
|
9224
|
+
`Integration scaffold \u2014 ${integrationScaffold.planned.length} template targets`
|
|
9215
9225
|
);
|
|
9216
|
-
for (const p of
|
|
9226
|
+
for (const p of integrationScaffold.planned) {
|
|
9217
9227
|
console.log(` ${theme.muted(icons.arrow)} ${path22.relative(ctx.cwd, p) || p}`);
|
|
9218
9228
|
}
|
|
9219
9229
|
}
|
|
@@ -9272,14 +9282,14 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9272
9282
|
);
|
|
9273
9283
|
}
|
|
9274
9284
|
}
|
|
9275
|
-
if (
|
|
9276
|
-
if (
|
|
9285
|
+
if (integrationScaffold) {
|
|
9286
|
+
if (integrationScaffold.ok) {
|
|
9277
9287
|
printSuccess(
|
|
9278
|
-
`
|
|
9288
|
+
`integration scaffold applied (config block, schema)`
|
|
9279
9289
|
);
|
|
9280
9290
|
} else {
|
|
9281
9291
|
printWarning(
|
|
9282
|
-
`
|
|
9292
|
+
`integration scaffold (Hygen) failed \u2014 runtime files were written; re-run after fixing: ${integrationScaffold.error ?? "unknown error"}`
|
|
9283
9293
|
);
|
|
9284
9294
|
}
|
|
9285
9295
|
}
|
|
@@ -9326,7 +9336,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9326
9336
|
}
|
|
9327
9337
|
if (desc3.name === "observability") {
|
|
9328
9338
|
printInfo(
|
|
9329
|
-
"Register `ObservabilityModule.forRoot()` AFTER Events/Jobs/Bridge/
|
|
9339
|
+
"Register `ObservabilityModule.forRoot()` AFTER Events/Jobs/Bridge/Integration in app.module.ts"
|
|
9330
9340
|
);
|
|
9331
9341
|
} else if (desc3.name === "auth") {
|
|
9332
9342
|
printInfo("auth subsystem installed.");
|
|
@@ -9340,9 +9350,9 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9340
9350
|
`Register ${capitalize(desc3.name)}Module.forRoot({ backend: '${backend}' }) in your app.module.ts`
|
|
9341
9351
|
);
|
|
9342
9352
|
}
|
|
9343
|
-
if (desc3.name === "
|
|
9353
|
+
if (desc3.name === "integration") {
|
|
9344
9354
|
printInfo(
|
|
9345
|
-
`Per-entity: register
|
|
9355
|
+
`Per-entity: register ExecuteIntegrationUseCase + your IChangeSource/IIntegrationSink bindings in a feature module (see IntegrationModule docstring).`
|
|
9346
9356
|
);
|
|
9347
9357
|
}
|
|
9348
9358
|
return 0;
|
|
@@ -9355,7 +9365,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9355
9365
|
* `codegen project init`. This method just invokes the
|
|
9356
9366
|
* `subsystem/openapi-config` Hygen action to inject the `openapi:`
|
|
9357
9367
|
* block into `codegen.config.yaml`, honoring the same `--force-config`
|
|
9358
|
-
* semantics as jobs/events/
|
|
9368
|
+
* semantics as jobs/events/integration/bridge.
|
|
9359
9369
|
*/
|
|
9360
9370
|
async executeOpenApiConfig(ctx) {
|
|
9361
9371
|
const configPath = path22.join(ctx.cwd, "codegen.config.yaml");
|
|
@@ -9418,9 +9428,9 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9418
9428
|
*
|
|
9419
9429
|
* Source is `examples/auth-integrations/`, NOT `runtime/subsystems/`,
|
|
9420
9430
|
* so this method short-circuits the `copyRuntime` flow. It vendors the
|
|
9421
|
-
* adapters tree + the canonical `
|
|
9431
|
+
* adapters tree + the canonical `connection.yaml`, then invokes the
|
|
9422
9432
|
* `subsystem auth-integrations` Hygen action to append the
|
|
9423
|
-
* `
|
|
9433
|
+
* `ConnectionsAuthModule` TODO to `app.module.ts`.
|
|
9424
9434
|
*
|
|
9425
9435
|
* Idempotent: pre-existing files are skipped unless `--force` is set.
|
|
9426
9436
|
*/
|
|
@@ -9468,7 +9478,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9468
9478
|
}
|
|
9469
9479
|
if (this.dryRun) {
|
|
9470
9480
|
printInfo(
|
|
9471
|
-
`Dry run \u2014 auth-integrations would vendor adapters +
|
|
9481
|
+
`Dry run \u2014 auth-integrations would vendor adapters + connection.yaml + append TODO`
|
|
9472
9482
|
);
|
|
9473
9483
|
for (const p of scaffold.planned) {
|
|
9474
9484
|
console.log(
|
|
@@ -9484,14 +9494,14 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
9484
9494
|
);
|
|
9485
9495
|
if (scaffold.authModuleRegistered === false) {
|
|
9486
9496
|
printWarning(
|
|
9487
|
-
"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."
|
|
9488
9498
|
);
|
|
9489
9499
|
}
|
|
9490
9500
|
printInfo("auth-integrations starter vendored.");
|
|
9491
9501
|
printInfo("Next steps:");
|
|
9492
|
-
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.");
|
|
9493
9503
|
printInfo(" 2. Ensure AuthModule.forRoot(...) is registered in AppModule (run `cdp subsystem install auth` if not).");
|
|
9494
|
-
printInfo(" 3. Wire
|
|
9504
|
+
printInfo(" 3. Wire ConnectionsAuthModule into AppModule (see TODO appended to app.module.ts).");
|
|
9495
9505
|
return 0;
|
|
9496
9506
|
}
|
|
9497
9507
|
};
|
|
@@ -9672,8 +9682,8 @@ function runEventsScaffold(cwd, config, opts) {
|
|
|
9672
9682
|
}
|
|
9673
9683
|
return { ok: true, planned, configBlockOutcome };
|
|
9674
9684
|
}
|
|
9675
|
-
function
|
|
9676
|
-
const locals =
|
|
9685
|
+
function runIntegrationScaffold(cwd, config, opts) {
|
|
9686
|
+
const locals = resolveIntegrationScaffoldLocals({
|
|
9677
9687
|
cwd,
|
|
9678
9688
|
config,
|
|
9679
9689
|
fileExists: (p) => fs11.existsSync(p)
|
|
@@ -9684,7 +9694,7 @@ function runSyncScaffold(cwd, config, opts) {
|
|
|
9684
9694
|
];
|
|
9685
9695
|
const configBlockOutcome = planConfigBlockAction(
|
|
9686
9696
|
locals.configPath,
|
|
9687
|
-
"
|
|
9697
|
+
"integration",
|
|
9688
9698
|
opts.forceConfig
|
|
9689
9699
|
);
|
|
9690
9700
|
if (configBlockOutcome === "parse-error") {
|
|
@@ -9695,7 +9705,7 @@ function runSyncScaffold(cwd, config, opts) {
|
|
|
9695
9705
|
}
|
|
9696
9706
|
const result = invokeHygen({
|
|
9697
9707
|
generator: "subsystem",
|
|
9698
|
-
action: "
|
|
9708
|
+
action: "integration",
|
|
9699
9709
|
cwd,
|
|
9700
9710
|
args: localsToHygenArgs3(locals),
|
|
9701
9711
|
// Suppress Hygen stdout in JSON mode so it doesn't corrupt the JSON output.
|
|
@@ -9711,9 +9721,9 @@ function runSyncScaffold(cwd, config, opts) {
|
|
|
9711
9721
|
}
|
|
9712
9722
|
const configResult = runConfigBlockAction({
|
|
9713
9723
|
cwd,
|
|
9714
|
-
actionFolder: "
|
|
9724
|
+
actionFolder: "integration-config",
|
|
9715
9725
|
configPath: locals.configPath,
|
|
9716
|
-
subsystem: "
|
|
9726
|
+
subsystem: "integration",
|
|
9717
9727
|
outcome: configBlockOutcome,
|
|
9718
9728
|
json: opts.json
|
|
9719
9729
|
});
|
|
@@ -9964,18 +9974,18 @@ function runAuthIntegrationsScaffold(cwd, config, opts) {
|
|
|
9964
9974
|
error: `auth-integrations starter source missing: ${examplesRoot}`
|
|
9965
9975
|
};
|
|
9966
9976
|
}
|
|
9967
|
-
const adaptersSrc = path22.join(examplesRoot, "runtime", "
|
|
9968
|
-
const adaptersDest = path22.join(locals.vendorRoot, "
|
|
9969
|
-
const
|
|
9977
|
+
const adaptersSrc = path22.join(examplesRoot, "runtime", "connections");
|
|
9978
|
+
const adaptersDest = path22.join(locals.vendorRoot, "connections");
|
|
9979
|
+
const connectionYamlSrc = path22.join(
|
|
9970
9980
|
examplesRoot,
|
|
9971
9981
|
"definitions",
|
|
9972
9982
|
"entities",
|
|
9973
|
-
"
|
|
9983
|
+
"connection.yaml"
|
|
9974
9984
|
);
|
|
9975
|
-
const
|
|
9985
|
+
const connectionYamlDest = locals.definitionsPath;
|
|
9976
9986
|
const planned = [
|
|
9977
9987
|
adaptersDest,
|
|
9978
|
-
|
|
9988
|
+
connectionYamlDest,
|
|
9979
9989
|
locals.appModulePath
|
|
9980
9990
|
];
|
|
9981
9991
|
if (opts.dryRun) {
|
|
@@ -9995,18 +10005,18 @@ function runAuthIntegrationsScaffold(cwd, config, opts) {
|
|
|
9995
10005
|
let yamlWritten = false;
|
|
9996
10006
|
let yamlSkipped = false;
|
|
9997
10007
|
try {
|
|
9998
|
-
if (fs11.existsSync(
|
|
10008
|
+
if (fs11.existsSync(connectionYamlDest) && !opts.force) {
|
|
9999
10009
|
yamlSkipped = true;
|
|
10000
|
-
} else if (fs11.existsSync(
|
|
10001
|
-
fs11.mkdirSync(path22.dirname(
|
|
10002
|
-
fs11.copyFileSync(
|
|
10010
|
+
} else if (fs11.existsSync(connectionYamlSrc)) {
|
|
10011
|
+
fs11.mkdirSync(path22.dirname(connectionYamlDest), { recursive: true });
|
|
10012
|
+
fs11.copyFileSync(connectionYamlSrc, connectionYamlDest);
|
|
10003
10013
|
yamlWritten = true;
|
|
10004
10014
|
}
|
|
10005
10015
|
} catch (err) {
|
|
10006
10016
|
return {
|
|
10007
10017
|
ok: false,
|
|
10008
10018
|
planned,
|
|
10009
|
-
error: `failed to vendor
|
|
10019
|
+
error: `failed to vendor connection.yaml: ${err instanceof Error ? err.message : String(err)}`,
|
|
10010
10020
|
authModuleRegistered: locals.authModuleRegistered
|
|
10011
10021
|
};
|
|
10012
10022
|
}
|
|
@@ -10022,16 +10032,16 @@ function runAuthIntegrationsScaffold(cwd, config, opts) {
|
|
|
10022
10032
|
ok: false,
|
|
10023
10033
|
planned,
|
|
10024
10034
|
error: result.stderr?.trim() || "hygen exited non-zero",
|
|
10025
|
-
written: adapterCopy.written.concat(yamlWritten ? [
|
|
10026
|
-
skipped: adapterCopy.skipped.concat(yamlSkipped ? [
|
|
10035
|
+
written: adapterCopy.written.concat(yamlWritten ? [connectionYamlDest] : []),
|
|
10036
|
+
skipped: adapterCopy.skipped.concat(yamlSkipped ? [connectionYamlDest] : []),
|
|
10027
10037
|
authModuleRegistered: locals.authModuleRegistered
|
|
10028
10038
|
};
|
|
10029
10039
|
}
|
|
10030
10040
|
return {
|
|
10031
10041
|
ok: true,
|
|
10032
10042
|
planned,
|
|
10033
|
-
written: adapterCopy.written.concat(yamlWritten ? [
|
|
10034
|
-
skipped: adapterCopy.skipped.concat(yamlSkipped ? [
|
|
10043
|
+
written: adapterCopy.written.concat(yamlWritten ? [connectionYamlDest] : []),
|
|
10044
|
+
skipped: adapterCopy.skipped.concat(yamlSkipped ? [connectionYamlDest] : []),
|
|
10035
10045
|
authModuleRegistered: locals.authModuleRegistered
|
|
10036
10046
|
};
|
|
10037
10047
|
}
|
|
@@ -10055,14 +10065,14 @@ var SubsystemListCommand = class extends Command3 {
|
|
|
10055
10065
|
json: this.json,
|
|
10056
10066
|
skipDetection: true
|
|
10057
10067
|
});
|
|
10058
|
-
const
|
|
10068
|
+
const states = await detectSubsystemStates(ctx);
|
|
10059
10069
|
const byName = /* @__PURE__ */ new Map();
|
|
10060
|
-
for (const i of
|
|
10070
|
+
for (const i of states) byName.set(i.name, i);
|
|
10061
10071
|
const rows = SUBSYSTEMS.map((s) => {
|
|
10062
10072
|
const inst = byName.get(s.name);
|
|
10063
10073
|
return {
|
|
10064
10074
|
name: s.name,
|
|
10065
|
-
status: inst ?
|
|
10075
|
+
status: inst ? inst.status : "available",
|
|
10066
10076
|
backend: inst ? inst.backend : null,
|
|
10067
10077
|
path: inst ? path22.relative(ctx.cwd, inst.path) || inst.path : null
|
|
10068
10078
|
};
|
|
@@ -10086,29 +10096,129 @@ var SubsystemListCommand = class extends Command3 {
|
|
|
10086
10096
|
var SubsystemRemoveCommand = class extends Command3 {
|
|
10087
10097
|
static paths = [["subsystem", "remove"]];
|
|
10088
10098
|
static usage = Command3.Usage({
|
|
10089
|
-
description: "Remove a subsystem
|
|
10099
|
+
description: "Remove a vendored subsystem",
|
|
10100
|
+
examples: [
|
|
10101
|
+
["Remove the jobs subsystem", "codegen subsystem remove jobs"],
|
|
10102
|
+
[
|
|
10103
|
+
"Skip the git-safety check (uncommitted edits will be lost)",
|
|
10104
|
+
"codegen subsystem remove jobs --force"
|
|
10105
|
+
],
|
|
10106
|
+
["Non-interactive parity with install", "codegen subsystem remove jobs --yes"]
|
|
10107
|
+
]
|
|
10090
10108
|
});
|
|
10091
10109
|
name = Option3.String({ required: true });
|
|
10110
|
+
// #7: parity with `subsystem install` so a non-interactive caller can pass
|
|
10111
|
+
// the same flag set across install/remove. Accepted but currently a no-op
|
|
10112
|
+
// (remove has no interactive prompt yet); kept for forward-compatibility.
|
|
10113
|
+
yes = Option3.Boolean("--yes,-y", false);
|
|
10114
|
+
force = Option3.Boolean("--force", false);
|
|
10092
10115
|
json = Option3.Boolean("--json", false);
|
|
10093
10116
|
cwd = Option3.String("--cwd", { required: false });
|
|
10094
10117
|
configPath = Option3.String("--config", { required: false });
|
|
10095
10118
|
async execute() {
|
|
10096
10119
|
if (this.json) setJsonMode(true);
|
|
10120
|
+
const ctx = await loadContext({
|
|
10121
|
+
cwd: this.cwd,
|
|
10122
|
+
configPath: this.configPath,
|
|
10123
|
+
json: this.json,
|
|
10124
|
+
skipDetection: true
|
|
10125
|
+
});
|
|
10126
|
+
const desc3 = describeSubsystem(this.name);
|
|
10127
|
+
if (!desc3) {
|
|
10128
|
+
printError(
|
|
10129
|
+
`Unknown subsystem '${this.name}'. Known: ${SUBSYSTEMS.map((s) => s.name).join(", ")}`
|
|
10130
|
+
);
|
|
10131
|
+
return 2;
|
|
10132
|
+
}
|
|
10133
|
+
if (desc3.name === "openapi-config") {
|
|
10134
|
+
printError(
|
|
10135
|
+
"openapi-config has no vendored runtime to remove \u2014 it's a config-only pseudo-subsystem."
|
|
10136
|
+
);
|
|
10137
|
+
printInfo(
|
|
10138
|
+
"To uninstall: delete the `openapi:` block from codegen.config.yaml and uninstall the @nestjs/swagger / @anatine/zod-openapi peer deps."
|
|
10139
|
+
);
|
|
10140
|
+
return 1;
|
|
10141
|
+
}
|
|
10142
|
+
if (desc3.name === "auth-integrations") {
|
|
10143
|
+
printError(
|
|
10144
|
+
"auth-integrations is vendored under <modules>/integrations/ alongside the codegen-emitted entity layer \u2014 not auto-removable here."
|
|
10145
|
+
);
|
|
10146
|
+
printInfo(
|
|
10147
|
+
"To uninstall: remove the integrations/ directory and the ConnectionsAuthModule registration from app.module.ts by hand."
|
|
10148
|
+
);
|
|
10149
|
+
return 1;
|
|
10150
|
+
}
|
|
10151
|
+
const installed = await detectInstalledSubsystems(ctx);
|
|
10152
|
+
const target = installed.find((i) => i.name === desc3.name);
|
|
10153
|
+
if (!target) {
|
|
10154
|
+
if (isJsonMode()) {
|
|
10155
|
+
printJson({
|
|
10156
|
+
command: "subsystem remove",
|
|
10157
|
+
subsystem: desc3.name,
|
|
10158
|
+
status: "not-installed"
|
|
10159
|
+
});
|
|
10160
|
+
} else {
|
|
10161
|
+
printError(`${desc3.name} is not installed \u2014 nothing to remove.`);
|
|
10162
|
+
}
|
|
10163
|
+
return 1;
|
|
10164
|
+
}
|
|
10165
|
+
const subsystemDir = target.path;
|
|
10166
|
+
if (!fs11.existsSync(subsystemDir)) {
|
|
10167
|
+
printError(
|
|
10168
|
+
`Detected install at ${subsystemDir} but the directory is gone \u2014 refusing to act.`
|
|
10169
|
+
);
|
|
10170
|
+
return 1;
|
|
10171
|
+
}
|
|
10172
|
+
if (!this.force) {
|
|
10173
|
+
const rel2 = path22.relative(ctx.cwd, subsystemDir) || subsystemDir;
|
|
10174
|
+
const gitCheck = checkGitSafety([rel2], ctx.cwd);
|
|
10175
|
+
if (gitCheck.inRepo && !gitCheck.clean) {
|
|
10176
|
+
printWarning(
|
|
10177
|
+
`Uncommitted changes under ${subsystemDir}. Pass --force to delete anyway.`
|
|
10178
|
+
);
|
|
10179
|
+
if (!isJsonMode()) return 1;
|
|
10180
|
+
}
|
|
10181
|
+
}
|
|
10182
|
+
try {
|
|
10183
|
+
fs11.rmSync(subsystemDir, { recursive: true, force: true });
|
|
10184
|
+
} catch (err) {
|
|
10185
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
10186
|
+
printError(`Failed to remove ${subsystemDir}: ${message}`);
|
|
10187
|
+
return 1;
|
|
10188
|
+
}
|
|
10189
|
+
let barrelRegenerated = false;
|
|
10190
|
+
try {
|
|
10191
|
+
const generatedDir = resolveGeneratedDir(ctx);
|
|
10192
|
+
await regenerateSubsystemBarrel({ ctx, generatedDir });
|
|
10193
|
+
barrelRegenerated = true;
|
|
10194
|
+
} catch (err) {
|
|
10195
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
10196
|
+
printWarning(`subsystem barrel regeneration failed \u2014 ${msg}`);
|
|
10197
|
+
}
|
|
10097
10198
|
if (isJsonMode()) {
|
|
10098
10199
|
printJson({
|
|
10099
10200
|
command: "subsystem remove",
|
|
10100
|
-
|
|
10101
|
-
|
|
10201
|
+
subsystem: desc3.name,
|
|
10202
|
+
status: "removed",
|
|
10203
|
+
path: subsystemDir,
|
|
10204
|
+
barrelRegenerated
|
|
10102
10205
|
});
|
|
10103
|
-
return
|
|
10206
|
+
return 0;
|
|
10104
10207
|
}
|
|
10105
|
-
|
|
10106
|
-
|
|
10107
|
-
theme.muted(
|
|
10108
|
-
" Manually delete the subsystem directory and remove the module\n registration from your app.module.ts."
|
|
10109
|
-
)
|
|
10208
|
+
printSuccess(
|
|
10209
|
+
`${desc3.name} subsystem removed (${path22.relative(ctx.cwd, subsystemDir) || subsystemDir}).`
|
|
10110
10210
|
);
|
|
10111
|
-
|
|
10211
|
+
if (barrelRegenerated) {
|
|
10212
|
+
printInfo("Regenerated <generated>/subsystems.ts barrel.");
|
|
10213
|
+
}
|
|
10214
|
+
printInfo("Next steps (manual):");
|
|
10215
|
+
printInfo(
|
|
10216
|
+
` 1. Remove the \`${capitalize(desc3.name)}Module.forRoot(...)\` registration from app.module.ts.`
|
|
10217
|
+
);
|
|
10218
|
+
printInfo(
|
|
10219
|
+
` 2. Remove the \`${desc3.name}:\` block from codegen.config.yaml (if you no longer want it).`
|
|
10220
|
+
);
|
|
10221
|
+
return 0;
|
|
10112
10222
|
}
|
|
10113
10223
|
};
|
|
10114
10224
|
var subsystemNoun = {
|
|
@@ -10153,11 +10263,11 @@ var VENDORED_RUNTIME_FILES = [
|
|
|
10153
10263
|
// Ambient tenant scope — imported by base-repository.ts (scopePredicate)
|
|
10154
10264
|
{ runtime: "base-classes/tenant-context.ts", target: "src/shared/base-classes/tenant-context.ts" },
|
|
10155
10265
|
{ runtime: "base-classes/base-service.ts", target: "src/shared/base-classes/base-service.ts" },
|
|
10156
|
-
{ runtime: "base-classes/
|
|
10157
|
-
{ runtime: "base-classes/
|
|
10158
|
-
// Inbound-
|
|
10159
|
-
{ runtime: "base-classes/
|
|
10160
|
-
{ 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" },
|
|
10161
10271
|
{ runtime: "base-classes/activity-entity-repository.ts", target: "src/shared/base-classes/activity-entity-repository.ts" },
|
|
10162
10272
|
{ runtime: "base-classes/activity-entity-service.ts", target: "src/shared/base-classes/activity-entity-service.ts" },
|
|
10163
10273
|
{ runtime: "base-classes/metadata-entity-repository.ts", target: "src/shared/base-classes/metadata-entity-repository.ts" },
|
|
@@ -10422,7 +10532,7 @@ function exampleEntityYaml() {
|
|
|
10422
10532
|
#
|
|
10423
10533
|
# entity:
|
|
10424
10534
|
# name: account
|
|
10425
|
-
# pattern:
|
|
10535
|
+
# pattern: Integrated # Base | Integrated | Activity | Metadata | Knowledge (or app-defined)
|
|
10426
10536
|
#
|
|
10427
10537
|
# fields:
|
|
10428
10538
|
# name:
|