@pattern-stack/codegen 0.10.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +122 -0
- package/README.md +5 -5
- package/consumer-skills/codegen/SKILL.md +2 -2
- package/consumer-skills/{sync → integration}/SKILL.md +29 -29
- package/consumer-skills/{sync → integration}/audit-and-detection.md +22 -22
- package/consumer-skills/{sync → integration}/change-sources-and-sinks.md +60 -60
- package/consumer-skills/subsystems/SKILL.md +8 -8
- package/consumer-skills/subsystems/wiring-and-order.md +7 -7
- package/dist/runtime/base-classes/index.d.ts +4 -4
- package/dist/runtime/base-classes/index.js +35 -35
- package/dist/runtime/base-classes/index.js.map +1 -1
- package/dist/runtime/base-classes/{synced-entity-repository.d.ts → integrated-entity-repository.d.ts} +15 -15
- package/dist/runtime/base-classes/{synced-entity-repository.js → integrated-entity-repository.js} +21 -21
- package/dist/runtime/base-classes/integrated-entity-repository.js.map +1 -0
- package/dist/runtime/base-classes/{synced-entity-service.d.ts → integrated-entity-service.d.ts} +6 -6
- package/dist/runtime/base-classes/{synced-entity-service.js → integrated-entity-service.js} +4 -4
- package/dist/runtime/base-classes/integrated-entity-service.js.map +1 -0
- package/dist/runtime/base-classes/{sync-upsert-config.d.ts → integration-upsert-config.d.ts} +13 -13
- package/dist/runtime/base-classes/integration-upsert-config.js +1 -0
- package/dist/runtime/base-classes/{junction-sync-repository.d.ts → junction-integration-repository.d.ts} +11 -11
- package/dist/runtime/base-classes/{junction-sync-repository.js → junction-integration-repository.js} +15 -15
- package/dist/runtime/base-classes/junction-integration-repository.js.map +1 -0
- package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.module.d.ts +4 -4
- package/dist/runtime/subsystems/auth/auth.module.js +3 -3
- package/dist/runtime/subsystems/auth/auth.module.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.tokens.d.ts +8 -8
- package/dist/runtime/subsystems/auth/auth.tokens.js +6 -6
- package/dist/runtime/subsystems/auth/auth.tokens.js.map +1 -1
- package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/auth/controllers/auth.controller.d.ts +2 -2
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js +3 -3
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js.map +1 -1
- package/dist/runtime/subsystems/auth/index.d.ts +3 -3
- package/dist/runtime/subsystems/auth/index.js +40 -40
- package/dist/runtime/subsystems/auth/index.js.map +1 -1
- package/dist/runtime/subsystems/auth/middleware/requester-context.js.map +1 -1
- package/dist/runtime/subsystems/auth/protocols/auth-strategy.d.ts +3 -3
- package/dist/runtime/subsystems/auth/protocols/{integration-store.d.ts → connection-store.d.ts} +20 -20
- package/dist/runtime/subsystems/auth/protocols/connection-store.js +1 -0
- package/dist/runtime/subsystems/auth/protocols/provider-strategy.d.ts +3 -3
- package/dist/runtime/subsystems/auth/runtime/{integration-broken.error.d.ts → connection-broken.error.d.ts} +5 -5
- package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js +19 -0
- package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js.map +1 -0
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.d.ts +10 -10
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js +28 -28
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js.map +1 -1
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.d.ts +1 -1
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js +3 -3
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js.map +1 -1
- package/dist/runtime/subsystems/index.d.ts +11 -7
- package/dist/runtime/subsystems/index.js +1041 -67
- package/dist/runtime/subsystems/index.js.map +1 -1
- package/dist/runtime/subsystems/{sync → integration}/build-change-source.d.ts +3 -3
- package/dist/runtime/subsystems/{sync → integration}/build-change-source.js +3 -3
- package/dist/runtime/subsystems/integration/build-change-source.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/deep-equal.differ.d.ts +2 -2
- package/dist/runtime/subsystems/{sync → integration}/deep-equal.differ.js +1 -1
- package/dist/runtime/subsystems/integration/deep-equal.differ.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/detection-config.schema.d.ts +3 -3
- package/dist/runtime/subsystems/{sync → integration}/detection-config.schema.js +1 -1
- package/dist/runtime/subsystems/integration/detection-config.schema.js.map +1 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.d.ts +25 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.js +34 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.js.map +1 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.d.ts +53 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.js +13 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.js.map +1 -0
- package/dist/runtime/subsystems/{sync/execute-sync.use-case.d.ts → integration/execute-integration.use-case.d.ts} +13 -13
- package/dist/runtime/subsystems/{sync/execute-sync.use-case.js → integration/execute-integration.use-case.js} +30 -30
- package/dist/runtime/subsystems/integration/execute-integration.use-case.js.map +1 -0
- package/dist/runtime/subsystems/integration/index.d.ts +30 -0
- package/dist/runtime/subsystems/{sync → integration}/index.js +206 -171
- package/dist/runtime/subsystems/integration/index.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-audit.schema.d.ts → integration/integration-audit.schema.d.ts} +64 -64
- package/dist/runtime/subsystems/{sync/sync-audit.schema.js → integration/integration-audit.schema.js} +47 -47
- package/dist/runtime/subsystems/integration/integration-audit.schema.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-change-source.protocol.d.ts → integration/integration-change-source.protocol.d.ts} +10 -10
- package/dist/runtime/subsystems/integration/integration-change-source.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.d.ts → integration/integration-cursor-store.drizzle-backend.d.ts} +1 -1
- package/dist/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.js → integration/integration-cursor-store.drizzle-backend.js} +65 -65
- package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.memory-backend.d.ts → integration/integration-cursor-store.memory-backend.d.ts} +6 -6
- package/dist/runtime/subsystems/{sync/sync-cursor-store.memory-backend.js → integration/integration-cursor-store.memory-backend.js} +5 -5
- package/dist/runtime/subsystems/integration/integration-cursor-store.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.protocol.d.ts → integration/integration-cursor-store.protocol.d.ts} +13 -13
- package/dist/runtime/subsystems/integration/integration-cursor-store.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-errors.d.ts → integration/integration-errors.d.ts} +2 -2
- package/dist/runtime/subsystems/{sync/sync-errors.js → integration/integration-errors.js} +3 -3
- package/dist/runtime/subsystems/integration/integration-errors.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-field-diff.protocol.d.ts → integration/integration-field-diff.protocol.d.ts} +2 -2
- package/dist/runtime/subsystems/{sync/sync-field-diff.protocol.js → integration/integration-field-diff.protocol.js} +2 -2
- package/dist/runtime/subsystems/integration/integration-field-diff.protocol.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-loopback.protocol.d.ts → integration/integration-loopback.protocol.d.ts} +2 -2
- package/dist/runtime/subsystems/integration/integration-loopback.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-middleware.protocol.d.ts → integration/integration-middleware.protocol.d.ts} +5 -5
- package/dist/runtime/subsystems/integration/integration-middleware.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.d.ts → integration/integration-run-recorder.drizzle-backend.d.ts} +5 -5
- package/dist/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.js → integration/integration-run-recorder.drizzle-backend.js} +73 -73
- package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.memory-backend.d.ts → integration/integration-run-recorder.memory-backend.d.ts} +15 -15
- package/dist/runtime/subsystems/{sync/sync-run-recorder.memory-backend.js → integration/integration-run-recorder.memory-backend.js} +11 -11
- package/dist/runtime/subsystems/integration/integration-run-recorder.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.protocol.d.ts → integration/integration-run-recorder.protocol.d.ts} +25 -25
- package/dist/runtime/subsystems/integration/integration-run-recorder.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-sink.protocol.d.ts → integration/integration-sink.protocol.d.ts} +5 -5
- package/dist/runtime/subsystems/integration/integration-sink.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync.module.d.ts → integration/integration.module.d.ts} +24 -24
- package/dist/runtime/subsystems/{sync/sync.module.js → integration/integration.module.js} +132 -132
- package/dist/runtime/subsystems/integration/integration.module.js.map +1 -0
- package/dist/runtime/subsystems/integration/integration.tokens.d.ts +60 -0
- package/dist/runtime/subsystems/integration/integration.tokens.js +20 -0
- package/dist/runtime/subsystems/integration/integration.tokens.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/loopback.middleware.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/loopback.middleware.js +1 -1
- package/dist/runtime/subsystems/integration/loopback.middleware.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/poll-change-source.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/poll-change-source.js +1 -1
- package/dist/runtime/subsystems/integration/poll-change-source.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/webhook-change-source.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/webhook-change-source.js +1 -1
- package/dist/runtime/subsystems/integration/webhook-change-source.js.map +1 -0
- package/dist/runtime/subsystems/jobs/job-worker.module.d.ts +1 -1
- package/dist/runtime/subsystems/observability/index.d.ts +4 -4
- package/dist/runtime/subsystems/observability/index.js +11 -11
- package/dist/runtime/subsystems/observability/index.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.module.d.ts +2 -2
- package/dist/runtime/subsystems/observability/observability.module.js +11 -11
- package/dist/runtime/subsystems/observability/observability.module.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.protocol.d.ts +11 -11
- package/dist/runtime/subsystems/observability/observability.service.d.ts +6 -6
- package/dist/runtime/subsystems/observability/observability.service.js +11 -11
- package/dist/runtime/subsystems/observability/observability.service.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.tokens.d.ts +1 -1
- package/dist/runtime/subsystems/observability/observability.tokens.js.map +1 -1
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.d.ts +3 -3
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.js.map +1 -1
- package/dist/runtime/subsystems/observability/reporters/index.d.ts +3 -3
- package/dist/runtime/subsystems/observability/reporters/index.js.map +1 -1
- package/dist/src/cli/index.js +1336 -376
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.d.ts +70 -22
- package/dist/src/index.js +290 -194
- package/dist/src/index.js.map +1 -1
- package/examples/auth-integrations/README.md +32 -32
- package/examples/auth-integrations/definitions/entities/{integration.yaml → connection.yaml} +10 -10
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-grant-sink.adapter.ts → connections/adapters/connection-grant-sink.adapter.ts} +7 -7
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-reader.adapter.ts → connections/adapters/connection-reader.adapter.ts} +10 -10
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-token-writer.adapter.ts → connections/adapters/connection-token-writer.adapter.ts} +11 -11
- package/examples/auth-integrations/runtime/connections/connections-auth.module.ts +81 -0
- package/examples/auth-integrations/runtime/{integrations/facade/integrations.service.ts → connections/facade/connections.service.ts} +35 -35
- package/examples/auth-integrations/runtime/{integrations → connections}/oauth/use-cases/create-or-update-from-oauth-grant.use-case.ts +11 -11
- package/examples/auth-integrations/runtime/{integrations/oauth/use-cases/disconnect-integration.use-case.ts → connections/oauth/use-cases/disconnect-connection.use-case.ts} +6 -6
- package/examples/auth-integrations/runtime/connections/oauth/use-cases/list-user-connections.use-case.ts +21 -0
- package/examples/auth-integrations/runtime/connections/oauth/use-cases/mark-connection-requires-reauth.use-case.ts +21 -0
- package/package.json +9 -1
- package/runtime/base-classes/index.ts +8 -8
- package/runtime/base-classes/{synced-entity-repository.ts → integrated-entity-repository.ts} +36 -36
- package/runtime/base-classes/{synced-entity-service.ts → integrated-entity-service.ts} +6 -6
- package/runtime/base-classes/{sync-upsert-config.ts → integration-upsert-config.ts} +12 -12
- package/runtime/base-classes/{junction-sync-repository.ts → junction-integration-repository.ts} +28 -28
- package/runtime/subsystems/auth/auth-oauth-state.schema.ts +1 -1
- package/runtime/subsystems/auth/auth.module.ts +4 -4
- package/runtime/subsystems/auth/auth.tokens.ts +7 -7
- package/runtime/subsystems/auth/controllers/auth.controller.ts +7 -7
- package/runtime/subsystems/auth/index.ts +19 -19
- package/runtime/subsystems/auth/protocols/auth-strategy.ts +3 -3
- package/runtime/subsystems/auth/protocols/{integration-store.ts → connection-store.ts} +19 -19
- package/runtime/subsystems/auth/protocols/provider-strategy.ts +2 -2
- package/runtime/subsystems/auth/runtime/{integration-broken.error.ts → connection-broken.error.ts} +5 -5
- package/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts +35 -35
- package/runtime/subsystems/auth/runtime/with-auth-retry.ts +3 -3
- package/runtime/subsystems/index.ts +26 -11
- package/runtime/subsystems/{sync → integration}/build-change-source.ts +3 -3
- package/runtime/subsystems/{sync → integration}/deep-equal.differ.ts +7 -7
- package/runtime/subsystems/{sync → integration}/detection-config.schema.ts +3 -3
- package/runtime/subsystems/integration/entity-change-source-registry.memory.ts +40 -0
- package/runtime/subsystems/integration/entity-change-source-registry.protocol.ts +59 -0
- package/runtime/subsystems/{sync/execute-sync.use-case.ts → integration/execute-integration.use-case.ts} +40 -40
- package/runtime/subsystems/{sync → integration}/index.ts +56 -47
- package/runtime/subsystems/{sync/sync-audit.schema.ts → integration/integration-audit.schema.ts} +61 -61
- package/runtime/subsystems/{sync/sync-change-source.protocol.ts → integration/integration-change-source.protocol.ts} +9 -9
- package/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.ts → integration/integration-cursor-store.drizzle-backend.ts} +30 -30
- package/runtime/subsystems/{sync/sync-cursor-store.memory-backend.ts → integration/integration-cursor-store.memory-backend.ts} +9 -9
- package/runtime/subsystems/{sync/sync-cursor-store.protocol.ts → integration/integration-cursor-store.protocol.ts} +13 -13
- package/runtime/subsystems/{sync/sync-errors.ts → integration/integration-errors.ts} +3 -3
- package/runtime/subsystems/{sync/sync-field-diff.protocol.ts → integration/integration-field-diff.protocol.ts} +2 -2
- package/runtime/subsystems/{sync/sync-loopback.protocol.ts → integration/integration-loopback.protocol.ts} +2 -2
- package/runtime/subsystems/{sync/sync-middleware.protocol.ts → integration/integration-middleware.protocol.ts} +6 -6
- package/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.ts → integration/integration-run-recorder.drizzle-backend.ts} +39 -39
- package/runtime/subsystems/{sync/sync-run-recorder.memory-backend.ts → integration/integration-run-recorder.memory-backend.ts} +23 -23
- package/runtime/subsystems/{sync/sync-run-recorder.protocol.ts → integration/integration-run-recorder.protocol.ts} +25 -25
- package/runtime/subsystems/{sync/sync-sink.protocol.ts → integration/integration-sink.protocol.ts} +4 -4
- package/runtime/subsystems/{sync/sync.module.ts → integration/integration.module.ts} +48 -48
- package/runtime/subsystems/integration/integration.tokens.ts +63 -0
- package/runtime/subsystems/{sync → integration}/loopback.middleware.ts +5 -5
- package/runtime/subsystems/{sync → integration}/poll-change-source.ts +7 -7
- package/runtime/subsystems/{sync → integration}/webhook-change-source.ts +7 -7
- package/runtime/subsystems/observability/index.ts +1 -1
- package/runtime/subsystems/observability/observability.module.ts +2 -2
- package/runtime/subsystems/observability/observability.protocol.ts +11 -11
- package/runtime/subsystems/observability/observability.service.ts +13 -13
- package/runtime/subsystems/observability/observability.tokens.ts +1 -1
- package/src/patterns/library/index.ts +4 -4
- package/src/patterns/library/{synced.pattern.ts → integrated.pattern.ts} +12 -12
- package/src/patterns/library/junction.pattern.ts +1 -1
- package/src/patterns/pattern-definition.ts +3 -3
- package/templates/entity/new/backend/modules/core/{sync-source.ejs.t → integration-source.ejs.t} +6 -6
- package/templates/entity/new/clean-lite-ps/entity.ejs.t +12 -3
- package/templates/entity/new/clean-lite-ps/module.ejs.t +1 -1
- package/templates/entity/new/clean-lite-ps/prompt-extension.js +243 -60
- package/templates/entity/new/clean-lite-ps/repository.ejs.t +27 -27
- package/templates/entity/new/frontend/collections/collection.ejs.t +26 -1
- package/templates/entity/new/frontend/collections/collections-base.ejs.t +11 -0
- package/templates/entity/new/frontend/entity/combined.ejs.t +31 -1
- package/templates/entity/new/prompt.js +27 -15
- package/templates/junction/new/entity.ejs.t +1 -1
- package/templates/junction/new/prompt.js +24 -24
- package/templates/junction/new/repository.ejs.t +19 -19
- package/templates/subsystem/auth/auth-oauth-state.schema.ejs.t +2 -2
- package/templates/subsystem/auth-config/prompt.js +1 -1
- package/templates/subsystem/auth-integrations/app-module-hook.ejs.t +5 -5
- package/templates/subsystem/bridge/prompt.js +1 -1
- package/templates/subsystem/integration/integration-audit.schema.ejs.t +192 -0
- package/templates/subsystem/{sync → integration}/prompt.js +12 -12
- package/templates/subsystem/{sync-config/codegen-config-sync-block.ejs.t → integration-config/codegen-config-integration-block.ejs.t} +7 -7
- package/templates/subsystem/integration-config/prompt.js +22 -0
- package/templates/subsystem/jobs/worker.ejs.t +2 -2
- package/templates/subsystem/observability/main-hook.ejs.t +1 -1
- package/templates/subsystem/observability/prompt.js +1 -1
- package/templates/subsystem/openapi-config/prompt.js +1 -1
- package/dist/runtime/base-classes/junction-sync-repository.js.map +0 -1
- package/dist/runtime/base-classes/sync-upsert-config.js +0 -1
- package/dist/runtime/base-classes/synced-entity-repository.js.map +0 -1
- package/dist/runtime/base-classes/synced-entity-service.js.map +0 -1
- package/dist/runtime/subsystems/auth/protocols/integration-store.js +0 -1
- package/dist/runtime/subsystems/auth/runtime/integration-broken.error.js +0 -19
- package/dist/runtime/subsystems/auth/runtime/integration-broken.error.js.map +0 -1
- package/dist/runtime/subsystems/sync/build-change-source.js.map +0 -1
- package/dist/runtime/subsystems/sync/deep-equal.differ.js.map +0 -1
- package/dist/runtime/subsystems/sync/detection-config.schema.js.map +0 -1
- package/dist/runtime/subsystems/sync/execute-sync.use-case.js.map +0 -1
- package/dist/runtime/subsystems/sync/index.d.ts +0 -28
- package/dist/runtime/subsystems/sync/index.js.map +0 -1
- package/dist/runtime/subsystems/sync/loopback.middleware.js.map +0 -1
- package/dist/runtime/subsystems/sync/poll-change-source.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-audit.schema.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-change-source.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.drizzle-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.memory-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-errors.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-field-diff.protocol.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-loopback.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-middleware.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.drizzle-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.memory-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-sink.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync.module.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync.tokens.d.ts +0 -47
- package/dist/runtime/subsystems/sync/sync.tokens.js +0 -18
- package/dist/runtime/subsystems/sync/sync.tokens.js.map +0 -1
- package/dist/runtime/subsystems/sync/webhook-change-source.js.map +0 -1
- package/examples/auth-integrations/runtime/integrations/integrations-auth.module.ts +0 -81
- package/examples/auth-integrations/runtime/integrations/oauth/use-cases/list-user-integrations.use-case.ts +0 -21
- package/examples/auth-integrations/runtime/integrations/oauth/use-cases/mark-integration-requires-reauth.use-case.ts +0 -21
- package/runtime/subsystems/sync/sync.tokens.ts +0 -49
- package/templates/entity/new/backend/modules/core/sync-source.providers.ejs.t +0 -18
- package/templates/subsystem/sync/sync-audit.schema.ejs.t +0 -192
- package/templates/subsystem/sync-config/prompt.js +0 -22
- /package/dist/runtime/base-classes/{sync-upsert-config.js.map → integration-upsert-config.js.map} +0 -0
- /package/dist/runtime/subsystems/auth/protocols/{integration-store.js.map → connection-store.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-change-source.protocol.js.map → integration/integration-change-source.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-cursor-store.protocol.js.map → integration/integration-cursor-store.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-loopback.protocol.js.map → integration/integration-loopback.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-middleware.protocol.js.map → integration/integration-middleware.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-run-recorder.protocol.js.map → integration/integration-run-recorder.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-sink.protocol.js.map → integration/integration-sink.protocol.js.map} +0 -0
package/templates/entity/new/backend/modules/core/{sync-source.ejs.t → integration-source.ejs.t}
RENAMED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
---
|
|
2
|
-
to: "<%= hasDetection ? (isCleanLitePs ? clpOutputPaths.
|
|
2
|
+
to: "<%= hasDetection ? (isCleanLitePs ? clpOutputPaths.integrationSourceModule : `${basePaths.backendSrc}/${paths.modules}/${name}-integration-source.module.ts`) : null %>"
|
|
3
3
|
skip_if: <%= !hasDetection %>
|
|
4
4
|
force: true
|
|
5
5
|
---
|
|
6
6
|
<%- typeof generatedBanner !== 'undefined' ? generatedBanner : '' %>
|
|
7
7
|
import { Module } from '@nestjs/common';
|
|
8
|
-
import { buildChangeSource } from '@shared/subsystems/
|
|
8
|
+
import { buildChangeSource } from '@shared/subsystems/integration';
|
|
9
9
|
import type {
|
|
10
10
|
DetectionConfig,
|
|
11
11
|
IChangeSource,
|
|
12
12
|
PollFetchCallback,
|
|
13
|
-
} from '@shared/subsystems/
|
|
14
|
-
import type { <%= className %> } from '<%= isCleanLitePs ? clpImports.
|
|
13
|
+
} from '@shared/subsystems/integration';
|
|
14
|
+
import type { <%= className %> } from '<%= isCleanLitePs ? clpImports.integrationSourceToEntity : imports.moduleToDomain %>';
|
|
15
15
|
|
|
16
16
|
const <%= name.toUpperCase() %>_DETECTION_CONFIGS: Record<string, DetectionConfig> = <%- detectionConfigsLiteral %>;
|
|
17
17
|
|
|
@@ -31,7 +31,7 @@ export const <%= name.toUpperCase() %>_CHANGE_SOURCES = Symbol('<%= name.toUpper
|
|
|
31
31
|
const fetch = fetches[provider];
|
|
32
32
|
if (!fetch) {
|
|
33
33
|
throw new Error(
|
|
34
|
-
`<%= className %>
|
|
34
|
+
`<%= className %>IntegrationSourceModule: missing fetch callback for provider '${provider}' in <%= name.toUpperCase() %>_POLL_FETCH_REGISTRY`,
|
|
35
35
|
);
|
|
36
36
|
}
|
|
37
37
|
return [provider, buildChangeSource(cfg, fetch)];
|
|
@@ -41,4 +41,4 @@ export const <%= name.toUpperCase() %>_CHANGE_SOURCES = Symbol('<%= name.toUpper
|
|
|
41
41
|
],
|
|
42
42
|
exports: [<%= name.toUpperCase() %>_CHANGE_SOURCES],
|
|
43
43
|
})
|
|
44
|
-
export class <%= className %>
|
|
44
|
+
export class <%= className %>IntegrationSourceModule {}
|
|
@@ -22,6 +22,10 @@ import { type InferSelectModel } from 'drizzle-orm';
|
|
|
22
22
|
import { <%= rel.relatedTable %> } from '<%= rel.importPath %>';
|
|
23
23
|
<%_ } _%>
|
|
24
24
|
<%_ }) _%>
|
|
25
|
+
<%_ /* #354: field-level foreign_key target table imports */ _%>
|
|
26
|
+
<%_ if (typeof clpFieldFkImports !== 'undefined') { clpFieldFkImports.forEach(imp => { _%>
|
|
27
|
+
import { <%= imp.relatedTable %> } from '<%= imp.importPath %>';
|
|
28
|
+
<%_ }) } _%>
|
|
25
29
|
<%_ /* CGP-358b: import has_many target tables for many() relation const */ _%>
|
|
26
30
|
<%_ if (typeof clpExistingHasMany !== 'undefined') { _%>
|
|
27
31
|
<%_ clpExistingHasMany.filter(rel => !rel.isSelfRef).forEach(rel => { _%>
|
|
@@ -65,10 +69,15 @@ export const <%= entityNamePlural %> = pgTable(
|
|
|
65
69
|
deletedAt: timestamp('deleted_at'),
|
|
66
70
|
<%_ } _%>
|
|
67
71
|
},
|
|
68
|
-
<%_
|
|
72
|
+
<%_ /* #355/#356: pgTable extra-config — indexes + composite unique indexes + external_id unique index */ _%>
|
|
73
|
+
<%_ if (typeof clpTableConstraints !== 'undefined' && clpTableConstraints.length > 0) { _%>
|
|
69
74
|
(t) => [
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
<%_ clpTableConstraints.forEach(c => { _%>
|
|
76
|
+
<%_ if (c.comment) { _%>
|
|
77
|
+
// <%= c.comment %>
|
|
78
|
+
<%_ } _%>
|
|
79
|
+
<%- c.expr %>,
|
|
80
|
+
<%_ }) _%>
|
|
72
81
|
],
|
|
73
82
|
<%_ } _%>
|
|
74
83
|
);
|
|
@@ -116,7 +116,7 @@ import { <%= classNames.searchController %> } from './<%= entityName %>-search.c
|
|
|
116
116
|
// exported so sibling modules that compose this entity cross-module (junction
|
|
117
117
|
// `.list()`, EAV value→definition resolution) inject the home-module instance
|
|
118
118
|
// — the only place the repo's own deps are wired (e.g. an EAV entity's repo
|
|
119
|
-
// injects FieldValueService for the #374
|
|
119
|
+
// injects FieldValueService for the #374 integration dual-write tx). Local-providing
|
|
120
120
|
// such a repo elsewhere can't satisfy those deps. Use-case internals stay unexported.
|
|
121
121
|
exports: [<%= classNames.service %>, <%= classNames.repository %>],
|
|
122
122
|
})
|
|
@@ -9,7 +9,7 @@ import fs from 'node:fs';
|
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import pluralizePkg from 'pluralize';
|
|
11
11
|
// The patterns barrel has the side effect of pre-registering the five
|
|
12
|
-
// library-shipped patterns (Base /
|
|
12
|
+
// library-shipped patterns (Base / Integrated / Activity / Knowledge /
|
|
13
13
|
// Metadata). App-defined patterns are loaded separately in the parent
|
|
14
14
|
// prompt.js via loadAppPatterns() against `codegen.config.yaml patterns:`
|
|
15
15
|
// globs before this helper runs — we only read the registry here.
|
|
@@ -108,7 +108,7 @@ export function resolvePatternBaseClasses(entity) {
|
|
|
108
108
|
/**
|
|
109
109
|
* Resolve the behaviors implied by an entity's declared pattern(s).
|
|
110
110
|
*
|
|
111
|
-
* A pattern (e.g. `
|
|
111
|
+
* A pattern (e.g. `Integrated`) may declare `impliedBehaviors` — behaviors the
|
|
112
112
|
* entity gets for free without re-declaring them in its `behaviors:` array.
|
|
113
113
|
* Walks every declared pattern (both the `pattern: X` and `patterns: [...]`
|
|
114
114
|
* shapes), unions their `impliedBehaviors`, and returns a deduped list.
|
|
@@ -145,6 +145,7 @@ const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
|
145
145
|
const camelCase = (s) => s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
146
146
|
const pascalCase = (s) => capitalize(camelCase(s));
|
|
147
147
|
const pluralize = (s) => pluralizePkg.plural(s);
|
|
148
|
+
const singularize = (s) => pluralizePkg.singular(s);
|
|
148
149
|
|
|
149
150
|
// ============================================================================
|
|
150
151
|
// Drizzle type mapping
|
|
@@ -260,15 +261,45 @@ function buildDrizzleChain(fieldName, field, drizzleType, enumName) {
|
|
|
260
261
|
chain += '.notNull()';
|
|
261
262
|
}
|
|
262
263
|
|
|
263
|
-
//
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
// Column defaults (#345). The value is validated upstream (schema `default:`).
|
|
265
|
+
// Covers every scalar type, enum literals, and the `now` sentinel on
|
|
266
|
+
// timestamp/date columns — not just booleans.
|
|
267
|
+
if (hasDefault) {
|
|
268
|
+
chain += renderColumnDefault(field.default, drizzleType);
|
|
266
269
|
}
|
|
267
270
|
|
|
268
|
-
// Timestamp defaults for datetime fields in behavior context handled separately
|
|
269
271
|
return chain;
|
|
270
272
|
}
|
|
271
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Render a Drizzle `.default(...)` (or `.defaultNow()`) suffix for a column.
|
|
276
|
+
*
|
|
277
|
+
* - timestamp/date + a `now`/`now()`/`current_timestamp` sentinel → `.defaultNow()`
|
|
278
|
+
* - numeric (Drizzle returns it as a string) → quoted, even for numeric YAML values
|
|
279
|
+
* - string / enum literal → single-quoted, escaped
|
|
280
|
+
* - number / boolean → bare literal
|
|
281
|
+
* - anything else (jsonb object/array default) → JSON literal
|
|
282
|
+
*/
|
|
283
|
+
function renderColumnDefault(value, drizzleType) {
|
|
284
|
+
if (
|
|
285
|
+
(drizzleType === 'timestamp' || drizzleType === 'date') &&
|
|
286
|
+
typeof value === 'string' &&
|
|
287
|
+
/^(now|now\(\)|current_timestamp)$/i.test(value)
|
|
288
|
+
) {
|
|
289
|
+
return '.defaultNow()';
|
|
290
|
+
}
|
|
291
|
+
if (drizzleType === 'numeric') {
|
|
292
|
+
return `.default('${String(value)}')`;
|
|
293
|
+
}
|
|
294
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
295
|
+
return `.default(${value})`;
|
|
296
|
+
}
|
|
297
|
+
if (typeof value === 'string') {
|
|
298
|
+
return `.default('${value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}')`;
|
|
299
|
+
}
|
|
300
|
+
return `.default(${JSON.stringify(value)})`;
|
|
301
|
+
}
|
|
302
|
+
|
|
272
303
|
/**
|
|
273
304
|
* Process entity fields into ProcessedField[]
|
|
274
305
|
*/
|
|
@@ -446,10 +477,95 @@ function processBelongsTo(relationships, parentEntityNamePlural) {
|
|
|
446
477
|
return result;
|
|
447
478
|
}
|
|
448
479
|
|
|
480
|
+
/**
|
|
481
|
+
* Field-level `foreign_key:` + `index:` emission (#354, #355).
|
|
482
|
+
*
|
|
483
|
+
* Distinct from `relationships:`-driven belongs_to FKs (processBelongsTo),
|
|
484
|
+
* which own their own column + import. This handles features declared
|
|
485
|
+
* directly on a column field:
|
|
486
|
+
*
|
|
487
|
+
* - `foreign_key: <table>.<column>` → append `.references(() => <table>.<column>)`
|
|
488
|
+
* to the column's Drizzle chain (self-FKs get the `: AnyPgColumn` annotation)
|
|
489
|
+
* and record the cross-module import. The table segment is the Drizzle table
|
|
490
|
+
* export name (plural, e.g. `conversations`); the import path singularizes it
|
|
491
|
+
* to the entity file (`../conversations/conversation.entity`).
|
|
492
|
+
* - `index: true` → emit a named single-column index in the pgTable
|
|
493
|
+
* extra-config callback (`<table>_<column>_idx`).
|
|
494
|
+
*
|
|
495
|
+
* Mutates each processed field's `drizzleChain` in place (the same objects are
|
|
496
|
+
* later rendered via clpProcessedFields). Returns the imports + index
|
|
497
|
+
* expressions the template needs.
|
|
498
|
+
*
|
|
499
|
+
* @param {object[]} renderedFields the fields actually emitted as columns
|
|
500
|
+
* (nonFkFields — belongs_to FK columns excluded)
|
|
501
|
+
* @param {object} fields raw field map keyed by snake_case name
|
|
502
|
+
* @param {string} entityNamePlural Drizzle table export name for self-FK detection
|
|
503
|
+
*/
|
|
504
|
+
function processFieldFeatures(renderedFields, fields, entityNamePlural) {
|
|
505
|
+
const fkImports = [];
|
|
506
|
+
const indexExpressions = [];
|
|
507
|
+
const seenImports = new Set();
|
|
508
|
+
let hasSelfFieldFk = false;
|
|
509
|
+
|
|
510
|
+
for (const pf of renderedFields) {
|
|
511
|
+
const field = fields[pf.name];
|
|
512
|
+
if (!field) continue;
|
|
513
|
+
|
|
514
|
+
// --- foreign_key (#354) ---
|
|
515
|
+
if (typeof field.foreign_key === 'string' && field.foreign_key.includes('.')) {
|
|
516
|
+
const [relatedTable, fkColumn] = field.foreign_key.split('.');
|
|
517
|
+
const isSelfFk = relatedTable === entityNamePlural;
|
|
518
|
+
pf.drizzleChain += isSelfFk
|
|
519
|
+
? `.references((): AnyPgColumn => ${relatedTable}.${fkColumn})`
|
|
520
|
+
: `.references(() => ${relatedTable}.${fkColumn})`;
|
|
521
|
+
|
|
522
|
+
if (isSelfFk) {
|
|
523
|
+
hasSelfFieldFk = true;
|
|
524
|
+
} else if (!seenImports.has(relatedTable)) {
|
|
525
|
+
seenImports.add(relatedTable);
|
|
526
|
+
fkImports.push({
|
|
527
|
+
relatedTable,
|
|
528
|
+
importPath: `../${relatedTable}/${singularize(relatedTable)}.entity`,
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// --- index: true (#355) ---
|
|
534
|
+
if (field.index === true) {
|
|
535
|
+
indexExpressions.push({
|
|
536
|
+
comment: null,
|
|
537
|
+
expr: `index('${entityNamePlural}_${pf.name}_idx').on(t.${pf.camelName})`,
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
return { fkImports, indexExpressions, hasSelfFieldFk };
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Composite unique index emission (#356).
|
|
547
|
+
*
|
|
548
|
+
* Top-level `unique_indexes: [{ fields: [...], name? }]` → a `uniqueIndex(...)`
|
|
549
|
+
* entry in the pgTable extra-config callback. Column names are camelCased to
|
|
550
|
+
* match the emitted Drizzle column identifiers; they may reference FK columns
|
|
551
|
+
* (belongs_to) or ordinary fields. Index name defaults to
|
|
552
|
+
* `<table>_<col1>_<col2>_..._uniq`.
|
|
553
|
+
*/
|
|
554
|
+
function processUniqueIndexes(uniqueIndexes, entityNamePlural) {
|
|
555
|
+
if (!Array.isArray(uniqueIndexes)) return [];
|
|
556
|
+
|
|
557
|
+
return uniqueIndexes.map((ui) => {
|
|
558
|
+
const cols = ui.fields;
|
|
559
|
+
const name = ui.name || `${entityNamePlural}_${cols.join('_')}_uniq`;
|
|
560
|
+
const onCols = cols.map((c) => `t.${camelCase(c)}`).join(', ');
|
|
561
|
+
return { comment: null, expr: `uniqueIndex('${name}').on(${onCols})` };
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
|
|
449
565
|
/**
|
|
450
566
|
* Collect drizzle imports needed for entity fields
|
|
451
567
|
*/
|
|
452
|
-
function collectDrizzleImports(processedFields, belongsTo, hasTimestamps, hasSoftDelete, hasExternalIdTracking, hasMany = []) {
|
|
568
|
+
function collectDrizzleImports(processedFields, belongsTo, hasTimestamps, hasSoftDelete, hasExternalIdTracking, hasMany = [], extraImports = []) {
|
|
453
569
|
const imports = new Set(['pgTable', 'uuid']);
|
|
454
570
|
|
|
455
571
|
for (const field of processedFields) {
|
|
@@ -475,7 +591,7 @@ function collectDrizzleImports(processedFields, belongsTo, hasTimestamps, hasSof
|
|
|
475
591
|
|
|
476
592
|
// external_id_tracking behavior injects varchar + jsonb columns plus a
|
|
477
593
|
// unique index over (provider, external_id) — the ON CONFLICT target the
|
|
478
|
-
//
|
|
594
|
+
// integration sink's integrationUpsert relies on.
|
|
479
595
|
if (hasExternalIdTracking) {
|
|
480
596
|
imports.add('varchar');
|
|
481
597
|
imports.add('jsonb');
|
|
@@ -486,6 +602,13 @@ function collectDrizzleImports(processedFields, belongsTo, hasTimestamps, hasSof
|
|
|
486
602
|
imports.add('relations');
|
|
487
603
|
}
|
|
488
604
|
|
|
605
|
+
// Caller-supplied extras: `index` (field-level index: true) and
|
|
606
|
+
// `uniqueIndex` (composite unique_indexes) — see processFieldFeatures /
|
|
607
|
+
// processUniqueIndexes.
|
|
608
|
+
for (const extra of extraImports) {
|
|
609
|
+
imports.add(extra);
|
|
610
|
+
}
|
|
611
|
+
|
|
489
612
|
return Array.from(imports).sort();
|
|
490
613
|
}
|
|
491
614
|
|
|
@@ -725,16 +848,16 @@ function processSearchQueries(queriesBlock, processedFields, belongsTo, entityNa
|
|
|
725
848
|
}
|
|
726
849
|
|
|
727
850
|
// ============================================================================
|
|
728
|
-
//
|
|
851
|
+
// Integration write-surface derivation (#374)
|
|
729
852
|
// ============================================================================
|
|
730
853
|
|
|
731
854
|
/**
|
|
732
|
-
* Pre-compute the inbound-
|
|
733
|
-
* Keeps the EJS thin + unit-testable: the template hand-emits the
|
|
855
|
+
* Pre-compute the inbound-integration write surface for a `pattern: Integrated` entity.
|
|
856
|
+
* Keeps the EJS thin + unit-testable: the template hand-emits the integrationConfig
|
|
734
857
|
* literal (so `refTable` can carry a LIVE Drizzle table handle, which
|
|
735
858
|
* renderPatternConfigLiteral cannot express) using these locals.
|
|
736
859
|
*
|
|
737
|
-
* Returns null when the entity is not
|
|
860
|
+
* Returns null when the entity is not Integrated.
|
|
738
861
|
*
|
|
739
862
|
* @param {string} patternName resolved pattern name
|
|
740
863
|
* @param {object[]} processedFields nonFkFields (camel + tsType + nullable)
|
|
@@ -743,8 +866,8 @@ function processSearchQueries(queriesBlock, processedFields, belongsTo, entityNa
|
|
|
743
866
|
* @param {boolean} eavEnabled
|
|
744
867
|
* @param {boolean} hasSoftDelete
|
|
745
868
|
*/
|
|
746
|
-
export function
|
|
747
|
-
if (patternName !== '
|
|
869
|
+
export function buildIntegrationSurface(patternName, processedFields, belongsTo, hasTimestamps, eavEnabled, hasSoftDelete, fields) {
|
|
870
|
+
if (patternName !== 'Integrated') return null;
|
|
748
871
|
|
|
749
872
|
// Copy-through columns: every non-FK declared field. external_id_tracking
|
|
750
873
|
// columns (external_id/provider/provider_metadata) are injected by the
|
|
@@ -782,10 +905,10 @@ export function buildSyncSurface(patternName, processedFields, belongsTo, hasTim
|
|
|
782
905
|
...(hasTimestamps ? ['createdAt', 'updatedAt'] : []),
|
|
783
906
|
];
|
|
784
907
|
|
|
785
|
-
// The
|
|
908
|
+
// The integrationConfig object literal the template hand-emits. fkResolvers carry a
|
|
786
909
|
// sentinel so the template can swap `refTable` to either 'self' or the live
|
|
787
910
|
// table identifier.
|
|
788
|
-
const
|
|
911
|
+
const integrationConfig = {
|
|
789
912
|
conflictTarget: ['provider', 'externalId'],
|
|
790
913
|
writeColumns,
|
|
791
914
|
projectionColumns,
|
|
@@ -793,7 +916,7 @@ export function buildSyncSurface(patternName, processedFields, belongsTo, hasTim
|
|
|
793
916
|
softDelete: !!hasSoftDelete,
|
|
794
917
|
};
|
|
795
918
|
|
|
796
|
-
//
|
|
919
|
+
// TIntegrationWrite fields: externalId:string, copy-through (typed, nullable-aware),
|
|
797
920
|
// one `<writeKey>?: string | null` per FK, fields?: Record<string, unknown>.
|
|
798
921
|
const writeFields = processedFields.map((f) => ({
|
|
799
922
|
camelName: f.camelName,
|
|
@@ -804,7 +927,7 @@ export function buildSyncSurface(patternName, processedFields, belongsTo, hasTim
|
|
|
804
927
|
tsType: 'string | null',
|
|
805
928
|
}));
|
|
806
929
|
|
|
807
|
-
//
|
|
930
|
+
// TIntegrationProjection fields: id + externalId + copy-through (typed) + each local
|
|
808
931
|
// FK column (typed string, nullable per rel) + createdAt/updatedAt.
|
|
809
932
|
const projectionFields = [
|
|
810
933
|
{ camelName: 'id', tsType: 'string' },
|
|
@@ -841,7 +964,7 @@ export function buildSyncSurface(patternName, processedFields, belongsTo, hasTim
|
|
|
841
964
|
const parentTableImports = Array.from(parentImportMap.values());
|
|
842
965
|
|
|
843
966
|
return {
|
|
844
|
-
|
|
967
|
+
integrationConfig,
|
|
845
968
|
fkResolvers,
|
|
846
969
|
writeFields,
|
|
847
970
|
writeFkFields,
|
|
@@ -885,6 +1008,18 @@ export function buildCleanLitePsLocals(definition, baseLocals) {
|
|
|
885
1008
|
const entityNamePlural = entity.plural || pluralize(entityName);
|
|
886
1009
|
const entityNamePluralPascal = pascalCase(entityNamePlural);
|
|
887
1010
|
|
|
1011
|
+
// #403: bounded-context folder grouping. A top-level `context:` nests this
|
|
1012
|
+
// entity's module folder under that segment so same-context entities group
|
|
1013
|
+
// together (`<modules>/<context>/<plural>/`); no context → flat
|
|
1014
|
+
// (`<modules>/<plural>/`, byte-identical to pre-#403). Emit-folder-only —
|
|
1015
|
+
// every intra-module import is folder-relative and therefore unaffected, and
|
|
1016
|
+
// the generated barrel recomputes its import paths from the full file paths
|
|
1017
|
+
// below. The module-folder base used by every clpOutputPaths entry:
|
|
1018
|
+
const entityContext = definition.context || null;
|
|
1019
|
+
const moduleGroupDir = entityContext
|
|
1020
|
+
? `${srcRoot}/modules/${entityContext}`
|
|
1021
|
+
: `${srcRoot}/modules`;
|
|
1022
|
+
|
|
888
1023
|
// Generation toggles — `generate.writes` defaults to true so consumers who
|
|
889
1024
|
// regenerate pick up create/update/delete use cases without YAML changes.
|
|
890
1025
|
// Set `generate.writes: false` in YAML to suppress write-side emission
|
|
@@ -953,7 +1088,7 @@ export function buildCleanLitePsLocals(definition, baseLocals) {
|
|
|
953
1088
|
// Behavior flags (re-read from behaviors array for clean-lite-ps use).
|
|
954
1089
|
//
|
|
955
1090
|
// Fold in the resolved pattern's `impliedBehaviors` (ADR-031): an entity
|
|
956
|
-
// declaring e.g. `pattern:
|
|
1091
|
+
// declaring e.g. `pattern: Integrated` need not re-declare the
|
|
957
1092
|
// `external_id_tracking` behavior — the pattern contributes it. Deduped
|
|
958
1093
|
// with any explicit `behaviors:` entries, explicit-first so order is
|
|
959
1094
|
// stable for pre-existing fixtures. Mirrors the dedup in
|
|
@@ -1033,6 +1168,33 @@ export function buildCleanLitePsLocals(definition, baseLocals) {
|
|
|
1033
1168
|
const fkFieldNames = new Set(belongsTo.map((r) => r.field));
|
|
1034
1169
|
const nonFkFields = processedFields.filter((f) => !fkFieldNames.has(f.name));
|
|
1035
1170
|
|
|
1171
|
+
// Field-level foreign_key + index emission (#354, #355). Mutates the
|
|
1172
|
+
// drizzleChain of the rendered (non-belongs_to) columns in place. Skip FK
|
|
1173
|
+
// imports for tables belongs_to already imports to avoid duplicate import
|
|
1174
|
+
// lines.
|
|
1175
|
+
const fieldFeatures = processFieldFeatures(nonFkFields, fields, entityNamePlural);
|
|
1176
|
+
const belongsToTables = new Set(belongsTo.map((r) => r.relatedTable));
|
|
1177
|
+
const clpFieldFkImports = fieldFeatures.fkImports.filter(
|
|
1178
|
+
(imp) => !belongsToTables.has(imp.relatedTable),
|
|
1179
|
+
);
|
|
1180
|
+
|
|
1181
|
+
// Composite unique indexes (#356).
|
|
1182
|
+
const uniqueIndexExpressions = processUniqueIndexes(definition.unique_indexes, entityNamePlural);
|
|
1183
|
+
|
|
1184
|
+
// pgTable extra-config callback entries, in emission order: single-column
|
|
1185
|
+
// indexes, composite unique indexes, then the external_id_tracking unique
|
|
1186
|
+
// index (the ON CONFLICT target integrationUpsert relies on).
|
|
1187
|
+
const clpTableConstraints = [
|
|
1188
|
+
...fieldFeatures.indexExpressions,
|
|
1189
|
+
...uniqueIndexExpressions,
|
|
1190
|
+
];
|
|
1191
|
+
if (hasExternalIdTracking) {
|
|
1192
|
+
clpTableConstraints.push({
|
|
1193
|
+
comment: 'external_id_tracking behavior — ON CONFLICT target for integrationUpsert',
|
|
1194
|
+
expr: `uniqueIndex('uq_${entityNamePlural}_provider_external_id').on(t.provider, t.externalId)`,
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1036
1198
|
// Enum field declarations — surface a separate collection so the entity
|
|
1037
1199
|
// template can emit `export const xEnum = pgEnum('x', [...])` ahead of
|
|
1038
1200
|
// the `pgTable(...)` block. Both FK-filtered and unfiltered processing
|
|
@@ -1045,59 +1207,70 @@ export function buildCleanLitePsLocals(definition, baseLocals) {
|
|
|
1045
1207
|
choices: f.choices,
|
|
1046
1208
|
}));
|
|
1047
1209
|
|
|
1048
|
-
// Drizzle imports needed
|
|
1049
|
-
|
|
1210
|
+
// Drizzle imports needed. `index` / `uniqueIndex` are pulled in only when a
|
|
1211
|
+
// field declares `index: true` or the entity declares `unique_indexes:`
|
|
1212
|
+
// (external_id_tracking adds `uniqueIndex` on its own flag below).
|
|
1213
|
+
const extraDrizzleImports = [];
|
|
1214
|
+
if (fieldFeatures.indexExpressions.length > 0) extraDrizzleImports.push('index');
|
|
1215
|
+
if (uniqueIndexExpressions.length > 0) extraDrizzleImports.push('uniqueIndex');
|
|
1216
|
+
const drizzleEntityImports = collectDrizzleImports(processedFields, belongsTo, hasTimestamps, hasSoftDelete, hasExternalIdTracking, hasMany, extraDrizzleImports);
|
|
1050
1217
|
// Whether relations() import is needed (CGP-358b: also trigger on has_many)
|
|
1051
1218
|
const hasRelationsBlock = belongsTo.length > 0 || hasMany.length > 0;
|
|
1052
1219
|
|
|
1053
1220
|
// Output paths
|
|
1054
1221
|
const outputPaths = {
|
|
1055
|
-
entity: `${
|
|
1056
|
-
repository: `${
|
|
1057
|
-
service: `${
|
|
1058
|
-
controller: `${
|
|
1059
|
-
module: `${
|
|
1060
|
-
index: `${
|
|
1061
|
-
findByIdUseCase: `${
|
|
1062
|
-
listUseCase: `${
|
|
1222
|
+
entity: `${moduleGroupDir}/${entityNamePlural}/${entityName}.entity.ts`,
|
|
1223
|
+
repository: `${moduleGroupDir}/${entityNamePlural}/${entityName}.repository.ts`,
|
|
1224
|
+
service: `${moduleGroupDir}/${entityNamePlural}/${entityName}.service.ts`,
|
|
1225
|
+
controller: `${moduleGroupDir}/${entityNamePlural}/${entityName}.controller.ts`,
|
|
1226
|
+
module: `${moduleGroupDir}/${entityNamePlural}/${entityNamePlural}.module.ts`,
|
|
1227
|
+
index: `${moduleGroupDir}/${entityNamePlural}/index.ts`,
|
|
1228
|
+
findByIdUseCase: `${moduleGroupDir}/${entityNamePlural}/use-cases/find-${entityName}-by-id.use-case.ts`,
|
|
1229
|
+
listUseCase: `${moduleGroupDir}/${entityNamePlural}/use-cases/list-${entityNamePlural}.use-case.ts`,
|
|
1063
1230
|
findByIdWithFieldsUseCase: eavEnabled
|
|
1064
|
-
? `${
|
|
1231
|
+
? `${moduleGroupDir}/${entityNamePlural}/use-cases/find-${entityName}-by-id-with-fields.use-case.ts`
|
|
1065
1232
|
: null,
|
|
1066
1233
|
listWithFieldsUseCase: eavEnabled
|
|
1067
|
-
? `${
|
|
1234
|
+
? `${moduleGroupDir}/${entityNamePlural}/use-cases/list-${entityNamePlural}-with-fields.use-case.ts`
|
|
1068
1235
|
: null,
|
|
1069
1236
|
createUseCase: generateWrites
|
|
1070
|
-
? `${
|
|
1237
|
+
? `${moduleGroupDir}/${entityNamePlural}/use-cases/create-${entityName}.use-case.ts`
|
|
1071
1238
|
: null,
|
|
1072
1239
|
updateUseCase: generateWrites
|
|
1073
|
-
? `${
|
|
1240
|
+
? `${moduleGroupDir}/${entityNamePlural}/use-cases/update-${entityName}.use-case.ts`
|
|
1074
1241
|
: null,
|
|
1075
1242
|
deleteUseCase: generateWrites
|
|
1076
|
-
? `${
|
|
1243
|
+
? `${moduleGroupDir}/${entityNamePlural}/use-cases/delete-${entityName}.use-case.ts`
|
|
1077
1244
|
: null,
|
|
1078
|
-
createDto: `${
|
|
1079
|
-
updateDto: `${
|
|
1080
|
-
outputDto: `${
|
|
1245
|
+
createDto: `${moduleGroupDir}/${entityNamePlural}/dto/create-${entityName}.dto.ts`,
|
|
1246
|
+
updateDto: `${moduleGroupDir}/${entityNamePlural}/dto/update-${entityName}.dto.ts`,
|
|
1247
|
+
outputDto: `${moduleGroupDir}/${entityNamePlural}/dto/${entityName}-output.dto.ts`,
|
|
1081
1248
|
searchUseCase: searchQueryResolved
|
|
1082
|
-
? `${
|
|
1249
|
+
? `${moduleGroupDir}/${entityNamePlural}/use-cases/search-${entityNamePlural}.use-case.ts`
|
|
1083
1250
|
: null,
|
|
1084
1251
|
searchController: searchQueryResolved
|
|
1085
|
-
? `${
|
|
1252
|
+
? `${moduleGroupDir}/${entityNamePlural}/${entityName}-search.controller.ts`
|
|
1086
1253
|
: null,
|
|
1087
1254
|
declarativeQueries: hasDeclarativeQueries
|
|
1088
|
-
? `${
|
|
1255
|
+
? `${moduleGroupDir}/${entityNamePlural}/use-cases/declarative-queries.ts`
|
|
1089
1256
|
: null,
|
|
1090
|
-
// ADR-033.1 §8 —
|
|
1257
|
+
// ADR-033.1 §8 — integration-source module emission for clean-lite-ps. Co-located
|
|
1091
1258
|
// with the entity feature module under src/modules/<plural>/. Closes #267.
|
|
1092
|
-
|
|
1093
|
-
|
|
1259
|
+
// #403: routed through moduleGroupDir so a `context:`-tagged entity nests the
|
|
1260
|
+
// integration-source module under its context segment (untagged → flat, the
|
|
1261
|
+
// same `${srcRoot}/modules/<plural>/…` path as before).
|
|
1262
|
+
integrationSourceModule: `${moduleGroupDir}/${entityNamePlural}/${entityName}-integration-source.module.ts`,
|
|
1263
|
+
// ADR-033.2's per-entity provider tuples (`<entity>-integration-source.providers.ts`)
|
|
1264
|
+
// are removed by RFC-0001 §8 (D4). The surface-scoped typed view
|
|
1265
|
+
// (`src/integrations/<surface>/types.generated.ts`) is the single source of
|
|
1266
|
+
// provider truth now — see src/cli/shared/adapter-emission-generator.ts.
|
|
1094
1267
|
};
|
|
1095
1268
|
|
|
1096
|
-
// Architecture-specific imports for clean-lite-ps. The
|
|
1269
|
+
// Architecture-specific imports for clean-lite-ps. The integration-source module
|
|
1097
1270
|
// imports the entity type sibling-style (`./<entity>.entity`) since the
|
|
1098
1271
|
// module file lives next to the entity file in the same feature folder.
|
|
1099
1272
|
const clpImports = {
|
|
1100
|
-
|
|
1273
|
+
integrationSourceToEntity: `./${entityName}.entity`,
|
|
1101
1274
|
};
|
|
1102
1275
|
|
|
1103
1276
|
// Class names
|
|
@@ -1156,8 +1329,8 @@ export function buildCleanLitePsLocals(definition, baseLocals) {
|
|
|
1156
1329
|
zodChainOutput: zodChainForOutput(f),
|
|
1157
1330
|
}));
|
|
1158
1331
|
|
|
1159
|
-
//
|
|
1160
|
-
const
|
|
1332
|
+
// Integration write-surface derivation (#374) — null unless pattern: Integrated.
|
|
1333
|
+
const integrationSurface = buildIntegrationSurface(
|
|
1161
1334
|
patternName,
|
|
1162
1335
|
nonFkFields,
|
|
1163
1336
|
belongsTo,
|
|
@@ -1211,16 +1384,16 @@ export function buildCleanLitePsLocals(definition, baseLocals) {
|
|
|
1211
1384
|
renderPatternConfigLiteral,
|
|
1212
1385
|
...patternConfigClasses,
|
|
1213
1386
|
|
|
1214
|
-
//
|
|
1215
|
-
// template hand-emits the
|
|
1216
|
-
//
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1387
|
+
// Integration write-surface (#374) — emitted only for pattern: Integrated. The
|
|
1388
|
+
// template hand-emits the integrationConfig literal (live refTable handles) +
|
|
1389
|
+
// TIntegrationWrite/TIntegrationProjection from these.
|
|
1390
|
+
hasIntegrationSurface: integrationSurface !== null,
|
|
1391
|
+
clpIntegrationConfig: integrationSurface?.integrationConfig ?? null,
|
|
1392
|
+
clpIntegrationFkResolvers: integrationSurface?.fkResolvers ?? [],
|
|
1393
|
+
clpIntegrationWriteFields: integrationSurface?.writeFields ?? [],
|
|
1394
|
+
clpIntegrationWriteFkFields: integrationSurface?.writeFkFields ?? [],
|
|
1395
|
+
clpIntegrationProjectionFields: integrationSurface?.projectionFields ?? [],
|
|
1396
|
+
clpIntegrationParentTableImports: integrationSurface?.parentTableImports ?? [],
|
|
1224
1397
|
|
|
1225
1398
|
// Behavior flags (also exposed at top level for template use)
|
|
1226
1399
|
hasTimestamps,
|
|
@@ -1245,10 +1418,14 @@ export function buildCleanLitePsLocals(definition, baseLocals) {
|
|
|
1245
1418
|
hasSearchQuery: !!searchQueryResolved,
|
|
1246
1419
|
|
|
1247
1420
|
|
|
1421
|
+
// #403: bounded-context segment (null when untagged). Drives the
|
|
1422
|
+
// module-folder nesting reflected in clpOutputPaths above.
|
|
1423
|
+
clpContext: entityContext,
|
|
1424
|
+
|
|
1248
1425
|
// Output paths
|
|
1249
1426
|
clpOutputPaths: outputPaths,
|
|
1250
1427
|
|
|
1251
|
-
// Architecture-specific imports (ADR-033.1 §8 —
|
|
1428
|
+
// Architecture-specific imports (ADR-033.1 §8 — integration-source closes #267)
|
|
1252
1429
|
clpImports,
|
|
1253
1430
|
|
|
1254
1431
|
// Class names
|
|
@@ -1269,9 +1446,15 @@ export function buildCleanLitePsLocals(definition, baseLocals) {
|
|
|
1269
1446
|
// strict mode flags the table const with TS7022/TS7024 (circular initializer).
|
|
1270
1447
|
// Surfaced by the cgp-62 relationship-scenario smoke when generating a CRM
|
|
1271
1448
|
// account with a `parent_account_id` self-FK.
|
|
1272
|
-
clpHasSelfFk: belongsTo.some((rel) => rel.isSelfFk),
|
|
1449
|
+
clpHasSelfFk: belongsTo.some((rel) => rel.isSelfFk) || fieldFeatures.hasSelfFieldFk,
|
|
1273
1450
|
clpEnumFields,
|
|
1274
1451
|
|
|
1452
|
+
// Field-level foreign_key imports (#354) and pgTable extra-config
|
|
1453
|
+
// entries: single-column indexes (#355) + composite unique indexes (#356)
|
|
1454
|
+
// + the external_id_tracking unique index.
|
|
1455
|
+
clpFieldFkImports,
|
|
1456
|
+
clpTableConstraints,
|
|
1457
|
+
|
|
1275
1458
|
// Declarative queries
|
|
1276
1459
|
processedQueries,
|
|
1277
1460
|
hasDeclarativeQueries,
|