@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
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// Migrates create*Field(...) calls from the old flag-based PII API (pii,
|
|
3
3
|
// userOwned, tenantOwned, subjectRef, allowPlaintext, lookupable,
|
|
4
|
-
// searchable, sensitive) to the author-facing personal/find API
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// searchable, sensitive) to the author-facing personal/find API.
|
|
5
|
+
// Idempotent — re-running is a no-op on already migrated fields (skipped once
|
|
6
|
+
// a `personal` property is present).
|
|
7
7
|
//
|
|
8
8
|
// Mapping table (exact):
|
|
9
9
|
// pii: true -> personal: "self"
|
|
@@ -87,7 +87,16 @@ const OVERRIDES_ARG_INDEX_1 = new Set(["createEmbeddedField", "createEmbeddedLis
|
|
|
87
87
|
const FIELD_FACTORY_RE = /^create\w*Field$/;
|
|
88
88
|
|
|
89
89
|
type ReportEntry = { readonly file: string; readonly line: number; readonly note: string };
|
|
90
|
-
|
|
90
|
+
const FIND_BUCKETS = [
|
|
91
|
+
"exact",
|
|
92
|
+
"fuzzy",
|
|
93
|
+
"none",
|
|
94
|
+
"secret",
|
|
95
|
+
"ref",
|
|
96
|
+
"personal-false",
|
|
97
|
+
"no-find",
|
|
98
|
+
] as const;
|
|
99
|
+
type FindBucket = (typeof FIND_BUCKETS)[number];
|
|
91
100
|
|
|
92
101
|
const reports: ReportEntry[] = [];
|
|
93
102
|
const newLookupableSites: ReportEntry[] = [];
|
|
@@ -168,50 +177,40 @@ function reportRawSubjectLiterals(
|
|
|
168
177
|
}
|
|
169
178
|
}
|
|
170
179
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
piiEncryptedProp,
|
|
180
|
-
"piiEncrypted: true on an entity field (removed from the type system) — needs a human decision, not a mechanical mapping",
|
|
181
|
-
);
|
|
182
|
-
// skip: reported above — piiEncrypted needs a human decision, not a mechanical mapping
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
180
|
+
type SubjectProp = { readonly name: SubjectFlagName; readonly prop: PropertyAssignment };
|
|
181
|
+
type PersonalInit = { readonly personal: string; readonly reason: string | undefined };
|
|
182
|
+
type FindSupport = "text" | "longText" | "none";
|
|
183
|
+
type FindabilityProps = {
|
|
184
|
+
readonly lookupable: PropertyAssignment | undefined;
|
|
185
|
+
readonly searchable: PropertyAssignment | undefined;
|
|
186
|
+
readonly sensitive: PropertyAssignment | undefined;
|
|
187
|
+
};
|
|
185
188
|
|
|
189
|
+
function singleSubjectFlag(obj: ObjectLiteralExpression): SubjectProp | undefined {
|
|
186
190
|
const subjectProps = SUBJECT_FLAG_NAMES.map((n) => ({ name: n, prop: findProp(obj, n) })).filter(
|
|
187
191
|
(x): x is { name: SubjectFlagName; prop: PropertyAssignment } => !!x.prop,
|
|
188
192
|
);
|
|
189
|
-
const lookupableProp = findProp(obj, "lookupable");
|
|
190
|
-
const searchableProp = findProp(obj, "searchable");
|
|
191
|
-
const sensitiveProp = findProp(obj, "sensitive");
|
|
192
|
-
const anonymizeProp = obj.getProperty("anonymize");
|
|
193
|
-
|
|
194
193
|
if (subjectProps.length === 0) {
|
|
195
194
|
// `searchable`/`sensitive` alone remain valid, unrelated FieldDef
|
|
196
195
|
// properties — left untouched. `lookupable` alone can never compile
|
|
197
196
|
// (always an excess property without a `personal` to attach `find`
|
|
198
197
|
// to). `anonymize` alone has no PersonalAnnotations arm to live on.
|
|
198
|
+
const lookupableProp = findProp(obj, "lookupable");
|
|
199
199
|
if (lookupableProp) {
|
|
200
200
|
report(
|
|
201
201
|
lookupableProp,
|
|
202
202
|
"lookupable without any subject annotation — no `personal` to attach `find` to",
|
|
203
203
|
);
|
|
204
204
|
}
|
|
205
|
+
const anonymizeProp = obj.getProperty("anonymize");
|
|
205
206
|
if (anonymizeProp) {
|
|
206
207
|
report(
|
|
207
208
|
anonymizeProp,
|
|
208
209
|
"anonymize without any subject annotation — no PersonalAnnotations arm accepts anonymize alone",
|
|
209
210
|
);
|
|
210
211
|
}
|
|
211
|
-
|
|
212
|
-
return;
|
|
212
|
+
return undefined;
|
|
213
213
|
}
|
|
214
|
-
|
|
215
214
|
if (subjectProps.length > 1) {
|
|
216
215
|
const first = subjectProps[0];
|
|
217
216
|
if (first) {
|
|
@@ -220,152 +219,154 @@ function processObjectLiteral(obj: ObjectLiteralExpression, factoryName: string)
|
|
|
220
219
|
`multiple subject annotations on one field (${subjectProps.map((s) => s.name).join(", ")}) — needs a human decision on which subject is correct`,
|
|
221
220
|
);
|
|
222
221
|
}
|
|
223
|
-
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const subject = subjectProps[0];
|
|
228
|
-
if (!subject) {
|
|
229
|
-
// skip: length===0 and length>1 already returned — empty [0] is unreachable
|
|
230
|
-
return;
|
|
222
|
+
return undefined;
|
|
231
223
|
}
|
|
224
|
+
return subjectProps[0];
|
|
225
|
+
}
|
|
232
226
|
|
|
227
|
+
function findSupportOf(factoryName: string, subject: SubjectProp): FindSupport | undefined {
|
|
233
228
|
if (NO_PERSONAL_FACTORIES.has(factoryName)) {
|
|
234
229
|
report(
|
|
235
230
|
subject.prop,
|
|
236
231
|
`${factoryName} has no personal-annotation support — subject flag "${subject.name}" cannot be expressed here`,
|
|
237
232
|
);
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
235
|
+
if (TEXT_FIND_FACTORIES.has(factoryName)) return "text";
|
|
236
|
+
if (LONGTEXT_FIND_FACTORIES.has(factoryName)) return "longText";
|
|
237
|
+
if (NO_FIND_FACTORIES.has(factoryName)) return "none";
|
|
238
|
+
report(
|
|
239
|
+
subject.prop,
|
|
240
|
+
`unrecognized field factory "${factoryName}" — cannot verify its PersonalAnnotations shape`,
|
|
241
|
+
);
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function personalFromTrueFlag(
|
|
246
|
+
personal: string,
|
|
247
|
+
): (subject: SubjectProp) => PersonalInit | undefined {
|
|
248
|
+
return (subject) => {
|
|
249
|
+
if (isTrueLiteral(subject.prop.getInitializer())) return { personal, reason: undefined };
|
|
250
|
+
report(subject.prop, `${subject.name} is set to a non-\`true\` value — cannot infer intent`);
|
|
251
|
+
return undefined;
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function personalFromAllowPlaintext(subject: SubjectProp): PersonalInit | undefined {
|
|
256
|
+
const init = subject.prop.getInitializer();
|
|
257
|
+
if (!init) {
|
|
258
|
+
report(subject.prop, "allowPlaintext has no value");
|
|
259
|
+
return undefined;
|
|
251
260
|
}
|
|
261
|
+
const reason = Node.isStringLiteral(init)
|
|
262
|
+
? `"${normalizeReasonSlug(init.getLiteralText())}"`
|
|
263
|
+
: init.getText();
|
|
264
|
+
return { personal: "false", reason };
|
|
265
|
+
}
|
|
252
266
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
if (
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if (!isTrueLiteral(subject.prop.getInitializer())) {
|
|
264
|
-
report(subject.prop, "tenantOwned is set to a non-`true` value — cannot infer intent");
|
|
265
|
-
// skip: reported above — non-`true` tenantOwned value, can't infer intent
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
personalInit = `"tenant"`;
|
|
269
|
-
} else if (subject.name === "subjectRef") {
|
|
270
|
-
if (!isTrueLiteral(subject.prop.getInitializer())) {
|
|
271
|
-
report(subject.prop, "subjectRef is set to a non-`true` value — cannot infer intent");
|
|
272
|
-
// skip: reported above — non-`true` subjectRef value, can't infer intent
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
personalInit = `"ref"`;
|
|
276
|
-
} else if (subject.name === "allowPlaintext") {
|
|
277
|
-
const init = subject.prop.getInitializer();
|
|
278
|
-
if (!init) {
|
|
279
|
-
report(subject.prop, "allowPlaintext has no value");
|
|
280
|
-
// skip: reported above — allowPlaintext has no value to migrate
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
personalInit = "false";
|
|
284
|
-
reasonInit = Node.isStringLiteral(init)
|
|
285
|
-
? `"${normalizeReasonSlug(init.getLiteralText())}"`
|
|
286
|
-
: init.getText();
|
|
287
|
-
} else {
|
|
288
|
-
const init = subject.prop.getInitializer();
|
|
289
|
-
if (!init || !Node.isObjectLiteralExpression(init)) {
|
|
290
|
-
report(subject.prop, "userOwned value is not an object literal — cannot extract ownerField");
|
|
291
|
-
// skip: reported above — userOwned value isn't an object literal, can't extract ownerField
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
const ownerFieldProp = findProp(init, "ownerField");
|
|
295
|
-
const ownerFieldInit = ownerFieldProp?.getInitializer();
|
|
296
|
-
if (!ownerFieldInit) {
|
|
297
|
-
report(subject.prop, 'userOwned is missing an "ownerField" property');
|
|
298
|
-
// skip: reported above — userOwned is missing its ownerField property
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
personalInit = `{ of: ${ownerFieldInit.getText()} }`;
|
|
267
|
+
function personalFromUserOwned(subject: SubjectProp): PersonalInit | undefined {
|
|
268
|
+
const init = subject.prop.getInitializer();
|
|
269
|
+
if (!init || !Node.isObjectLiteralExpression(init)) {
|
|
270
|
+
report(subject.prop, "userOwned value is not an object literal — cannot extract ownerField");
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
const ownerFieldInit = findProp(init, "ownerField")?.getInitializer();
|
|
274
|
+
if (!ownerFieldInit) {
|
|
275
|
+
report(subject.prop, 'userOwned is missing an "ownerField" property');
|
|
276
|
+
return undefined;
|
|
302
277
|
}
|
|
278
|
+
return { personal: `{ of: ${ownerFieldInit.getText()} }`, reason: undefined };
|
|
279
|
+
}
|
|
303
280
|
|
|
304
|
-
|
|
305
|
-
|
|
281
|
+
// One row per subject flag of the mapping table in the file header; a row
|
|
282
|
+
// reports and returns undefined when the flag value cannot be mapped.
|
|
283
|
+
const PERSONAL_INIT_BY_SUBJECT: Record<
|
|
284
|
+
SubjectFlagName,
|
|
285
|
+
(subject: SubjectProp) => PersonalInit | undefined
|
|
286
|
+
> = {
|
|
287
|
+
pii: personalFromTrueFlag(`"self"`),
|
|
288
|
+
userOwned: personalFromUserOwned,
|
|
289
|
+
tenantOwned: personalFromTrueFlag(`"tenant"`),
|
|
290
|
+
subjectRef: personalFromTrueFlag(`"ref"`),
|
|
291
|
+
allowPlaintext: personalFromAllowPlaintext,
|
|
292
|
+
};
|
|
306
293
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
personal:
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
});
|
|
322
|
-
counts[subject.name === "subjectRef" ? "ref" : "personal-false"]++;
|
|
323
|
-
// skip: already transformed above — nothing left to check for this subject
|
|
294
|
+
// These PersonalAnnotations arms carry no `find` field at all.
|
|
295
|
+
function migrateFindlessSubject(
|
|
296
|
+
obj: ObjectLiteralExpression,
|
|
297
|
+
subject: SubjectProp,
|
|
298
|
+
personal: PersonalInit,
|
|
299
|
+
lookupableProp: PropertyAssignment | undefined,
|
|
300
|
+
): void {
|
|
301
|
+
const isRef = subject.name === "subjectRef";
|
|
302
|
+
if (lookupableProp) {
|
|
303
|
+
report(
|
|
304
|
+
lookupableProp,
|
|
305
|
+
`lookupable combined with personal:${isRef ? '"ref"' : "false"} — findability doesn't apply to this subject, table has no mapping`,
|
|
306
|
+
);
|
|
307
|
+
// skip: reported above — lookupable doesn't apply to this subject, no mapping to migrate
|
|
324
308
|
return;
|
|
325
309
|
}
|
|
310
|
+
applyTransform(obj, [subject.prop], {
|
|
311
|
+
personal: personal.personal,
|
|
312
|
+
reason: personal.reason,
|
|
313
|
+
find: undefined,
|
|
314
|
+
});
|
|
315
|
+
counts[isRef ? "ref" : "personal-false"]++;
|
|
316
|
+
}
|
|
326
317
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
});
|
|
342
|
-
counts["no-find"]++;
|
|
343
|
-
// skip: already transformed above — no-find factory has nothing further to check
|
|
318
|
+
function migrateNoFindField(
|
|
319
|
+
obj: ObjectLiteralExpression,
|
|
320
|
+
factoryName: string,
|
|
321
|
+
subject: SubjectProp,
|
|
322
|
+
personal: PersonalInit,
|
|
323
|
+
findability: FindabilityProps,
|
|
324
|
+
): void {
|
|
325
|
+
const stray = findability.lookupable ?? findability.searchable ?? findability.sensitive;
|
|
326
|
+
if (stray) {
|
|
327
|
+
report(
|
|
328
|
+
stray,
|
|
329
|
+
`${factoryName} has no \`find\` in its PersonalAnnotations — findability flag present on a non-text field`,
|
|
330
|
+
);
|
|
331
|
+
// skip: reported above — findability flag on a non-text field, no valid find to attach
|
|
344
332
|
return;
|
|
345
333
|
}
|
|
334
|
+
applyTransform(obj, [subject.prop], {
|
|
335
|
+
personal: personal.personal,
|
|
336
|
+
reason: undefined,
|
|
337
|
+
find: undefined,
|
|
338
|
+
});
|
|
339
|
+
counts["no-find"]++;
|
|
340
|
+
}
|
|
346
341
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
342
|
+
// lookupable + searchable and searchable alone both map to "fuzzy".
|
|
343
|
+
function findValueOf(findability: FindabilityProps): "exact" | "fuzzy" | "none" | "secret" {
|
|
344
|
+
if (findability.sensitive) return "secret";
|
|
345
|
+
if (findability.searchable) return "fuzzy";
|
|
346
|
+
if (findability.lookupable) return "exact";
|
|
347
|
+
return "none";
|
|
348
|
+
}
|
|
350
349
|
|
|
351
|
-
|
|
350
|
+
function migrateTextFindField(
|
|
351
|
+
obj: ObjectLiteralExpression,
|
|
352
|
+
subject: SubjectProp,
|
|
353
|
+
personal: PersonalInit,
|
|
354
|
+
findability: FindabilityProps,
|
|
355
|
+
support: Exclude<FindSupport, "none">,
|
|
356
|
+
): void {
|
|
357
|
+
const { lookupable, searchable, sensitive } = findability;
|
|
358
|
+
if (sensitive && (lookupable || searchable)) {
|
|
352
359
|
report(
|
|
353
|
-
|
|
360
|
+
sensitive,
|
|
354
361
|
'sensitive combined with lookupable/searchable — two find values ("secret" vs "exact"/"fuzzy"), needs a human decision',
|
|
355
362
|
);
|
|
356
363
|
// skip: reported above — sensitive plus lookupable/searchable is an ambiguous find value
|
|
357
364
|
return;
|
|
358
365
|
}
|
|
359
366
|
|
|
360
|
-
|
|
361
|
-
if (
|
|
362
|
-
|
|
363
|
-
else if (hasLookupable) find = "exact";
|
|
364
|
-
else if (hasSearchable) find = "fuzzy";
|
|
365
|
-
else find = "none";
|
|
366
|
-
|
|
367
|
-
if (isLongTextFind && (find === "exact" || find === "fuzzy")) {
|
|
368
|
-
const findSite = lookupableProp ?? searchableProp;
|
|
367
|
+
const find = findValueOf(findability);
|
|
368
|
+
if (support === "longText" && (find === "exact" || find === "fuzzy")) {
|
|
369
|
+
const findSite = lookupable ?? searchable;
|
|
369
370
|
if (findSite) {
|
|
370
371
|
report(
|
|
371
372
|
findSite,
|
|
@@ -379,7 +380,7 @@ function processObjectLiteral(obj: ObjectLiteralExpression, factoryName: string)
|
|
|
379
380
|
// searchable-alone -> "fuzzy" makes expandPersonalAnnotations add
|
|
380
381
|
// `lookupable: true`, which the field didn't carry before — that's a
|
|
381
382
|
// new `_bidx` column (DDL migration), tracked separately for the report.
|
|
382
|
-
if (
|
|
383
|
+
if (searchable && !lookupable) {
|
|
383
384
|
newLookupableSites.push({
|
|
384
385
|
file: obj.getSourceFile().getFilePath(),
|
|
385
386
|
line: subject.prop.getStartLineNumber(),
|
|
@@ -388,13 +389,51 @@ function processObjectLiteral(obj: ObjectLiteralExpression, factoryName: string)
|
|
|
388
389
|
});
|
|
389
390
|
}
|
|
390
391
|
|
|
391
|
-
const removedProps = [subject.prop,
|
|
392
|
+
const removedProps = [subject.prop, lookupable, searchable, sensitive].filter(
|
|
392
393
|
(p): p is PropertyAssignment => !!p,
|
|
393
394
|
);
|
|
394
|
-
applyTransform(obj, removedProps, { personal:
|
|
395
|
+
applyTransform(obj, removedProps, { personal: personal.personal, reason: undefined, find });
|
|
395
396
|
counts[find]++;
|
|
396
397
|
}
|
|
397
398
|
|
|
399
|
+
function processObjectLiteral(obj: ObjectLiteralExpression, factoryName: string): void {
|
|
400
|
+
// skip: field already carries `personal` — already migrated, idempotent no-op
|
|
401
|
+
if (obj.getProperty("personal")) return;
|
|
402
|
+
|
|
403
|
+
const piiEncryptedProp = obj.getProperty("piiEncrypted");
|
|
404
|
+
if (piiEncryptedProp) {
|
|
405
|
+
report(
|
|
406
|
+
piiEncryptedProp,
|
|
407
|
+
"piiEncrypted: true on an entity field (removed from the type system) — needs a human decision, not a mechanical mapping",
|
|
408
|
+
);
|
|
409
|
+
// skip: reported above — piiEncrypted needs a human decision, not a mechanical mapping
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const subject = singleSubjectFlag(obj);
|
|
414
|
+
// skip: no subject flag, or several, reported by singleSubjectFlag where needed
|
|
415
|
+
if (!subject) return;
|
|
416
|
+
const support = findSupportOf(factoryName, subject);
|
|
417
|
+
// skip: factory without a verifiable PersonalAnnotations shape, reported by findSupportOf
|
|
418
|
+
if (!support) return;
|
|
419
|
+
const personal = PERSONAL_INIT_BY_SUBJECT[subject.name](subject);
|
|
420
|
+
// skip: flag value cannot be mapped, reported by its PERSONAL_INIT_BY_SUBJECT row
|
|
421
|
+
if (!personal) return;
|
|
422
|
+
|
|
423
|
+
const findability: FindabilityProps = {
|
|
424
|
+
lookupable: findProp(obj, "lookupable"),
|
|
425
|
+
searchable: findProp(obj, "searchable"),
|
|
426
|
+
sensitive: findProp(obj, "sensitive"),
|
|
427
|
+
};
|
|
428
|
+
if (subject.name === "subjectRef" || subject.name === "allowPlaintext") {
|
|
429
|
+
migrateFindlessSubject(obj, subject, personal, findability.lookupable);
|
|
430
|
+
} else if (support === "none") {
|
|
431
|
+
migrateNoFindField(obj, factoryName, subject, personal, findability);
|
|
432
|
+
} else {
|
|
433
|
+
migrateTextFindField(obj, subject, personal, findability, support);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
398
437
|
function applyTransform(
|
|
399
438
|
obj: ObjectLiteralExpression,
|
|
400
439
|
removedProps: readonly PropertyAssignment[],
|
|
@@ -411,7 +450,9 @@ function applyTransform(
|
|
|
411
450
|
const removedSet = new Set<PropertyAssignment>(removedProps);
|
|
412
451
|
let insertIndex = 0;
|
|
413
452
|
for (let i = 0; i < anchorIndex; i++) {
|
|
414
|
-
|
|
453
|
+
const property = properties[i];
|
|
454
|
+
if (!(property && Node.isPropertyAssignment(property) && removedSet.has(property)))
|
|
455
|
+
insertIndex++;
|
|
415
456
|
}
|
|
416
457
|
|
|
417
458
|
for (const p of removedProps) p.remove();
|
|
@@ -746,9 +787,7 @@ async function main(): Promise<void> {
|
|
|
746
787
|
|
|
747
788
|
const countsBefore = { ...counts };
|
|
748
789
|
for (const { name, objArg } of calls) processObjectLiteral(objArg, name);
|
|
749
|
-
const changed =
|
|
750
|
-
(k) => counts[k] !== countsBefore[k],
|
|
751
|
-
);
|
|
790
|
+
const changed = FIND_BUCKETS.some((k) => counts[k] !== countsBefore[k]);
|
|
752
791
|
|
|
753
792
|
if (changed) {
|
|
754
793
|
touchedFiles++;
|
|
@@ -12,7 +12,14 @@
|
|
|
12
12
|
// Without a mode flag it writes (kumiko-upgrade --apply calls it that way). --check exits 1
|
|
13
13
|
// while any rewritable or manual site is left; --dry-run only reports.
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
type ExportDeclaration,
|
|
17
|
+
type ExportSpecifier,
|
|
18
|
+
type ImportDeclaration,
|
|
19
|
+
type ImportSpecifier,
|
|
20
|
+
Project,
|
|
21
|
+
SyntaxKind,
|
|
22
|
+
} from "ts-morph";
|
|
16
23
|
import {
|
|
17
24
|
type CodemodResult,
|
|
18
25
|
ensureNamedImport,
|
|
@@ -64,6 +71,115 @@ function reportNamespaceUses(
|
|
|
64
71
|
}
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
function reportStarReexport(
|
|
75
|
+
declaration: ExportDeclaration,
|
|
76
|
+
filePath: string,
|
|
77
|
+
result: SiteLists,
|
|
78
|
+
): void {
|
|
79
|
+
result.manual.push({
|
|
80
|
+
file: filePath,
|
|
81
|
+
line: declaration.getStartLineNumber(),
|
|
82
|
+
description: `export * from ${declaration.getModuleSpecifierValue()}: re-export the moved names from ${TARGET_MODULE} by hand`,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function moveNamedReexports(
|
|
87
|
+
declaration: ExportDeclaration,
|
|
88
|
+
movedExports: readonly ExportSpecifier[],
|
|
89
|
+
filePath: string,
|
|
90
|
+
result: SiteLists,
|
|
91
|
+
): void {
|
|
92
|
+
const line = declaration.getStartLineNumber();
|
|
93
|
+
const snapshots = movedExports.map((named) => ({
|
|
94
|
+
name: named.getName(),
|
|
95
|
+
alias: named.getAliasNode()?.getText(),
|
|
96
|
+
isTypeOnly: named.isTypeOnly(),
|
|
97
|
+
}));
|
|
98
|
+
for (const named of movedExports) named.remove();
|
|
99
|
+
const typeOnlyDeclaration = declaration.isTypeOnly();
|
|
100
|
+
if (declaration.getNamedExports().length === 0) declaration.remove();
|
|
101
|
+
declaration.getSourceFile().addExportDeclaration({
|
|
102
|
+
moduleSpecifier: TARGET_MODULE,
|
|
103
|
+
namedExports: snapshots,
|
|
104
|
+
isTypeOnly: typeOnlyDeclaration,
|
|
105
|
+
});
|
|
106
|
+
result.rewrites.push({
|
|
107
|
+
file: filePath,
|
|
108
|
+
line,
|
|
109
|
+
description: `export { ${snapshots.map((snapshot) => snapshot.name).join(", ")} } -> ${TARGET_MODULE}`,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function rewriteReexports(
|
|
114
|
+
declaration: ExportDeclaration,
|
|
115
|
+
moved: ReadonlySet<string>,
|
|
116
|
+
filePath: string,
|
|
117
|
+
result: SiteLists,
|
|
118
|
+
): void {
|
|
119
|
+
const namedExports = declaration.getNamedExports();
|
|
120
|
+
const movedExports = namedExports.filter((named) => moved.has(named.getName()));
|
|
121
|
+
if (namedExports.length === 0) reportStarReexport(declaration, filePath, result);
|
|
122
|
+
else if (movedExports.length > 0) moveNamedReexports(declaration, movedExports, filePath, result);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function moveNamedImports(
|
|
126
|
+
declaration: ImportDeclaration,
|
|
127
|
+
movedImports: readonly ImportSpecifier[],
|
|
128
|
+
filePath: string,
|
|
129
|
+
result: SiteLists,
|
|
130
|
+
): void {
|
|
131
|
+
const line = declaration.getStartLineNumber();
|
|
132
|
+
const typeOnlyDeclaration = declaration.isTypeOnly();
|
|
133
|
+
const sourceFile = declaration.getSourceFile();
|
|
134
|
+
const names = movedImports.map((named) => named.getName());
|
|
135
|
+
// Collected first: removing a specifier invalidates the nodes of its siblings.
|
|
136
|
+
const snapshots = movedImports.map((named) => ({
|
|
137
|
+
name: named.getName(),
|
|
138
|
+
alias: named.getAliasNode()?.getText(),
|
|
139
|
+
typeOnly: named.isTypeOnly(),
|
|
140
|
+
}));
|
|
141
|
+
for (const named of movedImports) named.remove();
|
|
142
|
+
if (
|
|
143
|
+
declaration.getNamedImports().length === 0 &&
|
|
144
|
+
declaration.getNamespaceImport() === undefined &&
|
|
145
|
+
declaration.getDefaultImport() === undefined
|
|
146
|
+
) {
|
|
147
|
+
declaration.remove();
|
|
148
|
+
}
|
|
149
|
+
for (const snapshot of snapshots) {
|
|
150
|
+
const typeOnly = typeOnlyDeclaration || snapshot.typeOnly;
|
|
151
|
+
if (snapshot.alias === undefined) {
|
|
152
|
+
ensureNamedImport(sourceFile, TARGET_MODULE, snapshot.name, typeOnly);
|
|
153
|
+
} else {
|
|
154
|
+
sourceFile.addImportDeclaration({
|
|
155
|
+
moduleSpecifier: TARGET_MODULE,
|
|
156
|
+
namedImports: [{ name: snapshot.name, alias: snapshot.alias }],
|
|
157
|
+
isTypeOnly: typeOnly,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
result.rewrites.push({
|
|
162
|
+
file: filePath,
|
|
163
|
+
line,
|
|
164
|
+
description: `${names.join(", ")} -> ${TARGET_MODULE}`,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function rewriteImportDeclaration(
|
|
169
|
+
declaration: ImportDeclaration,
|
|
170
|
+
filePath: string,
|
|
171
|
+
result: SiteLists,
|
|
172
|
+
): void {
|
|
173
|
+
const moved = movedNamesOf(declaration);
|
|
174
|
+
if (moved !== undefined) {
|
|
175
|
+
reportNamespaceUses(declaration, moved, filePath, result);
|
|
176
|
+
const movedImports = declaration
|
|
177
|
+
.getNamedImports()
|
|
178
|
+
.filter((named) => moved.has(named.getName()));
|
|
179
|
+
if (movedImports.length > 0) moveNamedImports(declaration, movedImports, filePath, result);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
67
183
|
export function transformTestingInjectionSource(
|
|
68
184
|
source: string,
|
|
69
185
|
filePath = "source.ts",
|
|
@@ -77,47 +193,11 @@ export function transformTestingInjectionSource(
|
|
|
77
193
|
});
|
|
78
194
|
const sourceFile = project.createSourceFile(filePath, source);
|
|
79
195
|
for (const declaration of sourceFile.getImportDeclarations()) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
.filter((named) => moved.has(named.getName()));
|
|
86
|
-
if (movedImports.length === 0) continue;
|
|
87
|
-
const line = declaration.getStartLineNumber();
|
|
88
|
-
const typeOnlyDeclaration = declaration.isTypeOnly();
|
|
89
|
-
const names = movedImports.map((named) => named.getName());
|
|
90
|
-
// Collected first: removing a specifier invalidates the nodes of its siblings.
|
|
91
|
-
const snapshots = movedImports.map((named) => ({
|
|
92
|
-
name: named.getName(),
|
|
93
|
-
alias: named.getAliasNode()?.getText(),
|
|
94
|
-
typeOnly: named.isTypeOnly(),
|
|
95
|
-
}));
|
|
96
|
-
for (const named of movedImports) named.remove();
|
|
97
|
-
if (
|
|
98
|
-
declaration.getNamedImports().length === 0 &&
|
|
99
|
-
declaration.getNamespaceImport() === undefined &&
|
|
100
|
-
declaration.getDefaultImport() === undefined
|
|
101
|
-
) {
|
|
102
|
-
declaration.remove();
|
|
103
|
-
}
|
|
104
|
-
for (const snapshot of snapshots) {
|
|
105
|
-
const typeOnly = typeOnlyDeclaration || snapshot.typeOnly;
|
|
106
|
-
if (snapshot.alias === undefined) {
|
|
107
|
-
ensureNamedImport(sourceFile, TARGET_MODULE, snapshot.name, typeOnly);
|
|
108
|
-
} else {
|
|
109
|
-
sourceFile.addImportDeclaration({
|
|
110
|
-
moduleSpecifier: TARGET_MODULE,
|
|
111
|
-
namedImports: [{ name: snapshot.name, alias: snapshot.alias }],
|
|
112
|
-
isTypeOnly: typeOnly,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
result.rewrites.push({
|
|
117
|
-
file: filePath,
|
|
118
|
-
line,
|
|
119
|
-
description: `${names.join(", ")} -> ${TARGET_MODULE}`,
|
|
120
|
-
});
|
|
196
|
+
rewriteImportDeclaration(declaration, filePath, result);
|
|
197
|
+
}
|
|
198
|
+
for (const declaration of sourceFile.getExportDeclarations()) {
|
|
199
|
+
const moved = MOVED_NAMES_BY_MODULE.get(declaration.getModuleSpecifierValue() ?? "");
|
|
200
|
+
if (moved !== undefined) rewriteReexports(declaration, moved, filePath, result);
|
|
121
201
|
}
|
|
122
202
|
const output = result.rewrites.length > 0 ? sourceFile.getFullText() : source;
|
|
123
203
|
return { output, ...result };
|