@cosmicdrift/kumiko-framework 1.0.0 → 2.0.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/README.md +9 -38
- package/package.json +21 -2
- package/src/__tests__/anonymous-access.integration.test.ts +185 -0
- package/src/__tests__/consumer-cli.integration.test.ts +172 -0
- package/src/__tests__/entity-permalink-open.integration.test.ts +94 -0
- package/src/__tests__/full-stack.integration.test.ts +1 -1
- package/src/__tests__/schema-cli-temporal-polyfill.test.ts +48 -0
- package/src/__tests__/schema-cli.integration.test.ts +50 -0
- package/src/__tests__/store-table.integration.test.ts +93 -0
- package/src/api/__tests__/api.test.ts +373 -0
- package/src/api/__tests__/auth-middleware-anonymous-access-boot.test.ts +40 -0
- package/src/api/__tests__/auth-routes-cookie.test.ts +17 -1
- package/src/api/__tests__/auth-routes-invalid-body-invite.test.ts +253 -0
- package/src/api/__tests__/auth-routes-mfa-preauth-confirm.test.ts +222 -0
- package/src/api/__tests__/auth-routes-mfa-preauth-enable-start.test.ts +249 -0
- package/src/api/__tests__/auth-routes-mfa-verify.test.ts +202 -0
- package/src/api/__tests__/auth-routes-trusted-proxy.test.ts +135 -0
- package/src/api/__tests__/batch.integration.test.ts +101 -11
- package/src/api/__tests__/csrf-constants-sync.test.ts +20 -0
- package/src/api/__tests__/dispatcher-live.integration.test.ts +74 -0
- package/src/api/__tests__/jwt.test.ts +200 -1
- package/src/api/__tests__/login-rate-limiter-sweep.test.ts +50 -0
- package/src/api/__tests__/pat-scope.test.ts +36 -0
- package/src/api/__tests__/pii-leak-guard.integration.test.ts +103 -0
- package/src/api/__tests__/redis-login-rate-limiter.integration.test.ts +138 -0
- package/src/api/__tests__/request-id-middleware.test.ts +51 -0
- package/src/api/__tests__/server-boot-guards.test.ts +71 -0
- package/src/api/__tests__/server-jwt-ttl.test.ts +58 -0
- package/src/api/__tests__/sse-broker.test.ts +57 -0
- package/src/api/__tests__/sse-route.test.ts +4 -0
- package/src/api/api-constants.ts +11 -0
- package/src/api/auth-middleware.ts +248 -40
- package/src/api/auth-routes.ts +576 -95
- package/src/api/index.ts +13 -4
- package/src/api/jwt.ts +170 -11
- package/src/api/pat-scope.ts +14 -0
- package/src/api/pii-leak-guard.ts +47 -0
- package/src/api/request-context.ts +3 -0
- package/src/api/request-id-middleware.ts +2 -0
- package/src/api/routes.ts +169 -2
- package/src/api/server.ts +112 -16
- package/src/api/sse-broker.ts +39 -0
- package/src/bun-db/__tests__/PATTERN.md +0 -1
- package/src/bun-db/__tests__/coerce-row-temporal.test.ts +41 -0
- package/src/bun-db/__tests__/select-many-retry.test.ts +79 -0
- package/src/bun-db/__tests__/write-brand.test.ts +21 -0
- package/src/bun-db/connection.ts +3 -3
- package/src/bun-db/index.ts +2 -0
- package/src/bun-db/query.ts +105 -32
- package/src/consumer-cli.ts +134 -0
- package/src/crypto/__tests__/blind-index.test.ts +130 -0
- package/src/crypto/__tests__/event-pii.test.ts +161 -0
- package/src/crypto/__tests__/kek-rotation.integration.test.ts +180 -0
- package/src/crypto/__tests__/kms-adapter-contract.ts +134 -0
- package/src/crypto/__tests__/kms-adapter.contract.test.ts +4 -0
- package/src/crypto/__tests__/pg-kms-adapter.integration.test.ts +117 -0
- package/src/crypto/__tests__/pii-field-encryption.test.ts +376 -0
- package/src/crypto/__tests__/request-kms-cache.test.ts +74 -0
- package/src/crypto/__tests__/subject-resolver.test.ts +108 -0
- package/src/crypto/blind-index.ts +118 -0
- package/src/crypto/event-pii.ts +70 -0
- package/src/crypto/in-memory-kms-adapter.ts +50 -0
- package/src/crypto/index.ts +67 -0
- package/src/crypto/kms-adapter.ts +2 -0
- package/src/crypto/pg-kms-adapter.ts +295 -0
- package/src/crypto/pii-field-encryption.ts +248 -0
- package/src/crypto/request-kms-cache.ts +38 -0
- package/src/crypto/subject-resolver.ts +91 -0
- package/src/db/__tests__/assert-no-unreachable-live-rows.integration.test.ts +191 -0
- package/src/db/__tests__/blind-index.integration.test.ts +248 -0
- package/src/db/__tests__/build-filter-where.test.ts +34 -0
- package/src/db/__tests__/collect-table-metas.test.ts +10 -10
- package/src/db/__tests__/config-seed.integration.test.ts +13 -5
- package/src/db/__tests__/dialect-instant.test.ts +1 -4
- package/src/db/__tests__/entity-field-encryption.test.ts +7 -7
- package/src/db/__tests__/entity-table-meta-source.test.ts +50 -0
- package/src/db/__tests__/event-store-executor-context.pii-roundtrip.test.ts +67 -0
- package/src/db/__tests__/event-store-executor-write-verbs.integration.test.ts +402 -0
- package/src/db/__tests__/event-store-executor.integration.test.ts +299 -29
- package/src/db/__tests__/feature-table-sources.test.ts +34 -0
- package/src/db/__tests__/implicit-projection-equivalence.integration.test.ts +118 -39
- package/src/db/__tests__/instant-to-driver-temporal.test.ts +21 -0
- package/src/db/__tests__/located-timestamp.test.ts +19 -0
- package/src/db/__tests__/migrate-generator.test.ts +21 -0
- package/src/db/__tests__/migrate-runner.test.ts +61 -0
- package/src/db/__tests__/number-field-fractional.integration.test.ts +58 -0
- package/src/db/__tests__/rebuild-marker.test.ts +13 -3
- package/src/db/__tests__/replay-migration-sql.test.ts +384 -0
- package/src/db/__tests__/schema-inspection.test.ts +7 -0
- package/src/db/__tests__/schema-migration.integration.test.ts +1 -1
- package/src/db/__tests__/table-builder-meta-lockstep.test.ts +39 -0
- package/src/db/__tests__/tenant-db-where-merge.test.ts +49 -3
- package/src/db/__tests__/tenant-db.integration.test.ts +6 -2
- package/src/db/api.ts +2 -2
- package/src/db/apply-entity-event.ts +18 -14
- package/src/db/blind-index-cleanup.ts +55 -0
- package/src/db/bun-provider.ts +2 -2
- package/src/db/collect-table-metas.ts +6 -7
- package/src/db/config-seed.ts +9 -9
- package/src/db/connection.ts +7 -12
- package/src/db/cursor.ts +1 -18
- package/src/db/dialect.ts +20 -26
- package/src/db/entity-field-encryption.ts +81 -24
- package/src/db/entity-table-meta-types.ts +2 -0
- package/src/db/entity-table-meta.ts +63 -90
- package/src/db/event-store-executor-context.ts +404 -0
- package/src/db/event-store-executor-read.ts +275 -0
- package/src/db/event-store-executor-write.ts +644 -0
- package/src/db/event-store-executor.ts +28 -1155
- package/src/db/feature-table-sources.ts +6 -5
- package/src/db/index.ts +20 -3
- package/src/db/located-timestamp.ts +4 -0
- package/src/db/migrate-generator.ts +39 -6
- package/src/db/migrate-runner.ts +107 -11
- package/src/db/pg-error.ts +9 -1
- package/src/db/postgres-provider.ts +2 -2
- package/src/db/queries/__tests__/event-store-idempotency-index.integration.test.ts +80 -0
- package/src/db/queries/backfill-pii.ts +277 -0
- package/src/db/queries/ddl.ts +45 -0
- package/src/db/queries/event-consumer.ts +35 -2
- package/src/db/queries/event-store.ts +126 -19
- package/src/db/queries/projection-rebuild.ts +22 -8
- package/src/db/queries/shadow-swap.ts +183 -0
- package/src/db/queries/test-stack.ts +4 -30
- package/src/db/query-api.ts +1 -0
- package/src/db/query.ts +1 -0
- package/src/db/rebuild-marker.ts +18 -2
- package/src/db/reference-data.ts +2 -3
- package/src/db/replay-migration-sql.ts +257 -0
- package/src/db/schema-inspection.ts +1 -1
- package/src/db/table-builder.ts +102 -71
- package/src/db/tenant-db.ts +15 -53
- package/src/engine/__tests__/boot-validator-action-wiring.test.ts +242 -0
- package/src/engine/__tests__/boot-validator-boot-check.test.ts +99 -0
- package/src/engine/__tests__/boot-validator-dashboard.test.ts +237 -0
- package/src/engine/__tests__/boot-validator-entity-list.test.ts +104 -0
- package/src/engine/__tests__/boot-validator-gdpr-storage.test.ts +7 -69
- package/src/engine/__tests__/boot-validator-i18n-keys.test.ts +26 -5
- package/src/engine/__tests__/boot-validator-located-timestamps.test.ts +3 -19
- package/src/engine/__tests__/boot-validator-pii-retention.test.ts +246 -4
- package/src/engine/__tests__/boot-validator.test.ts +219 -15
- package/src/engine/__tests__/build-app-schema.test.ts +82 -0
- package/src/engine/__tests__/build-config-feature-schema.test.ts +125 -0
- package/src/engine/__tests__/build-target.test.ts +3 -11
- package/src/engine/__tests__/codemod-pipeline.test.ts +152 -21
- package/src/engine/__tests__/config-helpers.test.ts +16 -0
- package/src/engine/__tests__/define-feature-entity-mapping.test.ts +6 -0
- package/src/engine/__tests__/define-roles.test.ts +21 -0
- package/src/engine/__tests__/engine.test.ts +163 -1
- package/src/engine/__tests__/entity-handlers.test.ts +80 -0
- package/src/engine/__tests__/event-migration-declarative.test.ts +65 -0
- package/src/engine/__tests__/event-type-map-augmentation.test.ts +24 -0
- package/src/engine/__tests__/extend-entity-projection.test.ts +123 -0
- package/src/engine/__tests__/factories-time.test.ts +2 -66
- package/src/engine/__tests__/feature-crud-shorthand.test.ts +28 -0
- package/src/engine/__tests__/feature-manifest.test.ts +31 -1
- package/src/engine/__tests__/field-access.test.ts +23 -1
- package/src/engine/__tests__/hook-phases.test.ts +5 -5
- package/src/engine/__tests__/membership-roles.test.ts +4 -10
- package/src/engine/__tests__/nav.test.ts +86 -1
- package/src/engine/__tests__/pipeline-engine.test.ts +9 -9
- package/src/engine/__tests__/pipeline-handler.integration.test.ts +18 -18
- package/src/engine/__tests__/pipeline-observability.integration.test.ts +2 -2
- package/src/engine/__tests__/pipeline-performance.integration.test.ts +3 -3
- package/src/engine/__tests__/pipeline-sub-pipelines.test.ts +9 -9
- package/src/engine/__tests__/post-query-hook.test.ts +7 -7
- package/src/engine/__tests__/registrar-object-form.test.ts +141 -0
- package/src/engine/__tests__/registry.test.ts +144 -0
- package/src/engine/__tests__/schema-builder.test.ts +18 -0
- package/src/engine/__tests__/screen.test.ts +147 -1
- package/src/engine/__tests__/soft-delete-cleanup.test.ts +3 -0
- package/src/engine/__tests__/store-table.test.ts +229 -0
- package/src/engine/__tests__/tier-resolver-extension.test.ts +19 -1
- package/src/engine/__tests__/{visual-tree-patterns.test.ts → tree-actions-patterns.test.ts} +7 -95
- package/src/engine/__tests__/validate-projection-allowlist.test.ts +15 -15
- package/src/engine/boot-validator/__tests__/config-deps.test.ts +92 -0
- package/src/engine/boot-validator/action-wiring.ts +149 -0
- package/src/engine/boot-validator/boot-check.ts +21 -0
- package/src/engine/boot-validator/config-deps.ts +40 -4
- package/src/engine/boot-validator/entity-handler.ts +20 -21
- package/src/engine/boot-validator/entity-list-screens.ts +88 -0
- package/src/engine/boot-validator/gdpr-storage.ts +0 -20
- package/src/engine/boot-validator/i18n-keys.ts +58 -4
- package/src/engine/boot-validator/index.ts +33 -12
- package/src/engine/boot-validator/nav.ts +125 -0
- package/src/engine/boot-validator/pii-retention.ts +95 -10
- package/src/engine/boot-validator/{screens-nav.ts → screens.ts} +214 -191
- package/src/engine/boot-validator/workspaces.ts +68 -0
- package/src/engine/build-app-schema.ts +16 -0
- package/src/engine/build-config-feature-schema.ts +44 -7
- package/src/engine/codemod/pipeline-codemod.ts +5 -5
- package/src/engine/config-helpers.ts +15 -0
- package/src/engine/constants.ts +32 -6
- package/src/engine/create-app.ts +11 -0
- package/src/engine/define-feature.ts +95 -947
- package/src/engine/define-handler.ts +28 -94
- package/src/engine/define-workflow.ts +1 -1
- package/src/engine/effective-features.ts +12 -2
- package/src/engine/entity-handlers.ts +76 -11
- package/src/engine/extensions/tenant-data.ts +19 -0
- package/src/engine/extensions/user-data.ts +29 -2
- package/src/engine/factories.ts +8 -49
- package/src/engine/feature-ast/__tests__/canonical-form.test.ts +26 -29
- package/src/engine/feature-ast/__tests__/fixtures/cross-file-registrar/feature.ts +9 -0
- package/src/engine/feature-ast/__tests__/fixtures/cross-file-registrar/screens.ts +4 -0
- package/src/engine/feature-ast/__tests__/parse-happy-path.test.ts +1 -2
- package/src/engine/feature-ast/__tests__/parse-real-features.test.ts +18 -8
- package/src/engine/feature-ast/__tests__/parse.test.ts +1640 -160
- package/src/engine/feature-ast/__tests__/patch.test.ts +206 -12
- package/src/engine/feature-ast/__tests__/patcher.test.ts +20 -23
- package/src/engine/feature-ast/__tests__/render-roundtrip.test.ts +380 -5
- package/src/engine/feature-ast/extractors/events.ts +322 -0
- package/src/engine/feature-ast/extractors/handlers.ts +234 -0
- package/src/engine/feature-ast/extractors/hooks.ts +243 -0
- package/src/engine/feature-ast/extractors/index.ts +34 -31
- package/src/engine/feature-ast/extractors/jobs-routes.ts +221 -0
- package/src/engine/feature-ast/extractors/projections-screens.ts +269 -0
- package/src/engine/feature-ast/extractors/round1.ts +3 -3
- package/src/engine/feature-ast/extractors/round5.ts +3 -3
- package/src/engine/feature-ast/extractors/round6.ts +2 -36
- package/src/engine/feature-ast/extractors/shared.ts +64 -6
- package/src/engine/feature-ast/index.ts +2 -4
- package/src/engine/feature-ast/parse.ts +130 -23
- package/src/engine/feature-ast/patch.ts +39 -50
- package/src/engine/feature-ast/patcher.ts +37 -38
- package/src/engine/feature-ast/patterns.ts +50 -62
- package/src/engine/feature-ast/render.ts +67 -44
- package/src/engine/feature-builder-state.ts +168 -0
- package/src/engine/feature-config-events-jobs.ts +403 -0
- package/src/engine/feature-entity-handlers.ts +208 -0
- package/src/engine/feature-manifest.ts +2 -1
- package/src/engine/feature-ui-extensions.ts +500 -0
- package/src/engine/field-access.ts +13 -2
- package/src/engine/field-helpers.ts +31 -0
- package/src/engine/handler-helpers.ts +26 -0
- package/src/engine/hook-helpers.ts +16 -0
- package/src/engine/index.ts +23 -7
- package/src/engine/membership-roles.ts +13 -0
- package/src/engine/object-form.ts +27 -0
- package/src/engine/ownership.ts +26 -79
- package/src/engine/pattern-library/__tests__/library.test.ts +7 -20
- package/src/engine/pattern-library/library.ts +44 -1152
- package/src/engine/pattern-library/mixed-schemas.ts +450 -0
- package/src/engine/pattern-library/opaque-schemas.ts +124 -0
- package/src/engine/pattern-library/shared-fields.ts +75 -0
- package/src/engine/pattern-library/static-schemas.ts +456 -0
- package/src/engine/pipeline.ts +6 -11
- package/src/engine/registry-facade.ts +362 -0
- package/src/engine/registry-ingest.ts +478 -0
- package/src/engine/registry-state.ts +388 -0
- package/src/engine/registry-validate.ts +642 -0
- package/src/engine/registry.ts +78 -1658
- package/src/engine/run-pipeline.ts +1 -1
- package/src/engine/schema-builder.ts +1 -0
- package/src/engine/screen-helpers.ts +54 -0
- package/src/engine/soft-delete-cleanup.ts +6 -2
- package/src/engine/steps/__tests__/duration-utils.test.ts +20 -0
- package/src/engine/steps/_duration-utils.ts +2 -0
- package/src/engine/steps/unsafe-projection-upsert.ts +1 -4
- package/src/engine/tier-resolver-extension.ts +3 -2
- package/src/engine/types/config.ts +2 -482
- package/src/engine/types/define-handler.ts +2 -0
- package/src/engine/types/entity-handlers.ts +2 -0
- package/src/engine/types/event-type-map.ts +1 -37
- package/src/engine/types/feature.ts +2 -972
- package/src/engine/types/fields.ts +2 -675
- package/src/engine/types/handlers.ts +2 -774
- package/src/engine/types/hooks.ts +2 -184
- package/src/engine/types/http-route.ts +1 -54
- package/src/engine/types/identifiers.ts +1 -47
- package/src/engine/types/index.ts +86 -40
- package/src/engine/types/nav.ts +2 -63
- package/src/engine/types/ownership.ts +2 -0
- package/src/engine/types/projection.ts +2 -138
- package/src/engine/types/relations.ts +1 -51
- package/src/engine/types/screen.ts +2 -574
- package/src/engine/types/step.ts +2 -334
- package/src/engine/types/target-ref.ts +1 -21
- package/src/engine/types/tree-node.ts +1 -132
- package/src/engine/types/workspace.ts +2 -49
- package/src/engine/validate-projection-allowlist.ts +6 -6
- package/src/entrypoint/__tests__/entrypoint-job-wiring.integration.test.ts +120 -1
- package/src/entrypoint/index.ts +49 -6
- package/src/errors/classes.ts +22 -1
- package/src/errors/field-issue.ts +0 -3
- package/src/errors/index.ts +1 -1
- package/src/errors/write-error-info.ts +10 -22
- package/src/es-ops/README.md +1 -1
- package/src/es-ops/__tests__/runner.integration.test.ts +74 -0
- package/src/es-ops/context.ts +4 -2
- package/src/es-ops/types.ts +8 -1
- package/src/event-store/__tests__/admin-api.integration.test.ts +27 -1
- package/src/event-store/__tests__/backfill-pii.integration.test.ts +279 -0
- package/src/event-store/__tests__/event-store.integration.test.ts +201 -0
- package/src/event-store/__tests__/row-to-stored-event.test.ts +2 -2
- package/src/event-store/__tests__/snapshot.integration.test.ts +86 -0
- package/src/event-store/__tests__/unscoped-stream-primitives.guard.test.ts +58 -0
- package/src/event-store/__tests__/upcaster.integration.test.ts +77 -45
- package/src/event-store/admin-api.ts +11 -4
- package/src/event-store/errors.ts +2 -35
- package/src/event-store/event-store.ts +64 -78
- package/src/event-store/events-schema.ts +11 -13
- package/src/event-store/index.ts +18 -3
- package/src/event-store/rebuild-dead-letter.ts +111 -0
- package/src/event-store/snapshot.ts +63 -40
- package/src/event-store/types.ts +2 -0
- package/src/files/__tests__/build-storage-key.test.ts +28 -0
- package/src/files/__tests__/file-ref-entity.test.ts +8 -0
- package/src/files/__tests__/files.integration.test.ts +24 -0
- package/src/files/__tests__/in-memory-provider.contract.test.ts +4 -0
- package/src/files/__tests__/local-provider.test.ts +31 -0
- package/src/files/__tests__/provider-resolver.test.ts +70 -0
- package/src/files/__tests__/write-stream.test.ts +13 -0
- package/src/files/file-handle.ts +2 -19
- package/src/files/file-ref-entity.ts +2 -2
- package/src/files/file-routes.ts +13 -0
- package/src/files/index.ts +1 -1
- package/src/files/local-provider.ts +27 -8
- package/src/files/provider-resolver.ts +31 -20
- package/src/files/types.ts +13 -55
- package/src/i18n/__tests__/required-surface-keys.test.ts +17 -0
- package/src/i18n/required-surface-keys.ts +120 -1
- package/src/jobs/__tests__/job-queue-depth.integration.test.ts +82 -0
- package/src/jobs/__tests__/jobs.integration.test.ts +329 -3
- package/src/jobs/job-runner.ts +82 -12
- package/src/logging/types.ts +1 -7
- package/src/migrations/pending-rebuilds.ts +1 -1
- package/src/observability/__tests__/observability.integration.test.ts +4 -1
- package/src/observability/__tests__/recording-tracer.test.ts +6 -4
- package/src/observability/index.ts +2 -0
- package/src/observability/noop-provider.ts +0 -9
- package/src/observability/recording-tracer.ts +0 -12
- package/src/observability/standard-metrics.ts +64 -2
- package/src/observability/types/index.ts +1 -29
- package/src/observability/types/metric.ts +1 -56
- package/src/observability/types/provider.ts +1 -32
- package/src/observability/types/span.ts +1 -64
- package/src/pipeline/__tests__/ctx-bridge.integration.test.ts +2 -2
- package/src/pipeline/__tests__/dispatcher.test.ts +366 -1
- package/src/pipeline/__tests__/event-consumer-state.integration.test.ts +31 -0
- package/src/pipeline/__tests__/event-dispatcher-delivery-max-attempts.test.ts +126 -0
- package/src/pipeline/__tests__/event-dispatcher-rearm.integration.test.ts +263 -0
- package/src/pipeline/__tests__/event-dispatcher.integration.test.ts +10 -0
- package/src/pipeline/__tests__/job-trigger-consumer.integration.test.ts +106 -0
- package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +308 -77
- package/src/pipeline/__tests__/load-aggregate-query.integration.test.ts +16 -8
- package/src/pipeline/__tests__/post-query-hook.integration.test.ts +3 -3
- package/src/pipeline/__tests__/projection-rebuild.integration.test.ts +80 -2
- package/src/pipeline/__tests__/rebuild-poison-quarantine.integration.test.ts +274 -0
- package/src/pipeline/__tests__/try-append-event.integration.test.ts +166 -0
- package/src/pipeline/dispatch-batch.ts +187 -0
- package/src/pipeline/dispatch-query.ts +165 -0
- package/src/pipeline/dispatch-shared.ts +826 -0
- package/src/pipeline/dispatch-stream.ts +90 -0
- package/src/pipeline/dispatch-write.ts +451 -0
- package/src/pipeline/dispatcher-utils.ts +1 -1
- package/src/pipeline/dispatcher.ts +44 -1372
- package/src/pipeline/entity-cache.ts +2 -33
- package/src/pipeline/event-consumer-state.ts +30 -2
- package/src/pipeline/event-dispatcher-admin.ts +293 -0
- package/src/pipeline/event-dispatcher-delivery.ts +305 -0
- package/src/pipeline/event-dispatcher.ts +85 -542
- package/src/pipeline/index.ts +2 -0
- package/src/pipeline/msp-rebuild.ts +42 -3
- package/src/pipeline/multi-stream-apply-context.ts +4 -42
- package/src/pipeline/projection-rebuild.ts +105 -3
- package/src/pipeline/system-hooks.ts +144 -1
- package/src/rate-limit/__tests__/resolver.integration.test.ts +18 -0
- package/src/rate-limit/resolver.ts +16 -32
- package/src/schema-cli.ts +76 -16
- package/src/search/__tests__/meilisearch-adapter.integration.test.ts +207 -185
- package/src/search/__tests__/meilisearch-ids.test.ts +30 -0
- package/src/search/__tests__/reindex-entity.integration.test.ts +144 -0
- package/src/search/index.ts +6 -0
- package/src/search/meilisearch-adapter.ts +13 -12
- package/src/search/reindex-entity.ts +177 -0
- package/src/search/types.ts +1 -39
- package/src/secrets/__tests__/contains-secret.test.ts +34 -0
- package/src/secrets/__tests__/envelope-cipher.test.ts +59 -0
- package/src/secrets/__tests__/envelope.test.ts +1 -1
- package/src/secrets/dek-cache.ts +26 -5
- package/src/secrets/envelope-cipher.ts +53 -0
- package/src/secrets/envelope.ts +5 -3
- package/src/secrets/index.ts +13 -1
- package/src/secrets/stored-envelope.ts +46 -0
- package/src/secrets/types.ts +2 -162
- package/src/stack/__tests__/event-collector.test.ts +42 -0
- package/src/stack/__tests__/setup-test-stack-jobs.integration.test.ts +125 -0
- package/src/stack/db.ts +2 -1
- package/src/stack/push-entity-projection-tables.ts +4 -3
- package/src/stack/redis.ts +8 -0
- package/src/stack/request-helper.ts +38 -2
- package/src/stack/table-helpers.ts +6 -4
- package/src/stack/test-stack.ts +249 -131
- package/src/testing/__tests__/late-bound.test.ts +32 -0
- package/src/testing/__tests__/wait-for.test.ts +59 -0
- package/src/testing/boot-validator-fixture.ts +121 -0
- package/src/testing/e2e-generator.ts +8 -0
- package/src/testing/file-provider-contract.ts +104 -0
- package/src/testing/handler-context.ts +3 -1
- package/src/testing/index.ts +5 -0
- package/src/testing/late-bound.ts +5 -3
- package/src/testing/mutable-master-key-provider.ts +29 -3
- package/src/testing/wait-for.ts +3 -0
- package/src/testing/without-ambient-temporal.ts +14 -0
- package/src/time/__tests__/tz-dateline.test.ts +8 -10
- package/src/time/geo-tz.ts +1 -32
- package/src/time/index.ts +1 -0
- package/src/time/legacy-date.ts +18 -0
- package/src/time/polyfill.ts +21 -38
- package/src/time/tz-context.ts +44 -85
- package/src/ui-types/app-schema.ts +12 -0
- package/src/ui-types/index.ts +20 -7
- package/src/utils/__tests__/safe-json-temporal.test.ts +18 -0
- package/src/utils/safe-json.ts +13 -1
- package/src/__tests__/raw-table.integration.test.ts +0 -116
- package/src/bun-db/__tests__/bun-test-stack.ts +0 -6
- package/src/db/__tests__/encryption.test.ts +0 -39
- package/src/db/encryption.ts +0 -39
- package/src/db/row-helpers.ts +0 -4
- package/src/engine/__tests__/raw-table.test.ts +0 -150
- package/src/engine/__tests__/unmanaged-table.test.ts +0 -127
- package/src/engine/feature-ast/__tests__/visual-tree-parse.test.ts +0 -184
- package/src/engine/feature-ast/extractors/round4.ts +0 -1366
|
@@ -21,7 +21,13 @@
|
|
|
21
21
|
// Per-pattern extractors fill in iteratively (C1.5) — each round adds
|
|
22
22
|
// one extractor + a focused test.
|
|
23
23
|
|
|
24
|
-
import type {
|
|
24
|
+
import type {
|
|
25
|
+
ArrowFunction,
|
|
26
|
+
CallExpression,
|
|
27
|
+
Node,
|
|
28
|
+
ParameterDeclaration,
|
|
29
|
+
SourceFile,
|
|
30
|
+
} from "ts-morph";
|
|
25
31
|
import { Project, SyntaxKind } from "ts-morph";
|
|
26
32
|
|
|
27
33
|
import {
|
|
@@ -32,9 +38,7 @@ import {
|
|
|
32
38
|
extractDefineEvent,
|
|
33
39
|
extractDescribe,
|
|
34
40
|
extractEntity,
|
|
35
|
-
extractEntityHook,
|
|
36
41
|
extractEnvSchema,
|
|
37
|
-
extractEventMigration,
|
|
38
42
|
extractExposesApi,
|
|
39
43
|
extractExtendsRegistrar,
|
|
40
44
|
extractHook,
|
|
@@ -53,17 +57,18 @@ import {
|
|
|
53
57
|
extractRequires,
|
|
54
58
|
extractScreen,
|
|
55
59
|
extractSecret,
|
|
60
|
+
extractStoreTable,
|
|
61
|
+
extractStreamHandler,
|
|
56
62
|
extractSystemScope,
|
|
57
63
|
extractToggleable,
|
|
58
64
|
extractTranslations,
|
|
59
|
-
extractTree,
|
|
60
65
|
extractTreeActions,
|
|
61
66
|
extractUiHints,
|
|
62
|
-
extractUnmanagedTable,
|
|
63
67
|
extractUseExtension,
|
|
64
68
|
extractUsesApi,
|
|
65
69
|
extractWorkspace,
|
|
66
70
|
extractWriteHandler,
|
|
71
|
+
findFunctionLiteral,
|
|
67
72
|
} from "./extractors";
|
|
68
73
|
import type { FeaturePattern, UnknownPattern } from "./patterns";
|
|
69
74
|
import { type SourceLocation, sourceLocationFromNode } from "./source-location";
|
|
@@ -146,7 +151,7 @@ export function parseSourceFile(sourceFile: SourceFile): ParseResult {
|
|
|
146
151
|
const patterns: FeaturePattern[] = [];
|
|
147
152
|
const errors: ParseError[] = [];
|
|
148
153
|
|
|
149
|
-
walkSetupCallback(setupCallback, registrarParamName, sourceFile, patterns, errors);
|
|
154
|
+
walkSetupCallback(setupCallback.getBody(), registrarParamName, sourceFile, patterns, errors);
|
|
150
155
|
|
|
151
156
|
return { featureName, patterns, errors };
|
|
152
157
|
}
|
|
@@ -229,25 +234,131 @@ function extractRegistrarParamName(setup: ArrowFunction): string | undefined {
|
|
|
229
234
|
* structurally impossible.
|
|
230
235
|
*/
|
|
231
236
|
function walkSetupCallback(
|
|
232
|
-
|
|
237
|
+
body: Node,
|
|
233
238
|
registrarParamName: string,
|
|
234
239
|
sourceFile: SourceFile,
|
|
235
240
|
patterns: FeaturePattern[],
|
|
236
241
|
errors: ParseError[],
|
|
242
|
+
visitedWrapperDecls: Set<Node> = new Set(),
|
|
237
243
|
): void {
|
|
238
|
-
const body = setup.getBody();
|
|
239
244
|
for (const call of body.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
240
245
|
const methodName = extractRegistrarMethodName(call, registrarParamName);
|
|
241
|
-
if (
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
246
|
+
if (methodName) {
|
|
247
|
+
const result = dispatchExtractor(methodName, call, sourceFile);
|
|
248
|
+
if (result.kind === "pattern") {
|
|
249
|
+
patterns.push(result.pattern);
|
|
250
|
+
} else {
|
|
251
|
+
errors.push(result.error);
|
|
252
|
+
}
|
|
253
|
+
continue;
|
|
247
254
|
}
|
|
255
|
+
|
|
256
|
+
// Not a direct `<registrarParam>.<method>(...)` call. Check whether it's
|
|
257
|
+
// a registrar-wrapper call — a function that receives the registrar as
|
|
258
|
+
// a bare argument, e.g. `registerShowPonyScreens(r)`. Such wrappers are
|
|
259
|
+
// invisible to a receiver-shape match, so we resolve the callee (same
|
|
260
|
+
// file, or the declaring file of a named import — #1008) and recurse
|
|
261
|
+
// into its body with its own parameter name for the registrar slot.
|
|
262
|
+
const wrapper = resolveRegistrarWrapperCall(call, registrarParamName);
|
|
263
|
+
if (!wrapper) continue; // Free function call unrelated to the registrar — ignore.
|
|
264
|
+
if (visitedWrapperDecls.has(wrapper.declNode)) continue; // Cycle guard.
|
|
265
|
+
visitedWrapperDecls.add(wrapper.declNode);
|
|
266
|
+
// wrapper.sourceFile, not the outer `sourceFile` param: a cross-file
|
|
267
|
+
// wrapper's body lives in a different file, and sourceLocationFromNode
|
|
268
|
+
// uses whichever SourceFile it's given for both the `file` path and
|
|
269
|
+
// the line/column table — passing the wrong one silently corrupts
|
|
270
|
+
// both for every pattern found inside the wrapper.
|
|
271
|
+
walkSetupCallback(
|
|
272
|
+
wrapper.body,
|
|
273
|
+
wrapper.paramName,
|
|
274
|
+
wrapper.sourceFile,
|
|
275
|
+
patterns,
|
|
276
|
+
errors,
|
|
277
|
+
visitedWrapperDecls,
|
|
278
|
+
);
|
|
248
279
|
}
|
|
249
280
|
}
|
|
250
281
|
|
|
282
|
+
/**
|
|
283
|
+
* Resolves a bare call like `registerShowPonyScreens(r)` to the callee's
|
|
284
|
+
* body + its own parameter name for the registrar slot. The callee may be
|
|
285
|
+
* declared in the same file (function declaration, or a const initialized
|
|
286
|
+
* with an arrow/function expression), or imported by name from another
|
|
287
|
+
* file — resolved via the module specifier's SourceFile (#1008; only
|
|
288
|
+
* works against a real-filesystem Project, e.g. parseFeatureFile's. The
|
|
289
|
+
* in-memory Designer Project has no files to resolve against and
|
|
290
|
+
* getModuleSpecifierSourceFile() returns undefined there, same as any
|
|
291
|
+
* other unresolvable reference).
|
|
292
|
+
*/
|
|
293
|
+
function resolveRegistrarWrapperCall(
|
|
294
|
+
call: CallExpression,
|
|
295
|
+
registrarParamName: string,
|
|
296
|
+
):
|
|
297
|
+
| {
|
|
298
|
+
readonly body: Node;
|
|
299
|
+
readonly paramName: string;
|
|
300
|
+
readonly declNode: Node;
|
|
301
|
+
readonly sourceFile: SourceFile;
|
|
302
|
+
}
|
|
303
|
+
| undefined {
|
|
304
|
+
const callee = call.getExpression().asKind(SyntaxKind.Identifier);
|
|
305
|
+
if (!callee) return undefined;
|
|
306
|
+
|
|
307
|
+
const args = call.getArguments();
|
|
308
|
+
const argIndex = args.findIndex((arg) => arg.getText() === registrarParamName);
|
|
309
|
+
if (argIndex === -1) return undefined; // Registrar not passed to this call.
|
|
310
|
+
|
|
311
|
+
const callSourceFile = call.getSourceFile();
|
|
312
|
+
const name = callee.getText();
|
|
313
|
+
|
|
314
|
+
const local = resolveWrapperDeclarationInFile(callSourceFile, name, argIndex);
|
|
315
|
+
if (local) return { ...local, sourceFile: callSourceFile };
|
|
316
|
+
|
|
317
|
+
const importDecl = callSourceFile
|
|
318
|
+
.getImportDeclarations()
|
|
319
|
+
.find((d) =>
|
|
320
|
+
d.getNamedImports().some((ni) => (ni.getAliasNode()?.getText() ?? ni.getName()) === name),
|
|
321
|
+
);
|
|
322
|
+
if (!importDecl) return undefined;
|
|
323
|
+
const exportedName =
|
|
324
|
+
importDecl
|
|
325
|
+
.getNamedImports()
|
|
326
|
+
.find((ni) => (ni.getAliasNode()?.getText() ?? ni.getName()) === name)
|
|
327
|
+
?.getName() ?? name;
|
|
328
|
+
const targetFile = importDecl.getModuleSpecifierSourceFile();
|
|
329
|
+
if (!targetFile) return undefined; // Unresolvable: in-memory project, external package, or missing file.
|
|
330
|
+
|
|
331
|
+
const imported = resolveWrapperDeclarationInFile(targetFile, exportedName, argIndex);
|
|
332
|
+
return imported ? { ...imported, sourceFile: targetFile } : undefined;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function resolveWrapperDeclarationInFile(
|
|
336
|
+
sourceFile: SourceFile,
|
|
337
|
+
name: string,
|
|
338
|
+
argIndex: number,
|
|
339
|
+
): { readonly body: Node; readonly paramName: string; readonly declNode: Node } | undefined {
|
|
340
|
+
const fnDecl = sourceFile.getFunction(name);
|
|
341
|
+
if (fnDecl) {
|
|
342
|
+
const param = fnDecl.getParameters()[argIndex];
|
|
343
|
+
const body = fnDecl.getBody();
|
|
344
|
+
if (!param || !body) return undefined;
|
|
345
|
+
return { body, paramName: param.getName(), declNode: fnDecl };
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const varDecl = sourceFile.getVariableDeclaration(name);
|
|
349
|
+
const init = varDecl?.getInitializer();
|
|
350
|
+
const literal = init ? findFunctionLiteral(init) : undefined;
|
|
351
|
+
const fnLiteral =
|
|
352
|
+
literal?.asKind(SyntaxKind.ArrowFunction) ?? literal?.asKind(SyntaxKind.FunctionExpression);
|
|
353
|
+
if (fnLiteral) {
|
|
354
|
+
const param = fnLiteral.getParameters()[argIndex];
|
|
355
|
+
if (!param) return undefined;
|
|
356
|
+
return { body: fnLiteral.getBody(), paramName: param.getName(), declNode: fnLiteral };
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
361
|
+
|
|
251
362
|
/**
|
|
252
363
|
* Returns the method name when the call has the form
|
|
253
364
|
* `<registrarParamName>.<method>(...)`, otherwise undefined.
|
|
@@ -331,22 +442,20 @@ function dispatchExtractor(
|
|
|
331
442
|
// Round 4 — mixed (header + body) patterns
|
|
332
443
|
case "hook":
|
|
333
444
|
return extractHook(call, sourceFile);
|
|
334
|
-
case "entityHook":
|
|
335
|
-
return extractEntityHook(call, sourceFile);
|
|
336
445
|
case "authClaims":
|
|
337
446
|
return extractAuthClaims(call, sourceFile);
|
|
338
447
|
case "writeHandler":
|
|
339
448
|
return extractWriteHandler(call, sourceFile);
|
|
340
449
|
case "queryHandler":
|
|
341
450
|
return extractQueryHandler(call, sourceFile);
|
|
451
|
+
case "streamHandler":
|
|
452
|
+
return extractStreamHandler(call, sourceFile);
|
|
342
453
|
case "job":
|
|
343
454
|
return extractJob(call, sourceFile);
|
|
344
455
|
case "httpRoute":
|
|
345
456
|
return extractHttpRoute(call, sourceFile);
|
|
346
457
|
case "defineEvent":
|
|
347
458
|
return extractDefineEvent(call, sourceFile);
|
|
348
|
-
case "eventMigration":
|
|
349
|
-
return extractEventMigration(call, sourceFile);
|
|
350
459
|
case "notification":
|
|
351
460
|
return extractNotification(call, sourceFile);
|
|
352
461
|
case "projection":
|
|
@@ -362,13 +471,11 @@ function dispatchExtractor(
|
|
|
362
471
|
return extractUsesApi(call, sourceFile);
|
|
363
472
|
case "exposesApi":
|
|
364
473
|
return extractExposesApi(call, sourceFile);
|
|
365
|
-
case "
|
|
366
|
-
return
|
|
367
|
-
// Round 6 —
|
|
474
|
+
case "storeTable":
|
|
475
|
+
return extractStoreTable(call, sourceFile);
|
|
476
|
+
// Round 6 — Tree-Actions pattern
|
|
368
477
|
case "treeActions":
|
|
369
478
|
return extractTreeActions(call, sourceFile);
|
|
370
|
-
case "tree":
|
|
371
|
-
return extractTree(call, sourceFile);
|
|
372
479
|
// Round 7 — env-schema contract (opaque, Zod-expression argument)
|
|
373
480
|
case "envSchema":
|
|
374
481
|
return extractEnvSchema(call, sourceFile);
|
|
@@ -53,8 +53,12 @@ export type PatternId =
|
|
|
53
53
|
| { readonly kind: "screen"; readonly id: string }
|
|
54
54
|
| { readonly kind: "writeHandler"; readonly handlerName: string }
|
|
55
55
|
| { readonly kind: "queryHandler"; readonly handlerName: string }
|
|
56
|
-
| { readonly kind: "
|
|
57
|
-
| {
|
|
56
|
+
| { readonly kind: "streamHandler"; readonly handlerName: string }
|
|
57
|
+
| {
|
|
58
|
+
readonly kind: "hook";
|
|
59
|
+
readonly hookType: string;
|
|
60
|
+
readonly target: string | { readonly allOf: string };
|
|
61
|
+
}
|
|
58
62
|
| { readonly kind: "metric"; readonly shortName: string }
|
|
59
63
|
| { readonly kind: "secret"; readonly shortName: string }
|
|
60
64
|
| { readonly kind: "claimKey"; readonly shortName: string }
|
|
@@ -66,12 +70,6 @@ export type PatternId =
|
|
|
66
70
|
| { readonly kind: "projection"; readonly name: string }
|
|
67
71
|
| { readonly kind: "multiStreamProjection"; readonly name: string }
|
|
68
72
|
| { readonly kind: "defineEvent"; readonly eventName: string }
|
|
69
|
-
| {
|
|
70
|
-
readonly kind: "eventMigration";
|
|
71
|
-
readonly eventName: string;
|
|
72
|
-
readonly fromVersion: number;
|
|
73
|
-
readonly toVersion: number;
|
|
74
|
-
}
|
|
75
73
|
| { readonly kind: "extendsRegistrar"; readonly extensionName: string }
|
|
76
74
|
// Singleton patterns — only one per feature, kind alone identifies them.
|
|
77
75
|
| { readonly kind: "requires" }
|
|
@@ -84,8 +82,7 @@ export type PatternId =
|
|
|
84
82
|
| { readonly kind: "config" }
|
|
85
83
|
| { readonly kind: "translations" }
|
|
86
84
|
| { readonly kind: "authClaims" }
|
|
87
|
-
| { readonly kind: "treeActions" }
|
|
88
|
-
| { readonly kind: "tree" };
|
|
85
|
+
| { readonly kind: "treeActions" };
|
|
89
86
|
|
|
90
87
|
// =============================================================================
|
|
91
88
|
// Change ops — generic apply API
|
|
@@ -277,10 +274,9 @@ export const SINGLETON_KINDS: ReadonlySet<PatternId["kind"]> = new Set([
|
|
|
277
274
|
"config",
|
|
278
275
|
"translations",
|
|
279
276
|
"authClaims",
|
|
280
|
-
//
|
|
277
|
+
// Tree-Actions slot — at-most-one per feature, mirrors the registrar's
|
|
281
278
|
// only-once-guard in define-feature.ts.
|
|
282
279
|
"treeActions",
|
|
283
|
-
"tree",
|
|
284
280
|
]);
|
|
285
281
|
|
|
286
282
|
/**
|
|
@@ -336,7 +332,6 @@ function callMatchesId(call: CallExpression, id: PatternId): boolean {
|
|
|
336
332
|
case "translations":
|
|
337
333
|
case "authClaims":
|
|
338
334
|
case "treeActions":
|
|
339
|
-
case "tree":
|
|
340
335
|
return true;
|
|
341
336
|
|
|
342
337
|
case "entity":
|
|
@@ -359,12 +354,25 @@ function callMatchesId(call: CallExpression, id: PatternId): boolean {
|
|
|
359
354
|
return matchObjectProperty(call, "id", id.id);
|
|
360
355
|
case "writeHandler":
|
|
361
356
|
case "queryHandler":
|
|
357
|
+
case "streamHandler":
|
|
362
358
|
return (
|
|
363
359
|
matchFirstArgString(call, id.handlerName) ||
|
|
364
360
|
matchObjectProperty(call, "name", id.handlerName)
|
|
365
361
|
);
|
|
366
362
|
case "hook":
|
|
367
363
|
// Positional: r.hook(type, target, fn) | Object: { type, target }
|
|
364
|
+
if (typeof id.target === "object") {
|
|
365
|
+
// Entity-wide { allOf } target — only ever appears as the object
|
|
366
|
+
// literal { allOf: entity } (positional or nested in the object
|
|
367
|
+
// form), never as a bare string, so check both call shapes.
|
|
368
|
+
if (matchFirstArgString(call, id.hookType)) {
|
|
369
|
+
return matchAllOfArg(call.getArguments()[1], id.target.allOf);
|
|
370
|
+
}
|
|
371
|
+
return (
|
|
372
|
+
matchObjectProperty(call, "type", id.hookType) &&
|
|
373
|
+
matchObjectAllOfProperty(call, "target", id.target.allOf)
|
|
374
|
+
);
|
|
375
|
+
}
|
|
368
376
|
if (matchFirstArgString(call, id.hookType)) {
|
|
369
377
|
const target = call.getArguments()[1]?.asKind(SyntaxKind.StringLiteral)?.getLiteralValue();
|
|
370
378
|
return target === id.target;
|
|
@@ -373,15 +381,6 @@ function callMatchesId(call: CallExpression, id: PatternId): boolean {
|
|
|
373
381
|
matchObjectProperty(call, "type", id.hookType) &&
|
|
374
382
|
matchObjectProperty(call, "target", id.target)
|
|
375
383
|
);
|
|
376
|
-
case "entityHook":
|
|
377
|
-
if (matchFirstArgString(call, id.hookType)) {
|
|
378
|
-
const ent = call.getArguments()[1]?.asKind(SyntaxKind.StringLiteral)?.getLiteralValue();
|
|
379
|
-
return ent === id.entityName;
|
|
380
|
-
}
|
|
381
|
-
return (
|
|
382
|
-
matchObjectProperty(call, "type", id.hookType) &&
|
|
383
|
-
matchObjectProperty(call, "entity", id.entityName)
|
|
384
|
-
);
|
|
385
384
|
case "metric":
|
|
386
385
|
case "secret":
|
|
387
386
|
case "claimKey":
|
|
@@ -422,20 +421,6 @@ function callMatchesId(call: CallExpression, id: PatternId): boolean {
|
|
|
422
421
|
return (
|
|
423
422
|
matchFirstArgString(call, id.eventName) || matchObjectProperty(call, "name", id.eventName)
|
|
424
423
|
);
|
|
425
|
-
case "eventMigration": {
|
|
426
|
-
// Positional: r.eventMigration(name, from, to, fn)
|
|
427
|
-
if (matchFirstArgString(call, id.eventName)) {
|
|
428
|
-
const from = numericArg(call, 1);
|
|
429
|
-
const to = numericArg(call, 2);
|
|
430
|
-
return from === id.fromVersion && to === id.toVersion;
|
|
431
|
-
}
|
|
432
|
-
// Object: { event, fromVersion, toVersion }
|
|
433
|
-
return (
|
|
434
|
-
matchObjectProperty(call, "event", id.eventName) &&
|
|
435
|
-
matchObjectNumericProperty(call, "fromVersion", id.fromVersion) &&
|
|
436
|
-
matchObjectNumericProperty(call, "toVersion", id.toVersion)
|
|
437
|
-
);
|
|
438
|
-
}
|
|
439
424
|
case "extendsRegistrar":
|
|
440
425
|
return matchFirstArgString(call, id.extensionName);
|
|
441
426
|
default: {
|
|
@@ -462,25 +447,29 @@ function matchObjectProperty(call: CallExpression, propName: string, expected: s
|
|
|
462
447
|
return init?.getLiteralValue() === expected;
|
|
463
448
|
}
|
|
464
449
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
): boolean {
|
|
470
|
-
const obj = call.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression);
|
|
471
|
-
if (!obj) return false;
|
|
450
|
+
// Matches an r.hook `{ allOf: entity }` target — as the arg node directly
|
|
451
|
+
// (positional call form) or as a nested object property (object call form).
|
|
452
|
+
function matchAllOfArg(node: Node | undefined, expectedEntity: string): boolean {
|
|
453
|
+
const obj = node?.asKind(SyntaxKind.ObjectLiteralExpression);
|
|
472
454
|
const init = obj
|
|
473
|
-
|
|
455
|
+
?.getProperty("allOf")
|
|
474
456
|
?.asKind(SyntaxKind.PropertyAssignment)
|
|
475
457
|
?.getInitializer()
|
|
476
|
-
?.asKind(SyntaxKind.
|
|
477
|
-
return init
|
|
458
|
+
?.asKind(SyntaxKind.StringLiteral);
|
|
459
|
+
return init?.getLiteralValue() === expectedEntity;
|
|
478
460
|
}
|
|
479
461
|
|
|
480
|
-
function
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
462
|
+
function matchObjectAllOfProperty(
|
|
463
|
+
call: CallExpression,
|
|
464
|
+
propName: string,
|
|
465
|
+
expectedEntity: string,
|
|
466
|
+
): boolean {
|
|
467
|
+
const obj = call.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression);
|
|
468
|
+
const propInit = obj
|
|
469
|
+
?.getProperty(propName)
|
|
470
|
+
?.asKind(SyntaxKind.PropertyAssignment)
|
|
471
|
+
?.getInitializer();
|
|
472
|
+
return matchAllOfArg(propInit, expectedEntity);
|
|
484
473
|
}
|
|
485
474
|
|
|
486
475
|
// =============================================================================
|
|
@@ -104,17 +104,21 @@ export type AddQueryHandlerArgs = {
|
|
|
104
104
|
readonly rateLimit?: RateLimitOption;
|
|
105
105
|
};
|
|
106
106
|
|
|
107
|
-
export type
|
|
108
|
-
readonly
|
|
109
|
-
readonly
|
|
110
|
-
/** Source text of the closure, e.g. `"async (event, ctx) => { ... }"`. */
|
|
107
|
+
export type AddStreamHandlerArgs = {
|
|
108
|
+
readonly name: string;
|
|
109
|
+
readonly schemaSource: string;
|
|
111
110
|
readonly handlerSource: string;
|
|
112
|
-
readonly
|
|
111
|
+
readonly access?: AccessRule;
|
|
112
|
+
readonly rateLimit?: RateLimitOption;
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
-
export type
|
|
116
|
-
readonly type:
|
|
117
|
-
|
|
115
|
+
export type AddHookArgs = {
|
|
116
|
+
readonly type: LifecycleHookType | "validation";
|
|
117
|
+
// `{ allOf: entity }` — entity-wide target, fires for every write/query
|
|
118
|
+
// handler of that entity; replaces the old addEntityHook(). Only valid
|
|
119
|
+
// for postSave/preDelete/postDelete/postQuery, same as r.hook() itself.
|
|
120
|
+
readonly target: string | readonly string[] | { readonly allOf: string };
|
|
121
|
+
/** Source text of the closure, e.g. `"async (event, ctx) => { ... }"`. */
|
|
118
122
|
readonly handlerSource: string;
|
|
119
123
|
readonly phase?: HookPhase;
|
|
120
124
|
};
|
|
@@ -144,13 +148,10 @@ export type AddDefineEventArgs = {
|
|
|
144
148
|
readonly name: string;
|
|
145
149
|
readonly schemaSource: string;
|
|
146
150
|
readonly version?: number;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
readonly
|
|
151
|
-
readonly fromVersion: number;
|
|
152
|
-
readonly toVersion: number;
|
|
153
|
-
readonly transformSource: string;
|
|
151
|
+
// Keyed by fromVersion (as a string) → the transform source text for the
|
|
152
|
+
// fromVersion -> fromVersion+1 step. Folded in from the former
|
|
153
|
+
// addEventMigration (#1082 step 8).
|
|
154
|
+
readonly migrations?: Readonly<Record<string, string>>;
|
|
154
155
|
};
|
|
155
156
|
|
|
156
157
|
export type AddProjectionArgs = {
|
|
@@ -240,8 +241,8 @@ export type FeaturePatcher = {
|
|
|
240
241
|
readonly addScreen: (args: AddScreenArgs) => void;
|
|
241
242
|
readonly addWriteHandler: (args: AddWriteHandlerArgs) => void;
|
|
242
243
|
readonly addQueryHandler: (args: AddQueryHandlerArgs) => void;
|
|
244
|
+
readonly addStreamHandler: (args: AddStreamHandlerArgs) => void;
|
|
243
245
|
readonly addHook: (args: AddHookArgs) => void;
|
|
244
|
-
readonly addEntityHook: (args: AddEntityHookArgs) => void;
|
|
245
246
|
readonly addJob: (args: AddJobArgs) => void;
|
|
246
247
|
readonly addNotification: (args: AddNotificationArgs) => void;
|
|
247
248
|
readonly addAuthClaims: (args: AddAuthClaimsArgs) => void;
|
|
@@ -249,7 +250,6 @@ export type FeaturePatcher = {
|
|
|
249
250
|
readonly addProjection: (args: AddProjectionArgs) => void;
|
|
250
251
|
readonly addMultiStreamProjection: (args: AddMultiStreamProjectionArgs) => void;
|
|
251
252
|
readonly addDefineEvent: (args: AddDefineEventArgs) => void;
|
|
252
|
-
readonly addEventMigration: (args: AddEventMigrationArgs) => void;
|
|
253
253
|
// --- Symmetric ops (id-driven) ---
|
|
254
254
|
readonly replace: (id: PatternId, pattern: FeaturePattern) => void;
|
|
255
255
|
readonly remove: (id: PatternId) => void;
|
|
@@ -401,23 +401,24 @@ export function createFeaturePatcher(sourceFile: SourceFile): FeaturePatcher {
|
|
|
401
401
|
});
|
|
402
402
|
},
|
|
403
403
|
|
|
404
|
-
|
|
404
|
+
addStreamHandler({ name, schemaSource, handlerSource, access, rateLimit }) {
|
|
405
405
|
add({
|
|
406
|
-
kind: "
|
|
406
|
+
kind: "streamHandler",
|
|
407
407
|
source: SYNTHETIC_LOC,
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
...(
|
|
408
|
+
handlerName: name,
|
|
409
|
+
schemaSource: rawLoc(schemaSource),
|
|
410
|
+
handlerBody: rawLoc(handlerSource),
|
|
411
|
+
...(access !== undefined && { access }),
|
|
412
|
+
...(rateLimit !== undefined && { rateLimit }),
|
|
412
413
|
});
|
|
413
414
|
},
|
|
414
415
|
|
|
415
|
-
|
|
416
|
+
addHook({ type, target, handlerSource, phase }) {
|
|
416
417
|
add({
|
|
417
|
-
kind: "
|
|
418
|
+
kind: "hook",
|
|
418
419
|
source: SYNTHETIC_LOC,
|
|
419
420
|
hookType: type,
|
|
420
|
-
|
|
421
|
+
target,
|
|
421
422
|
fnBody: rawLoc(handlerSource),
|
|
422
423
|
...(phase !== undefined && { phase }),
|
|
423
424
|
});
|
|
@@ -495,24 +496,22 @@ export function createFeaturePatcher(sourceFile: SourceFile): FeaturePatcher {
|
|
|
495
496
|
});
|
|
496
497
|
},
|
|
497
498
|
|
|
498
|
-
addDefineEvent({ name, schemaSource, version }) {
|
|
499
|
+
addDefineEvent({ name, schemaSource, version, migrations }) {
|
|
500
|
+
const migrationLocs = migrations
|
|
501
|
+
? Object.fromEntries(
|
|
502
|
+
Object.entries(migrations).map(([fromVersion, source]) => [
|
|
503
|
+
fromVersion,
|
|
504
|
+
rawLoc(source),
|
|
505
|
+
]),
|
|
506
|
+
)
|
|
507
|
+
: undefined;
|
|
499
508
|
add({
|
|
500
509
|
kind: "defineEvent",
|
|
501
510
|
source: SYNTHETIC_LOC,
|
|
502
511
|
eventName: name,
|
|
503
512
|
schemaSource: rawLoc(schemaSource),
|
|
504
513
|
...(version !== undefined && { version }),
|
|
505
|
-
|
|
506
|
-
},
|
|
507
|
-
|
|
508
|
-
addEventMigration({ event, fromVersion, toVersion, transformSource }) {
|
|
509
|
-
add({
|
|
510
|
-
kind: "eventMigration",
|
|
511
|
-
source: SYNTHETIC_LOC,
|
|
512
|
-
eventName: event,
|
|
513
|
-
fromVersion,
|
|
514
|
-
toVersion,
|
|
515
|
-
transformBody: rawLoc(transformSource),
|
|
514
|
+
...(migrationLocs !== undefined && { migrations: migrationLocs }),
|
|
516
515
|
});
|
|
517
516
|
},
|
|
518
517
|
|