@cosmicdrift/kumiko-framework 0.387.0 → 0.389.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 +9 -1
- 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/golden-path.md +13 -1
- package/agents/examples/legal-pages.md +1 -1
- package/agents/examples/lifecycle-hooks.md +55 -2
- package/agents/examples/list-table-options.md +466 -0
- package/agents/examples/pdf-audit-export.md +4 -2
- 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/state-machine.md +3 -2
- package/agents/examples/tenant-isolation.md +73 -1
- package/agents/examples/wizard-form.md +941 -0
- package/agents/examples/writeform-section.md +548 -0
- package/agents/examples.md +1 -0
- package/agents/features.md +19 -2
- package/agents/widgets.md +2 -0
- package/dist/api/api-constants.d.ts +1 -0
- package/dist/api/api-constants.js +2 -0
- package/dist/api/auth-routes-shared.d.ts +2 -0
- package/dist/api/auth-routes-shared.js +5 -0
- package/dist/api/client-error-route.js +10 -5
- package/dist/api/entity-read-access.d.ts +2 -1
- package/dist/api/entity-read-access.js +14 -0
- package/dist/api/export/export-cells-reference.d.ts +9 -0
- package/dist/api/export/export-cells-reference.js +21 -0
- package/dist/api/export/export-cells.d.ts +11 -0
- package/dist/api/export/export-cells.js +136 -0
- package/dist/api/export/export-ciphertext-guard.d.ts +2 -0
- package/dist/api/export/export-ciphertext-guard.js +27 -0
- package/dist/api/export/export-columns.d.ts +29 -0
- package/dist/api/export/export-columns.js +85 -0
- package/dist/api/export/export-errors.d.ts +4 -0
- package/dist/api/export/export-errors.js +14 -0
- package/dist/api/export/export-route.d.ts +4 -0
- package/dist/api/export/export-route.js +74 -0
- package/dist/api/export/export-rows.d.ts +13 -0
- package/dist/api/export/export-rows.js +62 -0
- package/dist/api/export/export-screen.d.ts +12 -0
- package/dist/api/export/export-screen.js +47 -0
- package/dist/api/export/export-xlsx-writer.d.ts +4 -0
- package/dist/api/export/export-xlsx-writer.js +21 -0
- package/dist/api/extra-route.d.ts +4 -0
- package/dist/api/index.d.ts +3 -1
- package/dist/api/index.js +3 -1
- package/dist/api/pii-leak-guard.d.ts +3 -0
- package/dist/api/pii-leak-guard.js +3 -2
- package/dist/api/request-context.d.ts +1 -1
- package/dist/api/request-context.js +1 -1
- package/dist/api/routes.d.ts +16 -0
- 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 +206 -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 +299 -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 +238 -0
- package/dist/api/server.d.ts +10 -15
- package/dist/api/server.js +48 -1251
- package/dist/api/session-cookies.js +4 -4
- package/dist/api/sse-route.d.ts +2 -1
- package/dist/api/sse-route.js +27 -13
- package/dist/config/index.d.ts +3 -1
- 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.d.ts +1 -0
- package/dist/crypto/pg-kms-adapter.js +12 -18
- package/dist/crypto/pii-field-encryption.d.ts +5 -1
- package/dist/crypto/pii-field-encryption.js +3 -1
- package/dist/db/aggregate-sql.d.ts +23 -0
- package/dist/db/aggregate-sql.js +165 -0
- package/dist/db/closed-connection.d.ts +9 -0
- package/dist/db/closed-connection.js +88 -0
- package/dist/db/connection.d.ts +4 -5
- package/dist/db/connection.js +29 -20
- package/dist/db/dialect.js +1 -1
- 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 +101 -0
- 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.js +103 -110
- package/dist/db/event-store-executor-context.d.ts +2 -1
- package/dist/db/event-store-executor-read-aggregate-currencies.d.ts +17 -0
- package/dist/db/event-store-executor-read-aggregate-currencies.js +40 -0
- package/dist/db/event-store-executor-read-aggregate.d.ts +8 -0
- package/dist/db/event-store-executor-read-aggregate.js +143 -0
- package/dist/db/event-store-executor-read-filter.d.ts +31 -0
- package/dist/db/event-store-executor-read-filter.js +206 -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 +48 -701
- package/dist/db/event-store-executor-write-atomic.d.ts +4 -0
- package/dist/db/event-store-executor-write-atomic.js +41 -0
- package/dist/db/event-store-executor-write-steps.d.ts +17 -0
- package/dist/db/event-store-executor-write-steps.js +95 -0
- package/dist/db/event-store-executor-write.js +405 -509
- package/dist/db/event-store-executor.js +2 -1
- package/dist/db/executor-managed-tables.js +1 -1
- package/dist/db/index.d.ts +7 -3
- package/dist/db/index.js +6 -2
- package/dist/db/list-aggregate-labels.d.ts +14 -0
- package/dist/db/list-aggregate-labels.js +26 -0
- package/dist/db/migrate-generator.js +71 -86
- package/dist/db/migrate-runner.js +7 -4
- package/dist/db/pg-error.js +26 -21
- package/dist/db/queries/backfill-pii.js +3 -6
- package/dist/db/queries/database-now.js +2 -1
- package/dist/db/queries/shadow-swap.js +2 -3
- package/dist/db/query.d.ts +16 -15
- package/dist/db/query.js +76 -804
- package/dist/db/reference-data.js +19 -2
- package/dist/db/statement-timeout.js +2 -1
- package/dist/db/table-builder.js +113 -166
- 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-upsert.d.ts +5 -0
- package/dist/db/tenant-db-upsert.js +91 -0
- package/dist/db/tenant-db.js +50 -10
- package/dist/db/where-clause.d.ts +6 -0
- package/dist/db/where-clause.js +236 -0
- package/dist/derivatives/delete-stored-file.js +2 -1
- package/dist/engine/boot-validator/boot-check.js +1 -1
- package/dist/engine/boot-validator/bundled-lists-table.d.ts +2 -0
- package/dist/engine/boot-validator/bundled-lists-table.js +36 -0
- package/dist/engine/boot-validator/detail-screens.js +2 -2
- package/dist/engine/boot-validator/entity-handler.d.ts +1 -0
- package/dist/engine/boot-validator/entity-handler.js +17 -0
- package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +3 -0
- package/dist/engine/boot-validator/entity-list-aggregate-options.js +23 -0
- package/dist/engine/boot-validator/form-derivations.js +35 -1
- package/dist/engine/boot-validator/i18n-keys.js +5 -3
- package/dist/engine/boot-validator/index.js +2 -0
- package/dist/engine/boot-validator/list-bulk-actions.d.ts +3 -0
- package/dist/engine/boot-validator/list-bulk-actions.js +49 -0
- package/dist/engine/boot-validator/list-column-layout.d.ts +8 -0
- package/dist/engine/boot-validator/list-column-layout.js +41 -0
- package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +24 -0
- package/dist/engine/boot-validator/list-table-aggregate-options.js +145 -0
- package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +10 -0
- package/dist/engine/boot-validator/list-table-aggregate-query.js +31 -0
- package/dist/engine/boot-validator/list-table-export-options.d.ts +1 -0
- package/dist/engine/boot-validator/list-table-export-options.js +27 -0
- package/dist/engine/boot-validator/list-table-options.d.ts +3 -0
- package/dist/engine/boot-validator/list-table-options.js +77 -0
- package/dist/engine/boot-validator/list-table-reject-unknown-keys.d.ts +1 -0
- package/dist/engine/boot-validator/list-table-reject-unknown-keys.js +7 -0
- package/dist/engine/boot-validator/pii-retention.js +233 -155
- package/dist/engine/boot-validator/projection-list-screens.d.ts +1 -1
- package/dist/engine/boot-validator/projection-list-screens.js +3 -13
- package/dist/engine/boot-validator/related-list-table-rules.d.ts +4 -0
- package/dist/engine/boot-validator/related-list-table-rules.js +42 -0
- package/dist/engine/boot-validator/screens-actions.d.ts +1 -0
- package/dist/engine/boot-validator/screens-actions.js +8 -1
- package/dist/engine/boot-validator/screens-dashboard.js +2 -5
- package/dist/engine/boot-validator/screens-forms.js +2 -6
- 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 +235 -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 +56 -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 +24 -11
- package/dist/engine/boot-validator/screens.d.ts +0 -2
- package/dist/engine/boot-validator/screens.js +99 -860
- package/dist/engine/build-app-schema.d.ts +2 -1
- package/dist/engine/build-app-schema.js +65 -97
- package/dist/engine/build-config-feature-schema.js +6 -1
- package/dist/engine/define-feature.js +13 -2
- package/dist/engine/define-handler.js +1 -0
- package/dist/engine/entity-handlers.d.ts +13 -0
- package/dist/engine/entity-handlers.js +10 -21
- package/dist/engine/entity-list-runtime-options.d.ts +8 -0
- package/dist/engine/entity-list-runtime-options.js +18 -0
- package/dist/engine/feature-ast/extractors/handlers.js +1 -0
- package/dist/engine/feature-ast/extractors/index.d.ts +1 -1
- package/dist/engine/feature-ast/extractors/index.js +1 -1
- package/dist/engine/feature-ast/extractors/round1.d.ts +2 -1
- package/dist/engine/feature-ast/extractors/round1.js +6 -0
- package/dist/engine/feature-ast/extractors/round2.js +25 -6
- package/dist/engine/feature-ast/index.d.ts +1 -1
- package/dist/engine/feature-ast/parse.js +3 -1
- package/dist/engine/feature-ast/patch.d.ts +2 -0
- package/dist/engine/feature-ast/patch.js +5 -182
- package/dist/engine/feature-ast/pattern-change-schema.d.ts +10 -245
- package/dist/engine/feature-ast/pattern-change-schema.js +10 -163
- package/dist/engine/feature-ast/pattern-id-matchers.d.ts +7 -0
- package/dist/engine/feature-ast/pattern-id-matchers.js +211 -0
- package/dist/engine/feature-ast/pattern-id-schema.d.ts +251 -0
- package/dist/engine/feature-ast/pattern-id-schema.js +166 -0
- package/dist/engine/feature-ast/patterns.d.ts +14 -1
- package/dist/engine/feature-ast/patterns.js +44 -51
- package/dist/engine/feature-ast/render.js +52 -87
- package/dist/engine/feature-builder-state.d.ts +1 -0
- package/dist/engine/feature-builder-state.js +1 -0
- package/dist/engine/feature-entity-handlers.js +3 -0
- package/dist/engine/feature-manifest.d.ts +1 -0
- package/dist/engine/feature-manifest.js +1 -0
- package/dist/engine/field-access.d.ts +1 -0
- package/dist/engine/field-access.js +12 -0
- package/dist/engine/form-derivations.js +18 -7
- package/dist/engine/handler-field-references.js +1 -1
- package/dist/engine/index.d.ts +2 -2
- package/dist/engine/index.js +1 -1
- package/dist/engine/pattern-library/library.js +2 -1
- package/dist/engine/pattern-library/static-schemas.d.ts +1 -0
- package/dist/engine/pattern-library/static-schemas.js +9 -0
- package/dist/engine/project-app-schema-for-roles.d.ts +2 -0
- package/dist/engine/project-app-schema-for-roles.js +6 -4
- package/dist/engine/registry-ingest.js +1 -1
- package/dist/engine/schema-builder.js +228 -212
- package/dist/engine/screen-filter-ops.js +2 -0
- package/dist/engine/screen-helpers.js +1 -1
- package/dist/engine/screen-kind.d.ts +7 -0
- package/dist/engine/screen-kind.js +1 -0
- package/dist/engine/strip-disabled-features-from-app-schema.js +58 -17
- package/dist/engine/types/feature.d.ts +1 -0
- package/dist/engine/types/index.d.ts +4 -3
- package/dist/engine/types/screen.d.ts +1 -1
- package/dist/engine/types/screen.js +1 -1
- package/dist/engine/validate-projection-allowlist.js +2 -1
- package/dist/entrypoint/index.d.ts +6 -1
- package/dist/entrypoint/index.js +10 -1
- package/dist/errors/docs-url.d.ts +1 -1
- package/dist/errors/docs-url.js +22 -2
- package/dist/es-ops/context.js +1 -1
- package/dist/event-store/admin-api.js +1 -1
- package/dist/event-store/event-store.d.ts +1 -0
- package/dist/event-store/event-store.js +17 -8
- package/dist/event-store/provenance-append.js +1 -1
- package/dist/files/bind-pending-file-refs.js +3 -3
- package/dist/files/create-file-ref-from-bytes.js +7 -1
- package/dist/files/create-file-ref.d.ts +3 -0
- package/dist/files/create-file-ref.js +11 -2
- package/dist/files/file-handle.js +2 -3
- package/dist/files/file-routes.d.ts +2 -0
- package/dist/files/file-routes.js +40 -10
- package/dist/files/provider-resolver.d.ts +1 -0
- package/dist/files/provider-resolver.js +1 -1
- package/dist/files/record-write-check.d.ts +6 -0
- package/dist/files/record-write-check.js +13 -0
- package/dist/files/resolve-content-type.js +43 -0
- package/dist/files/upload-ledger.d.ts +2 -2
- package/dist/files/upload-ledger.js +11 -4
- package/dist/i18n/required-surface-keys.js +189 -208
- package/dist/internal/stack-support.d.ts +2 -1
- package/dist/internal/stack-support.js +1 -1
- package/dist/internal/testing.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 +61 -2
- 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 +50 -657
- package/dist/observability/escape-hatch-report.d.ts +3 -0
- package/dist/observability/escape-hatch-report.js +21 -3
- package/dist/pipeline/after-rollback-sink.d.ts +6 -0
- package/dist/pipeline/after-rollback-sink.js +32 -0
- package/dist/pipeline/cascade-handler.js +165 -138
- package/dist/pipeline/dispatch-batch.js +8 -1
- package/dist/pipeline/dispatch-query.js +10 -3
- package/dist/pipeline/dispatch-shared.d.ts +13 -3
- package/dist/pipeline/dispatch-shared.js +62 -710
- package/dist/pipeline/dispatch-write.js +296 -189
- package/dist/pipeline/event-dispatcher-admin.js +2 -1
- package/dist/pipeline/event-dispatcher-delivery.js +6 -6
- package/dist/pipeline/event-dispatcher.d.ts +1 -0
- package/dist/pipeline/event-dispatcher.js +6 -9
- 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 +23 -0
- package/dist/pipeline/handler-context-dispatch.js +101 -0
- package/dist/pipeline/handler-context-events.d.ts +41 -0
- package/dist/pipeline/handler-context-events.js +239 -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/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 +2 -1
- package/dist/pipeline/system-hooks.d.ts +3 -1
- package/dist/pipeline/system-hooks.js +55 -6
- package/dist/pipeline/write-result-masking.js +13 -10
- 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 -604
- package/dist/search/meilisearch-adapter.js +2 -1
- package/dist/search/reindex-entity.js +15 -5
- package/dist/ui-types/index.d.ts +2 -2
- package/dist/ui-types/index.js +1 -1
- package/dist/upgrade-changelog.d.ts +2 -0
- package/dist/upgrade-changelog.js +14 -0
- package/dist/upgrade-cli.d.ts +3 -12
- package/dist/upgrade-cli.js +171 -197
- package/dist/upgrade-marker-parse.d.ts +32 -0
- package/dist/upgrade-marker-parse.js +73 -0
- package/package.json +9 -6
- package/src/changes.json +555 -0
- package/src/scripts/codemod/codemod-support.ts +1 -1
- package/src/scripts/codemod/db-factory.ts +1 -1
- package/src/scripts/codemod/feature-layout.ts +10 -2
- 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 +175 -145
- package/src/scripts/codemod/testing-injection.ts +122 -42
- package/src/scripts/codemod/testing-move.ts +29 -7
- package/dist/engine/provider-plugin-context.d.ts +0 -3
- package/dist/engine/provider-plugin-context.js +0 -28
|
@@ -34,7 +34,8 @@ function isSubsetOf(stored, wanted) {
|
|
|
34
34
|
}
|
|
35
35
|
// A stored list that lies inside the current default and misses attributes is an
|
|
36
36
|
// older default that gained fields since; anything with a foreign attribute is
|
|
37
|
-
// an explicit configure() and stays untouched.
|
|
37
|
+
// an explicit configure() and stays untouched. Known limit: an explicit configure() that
|
|
38
|
+
// narrowed to a strict subset of the default is indistinguishable and gets widened again.
|
|
38
39
|
function isOutdatedDefault(stored, wanted) {
|
|
39
40
|
const pairs = [
|
|
40
41
|
[stored.searchable, wanted.searchable],
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// existing row and indexes it, same as a live write would.
|
|
7
7
|
import { resolveTableName } from "../db/entity-table-meta.js";
|
|
8
8
|
import { executeRawQueryRead } from "../db/queries/raw-sql.js";
|
|
9
|
-
import {
|
|
9
|
+
import { runInNewTransaction, runnerCanBeginTransaction } from "../db/query.js";
|
|
10
10
|
import { buildSearchDocument, decryptSearchableSubjectFields, hasErasedSearchableSubjectField, } from "../pipeline/system-hooks.js";
|
|
11
11
|
import { toSnakeCase } from "../utils/case.js";
|
|
12
12
|
function quoteIdent(name) {
|
|
@@ -26,10 +26,20 @@ function rowToState(row, fieldNames) {
|
|
|
26
26
|
}
|
|
27
27
|
return state;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
// Server pools cap statement_timeout, and a batch scan over a large table can outlast it. The caller's
|
|
30
|
+
// runner (often a gated proxy around the pool) is used as is, so the cap is lifted per batch
|
|
31
|
+
// with a transaction-local set_config instead of moving the scan to an ungated sibling pool. A runner already inside a
|
|
32
|
+
// transaction keeps the caller's setting rather than leaking ours into its remaining statements.
|
|
33
|
+
async function readBatchWithoutStatementTimeout(db, sqlText, params) {
|
|
34
|
+
if (!runnerCanBeginTransaction(db)) {
|
|
35
|
+
return executeRawQueryRead(db, sqlText, params);
|
|
36
|
+
}
|
|
37
|
+
return runInNewTransaction(db, async (tx) => {
|
|
38
|
+
await executeRawQueryRead(tx, "SELECT set_config('statement_timeout', '0', true)", []);
|
|
39
|
+
return executeRawQueryRead(tx, sqlText, params);
|
|
40
|
+
});
|
|
31
41
|
}
|
|
32
|
-
async function
|
|
42
|
+
export async function reindexEntity(db, registry, searchAdapter, entityName, tenantId, options = {}) {
|
|
33
43
|
const entity = registry.getEntity(entityName);
|
|
34
44
|
if (!entity) {
|
|
35
45
|
throw new Error(`reindexEntity: unknown entity "${entityName}"`);
|
|
@@ -61,7 +71,7 @@ async function scanAndIndexEntity(db, registry, searchAdapter, entityName, tenan
|
|
|
61
71
|
for (;;) {
|
|
62
72
|
// Keyset, not OFFSET: rows deleted or changed while the loop runs must not shift the window.
|
|
63
73
|
const afterLastId = lastId === undefined ? "" : `AND ${quoteIdent("id")} > $3`;
|
|
64
|
-
const rows = await
|
|
74
|
+
const rows = await readBatchWithoutStatementTimeout(db, `SELECT * FROM ${quoteIdent(tableName)}
|
|
65
75
|
WHERE ${quoteIdent("tenant_id")} = $1 ${deletedFilter} ${afterLastId}
|
|
66
76
|
ORDER BY ${quoteIdent("id")} ASC
|
|
67
77
|
LIMIT $2`, lastId === undefined ? [tenantId, batchSize] : [tenantId, batchSize, lastId]);
|
package/dist/ui-types/index.d.ts
CHANGED
|
@@ -11,8 +11,8 @@ export type { BooleanFieldDef, DateFieldDef, EmbeddedDerivedCellDef, EntityDefin
|
|
|
11
11
|
export type { AccessRule, OpenToAllAccessRule, OpenToAllDeclaration, OpenToAllPersonalData, RoleAccessPersonalData, RoleAccessRule, } from "../engine/types/handlers.ts";
|
|
12
12
|
export { isOpenToAllGranted, isUiAccessGranted } from "../engine/types/handlers.ts";
|
|
13
13
|
export type { IconKey, NavDefinition, NavIconKey } from "../engine/types/nav.ts";
|
|
14
|
-
export type { ActionFormFooterAction, ActionFormLoad, ActionFormRedirect, ActionFormScreenDefinition, ActionFormSuccessFact, ActionFormSuccessLink, ConfigEditScreenDefinition, CustomScreenDefinition, CustomScreenRoute, DashboardChartKind, DashboardChartMarkerKind, DashboardChartPanel, DashboardChartRangeOption, DashboardChartRanges, DashboardChartTone, DashboardCurrencyFormat, DashboardCustomPanel, DashboardDateParam, DashboardFeedPanel, DashboardFilterDefinition, DashboardI18nText, DashboardListPanel, DashboardMoneyParam, DashboardPanelDefinition, DashboardPanelEmptyState, DashboardPanelGate, DashboardPanelQueryOptions, DashboardPanelSpan, DashboardPanelVisibility, DashboardProgressListPanel, DashboardProgressTone, DashboardRecordBinding, DashboardRefresh, DashboardRelativeTimeFormat, DashboardRelativeTimeParam, DashboardScopeDefinition, DashboardScreenDefinition, DashboardScreenPanel, DashboardStatGroupPanel, DashboardStatPanel, DashboardText, DashboardTextBlock, DashboardTextPanel, DashboardTextParam, DashboardTimeRangeDefinition, DashboardValueFormat, EditExtensionSection, EditFieldPrefill, EditFieldSpec, EditFieldsSection, EditLayout, EditRelatedListSection, EditSectionSpec, EditWriteFormSection, EmbeddedListEditSpec, EntityEditAction, EntityEditActionPlacement, EntityEditScreenDefinition, EntityListExpandableRow, EntityListFacetConfig, EntityListFacetExtraOption, EntityListScreenDefinition, EntityWriteExcludedFields, FieldAffix, FieldCondition, FieldFillAction, FieldIconKey, FieldRenderer, FormWidth, ListBadgeTone, ListColumnDisplay, ListColumnSpec, ListEmptyStateSpec, ListFacetSpec, ListSortSpec, MetricNavigate, MetricSpec, PlatformComponent, ProjectionDetailScreenDefinition, ProjectionListScreenDefinition, RecordHeaderSubtitlePart,
|
|
15
|
-
export { relatedListGroupHeaderLabel, relatedListGroupKey, } from "../engine/types/screen.ts";
|
|
14
|
+
export type { ActionFormFooterAction, ActionFormLoad, ActionFormRedirect, ActionFormScreenDefinition, ActionFormSuccessFact, ActionFormSuccessLink, ConfigEditScreenDefinition, CustomScreenDefinition, CustomScreenRoute, DashboardChartKind, DashboardChartMarkerKind, DashboardChartPanel, DashboardChartRangeOption, DashboardChartRanges, DashboardChartTone, DashboardCurrencyFormat, DashboardCustomPanel, DashboardDateParam, DashboardFeedPanel, DashboardFilterDefinition, DashboardI18nText, DashboardListPanel, DashboardMoneyParam, DashboardPanelDefinition, DashboardPanelEmptyState, DashboardPanelGate, DashboardPanelQueryOptions, DashboardPanelSpan, DashboardPanelVisibility, DashboardProgressListPanel, DashboardProgressTone, DashboardRecordBinding, DashboardRefresh, DashboardRelativeTimeFormat, DashboardRelativeTimeParam, DashboardScopeDefinition, DashboardScreenDefinition, DashboardScreenPanel, DashboardStatGroupPanel, DashboardStatPanel, DashboardText, DashboardTextBlock, DashboardTextPanel, DashboardTextParam, DashboardTimeRangeDefinition, DashboardValueFormat, EditExtensionSection, EditFieldPrefill, EditFieldSpec, EditFieldsSection, EditLayout, EditRelatedListSection, EditSectionSpec, EditWriteFormSection, EmbeddedListEditSpec, EntityEditAction, EntityEditActionPlacement, EntityEditScreenDefinition, EntityListExpandableRow, EntityListFacetConfig, EntityListFacetExtraOption, EntityListScreenDefinition, EntityWriteExcludedFields, ExpandableRowGrouping, FieldAffix, FieldCondition, FieldFillAction, FieldIconKey, FieldRenderer, FormWidth, ListBadgeTone, ListBulkAction, ListColumnDisplay, ListColumnSpec, ListEmptyStateSpec, ListFacetSpec, ListSortSpec, ListTableDensity, ListTableOptions, MetricNavigate, MetricSpec, PlatformComponent, ProjectionDetailScreenDefinition, ProjectionListScreenDefinition, RecordHeaderSubtitlePart, RelatedListRowTone, RelatedListToolbarAction, RowAction, RowActionClientAction, RowActionDisplay, RowActionDrawer, RowActionMode, RowActionNavigate, RowActionWriteHandler, RowFieldExtractor, ScreenDefinition, ScreenFilter, ScreenFilterOp, ScreenSlots, SecretMintConfirmStep, SecretMintScreenDefinition, SecretReveal, SecretRevealField, SecretsEditScreenDefinition, SecretsEditSection, ToolbarAction, } from "../engine/types/screen.ts";
|
|
15
|
+
export { MAX_BULK_SELECTION, relatedListGroupHeaderLabel, relatedListGroupKey, } from "../engine/types/screen.ts";
|
|
16
16
|
export type { TargetRef } from "../engine/types/target-ref.ts";
|
|
17
17
|
export type { TreeAction, TreeNode, TreeNodeState } from "../engine/types/tree-node.ts";
|
|
18
18
|
export type { WorkspaceDefinition } from "../engine/types/workspace.ts";
|
package/dist/ui-types/index.js
CHANGED
|
@@ -25,7 +25,7 @@ export { applyFormDerivations, isFormDerivationInputMode, isUnusedFallbackOperan
|
|
|
25
25
|
export { parseRefTarget } from "../engine/parse-ref-target.js";
|
|
26
26
|
export { ACTION_FORM_PSEUDO_ENTITY, availableSelectOptions, evalFieldCondition, explicitListScreenId, findUnavailableSelectOptions, isExtensionEditSection, isFieldsEditSection, isFormatSpec, isRecordLocked, isUnchangedValue, isWriteFormEditSection, normalizeEditField, normalizeListColumn, resolveNavParentScreen, sectionFieldSpecs, } from "../engine/screen-helpers.js";
|
|
27
27
|
export { isOpenToAllGranted, isUiAccessGranted } from "../engine/types/handlers.js";
|
|
28
|
-
export { relatedListGroupHeaderLabel, relatedListGroupKey, } from "../engine/types/screen.js";
|
|
28
|
+
export { MAX_BULK_SELECTION, relatedListGroupHeaderLabel, relatedListGroupKey, } from "../engine/types/screen.js";
|
|
29
29
|
export { ACTION_FORM_ENTITY, handlerFieldLabelKey, handlerTitleKey, PROJECTION_DETAIL_ENTITY, WRITE_FORM_SECTION_ENTITY, } from "../i18n/required-surface-keys.js";
|
|
30
30
|
export { CARD_META_MAX, cardColumnRoles, cardFileDisplayKind } from "./card-column-roles.js";
|
|
31
31
|
export { formalLocaleTag } from "./formality.js";
|
|
@@ -23,3 +23,5 @@ export type UpgradeChangelogSection = {
|
|
|
23
23
|
export declare function renderUpgradeSection(section: UpgradeChangelogSection): string;
|
|
24
24
|
/** Puts the section on top; a section for the same target version is replaced, so a re-run stays idempotent. */
|
|
25
25
|
export declare function mergeUpgradeSection(existing: string | undefined, section: UpgradeChangelogSection): string;
|
|
26
|
+
/** Pure string match on the rendered `- [open] <id> · ` prefix, in every section. */
|
|
27
|
+
export declare function setManualStatusInChangelog(content: string, ids: ReadonlySet<string>, resolution: "migrated" | "not-applicable"): string;
|
|
@@ -46,3 +46,17 @@ export function mergeUpgradeSection(existing, section) {
|
|
|
46
46
|
const others = sections.filter((candidate) => !candidate.startsWith(prefix));
|
|
47
47
|
return [header, renderUpgradeSection(section), ...others].join("\n");
|
|
48
48
|
}
|
|
49
|
+
/** Pure string match on the rendered `- [open] <id> · ` prefix, in every section. */
|
|
50
|
+
export function setManualStatusInChangelog(content, ids, resolution) {
|
|
51
|
+
return content
|
|
52
|
+
.split("\n")
|
|
53
|
+
.map((line) => {
|
|
54
|
+
for (const id of ids) {
|
|
55
|
+
const open = `- [open] ${id} · `;
|
|
56
|
+
if (line.startsWith(open))
|
|
57
|
+
return `- [${resolution}] ${id} · ${line.slice(open.length)}`;
|
|
58
|
+
}
|
|
59
|
+
return line;
|
|
60
|
+
})
|
|
61
|
+
.join("\n");
|
|
62
|
+
}
|
package/dist/upgrade-cli.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { type ManualResolution, manualEntryId, type UpgradeMarkerManual, type UpgradeMarkerResolvedManual } from "./upgrade-marker-parse.ts";
|
|
2
|
+
export type { ManualResolution, UpgradeMarkerManual, UpgradeMarkerResolvedManual };
|
|
3
|
+
export { manualEntryId };
|
|
1
4
|
export type UpgradeCliOut = {
|
|
2
5
|
readonly log: (line: string) => void;
|
|
3
6
|
readonly err: (line: string) => void;
|
|
@@ -7,18 +10,6 @@ export declare function findPackageChangelogFiles(cwd: string): string[];
|
|
|
7
10
|
export declare function findFeaturesDirs(cwd: string): string[];
|
|
8
11
|
export declare function findCodemodScriptsRoot(repoRoot: string): string | null;
|
|
9
12
|
export declare function resolveCodemodScript(repoRoot: string, codemodField: string | undefined): string | null;
|
|
10
|
-
export type UpgradeMarkerManual = {
|
|
11
|
-
readonly id: string;
|
|
12
|
-
readonly version: string;
|
|
13
|
-
readonly title: string;
|
|
14
|
-
};
|
|
15
|
-
export type ManualResolution = "migrated" | "not-applicable";
|
|
16
|
-
export type UpgradeMarkerResolvedManual = UpgradeMarkerManual & {
|
|
17
|
-
readonly resolution: ManualResolution;
|
|
18
|
-
readonly reason: string;
|
|
19
|
-
readonly resolvedAt: string;
|
|
20
|
-
};
|
|
21
|
-
export declare function manualEntryId(version: string, title: string): string;
|
|
22
13
|
export declare function runUpgradeCli(argv: readonly string[], cwd: string, out: UpgradeCliOut, options?: {
|
|
23
14
|
readonly repoRoot?: string;
|
|
24
15
|
}): Promise<number>;
|
package/dist/upgrade-cli.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
1
|
import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, statSync, writeFileSync, } from "node:fs";
|
|
3
2
|
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
4
3
|
import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
5
4
|
import { getFlag, getStringFlag, parseArgs } from "./arg-parser.js";
|
|
6
5
|
import { compareVersions, filterEntriesAfter, parseFeatureChangelog, sortEntries, } from "./engine/index.js";
|
|
7
6
|
import { ensureTemporalPolyfill } from "./time/index.js";
|
|
8
|
-
import { mergeUpgradeSection } from "./upgrade-changelog.js";
|
|
9
|
-
|
|
7
|
+
import { mergeUpgradeSection, setManualStatusInChangelog, } from "./upgrade-changelog.js";
|
|
8
|
+
import { dedupeManualById, manualEntryId, parseStoredMarker, SEMVER_RE, } from "./upgrade-marker-parse.js";
|
|
9
|
+
export { manualEntryId };
|
|
10
10
|
const SEMVER_CORE_RE = /^(\d+\.\d+\.\d+)(?:-[0-9A-Za-z.-]+)?$/;
|
|
11
11
|
const CODEMOD_SUBDIR = "scripts/codemod";
|
|
12
12
|
function readPackageJsonVersion(packageJsonPath) {
|
|
@@ -304,13 +304,7 @@ function hasCodemod(e) {
|
|
|
304
304
|
function needsManualMigration(e) {
|
|
305
305
|
return !hasCodemod(e) || e.manualAfterCodemod === true;
|
|
306
306
|
}
|
|
307
|
-
const MANUAL_ID_HASH_LENGTH = 8;
|
|
308
307
|
const MAX_RESOLVE_REASON_LENGTH = 500;
|
|
309
|
-
// The hash tells apart entries that share a version (studio has several at 0.341.0).
|
|
310
|
-
export function manualEntryId(version, title) {
|
|
311
|
-
const hash = createHash("sha256").update(title).digest("hex").slice(0, MANUAL_ID_HASH_LENGTH);
|
|
312
|
-
return `${version}:${hash}`;
|
|
313
|
-
}
|
|
314
308
|
// Breaking entries that need hand work carry the id `kumiko-upgrade --resolve` takes.
|
|
315
309
|
function manualIdOf(entry) {
|
|
316
310
|
return entry.type === "breaking" && needsManualMigration(entry)
|
|
@@ -324,15 +318,6 @@ function toMarkerManual(entry) {
|
|
|
324
318
|
title: entry.title,
|
|
325
319
|
};
|
|
326
320
|
}
|
|
327
|
-
function dedupeManualById(entries) {
|
|
328
|
-
const seen = new Set();
|
|
329
|
-
return entries.filter((entry) => {
|
|
330
|
-
if (seen.has(entry.id))
|
|
331
|
-
return false;
|
|
332
|
-
seen.add(entry.id);
|
|
333
|
-
return true;
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
321
|
// Open manual items survive every marker write until --resolve moves them.
|
|
337
322
|
function carryOverManual(previous, newManual) {
|
|
338
323
|
const resolvedIds = new Set(previous.resolvedManual.map((entry) => entry.id));
|
|
@@ -360,64 +345,6 @@ function writeUpgradeMarker(targetDir, marker) {
|
|
|
360
345
|
writeFileSync(join(dir, "upgrade-state.json"), `${JSON.stringify(marker, null, 2)}\n`, "utf-8");
|
|
361
346
|
}
|
|
362
347
|
const NO_CARRY = { codemods: [], pendingManual: [], resolvedManual: [] };
|
|
363
|
-
function isRecord(value) {
|
|
364
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
365
|
-
}
|
|
366
|
-
function parseManualEntry(value) {
|
|
367
|
-
if (!isRecord(value))
|
|
368
|
-
return null;
|
|
369
|
-
const { id, version, title } = value;
|
|
370
|
-
if (typeof version !== "string" || typeof title !== "string")
|
|
371
|
-
return null;
|
|
372
|
-
return {
|
|
373
|
-
id: typeof id === "string" && id.length > 0 ? id : manualEntryId(version, title),
|
|
374
|
-
version,
|
|
375
|
-
title,
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
function parseResolvedEntry(value) {
|
|
379
|
-
const base = parseManualEntry(value);
|
|
380
|
-
if (base === null || !isRecord(value))
|
|
381
|
-
return null;
|
|
382
|
-
const { resolution, reason, resolvedAt } = value;
|
|
383
|
-
if (resolution !== "migrated" && resolution !== "not-applicable")
|
|
384
|
-
return null;
|
|
385
|
-
if (typeof reason !== "string" || typeof resolvedAt !== "string")
|
|
386
|
-
return null;
|
|
387
|
-
return { ...base, resolution, reason, resolvedAt };
|
|
388
|
-
}
|
|
389
|
-
function parseList(value, parseEntry) {
|
|
390
|
-
if (value === undefined)
|
|
391
|
-
return [];
|
|
392
|
-
if (!Array.isArray(value))
|
|
393
|
-
return null;
|
|
394
|
-
const parsed = value.map(parseEntry);
|
|
395
|
-
return parsed.every((entry) => entry !== null) ? parsed : null;
|
|
396
|
-
}
|
|
397
|
-
function isMarkerCodemod(value) {
|
|
398
|
-
return (isRecord(value) &&
|
|
399
|
-
typeof value["version"] === "string" &&
|
|
400
|
-
typeof value["codemod"] === "string" &&
|
|
401
|
-
typeof value["title"] === "string");
|
|
402
|
-
}
|
|
403
|
-
function parseStoredMarker(raw) {
|
|
404
|
-
if (!isRecord(raw))
|
|
405
|
-
return null;
|
|
406
|
-
const { version, appliedAt, codemods } = raw;
|
|
407
|
-
if (typeof version !== "string" || !SEMVER_RE.test(version))
|
|
408
|
-
return null;
|
|
409
|
-
const pendingManual = parseList(raw["pendingManual"], parseManualEntry);
|
|
410
|
-
const resolvedManual = parseList(raw["resolvedManual"], parseResolvedEntry);
|
|
411
|
-
if (pendingManual === null || resolvedManual === null)
|
|
412
|
-
return null;
|
|
413
|
-
return {
|
|
414
|
-
version,
|
|
415
|
-
appliedAt: typeof appliedAt === "string" ? appliedAt : Temporal.Now.instant().toString(),
|
|
416
|
-
codemods: Array.isArray(codemods) ? codemods.filter(isMarkerCodemod) : [],
|
|
417
|
-
pendingManual: dedupeManualById(pendingManual),
|
|
418
|
-
resolvedManual: dedupeManualById(resolvedManual),
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
348
|
// A missing marker is a bootstrap app that never ran `--apply`; an
|
|
422
349
|
// existing but unreadable one must not silently fall back to the installed
|
|
423
350
|
// version, or a bare `--apply` would skip every codemod in between.
|
|
@@ -659,27 +586,27 @@ function matchManualRefs(open, refs) {
|
|
|
659
586
|
}
|
|
660
587
|
return { resolvedIds, errors };
|
|
661
588
|
}
|
|
589
|
+
function failUpgrade(out, ...lines) {
|
|
590
|
+
out.err("");
|
|
591
|
+
for (const line of lines)
|
|
592
|
+
out.err(` ${line}`);
|
|
593
|
+
out.err("");
|
|
594
|
+
return 1;
|
|
595
|
+
}
|
|
662
596
|
function resolveManualMigrations(out, args, targetDir) {
|
|
663
|
-
const fail = (...lines) => {
|
|
664
|
-
out.err("");
|
|
665
|
-
for (const line of lines)
|
|
666
|
-
out.err(` ${line}`);
|
|
667
|
-
out.err("");
|
|
668
|
-
return 1;
|
|
669
|
-
};
|
|
670
597
|
const input = parseResolveInput(args);
|
|
671
598
|
if ("error" in input)
|
|
672
|
-
return
|
|
599
|
+
return failUpgrade(out, input.error);
|
|
673
600
|
const read = readMarker(targetDir);
|
|
674
601
|
if (read.kind === "missing") {
|
|
675
|
-
return
|
|
602
|
+
return failUpgrade(out, `No .kumiko/upgrade-state.json under ${targetDir}, nothing to resolve.`);
|
|
676
603
|
}
|
|
677
604
|
if (read.kind === "invalid")
|
|
678
|
-
return
|
|
605
|
+
return failUpgrade(out, "invalid .kumiko/upgrade-state.json, fix it first.");
|
|
679
606
|
const open = read.marker.pendingManual;
|
|
680
607
|
const { resolvedIds, errors } = matchManualRefs(open, input.refs);
|
|
681
608
|
if (errors.length > 0)
|
|
682
|
-
return
|
|
609
|
+
return failUpgrade(out, ...errors, "Nothing was written.");
|
|
683
610
|
const { reason } = input;
|
|
684
611
|
const resolution = getFlag(args, "not-applicable")
|
|
685
612
|
? "not-applicable"
|
|
@@ -697,6 +624,11 @@ function resolveManualMigrations(out, args, targetDir) {
|
|
|
697
624
|
...(remaining.length > 0 && { pendingManual: remaining }),
|
|
698
625
|
resolvedManual,
|
|
699
626
|
});
|
|
627
|
+
const changelogPath = join(targetDir, "CHANGELOG.md");
|
|
628
|
+
if (existsSync(changelogPath)) {
|
|
629
|
+
const content = readFileSync(changelogPath, "utf-8");
|
|
630
|
+
writeFileSync(changelogPath, setManualStatusInChangelog(content, resolvedIds, resolution), "utf-8");
|
|
631
|
+
}
|
|
700
632
|
out.log("");
|
|
701
633
|
out.log(` ✓ Marked ${newlyResolved.length} manual migration(s) as ${resolution}:`);
|
|
702
634
|
for (const entry of newlyResolved) {
|
|
@@ -721,32 +653,7 @@ kumiko-upgrade --resolve <id|version>[,<id|version>...] --reason "<text>" [--not
|
|
|
721
653
|
--not-applicable with --resolve, record the entries as not applicable instead of migrated
|
|
722
654
|
--dry-run with --apply, report what would run without writing anything
|
|
723
655
|
--help, -h print this usage and exit`;
|
|
724
|
-
|
|
725
|
-
export async function runUpgradeCli(argv, cwd, out, options) {
|
|
726
|
-
if (argv.includes("--help") || argv.includes("-h")) {
|
|
727
|
-
out.log(UPGRADE_USAGE);
|
|
728
|
-
return 0;
|
|
729
|
-
}
|
|
730
|
-
// Standalone CLI entry, not booted via runProdApp/runDevApp — Temporal needs an explicit polyfill here.
|
|
731
|
-
await ensureTemporalPolyfill();
|
|
732
|
-
const repoRoot = options?.repoRoot ?? cwd;
|
|
733
|
-
const args = parseArgs(argv);
|
|
734
|
-
const jsonMode = getFlag(args, "json");
|
|
735
|
-
const verbose = getFlag(args, "verbose");
|
|
736
|
-
const fromFlag = getStringFlag(args, "from");
|
|
737
|
-
// Resolved once here (not just inside --apply) so both the filter
|
|
738
|
-
// baseline below and the --apply codemod run target the same directory.
|
|
739
|
-
const dirFlag = getStringFlag(args, "dir");
|
|
740
|
-
const targetDir = dirFlag ? resolve(dirFlag) : cwd;
|
|
741
|
-
if (!existsSync(targetDir) || !statSync(targetDir).isDirectory()) {
|
|
742
|
-
out.err("");
|
|
743
|
-
out.err(` --dir path is not a directory: ${targetDir}`);
|
|
744
|
-
out.err("");
|
|
745
|
-
return 1;
|
|
746
|
-
}
|
|
747
|
-
if (args.flags.has("resolve")) {
|
|
748
|
-
return resolveManualMigrations(out, args, targetDir);
|
|
749
|
-
}
|
|
656
|
+
function resolveUpgradeBaseline(cwd, targetDir, fromFlag) {
|
|
750
657
|
// Always resolve the actually installed version, even when --from is set,
|
|
751
658
|
// so --json can report both the filter baseline and what's really there.
|
|
752
659
|
const installedVersion = readCurrentVersion(cwd);
|
|
@@ -761,33 +668,40 @@ export async function runUpgradeCli(argv, cwd, out, options) {
|
|
|
761
668
|
const markerRead = readMarker(targetDir);
|
|
762
669
|
const marker = fromFlag === undefined ? markerRead : { kind: "missing" };
|
|
763
670
|
if (marker.kind === "invalid") {
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
671
|
+
return {
|
|
672
|
+
kind: "error",
|
|
673
|
+
lines: ["invalid .kumiko/upgrade-state.json, fix it or pass --from <version>"],
|
|
674
|
+
};
|
|
768
675
|
}
|
|
769
676
|
const currentVersion = fromFlag ?? (marker.kind === "ok" ? marker.version : undefined) ?? installedVersion;
|
|
770
677
|
if (!currentVersion) {
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
678
|
+
return {
|
|
679
|
+
kind: "error",
|
|
680
|
+
lines: [
|
|
681
|
+
"Could not detect Kumiko version.",
|
|
682
|
+
"Run from an app directory with node_modules, or use --from <version>.",
|
|
683
|
+
],
|
|
684
|
+
};
|
|
776
685
|
}
|
|
777
686
|
if (!SEMVER_RE.test(currentVersion)) {
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
687
|
+
return {
|
|
688
|
+
kind: "error",
|
|
689
|
+
lines: [`Invalid version format: "${currentVersion}" — expected x.y.z`],
|
|
690
|
+
};
|
|
782
691
|
}
|
|
692
|
+
return { kind: "ok", value: { currentVersion, installedVersion, markerRead } };
|
|
693
|
+
}
|
|
694
|
+
function collectAllChangelogEntries(cwd) {
|
|
783
695
|
const featuresDirs = findFeaturesDirs(cwd);
|
|
784
696
|
const packageChangelogFiles = findPackageChangelogFiles(cwd);
|
|
785
697
|
if (featuresDirs.length === 0 && packageChangelogFiles.length === 0) {
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
698
|
+
return {
|
|
699
|
+
kind: "error",
|
|
700
|
+
lines: [
|
|
701
|
+
"Could not find bundled-features directory.",
|
|
702
|
+
"Run from framework/enterprise repo or an app with node_modules.",
|
|
703
|
+
],
|
|
704
|
+
};
|
|
791
705
|
}
|
|
792
706
|
const allEntries = [];
|
|
793
707
|
for (const dir of featuresDirs) {
|
|
@@ -796,6 +710,18 @@ export async function runUpgradeCli(argv, cwd, out, options) {
|
|
|
796
710
|
for (const changelogFile of packageChangelogFiles) {
|
|
797
711
|
allEntries.push(...readChangelogFile(changelogFile));
|
|
798
712
|
}
|
|
713
|
+
return { kind: "ok", value: allEntries };
|
|
714
|
+
}
|
|
715
|
+
function planUpgrade(args, cwd, targetDir) {
|
|
716
|
+
const dirFlag = getStringFlag(args, "dir");
|
|
717
|
+
const baseline = resolveUpgradeBaseline(cwd, targetDir, getStringFlag(args, "from"));
|
|
718
|
+
if (baseline.kind === "error")
|
|
719
|
+
return baseline;
|
|
720
|
+
const entries = collectAllChangelogEntries(cwd);
|
|
721
|
+
if (entries.kind === "error")
|
|
722
|
+
return entries;
|
|
723
|
+
const { currentVersion, installedVersion } = baseline.value;
|
|
724
|
+
const allEntries = entries.value;
|
|
799
725
|
// Installed version of the target the marker belongs to (cwd unless --dir).
|
|
800
726
|
const targetInstalledVersion = dirFlag ? readCurrentVersion(targetDir) : installedVersion;
|
|
801
727
|
// Changelogs can be found in a parent workspace's newer install. A change
|
|
@@ -804,87 +730,135 @@ export async function runUpgradeCli(argv, cwd, out, options) {
|
|
|
804
730
|
? allEntries
|
|
805
731
|
: allEntries.filter((entry) => compareVersions(entry.version, targetInstalledVersion) <= 0);
|
|
806
732
|
const pending = sortEntries(filterEntriesAfter(installedEntries, currentVersion));
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
733
|
+
return {
|
|
734
|
+
kind: "ok",
|
|
735
|
+
value: { ...baseline.value, targetInstalledVersion, allEntries, pending },
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
async function applyPlannedUpgrade(out, args, plan, repoRoot, targetDir) {
|
|
739
|
+
// Marker must reflect what is actually installed under the target (or
|
|
740
|
+
// cwd), not the filter baseline above — otherwise CI stays green forever.
|
|
741
|
+
const markerVersion = plan.targetInstalledVersion;
|
|
742
|
+
const dryRun = getFlag(args, "dry-run");
|
|
743
|
+
if (markerVersion === null && !dryRun) {
|
|
744
|
+
return failUpgrade(out, `Could not detect the installed Kumiko version under ${targetDir}.`, "Refusing to write an upgrade marker without it (--from is only a filter).");
|
|
745
|
+
}
|
|
746
|
+
out.log("");
|
|
747
|
+
const code = await applyCodemods(out, plan.pending, repoRoot, targetDir, dryRun, markerVersion ?? plan.currentVersion, carryOf(plan.markerRead), plan.currentVersion, getFlag(args, "verbose") ? manualDetailsOf(plan.allEntries) : undefined);
|
|
748
|
+
out.log("");
|
|
749
|
+
return code;
|
|
750
|
+
}
|
|
751
|
+
function reportUpgradeJson(out, plan) {
|
|
752
|
+
const { currentVersion, installedVersion } = plan;
|
|
753
|
+
const { pendingManual } = carryOf(plan.markerRead);
|
|
754
|
+
const pendingWithManualId = plan.pending.map((entry) => {
|
|
755
|
+
const manualId = manualIdOf(entry);
|
|
756
|
+
return manualId === undefined ? entry : { ...entry, manualId };
|
|
757
|
+
});
|
|
758
|
+
out.log(JSON.stringify({ currentVersion, installedVersion, pending: pendingWithManualId, pendingManual }, null, 2));
|
|
759
|
+
return 0;
|
|
760
|
+
}
|
|
761
|
+
function logEntryDetail(out, entry, verbose) {
|
|
762
|
+
if (verbose && entry.detail) {
|
|
763
|
+
out.log(` ${entry.detail}`);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
function logBreakingSection(out, breaking, verbose) {
|
|
767
|
+
// skip: no breaking entries, the section is omitted
|
|
768
|
+
if (breaking.length === 0)
|
|
769
|
+
return;
|
|
770
|
+
out.log(` ⚠ BREAKING (${breaking.length})`);
|
|
771
|
+
out.log("");
|
|
772
|
+
for (const e of breaking) {
|
|
773
|
+
const manualId = manualIdOf(e);
|
|
774
|
+
out.log(` ${e.version} · ${e.title}${manualId === undefined ? "" : ` [${manualId}]`}`);
|
|
775
|
+
logEntryDetail(out, e, verbose);
|
|
776
|
+
if (e.migration) {
|
|
777
|
+
out.log(` → Migration: ${e.migration}`);
|
|
818
778
|
}
|
|
819
779
|
out.log("");
|
|
820
|
-
const code = await applyCodemods(out, pending, repoRoot, targetDir, dryRun, markerVersion ?? currentVersion, carryOf(markerRead), currentVersion, verbose ? manualDetailsOf(allEntries) : undefined);
|
|
821
|
-
out.log("");
|
|
822
|
-
return code;
|
|
823
|
-
}
|
|
824
|
-
if (jsonMode) {
|
|
825
|
-
const { pendingManual } = carryOf(markerRead);
|
|
826
|
-
const pendingWithManualId = pending.map((entry) => {
|
|
827
|
-
const manualId = manualIdOf(entry);
|
|
828
|
-
return manualId === undefined ? entry : { ...entry, manualId };
|
|
829
|
-
});
|
|
830
|
-
out.log(JSON.stringify({ currentVersion, installedVersion, pending: pendingWithManualId, pendingManual }, null, 2));
|
|
831
|
-
return 0;
|
|
832
780
|
}
|
|
781
|
+
}
|
|
782
|
+
function logNonBreakingSection(out, heading, entries, verbose, showCodemod) {
|
|
783
|
+
// skip: no entries of this type, the section is omitted
|
|
784
|
+
if (entries.length === 0)
|
|
785
|
+
return;
|
|
786
|
+
out.log(` ✓ ${heading} (${entries.length})`);
|
|
787
|
+
out.log("");
|
|
788
|
+
for (const e of entries) {
|
|
789
|
+
out.log(` ${e.version} · ${e.title}`);
|
|
790
|
+
logEntryDetail(out, e, verbose);
|
|
791
|
+
if (showCodemod && hasCodemod(e)) {
|
|
792
|
+
out.log(` → codemod: ${e.codemod} (runs on --apply)`);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
out.log("");
|
|
796
|
+
}
|
|
797
|
+
function logApplyHint(out, plan) {
|
|
798
|
+
const { markerRead, targetInstalledVersion } = plan;
|
|
799
|
+
const markerBehindInstalled = markerRead.kind === "ok" &&
|
|
800
|
+
targetInstalledVersion !== null &&
|
|
801
|
+
compareVersions(markerRead.version, targetInstalledVersion) < 0;
|
|
802
|
+
// skip: nothing differs between marker and installed version, so there is nothing to record.
|
|
803
|
+
if (plan.pending.length === 0 && !markerBehindInstalled)
|
|
804
|
+
return;
|
|
805
|
+
out.log(" Nothing is recorded yet: the upgrade CHANGELOG and the marker are only");
|
|
806
|
+
out.log(" written by --apply (add --dry-run to preview without writing).");
|
|
807
|
+
out.log("");
|
|
808
|
+
}
|
|
809
|
+
function reportUpgradeText(out, plan, verbose) {
|
|
810
|
+
const { pending } = plan;
|
|
833
811
|
const breaking = pending.filter((e) => e.type === "breaking");
|
|
834
|
-
const
|
|
835
|
-
const
|
|
836
|
-
const openManual = carryOf(markerRead).pendingManual;
|
|
812
|
+
const openManual = carryOf(plan.markerRead).pendingManual;
|
|
813
|
+
const manualDetails = verbose ? manualDetailsOf(plan.allEntries) : undefined;
|
|
837
814
|
out.log("");
|
|
838
|
-
out.log(` Upgrade: ${currentVersion} → latest`);
|
|
815
|
+
out.log(` Upgrade: ${plan.currentVersion} → latest`);
|
|
839
816
|
out.log("");
|
|
840
817
|
if (pending.length === 0) {
|
|
841
818
|
out.log(" ✓ Nothing new since your version.");
|
|
842
819
|
out.log("");
|
|
843
|
-
|
|
820
|
+
logApplyHint(out, plan);
|
|
821
|
+
logOpenManual(out, openManual, manualDetails);
|
|
844
822
|
return 0;
|
|
845
823
|
}
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
for (const e of breaking) {
|
|
850
|
-
const manualId = manualIdOf(e);
|
|
851
|
-
out.log(` ${e.version} · ${e.title}${manualId === undefined ? "" : ` [${manualId}]`}`);
|
|
852
|
-
if (verbose && e.detail) {
|
|
853
|
-
out.log(` ${e.detail}`);
|
|
854
|
-
}
|
|
855
|
-
if (e.migration) {
|
|
856
|
-
out.log(` → Migration: ${e.migration}`);
|
|
857
|
-
}
|
|
858
|
-
out.log("");
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
if (improvements.length > 0) {
|
|
862
|
-
out.log(` ✓ IMPROVEMENTS (${improvements.length})`);
|
|
863
|
-
out.log("");
|
|
864
|
-
for (const e of improvements) {
|
|
865
|
-
out.log(` ${e.version} · ${e.title}`);
|
|
866
|
-
if (verbose && e.detail) {
|
|
867
|
-
out.log(` ${e.detail}`);
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
out.log("");
|
|
871
|
-
}
|
|
872
|
-
if (fixes.length > 0) {
|
|
873
|
-
out.log(` ✓ FIXES (${fixes.length})`);
|
|
874
|
-
out.log("");
|
|
875
|
-
for (const e of fixes) {
|
|
876
|
-
out.log(` ${e.version} · ${e.title}`);
|
|
877
|
-
if (verbose && e.detail) {
|
|
878
|
-
out.log(` ${e.detail}`);
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
out.log("");
|
|
882
|
-
}
|
|
824
|
+
logBreakingSection(out, breaking, verbose);
|
|
825
|
+
logNonBreakingSection(out, "IMPROVEMENTS", pending.filter((e) => e.type === "improvement"), verbose, true);
|
|
826
|
+
logNonBreakingSection(out, "FIXES", pending.filter((e) => e.type === "fix"), verbose, false);
|
|
883
827
|
if (breaking.length > 0) {
|
|
884
828
|
out.log(" ⚠ Review breaking changes above before upgrading.");
|
|
885
829
|
out.log(" Run with --verbose for full migration details.");
|
|
886
830
|
out.log("");
|
|
887
831
|
}
|
|
888
|
-
|
|
832
|
+
logApplyHint(out, plan);
|
|
833
|
+
logOpenManual(out, openManual, manualDetails);
|
|
889
834
|
return 0;
|
|
890
835
|
}
|
|
836
|
+
// Shared by `kumiko upgrade` and the published kumiko-upgrade bin.
|
|
837
|
+
export async function runUpgradeCli(argv, cwd, out, options) {
|
|
838
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
839
|
+
out.log(UPGRADE_USAGE);
|
|
840
|
+
return 0;
|
|
841
|
+
}
|
|
842
|
+
// Standalone CLI entry, not booted via runProdApp/runDevApp — Temporal needs an explicit polyfill here.
|
|
843
|
+
await ensureTemporalPolyfill();
|
|
844
|
+
const args = parseArgs(argv);
|
|
845
|
+
// Resolved once here (not just inside --apply) so both the filter
|
|
846
|
+
// baseline and the --apply codemod run target the same directory.
|
|
847
|
+
const dirFlag = getStringFlag(args, "dir");
|
|
848
|
+
const targetDir = dirFlag ? resolve(dirFlag) : cwd;
|
|
849
|
+
if (!existsSync(targetDir) || !statSync(targetDir).isDirectory()) {
|
|
850
|
+
return failUpgrade(out, `--dir path is not a directory: ${targetDir}`);
|
|
851
|
+
}
|
|
852
|
+
if (args.flags.has("resolve")) {
|
|
853
|
+
return resolveManualMigrations(out, args, targetDir);
|
|
854
|
+
}
|
|
855
|
+
const planned = planUpgrade(args, cwd, targetDir);
|
|
856
|
+
if (planned.kind === "error")
|
|
857
|
+
return failUpgrade(out, ...planned.lines);
|
|
858
|
+
if (getFlag(args, "apply")) {
|
|
859
|
+
return applyPlannedUpgrade(out, args, planned.value, options?.repoRoot ?? cwd, targetDir);
|
|
860
|
+
}
|
|
861
|
+
if (getFlag(args, "json"))
|
|
862
|
+
return reportUpgradeJson(out, planned.value);
|
|
863
|
+
return reportUpgradeText(out, planned.value, getFlag(args, "verbose"));
|
|
864
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare const SEMVER_RE: RegExp;
|
|
2
|
+
export type UpgradeMarkerCodemod = {
|
|
3
|
+
readonly version: string;
|
|
4
|
+
readonly codemod: string;
|
|
5
|
+
readonly title: string;
|
|
6
|
+
};
|
|
7
|
+
export type UpgradeMarkerManual = {
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly version: string;
|
|
10
|
+
readonly title: string;
|
|
11
|
+
};
|
|
12
|
+
export type ManualResolution = "migrated" | "not-applicable";
|
|
13
|
+
export type UpgradeMarkerResolvedManual = UpgradeMarkerManual & {
|
|
14
|
+
readonly resolution: ManualResolution;
|
|
15
|
+
readonly reason: string;
|
|
16
|
+
readonly resolvedAt: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function manualEntryId(version: string, title: string): string;
|
|
19
|
+
export declare function dedupeManualById<T extends {
|
|
20
|
+
readonly id: string;
|
|
21
|
+
}>(entries: readonly T[]): readonly T[];
|
|
22
|
+
export type MarkerCarry = {
|
|
23
|
+
readonly codemods: readonly UpgradeMarkerCodemod[];
|
|
24
|
+
readonly pendingManual: readonly UpgradeMarkerManual[];
|
|
25
|
+
readonly resolvedManual: readonly UpgradeMarkerResolvedManual[];
|
|
26
|
+
};
|
|
27
|
+
export type StoredMarker = MarkerCarry & {
|
|
28
|
+
readonly version: string;
|
|
29
|
+
readonly appliedAt: string;
|
|
30
|
+
readonly codemods: readonly UpgradeMarkerCodemod[];
|
|
31
|
+
};
|
|
32
|
+
export declare function parseStoredMarker(raw: unknown): StoredMarker | null;
|