@cosmicdrift/kumiko-framework 0.386.0 → 0.388.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/AGENTS.md +6 -1
- package/LICENSE +21 -57
- package/README.md +2 -2
- package/agents/examples/anonymous-access.md +1 -1
- package/agents/examples/apex-landing.md +204 -0
- package/agents/examples/api-worker-split.md +64 -0
- package/agents/examples/app-config.md +14 -0
- package/agents/examples/auth-mfa.md +115 -0
- package/agents/examples/env-composition.md +28 -1
- package/agents/examples/legal-pages.md +1 -1
- package/agents/examples/prod-boot-options.md +16 -0
- package/agents/examples/rate-limiting.md +48 -0
- package/agents/examples/record-detail-layout.md +692 -0
- package/agents/examples/seed-migration.md +212 -0
- package/agents/examples/wizard-form.md +941 -0
- package/agents/examples/writeform-section.md +548 -0
- package/agents/features.md +19 -2
- package/agents/widgets.md +40 -39
- package/dist/api/api-constants.js +2 -2
- package/dist/api/auth-middleware.js +7 -7
- package/dist/api/auth-rate-limiters.js +7 -3
- package/dist/api/auth-routes-mfa.js +1 -1
- package/dist/api/auth-routes-session.js +1 -1
- package/dist/api/auth-routes-shared.js +7 -3
- package/dist/api/auth-routes-signup.js +1 -1
- package/dist/api/client-error-route.js +8 -2
- package/dist/api/client-ip.js +3 -1
- package/dist/api/extra-route.js +1 -1
- package/dist/api/index.d.ts +3 -1
- package/dist/api/index.js +3 -1
- package/dist/api/pii-leak-guard.js +4 -2
- package/dist/api/readiness.js +5 -5
- package/dist/api/redis-sse-broker.js +8 -6
- package/dist/api/request-context.d.ts +1 -1
- package/dist/api/request-context.js +1 -1
- package/dist/api/routes.js +2 -2
- package/dist/api/server-boot-checks.d.ts +10 -0
- package/dist/api/server-boot-checks.js +157 -0
- package/dist/api/server-event-dispatcher.d.ts +26 -0
- package/dist/api/server-event-dispatcher.js +208 -0
- package/dist/api/server-extra-routes.d.ts +11 -0
- package/dist/api/server-extra-routes.js +203 -0
- package/dist/api/server-middleware.d.ts +20 -0
- package/dist/api/server-middleware.js +211 -0
- package/dist/api/server-routes.d.ts +19 -0
- package/dist/api/server-routes.js +293 -0
- package/dist/api/server-websocket-routes.d.ts +4 -0
- package/dist/api/server-websocket-routes.js +108 -0
- package/dist/api/server-wiring.d.ts +32 -0
- package/dist/api/server-wiring.js +236 -0
- package/dist/api/server.d.ts +10 -15
- package/dist/api/server.js +48 -1250
- package/dist/api/session-cookies.js +4 -4
- package/dist/api/sse-broker.js +1 -1
- package/dist/api/sse-route.d.ts +13 -13
- package/dist/api/sse-route.js +31 -27
- package/dist/auth/index.js +4 -4
- package/dist/auth/roles.d.ts +4 -4
- package/dist/auth/roles.js +24 -24
- package/dist/compliance/duration-spec.js +18 -20
- package/dist/compliance/index.js +2 -3
- package/dist/compliance/override-schema.d.ts +4 -4
- package/dist/compliance/override-schema.js +19 -22
- package/dist/compliance/profiles.d.ts +26 -29
- package/dist/compliance/profiles.js +62 -69
- package/dist/compliance/sub-processors.d.ts +28 -30
- package/dist/compliance/sub-processors.js +17 -21
- package/dist/consumer-cli.js +4 -4
- package/dist/crypto/blind-index.js +18 -17
- package/dist/crypto/ciphertext-pattern.js +1 -1
- package/dist/crypto/event-pii.js +3 -3
- package/dist/crypto/kek-source.d.ts +1 -1
- package/dist/crypto/kek-source.js +3 -2
- package/dist/crypto/kms-adapter.d.ts +1 -1
- package/dist/crypto/kms-adapter.js +4 -6
- package/dist/crypto/kms-wiring.d.ts +1 -2
- package/dist/crypto/kms-wiring.js +2 -2
- package/dist/crypto/owner-transition-rekey.d.ts +5 -1
- package/dist/crypto/owner-transition-rekey.js +1 -1
- package/dist/crypto/pg-kms-adapter.js +2 -6
- package/dist/crypto/pii-field-encryption.d.ts +5 -1
- package/dist/crypto/pii-field-encryption.js +7 -5
- package/dist/crypto/subject-resolver.d.ts +1 -1
- package/dist/crypto/subject-resolver.js +2 -2
- package/dist/db/aggregate-sql.d.ts +21 -0
- package/dist/db/aggregate-sql.js +155 -0
- package/dist/db/apply-entity-event.d.ts +6 -6
- package/dist/db/apply-entity-event.js +55 -55
- package/dist/db/blind-index-cleanup.js +7 -7
- package/dist/db/closed-connection.d.ts +9 -0
- package/dist/db/closed-connection.js +95 -0
- package/dist/db/collect-table-metas.js +10 -11
- package/dist/db/compound-types.d.ts +1 -1
- package/dist/db/compound-types.js +12 -12
- package/dist/db/cursor.js +3 -4
- package/dist/db/dialect.d.ts +2 -2
- package/dist/db/dialect.js +3 -3
- package/dist/db/distinct-on.d.ts +1 -1
- package/dist/db/driver-row-coercion.d.ts +2 -0
- package/dist/db/driver-row-coercion.js +186 -0
- package/dist/db/driver-value-preparation.d.ts +16 -0
- package/dist/db/driver-value-preparation.js +99 -0
- package/dist/db/eagerload.d.ts +3 -3
- package/dist/db/eagerload.js +21 -12
- package/dist/db/entity-field-encryption.d.ts +1 -0
- package/dist/db/entity-field-encryption.js +1 -1
- package/dist/db/entity-table-meta.d.ts +2 -2
- package/dist/db/entity-table-meta.js +105 -112
- package/dist/db/event-store-executor-context.d.ts +3 -2
- package/dist/db/event-store-executor-context.js +13 -13
- package/dist/db/event-store-executor-read-aggregate.d.ts +8 -0
- package/dist/db/event-store-executor-read-aggregate.js +112 -0
- package/dist/db/event-store-executor-read-filter.d.ts +31 -0
- package/dist/db/event-store-executor-read-filter.js +203 -0
- package/dist/db/event-store-executor-read-paging.d.ts +14 -0
- package/dist/db/event-store-executor-read-paging.js +99 -0
- package/dist/db/event-store-executor-read-rows.d.ts +6 -0
- package/dist/db/event-store-executor-read-rows.js +32 -0
- package/dist/db/event-store-executor-read-search.d.ts +28 -0
- package/dist/db/event-store-executor-read-search.js +221 -0
- package/dist/db/event-store-executor-read-sort.d.ts +41 -0
- package/dist/db/event-store-executor-read-sort.js +130 -0
- package/dist/db/event-store-executor-read-where.d.ts +24 -0
- package/dist/db/event-store-executor-read-where.js +81 -0
- package/dist/db/event-store-executor-read.d.ts +2 -9
- package/dist/db/event-store-executor-read.js +50 -704
- package/dist/db/event-store-executor-write-steps.d.ts +20 -0
- package/dist/db/event-store-executor-write-steps.js +100 -0
- package/dist/db/event-store-executor-write.js +401 -510
- package/dist/db/index.d.ts +6 -2
- package/dist/db/index.js +5 -1
- package/dist/db/list-aggregate-labels.d.ts +14 -0
- package/dist/db/list-aggregate-labels.js +26 -0
- package/dist/db/located-timestamp.d.ts +11 -11
- package/dist/db/located-timestamp.js +29 -30
- package/dist/db/migrate-generator.d.ts +1 -1
- package/dist/db/migrate-generator.js +97 -105
- package/dist/db/migrate-runner.js +29 -26
- package/dist/db/money.d.ts +6 -6
- package/dist/db/money.js +29 -27
- package/dist/db/queries/backfill-pii.js +5 -5
- package/dist/db/queries/ddl.js +1 -1
- package/dist/db/queries/es-ops.d.ts +1 -1
- package/dist/db/queries/es-ops.js +1 -1
- package/dist/db/queries/event-consumer.js +3 -3
- package/dist/db/queries/event-store.js +4 -2
- package/dist/db/queries/projection-rebuild.js +3 -3
- package/dist/db/queries/raw-sql.d.ts +2 -2
- package/dist/db/queries/raw-sql.js +2 -2
- package/dist/db/queries/shadow-swap.js +19 -19
- package/dist/db/query.d.ts +3 -16
- package/dist/db/query.js +8 -761
- package/dist/db/rebuild-marker.js +20 -21
- package/dist/db/reference-data.js +6 -1
- package/dist/db/replay-migration-sql.js +2 -2
- package/dist/db/schema-inspection.js +4 -5
- package/dist/db/table-builder.d.ts +1 -2
- package/dist/db/table-builder.js +137 -190
- package/dist/db/table-info.d.ts +10 -0
- package/dist/db/table-info.js +45 -0
- package/dist/db/temporal-value-guards.d.ts +6 -0
- package/dist/db/temporal-value-guards.js +15 -0
- package/dist/db/tenant-db-runner.d.ts +1 -0
- package/dist/db/tenant-db-runner.js +3 -0
- package/dist/db/tenant-db.d.ts +2 -2
- package/dist/db/tenant-db.js +48 -11
- package/dist/db/where-clause.d.ts +6 -0
- package/dist/db/where-clause.js +236 -0
- package/dist/derivatives/delete-stored-file.js +6 -2
- package/dist/derivatives/derivatives-context.js +1 -1
- package/dist/engine/boot-validator/access-roles.js +4 -3
- package/dist/engine/boot-validator/api-ext.js +14 -14
- package/dist/engine/boot-validator/boot-check.js +1 -1
- package/dist/engine/boot-validator/config-deps.js +7 -6
- package/dist/engine/boot-validator/detail-screens.js +4 -4
- package/dist/engine/boot-validator/entity-handler.d.ts +1 -0
- package/dist/engine/boot-validator/entity-handler.js +77 -61
- package/dist/engine/boot-validator/form-derivations.js +35 -1
- package/dist/engine/boot-validator/gdpr-storage.js +4 -4
- package/dist/engine/boot-validator/i18n-keys.js +6 -4
- package/dist/engine/boot-validator/index.d.ts +2 -2
- package/dist/engine/boot-validator/index.js +22 -20
- package/dist/engine/boot-validator/nav.js +5 -5
- package/dist/engine/boot-validator/ownership.js +12 -9
- package/dist/engine/boot-validator/parent-ref.js +1 -1
- package/dist/engine/boot-validator/pii-retention.js +258 -187
- package/dist/engine/boot-validator/projection-list-screens.js +7 -7
- package/dist/engine/boot-validator/query-refs.js +1 -1
- package/dist/engine/boot-validator/screens-actions.d.ts +1 -0
- package/dist/engine/boot-validator/screens-actions.js +23 -17
- package/dist/engine/boot-validator/screens-dashboard.js +2 -5
- package/dist/engine/boot-validator/screens-forms.js +12 -17
- package/dist/engine/boot-validator/screens-kind-config-edit.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-config-edit.js +88 -0
- package/dist/engine/boot-validator/screens-kind-entity-edit.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-entity-edit.js +55 -0
- package/dist/engine/boot-validator/screens-kind-entity-list.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-entity-list.js +228 -0
- package/dist/engine/boot-validator/screens-kind-projection-detail.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-projection-detail.js +235 -0
- package/dist/engine/boot-validator/screens-kind-projection-list.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-projection-list.js +52 -0
- package/dist/engine/boot-validator/screens-kind-secret-mint.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-secret-mint.js +28 -0
- package/dist/engine/boot-validator/screens-kind-shared.d.ts +37 -0
- package/dist/engine/boot-validator/screens-kind-shared.js +142 -0
- package/dist/engine/boot-validator/screens-lists.d.ts +2 -1
- package/dist/engine/boot-validator/screens-lists.js +26 -24
- package/dist/engine/boot-validator/screens.d.ts +0 -2
- package/dist/engine/boot-validator/screens.js +102 -869
- package/dist/engine/boot-validator/security-baseline.js +3 -2
- package/dist/engine/boot-validator/transfer-graph.js +2 -2
- package/dist/engine/boot-validator/workspaces.js +3 -3
- package/dist/engine/bridge-stub.js +3 -4
- package/dist/engine/build-app-schema.js +130 -170
- package/dist/engine/build-config-feature-schema.js +50 -50
- package/dist/engine/build-target.js +20 -23
- package/dist/engine/codemod/pipeline-codemod.js +20 -13
- package/dist/engine/config-helpers.js +4 -4
- package/dist/engine/constants.js +2 -2
- package/dist/engine/create-app.js +2 -2
- package/dist/engine/define-feature.js +21 -13
- package/dist/engine/define-handler.js +13 -11
- package/dist/engine/define-step.js +1 -1
- package/dist/engine/define-workflow.d.ts +5 -5
- package/dist/engine/define-workflow.js +6 -6
- package/dist/engine/entity-handlers.d.ts +13 -0
- package/dist/engine/entity-handlers.js +22 -34
- package/dist/engine/entity-list-runtime-options.d.ts +8 -0
- package/dist/engine/entity-list-runtime-options.js +18 -0
- package/dist/engine/event-def.js +2 -2
- package/dist/engine/extension-names.d.ts +16 -17
- package/dist/engine/extension-names.js +37 -38
- package/dist/engine/extensions/escape-hatch-usage.js +1 -1
- package/dist/engine/extensions/tenant-data.js +2 -2
- package/dist/engine/extensions/user-data.d.ts +23 -24
- package/dist/engine/factories.d.ts +14 -13
- package/dist/engine/factories.js +38 -37
- package/dist/engine/feature-ast/entity-field-types.js +1 -1
- package/dist/engine/feature-ast/extractors/handlers.js +2 -1
- package/dist/engine/feature-ast/extractors/hooks.js +1 -1
- package/dist/engine/feature-ast/extractors/round2.js +25 -6
- package/dist/engine/feature-ast/extractors/shared.d.ts +2 -3
- package/dist/engine/feature-ast/extractors/shared.js +2 -3
- package/dist/engine/feature-ast/parse.js +13 -13
- package/dist/engine/feature-ast/patch.js +4 -182
- package/dist/engine/feature-ast/pattern-change-schema.d.ts +3 -0
- package/dist/engine/feature-ast/pattern-change-schema.js +2 -1
- package/dist/engine/feature-ast/pattern-id-matchers.d.ts +7 -0
- package/dist/engine/feature-ast/pattern-id-matchers.js +210 -0
- package/dist/engine/feature-ast/patterns.d.ts +11 -2
- package/dist/engine/feature-ast/patterns.js +43 -51
- package/dist/engine/feature-ast/render.js +50 -89
- package/dist/engine/feature-config-events-jobs.js +15 -12
- package/dist/engine/feature-entity-handlers.js +12 -5
- package/dist/engine/feature-manifest.d.ts +9 -9
- package/dist/engine/feature-manifest.js +6 -7
- package/dist/engine/feature-ui-extensions.d.ts +3 -3
- package/dist/engine/feature-ui-extensions.js +30 -22
- package/dist/engine/field-access.js +5 -6
- package/dist/engine/form-derivations.js +18 -7
- package/dist/engine/handler-field-references.js +1 -1
- package/dist/engine/index.d.ts +1 -0
- package/dist/engine/index.js +4 -4
- package/dist/engine/object-form.d.ts +1 -0
- package/dist/engine/object-form.js +14 -4
- package/dist/engine/ownership.js +3 -3
- package/dist/engine/parse-ref-target.js +5 -7
- package/dist/engine/pattern-library/index.js +2 -2
- package/dist/engine/pattern-library/library.js +2 -2
- package/dist/engine/pattern-library/types.js +3 -3
- package/dist/engine/pipeline.js +2 -2
- package/dist/engine/project-app-schema-for-roles.d.ts +2 -0
- package/dist/engine/project-app-schema-for-roles.js +7 -5
- package/dist/engine/projection-helpers.js +9 -9
- package/dist/engine/qualified-name.js +2 -2
- package/dist/engine/registry-facade.js +1 -1
- package/dist/engine/registry-ingest.js +13 -13
- package/dist/engine/registry-state.js +17 -19
- package/dist/engine/registry-validate.js +12 -12
- package/dist/engine/run-in.js +2 -2
- package/dist/engine/run-pipeline.js +7 -0
- package/dist/engine/schema-builder.js +251 -233
- package/dist/engine/screen-filter-ops.js +17 -20
- package/dist/engine/screen-helpers.js +4 -3
- package/dist/engine/screen-kind.d.ts +7 -0
- package/dist/engine/screen-kind.js +1 -0
- package/dist/engine/state-machine.d.ts +12 -12
- package/dist/engine/state-machine.js +7 -7
- package/dist/engine/steps/_resolver-utils.js +4 -3
- package/dist/engine/steps/for-each.js +4 -4
- package/dist/engine/steps/unsafe-projection-delete.js +1 -1
- package/dist/engine/steps/unsafe-projection-upsert.js +4 -4
- package/dist/engine/steps/wait-for-event.js +4 -4
- package/dist/engine/steps/workflow-system-events.js +3 -3
- package/dist/engine/strip-disabled-features-from-app-schema.js +51 -14
- package/dist/engine/tier-resolver-extension.d.ts +29 -27
- package/dist/engine/tier-resolver-extension.js +26 -26
- package/dist/engine/transfer-adjacency.js +2 -2
- package/dist/engine/validate-projection-allowlist.js +9 -28
- package/dist/engine/walk-step-instances.d.ts +2 -0
- package/dist/engine/walk-step-instances.js +38 -0
- package/dist/engine/where-rule-lint.js +1 -1
- package/dist/engine/write-handler-qn-extract.js +1 -1
- package/dist/entrypoint/index.d.ts +4 -1
- package/dist/entrypoint/index.js +10 -4
- package/dist/env/index.d.ts +7 -6
- package/dist/env/index.js +10 -9
- package/dist/errors/docs-url.d.ts +1 -1
- package/dist/errors/docs-url.js +22 -2
- package/dist/errors/transition-details.js +7 -7
- package/dist/errors/write-error-info.d.ts +6 -6
- package/dist/errors/write-error-info.js +6 -6
- package/dist/es-ops/context.d.ts +9 -9
- package/dist/es-ops/context.js +29 -29
- package/dist/es-ops/index.js +7 -9
- package/dist/es-ops/operations-schema.js +4 -10
- package/dist/es-ops/runner.d.ts +11 -11
- package/dist/es-ops/runner.js +49 -53
- package/dist/es-ops/types.d.ts +55 -55
- package/dist/es-ops/types.js +11 -11
- package/dist/event-store/admin-api.js +7 -8
- package/dist/event-store/errors.js +1 -1
- package/dist/event-store/event-store.js +12 -6
- package/dist/event-store/rebuild-dead-letter.js +1 -1
- package/dist/files/bind-pending-file-refs.js +3 -3
- package/dist/files/create-file-ref-from-bytes.js +4 -1
- package/dist/files/feature.js +9 -10
- package/dist/files/file-handle.js +7 -9
- package/dist/files/file-ref-entity.js +15 -15
- package/dist/files/file-ref-table.js +7 -8
- package/dist/files/file-routes.d.ts +7 -0
- package/dist/files/file-routes.js +22 -13
- package/dist/files/in-memory-provider.js +8 -9
- package/dist/files/local-provider.js +18 -25
- package/dist/files/provider-resolver.d.ts +7 -7
- package/dist/files/resolve-content-type.js +43 -0
- package/dist/files/storage-tracking.js +2 -2
- package/dist/files/upload-ledger.js +7 -0
- package/dist/files/zip-stream.d.ts +12 -19
- package/dist/files/zip-stream.js +44 -63
- package/dist/i18n/required-surface-keys.d.ts +1 -1
- package/dist/i18n/required-surface-keys.js +188 -212
- package/dist/internal/stack-support.d.ts +2 -1
- package/dist/internal/stack-support.js +1 -1
- package/dist/jobs/job-runner-context.d.ts +32 -0
- package/dist/jobs/job-runner-context.js +305 -0
- package/dist/jobs/job-runner-execution.d.ts +7 -0
- package/dist/jobs/job-runner-execution.js +160 -0
- package/dist/jobs/job-runner-gates.d.ts +19 -0
- package/dist/jobs/job-runner-gates.js +198 -0
- package/dist/jobs/job-runner-helpers.d.ts +17 -3
- package/dist/jobs/job-runner-helpers.js +69 -4
- package/dist/jobs/job-runner-schedulers.d.ts +1 -1
- package/dist/jobs/job-runner-schedulers.js +3 -4
- package/dist/jobs/job-runner-scope.d.ts +44 -0
- package/dist/jobs/job-runner-scope.js +102 -0
- package/dist/jobs/job-runner-types.d.ts +12 -0
- package/dist/jobs/job-runner.d.ts +0 -1
- package/dist/jobs/job-runner.js +57 -669
- package/dist/lifecycle/lifecycle.js +3 -5
- package/dist/lifecycle/signal-handlers.js +5 -4
- package/dist/logging/utils.d.ts +2 -1
- package/dist/logging/utils.js +38 -10
- package/dist/migrations/index.js +1 -1
- package/dist/migrations/kumiko-drift.js +14 -13
- package/dist/migrations/pending-rebuilds.d.ts +21 -20
- package/dist/migrations/pending-rebuilds.js +27 -27
- package/dist/migrations/projection-table-index.d.ts +3 -3
- package/dist/migrations/projection-table-index.js +8 -8
- package/dist/observability/escape-hatch-report.d.ts +3 -0
- package/dist/observability/escape-hatch-report.js +12 -1
- package/dist/observability/metric-validator.js +1 -1
- package/dist/observability/metrics-handle.js +3 -3
- package/dist/pipeline/append-event-core.js +11 -2
- package/dist/pipeline/cascade-handler.d.ts +1 -1
- package/dist/pipeline/cascade-handler.js +165 -138
- package/dist/pipeline/dispatch-batch.js +2 -2
- package/dist/pipeline/dispatch-query.js +20 -13
- package/dist/pipeline/dispatch-shared.d.ts +14 -3
- package/dist/pipeline/dispatch-shared.js +67 -721
- package/dist/pipeline/dispatch-stream.js +1 -1
- package/dist/pipeline/dispatch-write.js +297 -190
- package/dist/pipeline/dispatcher-utils.d.ts +1 -1
- package/dist/pipeline/dispatcher-utils.js +1 -1
- package/dist/pipeline/event-consumer-state.js +2 -2
- package/dist/pipeline/event-dispatcher-admin.js +2 -1
- package/dist/pipeline/event-dispatcher-delivery.js +4 -6
- package/dist/pipeline/event-dispatcher.js +17 -28
- package/dist/pipeline/handler-context-auth.d.ts +9 -0
- package/dist/pipeline/handler-context-auth.js +54 -0
- package/dist/pipeline/handler-context-config.d.ts +14 -0
- package/dist/pipeline/handler-context-config.js +113 -0
- package/dist/pipeline/handler-context-db.d.ts +24 -0
- package/dist/pipeline/handler-context-db.js +149 -0
- package/dist/pipeline/handler-context-dispatch.d.ts +21 -0
- package/dist/pipeline/handler-context-dispatch.js +89 -0
- package/dist/pipeline/handler-context-events.d.ts +43 -0
- package/dist/pipeline/handler-context-events.js +237 -0
- package/dist/pipeline/handler-context-notify.d.ts +12 -0
- package/dist/pipeline/handler-context-notify.js +55 -0
- package/dist/pipeline/handler-context-observability.d.ts +7 -0
- package/dist/pipeline/handler-context-observability.js +21 -0
- package/dist/pipeline/handler-context-scope.d.ts +48 -0
- package/dist/pipeline/handler-context-scope.js +88 -0
- package/dist/pipeline/irreversible-operation-gate.js +1 -1
- package/dist/pipeline/lifecycle-pipeline.js +9 -9
- package/dist/pipeline/member-read-only-transaction.js +1 -3
- package/dist/pipeline/msp-rebuild.js +1 -1
- package/dist/pipeline/notify-scope.js +12 -1
- package/dist/pipeline/pre-handler-gates.js +20 -4
- package/dist/pipeline/pre-transaction-reservations.d.ts +1 -0
- package/dist/pipeline/pre-transaction-reservations.js +9 -3
- package/dist/pipeline/projection-rebuild.js +15 -13
- package/dist/pipeline/system-hooks.js +39 -41
- package/dist/pipeline/system-identity-switch.js +1 -3
- package/dist/pipeline/tenant-timezone-cache.js +1 -1
- package/dist/random/generate.d.ts +29 -29
- package/dist/random/generate.js +30 -30
- package/dist/random/words.js +20 -20
- package/dist/rate-limit/middleware.js +9 -5
- package/dist/redis/client.js +2 -2
- package/dist/redis/pubsub-signal.js +14 -17
- package/dist/schema-cli/apply-command.d.ts +2 -0
- package/dist/schema-cli/apply-command.js +97 -0
- package/dist/schema-cli/baseline-command.d.ts +2 -0
- package/dist/schema-cli/baseline-command.js +33 -0
- package/dist/schema-cli/generate-command.d.ts +2 -0
- package/dist/schema-cli/generate-command.js +90 -0
- package/dist/schema-cli/shared.d.ts +39 -0
- package/dist/schema-cli/shared.js +95 -0
- package/dist/schema-cli/status-command.d.ts +2 -0
- package/dist/schema-cli/status-command.js +73 -0
- package/dist/schema-cli/validate-boot-input.d.ts +5 -0
- package/dist/schema-cli/validate-boot-input.js +130 -0
- package/dist/schema-cli/validate-command.d.ts +2 -0
- package/dist/schema-cli/validate-command.js +130 -0
- package/dist/schema-cli.d.ts +2 -18
- package/dist/schema-cli.js +47 -510
- package/dist/search/index.js +4 -4
- package/dist/search/meilisearch-adapter.js +2 -1
- package/dist/search/purge-subject.js +4 -5
- package/dist/search/reindex-entity.js +6 -9
- package/dist/time/boot-tz-warning.d.ts +2 -2
- package/dist/time/boot-tz-warning.js +8 -8
- package/dist/time/iana.js +10 -10
- package/dist/time/index.js +9 -9
- package/dist/time/legacy-date.d.ts +2 -2
- package/dist/time/legacy-date.js +6 -8
- package/dist/time/polyfill.js +1 -1
- package/dist/time/tz-context.d.ts +1 -1
- package/dist/time/tz-context.js +1 -1
- package/dist/ui-types/app-schema.js +7 -7
- package/dist/ui-types/list-row-meta.js +4 -4
- package/dist/upgrade-cli.js +159 -130
- package/dist/utils/compare.js +1 -1
- package/package.json +5 -5
- package/src/changes.json +358 -0
- package/src/scripts/codemod/crypto-shredding-testing-move.ts +2 -2
- package/src/scripts/codemod/feature-layout.ts +10 -2
- package/src/scripts/codemod/migrate-cross-tenant.ts +1 -1
- package/src/scripts/codemod/migrate-open-to-all.ts +1 -1
- package/src/scripts/codemod/object-form.ts +41 -4
- package/src/scripts/codemod/package-merge.ts +58 -8
- package/src/scripts/codemod/pii-personal-migration.ts +192 -153
- package/src/scripts/codemod/testing-injection.ts +122 -42
- package/src/scripts/codemod/testing-move.ts +29 -7
- package/src/scripts/codemod/unprocessable-error-details-reason.ts +2 -2
package/dist/engine/factories.js
CHANGED
|
@@ -24,7 +24,7 @@ function resolvePersonalFlags(personal, reason) {
|
|
|
24
24
|
userOwned: { ownerField: personal.of, ...(whenAbsent !== undefined && { whenAbsent }) },
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
-
// Resolves the author-facing `personal`/`find` annotations
|
|
27
|
+
// Resolves the author-facing `personal`/`find` annotations
|
|
28
28
|
// into the internal ResolvedPiiFlags every factory below merges into its
|
|
29
29
|
// return value. `personal`, `find`, `reason` never survive into the field def.
|
|
30
30
|
function expandPersonalAnnotations(overrides) {
|
|
@@ -73,7 +73,7 @@ function missingTextFieldStanceError(factoryName) {
|
|
|
73
73
|
function isNonEmptyString(value) {
|
|
74
74
|
return typeof value === "string" && value.trim().length > 0;
|
|
75
75
|
}
|
|
76
|
-
// Fail-closed stance gate
|
|
76
|
+
// Fail-closed stance gate for the two text-shaped
|
|
77
77
|
// factories — runs before expandPersonalAnnotations so an untyped JS caller
|
|
78
78
|
// (no compiler to stop it) can't slip an unannotated text field past the
|
|
79
79
|
// type layer either. The typed signature above already rejects a
|
|
@@ -109,13 +109,12 @@ function assertTextFieldStance(factoryName, overrides) {
|
|
|
109
109
|
throw missingTextFieldStanceError(factoryName);
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
|
-
//
|
|
113
|
-
// `createTextField({ required: true })` literal `required: true`
|
|
114
|
-
//
|
|
115
|
-
// Mapped-Type
|
|
116
|
-
// `
|
|
117
|
-
//
|
|
118
|
-
// in jeder required-bearing factory unten.
|
|
112
|
+
// Use generic `R extends true | false` instead of `boolean` so
|
|
113
|
+
// `createTextField({ required: true })` preserves the literal `required: true`
|
|
114
|
+
// in the return type. Widening to `boolean` would prevent EntityTable<E>'s
|
|
115
|
+
// Mapped-Type from distinguishing `required: true` from `required: false`,
|
|
116
|
+
// making every column nullable. Default `R = false` matches the runtime
|
|
117
|
+
// default. This pattern is used in every required-bearing factory below.
|
|
119
118
|
export function createTextField(overrides) {
|
|
120
119
|
assertTextFieldStance("createTextField", overrides);
|
|
121
120
|
return {
|
|
@@ -129,13 +128,13 @@ export function createTextField(overrides) {
|
|
|
129
128
|
}
|
|
130
129
|
/**
|
|
131
130
|
* Long-form text field for source-code, markdown, blog-posts, email-
|
|
132
|
-
* templates — anything that can be megabytes large.
|
|
133
|
-
* from `text`:
|
|
134
|
-
* DB
|
|
131
|
+
* templates — anything that can be megabytes large. Its type-level API
|
|
132
|
+
* differs from `text`: it has no sortable/searchable/filterable/format options.
|
|
133
|
+
* The DB mapping is identical to text (`PG text` is unbounded).
|
|
135
134
|
*
|
|
136
|
-
* Soft-cap default:
|
|
137
|
-
*
|
|
138
|
-
*
|
|
135
|
+
* Soft-cap default: no maxLength (`PG text` has a 1 GB hard limit).
|
|
136
|
+
* Set an explicit `maxLength` to reject an accidental browser paste early
|
|
137
|
+
* (for example, `1_000_000 = 1 MB`).
|
|
139
138
|
*/
|
|
140
139
|
/**
|
|
141
140
|
* Read-time computed field for `EntityDefinition.derivedFields` (NOT `fields`).
|
|
@@ -277,10 +276,10 @@ export function createEmbeddedListField(schema, overrides) {
|
|
|
277
276
|
multiple: true,
|
|
278
277
|
};
|
|
279
278
|
}
|
|
280
|
-
// Free-form jsonb
|
|
281
|
-
// `{}`, NOT NULL.
|
|
282
|
-
// `customFields
|
|
283
|
-
// inferred
|
|
279
|
+
// Free-form jsonb column — see the `JsonbFieldDef` documentation. Schema-less,
|
|
280
|
+
// defaults to `{}`, and is NOT NULL. Primarily used by the custom-fields
|
|
281
|
+
// bundle for the host entity's `customFields` column; other valid uses include
|
|
282
|
+
// tenant configuration blobs, AI-inferred metadata, and future tag arrays.
|
|
284
283
|
export function createJsonbField(overrides) {
|
|
285
284
|
return {
|
|
286
285
|
type: "jsonb",
|
|
@@ -295,17 +294,17 @@ export function createDateField(overrides) {
|
|
|
295
294
|
}; // @cast-boundary engine-payload
|
|
296
295
|
}
|
|
297
296
|
/**
|
|
298
|
-
* UTC
|
|
299
|
-
* (createdAt, loginAt, actualPickupAt). Temporal.Instant
|
|
297
|
+
* UTC instant for events occurring at a specific point in time
|
|
298
|
+
* (createdAt, loginAt, actualPickupAt). Uses Temporal.Instant internally.
|
|
300
299
|
*
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
300
|
+
* With `locatedBy: "<name>Tz"`, the field becomes a wall-clock pair for an
|
|
301
|
+
* appointment at a location — prefer `createLocatedTimestampField()` instead,
|
|
302
|
+
* which creates one atomic field rather than a loosely connected pair.
|
|
304
303
|
*/
|
|
305
304
|
export function createTimestampField(overrides) {
|
|
306
|
-
//
|
|
307
|
-
//
|
|
308
|
-
//
|
|
305
|
+
// Building the object this way avoids hardcoding `required: false` in the
|
|
306
|
+
// literal, which would make TypeScript widen R to `boolean` instead of
|
|
307
|
+
// inferring the `true`/`false` literal from the overrides argument.
|
|
309
308
|
return {
|
|
310
309
|
...expandPersonalAnnotations(overrides),
|
|
311
310
|
type: "timestamp",
|
|
@@ -313,8 +312,9 @@ export function createTimestampField(overrides) {
|
|
|
313
312
|
};
|
|
314
313
|
}
|
|
315
314
|
/**
|
|
316
|
-
* IANA-
|
|
317
|
-
*
|
|
315
|
+
* IANA time-zone name (for example, "Europe/Berlin"). The boot/schema
|
|
316
|
+
* validator checks it using `Intl.supportedValuesOf("timeZone")` during the
|
|
317
|
+
* Zod step.
|
|
318
318
|
*/
|
|
319
319
|
export function createTzField(overrides) {
|
|
320
320
|
return {
|
|
@@ -372,14 +372,15 @@ export function createFilesField(overrides) {
|
|
|
372
372
|
export function createImagesField(overrides) {
|
|
373
373
|
return { type: "images", ...expandPersonalAnnotations(overrides) };
|
|
374
374
|
}
|
|
375
|
-
// `F`
|
|
376
|
-
//
|
|
377
|
-
// boolean).
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
//
|
|
381
|
-
// `const F
|
|
382
|
-
// `type`
|
|
375
|
+
// Leave `F` unconstrained so TypeScript preserves the literal types of
|
|
376
|
+
// individual field definitions (`required: true` remains `true`, not
|
|
377
|
+
// `boolean`). Constraining it to FieldsMap would widen them — see the
|
|
378
|
+
// TypeScript issue concerning constraint inference for structural records.
|
|
379
|
+
// Instead, conformance is validated through the conditional return type: if F
|
|
380
|
+
// is not compatible with FieldsMap, the return type collapses to `never`.
|
|
381
|
+
// `const F` preserves the `type` literal in inline field literals
|
|
382
|
+
// (`{ type: "reference", ... }`) without `as const`; otherwise it widens to
|
|
383
|
+
// string and produces `never`.
|
|
383
384
|
export function createEntity(def) {
|
|
384
385
|
return {
|
|
385
386
|
softDelete: false,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Shared field-type validation for EntityDefinition. Used by both the
|
|
2
2
|
// static extractor (extractEntity, parse-time ParseError) and the runtime
|
|
3
3
|
// PatternChange validator (pattern-change-schema.ts) so the two never drift
|
|
4
|
-
// into reporting different "unknown field type" catalogues
|
|
4
|
+
// into reporting different "unknown field type" catalogues.
|
|
5
5
|
import { FIELD_TYPE_NAMES } from "@cosmicdrift/kumiko-types/fields";
|
|
6
6
|
import { isPlainObject, isRawRefSentinel } from "./extractors/shared.js";
|
|
7
7
|
/**
|
|
@@ -33,6 +33,7 @@ const WRITE_HANDLER_KEY_KINDS = {
|
|
|
33
33
|
unsafeSkipTransitionGuard: "modeled",
|
|
34
34
|
rateLimit: "modeled",
|
|
35
35
|
additionalRateLimits: "modeled",
|
|
36
|
+
rateLimitCost: "opaque",
|
|
36
37
|
escapeHatch: "modeled",
|
|
37
38
|
tenantlessAnonymous: "opaque",
|
|
38
39
|
reserveBeforeTransaction: "opaque",
|
|
@@ -256,7 +257,7 @@ export function parseHandlerCall(call, sourceFile, methodName) {
|
|
|
256
257
|
// (`r.writeHandler(eventCreateHandler)`, `r.queryHandler(someQuery())`)
|
|
257
258
|
// that resolveObjectLiteralArg above couldn't turn into an object literal
|
|
258
259
|
// (imported binding, factory call, ...). Keep it recognised as this kind
|
|
259
|
-
// instead of ParseErroring
|
|
260
|
+
// instead of ParseErroring. Opaque: renderWriteHandler/
|
|
260
261
|
// renderQueryHandler re-emit `source.raw` verbatim when handlerName is
|
|
261
262
|
// undefined.
|
|
262
263
|
if (args.length === 1 && isRawRefSentinel(readDataLiteralNode(first))) {
|
|
@@ -230,7 +230,7 @@ export function extractHook(call, sourceFile) {
|
|
|
230
230
|
...escapeHatchOutcome,
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
|
-
// guard:dup-ok —
|
|
233
|
+
// guard:dup-ok — intentional parallel to extractTree; different Feature-AST extractors by design
|
|
234
234
|
export function extractAuthClaims(call, sourceFile) {
|
|
235
235
|
const arg = call.getArguments()[0];
|
|
236
236
|
if (!arg) {
|
|
@@ -2,19 +2,36 @@ import { SyntaxKind } from "ts-morph";
|
|
|
2
2
|
import { describeUnknownFieldType, findUnknownEntityFieldTypes } from "../entity-field-types.js";
|
|
3
3
|
import { sourceLocationFromNode } from "../source-location.js";
|
|
4
4
|
import { fail, isPlainObject, isRawRefSentinel, ok, readDataLiteralNode, readNameLiteral, readNameOrRef, } from "./shared.js";
|
|
5
|
+
function readBackingTableRef(property) {
|
|
6
|
+
const initializer = property.asKind(SyntaxKind.PropertyAssignment)?.getInitializer() ??
|
|
7
|
+
property.asKind(SyntaxKind.ShorthandPropertyAssignment)?.getNameNode();
|
|
8
|
+
const reference = initializer ? readDataLiteralNode(initializer) : undefined;
|
|
9
|
+
return isRawRefSentinel(reference) ? reference : undefined;
|
|
10
|
+
}
|
|
5
11
|
// `{ name: "x", ...xEntity }` — the definition is a reference the parser cannot
|
|
6
12
|
// inline, so it is kept as a raw-ref sentinel and re-rendered as the same spread.
|
|
7
13
|
// `backingTable` is runtime wiring (a table identifier), not part of the
|
|
8
|
-
// definition data, so it
|
|
14
|
+
// definition data, so it is carried next to the definition and skipped by the shape check.
|
|
9
15
|
function readSpreadOnlyDefinition(obj) {
|
|
10
|
-
const
|
|
11
|
-
.
|
|
12
|
-
|
|
16
|
+
const isBackingTable = (property) => {
|
|
17
|
+
const name = property.asKind(SyntaxKind.PropertyAssignment)?.getName() ??
|
|
18
|
+
property.asKind(SyntaxKind.ShorthandPropertyAssignment)?.getName();
|
|
19
|
+
return name === "backingTable";
|
|
20
|
+
};
|
|
21
|
+
const allProperties = obj.getProperties();
|
|
22
|
+
const properties = allProperties.filter((property) => !isBackingTable(property));
|
|
13
23
|
const spread = properties.length === 2 ? properties[1]?.asKind(SyntaxKind.SpreadAssignment) : undefined;
|
|
14
24
|
if (!spread)
|
|
15
25
|
return undefined;
|
|
16
26
|
const reference = readDataLiteralNode(spread.getExpression());
|
|
17
|
-
|
|
27
|
+
if (!isRawRefSentinel(reference))
|
|
28
|
+
return undefined;
|
|
29
|
+
const backingTableProperty = allProperties.find(isBackingTable);
|
|
30
|
+
const backingTable = backingTableProperty ? readBackingTableRef(backingTableProperty) : undefined;
|
|
31
|
+
// A backingTable that is not a plain reference cannot be re-rendered; fall back to the data reader.
|
|
32
|
+
if (backingTableProperty && !backingTable)
|
|
33
|
+
return undefined;
|
|
34
|
+
return { definition: reference, backingTable };
|
|
18
35
|
}
|
|
19
36
|
export function extractEntity(call, sourceFile) {
|
|
20
37
|
const args = call.getArguments();
|
|
@@ -32,7 +49,8 @@ export function extractEntity(call, sourceFile) {
|
|
|
32
49
|
if (!nameInit) {
|
|
33
50
|
return fail("entity", sourceLocationFromNode(call, sourceFile), "object form requires a string-literal `name` property");
|
|
34
51
|
}
|
|
35
|
-
const
|
|
52
|
+
const spreadOnly = readSpreadOnlyDefinition(obj);
|
|
53
|
+
const definition = spreadOnly?.definition ?? readDataLiteralNode(obj);
|
|
36
54
|
if (!isPlainObject(definition)) {
|
|
37
55
|
return fail("entity", sourceLocationFromNode(call, sourceFile), "definition could not be read as a plain object (contains functions or identifiers)");
|
|
38
56
|
}
|
|
@@ -49,6 +67,7 @@ export function extractEntity(call, sourceFile) {
|
|
|
49
67
|
// Field-type membership is checked above; the cast is the extractor's
|
|
50
68
|
// existing narrowing contract (readDataLiteralNode returns unknown).
|
|
51
69
|
definition: defWithoutName,
|
|
70
|
+
...(spreadOnly?.backingTable && { backingTable: spreadOnly.backingTable }),
|
|
52
71
|
});
|
|
53
72
|
}
|
|
54
73
|
const entityName = readNameLiteral(first);
|
|
@@ -47,8 +47,7 @@ export declare function readStringOrRaw(node: Node): string | RawRefSentinel | u
|
|
|
47
47
|
* Like readStringLiteralArgs, but an argument that resolves to a raw-ref
|
|
48
48
|
* sentinel is kept as that sentinel instead of failing the whole call. Used
|
|
49
49
|
* where a value stands in for a single name/key and inlining its resolved
|
|
50
|
-
* string would corrupt the render roundtrip (e.g. `r.requires(someFeature.name)`
|
|
51
|
-
* — see #1009).
|
|
50
|
+
* string would corrupt the render roundtrip (e.g. `r.requires(someFeature.name)`).
|
|
52
51
|
*/
|
|
53
52
|
export declare function readStringOrRawArgs(call: CallExpression): readonly (string | RawRefSentinel)[] | undefined;
|
|
54
53
|
export { isPlainObject } from "../../../utils/is-plain-object.ts";
|
|
@@ -67,7 +66,7 @@ export type NameLiteralRef = {
|
|
|
67
66
|
};
|
|
68
67
|
/**
|
|
69
68
|
* Like `readNameLiteral`, but for callers that must preserve an
|
|
70
|
-
* identifier-authored name across a render → parse round-trip
|
|
69
|
+
* identifier-authored name across a render → parse round-trip.
|
|
71
70
|
* `raw` is populated only when the node resolved via an identifier — a
|
|
72
71
|
* string-literal node has nothing worth preserving beyond its value, and
|
|
73
72
|
* setting `raw` for it too would make `JSON.stringify(value)` and
|
|
@@ -147,8 +147,7 @@ export function readStringOrRaw(node) {
|
|
|
147
147
|
* Like readStringLiteralArgs, but an argument that resolves to a raw-ref
|
|
148
148
|
* sentinel is kept as that sentinel instead of failing the whole call. Used
|
|
149
149
|
* where a value stands in for a single name/key and inlining its resolved
|
|
150
|
-
* string would corrupt the render roundtrip (e.g. `r.requires(someFeature.name)`
|
|
151
|
-
* — see #1009).
|
|
150
|
+
* string would corrupt the render roundtrip (e.g. `r.requires(someFeature.name)`).
|
|
152
151
|
*/
|
|
153
152
|
export function readStringOrRawArgs(call) {
|
|
154
153
|
const out = [];
|
|
@@ -229,7 +228,7 @@ function resolveIdentifierToStringLiteral(identifier) {
|
|
|
229
228
|
}
|
|
230
229
|
/**
|
|
231
230
|
* Like `readNameLiteral`, but for callers that must preserve an
|
|
232
|
-
* identifier-authored name across a render → parse round-trip
|
|
231
|
+
* identifier-authored name across a render → parse round-trip.
|
|
233
232
|
* `raw` is populated only when the node resolved via an identifier — a
|
|
234
233
|
* string-literal node has nothing worth preserving beyond its value, and
|
|
235
234
|
* setting `raw` for it too would make `JSON.stringify(value)` and
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
// - Top-level code outside `defineFeature(...)`. Designer/AI treat
|
|
18
18
|
// such files as "not a feature file".
|
|
19
19
|
//
|
|
20
|
-
// **Skeleton status
|
|
21
|
-
// Per-pattern extractors fill in iteratively
|
|
20
|
+
// **Skeleton status:** interface fixed, extractors are TODO.
|
|
21
|
+
// Per-pattern extractors fill in iteratively — each iteration adds
|
|
22
22
|
// one extractor + a focused test.
|
|
23
23
|
import { Project, SyntaxKind } from "ts-morph";
|
|
24
24
|
import { extractAiClassify, extractAiExtract, extractAiGenerate, extractAuthClaims, extractBootCheck, extractClaimKey, extractConfig, extractDefineEvent, extractDescribe, extractEntity, extractEnvSchema, extractExposesApi, extractExtendsRegistrar, extractHook, extractHttpRoute, extractJob, extractMetric, extractMultiStreamProjection, extractNav, extractNotification, extractOptionalRequires, extractProjection, extractQueryHandler, extractReadsConfig, extractReferenceData, extractRelation, extractRequires, extractScreen, extractSecret, extractSecretNamespace, extractStoreTable, extractStreamHandler, extractSystemScope, extractToggleable, extractTranslations, extractTreeActions, extractUiHints, extractUseExtension, extractUsesApi, extractWorkspace, extractWriteHandler, findFunctionLiteral, findImportBindingForLocalName, readObjectPropertyInitializer, resolveModuleFile, resolveSameFileObjectLiteral, } from "./extractors/index.js";
|
|
@@ -185,7 +185,7 @@ function walkSetupCallback(body, registrarParamName, sourceFile, patterns, error
|
|
|
185
185
|
// a registrar-wrapper call — a function that receives the registrar as
|
|
186
186
|
// a bare argument, e.g. `registerShowPonyScreens(r)`. Such wrappers are
|
|
187
187
|
// invisible to a receiver-shape match, so we resolve the callee (same
|
|
188
|
-
// file, or the declaring file of a named import
|
|
188
|
+
// file, or the declaring file of a named import) and recurse
|
|
189
189
|
// into its body with its own parameter name for the registrar slot.
|
|
190
190
|
const wrapper = resolveRegistrarWrapperCall(call, registrarParamName);
|
|
191
191
|
if (!wrapper)
|
|
@@ -368,7 +368,7 @@ function walkAiStepCalls(body, registrarParamName, sourceFile, patterns, errors,
|
|
|
368
368
|
}
|
|
369
369
|
}
|
|
370
370
|
// =============================================================================
|
|
371
|
-
// Internal — pattern extractors
|
|
371
|
+
// Internal — pattern extractors
|
|
372
372
|
// =============================================================================
|
|
373
373
|
/**
|
|
374
374
|
* Route an `<r>.<method>(...)` call to its concrete extractor. New
|
|
@@ -377,12 +377,12 @@ function walkAiStepCalls(body, registrarParamName, sourceFile, patterns, errors,
|
|
|
377
377
|
* commit to the new kind via compile errors.
|
|
378
378
|
*
|
|
379
379
|
* Skeleton: every recognised method currently returns an UnknownPattern
|
|
380
|
-
* with the right method name.
|
|
381
|
-
*
|
|
380
|
+
* with the right method name. Extractors replace the cases with concrete
|
|
381
|
+
* implementations one at a time.
|
|
382
382
|
*/
|
|
383
383
|
function dispatchExtractor(methodName, call, sourceFile) {
|
|
384
384
|
switch (methodName) {
|
|
385
|
-
//
|
|
385
|
+
// Simplest static patterns
|
|
386
386
|
case "requires":
|
|
387
387
|
return extractRequires(call, sourceFile);
|
|
388
388
|
case "optionalRequires":
|
|
@@ -397,7 +397,7 @@ function dispatchExtractor(methodName, call, sourceFile) {
|
|
|
397
397
|
return extractDescribe(call, sourceFile);
|
|
398
398
|
case "uiHints":
|
|
399
399
|
return extractUiHints(call, sourceFile);
|
|
400
|
-
//
|
|
400
|
+
// Object-literal-based static patterns
|
|
401
401
|
case "entity":
|
|
402
402
|
return extractEntity(call, sourceFile);
|
|
403
403
|
case "relation":
|
|
@@ -406,7 +406,7 @@ function dispatchExtractor(methodName, call, sourceFile) {
|
|
|
406
406
|
return extractNav(call, sourceFile);
|
|
407
407
|
case "workspace":
|
|
408
408
|
return extractWorkspace(call, sourceFile);
|
|
409
|
-
//
|
|
409
|
+
// Complex static patterns
|
|
410
410
|
case "config":
|
|
411
411
|
return extractConfig(call, sourceFile);
|
|
412
412
|
case "translations":
|
|
@@ -423,7 +423,7 @@ function dispatchExtractor(methodName, call, sourceFile) {
|
|
|
423
423
|
return extractReferenceData(call, sourceFile);
|
|
424
424
|
case "useExtension":
|
|
425
425
|
return extractUseExtension(call, sourceFile);
|
|
426
|
-
//
|
|
426
|
+
// Mixed (header + body) patterns
|
|
427
427
|
case "hook":
|
|
428
428
|
return extractHook(call, sourceFile);
|
|
429
429
|
case "authClaims":
|
|
@@ -448,7 +448,7 @@ function dispatchExtractor(methodName, call, sourceFile) {
|
|
|
448
448
|
return extractMultiStreamProjection(call, sourceFile);
|
|
449
449
|
case "screen":
|
|
450
450
|
return extractScreen(call, sourceFile);
|
|
451
|
-
//
|
|
451
|
+
// Opaque patterns
|
|
452
452
|
case "extendsRegistrar":
|
|
453
453
|
return extractExtendsRegistrar(call, sourceFile);
|
|
454
454
|
case "usesApi":
|
|
@@ -459,10 +459,10 @@ function dispatchExtractor(methodName, call, sourceFile) {
|
|
|
459
459
|
return extractStoreTable(call, sourceFile);
|
|
460
460
|
case "bootCheck":
|
|
461
461
|
return extractBootCheck(call, sourceFile);
|
|
462
|
-
//
|
|
462
|
+
// Tree-Actions pattern
|
|
463
463
|
case "treeActions":
|
|
464
464
|
return extractTreeActions(call, sourceFile);
|
|
465
|
-
//
|
|
465
|
+
// Env-schema contract (opaque, Zod-expression argument)
|
|
466
466
|
case "envSchema":
|
|
467
467
|
return extractEnvSchema(call, sourceFile);
|
|
468
468
|
// Unknown method — UnknownPattern signal so Designer/AI surface it
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
// roadmap C-Notes for the canonical-comment-attach Pattern that would
|
|
34
34
|
// preserve prefixed `// kumiko-comment:` markers across roundtrips.
|
|
35
35
|
import { SyntaxKind, } from "ts-morph";
|
|
36
|
-
import {
|
|
36
|
+
import { readPropertyKey } from "./extractors/shared.js";
|
|
37
|
+
import { callMatchesId } from "./pattern-id-matchers.js";
|
|
37
38
|
import { indent, PATTERN_INDENT, renderPattern, renderValue } from "./render.js";
|
|
38
39
|
/**
|
|
39
40
|
* Apply a sequence of changes to the source file in-place. The list is
|
|
@@ -523,7 +524,7 @@ function findCallForId(sourceFile, id) {
|
|
|
523
524
|
continue;
|
|
524
525
|
if (propAccess.getName() !== id.kind)
|
|
525
526
|
continue;
|
|
526
|
-
if (callMatchesId(call, id))
|
|
527
|
+
if (callMatchesId(call, id.kind, id))
|
|
527
528
|
matches.push(call);
|
|
528
529
|
}
|
|
529
530
|
if (SINGLETON_KINDS.has(id.kind) && matches.length > 1) {
|
|
@@ -536,28 +537,6 @@ const AI_STEP_FACTORY = {
|
|
|
536
537
|
"ai.extract": "aiExtractStep",
|
|
537
538
|
"ai.classify": "aiClassifyStep",
|
|
538
539
|
};
|
|
539
|
-
function readAiStepKey(call) {
|
|
540
|
-
const arg = call.getArguments()[0];
|
|
541
|
-
if (!arg)
|
|
542
|
-
return undefined;
|
|
543
|
-
const obj = resolveSameFileObjectLiteral(arg);
|
|
544
|
-
if (!obj)
|
|
545
|
-
return undefined;
|
|
546
|
-
const prop = obj.getProperty("stepKey");
|
|
547
|
-
if (!prop)
|
|
548
|
-
return undefined;
|
|
549
|
-
const assign = prop.asKind(SyntaxKind.PropertyAssignment);
|
|
550
|
-
if (assign) {
|
|
551
|
-
const init = assign.getInitializer();
|
|
552
|
-
if (!init)
|
|
553
|
-
return undefined;
|
|
554
|
-
return readNameLiteral(init);
|
|
555
|
-
}
|
|
556
|
-
const shorthand = prop.asKind(SyntaxKind.ShorthandPropertyAssignment);
|
|
557
|
-
if (shorthand)
|
|
558
|
-
return readNameLiteral(shorthand.getNameNode());
|
|
559
|
-
return undefined;
|
|
560
|
-
}
|
|
561
540
|
function findAiStepCall(sourceFile, id) {
|
|
562
541
|
if (!isAiStepId(id))
|
|
563
542
|
return undefined;
|
|
@@ -566,7 +545,7 @@ function findAiStepCall(sourceFile, id) {
|
|
|
566
545
|
for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
567
546
|
if (call.getExpression().getText() !== factory)
|
|
568
547
|
continue;
|
|
569
|
-
if (callMatchesId(call, id))
|
|
548
|
+
if (callMatchesId(call, id.kind, id))
|
|
570
549
|
matches.push(call);
|
|
571
550
|
}
|
|
572
551
|
if (matches.length > 1) {
|
|
@@ -574,163 +553,6 @@ function findAiStepCall(sourceFile, id) {
|
|
|
574
553
|
}
|
|
575
554
|
return matches[0];
|
|
576
555
|
}
|
|
577
|
-
function callMatchesId(call, id) {
|
|
578
|
-
switch (id.kind) {
|
|
579
|
-
// Singletons: kind alone identifies the call.
|
|
580
|
-
case "requires":
|
|
581
|
-
case "optionalRequires":
|
|
582
|
-
case "readsConfig":
|
|
583
|
-
case "systemScope":
|
|
584
|
-
case "toggleable":
|
|
585
|
-
case "describe":
|
|
586
|
-
case "uiHints":
|
|
587
|
-
case "config":
|
|
588
|
-
case "translations":
|
|
589
|
-
case "authClaims":
|
|
590
|
-
case "treeActions":
|
|
591
|
-
return true;
|
|
592
|
-
case "entity":
|
|
593
|
-
return (matchFirstArgString(call, id.entityName) || matchObjectProperty(call, "name", id.entityName));
|
|
594
|
-
case "relation":
|
|
595
|
-
// Positional: r.relation(entity, name, def) | Object: { entity, name, ... }
|
|
596
|
-
if (matchFirstArgString(call, id.entityName)) {
|
|
597
|
-
return matchArgString(call, 1, id.relationName);
|
|
598
|
-
}
|
|
599
|
-
return (matchObjectProperty(call, "entity", id.entityName) &&
|
|
600
|
-
matchObjectProperty(call, "name", id.relationName));
|
|
601
|
-
case "nav":
|
|
602
|
-
case "workspace":
|
|
603
|
-
case "screen":
|
|
604
|
-
return matchObjectProperty(call, "id", id.id);
|
|
605
|
-
case "writeHandler":
|
|
606
|
-
case "queryHandler":
|
|
607
|
-
case "streamHandler":
|
|
608
|
-
return (matchFirstArgString(call, id.handlerName) ||
|
|
609
|
-
matchObjectProperty(call, "name", id.handlerName));
|
|
610
|
-
case "hook":
|
|
611
|
-
// Positional: r.hook(type, target, fn) | Object: { type, target }
|
|
612
|
-
if (typeof id.target === "object") {
|
|
613
|
-
// Entity-wide { allOf } target — only ever appears as the object
|
|
614
|
-
// literal { allOf: entity } (positional or nested in the object
|
|
615
|
-
// form), never as a bare string, so check both call shapes.
|
|
616
|
-
if (matchFirstArgString(call, id.hookType)) {
|
|
617
|
-
return matchAllOfArg(call.getArguments()[1], id.target.allOf);
|
|
618
|
-
}
|
|
619
|
-
return (matchObjectProperty(call, "type", id.hookType) &&
|
|
620
|
-
matchObjectAllOfProperty(call, "target", id.target.allOf));
|
|
621
|
-
}
|
|
622
|
-
if (matchFirstArgString(call, id.hookType)) {
|
|
623
|
-
return matchArgNameOrRef(call, 1, id.target);
|
|
624
|
-
}
|
|
625
|
-
return (matchObjectProperty(call, "type", id.hookType) &&
|
|
626
|
-
matchObjectProperty(call, "target", id.target));
|
|
627
|
-
case "metric":
|
|
628
|
-
case "secret":
|
|
629
|
-
case "secretNamespace":
|
|
630
|
-
case "claimKey":
|
|
631
|
-
return (matchFirstArgString(call, id.shortName) || matchObjectProperty(call, "name", id.shortName));
|
|
632
|
-
case "referenceData":
|
|
633
|
-
return (matchFirstArgString(call, id.entityName) ||
|
|
634
|
-
matchObjectProperty(call, "entity", id.entityName));
|
|
635
|
-
case "useExtension":
|
|
636
|
-
// Positional: r.useExtension(name, entity) | Object: { name, entity }
|
|
637
|
-
if (matchFirstArgString(call, id.extensionName)) {
|
|
638
|
-
return matchArgNameOrRef(call, 1, id.entityName);
|
|
639
|
-
}
|
|
640
|
-
return (matchObjectProperty(call, "name", id.extensionName) &&
|
|
641
|
-
matchObjectProperty(call, "entity", id.entityName));
|
|
642
|
-
case "job":
|
|
643
|
-
return matchFirstArgString(call, id.jobName) || matchObjectProperty(call, "name", id.jobName);
|
|
644
|
-
case "notification":
|
|
645
|
-
return (matchFirstArgString(call, id.notificationName) ||
|
|
646
|
-
matchObjectProperty(call, "name", id.notificationName));
|
|
647
|
-
case "httpRoute":
|
|
648
|
-
// Object form only; positional doesn't apply.
|
|
649
|
-
return (matchObjectProperty(call, "method", id.method) && matchObjectProperty(call, "path", id.path));
|
|
650
|
-
case "projection":
|
|
651
|
-
case "multiStreamProjection":
|
|
652
|
-
return matchObjectProperty(call, "name", id.name);
|
|
653
|
-
case "defineEvent":
|
|
654
|
-
return (matchFirstArgString(call, id.eventName) || matchObjectProperty(call, "name", id.eventName));
|
|
655
|
-
case "extendsRegistrar":
|
|
656
|
-
return matchFirstArgString(call, id.extensionName);
|
|
657
|
-
case "ai.generate":
|
|
658
|
-
case "ai.extract":
|
|
659
|
-
case "ai.classify":
|
|
660
|
-
return readAiStepKey(call) === id.stepKey;
|
|
661
|
-
default: {
|
|
662
|
-
const _exhaustive = id;
|
|
663
|
-
return _exhaustive;
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
// Resolves an argument the same way the extractors do (readNameLiteral):
|
|
668
|
-
// a string literal directly, or a bare identifier following its
|
|
669
|
-
// declaration (same-file or imported) to a string-literal initializer —
|
|
670
|
-
// the dominant naming style in the framework's own bundled-features
|
|
671
|
-
// (`r.entity(ENTITY, ...)`, `r.useExtension(EXT_X, ...)`, see #1746).
|
|
672
|
-
//
|
|
673
|
-
// Narrow on purpose: every kind's arg-0 (and relation's arg-1) is parsed
|
|
674
|
-
// via readNameLiteral, never readNameOrRef (see round2.ts/round3.ts) —
|
|
675
|
-
// widening this shared helper to readNameOrRef would let an object-form
|
|
676
|
-
// call's first argument (an ObjectLiteralExpression) match here too,
|
|
677
|
-
// short-circuiting the object-form branch in callMatchesId. Positions
|
|
678
|
-
// where the parser itself accepts an inline `{ name: "..." }` ref use
|
|
679
|
-
// `matchArgNameOrRef` below instead.
|
|
680
|
-
function matchArgString(call, index, expected) {
|
|
681
|
-
const arg = call.getArguments()[index];
|
|
682
|
-
if (!arg)
|
|
683
|
-
return false;
|
|
684
|
-
return readNameLiteral(arg) === expected;
|
|
685
|
-
}
|
|
686
|
-
// @wrapper-known semantic-alias
|
|
687
|
-
function matchFirstArgString(call, expected) {
|
|
688
|
-
return matchArgString(call, 0, expected);
|
|
689
|
-
}
|
|
690
|
-
// Like matchArgString, but via readNameOrRef — for the specific positional
|
|
691
|
-
// slots where the parser accepts an inline `{ name: "..." }` object ref in
|
|
692
|
-
// addition to a literal/identifier (useExtension's entity arg, hook's
|
|
693
|
-
// target arg; see round3.ts:445 / hooks.ts:75). Not a drop-in replacement
|
|
694
|
-
// for matchArgString: applying it to an arg-0 position would match an
|
|
695
|
-
// object-form call's first (and only) argument, see the comment above.
|
|
696
|
-
function matchArgNameOrRef(call, index, expected) {
|
|
697
|
-
const arg = call.getArguments()[index];
|
|
698
|
-
if (!arg)
|
|
699
|
-
return false;
|
|
700
|
-
return readNameOrRef(arg) === expected;
|
|
701
|
-
}
|
|
702
|
-
// Object-form property values are resolved via readNameOrRef, not the
|
|
703
|
-
// narrower readNameLiteral — some properties (useExtension's `entity`,
|
|
704
|
-
// hook's `target`/`allOf`) accept an inline `{ name: "..." }` ref in the
|
|
705
|
-
// parser (see extractors/round3.ts, extractors/hooks.ts), not just a
|
|
706
|
-
// literal or identifier. readNameOrRef is a superset of readNameLiteral,
|
|
707
|
-
// so this is safe for every other property too.
|
|
708
|
-
function matchObjectProperty(call, propName, expected) {
|
|
709
|
-
const obj = call.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression);
|
|
710
|
-
if (!obj)
|
|
711
|
-
return false;
|
|
712
|
-
const init = obj.getProperty(propName)?.asKind(SyntaxKind.PropertyAssignment)?.getInitializer();
|
|
713
|
-
if (!init)
|
|
714
|
-
return false;
|
|
715
|
-
return readNameOrRef(init) === expected;
|
|
716
|
-
}
|
|
717
|
-
// Matches an r.hook `{ allOf: entity }` target — as the arg node directly
|
|
718
|
-
// (positional call form) or as a nested object property (object call form).
|
|
719
|
-
function matchAllOfArg(node, expectedEntity) {
|
|
720
|
-
const obj = node?.asKind(SyntaxKind.ObjectLiteralExpression);
|
|
721
|
-
const init = obj?.getProperty("allOf")?.asKind(SyntaxKind.PropertyAssignment)?.getInitializer();
|
|
722
|
-
if (!init)
|
|
723
|
-
return false;
|
|
724
|
-
return readNameOrRef(init) === expectedEntity;
|
|
725
|
-
}
|
|
726
|
-
function matchObjectAllOfProperty(call, propName, expectedEntity) {
|
|
727
|
-
const obj = call.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression);
|
|
728
|
-
const propInit = obj
|
|
729
|
-
?.getProperty(propName)
|
|
730
|
-
?.asKind(SyntaxKind.PropertyAssignment)
|
|
731
|
-
?.getInitializer();
|
|
732
|
-
return matchAllOfArg(propInit, expectedEntity);
|
|
733
|
-
}
|
|
734
556
|
// =============================================================================
|
|
735
557
|
// Format helpers — line boundaries / blank-line collapse
|
|
736
558
|
// (indent / PATTERN_INDENT live in render.ts and are imported above.)
|
|
@@ -7,6 +7,7 @@ import type { RelationDefinition } from "../types/relations.ts";
|
|
|
7
7
|
import type { ScreenDefinition } from "../types/screen.ts";
|
|
8
8
|
import type { TreeActionDef } from "../types/tree-node.ts";
|
|
9
9
|
import type { WorkspaceDefinition } from "../types/workspace.ts";
|
|
10
|
+
import type { RawRefSentinel } from "./extractors/shared.ts";
|
|
10
11
|
import type { PatternChange } from "./patch.ts";
|
|
11
12
|
import type { SourceLocation } from "./source-location.ts";
|
|
12
13
|
export type PatternChangeIssue = {
|
|
@@ -26,6 +27,7 @@ export declare const PATTERN_SCHEMAS_BY_KIND: {
|
|
|
26
27
|
source: z.ZodType<SourceLocation, unknown, z.core.$ZodTypeInternals<SourceLocation, unknown>>;
|
|
27
28
|
entityName: z.ZodString;
|
|
28
29
|
definition: z.ZodType<EntityDefinition, unknown, z.core.$ZodTypeInternals<EntityDefinition, unknown>>;
|
|
30
|
+
backingTable: z.ZodOptional<z.ZodType<RawRefSentinel, unknown, z.core.$ZodTypeInternals<RawRefSentinel, unknown>>>;
|
|
29
31
|
}, z.core.$strict>;
|
|
30
32
|
relation: z.ZodObject<{
|
|
31
33
|
kind: z.ZodLiteral<"relation">;
|
|
@@ -648,6 +650,7 @@ export declare const patternSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
648
650
|
source: z.ZodType<SourceLocation, unknown, z.core.$ZodTypeInternals<SourceLocation, unknown>>;
|
|
649
651
|
entityName: z.ZodString;
|
|
650
652
|
definition: z.ZodType<EntityDefinition, unknown, z.core.$ZodTypeInternals<EntityDefinition, unknown>>;
|
|
653
|
+
backingTable: z.ZodOptional<z.ZodType<RawRefSentinel, unknown, z.core.$ZodTypeInternals<RawRefSentinel, unknown>>>;
|
|
651
654
|
}, z.core.$strict>, z.ZodObject<{
|
|
652
655
|
kind: z.ZodLiteral<"relation">;
|
|
653
656
|
source: z.ZodType<SourceLocation, unknown, z.core.$ZodTypeInternals<SourceLocation, unknown>>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// tool (or any external caller) hands us JSON; before it ever reaches
|
|
3
3
|
// `applyChanges` it must pass through here. Every rejection carries an
|
|
4
4
|
// exact dotted/bracketed path so the caller (frequently an LLM) can
|
|
5
|
-
// self-correct without a human in the loop
|
|
5
|
+
// self-correct without a human in the loop.
|
|
6
6
|
//
|
|
7
7
|
// **Zod v4 constraint driving this file's shape:** every discriminated-
|
|
8
8
|
// union member below stays a plain `z.object(...)` (or `.superRefine`
|
|
@@ -332,6 +332,7 @@ const entitySchema = z
|
|
|
332
332
|
source: sourceFieldSchema,
|
|
333
333
|
entityName: z.string(),
|
|
334
334
|
definition: entityDefinitionSchema,
|
|
335
|
+
backingTable: passthroughSchema().optional(),
|
|
335
336
|
})
|
|
336
337
|
.strict();
|
|
337
338
|
const relationSchema = z
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type CallExpression } from "ts-morph";
|
|
2
|
+
import type { PatternId } from "./patch.ts";
|
|
3
|
+
import type { MembersByKind } from "./patterns.ts";
|
|
4
|
+
type PatternIdKind = PatternId["kind"];
|
|
5
|
+
type PatternIdOfKind = MembersByKind<PatternId>;
|
|
6
|
+
export declare function callMatchesId<K extends PatternIdKind>(call: CallExpression, kind: K, id: PatternIdOfKind[K]): boolean;
|
|
7
|
+
export {};
|