@cosmicdrift/kumiko-framework 0.327.0 → 0.328.1
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/dist/api/anonymous-cookie.d.ts +8 -0
- package/dist/api/anonymous-cookie.js +40 -0
- package/dist/api/api-constants.d.ts +47 -0
- package/dist/api/api-constants.js +136 -0
- package/dist/api/auth-middleware.d.ts +42 -0
- package/dist/api/auth-middleware.js +450 -0
- package/dist/api/auth-routes.d.ts +83 -0
- package/dist/api/auth-routes.js +1003 -0
- package/dist/api/client-ip.d.ts +15 -0
- package/dist/api/client-ip.js +101 -0
- package/dist/api/csrf-middleware.d.ts +9 -0
- package/dist/api/csrf-middleware.js +67 -0
- package/dist/api/extra-route.d.ts +99 -0
- package/dist/api/extra-route.js +48 -0
- package/dist/api/http-cache.d.ts +31 -0
- package/dist/api/http-cache.js +102 -0
- package/dist/api/index.d.ts +32 -0
- package/dist/api/index.js +20 -0
- package/dist/api/jwt.d.ts +22 -0
- package/dist/api/jwt.js +199 -0
- package/dist/api/observability-middleware.d.ts +8 -0
- package/dist/api/observability-middleware.js +68 -0
- package/dist/api/origin-middleware.d.ts +12 -0
- package/dist/api/origin-middleware.js +120 -0
- package/dist/api/pat-route-guard.d.ts +2 -0
- package/dist/api/pat-route-guard.js +43 -0
- package/dist/api/pat-scope.d.ts +2 -0
- package/dist/api/pat-scope.js +13 -0
- package/dist/api/pii-leak-guard.d.ts +2 -0
- package/dist/api/pii-leak-guard.js +40 -0
- package/dist/api/post-auth-landing.d.ts +14 -0
- package/dist/api/post-auth-landing.js +92 -0
- package/dist/api/readiness.d.ts +23 -0
- package/dist/api/readiness.js +98 -0
- package/dist/api/redis-sse-broker.d.ts +13 -0
- package/dist/api/redis-sse-broker.js +138 -0
- package/dist/api/request-context.d.ts +34 -0
- package/dist/api/request-context.js +60 -0
- package/dist/api/request-id-middleware.d.ts +37 -0
- package/dist/api/request-id-middleware.js +112 -0
- package/dist/api/route-registrars.d.ts +24 -0
- package/dist/api/route-registrars.js +133 -0
- package/dist/api/routes.d.ts +20 -0
- package/dist/api/routes.js +373 -0
- package/dist/api/server.d.ts +81 -0
- package/dist/api/server.js +1068 -0
- package/dist/api/sse-broker.d.ts +36 -0
- package/dist/api/sse-broker.js +112 -0
- package/dist/api/sse-route.d.ts +24 -0
- package/dist/api/sse-route.js +61 -0
- package/dist/api/tokens.d.ts +1 -0
- package/dist/api/tokens.js +15 -0
- package/dist/api/websocket-route.d.ts +59 -0
- package/dist/api/websocket-route.js +239 -0
- package/dist/arg-parser.d.ts +8 -0
- package/dist/arg-parser.js +59 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.js +5 -0
- package/dist/auth/roles.d.ts +16 -0
- package/dist/auth/roles.js +35 -0
- package/dist/bun-db/connection.d.ts +16 -0
- package/dist/bun-db/connection.js +54 -0
- package/dist/bun-db/index.d.ts +4 -0
- package/dist/bun-db/index.js +4 -0
- package/dist/bun-db/query.d.ts +64 -0
- package/dist/bun-db/query.js +1145 -0
- package/dist/compliance/duration-spec.d.ts +7 -0
- package/dist/compliance/duration-spec.js +37 -0
- package/dist/compliance/index.d.ts +6 -0
- package/dist/compliance/index.js +7 -0
- package/dist/compliance/override-schema.d.ts +78 -0
- package/dist/compliance/override-schema.js +124 -0
- package/dist/compliance/profiles.d.ts +125 -0
- package/dist/compliance/profiles.js +284 -0
- package/dist/compliance/sub-processors.d.ts +69 -0
- package/dist/compliance/sub-processors.js +109 -0
- package/dist/consumer-cli.d.ts +5 -0
- package/dist/consumer-cli.js +116 -0
- package/dist/crypto/blind-index.d.ts +10 -0
- package/dist/crypto/blind-index.js +97 -0
- package/dist/crypto/ciphertext-pattern.d.ts +3 -0
- package/dist/crypto/ciphertext-pattern.js +16 -0
- package/dist/crypto/event-pii.d.ts +8 -0
- package/dist/crypto/event-pii.js +79 -0
- package/dist/crypto/in-memory-kms-adapter.d.ts +11 -0
- package/dist/crypto/in-memory-kms-adapter.js +33 -0
- package/dist/crypto/index.d.ts +11 -0
- package/dist/crypto/index.js +11 -0
- package/dist/crypto/is-self-pii-field.d.ts +5 -0
- package/dist/crypto/is-self-pii-field.js +4 -0
- package/dist/crypto/kek-source.d.ts +23 -0
- package/dist/crypto/kek-source.js +122 -0
- package/dist/crypto/kms-adapter.d.ts +26 -0
- package/dist/crypto/kms-adapter.js +46 -0
- package/dist/crypto/kms-wiring.d.ts +67 -0
- package/dist/crypto/kms-wiring.js +125 -0
- package/dist/crypto/pg-kms-adapter.d.ts +55 -0
- package/dist/crypto/pg-kms-adapter.js +232 -0
- package/dist/crypto/pii-field-encryption.d.ts +20 -0
- package/dist/crypto/pii-field-encryption.js +201 -0
- package/dist/crypto/request-kms-cache.d.ts +8 -0
- package/dist/crypto/request-kms-cache.js +21 -0
- package/dist/crypto/subject-resolver.d.ts +30 -0
- package/dist/crypto/subject-resolver.js +153 -0
- package/dist/crypto/system-event-pii.d.ts +4 -0
- package/dist/crypto/system-event-pii.js +37 -0
- package/dist/db/api.d.ts +18 -0
- package/dist/db/api.js +23 -0
- package/dist/db/apply-entity-event.d.ts +21 -0
- package/dist/db/apply-entity-event.js +175 -0
- package/dist/db/assert-exists-in.d.ts +23 -0
- package/dist/db/assert-exists-in.js +34 -0
- package/dist/db/blind-index-cleanup.d.ts +5 -0
- package/dist/db/blind-index-cleanup.js +112 -0
- package/dist/db/bun-provider.d.ts +2 -0
- package/dist/db/bun-provider.js +37 -0
- package/dist/db/collect-table-metas.d.ts +3 -0
- package/dist/db/collect-table-metas.js +76 -0
- package/dist/db/compound-types.d.ts +9 -0
- package/dist/db/compound-types.js +31 -0
- package/dist/db/config-seed.d.ts +19 -0
- package/dist/db/config-seed.js +75 -0
- package/dist/db/connection.d.ts +10 -0
- package/dist/db/connection.js +35 -0
- package/dist/db/cursor.d.ts +9 -0
- package/dist/db/cursor.js +39 -0
- package/dist/db/dialect.d.ts +100 -0
- package/dist/db/dialect.js +386 -0
- package/dist/db/eagerload.d.ts +18 -0
- package/dist/db/eagerload.js +191 -0
- package/dist/db/entity-field-encryption.d.ts +15 -0
- package/dist/db/entity-field-encryption.js +127 -0
- package/dist/db/entity-table-from-registry.d.ts +4 -0
- package/dist/db/entity-table-from-registry.js +25 -0
- package/dist/db/entity-table-meta-types.d.ts +1 -0
- package/dist/db/entity-table-meta-types.js +1 -0
- package/dist/db/entity-table-meta.d.ts +30 -0
- package/dist/db/entity-table-meta.js +423 -0
- package/dist/db/event-store-executor-context.d.ts +49 -0
- package/dist/db/event-store-executor-context.js +368 -0
- package/dist/db/event-store-executor-read.d.ts +10 -0
- package/dist/db/event-store-executor-read.js +683 -0
- package/dist/db/event-store-executor-write.d.ts +3 -0
- package/dist/db/event-store-executor-write.js +705 -0
- package/dist/db/event-store-executor.d.ts +20 -0
- package/dist/db/event-store-executor.js +11 -0
- package/dist/db/feature-table-sources.d.ts +6 -0
- package/dist/db/feature-table-sources.js +24 -0
- package/dist/db/index.d.ts +37 -0
- package/dist/db/index.js +29 -0
- package/dist/db/located-timestamp.d.ts +22 -0
- package/dist/db/located-timestamp.js +100 -0
- package/dist/db/migrate-generator.d.ts +81 -0
- package/dist/db/migrate-generator.js +428 -0
- package/dist/db/migrate-runner.d.ts +30 -0
- package/dist/db/migrate-runner.js +273 -0
- package/dist/db/money.d.ts +30 -0
- package/dist/db/money.js +153 -0
- package/dist/db/parent-ref-clause.d.ts +10 -0
- package/dist/db/parent-ref-clause.js +124 -0
- package/dist/db/pg-error.d.ts +10 -0
- package/dist/db/pg-error.js +63 -0
- package/dist/db/postgres-provider.d.ts +2 -0
- package/dist/db/postgres-provider.js +21 -0
- package/dist/db/queries/advisory-lock.d.ts +3 -0
- package/dist/db/queries/advisory-lock.js +5 -0
- package/dist/db/queries/backfill-pii.d.ts +38 -0
- package/dist/db/queries/backfill-pii.js +433 -0
- package/dist/db/queries/ddl.d.ts +4 -0
- package/dist/db/queries/ddl.js +22 -0
- package/dist/db/queries/entity-read.d.ts +2 -0
- package/dist/db/queries/entity-read.js +5 -0
- package/dist/db/queries/es-ops.d.ts +5 -0
- package/dist/db/queries/es-ops.js +10 -0
- package/dist/db/queries/event-consumer.d.ts +36 -0
- package/dist/db/queries/event-consumer.js +261 -0
- package/dist/db/queries/event-store-admin.d.ts +24 -0
- package/dist/db/queries/event-store-admin.js +71 -0
- package/dist/db/queries/event-store-transfer.d.ts +20 -0
- package/dist/db/queries/event-store-transfer.js +31 -0
- package/dist/db/queries/event-store.d.ts +54 -0
- package/dist/db/queries/event-store.js +231 -0
- package/dist/db/queries/pii-backfill-state.d.ts +7 -0
- package/dist/db/queries/pii-backfill-state.js +14 -0
- package/dist/db/queries/projection-rebuild.d.ts +6 -0
- package/dist/db/queries/projection-rebuild.js +65 -0
- package/dist/db/queries/raw-sql.d.ts +9 -0
- package/dist/db/queries/raw-sql.js +16 -0
- package/dist/db/queries/seed-context.d.ts +20 -0
- package/dist/db/queries/seed-context.js +25 -0
- package/dist/db/queries/shadow-swap.d.ts +18 -0
- package/dist/db/queries/shadow-swap.js +307 -0
- package/dist/db/queries/table-ops.d.ts +4 -0
- package/dist/db/queries/table-ops.js +8 -0
- package/dist/db/queries/test-stack.d.ts +6 -0
- package/dist/db/queries/test-stack.js +20 -0
- package/dist/db/query-api.d.ts +2 -0
- package/dist/db/query-api.js +6 -0
- package/dist/db/query.d.ts +1 -0
- package/dist/db/query.js +3 -0
- package/dist/db/rebuild-marker.d.ts +4 -0
- package/dist/db/rebuild-marker.js +96 -0
- package/dist/db/reference-data.d.ts +14 -0
- package/dist/db/reference-data.js +66 -0
- package/dist/db/render-ddl.d.ts +4 -0
- package/dist/db/render-ddl.js +55 -0
- package/dist/db/replay-migration-sql.d.ts +12 -0
- package/dist/db/replay-migration-sql.js +223 -0
- package/dist/db/schema-inspection.d.ts +3 -0
- package/dist/db/schema-inspection.js +60 -0
- package/dist/db/table-builder.d.ts +194 -0
- package/dist/db/table-builder.js +430 -0
- package/dist/db/tenant-db-runner.d.ts +4 -0
- package/dist/db/tenant-db-runner.js +17 -0
- package/dist/db/tenant-db.d.ts +32 -0
- package/dist/db/tenant-db.js +501 -0
- package/dist/derivatives/delete-stored-file.d.ts +6 -0
- package/dist/derivatives/delete-stored-file.js +70 -0
- package/dist/derivatives/derivatives-context.d.ts +21 -0
- package/dist/derivatives/derivatives-context.js +212 -0
- package/dist/derivatives/field-variants.d.ts +3 -0
- package/dist/derivatives/field-variants.js +16 -0
- package/dist/derivatives/index.d.ts +6 -0
- package/dist/derivatives/index.js +4 -0
- package/dist/derivatives/variant-key.d.ts +10 -0
- package/dist/derivatives/variant-key.js +100 -0
- package/dist/engine/access.d.ts +2 -0
- package/dist/engine/access.js +25 -0
- package/dist/engine/active-membership.d.ts +26 -0
- package/dist/engine/active-membership.js +25 -0
- package/dist/engine/boot-validator/access-declarations.d.ts +2 -0
- package/dist/engine/boot-validator/access-declarations.js +148 -0
- package/dist/engine/boot-validator/access-roles.d.ts +2 -0
- package/dist/engine/boot-validator/access-roles.js +76 -0
- package/dist/engine/boot-validator/action-wiring.d.ts +3 -0
- package/dist/engine/boot-validator/action-wiring.js +104 -0
- package/dist/engine/boot-validator/api-ext.d.ts +3 -0
- package/dist/engine/boot-validator/api-ext.js +54 -0
- package/dist/engine/boot-validator/boot-check.d.ts +2 -0
- package/dist/engine/boot-validator/boot-check.js +20 -0
- package/dist/engine/boot-validator/config-deps.d.ts +10 -0
- package/dist/engine/boot-validator/config-deps.js +180 -0
- package/dist/engine/boot-validator/custom-screen-write-qns.d.ts +8 -0
- package/dist/engine/boot-validator/custom-screen-write-qns.js +75 -0
- package/dist/engine/boot-validator/detail-screens.d.ts +6 -0
- package/dist/engine/boot-validator/detail-screens.js +31 -0
- package/dist/engine/boot-validator/entity-handler.d.ts +23 -0
- package/dist/engine/boot-validator/entity-handler.js +754 -0
- package/dist/engine/boot-validator/entity-list-screens.d.ts +4 -0
- package/dist/engine/boot-validator/entity-list-screens.js +75 -0
- package/dist/engine/boot-validator/gdpr-storage.d.ts +2 -0
- package/dist/engine/boot-validator/gdpr-storage.js +48 -0
- package/dist/engine/boot-validator/global-tenancy.d.ts +2 -0
- package/dist/engine/boot-validator/global-tenancy.js +24 -0
- package/dist/engine/boot-validator/i18n-keys.d.ts +2 -0
- package/dist/engine/boot-validator/i18n-keys.js +88 -0
- package/dist/engine/boot-validator/index.d.ts +34 -0
- package/dist/engine/boot-validator/index.js +196 -0
- package/dist/engine/boot-validator/nav.d.ts +20 -0
- package/dist/engine/boot-validator/nav.js +202 -0
- package/dist/engine/boot-validator/ownership.d.ts +36 -0
- package/dist/engine/boot-validator/ownership.js +268 -0
- package/dist/engine/boot-validator/parent-ref.d.ts +3 -0
- package/dist/engine/boot-validator/parent-ref.js +73 -0
- package/dist/engine/boot-validator/pii-retention.d.ts +2 -0
- package/dist/engine/boot-validator/pii-retention.js +204 -0
- package/dist/engine/boot-validator/projection-list-screens.d.ts +4 -0
- package/dist/engine/boot-validator/projection-list-screens.js +219 -0
- package/dist/engine/boot-validator/query-output-columns.d.ts +2 -0
- package/dist/engine/boot-validator/query-output-columns.js +160 -0
- package/dist/engine/boot-validator/query-refs.d.ts +2 -0
- package/dist/engine/boot-validator/query-refs.js +72 -0
- package/dist/engine/boot-validator/record-owned.d.ts +2 -0
- package/dist/engine/boot-validator/record-owned.js +16 -0
- package/dist/engine/boot-validator/screens.d.ts +34 -0
- package/dist/engine/boot-validator/screens.js +1665 -0
- package/dist/engine/boot-validator/security-baseline.d.ts +3 -0
- package/dist/engine/boot-validator/security-baseline.js +18 -0
- package/dist/engine/boot-validator/transfer-graph.d.ts +3 -0
- package/dist/engine/boot-validator/transfer-graph.js +120 -0
- package/dist/engine/boot-validator/url-prefill-fields.d.ts +2 -0
- package/dist/engine/boot-validator/url-prefill-fields.js +106 -0
- package/dist/engine/boot-validator/workspaces.d.ts +20 -0
- package/dist/engine/boot-validator/workspaces.js +81 -0
- package/dist/engine/boot-validator/zod-shape.d.ts +5 -0
- package/dist/engine/boot-validator/zod-shape.js +110 -0
- package/dist/engine/boot-validator.d.ts +1 -0
- package/dist/engine/boot-validator.js +1 -0
- package/dist/engine/build-app-schema.d.ts +14 -0
- package/dist/engine/build-app-schema.js +494 -0
- package/dist/engine/build-config-feature-schema.d.ts +15 -0
- package/dist/engine/build-config-feature-schema.js +582 -0
- package/dist/engine/build-target.d.ts +28 -0
- package/dist/engine/build-target.js +43 -0
- package/dist/engine/changeset-changes.d.ts +12 -0
- package/dist/engine/changeset-changes.js +104 -0
- package/dist/engine/codemod/index.d.ts +2 -0
- package/dist/engine/codemod/index.js +1 -0
- package/dist/engine/codemod/pipeline-codemod.d.ts +50 -0
- package/dist/engine/codemod/pipeline-codemod.js +529 -0
- package/dist/engine/config-helpers.d.ts +42 -0
- package/dist/engine/config-helpers.js +115 -0
- package/dist/engine/constants.d.ts +52 -0
- package/dist/engine/constants.js +79 -0
- package/dist/engine/create-app.d.ts +17 -0
- package/dist/engine/create-app.js +119 -0
- package/dist/engine/cross-tenant.d.ts +3 -0
- package/dist/engine/cross-tenant.js +18 -0
- package/dist/engine/dedupe-features.d.ts +2 -0
- package/dist/engine/dedupe-features.js +36 -0
- package/dist/engine/define-feature.d.ts +7 -0
- package/dist/engine/define-feature.js +143 -0
- package/dist/engine/define-handler.d.ts +21 -0
- package/dist/engine/define-handler.js +117 -0
- package/dist/engine/define-roles.d.ts +5 -0
- package/dist/engine/define-roles.js +14 -0
- package/dist/engine/define-step.d.ts +4 -0
- package/dist/engine/define-step.js +22 -0
- package/dist/engine/define-workflow.d.ts +89 -0
- package/dist/engine/define-workflow.js +70 -0
- package/dist/engine/effective-features.d.ts +6 -0
- package/dist/engine/effective-features.js +73 -0
- package/dist/engine/embedded-derived.d.ts +29 -0
- package/dist/engine/embedded-derived.js +82 -0
- package/dist/engine/entity-handlers.d.ts +67 -0
- package/dist/engine/entity-handlers.js +567 -0
- package/dist/engine/escape-hatch-declaration.d.ts +2 -0
- package/dist/engine/escape-hatch-declaration.js +5 -0
- package/dist/engine/event-helpers.d.ts +11 -0
- package/dist/engine/event-helpers.js +47 -0
- package/dist/engine/extension-names.d.ts +164 -0
- package/dist/engine/extension-names.js +172 -0
- package/dist/engine/extension-selector-plugins.d.ts +5 -0
- package/dist/engine/extension-selector-plugins.js +14 -0
- package/dist/engine/extensions/escape-hatch-usage.d.ts +2 -0
- package/dist/engine/extensions/escape-hatch-usage.js +12 -0
- package/dist/engine/extensions/storage-provider.d.ts +4 -0
- package/dist/engine/extensions/storage-provider.js +1 -0
- package/dist/engine/extensions/tenant-data.d.ts +15 -0
- package/dist/engine/extensions/tenant-data.js +7 -0
- package/dist/engine/extensions/tenant-resource.d.ts +14 -0
- package/dist/engine/extensions/tenant-resource.js +6 -0
- package/dist/engine/extensions/user-data.d.ts +152 -0
- package/dist/engine/extensions/user-data.js +12 -0
- package/dist/engine/factories.d.ts +195 -0
- package/dist/engine/factories.js +387 -0
- package/dist/engine/feature-ast/entity-field-types.d.ts +13 -0
- package/dist/engine/feature-ast/entity-field-types.js +35 -0
- package/dist/engine/feature-ast/extractors/ai-steps.d.ts +6 -0
- package/dist/engine/feature-ast/extractors/ai-steps.js +254 -0
- package/dist/engine/feature-ast/extractors/events.d.ts +5 -0
- package/dist/engine/feature-ast/extractors/events.js +262 -0
- package/dist/engine/feature-ast/extractors/handlers.d.ts +23 -0
- package/dist/engine/feature-ast/extractors/handlers.js +319 -0
- package/dist/engine/feature-ast/extractors/hooks.d.ts +23 -0
- package/dist/engine/feature-ast/extractors/hooks.js +228 -0
- package/dist/engine/feature-ast/extractors/index.d.ts +14 -0
- package/dist/engine/feature-ast/extractors/index.js +13 -0
- package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +7 -0
- package/dist/engine/feature-ast/extractors/jobs-routes.js +141 -0
- package/dist/engine/feature-ast/extractors/projections-screens.d.ts +10 -0
- package/dist/engine/feature-ast/extractors/projections-screens.js +195 -0
- package/dist/engine/feature-ast/extractors/resolve-import.d.ts +14 -0
- package/dist/engine/feature-ast/extractors/resolve-import.js +152 -0
- package/dist/engine/feature-ast/extractors/round1.d.ts +10 -0
- package/dist/engine/feature-ast/extractors/round1.js +81 -0
- package/dist/engine/feature-ast/extractors/round2.d.ts +7 -0
- package/dist/engine/feature-ast/extractors/round2.js +158 -0
- package/dist/engine/feature-ast/extractors/round3.d.ts +22 -0
- package/dist/engine/feature-ast/extractors/round3.js +280 -0
- package/dist/engine/feature-ast/extractors/round5.d.ts +8 -0
- package/dist/engine/feature-ast/extractors/round5.js +63 -0
- package/dist/engine/feature-ast/extractors/round6.d.ts +4 -0
- package/dist/engine/feature-ast/extractors/round6.js +17 -0
- package/dist/engine/feature-ast/extractors/shared.d.ts +85 -0
- package/dist/engine/feature-ast/extractors/shared.js +326 -0
- package/dist/engine/feature-ast/index.d.ts +16 -0
- package/dist/engine/feature-ast/index.js +10 -0
- package/dist/engine/feature-ast/parse.d.ts +30 -0
- package/dist/engine/feature-ast/parse.js +464 -0
- package/dist/engine/feature-ast/patch.d.ts +207 -0
- package/dist/engine/feature-ast/patch.js +771 -0
- package/dist/engine/feature-ast/patcher.d.ts +211 -0
- package/dist/engine/feature-ast/patcher.js +277 -0
- package/dist/engine/feature-ast/pattern-change-schema.d.ts +670 -0
- package/dist/engine/feature-ast/pattern-change-schema.js +1196 -0
- package/dist/engine/feature-ast/patterns.d.ts +302 -0
- package/dist/engine/feature-ast/patterns.js +113 -0
- package/dist/engine/feature-ast/render.d.ts +47 -0
- package/dist/engine/feature-ast/render.js +681 -0
- package/dist/engine/feature-ast/source-location.d.ts +17 -0
- package/dist/engine/feature-ast/source-location.js +27 -0
- package/dist/engine/feature-builder-state.d.ts +69 -0
- package/dist/engine/feature-builder-state.js +64 -0
- package/dist/engine/feature-changelog.d.ts +21 -0
- package/dist/engine/feature-changelog.js +76 -0
- package/dist/engine/feature-config-events-jobs.d.ts +58 -0
- package/dist/engine/feature-config-events-jobs.js +318 -0
- package/dist/engine/feature-entity-handlers.d.ts +38 -0
- package/dist/engine/feature-entity-handlers.js +185 -0
- package/dist/engine/feature-manifest.d.ts +73 -0
- package/dist/engine/feature-manifest.js +87 -0
- package/dist/engine/feature-ui-extensions.d.ts +68 -0
- package/dist/engine/feature-ui-extensions.js +488 -0
- package/dist/engine/field-access.d.ts +4 -0
- package/dist/engine/field-access.js +119 -0
- package/dist/engine/field-helpers.d.ts +4 -0
- package/dist/engine/field-helpers.js +28 -0
- package/dist/engine/handler-helpers.d.ts +19 -0
- package/dist/engine/handler-helpers.js +24 -0
- package/dist/engine/hook-helpers.d.ts +4 -0
- package/dist/engine/hook-helpers.js +13 -0
- package/dist/engine/i18n-key.d.ts +2 -0
- package/dist/engine/i18n-key.js +10 -0
- package/dist/engine/index.d.ts +77 -0
- package/dist/engine/index.js +70 -0
- package/dist/engine/instruction-fields.d.ts +2 -0
- package/dist/engine/instruction-fields.js +9 -0
- package/dist/engine/membership-roles.d.ts +5 -0
- package/dist/engine/membership-roles.js +48 -0
- package/dist/engine/object-form.d.ts +4 -0
- package/dist/engine/object-form.js +21 -0
- package/dist/engine/ownership.d.ts +12 -0
- package/dist/engine/ownership.js +339 -0
- package/dist/engine/parse-ref-target.d.ts +6 -0
- package/dist/engine/parse-ref-target.js +21 -0
- package/dist/engine/pattern-library/index.d.ts +2 -0
- package/dist/engine/pattern-library/index.js +3 -0
- package/dist/engine/pattern-library/library.d.ts +14 -0
- package/dist/engine/pattern-library/library.js +92 -0
- package/dist/engine/pattern-library/mixed-schemas.d.ts +16 -0
- package/dist/engine/pattern-library/mixed-schemas.js +569 -0
- package/dist/engine/pattern-library/opaque-schemas.d.ts +7 -0
- package/dist/engine/pattern-library/opaque-schemas.js +115 -0
- package/dist/engine/pattern-library/shared-fields.d.ts +120 -0
- package/dist/engine/pattern-library/shared-fields.js +71 -0
- package/dist/engine/pattern-library/static-schemas.d.ts +19 -0
- package/dist/engine/pattern-library/static-schemas.js +435 -0
- package/dist/engine/pattern-library/types.d.ts +158 -0
- package/dist/engine/pattern-library/types.js +36 -0
- package/dist/engine/personal-data-fields.d.ts +5 -0
- package/dist/engine/personal-data-fields.js +56 -0
- package/dist/engine/pipeline.d.ts +4 -0
- package/dist/engine/pipeline.js +87 -0
- package/dist/engine/project-app-schema-for-roles.d.ts +2 -0
- package/dist/engine/project-app-schema-for-roles.js +679 -0
- package/dist/engine/projection-helpers.d.ts +7 -0
- package/dist/engine/projection-helpers.js +61 -0
- package/dist/engine/qualified-name.d.ts +27 -0
- package/dist/engine/qualified-name.js +137 -0
- package/dist/engine/read-claim.d.ts +2 -0
- package/dist/engine/read-claim.js +28 -0
- package/dist/engine/registry-facade.d.ts +3 -0
- package/dist/engine/registry-facade.js +231 -0
- package/dist/engine/registry-ingest.d.ts +14 -0
- package/dist/engine/registry-ingest.js +415 -0
- package/dist/engine/registry-state.d.ts +93 -0
- package/dist/engine/registry-state.js +233 -0
- package/dist/engine/registry-validate.d.ts +25 -0
- package/dist/engine/registry-validate.js +669 -0
- package/dist/engine/registry.d.ts +2 -0
- package/dist/engine/registry.js +52 -0
- package/dist/engine/resolve-config-or-param.d.ts +18 -0
- package/dist/engine/resolve-config-or-param.js +76 -0
- package/dist/engine/role-assignment.d.ts +1 -0
- package/dist/engine/role-assignment.js +58 -0
- package/dist/engine/run-in.d.ts +2 -0
- package/dist/engine/run-in.js +28 -0
- package/dist/engine/run-pipeline.d.ts +25 -0
- package/dist/engine/run-pipeline.js +111 -0
- package/dist/engine/schema-builder.d.ts +8 -0
- package/dist/engine/schema-builder.js +406 -0
- package/dist/engine/screen-filter-ops.d.ts +3 -0
- package/dist/engine/screen-filter-ops.js +55 -0
- package/dist/engine/screen-helpers.d.ts +27 -0
- package/dist/engine/screen-helpers.js +100 -0
- package/dist/engine/soft-delete-cleanup.d.ts +10 -0
- package/dist/engine/soft-delete-cleanup.js +114 -0
- package/dist/engine/state-machine.d.ts +34 -0
- package/dist/engine/state-machine.js +44 -0
- package/dist/engine/steps/_duration-utils.d.ts +1 -0
- package/dist/engine/steps/_duration-utils.js +28 -0
- package/dist/engine/steps/_event-match.d.ts +2 -0
- package/dist/engine/steps/_event-match.js +88 -0
- package/dist/engine/steps/_no-return-guard.d.ts +2 -0
- package/dist/engine/steps/_no-return-guard.js +16 -0
- package/dist/engine/steps/_read-source.d.ts +6 -0
- package/dist/engine/steps/_read-source.js +7 -0
- package/dist/engine/steps/_resolver-utils.d.ts +11 -0
- package/dist/engine/steps/_resolver-utils.js +36 -0
- package/dist/engine/steps/_step-dispatch-constants.d.ts +13 -0
- package/dist/engine/steps/_step-dispatch-constants.js +32 -0
- package/dist/engine/steps/aggregate-append-event.d.ts +10 -0
- package/dist/engine/steps/aggregate-append-event.js +43 -0
- package/dist/engine/steps/aggregate-create.d.ts +6 -0
- package/dist/engine/steps/aggregate-create.js +38 -0
- package/dist/engine/steps/aggregate-update.d.ts +10 -0
- package/dist/engine/steps/aggregate-update.js +38 -0
- package/dist/engine/steps/branch.d.ts +8 -0
- package/dist/engine/steps/branch.js +66 -0
- package/dist/engine/steps/call-feature.d.ts +7 -0
- package/dist/engine/steps/call-feature.js +30 -0
- package/dist/engine/steps/compute.d.ts +2 -0
- package/dist/engine/steps/compute.js +29 -0
- package/dist/engine/steps/describe-workflow-step-error.d.ts +1 -0
- package/dist/engine/steps/describe-workflow-step-error.js +6 -0
- package/dist/engine/steps/for-each.d.ts +9 -0
- package/dist/engine/steps/for-each.js +88 -0
- package/dist/engine/steps/mail-send.d.ts +10 -0
- package/dist/engine/steps/mail-send.js +33 -0
- package/dist/engine/steps/read-find-many.d.ts +10 -0
- package/dist/engine/steps/read-find-many.js +32 -0
- package/dist/engine/steps/read-find-one.d.ts +9 -0
- package/dist/engine/steps/read-find-one.js +41 -0
- package/dist/engine/steps/retry.d.ts +9 -0
- package/dist/engine/steps/retry.js +76 -0
- package/dist/engine/steps/return.d.ts +4 -0
- package/dist/engine/steps/return.js +25 -0
- package/dist/engine/steps/unsafe-projection-delete.d.ts +8 -0
- package/dist/engine/steps/unsafe-projection-delete.js +35 -0
- package/dist/engine/steps/unsafe-projection-upsert.d.ts +8 -0
- package/dist/engine/steps/unsafe-projection-upsert.js +73 -0
- package/dist/engine/steps/wait-for-event.d.ts +8 -0
- package/dist/engine/steps/wait-for-event.js +63 -0
- package/dist/engine/steps/wait.d.ts +6 -0
- package/dist/engine/steps/wait.js +50 -0
- package/dist/engine/steps/webhook-send.d.ts +24 -0
- package/dist/engine/steps/webhook-send.js +38 -0
- package/dist/engine/system-user.d.ts +8 -0
- package/dist/engine/system-user.js +29 -0
- package/dist/engine/tier-resolver-extension.d.ts +62 -0
- package/dist/engine/tier-resolver-extension.js +55 -0
- package/dist/engine/types/config.d.ts +1 -0
- package/dist/engine/types/config.js +1 -0
- package/dist/engine/types/define-handler.d.ts +1 -0
- package/dist/engine/types/define-handler.js +1 -0
- package/dist/engine/types/entity-handlers.d.ts +1 -0
- package/dist/engine/types/entity-handlers.js +1 -0
- package/dist/engine/types/event-type-map.js +1 -0
- package/dist/engine/types/extension-options-map.js +1 -0
- package/dist/engine/types/feature.d.ts +1 -0
- package/dist/engine/types/feature.js +1 -0
- package/dist/engine/types/fields.d.ts +1 -0
- package/dist/engine/types/fields.js +1 -0
- package/dist/engine/types/handlers.d.ts +2 -0
- package/dist/engine/types/handlers.js +1 -0
- package/dist/engine/types/hooks.d.ts +1 -0
- package/dist/engine/types/hooks.js +1 -0
- package/dist/engine/types/http-route.js +1 -0
- package/dist/engine/types/identifiers.js +1 -0
- package/dist/engine/types/index.d.ts +30 -0
- package/dist/engine/types/index.js +10 -0
- package/dist/engine/types/nav.d.ts +1 -0
- package/dist/engine/types/nav.js +1 -0
- package/dist/engine/types/ownership.d.ts +1 -0
- package/dist/engine/types/ownership.js +1 -0
- package/dist/engine/types/projection.d.ts +1 -0
- package/dist/engine/types/projection.js +1 -0
- package/dist/engine/types/relations.js +1 -0
- package/dist/engine/types/screen.d.ts +2 -0
- package/dist/engine/types/screen.js +1 -0
- package/dist/engine/types/step.d.ts +1 -0
- package/dist/engine/types/step.js +1 -0
- package/dist/engine/types/target-ref.js +1 -0
- package/dist/engine/types/tree-node.js +1 -0
- package/dist/engine/types/workspace.d.ts +1 -0
- package/dist/engine/types/workspace.js +1 -0
- package/dist/engine/validate-projection-allowlist.d.ts +10 -0
- package/dist/engine/validate-projection-allowlist.js +164 -0
- package/dist/engine/validation.d.ts +3 -0
- package/dist/engine/validation.js +23 -0
- package/dist/engine/where-rule-lint.d.ts +2 -0
- package/dist/engine/where-rule-lint.js +171 -0
- package/dist/engine/write-handler-qn-extract.d.ts +15 -0
- package/dist/engine/write-handler-qn-extract.js +36 -0
- package/dist/entrypoint/index.d.ts +83 -0
- package/dist/entrypoint/index.js +312 -0
- package/dist/env/_zod-introspect.d.ts +17 -0
- package/dist/env/_zod-introspect.js +35 -0
- package/dist/env/dry-run.d.ts +13 -0
- package/dist/env/dry-run.js +158 -0
- package/dist/env/index.d.ts +98 -0
- package/dist/env/index.js +313 -0
- package/dist/errors/classes.d.ts +109 -0
- package/dist/errors/classes.js +190 -0
- package/dist/errors/field-issue.d.ts +6 -0
- package/dist/errors/field-issue.js +1 -0
- package/dist/errors/index.d.ts +15 -0
- package/dist/errors/index.js +9 -0
- package/dist/errors/kumiko-error.d.ts +25 -0
- package/dist/errors/kumiko-error.js +43 -0
- package/dist/errors/member-resolution.d.ts +2 -0
- package/dist/errors/member-resolution.js +10 -0
- package/dist/errors/reasons.d.ts +23 -0
- package/dist/errors/reasons.js +81 -0
- package/dist/errors/serialize.d.ts +32 -0
- package/dist/errors/serialize.js +76 -0
- package/dist/errors/to-kumiko-error.d.ts +2 -0
- package/dist/errors/to-kumiko-error.js +9 -0
- package/dist/errors/transition-details.d.ts +7 -0
- package/dist/errors/transition-details.js +16 -0
- package/dist/errors/write-error-info.d.ts +20 -0
- package/dist/errors/write-error-info.js +99 -0
- package/dist/errors/zod-bridge.d.ts +3 -0
- package/dist/errors/zod-bridge.js +58 -0
- package/dist/es-ops/context.d.ts +19 -0
- package/dist/es-ops/context.js +70 -0
- package/dist/es-ops/index.d.ts +4 -0
- package/dist/es-ops/index.js +14 -0
- package/dist/es-ops/operations-schema.d.ts +5 -0
- package/dist/es-ops/operations-schema.js +40 -0
- package/dist/es-ops/runner.d.ts +29 -0
- package/dist/es-ops/runner.js +195 -0
- package/dist/es-ops/types.d.ts +92 -0
- package/dist/es-ops/types.js +14 -0
- package/dist/event-store/admin-api.d.ts +17 -0
- package/dist/event-store/admin-api.js +173 -0
- package/dist/event-store/archive.d.ts +14 -0
- package/dist/event-store/archive.js +55 -0
- package/dist/event-store/errors.d.ts +15 -0
- package/dist/event-store/errors.js +49 -0
- package/dist/event-store/event-store.d.ts +38 -0
- package/dist/event-store/event-store.js +310 -0
- package/dist/event-store/events-schema.d.ts +3 -0
- package/dist/event-store/events-schema.js +66 -0
- package/dist/event-store/index.d.ts +12 -0
- package/dist/event-store/index.js +12 -0
- package/dist/event-store/provenance-append.d.ts +13 -0
- package/dist/event-store/provenance-append.js +49 -0
- package/dist/event-store/rebuild-dead-letter.d.ts +25 -0
- package/dist/event-store/rebuild-dead-letter.js +71 -0
- package/dist/event-store/row-to-stored-event.d.ts +17 -0
- package/dist/event-store/row-to-stored-event.js +15 -0
- package/dist/event-store/snapshot.d.ts +26 -0
- package/dist/event-store/snapshot.js +155 -0
- package/dist/event-store/transfer.d.ts +13 -0
- package/dist/event-store/transfer.js +62 -0
- package/dist/event-store/types.d.ts +1 -0
- package/dist/event-store/types.js +1 -0
- package/dist/event-store/upcaster-dead-letter.d.ts +27 -0
- package/dist/event-store/upcaster-dead-letter.js +76 -0
- package/dist/event-store/upcaster.d.ts +14 -0
- package/dist/event-store/upcaster.js +86 -0
- package/dist/files/content-disposition.d.ts +3 -0
- package/dist/files/content-disposition.js +50 -0
- package/dist/files/feature.d.ts +9 -0
- package/dist/files/feature.js +26 -0
- package/dist/files/file-handle.d.ts +7 -0
- package/dist/files/file-handle.js +71 -0
- package/dist/files/file-ref-entity.d.ts +134 -0
- package/dist/files/file-ref-entity.js +32 -0
- package/dist/files/file-ref-table.d.ts +134 -0
- package/dist/files/file-ref-table.js +12 -0
- package/dist/files/file-routes.d.ts +34 -0
- package/dist/files/file-routes.js +433 -0
- package/dist/files/in-memory-provider.d.ts +7 -0
- package/dist/files/in-memory-provider.js +82 -0
- package/dist/files/index.d.ts +17 -0
- package/dist/files/index.js +13 -0
- package/dist/files/local-provider.d.ts +2 -0
- package/dist/files/local-provider.js +128 -0
- package/dist/files/provider-resolver.d.ts +58 -0
- package/dist/files/provider-resolver.js +87 -0
- package/dist/files/storage-tracking.d.ts +20 -0
- package/dist/files/storage-tracking.js +179 -0
- package/dist/files/types.d.ts +59 -0
- package/dist/files/types.js +276 -0
- package/dist/files/zip-stream.d.ts +31 -0
- package/dist/files/zip-stream.js +207 -0
- package/dist/http/index.d.ts +2 -0
- package/dist/http/index.js +1 -0
- package/dist/i18n/index.d.ts +12 -0
- package/dist/i18n/index.js +27 -0
- package/dist/i18n/mail-registry.d.ts +7 -0
- package/dist/i18n/mail-registry.js +34 -0
- package/dist/i18n/request-locale.d.ts +22 -0
- package/dist/i18n/request-locale.js +62 -0
- package/dist/i18n/required-surface-keys.d.ts +33 -0
- package/dist/i18n/required-surface-keys.js +416 -0
- package/dist/i18n/settings-hub-keys.d.ts +14 -0
- package/dist/i18n/settings-hub-keys.js +29 -0
- package/dist/jobs/index.d.ts +2 -0
- package/dist/jobs/index.js +1 -0
- package/dist/jobs/job-runner.d.ts +54 -0
- package/dist/jobs/job-runner.js +1110 -0
- package/dist/lifecycle/index.d.ts +2 -0
- package/dist/lifecycle/index.js +2 -0
- package/dist/lifecycle/lifecycle.d.ts +23 -0
- package/dist/lifecycle/lifecycle.js +111 -0
- package/dist/lifecycle/signal-handlers.d.ts +10 -0
- package/dist/lifecycle/signal-handlers.js +40 -0
- package/dist/logging/index.d.ts +4 -0
- package/dist/logging/index.js +2 -0
- package/dist/logging/pino-logger.d.ts +9 -0
- package/dist/logging/pino-logger.js +61 -0
- package/dist/logging/types.js +1 -0
- package/dist/logging/utils.d.ts +8 -0
- package/dist/logging/utils.js +41 -0
- package/dist/migrations/index.d.ts +4 -0
- package/dist/migrations/index.js +8 -0
- package/dist/migrations/kumiko-drift.d.ts +26 -0
- package/dist/migrations/kumiko-drift.js +151 -0
- package/dist/migrations/pending-rebuilds.d.ts +81 -0
- package/dist/migrations/pending-rebuilds.js +163 -0
- package/dist/migrations/pii-event-backfill.d.ts +40 -0
- package/dist/migrations/pii-event-backfill.js +275 -0
- package/dist/migrations/projection-table-index.d.ts +5 -0
- package/dist/migrations/projection-table-index.js +21 -0
- package/dist/observability/console-provider.d.ts +10 -0
- package/dist/observability/console-provider.js +101 -0
- package/dist/observability/context.d.ts +10 -0
- package/dist/observability/context.js +13 -0
- package/dist/observability/escape-hatch-report.d.ts +23 -0
- package/dist/observability/escape-hatch-report.js +92 -0
- package/dist/observability/fallback.d.ts +4 -0
- package/dist/observability/fallback.js +28 -0
- package/dist/observability/ids.d.ts +2 -0
- package/dist/observability/ids.js +22 -0
- package/dist/observability/index.d.ts +15 -0
- package/dist/observability/index.js +15 -0
- package/dist/observability/metric-validator.d.ts +4 -0
- package/dist/observability/metric-validator.js +73 -0
- package/dist/observability/metrics-handle.d.ts +5 -0
- package/dist/observability/metrics-handle.js +102 -0
- package/dist/observability/metrics-wiring.d.ts +18 -0
- package/dist/observability/metrics-wiring.js +21 -0
- package/dist/observability/noop-provider.d.ts +2 -0
- package/dist/observability/noop-provider.js +105 -0
- package/dist/observability/prometheus-meter.d.ts +26 -0
- package/dist/observability/prometheus-meter.js +257 -0
- package/dist/observability/recording-meter.d.ts +31 -0
- package/dist/observability/recording-meter.js +127 -0
- package/dist/observability/recording-tracer.d.ts +32 -0
- package/dist/observability/recording-tracer.js +135 -0
- package/dist/observability/redis-wrapper.d.ts +3 -0
- package/dist/observability/redis-wrapper.js +121 -0
- package/dist/observability/sensitive-filter.d.ts +9 -0
- package/dist/observability/sensitive-filter.js +92 -0
- package/dist/observability/standard-metrics.d.ts +41 -0
- package/dist/observability/standard-metrics.js +237 -0
- package/dist/observability/types/index.js +1 -0
- package/dist/observability/types/metric.js +1 -0
- package/dist/observability/types/provider.js +1 -0
- package/dist/observability/types/span.js +1 -0
- package/dist/pipeline/active-membership.d.ts +12 -0
- package/dist/pipeline/active-membership.js +124 -0
- package/dist/pipeline/append-event-core.d.ts +12 -0
- package/dist/pipeline/append-event-core.js +84 -0
- package/dist/pipeline/auth-claims-resolver.d.ts +9 -0
- package/dist/pipeline/auth-claims-resolver.js +76 -0
- package/dist/pipeline/cascade-handler.d.ts +6 -0
- package/dist/pipeline/cascade-handler.js +85 -0
- package/dist/pipeline/dispatch-batch.d.ts +5 -0
- package/dist/pipeline/dispatch-batch.js +217 -0
- package/dist/pipeline/dispatch-query.d.ts +4 -0
- package/dist/pipeline/dispatch-query.js +141 -0
- package/dist/pipeline/dispatch-shared.d.ts +58 -0
- package/dist/pipeline/dispatch-shared.js +924 -0
- package/dist/pipeline/dispatch-stream.d.ts +3 -0
- package/dist/pipeline/dispatch-stream.js +89 -0
- package/dist/pipeline/dispatch-write.d.ts +6 -0
- package/dist/pipeline/dispatch-write.js +428 -0
- package/dist/pipeline/dispatcher-utils.d.ts +36 -0
- package/dist/pipeline/dispatcher-utils.js +139 -0
- package/dist/pipeline/dispatcher.d.ts +30 -0
- package/dist/pipeline/dispatcher.js +131 -0
- package/dist/pipeline/distributed-lock.d.ts +13 -0
- package/dist/pipeline/distributed-lock.js +42 -0
- package/dist/pipeline/entity-cache.d.ts +7 -0
- package/dist/pipeline/entity-cache.js +68 -0
- package/dist/pipeline/event-consumer-state.d.ts +16 -0
- package/dist/pipeline/event-consumer-state.js +96 -0
- package/dist/pipeline/event-dedup.d.ts +11 -0
- package/dist/pipeline/event-dedup.js +12 -0
- package/dist/pipeline/event-dispatcher-admin.d.ts +46 -0
- package/dist/pipeline/event-dispatcher-admin.js +196 -0
- package/dist/pipeline/event-dispatcher-delivery.d.ts +68 -0
- package/dist/pipeline/event-dispatcher-delivery.js +310 -0
- package/dist/pipeline/event-dispatcher.d.ts +52 -0
- package/dist/pipeline/event-dispatcher.js +523 -0
- package/dist/pipeline/event-retention.d.ts +20 -0
- package/dist/pipeline/event-retention.js +78 -0
- package/dist/pipeline/idempotency.d.ts +19 -0
- package/dist/pipeline/idempotency.js +115 -0
- package/dist/pipeline/index.d.ts +34 -0
- package/dist/pipeline/index.js +19 -0
- package/dist/pipeline/irreversible-operation-gate.d.ts +4 -0
- package/dist/pipeline/irreversible-operation-gate.js +57 -0
- package/dist/pipeline/lifecycle-pipeline.d.ts +29 -0
- package/dist/pipeline/lifecycle-pipeline.js +266 -0
- package/dist/pipeline/member-read-only-transaction.d.ts +3 -0
- package/dist/pipeline/member-read-only-transaction.js +68 -0
- package/dist/pipeline/member-reader.d.ts +7 -0
- package/dist/pipeline/member-reader.js +87 -0
- package/dist/pipeline/msp-rebuild.d.ts +12 -0
- package/dist/pipeline/msp-rebuild.js +163 -0
- package/dist/pipeline/multi-stream-apply-context.d.ts +18 -0
- package/dist/pipeline/multi-stream-apply-context.js +40 -0
- package/dist/pipeline/pending-gap-ranges.d.ts +12 -0
- package/dist/pipeline/pending-gap-ranges.js +99 -0
- package/dist/pipeline/projection-rebuild.d.ts +55 -0
- package/dist/pipeline/projection-rebuild.js +285 -0
- package/dist/pipeline/projection-state.d.ts +9 -0
- package/dist/pipeline/projection-state.js +51 -0
- package/dist/pipeline/projections-runner.d.ts +5 -0
- package/dist/pipeline/projections-runner.js +57 -0
- package/dist/pipeline/redis-keys.d.ts +8 -0
- package/dist/pipeline/redis-keys.js +10 -0
- package/dist/pipeline/system-hooks.d.ts +25 -0
- package/dist/pipeline/system-hooks.js +590 -0
- package/dist/pipeline/system-identity-switch.d.ts +30 -0
- package/dist/pipeline/system-identity-switch.js +248 -0
- package/dist/pipeline/tenant-timezone-cache.d.ts +17 -0
- package/dist/pipeline/tenant-timezone-cache.js +55 -0
- package/dist/pipeline/write-origin.d.ts +10 -0
- package/dist/pipeline/write-origin.js +110 -0
- package/dist/random/generate.d.ts +56 -0
- package/dist/random/generate.js +92 -0
- package/dist/random/index.d.ts +2 -0
- package/dist/random/index.js +2 -0
- package/dist/random/words.d.ts +2 -0
- package/dist/random/words.js +391 -0
- package/dist/rate-limit/bucket.d.ts +14 -0
- package/dist/rate-limit/bucket.js +20 -0
- package/dist/rate-limit/index.d.ts +3 -0
- package/dist/rate-limit/index.js +3 -0
- package/dist/rate-limit/middleware.d.ts +24 -0
- package/dist/rate-limit/middleware.js +101 -0
- package/dist/rate-limit/resolver.d.ts +9 -0
- package/dist/rate-limit/resolver.js +177 -0
- package/dist/redis/client.d.ts +9 -0
- package/dist/redis/client.js +44 -0
- package/dist/redis/index.d.ts +4 -0
- package/dist/redis/index.js +2 -0
- package/dist/redis/pubsub-signal.d.ts +11 -0
- package/dist/redis/pubsub-signal.js +79 -0
- package/dist/schema-cli.d.ts +21 -0
- package/dist/schema-cli.js +438 -0
- package/dist/scripts/codemod/crypto-shredding-testing-move.d.ts +2 -0
- package/dist/scripts/codemod/crypto-shredding-testing-move.js +109 -0
- package/dist/scripts/codemod/migrate-cross-tenant.d.ts +19 -0
- package/dist/scripts/codemod/migrate-cross-tenant.js +266 -0
- package/dist/scripts/codemod/migrate-db-raw.d.ts +23 -0
- package/dist/scripts/codemod/migrate-db-raw.js +345 -0
- package/dist/scripts/codemod/migrate-open-to-all.d.ts +22 -0
- package/dist/scripts/codemod/migrate-open-to-all.js +194 -0
- package/dist/scripts/codemod/pii-personal-migration.d.ts +11 -0
- package/dist/scripts/codemod/pii-personal-migration.js +615 -0
- package/dist/scripts/codemod/unprocessable-error-details-reason.d.ts +2 -0
- package/dist/scripts/codemod/unprocessable-error-details-reason.js +235 -0
- package/dist/search/derive-search-adapter-config.d.ts +3 -0
- package/dist/search/derive-search-adapter-config.js +23 -0
- package/dist/search/in-memory-adapter.d.ts +2 -0
- package/dist/search/in-memory-adapter.js +96 -0
- package/dist/search/index.d.ts +6 -0
- package/dist/search/index.js +8 -0
- package/dist/search/meilisearch-adapter.d.ts +10 -0
- package/dist/search/meilisearch-adapter.js +175 -0
- package/dist/search/purge-subject.d.ts +7 -0
- package/dist/search/purge-subject.js +178 -0
- package/dist/search/reindex-entity.d.ts +18 -0
- package/dist/search/reindex-entity.js +139 -0
- package/dist/search/types.js +1 -0
- package/dist/secrets/dek-cache.d.ts +13 -0
- package/dist/secrets/dek-cache.js +97 -0
- package/dist/secrets/derive-purpose-secret.d.ts +1 -0
- package/dist/secrets/derive-purpose-secret.js +16 -0
- package/dist/secrets/env-master-key-provider.d.ts +6 -0
- package/dist/secrets/env-master-key-provider.js +134 -0
- package/dist/secrets/envelope-cipher.d.ts +8 -0
- package/dist/secrets/envelope-cipher.js +36 -0
- package/dist/secrets/envelope.d.ts +3 -0
- package/dist/secrets/envelope.js +44 -0
- package/dist/secrets/index.d.ts +9 -0
- package/dist/secrets/index.js +9 -0
- package/dist/secrets/leak-guard.d.ts +1 -0
- package/dist/secrets/leak-guard.js +79 -0
- package/dist/secrets/rotation.d.ts +2 -0
- package/dist/secrets/rotation.js +29 -0
- package/dist/secrets/stored-envelope.d.ts +11 -0
- package/dist/secrets/stored-envelope.js +32 -0
- package/dist/secrets/types.d.ts +1 -0
- package/dist/seeding/entity-seed.d.ts +19 -0
- package/dist/seeding/entity-seed.js +12 -0
- package/dist/seeding/index.d.ts +2 -0
- package/dist/seeding/index.js +2 -0
- package/dist/seeding/types.d.ts +7 -0
- package/dist/seeding/types.js +1 -0
- package/dist/stack/db.d.ts +19 -0
- package/dist/stack/db.js +61 -0
- package/dist/stack/drain-event-consumers.d.ts +4 -0
- package/dist/stack/drain-event-consumers.js +48 -0
- package/dist/stack/drain-jobs.d.ts +20 -0
- package/dist/stack/drain-jobs.js +99 -0
- package/dist/stack/event-collector.d.ts +9 -0
- package/dist/stack/event-collector.js +12 -0
- package/dist/stack/index.d.ts +9 -0
- package/dist/stack/index.js +19 -0
- package/dist/stack/push-entity-projection-tables.d.ts +24 -0
- package/dist/stack/push-entity-projection-tables.js +73 -0
- package/dist/stack/redis.d.ts +11 -0
- package/dist/stack/redis.js +38 -0
- package/dist/stack/request-helper.d.ts +35 -0
- package/dist/stack/request-helper.js +144 -0
- package/dist/stack/table-helpers.d.ts +32 -0
- package/dist/stack/table-helpers.js +138 -0
- package/dist/stack/test-stack.d.ts +161 -0
- package/dist/stack/test-stack.js +398 -0
- package/dist/stack/test-users.d.ts +33 -0
- package/dist/stack/test-users.js +29 -0
- package/dist/testing/access-assertions.d.ts +2 -0
- package/dist/testing/access-assertions.js +13 -0
- package/dist/testing/assertions.d.ts +10 -0
- package/dist/testing/assertions.js +22 -0
- package/dist/testing/boot-validator-fixture.d.ts +3 -0
- package/dist/testing/boot-validator-fixture.js +101 -0
- package/dist/testing/closed-connection-error.d.ts +7 -0
- package/dist/testing/closed-connection-error.js +47 -0
- package/dist/testing/db-cleanup.d.ts +9 -0
- package/dist/testing/db-cleanup.js +31 -0
- package/dist/testing/e2e-generator.d.ts +49 -0
- package/dist/testing/e2e-generator.js +377 -0
- package/dist/testing/expect-error.d.ts +2 -0
- package/dist/testing/expect-error.js +22 -0
- package/dist/testing/file-provider-contract.d.ts +2 -0
- package/dist/testing/file-provider-contract.js +102 -0
- package/dist/testing/handler-context.d.ts +4 -0
- package/dist/testing/handler-context.js +72 -0
- package/dist/testing/http-cookies.d.ts +7 -0
- package/dist/testing/http-cookies.js +47 -0
- package/dist/testing/index.d.ts +24 -0
- package/dist/testing/index.js +32 -0
- package/dist/testing/late-bound.d.ts +9 -0
- package/dist/testing/late-bound.js +31 -0
- package/dist/testing/multipart-helper.d.ts +22 -0
- package/dist/testing/multipart-helper.js +77 -0
- package/dist/testing/mutable-master-key-provider.d.ts +7 -0
- package/dist/testing/mutable-master-key-provider.js +35 -0
- package/dist/testing/observability-recorder.d.ts +9 -0
- package/dist/testing/observability-recorder.js +29 -0
- package/dist/testing/real-providers.d.ts +3 -0
- package/dist/testing/real-providers.js +21 -0
- package/dist/testing/seed.d.ts +9 -0
- package/dist/testing/seed.js +21 -0
- package/dist/testing/shared-entities.d.ts +256 -0
- package/dist/testing/shared-entities.js +56 -0
- package/dist/testing/utils.d.ts +1 -0
- package/dist/testing/utils.js +1 -0
- package/dist/testing/wait-for.d.ts +20 -0
- package/dist/testing/wait-for.js +46 -0
- package/dist/testing/without-ambient-temporal.d.ts +5 -0
- package/dist/testing/without-ambient-temporal.js +17 -0
- package/dist/time/boot-tz-warning.d.ts +5 -0
- package/dist/time/boot-tz-warning.js +24 -0
- package/dist/time/geo-tz.js +1 -0
- package/dist/time/iana.d.ts +1 -0
- package/dist/time/iana.js +18 -0
- package/dist/time/index.d.ts +6 -0
- package/dist/time/index.js +15 -0
- package/dist/time/legacy-date.d.ts +5 -0
- package/dist/time/legacy-date.js +15 -0
- package/dist/time/polyfill.d.ts +9 -0
- package/dist/time/polyfill.js +52 -0
- package/dist/time/tz-context.d.ts +13 -0
- package/dist/time/tz-context.js +80 -0
- package/dist/ui-types/app-schema.d.ts +26 -0
- package/dist/ui-types/app-schema.js +9 -0
- package/dist/ui-types/formality.d.ts +2 -0
- package/dist/ui-types/formality.js +5 -0
- package/dist/ui-types/index.d.ts +22 -0
- package/dist/ui-types/index.js +31 -0
- package/dist/ui-types/list-row-meta.d.ts +18 -0
- package/dist/ui-types/list-row-meta.js +65 -0
- package/dist/ui-types/plural.d.ts +12 -0
- package/dist/ui-types/plural.js +57 -0
- package/dist/upgrade-cli.d.ts +11 -0
- package/dist/upgrade-cli.js +532 -0
- package/dist/utils/assert.d.ts +1 -0
- package/dist/utils/assert.js +18 -0
- package/dist/utils/case.d.ts +1 -0
- package/dist/utils/case.js +6 -0
- package/dist/utils/compare.d.ts +1 -0
- package/dist/utils/compare.js +10 -0
- package/dist/utils/env-parse.d.ts +1 -0
- package/dist/utils/env-parse.js +13 -0
- package/dist/utils/ids.d.ts +2 -0
- package/dist/utils/ids.js +23 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/is-plain-object.d.ts +2 -0
- package/dist/utils/is-plain-object.js +4 -0
- package/dist/utils/parse-string-array-json.d.ts +2 -0
- package/dist/utils/parse-string-array-json.js +11 -0
- package/dist/utils/safe-json.d.ts +17 -0
- package/dist/utils/safe-json.js +47 -0
- package/dist/utils/serialization.d.ts +1 -0
- package/dist/utils/serialization.js +13 -0
- package/package.json +274 -93
- package/src/changes.json +42 -0
- package/src/scripts/codemod/pii-personal-migration.ts +5 -5
- package/src/__tests__/anonymous-access.integration.test.ts +0 -513
- package/src/__tests__/consumer-cli.integration.test.ts +0 -172
- package/src/__tests__/derived-fields.integration.test.ts +0 -126
- package/src/__tests__/entity-list-limits.integration.test.ts +0 -84
- package/src/__tests__/entity-permalink-open.integration.test.ts +0 -99
- package/src/__tests__/error-contract.integration.test.ts +0 -436
- package/src/__tests__/field-access.integration.test.ts +0 -273
- package/src/__tests__/fixtures/migrate-cross-tenant/manual-only.expected.ts +0 -44
- package/src/__tests__/fixtures/migrate-cross-tenant/manual-only.input.ts +0 -44
- package/src/__tests__/fixtures/migrate-cross-tenant/rewrite.expected.ts +0 -41
- package/src/__tests__/fixtures/migrate-cross-tenant/rewrite.input.ts +0 -41
- package/src/__tests__/fixtures/migrate-db-raw/global-fetch.expected.ts +0 -9
- package/src/__tests__/fixtures/migrate-db-raw/global-fetch.input.ts +0 -10
- package/src/__tests__/fixtures/migrate-db-raw/global-select.expected.ts +0 -6
- package/src/__tests__/fixtures/migrate-db-raw/global-select.input.ts +0 -12
- package/src/__tests__/fixtures/migrate-db-raw/import-pruning.expected.ts +0 -12
- package/src/__tests__/fixtures/migrate-db-raw/import-pruning.input.ts +0 -12
- package/src/__tests__/fixtures/migrate-db-raw/manual-only.expected.ts +0 -26
- package/src/__tests__/fixtures/migrate-db-raw/manual-only.input.ts +0 -26
- package/src/__tests__/fixtures/migrate-db-raw/own-tenant-const-shorthand.expected.ts +0 -10
- package/src/__tests__/fixtures/migrate-db-raw/own-tenant-const-shorthand.input.ts +0 -11
- package/src/__tests__/fixtures/migrate-db-raw/own-tenant-event.expected.ts +0 -9
- package/src/__tests__/fixtures/migrate-db-raw/own-tenant-event.input.ts +0 -15
- package/src/__tests__/fixtures/migrate-open-to-all/manual-only.expected.ts +0 -16
- package/src/__tests__/fixtures/migrate-open-to-all/manual-only.input.ts +0 -16
- package/src/__tests__/fixtures/migrate-open-to-all/test-nested-shorthand.expected.ts +0 -12
- package/src/__tests__/fixtures/migrate-open-to-all/test-nested-shorthand.input.ts +0 -12
- package/src/__tests__/fixtures/migrate-open-to-all/test-simple.expected.ts +0 -7
- package/src/__tests__/fixtures/migrate-open-to-all/test-simple.input.ts +0 -7
- package/src/__tests__/full-stack.integration.test.ts +0 -924
- package/src/__tests__/migrate-cross-tenant-codemod.test.ts +0 -106
- package/src/__tests__/migrate-db-raw-codemod.test.ts +0 -132
- package/src/__tests__/migrate-open-to-all-codemod.test.ts +0 -84
- package/src/__tests__/ownership-where-write-path.integration.test.ts +0 -147
- package/src/__tests__/ownership.integration.test.ts +0 -454
- package/src/__tests__/pii-personal-migration-report-codemod.test.ts +0 -160
- package/src/__tests__/reference-data.integration.test.ts +0 -243
- package/src/__tests__/related-list-parent-filter.integration.test.ts +0 -103
- package/src/__tests__/schema-cli-kms-slots.integration.test.ts +0 -172
- package/src/__tests__/schema-cli-rebuild.integration.test.ts +0 -189
- package/src/__tests__/schema-cli-status.integration.test.ts +0 -96
- package/src/__tests__/schema-cli-temporal-polyfill.test.ts +0 -48
- package/src/__tests__/schema-cli.integration.test.ts +0 -485
- package/src/__tests__/store-table.integration.test.ts +0 -94
- package/src/__tests__/transition-guard.integration.test.ts +0 -342
- package/src/__tests__/unprocessable-error-details-reason-codemod.test.ts +0 -205
- package/src/__tests__/upgrade-cli.test.ts +0 -723
- package/src/api/__tests__/api-constants-completeness.test.ts +0 -63
- package/src/api/__tests__/api.test.ts +0 -869
- package/src/api/__tests__/auth-middleware-anonymous-access-boot.test.ts +0 -40
- package/src/api/__tests__/auth-middleware-transport.test.ts +0 -102
- package/src/api/__tests__/auth-routes-cookie.test.ts +0 -330
- package/src/api/__tests__/auth-routes-invalid-body-invite.test.ts +0 -263
- package/src/api/__tests__/auth-routes-mfa-preauth-confirm.test.ts +0 -230
- package/src/api/__tests__/auth-routes-mfa-preauth-enable-start.test.ts +0 -263
- package/src/api/__tests__/auth-routes-mfa-verify.test.ts +0 -221
- package/src/api/__tests__/auth-routes-trusted-proxy.test.ts +0 -164
- package/src/api/__tests__/batch.integration.test.ts +0 -548
- package/src/api/__tests__/body-limit.test.ts +0 -184
- package/src/api/__tests__/client-ip.test.ts +0 -184
- package/src/api/__tests__/csrf-constants-sync.test.ts +0 -20
- package/src/api/__tests__/csrf-middleware.test.ts +0 -97
- package/src/api/__tests__/dispatcher-live.integration.test.ts +0 -292
- package/src/api/__tests__/extra-route-rejection.test.ts +0 -38
- package/src/api/__tests__/extra-routes.integration.test.ts +0 -663
- package/src/api/__tests__/http-cache.test.ts +0 -173
- package/src/api/__tests__/http-route-entry.integration.test.ts +0 -114
- package/src/api/__tests__/http-route-rate-limit.integration.test.ts +0 -148
- package/src/api/__tests__/jwt.test.ts +0 -316
- package/src/api/__tests__/login-rate-limiter-sweep.test.ts +0 -50
- package/src/api/__tests__/metrics-endpoint.test.ts +0 -132
- package/src/api/__tests__/nested-write-ownership.integration.test.ts +0 -268
- package/src/api/__tests__/nested-write.integration.test.ts +0 -210
- package/src/api/__tests__/origin-middleware.integration.test.ts +0 -273
- package/src/api/__tests__/origin-middleware.test.ts +0 -279
- package/src/api/__tests__/pat-route-guard.integration.test.ts +0 -126
- package/src/api/__tests__/pat-scope.test.ts +0 -36
- package/src/api/__tests__/pii-leak-guard.integration.test.ts +0 -112
- package/src/api/__tests__/post-auth-landing.test.ts +0 -100
- package/src/api/__tests__/readiness.test.ts +0 -76
- package/src/api/__tests__/redis-login-rate-limiter.integration.test.ts +0 -138
- package/src/api/__tests__/redis-sse-broker.integration.test.ts +0 -321
- package/src/api/__tests__/request-id-middleware.test.ts +0 -229
- package/src/api/__tests__/request-locale.integration.test.ts +0 -146
- package/src/api/__tests__/schema-route.integration.test.ts +0 -157
- package/src/api/__tests__/server-boot-guards.test.ts +0 -308
- package/src/api/__tests__/server-error-logging.test.ts +0 -342
- package/src/api/__tests__/server-jwt-ttl.test.ts +0 -58
- package/src/api/__tests__/sse-broker.test.ts +0 -267
- package/src/api/__tests__/sse-route.test.ts +0 -245
- package/src/api/__tests__/stream-escape-hatch.integration.test.ts +0 -203
- package/src/api/__tests__/websocket-route.test.ts +0 -552
- package/src/api/anonymous-cookie.ts +0 -61
- package/src/api/api-constants.ts +0 -153
- package/src/api/auth-middleware.ts +0 -694
- package/src/api/auth-routes.ts +0 -1590
- package/src/api/client-ip.ts +0 -131
- package/src/api/csrf-middleware.ts +0 -74
- package/src/api/extra-route.ts +0 -178
- package/src/api/http-cache.ts +0 -122
- package/src/api/index.ts +0 -117
- package/src/api/jwt.ts +0 -277
- package/src/api/observability-middleware.ts +0 -89
- package/src/api/origin-middleware.ts +0 -137
- package/src/api/pat-route-guard.ts +0 -51
- package/src/api/pat-scope.ts +0 -14
- package/src/api/pii-leak-guard.ts +0 -46
- package/src/api/post-auth-landing.ts +0 -105
- package/src/api/readiness.ts +0 -132
- package/src/api/redis-sse-broker.ts +0 -171
- package/src/api/request-context.ts +0 -137
- package/src/api/request-id-middleware.ts +0 -138
- package/src/api/route-registrars.ts +0 -193
- package/src/api/routes.ts +0 -432
- package/src/api/server.ts +0 -1550
- package/src/api/sse-broker.ts +0 -175
- package/src/api/sse-route.ts +0 -74
- package/src/api/tokens.ts +0 -16
- package/src/api/websocket-route.ts +0 -327
- package/src/arg-parser.ts +0 -66
- package/src/auth/__tests__/roles.test.ts +0 -24
- package/src/auth/index.ts +0 -7
- package/src/auth/roles.ts +0 -42
- package/src/bun-db/__tests__/PATTERN.md +0 -72
- package/src/bun-db/__tests__/_helpers.ts +0 -104
- package/src/bun-db/__tests__/batch-methods.integration.test.ts +0 -143
- package/src/bun-db/__tests__/batch-methods.test.ts +0 -21
- package/src/bun-db/__tests__/bun-test-db.ts +0 -19
- package/src/bun-db/__tests__/closed-connection-retry.integration.test.ts +0 -159
- package/src/bun-db/__tests__/coerce-row-plain-date.test.ts +0 -70
- package/src/bun-db/__tests__/coerce-row-temporal.test.ts +0 -41
- package/src/bun-db/__tests__/column-types.integration.test.ts +0 -132
- package/src/bun-db/__tests__/compound-types.integration.test.ts +0 -134
- package/src/bun-db/__tests__/decimal-field.integration.test.ts +0 -81
- package/src/bun-db/__tests__/extract-table-info.test.ts +0 -71
- package/src/bun-db/__tests__/jsonb-edge-cases.integration.test.ts +0 -235
- package/src/bun-db/__tests__/postgres-closed-socket-write.integration.test.ts +0 -87
- package/src/bun-db/__tests__/query-guards.test.ts +0 -111
- package/src/bun-db/__tests__/run-in-savepoint-if-supported.integration.test.ts +0 -47
- package/src/bun-db/__tests__/select-many-retry.integration.test.ts +0 -138
- package/src/bun-db/__tests__/smoke.integration.test.ts +0 -43
- package/src/bun-db/__tests__/sql-expr-brand.test.ts +0 -115
- package/src/bun-db/__tests__/sql-methods.integration.test.ts +0 -231
- package/src/bun-db/__tests__/where-patterns.integration.test.ts +0 -213
- package/src/bun-db/__tests__/write-brand.test.ts +0 -72
- package/src/bun-db/connection.ts +0 -87
- package/src/bun-db/index.ts +0 -36
- package/src/bun-db/query.ts +0 -1259
- package/src/compliance/__tests__/duration-spec.test.ts +0 -72
- package/src/compliance/__tests__/profiles.test.ts +0 -308
- package/src/compliance/__tests__/sub-processors.test.ts +0 -149
- package/src/compliance/duration-spec.ts +0 -44
- package/src/compliance/index.ts +0 -31
- package/src/compliance/override-schema.ts +0 -136
- package/src/compliance/profiles.ts +0 -424
- package/src/compliance/sub-processors.ts +0 -165
- package/src/consumer-cli.ts +0 -134
- package/src/crypto/__tests__/blind-index.test.ts +0 -132
- package/src/crypto/__tests__/event-pii.test.ts +0 -417
- package/src/crypto/__tests__/kek-rotation.integration.test.ts +0 -180
- package/src/crypto/__tests__/kek-source.test.ts +0 -441
- package/src/crypto/__tests__/kms-adapter-contract.ts +0 -134
- package/src/crypto/__tests__/kms-adapter.contract.test.ts +0 -4
- package/src/crypto/__tests__/kms-wiring.test.ts +0 -203
- package/src/crypto/__tests__/pg-kms-adapter.integration.test.ts +0 -154
- package/src/crypto/__tests__/pii-field-encryption.test.ts +0 -403
- package/src/crypto/__tests__/request-kms-cache.test.ts +0 -74
- package/src/crypto/__tests__/subject-id-schema.test.ts +0 -60
- package/src/crypto/__tests__/subject-key-record.test.ts +0 -109
- package/src/crypto/__tests__/subject-resolver.test.ts +0 -250
- package/src/crypto/__tests__/system-event-pii.test.ts +0 -77
- package/src/crypto/blind-index.ts +0 -118
- package/src/crypto/ciphertext-pattern.ts +0 -19
- package/src/crypto/event-pii.ts +0 -99
- package/src/crypto/in-memory-kms-adapter.ts +0 -50
- package/src/crypto/index.ts +0 -84
- package/src/crypto/is-self-pii-field.ts +0 -8
- package/src/crypto/kek-source.ts +0 -180
- package/src/crypto/kms-adapter.ts +0 -51
- package/src/crypto/kms-wiring.ts +0 -208
- package/src/crypto/pg-kms-adapter.ts +0 -303
- package/src/crypto/pii-field-encryption.ts +0 -266
- package/src/crypto/request-kms-cache.ts +0 -38
- package/src/crypto/subject-resolver.ts +0 -232
- package/src/crypto/system-event-pii.ts +0 -57
- package/src/db/__tests__/apply-entity-event-removed-column.integration.test.ts +0 -109
- package/src/db/__tests__/apply-entity-event-tenant.integration.test.ts +0 -159
- package/src/db/__tests__/assert-exists-in.integration.test.ts +0 -120
- package/src/db/__tests__/assert-no-unreachable-live-rows.integration.test.ts +0 -190
- package/src/db/__tests__/big-int-field.test.ts +0 -132
- package/src/db/__tests__/blind-index.integration.test.ts +0 -280
- package/src/db/__tests__/build-filter-where.test.ts +0 -50
- package/src/db/__tests__/collect-table-metas.test.ts +0 -188
- package/src/db/__tests__/column-ddl.integration.test.ts +0 -122
- package/src/db/__tests__/compound-types.test.ts +0 -126
- package/src/db/__tests__/config-seed.integration.test.ts +0 -292
- package/src/db/__tests__/connection-close-outage.integration.test.ts +0 -110
- package/src/db/__tests__/connection-options.test.ts +0 -68
- package/src/db/__tests__/cursor.test.ts +0 -42
- package/src/db/__tests__/decimal-field.test.ts +0 -109
- package/src/db/__tests__/dialect-instant.test.ts +0 -47
- package/src/db/__tests__/eagerload.integration.test.ts +0 -374
- package/src/db/__tests__/entity-field-encryption.test.ts +0 -74
- package/src/db/__tests__/entity-table-from-registry.test.ts +0 -79
- package/src/db/__tests__/entity-table-meta-source.test.ts +0 -92
- package/src/db/__tests__/entity-table-types.test.ts +0 -162
- package/src/db/__tests__/event-store-executor-context.pii-roundtrip.test.ts +0 -67
- package/src/db/__tests__/event-store-executor-global-tenancy.integration.test.ts +0 -73
- package/src/db/__tests__/event-store-executor-list.integration.test.ts +0 -791
- package/src/db/__tests__/event-store-executor-money-rehydrate.integration.test.ts +0 -153
- package/src/db/__tests__/event-store-executor-reference-search.integration.test.ts +0 -643
- package/src/db/__tests__/event-store-executor-reference-sort.integration.test.ts +0 -256
- package/src/db/__tests__/event-store-executor-write-verbs.integration.test.ts +0 -788
- package/src/db/__tests__/event-store-executor.integration.test.ts +0 -844
- package/src/db/__tests__/event-store-system-stream.integration.test.ts +0 -96
- package/src/db/__tests__/feature-table-sources.test.ts +0 -34
- package/src/db/__tests__/implicit-projection-equivalence.integration.test.ts +0 -393
- package/src/db/__tests__/instant-to-driver-temporal.test.ts +0 -21
- package/src/db/__tests__/list-filter-field-access.integration.test.ts +0 -218
- package/src/db/__tests__/list-pagination.test.ts +0 -28
- package/src/db/__tests__/list-row-meta-drift.test.ts +0 -15
- package/src/db/__tests__/located-timestamp.test.ts +0 -203
- package/src/db/__tests__/managed-recreate.integration.test.ts +0 -78
- package/src/db/__tests__/migrate-generator.test.ts +0 -383
- package/src/db/__tests__/migrate-runner.test.ts +0 -118
- package/src/db/__tests__/money.test.ts +0 -291
- package/src/db/__tests__/multi-row-insert.integration.test.ts +0 -88
- package/src/db/__tests__/number-field-fractional.integration.test.ts +0 -58
- package/src/db/__tests__/parent-ref-clause.test.ts +0 -213
- package/src/db/__tests__/parse-auto-verb.test.ts +0 -70
- package/src/db/__tests__/pg-error.test.ts +0 -57
- package/src/db/__tests__/rebuild-marker.test.ts +0 -180
- package/src/db/__tests__/replay-migration-sql.test.ts +0 -401
- package/src/db/__tests__/required-not-null-migration-safety.integration.test.ts +0 -109
- package/src/db/__tests__/run-in-own-transaction.integration.test.ts +0 -166
- package/src/db/__tests__/schema-inspection.test.ts +0 -27
- package/src/db/__tests__/schema-migration.integration.test.ts +0 -354
- package/src/db/__tests__/source-shadow-create.integration.test.ts +0 -59
- package/src/db/__tests__/system-db-view-export.test.ts +0 -107
- package/src/db/__tests__/table-builder-indexes.test.ts +0 -189
- package/src/db/__tests__/table-builder-meta-lockstep.test.ts +0 -224
- package/src/db/__tests__/table-builder-required.test.ts +0 -214
- package/src/db/__tests__/tenant-db-convention-cross-tenant.test.ts +0 -72
- package/src/db/__tests__/tenant-db-count.integration.test.ts +0 -92
- package/src/db/__tests__/tenant-db-declared-unsafe-raw.test.ts +0 -163
- package/src/db/__tests__/tenant-db-global.integration.test.ts +0 -134
- package/src/db/__tests__/tenant-db-global.test.ts +0 -352
- package/src/db/__tests__/tenant-db-no-raw.test.ts +0 -85
- package/src/db/__tests__/tenant-db-where-merge.integration.test.ts +0 -123
- package/src/db/__tests__/tenant-db-where-merge.test.ts +0 -164
- package/src/db/__tests__/tenant-db.integration.test.ts +0 -575
- package/src/db/__tests__/unchecked-system-db.test.ts +0 -259
- package/src/db/__tests__/unique-violation-mapping.integration.test.ts +0 -200
- package/src/db/__tests__/with-systemdb-unsafe-raw-grant.test.ts +0 -71
- package/src/db/api.ts +0 -52
- package/src/db/apply-entity-event.ts +0 -211
- package/src/db/assert-exists-in.ts +0 -52
- package/src/db/blind-index-cleanup.ts +0 -145
- package/src/db/bun-provider.ts +0 -42
- package/src/db/collect-table-metas.ts +0 -98
- package/src/db/compound-types.ts +0 -47
- package/src/db/config-seed.ts +0 -104
- package/src/db/connection.ts +0 -57
- package/src/db/cursor.ts +0 -47
- package/src/db/dialect.ts +0 -544
- package/src/db/eagerload.ts +0 -260
- package/src/db/entity-field-encryption.ts +0 -158
- package/src/db/entity-table-from-registry.ts +0 -31
- package/src/db/entity-table-meta-types.ts +0 -2
- package/src/db/entity-table-meta.ts +0 -491
- package/src/db/event-store-executor-context.ts +0 -510
- package/src/db/event-store-executor-read.ts +0 -916
- package/src/db/event-store-executor-write.ts +0 -920
- package/src/db/event-store-executor.ts +0 -50
- package/src/db/feature-table-sources.ts +0 -35
- package/src/db/index.ts +0 -162
- package/src/db/located-timestamp.ts +0 -118
- package/src/db/migrate-generator.ts +0 -549
- package/src/db/migrate-runner.ts +0 -348
- package/src/db/money.ts +0 -211
- package/src/db/parent-ref-clause.ts +0 -182
- package/src/db/pg-error.ts +0 -74
- package/src/db/postgres-provider.ts +0 -28
- package/src/db/queries/__tests__/event-store-idempotency-index.integration.test.ts +0 -78
- package/src/db/queries/__tests__/shadow-swap.test.ts +0 -43
- package/src/db/queries/__tests__/unsafe-read-retrying.integration.test.ts +0 -115
- package/src/db/queries/advisory-lock.ts +0 -11
- package/src/db/queries/backfill-pii.ts +0 -479
- package/src/db/queries/ddl.ts +0 -45
- package/src/db/queries/entity-read.ts +0 -15
- package/src/db/queries/es-ops.ts +0 -17
- package/src/db/queries/event-consumer.ts +0 -418
- package/src/db/queries/event-store-admin.ts +0 -130
- package/src/db/queries/event-store-transfer.ts +0 -73
- package/src/db/queries/event-store.ts +0 -354
- package/src/db/queries/projection-rebuild.ts +0 -104
- package/src/db/queries/raw-sql.ts +0 -28
- package/src/db/queries/seed-context.ts +0 -62
- package/src/db/queries/shadow-swap.ts +0 -378
- package/src/db/queries/table-ops.ts +0 -11
- package/src/db/queries/test-stack.ts +0 -32
- package/src/db/query-api.ts +0 -24
- package/src/db/query.ts +0 -35
- package/src/db/rebuild-marker.ts +0 -103
- package/src/db/reference-data.ts +0 -73
- package/src/db/render-ddl.ts +0 -57
- package/src/db/replay-migration-sql.ts +0 -257
- package/src/db/schema-inspection.ts +0 -81
- package/src/db/table-builder.ts +0 -692
- package/src/db/tenant-db-runner.ts +0 -23
- package/src/db/tenant-db.ts +0 -727
- package/src/derivatives/__tests__/derivatives-context.integration.test.ts +0 -231
- package/src/derivatives/__tests__/derivatives-context.test.ts +0 -369
- package/src/derivatives/__tests__/field-variants.test.ts +0 -62
- package/src/derivatives/__tests__/variant-key.test.ts +0 -183
- package/src/derivatives/__tests__/variant-route.integration.test.ts +0 -268
- package/src/derivatives/delete-stored-file.ts +0 -86
- package/src/derivatives/derivatives-context.ts +0 -314
- package/src/derivatives/field-variants.ts +0 -20
- package/src/derivatives/index.ts +0 -14
- package/src/derivatives/variant-key.ts +0 -108
- package/src/engine/__tests__/_pipeline-test-utils.ts +0 -23
- package/src/engine/__tests__/auth-claims-registrar.test.ts +0 -74
- package/src/engine/__tests__/boot-validator-action-wiring.test.ts +0 -362
- package/src/engine/__tests__/boot-validator-api-exposure.test.ts +0 -142
- package/src/engine/__tests__/boot-validator-boot-check.test.ts +0 -104
- package/src/engine/__tests__/boot-validator-dashboard.test.ts +0 -381
- package/src/engine/__tests__/boot-validator-detail-for.test.ts +0 -106
- package/src/engine/__tests__/boot-validator-entity-list.test.ts +0 -120
- package/src/engine/__tests__/boot-validator-gdpr-storage.test.ts +0 -85
- package/src/engine/__tests__/boot-validator-i18n-keys.test.ts +0 -153
- package/src/engine/__tests__/boot-validator-located-timestamps.test.ts +0 -92
- package/src/engine/__tests__/boot-validator-nav-area.test.ts +0 -116
- package/src/engine/__tests__/boot-validator-pii-retention.test.ts +0 -994
- package/src/engine/__tests__/boot-validator-projection-list.test.ts +0 -629
- package/src/engine/__tests__/boot-validator-query-output-schema.test.ts +0 -578
- package/src/engine/__tests__/boot-validator-query-refs.test.ts +0 -151
- package/src/engine/__tests__/boot-validator-ref-entity.test.ts +0 -196
- package/src/engine/__tests__/boot-validator-s0-integration.test.ts +0 -172
- package/src/engine/__tests__/boot-validator.test.ts +0 -5984
- package/src/engine/__tests__/build-app-schema-settings-hub.test.ts +0 -246
- package/src/engine/__tests__/build-app-schema-url-prefill.test.ts +0 -222
- package/src/engine/__tests__/build-app-schema.test.ts +0 -1141
- package/src/engine/__tests__/build-config-feature-schema-extension-selector.test.ts +0 -395
- package/src/engine/__tests__/build-config-feature-schema-secrets.test.ts +0 -188
- package/src/engine/__tests__/build-config-feature-schema.test.ts +0 -511
- package/src/engine/__tests__/build-target.test.ts +0 -127
- package/src/engine/__tests__/changeset-changes.test.ts +0 -64
- package/src/engine/__tests__/claim-keys.test.ts +0 -274
- package/src/engine/__tests__/codemod-pipeline.test.ts +0 -682
- package/src/engine/__tests__/config-helpers.test.ts +0 -309
- package/src/engine/__tests__/content-collection.test.ts +0 -307
- package/src/engine/__tests__/decimal-field.test.ts +0 -59
- package/src/engine/__tests__/dedupe-features.test.ts +0 -85
- package/src/engine/__tests__/define-feature-entity-mapping.test.ts +0 -53
- package/src/engine/__tests__/define-roles.test.ts +0 -21
- package/src/engine/__tests__/define-workflow.test.ts +0 -79
- package/src/engine/__tests__/describe-workflow-step-error.test.ts +0 -17
- package/src/engine/__tests__/duration-utils.test.ts +0 -16
- package/src/engine/__tests__/effective-features.test.ts +0 -86
- package/src/engine/__tests__/embedded-derived.test.ts +0 -35
- package/src/engine/__tests__/engine.test.ts +0 -2406
- package/src/engine/__tests__/entity-create-caller-id.integration.test.ts +0 -87
- package/src/engine/__tests__/entity-exclude-fields.integration.test.ts +0 -134
- package/src/engine/__tests__/entity-handlers-escape-hatch.test.ts +0 -91
- package/src/engine/__tests__/entity-handlers.test.ts +0 -562
- package/src/engine/__tests__/entity-presave-wiring.integration.test.ts +0 -153
- package/src/engine/__tests__/entity-restore-tenant-isolation.integration.test.ts +0 -168
- package/src/engine/__tests__/entity-write-crosstenant.integration.test.ts +0 -317
- package/src/engine/__tests__/event-helpers.test.ts +0 -68
- package/src/engine/__tests__/event-migration-declarative.test.ts +0 -67
- package/src/engine/__tests__/event-type-map-augmentation.test.ts +0 -24
- package/src/engine/__tests__/extend-entity-projection.test.ts +0 -133
- package/src/engine/__tests__/extends-registrar.test.ts +0 -279
- package/src/engine/__tests__/factories-long-text.test.ts +0 -95
- package/src/engine/__tests__/factories-number-unit.test.ts +0 -23
- package/src/engine/__tests__/factories-personal.test.ts +0 -216
- package/src/engine/__tests__/factories-time.test.ts +0 -94
- package/src/engine/__tests__/feature-crud-shorthand.test.ts +0 -73
- package/src/engine/__tests__/feature-crud-verb-access.integration.test.ts +0 -83
- package/src/engine/__tests__/feature-manifest.test.ts +0 -137
- package/src/engine/__tests__/field-access.test.ts +0 -65
- package/src/engine/__tests__/field-predicates.test.ts +0 -48
- package/src/engine/__tests__/form-money-currency-types.test.ts +0 -90
- package/src/engine/__tests__/hook-identity-switch-grant.test.ts +0 -188
- package/src/engine/__tests__/hook-phases.test.ts +0 -172
- package/src/engine/__tests__/http-route-anonymous-required.test.ts +0 -43
- package/src/engine/__tests__/identifiers.test.ts +0 -35
- package/src/engine/__tests__/lifecycle-hooks.test.ts +0 -243
- package/src/engine/__tests__/membership-roles.test.ts +0 -67
- package/src/engine/__tests__/metric-navigate-tab.test.ts +0 -167
- package/src/engine/__tests__/multiselect-filter.integration.test.ts +0 -141
- package/src/engine/__tests__/nav.test.ts +0 -497
- package/src/engine/__tests__/no-return-guard.test.ts +0 -17
- package/src/engine/__tests__/ownership.test.ts +0 -475
- package/src/engine/__tests__/parse-ref-target.test.ts +0 -43
- package/src/engine/__tests__/pipeline-engine.test.ts +0 -215
- package/src/engine/__tests__/pipeline-handler.integration.test.ts +0 -880
- package/src/engine/__tests__/pipeline-observability.integration.test.ts +0 -142
- package/src/engine/__tests__/pipeline-performance.integration.test.ts +0 -152
- package/src/engine/__tests__/pipeline-sub-pipelines.test.ts +0 -288
- package/src/engine/__tests__/post-query-hook.test.ts +0 -144
- package/src/engine/__tests__/project-app-schema-for-roles.test.ts +0 -500
- package/src/engine/__tests__/projection-detail-actions.test.ts +0 -145
- package/src/engine/__tests__/projection-detail-singleton.test.ts +0 -86
- package/src/engine/__tests__/projection-detail-tabs.test.ts +0 -314
- package/src/engine/__tests__/projection-helpers.test.ts +0 -75
- package/src/engine/__tests__/projection-list-filter.integration.test.ts +0 -115
- package/src/engine/__tests__/projection.test.ts +0 -191
- package/src/engine/__tests__/qualified-name.test.ts +0 -306
- package/src/engine/__tests__/read-steps-tenant-filter.integration.test.ts +0 -215
- package/src/engine/__tests__/registrar-object-form.test.ts +0 -141
- package/src/engine/__tests__/registry.test.ts +0 -326
- package/src/engine/__tests__/required-surface-keys.test.ts +0 -477
- package/src/engine/__tests__/resolve-config-or-param.test.ts +0 -315
- package/src/engine/__tests__/role-assignment.test.ts +0 -71
- package/src/engine/__tests__/row-action-navigate-tab.test.ts +0 -107
- package/src/engine/__tests__/run-in.test.ts +0 -38
- package/src/engine/__tests__/schema-builder-date-bounds.test.ts +0 -47
- package/src/engine/__tests__/schema-builder.test.ts +0 -1211
- package/src/engine/__tests__/screen-definition-exports.test.ts +0 -102
- package/src/engine/__tests__/screen-filter-ops.test.ts +0 -31
- package/src/engine/__tests__/screen-helpers.test.ts +0 -52
- package/src/engine/__tests__/screen.test.ts +0 -1684
- package/src/engine/__tests__/search-payload-extension.test.ts +0 -288
- package/src/engine/__tests__/soft-delete-cleanup-job-tenant-db.integration.test.ts +0 -82
- package/src/engine/__tests__/soft-delete-cleanup.test.ts +0 -167
- package/src/engine/__tests__/state-machine.test.ts +0 -148
- package/src/engine/__tests__/steps-aggregate-append-event.test.ts +0 -115
- package/src/engine/__tests__/steps-aggregate-create.test.ts +0 -92
- package/src/engine/__tests__/steps-aggregate-update.test.ts +0 -127
- package/src/engine/__tests__/steps-call-feature.test.ts +0 -123
- package/src/engine/__tests__/steps-mail-send.test.ts +0 -137
- package/src/engine/__tests__/steps-read.test.ts +0 -332
- package/src/engine/__tests__/steps-resolver-utils.test.ts +0 -50
- package/src/engine/__tests__/steps-unsafe-projection-delete.test.ts +0 -77
- package/src/engine/__tests__/steps-unsafe-projection-upsert.test.ts +0 -131
- package/src/engine/__tests__/steps-webhook-send.test.ts +0 -143
- package/src/engine/__tests__/steps-workflow.test.ts +0 -353
- package/src/engine/__tests__/store-table.test.ts +0 -247
- package/src/engine/__tests__/system-user.test.ts +0 -57
- package/src/engine/__tests__/tier-resolver-extension.test.ts +0 -69
- package/src/engine/__tests__/toolbar-navigate-tab.test.ts +0 -233
- package/src/engine/__tests__/tree-actions-patterns.test.ts +0 -163
- package/src/engine/__tests__/validate-custom-screen-write-qns.test.ts +0 -43
- package/src/engine/__tests__/validate-projection-allowlist.test.ts +0 -498
- package/src/engine/__tests__/validation-hooks.test.ts +0 -77
- package/src/engine/__tests__/where-rule-lint.test.ts +0 -79
- package/src/engine/__tests__/write-handler-qn-extract.test.ts +0 -50
- package/src/engine/access.ts +0 -27
- package/src/engine/active-membership.ts +0 -70
- package/src/engine/boot-validator/__tests__/access-declarations.test.ts +0 -707
- package/src/engine/boot-validator/__tests__/access-roles.test.ts +0 -84
- package/src/engine/boot-validator/__tests__/action-icon.test.ts +0 -81
- package/src/engine/boot-validator/__tests__/anonymous-rate-limit-required.test.ts +0 -63
- package/src/engine/boot-validator/__tests__/config-deps.test.ts +0 -92
- package/src/engine/boot-validator/__tests__/global-tenancy.test.ts +0 -73
- package/src/engine/boot-validator/__tests__/i18n-keys.test.ts +0 -340
- package/src/engine/boot-validator/__tests__/nav.test.ts +0 -290
- package/src/engine/boot-validator/__tests__/no-all-role-in-handler-access.test.ts +0 -77
- package/src/engine/boot-validator/__tests__/ownership.test.ts +0 -87
- package/src/engine/boot-validator/__tests__/parent-ref.test.ts +0 -161
- package/src/engine/boot-validator/__tests__/rate-limit-disabled-reason.test.ts +0 -45
- package/src/engine/boot-validator/__tests__/record-owned.test.ts +0 -65
- package/src/engine/boot-validator/__tests__/security-baseline.test.ts +0 -107
- package/src/engine/boot-validator/__tests__/transfer-graph.test.ts +0 -138
- package/src/engine/boot-validator/access-declarations.ts +0 -211
- package/src/engine/boot-validator/access-roles.ts +0 -85
- package/src/engine/boot-validator/action-wiring.ts +0 -163
- package/src/engine/boot-validator/api-ext.ts +0 -81
- package/src/engine/boot-validator/boot-check.ts +0 -21
- package/src/engine/boot-validator/config-deps.ts +0 -246
- package/src/engine/boot-validator/custom-screen-write-qns.ts +0 -87
- package/src/engine/boot-validator/detail-screens.ts +0 -49
- package/src/engine/boot-validator/entity-handler.ts +0 -1011
- package/src/engine/boot-validator/entity-list-screens.ts +0 -100
- package/src/engine/boot-validator/gdpr-storage.ts +0 -59
- package/src/engine/boot-validator/global-tenancy.ts +0 -29
- package/src/engine/boot-validator/i18n-keys.ts +0 -101
- package/src/engine/boot-validator/index.ts +0 -301
- package/src/engine/boot-validator/nav.ts +0 -241
- package/src/engine/boot-validator/ownership.ts +0 -352
- package/src/engine/boot-validator/parent-ref.ts +0 -96
- package/src/engine/boot-validator/pii-retention.ts +0 -272
- package/src/engine/boot-validator/projection-list-screens.ts +0 -293
- package/src/engine/boot-validator/query-output-columns.ts +0 -273
- package/src/engine/boot-validator/query-refs.ts +0 -141
- package/src/engine/boot-validator/record-owned.ts +0 -21
- package/src/engine/boot-validator/screens.ts +0 -2604
- package/src/engine/boot-validator/security-baseline.ts +0 -26
- package/src/engine/boot-validator/transfer-graph.ts +0 -135
- package/src/engine/boot-validator/url-prefill-fields.ts +0 -178
- package/src/engine/boot-validator/workspaces.ts +0 -106
- package/src/engine/boot-validator/zod-shape.ts +0 -142
- package/src/engine/boot-validator.ts +0 -8
- package/src/engine/build-app-schema.ts +0 -540
- package/src/engine/build-config-feature-schema.ts +0 -815
- package/src/engine/build-target.ts +0 -99
- package/src/engine/changeset-changes.ts +0 -117
- package/src/engine/codemod/index.ts +0 -15
- package/src/engine/codemod/pipeline-codemod.ts +0 -641
- package/src/engine/config-helpers.ts +0 -217
- package/src/engine/constants.ts +0 -117
- package/src/engine/create-app.ts +0 -177
- package/src/engine/cross-tenant.test.ts +0 -32
- package/src/engine/cross-tenant.ts +0 -22
- package/src/engine/dedupe-features.ts +0 -46
- package/src/engine/define-feature.ts +0 -169
- package/src/engine/define-handler.ts +0 -194
- package/src/engine/define-roles.ts +0 -19
- package/src/engine/define-step.ts +0 -28
- package/src/engine/define-workflow.ts +0 -147
- package/src/engine/effective-features.ts +0 -97
- package/src/engine/embedded-derived.ts +0 -93
- package/src/engine/entity-handlers.ts +0 -782
- package/src/engine/escape-hatch-declaration.ts +0 -7
- package/src/engine/event-helpers.ts +0 -73
- package/src/engine/extension-names.ts +0 -242
- package/src/engine/extension-selector-plugins.ts +0 -24
- package/src/engine/extensions/__tests__/hook-ctx-db-tenant-scoped.test.ts +0 -76
- package/src/engine/extensions/escape-hatch-usage.ts +0 -16
- package/src/engine/extensions/storage-provider.ts +0 -16
- package/src/engine/extensions/tenant-data.ts +0 -34
- package/src/engine/extensions/tenant-resource.ts +0 -40
- package/src/engine/extensions/user-data.ts +0 -181
- package/src/engine/factories.ts +0 -559
- package/src/engine/feature-ast/__tests__/canonical-form.test.ts +0 -416
- package/src/engine/feature-ast/__tests__/fixtures/cross-file-name-const/constants.ts +0 -1
- package/src/engine/feature-ast/__tests__/fixtures/cross-file-name-const/feature.ts +0 -8
- package/src/engine/feature-ast/__tests__/fixtures/cross-file-patch-const/constants.ts +0 -2
- package/src/engine/feature-ast/__tests__/fixtures/cross-file-patch-const/feature.ts +0 -8
- package/src/engine/feature-ast/__tests__/fixtures/cross-file-registrar/feature.ts +0 -9
- package/src/engine/feature-ast/__tests__/fixtures/cross-file-registrar/screens.ts +0 -4
- package/src/engine/feature-ast/__tests__/fixtures/resolve-import/alias-reexport.ts +0 -1
- package/src/engine/feature-ast/__tests__/fixtures/resolve-import/cycle-a.ts +0 -1
- package/src/engine/feature-ast/__tests__/fixtures/resolve-import/cycle-b.ts +0 -1
- package/src/engine/feature-ast/__tests__/fixtures/resolve-import/entry.ts +0 -3
- package/src/engine/feature-ast/__tests__/fixtures/resolve-import/local-rebind.ts +0 -3
- package/src/engine/feature-ast/__tests__/fixtures/resolve-import/origin.ts +0 -1
- package/src/engine/feature-ast/__tests__/fixtures/resolve-import/star-barrel.ts +0 -1
- package/src/engine/feature-ast/__tests__/handler-header-roundtrip.test.ts +0 -669
- package/src/engine/feature-ast/__tests__/parse-happy-path.test.ts +0 -196
- package/src/engine/feature-ast/__tests__/parse-real-features.test.ts +0 -138
- package/src/engine/feature-ast/__tests__/parse.test.ts +0 -2841
- package/src/engine/feature-ast/__tests__/patch-update.test.ts +0 -718
- package/src/engine/feature-ast/__tests__/patch.test.ts +0 -780
- package/src/engine/feature-ast/__tests__/patcher.test.ts +0 -468
- package/src/engine/feature-ast/__tests__/pattern-change-schema.test.ts +0 -819
- package/src/engine/feature-ast/__tests__/read-optional-access-rule.test.ts +0 -42
- package/src/engine/feature-ast/__tests__/render-roundtrip.test.ts +0 -947
- package/src/engine/feature-ast/__tests__/resolve-import.test.ts +0 -138
- package/src/engine/feature-ast/entity-field-types.ts +0 -41
- package/src/engine/feature-ast/extractors/ai-steps.ts +0 -352
- package/src/engine/feature-ast/extractors/events.ts +0 -349
- package/src/engine/feature-ast/extractors/handlers.ts +0 -459
- package/src/engine/feature-ast/extractors/hooks.ts +0 -331
- package/src/engine/feature-ast/extractors/index.ts +0 -92
- package/src/engine/feature-ast/extractors/jobs-routes.ts +0 -225
- package/src/engine/feature-ast/extractors/projections-screens.ts +0 -269
- package/src/engine/feature-ast/extractors/resolve-import.ts +0 -187
- package/src/engine/feature-ast/extractors/round1.ts +0 -150
- package/src/engine/feature-ast/extractors/round2.ts +0 -276
- package/src/engine/feature-ast/extractors/round3.ts +0 -474
- package/src/engine/feature-ast/extractors/round5.ts +0 -114
- package/src/engine/feature-ast/extractors/round6.ts +0 -32
- package/src/engine/feature-ast/extractors/shared.ts +0 -356
- package/src/engine/feature-ast/index.ts +0 -113
- package/src/engine/feature-ast/parse.ts +0 -615
- package/src/engine/feature-ast/patch.ts +0 -979
- package/src/engine/feature-ast/patcher.ts +0 -546
- package/src/engine/feature-ast/pattern-change-schema.ts +0 -1411
- package/src/engine/feature-ast/patterns.ts +0 -803
- package/src/engine/feature-ast/render.ts +0 -767
- package/src/engine/feature-ast/source-location.ts +0 -45
- package/src/engine/feature-builder-state.ts +0 -174
- package/src/engine/feature-changelog.ts +0 -95
- package/src/engine/feature-config-events-jobs.ts +0 -472
- package/src/engine/feature-entity-handlers.ts +0 -269
- package/src/engine/feature-manifest.ts +0 -173
- package/src/engine/feature-ui-extensions.ts +0 -648
- package/src/engine/field-access.ts +0 -140
- package/src/engine/field-helpers.ts +0 -35
- package/src/engine/handler-helpers.ts +0 -26
- package/src/engine/hook-helpers.ts +0 -16
- package/src/engine/i18n-key.ts +0 -12
- package/src/engine/index.ts +0 -585
- package/src/engine/instruction-fields.ts +0 -11
- package/src/engine/membership-roles.ts +0 -61
- package/src/engine/object-form.ts +0 -27
- package/src/engine/ownership.ts +0 -404
- package/src/engine/parse-ref-target.ts +0 -28
- package/src/engine/pattern-library/__tests__/library.test.ts +0 -399
- package/src/engine/pattern-library/index.ts +0 -24
- package/src/engine/pattern-library/library.ts +0 -140
- package/src/engine/pattern-library/mixed-schemas.ts +0 -588
- package/src/engine/pattern-library/opaque-schemas.ts +0 -124
- package/src/engine/pattern-library/shared-fields.ts +0 -79
- package/src/engine/pattern-library/static-schemas.ts +0 -456
- package/src/engine/pattern-library/types.ts +0 -255
- package/src/engine/personal-data-fields.ts +0 -66
- package/src/engine/pipeline.ts +0 -111
- package/src/engine/project-app-schema-for-roles.ts +0 -950
- package/src/engine/projection-helpers.ts +0 -79
- package/src/engine/qualified-name.ts +0 -165
- package/src/engine/read-claim.ts +0 -31
- package/src/engine/registry-facade.ts +0 -381
- package/src/engine/registry-ingest.ts +0 -479
- package/src/engine/registry-state.ts +0 -410
- package/src/engine/registry-validate.ts +0 -810
- package/src/engine/registry.ts +0 -94
- package/src/engine/resolve-config-or-param.ts +0 -157
- package/src/engine/role-assignment.ts +0 -63
- package/src/engine/run-in.ts +0 -29
- package/src/engine/run-pipeline.ts +0 -162
- package/src/engine/schema-builder.ts +0 -428
- package/src/engine/screen-filter-ops.ts +0 -60
- package/src/engine/screen-helpers.ts +0 -161
- package/src/engine/soft-delete-cleanup.ts +0 -126
- package/src/engine/state-machine.ts +0 -71
- package/src/engine/steps/__tests__/duration-utils.test.ts +0 -20
- package/src/engine/steps/_duration-utils.ts +0 -35
- package/src/engine/steps/_event-match.ts +0 -98
- package/src/engine/steps/_no-return-guard.ts +0 -21
- package/src/engine/steps/_read-source.ts +0 -12
- package/src/engine/steps/_resolver-utils.ts +0 -42
- package/src/engine/steps/_step-dispatch-constants.ts +0 -38
- package/src/engine/steps/aggregate-append-event.ts +0 -56
- package/src/engine/steps/aggregate-create.ts +0 -56
- package/src/engine/steps/aggregate-update.ts +0 -68
- package/src/engine/steps/branch.ts +0 -84
- package/src/engine/steps/call-feature.ts +0 -49
- package/src/engine/steps/compute.ts +0 -41
- package/src/engine/steps/describe-workflow-step-error.ts +0 -6
- package/src/engine/steps/for-each.ts +0 -111
- package/src/engine/steps/mail-send.ts +0 -48
- package/src/engine/steps/read-find-many.ts +0 -57
- package/src/engine/steps/read-find-one.ts +0 -59
- package/src/engine/steps/retry.ts +0 -99
- package/src/engine/steps/return.ts +0 -35
- package/src/engine/steps/unsafe-projection-delete.ts +0 -50
- package/src/engine/steps/unsafe-projection-upsert.ts +0 -88
- package/src/engine/steps/wait-for-event.ts +0 -90
- package/src/engine/steps/wait.ts +0 -69
- package/src/engine/steps/webhook-send.ts +0 -63
- package/src/engine/system-user.ts +0 -38
- package/src/engine/tier-resolver-extension.ts +0 -107
- package/src/engine/types/config.ts +0 -2
- package/src/engine/types/define-handler.ts +0 -2
- package/src/engine/types/entity-handlers.ts +0 -2
- package/src/engine/types/feature.ts +0 -2
- package/src/engine/types/fields.ts +0 -2
- package/src/engine/types/handlers.ts +0 -3
- package/src/engine/types/hooks.ts +0 -2
- package/src/engine/types/index.ts +0 -393
- package/src/engine/types/nav.ts +0 -2
- package/src/engine/types/ownership.ts +0 -2
- package/src/engine/types/projection.ts +0 -2
- package/src/engine/types/screen.ts +0 -3
- package/src/engine/types/step.ts +0 -2
- package/src/engine/types/workspace.ts +0 -2
- package/src/engine/validate-projection-allowlist.ts +0 -191
- package/src/engine/validation.ts +0 -33
- package/src/engine/where-rule-lint.ts +0 -196
- package/src/engine/write-handler-qn-extract.ts +0 -47
- package/src/entrypoint/__tests__/entrypoint-attach-dispatcher.integration.test.ts +0 -140
- package/src/entrypoint/__tests__/entrypoint-job-wiring.integration.test.ts +0 -292
- package/src/entrypoint/__tests__/split-deploy.integration.test.ts +0 -467
- package/src/entrypoint/index.ts +0 -541
- package/src/env/__tests__/compose-env-schema.test.ts +0 -410
- package/src/env/__tests__/dry-run.test.ts +0 -161
- package/src/env/__tests__/parse-env-dry-run.test.ts +0 -40
- package/src/env/_zod-introspect.ts +0 -51
- package/src/env/dry-run.ts +0 -204
- package/src/env/index.ts +0 -435
- package/src/errors/__tests__/classes.test.ts +0 -442
- package/src/errors/__tests__/error-helpers.test.ts +0 -58
- package/src/errors/__tests__/reason-i18n.test.ts +0 -46
- package/src/errors/__tests__/write-failures.test.ts +0 -167
- package/src/errors/classes.ts +0 -311
- package/src/errors/field-issue.ts +0 -8
- package/src/errors/i18n/de.yaml +0 -244
- package/src/errors/i18n/en.yaml +0 -234
- package/src/errors/index.ts +0 -47
- package/src/errors/kumiko-error.ts +0 -67
- package/src/errors/member-resolution.ts +0 -12
- package/src/errors/reasons.ts +0 -102
- package/src/errors/serialize.ts +0 -136
- package/src/errors/to-kumiko-error.ts +0 -8
- package/src/errors/transition-details.ts +0 -30
- package/src/errors/write-error-info.ts +0 -124
- package/src/errors/zod-bridge.ts +0 -62
- package/src/es-ops/README.md +0 -179
- package/src/es-ops/__tests__/context.integration.test.ts +0 -378
- package/src/es-ops/__tests__/runner.integration.test.ts +0 -483
- package/src/es-ops/__tests__/runner.test.ts +0 -202
- package/src/es-ops/context.ts +0 -98
- package/src/es-ops/index.ts +0 -34
- package/src/es-ops/operations-schema.ts +0 -57
- package/src/es-ops/runner.ts +0 -253
- package/src/es-ops/types.ts +0 -124
- package/src/event-store/__tests__/admin-api.integration.test.ts +0 -412
- package/src/event-store/__tests__/backfill-pii.integration.test.ts +0 -880
- package/src/event-store/__tests__/event-attribution.integration.test.ts +0 -236
- package/src/event-store/__tests__/event-store.integration.test.ts +0 -932
- package/src/event-store/__tests__/get-stream-version-perf.integration.test.ts +0 -87
- package/src/event-store/__tests__/perf.integration.test.ts +0 -283
- package/src/event-store/__tests__/provenance-append.integration.test.ts +0 -140
- package/src/event-store/__tests__/row-to-stored-event.test.ts +0 -68
- package/src/event-store/__tests__/snapshot.integration.test.ts +0 -328
- package/src/event-store/__tests__/transfer.integration.test.ts +0 -236
- package/src/event-store/__tests__/unscoped-stream-primitives.guard.test.ts +0 -62
- package/src/event-store/__tests__/upcaster-dead-letter.integration.test.ts +0 -202
- package/src/event-store/__tests__/upcaster.integration.test.ts +0 -491
- package/src/event-store/admin-api.ts +0 -241
- package/src/event-store/archive.ts +0 -83
- package/src/event-store/errors.ts +0 -58
- package/src/event-store/event-store.ts +0 -449
- package/src/event-store/events-schema.ts +0 -89
- package/src/event-store/index.ts +0 -76
- package/src/event-store/provenance-append.ts +0 -67
- package/src/event-store/rebuild-dead-letter.ts +0 -111
- package/src/event-store/row-to-stored-event.ts +0 -34
- package/src/event-store/snapshot.ts +0 -235
- package/src/event-store/transfer.ts +0 -84
- package/src/event-store/types.ts +0 -2
- package/src/event-store/upcaster-dead-letter.ts +0 -120
- package/src/event-store/upcaster.ts +0 -147
- package/src/files/__tests__/build-storage-key.test.ts +0 -28
- package/src/files/__tests__/content-disposition.test.ts +0 -123
- package/src/files/__tests__/file-field-pipeline.integration.test.ts +0 -229
- package/src/files/__tests__/file-handle.test.ts +0 -175
- package/src/files/__tests__/file-ref-entity.test.ts +0 -42
- package/src/files/__tests__/files.integration.test.ts +0 -1749
- package/src/files/__tests__/in-memory-provider.contract.test.ts +0 -4
- package/src/files/__tests__/in-memory-provider.test.ts +0 -94
- package/src/files/__tests__/local-provider.contract.test.ts +0 -14
- package/src/files/__tests__/local-provider.test.ts +0 -31
- package/src/files/__tests__/provider-resolver.test.ts +0 -70
- package/src/files/__tests__/read-stream.test.ts +0 -105
- package/src/files/__tests__/storage-tracking.integration.test.ts +0 -238
- package/src/files/__tests__/storage-tracking.test.ts +0 -46
- package/src/files/__tests__/write-stream.test.ts +0 -250
- package/src/files/__tests__/zip-stream.test.ts +0 -357
- package/src/files/content-disposition.ts +0 -55
- package/src/files/feature.ts +0 -44
- package/src/files/file-handle.ts +0 -83
- package/src/files/file-ref-entity.ts +0 -33
- package/src/files/file-ref-table.ts +0 -13
- package/src/files/file-routes.ts +0 -579
- package/src/files/in-memory-provider.ts +0 -113
- package/src/files/index.ts +0 -57
- package/src/files/local-provider.ts +0 -132
- package/src/files/provider-resolver.ts +0 -176
- package/src/files/storage-tracking.ts +0 -245
- package/src/files/types.ts +0 -336
- package/src/files/zip-stream.ts +0 -251
- package/src/http/index.ts +0 -10
- package/src/i18n/__tests__/i18n.test.ts +0 -113
- package/src/i18n/__tests__/mail-registry.test.ts +0 -54
- package/src/i18n/__tests__/request-locale.test.ts +0 -19
- package/src/i18n/__tests__/required-surface-keys.test.ts +0 -17
- package/src/i18n/index.ts +0 -51
- package/src/i18n/mail-registry.ts +0 -42
- package/src/i18n/request-locale.ts +0 -72
- package/src/i18n/required-surface-keys.ts +0 -451
- package/src/i18n/settings-hub-keys.ts +0 -31
- package/src/jobs/__tests__/job-attempt-context.integration.test.ts +0 -76
- package/src/jobs/__tests__/job-backoff.integration.test.ts +0 -147
- package/src/jobs/__tests__/job-event-trigger.integration.test.ts +0 -175
- package/src/jobs/__tests__/job-last-success.integration.test.ts +0 -135
- package/src/jobs/__tests__/job-multi-trigger.integration.test.ts +0 -147
- package/src/jobs/__tests__/job-public-intake-origin.integration.test.ts +0 -536
- package/src/jobs/__tests__/job-queue-depth.integration.test.ts +0 -82
- package/src/jobs/__tests__/job-retention.integration.test.ts +0 -316
- package/src/jobs/__tests__/job-retry-enqueue-paths.integration.test.ts +0 -309
- package/src/jobs/__tests__/job-runner-boot-timeout.test.ts +0 -55
- package/src/jobs/__tests__/job-systemdb.integration.test.ts +0 -153
- package/src/jobs/__tests__/job-tenant-db.integration.test.ts +0 -162
- package/src/jobs/__tests__/job-write-as.integration.test.ts +0 -251
- package/src/jobs/__tests__/jobs.integration.test.ts +0 -1563
- package/src/jobs/__tests__/scheduler-id.test.ts +0 -30
- package/src/jobs/index.ts +0 -8
- package/src/jobs/job-runner.ts +0 -1390
- package/src/lifecycle/__tests__/create-test-lifecycle.ts +0 -19
- package/src/lifecycle/__tests__/lifecycle-server.integration.test.ts +0 -108
- package/src/lifecycle/__tests__/lifecycle.test.ts +0 -212
- package/src/lifecycle/__tests__/signal-handlers.test.ts +0 -98
- package/src/lifecycle/index.ts +0 -13
- package/src/lifecycle/lifecycle.ts +0 -157
- package/src/lifecycle/signal-handlers.ts +0 -64
- package/src/logging/__tests__/fallback-logger.test.ts +0 -90
- package/src/logging/__tests__/pino-trace-bridge.test.ts +0 -50
- package/src/logging/index.ts +0 -4
- package/src/logging/pino-logger.ts +0 -68
- package/src/logging/utils.ts +0 -50
- package/src/migrations/__tests__/kumiko-drift.integration.test.ts +0 -238
- package/src/migrations/__tests__/kumiko-drift.report.test.ts +0 -105
- package/src/migrations/__tests__/pending-rebuilds.integration.test.ts +0 -370
- package/src/migrations/index.ts +0 -25
- package/src/migrations/kumiko-drift.ts +0 -187
- package/src/migrations/pending-rebuilds.ts +0 -225
- package/src/migrations/projection-table-index.ts +0 -23
- package/src/observability/__tests__/console-provider.test.ts +0 -67
- package/src/observability/__tests__/escape-hatch-report.test.ts +0 -149
- package/src/observability/__tests__/metric-validator.test.ts +0 -95
- package/src/observability/__tests__/metrics-handle.test.ts +0 -30
- package/src/observability/__tests__/metrics-wiring.test.ts +0 -61
- package/src/observability/__tests__/noop-provider.test.ts +0 -82
- package/src/observability/__tests__/observability.integration.test.ts +0 -639
- package/src/observability/__tests__/prometheus-meter.test.ts +0 -144
- package/src/observability/__tests__/recording-meter.test.ts +0 -101
- package/src/observability/__tests__/recording-tracer.test.ts +0 -112
- package/src/observability/__tests__/sensitive-filter.test.ts +0 -98
- package/src/observability/console-provider.ts +0 -130
- package/src/observability/context.ts +0 -26
- package/src/observability/escape-hatch-report.ts +0 -129
- package/src/observability/fallback.ts +0 -34
- package/src/observability/ids.ts +0 -25
- package/src/observability/index.ts +0 -88
- package/src/observability/metric-validator.ts +0 -98
- package/src/observability/metrics-handle.ts +0 -105
- package/src/observability/metrics-wiring.ts +0 -32
- package/src/observability/noop-provider.ts +0 -137
- package/src/observability/prometheus-meter.ts +0 -286
- package/src/observability/recording-meter.ts +0 -156
- package/src/observability/recording-tracer.ts +0 -186
- package/src/observability/redis-wrapper.ts +0 -132
- package/src/observability/sensitive-filter.ts +0 -108
- package/src/observability/standard-metrics.ts +0 -295
- package/src/pipeline/__tests__/archive-stream.integration.test.ts +0 -299
- package/src/pipeline/__tests__/auth-claims-resolver.test.ts +0 -279
- package/src/pipeline/__tests__/blind-index-rebuild-guard.integration.test.ts +0 -94
- package/src/pipeline/__tests__/cascade-handler.integration.test.ts +0 -435
- package/src/pipeline/__tests__/cascade-handler.test.ts +0 -67
- package/src/pipeline/__tests__/causation-chain.integration.test.ts +0 -207
- package/src/pipeline/__tests__/ctx-bridge.integration.test.ts +0 -507
- package/src/pipeline/__tests__/ctx-systemdb.integration.test.ts +0 -120
- package/src/pipeline/__tests__/dispatcher-utils.test.ts +0 -132
- package/src/pipeline/__tests__/dispatcher.test.ts +0 -1091
- package/src/pipeline/__tests__/distributed-lock.integration.test.ts +0 -110
- package/src/pipeline/__tests__/domain-events-projections.integration.test.ts +0 -323
- package/src/pipeline/__tests__/escape-hatch-audit.integration.test.ts +0 -254
- package/src/pipeline/__tests__/escape-hatch.integration.test.ts +0 -90
- package/src/pipeline/__tests__/event-consumer-state.integration.test.ts +0 -81
- package/src/pipeline/__tests__/event-dedup.integration.test.ts +0 -153
- package/src/pipeline/__tests__/event-define-event-strict.integration.test.ts +0 -196
- package/src/pipeline/__tests__/event-dispatcher-batch-delivery.test.ts +0 -178
- package/src/pipeline/__tests__/event-dispatcher-batch-handler.integration.test.ts +0 -143
- package/src/pipeline/__tests__/event-dispatcher-commit-order.integration.test.ts +0 -278
- package/src/pipeline/__tests__/event-dispatcher-db-outage.integration.test.ts +0 -224
- package/src/pipeline/__tests__/event-dispatcher-delivery-max-attempts.test.ts +0 -127
- package/src/pipeline/__tests__/event-dispatcher-idle.integration.test.ts +0 -94
- package/src/pipeline/__tests__/event-dispatcher-lifecycle.integration.test.ts +0 -209
- package/src/pipeline/__tests__/event-dispatcher-multi-instance.integration.test.ts +0 -424
- package/src/pipeline/__tests__/event-dispatcher-pass-failure.integration.test.ts +0 -266
- package/src/pipeline/__tests__/event-dispatcher-per-consumer-turns.integration.test.ts +0 -126
- package/src/pipeline/__tests__/event-dispatcher-pg-listen.integration.test.ts +0 -106
- package/src/pipeline/__tests__/event-dispatcher-rearm.integration.test.ts +0 -263
- package/src/pipeline/__tests__/event-dispatcher-recovery.integration.test.ts +0 -202
- package/src/pipeline/__tests__/event-dispatcher-second-audit.integration.test.ts +0 -282
- package/src/pipeline/__tests__/event-dispatcher-start-from.integration.test.ts +0 -276
- package/src/pipeline/__tests__/event-dispatcher-strict.test.ts +0 -67
- package/src/pipeline/__tests__/event-dispatcher.integration.test.ts +0 -290
- package/src/pipeline/__tests__/event-retention.integration.test.ts +0 -242
- package/src/pipeline/__tests__/fetch-for-writing.integration.test.ts +0 -364
- package/src/pipeline/__tests__/hook-systemdb-escape-hatch.integration.test.ts +0 -246
- package/src/pipeline/__tests__/idempotency-transient-failure.integration.test.ts +0 -198
- package/src/pipeline/__tests__/instruction-field-gate.integration.test.ts +0 -213
- package/src/pipeline/__tests__/irreversible-operation-gate.integration.test.ts +0 -249
- package/src/pipeline/__tests__/job-trigger-consumer.integration.test.ts +0 -235
- package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +0 -800
- package/src/pipeline/__tests__/load-aggregate-query.integration.test.ts +0 -281
- package/src/pipeline/__tests__/member-resolution-read-only.test.ts +0 -79
- package/src/pipeline/__tests__/msp-error-mode.integration.test.ts +0 -149
- package/src/pipeline/__tests__/msp-multi-hop.integration.test.ts +0 -231
- package/src/pipeline/__tests__/msp-rebuild.integration.test.ts +0 -510
- package/src/pipeline/__tests__/multi-stream-projection.integration.test.ts +0 -313
- package/src/pipeline/__tests__/pending-gap-ranges.test.ts +0 -94
- package/src/pipeline/__tests__/perf-rebuild.integration.test.ts +0 -147
- package/src/pipeline/__tests__/post-query-hook.integration.test.ts +0 -165
- package/src/pipeline/__tests__/projection-rebuild.integration.test.ts +0 -1033
- package/src/pipeline/__tests__/projections-runner-systemscope.integration.test.ts +0 -101
- package/src/pipeline/__tests__/public-intake-runtime-gate.integration.test.ts +0 -684
- package/src/pipeline/__tests__/query-projection.integration.test.ts +0 -357
- package/src/pipeline/__tests__/rate-limit-default.integration.test.ts +0 -118
- package/src/pipeline/__tests__/rate-limit-default.test.ts +0 -117
- package/src/pipeline/__tests__/rebuild-poison-quarantine.integration.test.ts +0 -275
- package/src/pipeline/__tests__/redis-keys.test.ts +0 -12
- package/src/pipeline/__tests__/redis-pipeline.integration.test.ts +0 -490
- package/src/pipeline/__tests__/search-consumer-named-events.integration.test.ts +0 -274
- package/src/pipeline/__tests__/system-identity-switch.integration.test.ts +0 -583
- package/src/pipeline/__tests__/system-identity-switch.test.ts +0 -645
- package/src/pipeline/__tests__/tenant-timezone-cache.test.ts +0 -89
- package/src/pipeline/__tests__/try-append-event.integration.test.ts +0 -168
- package/src/pipeline/__tests__/unsafe-raw-escape-hatch.integration.test.ts +0 -103
- package/src/pipeline/active-membership.ts +0 -190
- package/src/pipeline/append-event-core.ts +0 -117
- package/src/pipeline/auth-claims-resolver.ts +0 -103
- package/src/pipeline/cascade-handler.ts +0 -109
- package/src/pipeline/dispatch-batch.ts +0 -269
- package/src/pipeline/dispatch-query.ts +0 -195
- package/src/pipeline/dispatch-shared.ts +0 -1242
- package/src/pipeline/dispatch-stream.ts +0 -129
- package/src/pipeline/dispatch-write.ts +0 -599
- package/src/pipeline/dispatcher-utils.ts +0 -199
- package/src/pipeline/dispatcher.ts +0 -278
- package/src/pipeline/distributed-lock.ts +0 -66
- package/src/pipeline/entity-cache.ts +0 -82
- package/src/pipeline/event-consumer-state.ts +0 -190
- package/src/pipeline/event-dedup.ts +0 -23
- package/src/pipeline/event-dispatcher-admin.ts +0 -320
- package/src/pipeline/event-dispatcher-delivery.ts +0 -499
- package/src/pipeline/event-dispatcher.ts +0 -817
- package/src/pipeline/event-retention.ts +0 -144
- package/src/pipeline/idempotency.ts +0 -158
- package/src/pipeline/index.ts +0 -83
- package/src/pipeline/irreversible-operation-gate.ts +0 -76
- package/src/pipeline/lifecycle-pipeline.ts +0 -421
- package/src/pipeline/member-read-only-transaction.ts +0 -71
- package/src/pipeline/member-reader.ts +0 -110
- package/src/pipeline/msp-rebuild.ts +0 -306
- package/src/pipeline/multi-stream-apply-context.ts +0 -85
- package/src/pipeline/pending-gap-ranges.ts +0 -120
- package/src/pipeline/projection-rebuild.ts +0 -539
- package/src/pipeline/projection-state.ts +0 -60
- package/src/pipeline/projections-runner.ts +0 -66
- package/src/pipeline/redis-keys.ts +0 -11
- package/src/pipeline/system-hooks.ts +0 -695
- package/src/pipeline/system-identity-switch.ts +0 -401
- package/src/pipeline/tenant-timezone-cache.ts +0 -92
- package/src/pipeline/write-origin.ts +0 -128
- package/src/random/__tests__/generate.test.ts +0 -149
- package/src/random/__tests__/words.test.ts +0 -44
- package/src/random/generate.ts +0 -141
- package/src/random/index.ts +0 -8
- package/src/random/words.ts +0 -393
- package/src/rate-limit/__tests__/dispatcher-l3.integration.test.ts +0 -111
- package/src/rate-limit/__tests__/middleware.integration.test.ts +0 -246
- package/src/rate-limit/__tests__/resolver.integration.test.ts +0 -211
- package/src/rate-limit/bucket.ts +0 -36
- package/src/rate-limit/index.ts +0 -14
- package/src/rate-limit/middleware.ts +0 -179
- package/src/rate-limit/resolver.ts +0 -251
- package/src/redis/__tests__/redis-options.test.ts +0 -54
- package/src/redis/client.ts +0 -77
- package/src/redis/index.ts +0 -4
- package/src/redis/pubsub-signal.ts +0 -107
- package/src/schema-cli.ts +0 -510
- package/src/search/__tests__/derive-search-adapter-config.test.ts +0 -65
- package/src/search/__tests__/meilisearch-adapter.integration.test.ts +0 -348
- package/src/search/__tests__/meilisearch-ids.test.ts +0 -30
- package/src/search/__tests__/reindex-entity.integration.test.ts +0 -243
- package/src/search/__tests__/search-adapter.test.ts +0 -256
- package/src/search/__tests__/search-consumer-batch.integration.test.ts +0 -306
- package/src/search/__tests__/search-pii-derived-index.integration.test.ts +0 -208
- package/src/search/derive-search-adapter-config.ts +0 -27
- package/src/search/in-memory-adapter.ts +0 -123
- package/src/search/index.ts +0 -20
- package/src/search/meilisearch-adapter.ts +0 -189
- package/src/search/purge-subject.ts +0 -253
- package/src/search/reindex-entity.ts +0 -190
- package/src/secrets/__tests__/contains-secret.test.ts +0 -108
- package/src/secrets/__tests__/dek-cache.test.ts +0 -211
- package/src/secrets/__tests__/derive-purpose-secret.test.ts +0 -52
- package/src/secrets/__tests__/env-master-key-provider.test.ts +0 -119
- package/src/secrets/__tests__/envelope-cipher.test.ts +0 -59
- package/src/secrets/__tests__/envelope.test.ts +0 -74
- package/src/secrets/__tests__/leak-guard.test.ts +0 -104
- package/src/secrets/__tests__/rotation.test.ts +0 -149
- package/src/secrets/dek-cache.ts +0 -137
- package/src/secrets/derive-purpose-secret.ts +0 -17
- package/src/secrets/env-master-key-provider.ts +0 -162
- package/src/secrets/envelope-cipher.ts +0 -53
- package/src/secrets/envelope.ts +0 -57
- package/src/secrets/index.ts +0 -33
- package/src/secrets/leak-guard.ts +0 -87
- package/src/secrets/rotation.ts +0 -34
- package/src/secrets/stored-envelope.ts +0 -46
- package/src/seeding/__tests__/entity-seed.test.ts +0 -70
- package/src/seeding/entity-seed.ts +0 -31
- package/src/seeding/index.ts +0 -6
- package/src/seeding/types.ts +0 -8
- package/src/stack/__tests__/drain-event-consumers.integration.test.ts +0 -166
- package/src/stack/__tests__/drain-jobs.integration.test.ts +0 -159
- package/src/stack/__tests__/event-collector.test.ts +0 -42
- package/src/stack/__tests__/ownership-boot-guard.integration.test.ts +0 -108
- package/src/stack/__tests__/push-entity-projection-tables-column-sync.integration.test.ts +0 -107
- package/src/stack/__tests__/request-helper.integration.test.ts +0 -140
- package/src/stack/__tests__/request-helper.test.ts +0 -159
- package/src/stack/__tests__/setup-test-stack-entity-tables.integration.test.ts +0 -65
- package/src/stack/__tests__/setup-test-stack-jobs.integration.test.ts +0 -185
- package/src/stack/__tests__/setup-test-stack-metrics.integration.test.ts +0 -79
- package/src/stack/db.ts +0 -82
- package/src/stack/drain-event-consumers.ts +0 -74
- package/src/stack/drain-jobs.ts +0 -129
- package/src/stack/event-collector.ts +0 -23
- package/src/stack/index.ts +0 -34
- package/src/stack/push-entity-projection-tables.ts +0 -95
- package/src/stack/redis.ts +0 -55
- package/src/stack/request-helper.ts +0 -298
- package/src/stack/table-helpers.ts +0 -175
- package/src/stack/test-stack.ts +0 -596
- package/src/stack/test-users.ts +0 -37
- package/src/testing/__tests__/db-cleanup.test.ts +0 -40
- package/src/testing/__tests__/e2e-generator.test.ts +0 -349
- package/src/testing/__tests__/ensure-entity-table.integration.test.ts +0 -52
- package/src/testing/__tests__/late-bound.test.ts +0 -32
- package/src/testing/__tests__/multipart-helper.test.ts +0 -49
- package/src/testing/__tests__/real-providers.test.ts +0 -62
- package/src/testing/__tests__/wait-for.test.ts +0 -104
- package/src/testing/access-assertions.ts +0 -15
- package/src/testing/assertions.ts +0 -35
- package/src/testing/boot-validator-fixture.ts +0 -124
- package/src/testing/closed-connection-error.ts +0 -62
- package/src/testing/db-cleanup.ts +0 -45
- package/src/testing/e2e-generator.ts +0 -494
- package/src/testing/expect-error.ts +0 -25
- package/src/testing/file-provider-contract.ts +0 -123
- package/src/testing/handler-context.ts +0 -143
- package/src/testing/http-cookies.ts +0 -52
- package/src/testing/index.ts +0 -60
- package/src/testing/late-bound.ts +0 -41
- package/src/testing/multipart-helper.ts +0 -94
- package/src/testing/mutable-master-key-provider.ts +0 -57
- package/src/testing/observability-recorder.ts +0 -54
- package/src/testing/real-providers.ts +0 -30
- package/src/testing/seed.ts +0 -50
- package/src/testing/shared-entities.ts +0 -65
- package/src/testing/utils.ts +0 -1
- package/src/testing/wait-for.ts +0 -49
- package/src/testing/without-ambient-temporal.ts +0 -14
- package/src/time/__tests__/boot-tz-warning.test.ts +0 -46
- package/src/time/__tests__/geo-tz.test.ts +0 -71
- package/src/time/__tests__/iana.test.ts +0 -35
- package/src/time/__tests__/polyfill-reinstall.test.ts +0 -17
- package/src/time/__tests__/polyfill.test.ts +0 -73
- package/src/time/__tests__/tz-context.test.ts +0 -121
- package/src/time/__tests__/tz-dateline.test.ts +0 -34
- package/src/time/boot-tz-warning.ts +0 -30
- package/src/time/iana.ts +0 -19
- package/src/time/index.ts +0 -23
- package/src/time/legacy-date.ts +0 -18
- package/src/time/polyfill.ts +0 -59
- package/src/time/tz-context.ts +0 -100
- package/src/ui-types/__tests__/plural.test.ts +0 -108
- package/src/ui-types/app-schema.ts +0 -91
- package/src/ui-types/formality.ts +0 -7
- package/src/ui-types/index.ts +0 -158
- package/src/ui-types/list-row-meta.ts +0 -87
- package/src/ui-types/plural.ts +0 -69
- package/src/upgrade-cli.ts +0 -651
- package/src/utils/__tests__/assert.test.ts +0 -17
- package/src/utils/__tests__/case.test.ts +0 -16
- package/src/utils/__tests__/compare.test.ts +0 -20
- package/src/utils/__tests__/env-parse.test.ts +0 -54
- package/src/utils/__tests__/ids.test.ts +0 -52
- package/src/utils/__tests__/is-plain-object.test.ts +0 -16
- package/src/utils/__tests__/parse-string-array-json.test.ts +0 -16
- package/src/utils/__tests__/safe-json-temporal.test.ts +0 -28
- package/src/utils/__tests__/safe-json.test.ts +0 -22
- package/src/utils/__tests__/serialization.test.ts +0 -30
- package/src/utils/assert.ts +0 -18
- package/src/utils/case.ts +0 -6
- package/src/utils/compare.ts +0 -10
- package/src/utils/env-parse.ts +0 -16
- package/src/utils/ids.ts +0 -26
- package/src/utils/index.ts +0 -9
- package/src/utils/is-plain-object.ts +0 -4
- package/src/utils/parse-string-array-json.ts +0 -14
- package/src/utils/safe-json.ts +0 -50
- package/src/utils/serialization.ts +0 -14
- /package/{src/engine/types/event-type-map.ts → dist/engine/types/event-type-map.d.ts} +0 -0
- /package/{src/engine/types/extension-options-map.ts → dist/engine/types/extension-options-map.d.ts} +0 -0
- /package/{src/engine/types/http-route.ts → dist/engine/types/http-route.d.ts} +0 -0
- /package/{src/engine/types/identifiers.ts → dist/engine/types/identifiers.d.ts} +0 -0
- /package/{src/engine/types/relations.ts → dist/engine/types/relations.d.ts} +0 -0
- /package/{src/engine/types/target-ref.ts → dist/engine/types/target-ref.d.ts} +0 -0
- /package/{src/engine/types/tree-node.ts → dist/engine/types/tree-node.d.ts} +0 -0
- /package/{src/logging/types.ts → dist/logging/types.d.ts} +0 -0
- /package/{src/observability/types/index.ts → dist/observability/types/index.d.ts} +0 -0
- /package/{src/observability/types/metric.ts → dist/observability/types/metric.d.ts} +0 -0
- /package/{src/observability/types/provider.ts → dist/observability/types/provider.d.ts} +0 -0
- /package/{src/observability/types/span.ts → dist/observability/types/span.d.ts} +0 -0
- /package/{src/search/types.ts → dist/search/types.d.ts} +0 -0
- /package/{src/secrets/types.ts → dist/secrets/types.js} +0 -0
- /package/{src/time/geo-tz.ts → dist/time/geo-tz.d.ts} +0 -0
|
@@ -1,1563 +0,0 @@
|
|
|
1
|
-
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
2
|
-
import { Queue } from "bullmq";
|
|
3
|
-
import { Redis } from "ioredis";
|
|
4
|
-
import * as z from "zod";
|
|
5
|
-
import { requestContext } from "../../api/request-context";
|
|
6
|
-
import { tenantDbRunner } from "../../db/tenant-db-runner";
|
|
7
|
-
import { createRegistry, defineFeature } from "../../engine";
|
|
8
|
-
import type {
|
|
9
|
-
AppContext,
|
|
10
|
-
ConfigAccessor,
|
|
11
|
-
ConfigAccessorFactory,
|
|
12
|
-
NotifyFactory,
|
|
13
|
-
Registry,
|
|
14
|
-
TenantId,
|
|
15
|
-
} from "../../engine/types";
|
|
16
|
-
import { createInMemoryFileProvider } from "../../files/in-memory-provider";
|
|
17
|
-
import { RedisKeys } from "../../pipeline/redis-keys";
|
|
18
|
-
import { createTestRedis, type TestRedis, TestUsers } from "../../stack";
|
|
19
|
-
import { sleep, waitFor } from "../../testing";
|
|
20
|
-
import {
|
|
21
|
-
bootJobIdForJobName,
|
|
22
|
-
createJobRunner,
|
|
23
|
-
type JobLogEntry,
|
|
24
|
-
type JobMeta,
|
|
25
|
-
type JobRunner,
|
|
26
|
-
type JobRunnerOptions,
|
|
27
|
-
} from "../job-runner";
|
|
28
|
-
|
|
29
|
-
// --- Shared state ---
|
|
30
|
-
|
|
31
|
-
let testRedis: TestRedis;
|
|
32
|
-
let redisUrl: string;
|
|
33
|
-
|
|
34
|
-
// Track which jobs ran and when
|
|
35
|
-
const jobLog: Array<{ name: string; payload: Record<string, unknown>; timestamp: number }> = [];
|
|
36
|
-
|
|
37
|
-
// Counts eventRetrySucceeds' own attempts — throws once on attempt 1, then
|
|
38
|
-
// succeeds, so a real retry must have happened for the job to ever reach 2.
|
|
39
|
-
let eventRetryAttemptCount = 0;
|
|
40
|
-
|
|
41
|
-
function clearLog() {
|
|
42
|
-
jobLog.length = 0;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// --- Feature with test jobs ---
|
|
46
|
-
|
|
47
|
-
const testFeature = defineFeature("test", (r) => {
|
|
48
|
-
// Scenario 1: Boot job
|
|
49
|
-
r.job("bootSync", { trigger: { manual: true }, runOnBoot: true }, async (payload) => {
|
|
50
|
-
jobLog.push({ name: "test:job:boot-sync", payload, timestamp: Date.now() });
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// Scenario 2: Scheduled job (cron every second for testing)
|
|
54
|
-
r.job("scheduled", { trigger: { cron: "* * * * * *" } }, async (payload) => {
|
|
55
|
-
jobLog.push({ name: "test:job:scheduled", payload, timestamp: Date.now() });
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
// Scenario 3: Manual trigger
|
|
59
|
-
r.job("manualReport", { trigger: { manual: true } }, async (payload) => {
|
|
60
|
-
jobLog.push({ name: "test:job:manual-report", payload, timestamp: Date.now() });
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Concurrency: skip — if running, skip new
|
|
64
|
-
r.job("skipJob", { trigger: { manual: true }, concurrency: "skip" }, async (payload) => {
|
|
65
|
-
jobLog.push({ name: "test:job:skip-job", payload, timestamp: Date.now() });
|
|
66
|
-
await sleep(500); // Simulate long-running job
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// Concurrency: parallel — multiple can run
|
|
70
|
-
r.job("parallelJob", { trigger: { manual: true }, concurrency: "parallel" }, async (payload) => {
|
|
71
|
-
jobLog.push({ name: "test:job:parallel-job", payload, timestamp: Date.now() });
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// Concurrency: replace — cancel old, start new
|
|
75
|
-
r.job("replaceJob", { trigger: { manual: true }, concurrency: "replace" }, async (payload) => {
|
|
76
|
-
jobLog.push({ name: "test:job:replace-job", payload, timestamp: Date.now() });
|
|
77
|
-
await sleep(200);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
// Concurrency: debounce — wait until quiet, then run once
|
|
81
|
-
r.job(
|
|
82
|
-
"debounceJob",
|
|
83
|
-
{ trigger: { manual: true }, concurrency: "debounce", debounceMs: 300 },
|
|
84
|
-
async (payload) => {
|
|
85
|
-
jobLog.push({ name: "test:job:debounce-job", payload, timestamp: Date.now() });
|
|
86
|
-
},
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
// Concurrency: sequential — same-name dispatches must serialise via the
|
|
90
|
-
// per-name Redis SETNX-lock. Sleep duration sets the gap the assertions
|
|
91
|
-
// measure: parallel mode lands all entries within ~50ms; sequential
|
|
92
|
-
// spaces them by ≥sleep-duration each. If you tweak the sleep here,
|
|
93
|
-
// bump the timestamp deltas in the assertion to match.
|
|
94
|
-
r.job(
|
|
95
|
-
"sequentialJob",
|
|
96
|
-
{ trigger: { manual: true }, concurrency: "sequential" },
|
|
97
|
-
async (payload) => {
|
|
98
|
-
jobLog.push({ name: "test:job:sequential-job", payload, timestamp: Date.now() });
|
|
99
|
-
await sleep(300);
|
|
100
|
-
},
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
// Sequential variant that throws. Used to assert the lock is released in
|
|
104
|
-
// the finally-path (next dispatch must still acquire it). retries=0 so
|
|
105
|
-
// the failure doesn't replay and pollute the log.
|
|
106
|
-
r.job(
|
|
107
|
-
"sequentialFailJob",
|
|
108
|
-
{ trigger: { manual: true }, concurrency: "sequential", retries: 0 },
|
|
109
|
-
async (payload) => {
|
|
110
|
-
jobLog.push({ name: "test:job:sequential-fail-job", payload, timestamp: Date.now() });
|
|
111
|
-
throw new Error("sequential boom");
|
|
112
|
-
},
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
// maxPerTenant: cap concurrent + waiting jobs per tenant. Long sleep so
|
|
116
|
-
// the dispatcher checks ALL queued counts (including waiting ones).
|
|
117
|
-
r.job(
|
|
118
|
-
"perTenantLimited",
|
|
119
|
-
{ trigger: { manual: true }, concurrency: "parallel", maxPerTenant: 2 },
|
|
120
|
-
async (payload) => {
|
|
121
|
-
jobLog.push({ name: "test:job:per-tenant-limited", payload, timestamp: Date.now() });
|
|
122
|
-
await sleep(500);
|
|
123
|
-
},
|
|
124
|
-
);
|
|
125
|
-
r.writeHandler(
|
|
126
|
-
"capped-event",
|
|
127
|
-
z.object({ n: z.number() }),
|
|
128
|
-
async (event) => ({ isSuccess: true, data: { n: event.payload.n } }),
|
|
129
|
-
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
130
|
-
);
|
|
131
|
-
// Event-triggered twin — exercises handleEvent's maxPerTenant guard
|
|
132
|
-
// (dispatch and handleEvent share isOverPerTenantLimit).
|
|
133
|
-
r.job(
|
|
134
|
-
"perTenantLimitedEvent",
|
|
135
|
-
{
|
|
136
|
-
trigger: { on: "test:write:capped-event" },
|
|
137
|
-
concurrency: "parallel",
|
|
138
|
-
maxPerTenant: 2,
|
|
139
|
-
},
|
|
140
|
-
async (payload) => {
|
|
141
|
-
jobLog.push({
|
|
142
|
-
name: "test:job:per-tenant-limited-event",
|
|
143
|
-
payload,
|
|
144
|
-
timestamp: Date.now(),
|
|
145
|
-
});
|
|
146
|
-
await sleep(500);
|
|
147
|
-
},
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
r.writeHandler(
|
|
151
|
-
"retry-event-trigger",
|
|
152
|
-
z.object({ n: z.number() }),
|
|
153
|
-
async (event) => ({ isSuccess: true, data: { n: event.payload.n } }),
|
|
154
|
-
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
155
|
-
);
|
|
156
|
-
// Event-triggered job with retries — proves handleEvent passes
|
|
157
|
-
// retries/backoff to the queue the same way dispatch() does (fw
|
|
158
|
-
// job-runner retries regression, solon).
|
|
159
|
-
r.job(
|
|
160
|
-
"eventRetrySucceeds",
|
|
161
|
-
{ trigger: { on: "test:write:retry-event-trigger" }, retries: 2 },
|
|
162
|
-
async (payload) => {
|
|
163
|
-
eventRetryAttemptCount += 1;
|
|
164
|
-
jobLog.push({ name: "test:job:event-retry-succeeds", payload, timestamp: Date.now() });
|
|
165
|
-
if (eventRetryAttemptCount === 1) throw new Error("fails on first attempt");
|
|
166
|
-
},
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
// Job that fails
|
|
170
|
-
r.job("failingJob", { trigger: { manual: true }, retries: 1 }, async () => {
|
|
171
|
-
throw new Error("intentional failure");
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
// perTenant fan-out — used to assert missing getActiveTenantIds fails
|
|
175
|
-
// the wrapper job without killing the worker.
|
|
176
|
-
r.job("perTenantFanout", { trigger: { manual: true }, perTenant: true }, async (payload) => {
|
|
177
|
-
jobLog.push({ name: "test:job:per-tenant-fanout", payload, timestamp: Date.now() });
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
// Correlation propagation probe — records the requestContext it sees at
|
|
181
|
-
// handler-time so tests can assert the scheduling request's correlationId
|
|
182
|
-
// made it through BullMQ into the worker process.
|
|
183
|
-
r.job("correlationProbe", { trigger: { manual: true } }, async (payload) => {
|
|
184
|
-
const seen = requestContext.get();
|
|
185
|
-
jobLog.push({
|
|
186
|
-
name: "test:job:correlation-probe",
|
|
187
|
-
payload: {
|
|
188
|
-
...payload,
|
|
189
|
-
observedCorrelationId: seen?.correlationId ?? null,
|
|
190
|
-
observedRequestId: seen?.requestId ?? null,
|
|
191
|
-
},
|
|
192
|
-
timestamp: Date.now(),
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
// Exercises createJobLogger (info/warn/error/debug/child) — otherwise those
|
|
196
|
-
// one-liners stay uncovered even though every job builds a logger.
|
|
197
|
-
r.job("logProbe", { trigger: { manual: true } }, async (payload, ctx) => {
|
|
198
|
-
expect(ctx.log).toBeDefined();
|
|
199
|
-
const log = ctx.log!;
|
|
200
|
-
log.info("log-probe-info", { n: payload["n"] });
|
|
201
|
-
log.warn("log-probe-warn");
|
|
202
|
-
log.error("log-probe-error", { ok: false });
|
|
203
|
-
log.debug("log-probe-debug");
|
|
204
|
-
log.child({ probe: true }).info("log-probe-child");
|
|
205
|
-
jobLog.push({ name: "test:job:log-probe", payload, timestamp: Date.now() });
|
|
206
|
-
});
|
|
207
|
-
// job-runner must build ctx.files the same way dispatch-shared.ts does for
|
|
208
|
-
// write-handlers/MSPs — regression guard for #1520 (ctx.files was never
|
|
209
|
-
// materialized for jobs, so ctx.files.ref(...).read() threw for every job).
|
|
210
|
-
r.job("filesProbe", { trigger: { manual: true } }, async (payload, ctx) => {
|
|
211
|
-
const content = await ctx.files!.ref(payload["key"] as string).read();
|
|
212
|
-
jobLog.push({
|
|
213
|
-
name: "test:job:files-probe",
|
|
214
|
-
payload: { text: new TextDecoder().decode(content) },
|
|
215
|
-
timestamp: Date.now(),
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
// job-runner must build ctx.notify/ctx.config the same way dispatch-shared.ts
|
|
220
|
-
// does for write-handlers — regression guard for #1532 (only ctx.files got
|
|
221
|
-
// the same fix; ctx.notify/ctx.config stayed undefined for every job).
|
|
222
|
-
r.job("notifyProbe", { trigger: { manual: true } }, async (payload, ctx) => {
|
|
223
|
-
await ctx.notify!("test-notification", { to: payload["toUserId"] as string });
|
|
224
|
-
jobLog.push({ name: "test:job:notify-probe", payload, timestamp: Date.now() });
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
r.job("configProbe", { trigger: { manual: true } }, async (_payload, ctx) => {
|
|
228
|
-
const value = await ctx.config!("test:config:probe-key");
|
|
229
|
-
jobLog.push({ name: "test:job:config-probe", payload: { value }, timestamp: Date.now() });
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
// ctx.write/queryAs throw until JobRunner.attachDispatcher() has run —
|
|
233
|
-
// regression guard for framework#2043. No test runner here ever calls
|
|
234
|
-
// attachDispatcher(), so this always hits the stub.
|
|
235
|
-
r.job("writeProbe", { trigger: { manual: true }, retries: 0 }, async (_payload, ctx) => {
|
|
236
|
-
await ctx.write("test:write:probe", {});
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
beforeAll(async () => {
|
|
241
|
-
testRedis = await createTestRedis();
|
|
242
|
-
redisUrl = `redis://${testRedis.redis.options.host}:${testRedis.redis.options.port}/${testRedis.redis.options.db}`;
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
afterAll(async () => {
|
|
246
|
-
await testRedis.cleanup();
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
// Helper to create a runner, run tests, then stop
|
|
250
|
-
async function withRunner(
|
|
251
|
-
fn: (runner: JobRunner, registry: Registry) => Promise<void>,
|
|
252
|
-
opts?: Partial<JobRunnerOptions>,
|
|
253
|
-
): Promise<void> {
|
|
254
|
-
const registry = createRegistry([testFeature]);
|
|
255
|
-
const context: AppContext = {};
|
|
256
|
-
// Date.now() alone collided when two tests ran in the same millisecond;
|
|
257
|
-
// adding a random suffix keeps queue names unique across the whole run.
|
|
258
|
-
const queueNamePrefix = `kumiko-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
259
|
-
const runner = createJobRunner({
|
|
260
|
-
registry,
|
|
261
|
-
context,
|
|
262
|
-
redisUrl,
|
|
263
|
-
consumerLane: "worker",
|
|
264
|
-
queueNamePrefix,
|
|
265
|
-
...opts,
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
try {
|
|
269
|
-
await runner.start();
|
|
270
|
-
await fn(runner, registry);
|
|
271
|
-
} finally {
|
|
272
|
-
await runner.stop();
|
|
273
|
-
// Purge any lingering scheduler/repeat keys the worker-lane queue left
|
|
274
|
-
// behind. BullMQ stores them under <queueName>:* — orphaned schedulers
|
|
275
|
-
// from a previous test run would otherwise fire into a now-stopped
|
|
276
|
-
// worker. Only the worker lane is queried because these tests run jobs
|
|
277
|
-
// with the default runIn, which resolves to "worker".
|
|
278
|
-
const keys = await testRedis.redis.keys(`bull:${queueNamePrefix}-worker:*`);
|
|
279
|
-
if (keys.length > 0) await testRedis.redis.del(...keys);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// --- Scenario 1: Boot job runs on startup ---
|
|
284
|
-
|
|
285
|
-
describe("scenario 1: boot job", () => {
|
|
286
|
-
test("runOnBoot job executes when runner starts", async () => {
|
|
287
|
-
clearLog();
|
|
288
|
-
await withRunner(async () => {
|
|
289
|
-
await waitFor(() => {
|
|
290
|
-
const bootEntries = jobLog.filter((e) => e.name === "test:job:boot-sync");
|
|
291
|
-
expect(bootEntries.length).toBeGreaterThanOrEqual(1);
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
// --- Scenario 2: Scheduled (cron) job ---
|
|
298
|
-
|
|
299
|
-
describe("scenario 2: scheduled job", () => {
|
|
300
|
-
test("cron job is registered in registry", () => {
|
|
301
|
-
const registry = createRegistry([testFeature]);
|
|
302
|
-
const job = registry.getJob("test:job:scheduled");
|
|
303
|
-
expect(job).toBeDefined();
|
|
304
|
-
if (job && "cron" in job.trigger) {
|
|
305
|
-
expect(job.trigger.cron).toBe("* * * * * *");
|
|
306
|
-
} else {
|
|
307
|
-
expect.unreachable("Expected cron trigger");
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
// BullMQ's repeatable scheduler needs a second or two to register its
|
|
312
|
-
// first tick — a generous delay schedule covers the startup window.
|
|
313
|
-
test("cron job fires via BullMQ scheduler", async () => {
|
|
314
|
-
clearLog();
|
|
315
|
-
await withRunner(async () => {
|
|
316
|
-
await waitFor(
|
|
317
|
-
() => {
|
|
318
|
-
const entries = jobLog.filter((e) => e.name === "test:job:scheduled");
|
|
319
|
-
expect(entries.length).toBeGreaterThanOrEqual(1);
|
|
320
|
-
},
|
|
321
|
-
{ delays: [2000, 3000, 5000] },
|
|
322
|
-
);
|
|
323
|
-
});
|
|
324
|
-
});
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
// --- Scenario 3: Manual trigger ---
|
|
328
|
-
|
|
329
|
-
describe("scenario 3: manual trigger", () => {
|
|
330
|
-
test("dispatch runs the job with payload", async () => {
|
|
331
|
-
clearLog();
|
|
332
|
-
await withRunner(async (runner) => {
|
|
333
|
-
await runner.dispatch("test:job:manual-report", { reportId: 42 });
|
|
334
|
-
await waitFor(() => {
|
|
335
|
-
const entries = jobLog.filter((e) => e.name === "test:job:manual-report");
|
|
336
|
-
expect(entries.length).toBe(1);
|
|
337
|
-
expect(entries[0]?.payload).toEqual({ reportId: 42 });
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
test("dispatch unknown job throws", async () => {
|
|
343
|
-
await withRunner(async (runner) => {
|
|
344
|
-
await expect(runner.dispatch("nonexistent:job:missing")).rejects.toThrow("Unknown job");
|
|
345
|
-
});
|
|
346
|
-
});
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
describe("scenario 3b: ctx.files resolves through the file provider", () => {
|
|
350
|
-
test("job handler can read back a file via ctx.files.ref(key)", async () => {
|
|
351
|
-
clearLog();
|
|
352
|
-
const provider = createInMemoryFileProvider();
|
|
353
|
-
await provider.write("probe/hello.txt", new TextEncoder().encode("hello from files probe"));
|
|
354
|
-
|
|
355
|
-
await withRunner(
|
|
356
|
-
async (runner) => {
|
|
357
|
-
await runner.dispatch("test:job:files-probe", { key: "probe/hello.txt" });
|
|
358
|
-
await waitFor(() => {
|
|
359
|
-
const entries = jobLog.filter((e) => e.name === "test:job:files-probe");
|
|
360
|
-
expect(entries.length).toBe(1);
|
|
361
|
-
expect(entries[0]?.payload["text"]).toBe("hello from files probe");
|
|
362
|
-
});
|
|
363
|
-
},
|
|
364
|
-
{ context: { _fileProviderResolver: () => Promise.resolve(provider) } },
|
|
365
|
-
);
|
|
366
|
-
});
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
describe("scenario 3c: ctx.notify resolves through the notify factory (#1532)", () => {
|
|
370
|
-
test("job handler can call ctx.notify and the factory is bound to the job's system user + tenant", async () => {
|
|
371
|
-
clearLog();
|
|
372
|
-
const calls: Array<{ readonly notifierTenantId: string; readonly notificationType: string }> =
|
|
373
|
-
[];
|
|
374
|
-
const notifyFactory: NotifyFactory = (_user, tenantId) => async (notificationType) => {
|
|
375
|
-
calls.push({ notifierTenantId: tenantId, notificationType });
|
|
376
|
-
};
|
|
377
|
-
|
|
378
|
-
await withRunner(
|
|
379
|
-
async (runner) => {
|
|
380
|
-
await runner.dispatch("test:job:notify-probe", { toUserId: "u1" });
|
|
381
|
-
await waitFor(() => {
|
|
382
|
-
const entries = jobLog.filter((e) => e.name === "test:job:notify-probe");
|
|
383
|
-
expect(entries.length).toBe(1);
|
|
384
|
-
});
|
|
385
|
-
expect(calls).toHaveLength(1);
|
|
386
|
-
expect(calls[0]?.notificationType).toBe("test-notification");
|
|
387
|
-
},
|
|
388
|
-
{ context: { _notifyFactory: notifyFactory } },
|
|
389
|
-
);
|
|
390
|
-
});
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
describe("scenario 3d: ctx.config resolves through the config accessor factory (#1532)", () => {
|
|
394
|
-
test("job handler can call ctx.config and the factory receives a tenant-scoped db", async () => {
|
|
395
|
-
clearLog();
|
|
396
|
-
let receivedDb: unknown;
|
|
397
|
-
const configAccessorFactory: ConfigAccessorFactory = (deps) => {
|
|
398
|
-
receivedDb = deps.db;
|
|
399
|
-
// Stub accessor: only the string-key overload is exercised here.
|
|
400
|
-
return (async () => "probe-value") as ConfigAccessor;
|
|
401
|
-
};
|
|
402
|
-
|
|
403
|
-
await withRunner(
|
|
404
|
-
async (runner) => {
|
|
405
|
-
await runner.dispatch("test:job:config-probe", {});
|
|
406
|
-
await waitFor(() => {
|
|
407
|
-
const entries = jobLog.filter((e) => e.name === "test:job:config-probe");
|
|
408
|
-
expect(entries.length).toBe(1);
|
|
409
|
-
expect(entries[0]?.payload["value"]).toBe("probe-value");
|
|
410
|
-
});
|
|
411
|
-
expect(receivedDb).toBeDefined();
|
|
412
|
-
},
|
|
413
|
-
{ context: { _configAccessorFactory: configAccessorFactory, db: {} as AppContext["db"] } },
|
|
414
|
-
);
|
|
415
|
-
});
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
// --- Concurrency modes ---
|
|
419
|
-
|
|
420
|
-
describe("concurrency: parallel", () => {
|
|
421
|
-
test("multiple parallel jobs all run", async () => {
|
|
422
|
-
clearLog();
|
|
423
|
-
await withRunner(async (runner) => {
|
|
424
|
-
await runner.dispatch("test:job:parallel-job", { n: 1 });
|
|
425
|
-
await runner.dispatch("test:job:parallel-job", { n: 2 });
|
|
426
|
-
await runner.dispatch("test:job:parallel-job", { n: 3 });
|
|
427
|
-
await waitFor(() => {
|
|
428
|
-
const entries = jobLog.filter((e) => e.name === "test:job:parallel-job");
|
|
429
|
-
expect(entries.length).toBe(3);
|
|
430
|
-
});
|
|
431
|
-
});
|
|
432
|
-
});
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
describe("concurrency: skip", () => {
|
|
436
|
-
test("skip mode prevents duplicate execution", async () => {
|
|
437
|
-
clearLog();
|
|
438
|
-
await withRunner(async (runner) => {
|
|
439
|
-
// First job takes 500ms
|
|
440
|
-
await runner.dispatch("test:job:skip-job", { n: 1 });
|
|
441
|
-
|
|
442
|
-
// Try dispatching multiple times while first is running
|
|
443
|
-
let skippedCount = 0;
|
|
444
|
-
// @timeout-exception: #3118 paces repeated dispatch attempts, nothing to poll for
|
|
445
|
-
for (let i = 0; i < 5; i++) {
|
|
446
|
-
await sleep(50);
|
|
447
|
-
const id = await runner.dispatch("test:job:skip-job", { n: i + 2 });
|
|
448
|
-
if (id === "skipped") skippedCount++;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
// Wait until the first (running) job finishes so its log entry lands.
|
|
452
|
-
// Skip-mode guarantees max one job at a time, so we only ever need to
|
|
453
|
-
// see a single entry to know the run settled.
|
|
454
|
-
await waitFor(() => {
|
|
455
|
-
const entries = jobLog.filter((e) => e.name === "test:job:skip-job");
|
|
456
|
-
expect(entries.length).toBeGreaterThanOrEqual(1);
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
// At least some should have been skipped
|
|
460
|
-
expect(skippedCount).toBeGreaterThan(0);
|
|
461
|
-
// Should not have run all 6 times
|
|
462
|
-
const entries = jobLog.filter((e) => e.name === "test:job:skip-job");
|
|
463
|
-
expect(entries.length).toBeLessThan(6);
|
|
464
|
-
});
|
|
465
|
-
});
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
describe("concurrency: sequential", () => {
|
|
469
|
-
test("same-name dispatches run strictly one after the other", async () => {
|
|
470
|
-
clearLog();
|
|
471
|
-
await withRunner(async (runner) => {
|
|
472
|
-
// Three rapid dispatches. Parallel mode would land all entries
|
|
473
|
-
// within a single poll cycle (~50ms apart). The SETNX lock in the
|
|
474
|
-
// job-runner forces them to wait — each picks up only after the
|
|
475
|
-
// previous releases its lock at the end of its 300ms sleep.
|
|
476
|
-
await runner.dispatch("test:job:sequential-job", { n: 1 });
|
|
477
|
-
await runner.dispatch("test:job:sequential-job", { n: 2 });
|
|
478
|
-
await runner.dispatch("test:job:sequential-job", { n: 3 });
|
|
479
|
-
|
|
480
|
-
// Generous polling — re-enqueue with delay 200ms means the third
|
|
481
|
-
// job needs at least ~600ms total to land. Worst case allows for
|
|
482
|
-
// some BullMQ poll overhead.
|
|
483
|
-
await waitFor(
|
|
484
|
-
() => {
|
|
485
|
-
const entries = jobLog.filter((e) => e.name === "test:job:sequential-job");
|
|
486
|
-
expect(entries.length).toBe(3);
|
|
487
|
-
},
|
|
488
|
-
{ delays: [400, 800, 1500, 3000] },
|
|
489
|
-
);
|
|
490
|
-
|
|
491
|
-
const entries = jobLog
|
|
492
|
-
.filter((e) => e.name === "test:job:sequential-job")
|
|
493
|
-
.sort((a, b) => a.timestamp - b.timestamp);
|
|
494
|
-
// Each entry must start at least ~250ms after the previous —
|
|
495
|
-
// sleep is 300ms, with slack for poll overhead. If sequential
|
|
496
|
-
// breaks (lock never acquired, group ignored), the deltas
|
|
497
|
-
// collapse to single-digit milliseconds.
|
|
498
|
-
const delta12 = (entries[1]?.timestamp ?? 0) - (entries[0]?.timestamp ?? 0);
|
|
499
|
-
const delta23 = (entries[2]?.timestamp ?? 0) - (entries[1]?.timestamp ?? 0);
|
|
500
|
-
expect(delta12).toBeGreaterThanOrEqual(250);
|
|
501
|
-
expect(delta23).toBeGreaterThanOrEqual(250);
|
|
502
|
-
|
|
503
|
-
// NOT dispatch order: "sequential" is mutual exclusion, not a FIFO
|
|
504
|
-
// queue. A re-enqueued lock loser goes to the back of its
|
|
505
|
-
// queue, so it can still win the next race. What's guaranteed, and
|
|
506
|
-
// already asserted above via delta12/delta23, is that runs never
|
|
507
|
-
// overlap. Assert the complete set instead of a specific order.
|
|
508
|
-
expect(entries.map((e) => e.payload)).toEqual(
|
|
509
|
-
expect.arrayContaining([{ n: 1 }, { n: 2 }, { n: 3 }]),
|
|
510
|
-
);
|
|
511
|
-
});
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
test("runners with distinct queueNamePrefix do not share the sequential lock", async () => {
|
|
515
|
-
clearLog();
|
|
516
|
-
// Regression guard: the lock key used to omit queueNamePrefix, so two
|
|
517
|
-
// isolated runners sharing a Redis collided on the same lock.
|
|
518
|
-
const prefixA = `kumiko-test-lockscope-a-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
519
|
-
const prefixB = `kumiko-test-lockscope-b-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
520
|
-
const runnerA = createJobRunner({
|
|
521
|
-
registry: createRegistry([testFeature]),
|
|
522
|
-
context: {},
|
|
523
|
-
redisUrl,
|
|
524
|
-
consumerLane: "worker",
|
|
525
|
-
queueNamePrefix: prefixA,
|
|
526
|
-
});
|
|
527
|
-
const runnerB = createJobRunner({
|
|
528
|
-
registry: createRegistry([testFeature]),
|
|
529
|
-
context: {},
|
|
530
|
-
redisUrl,
|
|
531
|
-
consumerLane: "worker",
|
|
532
|
-
queueNamePrefix: prefixB,
|
|
533
|
-
});
|
|
534
|
-
// Own client, no keyPrefix — testRedis.redis auto-prefixes SET/DEL and
|
|
535
|
-
// would write a different key than the runner's own lock connection.
|
|
536
|
-
const lockKeyA = `${RedisKeys.lock}seq:${prefixA}:worker:test:job:sequential-job`;
|
|
537
|
-
const rawRedis = new Redis(redisUrl);
|
|
538
|
-
rawRedis.on("error", () => {});
|
|
539
|
-
const queueA = new Queue(`${prefixA}-worker`, {
|
|
540
|
-
connection: { host: testRedis.redis.options.host, port: testRedis.redis.options.port },
|
|
541
|
-
});
|
|
542
|
-
// A post-close 'error' here is otherwise unhandled and bun:test
|
|
543
|
-
// attributes it to whichever test runs next (fw#1805).
|
|
544
|
-
queueA.on("error", () => {});
|
|
545
|
-
|
|
546
|
-
try {
|
|
547
|
-
await rawRedis.set(lockKeyA, "held-by-test", "EX", 30, "NX");
|
|
548
|
-
|
|
549
|
-
await runnerA.start();
|
|
550
|
-
await runnerB.start();
|
|
551
|
-
|
|
552
|
-
await runnerA.dispatch("test:job:sequential-job", { n: 100 });
|
|
553
|
-
|
|
554
|
-
// A's handler returns successfully on a lock loss (re-enqueue, not a
|
|
555
|
-
// throw) — BullMQ records the dropped attempt as completed even
|
|
556
|
-
// though the job body never ran. Filtered by name+payload so unrelated
|
|
557
|
-
// boot/cron jobs on the same worker queue don't false-positive this.
|
|
558
|
-
await waitFor(
|
|
559
|
-
async () => {
|
|
560
|
-
const completed = await queueA.getCompleted();
|
|
561
|
-
const lostAttempts = completed.filter(
|
|
562
|
-
(job) => job.name === "test:job:sequential-job" && job.data.n === 100,
|
|
563
|
-
);
|
|
564
|
-
expect(lostAttempts.length).toBeGreaterThanOrEqual(1);
|
|
565
|
-
},
|
|
566
|
-
{ delays: [400, 800, 1500, 3000] },
|
|
567
|
-
);
|
|
568
|
-
expect(
|
|
569
|
-
jobLog.some((e) => e.name === "test:job:sequential-job" && e.payload["n"] === 100),
|
|
570
|
-
).toBe(false);
|
|
571
|
-
|
|
572
|
-
// B shares no lock scope with the externally held A-key, so it must
|
|
573
|
-
// run despite A being blocked.
|
|
574
|
-
await runnerB.dispatch("test:job:sequential-job", { n: 200 });
|
|
575
|
-
await waitFor(
|
|
576
|
-
() => {
|
|
577
|
-
const entries = jobLog.filter(
|
|
578
|
-
(e) => e.name === "test:job:sequential-job" && e.payload["n"] === 200,
|
|
579
|
-
);
|
|
580
|
-
expect(entries.length).toBeGreaterThanOrEqual(1);
|
|
581
|
-
},
|
|
582
|
-
{ delays: [400, 800, 1500, 3000] },
|
|
583
|
-
);
|
|
584
|
-
|
|
585
|
-
// Releasing the externally held key unblocks A's own dispatch.
|
|
586
|
-
await rawRedis.del(lockKeyA);
|
|
587
|
-
await waitFor(
|
|
588
|
-
() => {
|
|
589
|
-
const entries = jobLog.filter(
|
|
590
|
-
(e) => e.name === "test:job:sequential-job" && e.payload["n"] === 100,
|
|
591
|
-
);
|
|
592
|
-
expect(entries.length).toBeGreaterThanOrEqual(1);
|
|
593
|
-
},
|
|
594
|
-
{ delays: [400, 800, 1500, 3000] },
|
|
595
|
-
);
|
|
596
|
-
} finally {
|
|
597
|
-
await runnerA.stop();
|
|
598
|
-
await runnerB.stop();
|
|
599
|
-
await queueA.close();
|
|
600
|
-
await rawRedis.del(lockKeyA);
|
|
601
|
-
rawRedis.disconnect();
|
|
602
|
-
const keysA = await testRedis.redis.keys(`bull:${prefixA}-worker:*`);
|
|
603
|
-
if (keysA.length > 0) await testRedis.redis.del(...keysA);
|
|
604
|
-
const keysB = await testRedis.redis.keys(`bull:${prefixB}-worker:*`);
|
|
605
|
-
if (keysB.length > 0) await testRedis.redis.del(...keysB);
|
|
606
|
-
}
|
|
607
|
-
});
|
|
608
|
-
|
|
609
|
-
test("lock is released even when the handler throws", async () => {
|
|
610
|
-
clearLog();
|
|
611
|
-
await withRunner(async (runner) => {
|
|
612
|
-
// First dispatch fails. If the finally-path didn't release the lock,
|
|
613
|
-
// the second dispatch couldn't acquire it and would loop forever in
|
|
614
|
-
// the re-enqueue path until BullMQ gave up.
|
|
615
|
-
await runner.dispatch("test:job:sequential-fail-job", { n: 1 });
|
|
616
|
-
await waitFor(
|
|
617
|
-
() => {
|
|
618
|
-
const entries = jobLog.filter((e) => e.name === "test:job:sequential-fail-job");
|
|
619
|
-
expect(entries.length).toBeGreaterThanOrEqual(1);
|
|
620
|
-
},
|
|
621
|
-
{ delays: [200, 400, 800] },
|
|
622
|
-
);
|
|
623
|
-
// Tiny grace so BullMQ marks the failed job done and our finally
|
|
624
|
-
// ran — otherwise the lock-release race could outlast the next
|
|
625
|
-
// dispatch's acquire attempt.
|
|
626
|
-
await sleep(150);
|
|
627
|
-
|
|
628
|
-
// No surviving lock for this job-name in Redis — the value-matched
|
|
629
|
-
// DEL ran in finally.
|
|
630
|
-
const surviving = await testRedis.redis.keys("kumiko:lock:seq:*sequential-fail-job");
|
|
631
|
-
expect(surviving.length).toBe(0);
|
|
632
|
-
|
|
633
|
-
// Fresh dispatch must run — proves the lock isn't blocking new
|
|
634
|
-
// arrivals after the throw.
|
|
635
|
-
await runner.dispatch("test:job:sequential-fail-job", { n: 2 });
|
|
636
|
-
await waitFor(
|
|
637
|
-
() => {
|
|
638
|
-
const entries = jobLog.filter((e) => e.name === "test:job:sequential-fail-job");
|
|
639
|
-
expect(entries.length).toBeGreaterThanOrEqual(2);
|
|
640
|
-
},
|
|
641
|
-
{ delays: [200, 400, 800] },
|
|
642
|
-
);
|
|
643
|
-
});
|
|
644
|
-
});
|
|
645
|
-
|
|
646
|
-
test("lock release is value-matched: foreign tokens survive expiration races", async () => {
|
|
647
|
-
// Pin the contract that distributed-lock's release script enforces:
|
|
648
|
-
// a release call from a worker whose token has already expired and
|
|
649
|
-
// been claimed by someone else must NOT delete the new owner's lock.
|
|
650
|
-
// Tested at the lock layer because we can't reliably race a TTL
|
|
651
|
-
// expiration inside the job-runner inside a 5s test budget.
|
|
652
|
-
const { createDistributedLock } = await import("../../pipeline/distributed-lock");
|
|
653
|
-
const prefix = "kumiko:lock:seq:test-vmd:";
|
|
654
|
-
const lock = createDistributedLock(testRedis.redis, prefix);
|
|
655
|
-
|
|
656
|
-
const tokenA = await lock.acquire("contract-key", { ttlSeconds: 10 });
|
|
657
|
-
expect(tokenA).not.toBeNull();
|
|
658
|
-
// Forcibly take it away — simulates the TTL-expired-and-reclaimed
|
|
659
|
-
// sequence without waiting 10s.
|
|
660
|
-
await testRedis.redis.set(`${prefix}contract-key`, "different-token");
|
|
661
|
-
|
|
662
|
-
// Worker A (now stale) tries to release: must be a no-op.
|
|
663
|
-
const releasedByStale = await lock.release("contract-key", tokenA as string);
|
|
664
|
-
expect(releasedByStale).toBe(false);
|
|
665
|
-
const stillHeld = await testRedis.redis.get(`${prefix}contract-key`);
|
|
666
|
-
expect(stillHeld).toBe("different-token");
|
|
667
|
-
|
|
668
|
-
await testRedis.redis.del(`${prefix}contract-key`);
|
|
669
|
-
});
|
|
670
|
-
});
|
|
671
|
-
|
|
672
|
-
describe("concurrency: debounce", () => {
|
|
673
|
-
test("rapid dispatches result in fewer executions than dispatches", async () => {
|
|
674
|
-
clearLog();
|
|
675
|
-
await withRunner(async (runner) => {
|
|
676
|
-
// Rapid fire 5 times — debounce should collapse some
|
|
677
|
-
await runner.dispatch("test:job:debounce-job", { n: 1 });
|
|
678
|
-
await runner.dispatch("test:job:debounce-job", { n: 2 });
|
|
679
|
-
await runner.dispatch("test:job:debounce-job", { n: 3 });
|
|
680
|
-
await runner.dispatch("test:job:debounce-job", { n: 4 });
|
|
681
|
-
await runner.dispatch("test:job:debounce-job", { n: 5 });
|
|
682
|
-
|
|
683
|
-
// Debounce (300ms) fires after the last rapid dispatch, then BullMQ
|
|
684
|
-
// picks the job up — first successful poll usually lands around 500ms.
|
|
685
|
-
await waitFor(
|
|
686
|
-
() => {
|
|
687
|
-
const entries = jobLog.filter((e) => e.name === "test:job:debounce-job");
|
|
688
|
-
expect(entries.length).toBeGreaterThanOrEqual(1);
|
|
689
|
-
},
|
|
690
|
-
{ delays: [500, 1000, 2000] },
|
|
691
|
-
);
|
|
692
|
-
|
|
693
|
-
const entries = jobLog.filter((e) => e.name === "test:job:debounce-job");
|
|
694
|
-
// Debounce should result in fewer executions than dispatches
|
|
695
|
-
expect(entries.length).toBeLessThan(5);
|
|
696
|
-
expect(entries.length).toBeGreaterThanOrEqual(1);
|
|
697
|
-
});
|
|
698
|
-
});
|
|
699
|
-
});
|
|
700
|
-
|
|
701
|
-
describe("concurrency: replace", () => {
|
|
702
|
-
test("enqueuer-only: each dispatch removes prior waiting peers", async () => {
|
|
703
|
-
// No consumer → jobs stay waiting. The replace branch walks getWaiting()
|
|
704
|
-
// and removes same-name peers before add — so three dispatches leave one.
|
|
705
|
-
const queueNamePrefix = `kumiko-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
706
|
-
await withRunner(
|
|
707
|
-
async (runner) => {
|
|
708
|
-
const id1 = await runner.dispatch("test:job:replace-job", { n: 1 });
|
|
709
|
-
const id2 = await runner.dispatch("test:job:replace-job", { n: 2 });
|
|
710
|
-
const id3 = await runner.dispatch("test:job:replace-job", { n: 3 });
|
|
711
|
-
expect(id1).toBeDefined();
|
|
712
|
-
expect(id2).toBeDefined();
|
|
713
|
-
expect(id3).toBeDefined();
|
|
714
|
-
expect(id1).not.toBe("skipped");
|
|
715
|
-
expect(id3).not.toBe(id1);
|
|
716
|
-
|
|
717
|
-
const queue = new Queue(`${queueNamePrefix}-worker`, {
|
|
718
|
-
connection: { host: testRedis.redis.options.host, port: testRedis.redis.options.port },
|
|
719
|
-
});
|
|
720
|
-
// A post-close 'error' here is otherwise unhandled and bun:test
|
|
721
|
-
// attributes it to whichever test runs next (fw#1805).
|
|
722
|
-
queue.on("error", () => {});
|
|
723
|
-
try {
|
|
724
|
-
const waiting = (await queue.getWaiting()).filter(
|
|
725
|
-
(job) => job.name === "test:job:replace-job",
|
|
726
|
-
);
|
|
727
|
-
expect(waiting).toHaveLength(1);
|
|
728
|
-
expect(waiting[0]?.data.n).toBe(3);
|
|
729
|
-
} finally {
|
|
730
|
-
await queue.close();
|
|
731
|
-
}
|
|
732
|
-
},
|
|
733
|
-
{ consumerLane: undefined, queueNamePrefix },
|
|
734
|
-
);
|
|
735
|
-
});
|
|
736
|
-
});
|
|
737
|
-
|
|
738
|
-
describe("concurrency: maxPerTenant", () => {
|
|
739
|
-
test("max=2: third dispatch for same tenant returns skipped, other tenant unaffected", async () => {
|
|
740
|
-
clearLog();
|
|
741
|
-
await withRunner(async (runner) => {
|
|
742
|
-
const tenantA = "tenant-a";
|
|
743
|
-
const tenantB = "tenant-b";
|
|
744
|
-
|
|
745
|
-
// First two for tenantA fill the bucket — both should accept.
|
|
746
|
-
const idA1 = await runner.dispatch("test:job:per-tenant-limited", {
|
|
747
|
-
n: 1,
|
|
748
|
-
_tenantId: tenantA,
|
|
749
|
-
});
|
|
750
|
-
const idA2 = await runner.dispatch("test:job:per-tenant-limited", {
|
|
751
|
-
n: 2,
|
|
752
|
-
_tenantId: tenantA,
|
|
753
|
-
});
|
|
754
|
-
expect(idA1).not.toBe("skipped:max-per-tenant");
|
|
755
|
-
expect(idA2).not.toBe("skipped:max-per-tenant");
|
|
756
|
-
|
|
757
|
-
// Third for tenantA hits the cap before BullMQ drains the first.
|
|
758
|
-
// Small sleep so we don't race the queue.add of the first two.
|
|
759
|
-
await sleep(50);
|
|
760
|
-
const idA3 = await runner.dispatch("test:job:per-tenant-limited", {
|
|
761
|
-
n: 3,
|
|
762
|
-
_tenantId: tenantA,
|
|
763
|
-
});
|
|
764
|
-
expect(idA3).toBe("skipped:max-per-tenant");
|
|
765
|
-
|
|
766
|
-
// tenantB has its own bucket — accepted.
|
|
767
|
-
const idB1 = await runner.dispatch("test:job:per-tenant-limited", {
|
|
768
|
-
n: 4,
|
|
769
|
-
_tenantId: tenantB,
|
|
770
|
-
});
|
|
771
|
-
expect(idB1).not.toBe("skipped:max-per-tenant");
|
|
772
|
-
|
|
773
|
-
// After the 500ms-handlers settle the bucket empties. jobLog.push runs
|
|
774
|
-
// at handler START, so a log entry doesn't mean the job is "done" —
|
|
775
|
-
// it's still in `active` for the rest of the sleep. Wait long enough
|
|
776
|
-
// that the slowest 500ms handler has returned, then a fresh tenantA
|
|
777
|
-
// dispatch lands again.
|
|
778
|
-
await sleep(900);
|
|
779
|
-
const idA4 = await runner.dispatch("test:job:per-tenant-limited", {
|
|
780
|
-
n: 5,
|
|
781
|
-
_tenantId: tenantA,
|
|
782
|
-
});
|
|
783
|
-
expect(idA4).not.toBe("skipped:max-per-tenant");
|
|
784
|
-
});
|
|
785
|
-
});
|
|
786
|
-
|
|
787
|
-
test("missing _tenantId disables the guard (backwards-compatible)", async () => {
|
|
788
|
-
clearLog();
|
|
789
|
-
await withRunner(async (runner) => {
|
|
790
|
-
// No _tenantId in payload — guard inactive, all 4 accepted regardless of cap.
|
|
791
|
-
for (let i = 0; i < 4; i++) {
|
|
792
|
-
const id = await runner.dispatch("test:job:per-tenant-limited", { n: i });
|
|
793
|
-
expect(id).not.toBe("skipped:max-per-tenant");
|
|
794
|
-
}
|
|
795
|
-
});
|
|
796
|
-
});
|
|
797
|
-
});
|
|
798
|
-
|
|
799
|
-
// --- Correlation propagation ---
|
|
800
|
-
|
|
801
|
-
describe("job logger", () => {
|
|
802
|
-
test("handler can call info/warn/error/debug/child without throw", async () => {
|
|
803
|
-
clearLog();
|
|
804
|
-
await withRunner(async (runner) => {
|
|
805
|
-
await runner.dispatch("test:job:log-probe", { n: 1 });
|
|
806
|
-
await waitFor(() => {
|
|
807
|
-
expect(jobLog.some((e) => e.name === "test:job:log-probe")).toBe(true);
|
|
808
|
-
});
|
|
809
|
-
});
|
|
810
|
-
});
|
|
811
|
-
|
|
812
|
-
// Inspects the actual createJobLogger output instead of only asserting the
|
|
813
|
-
// handler ran — a child() that drops its context or a warn() mapped to
|
|
814
|
-
// debug would previously stay green.
|
|
815
|
-
test("info/warn/error land with the right level; debug is dropped; child merges its context", async () => {
|
|
816
|
-
clearLog();
|
|
817
|
-
let capturedLogs: JobLogEntry[] = [];
|
|
818
|
-
await withRunner(
|
|
819
|
-
async (runner) => {
|
|
820
|
-
await runner.dispatch("test:job:log-probe", { n: 1 });
|
|
821
|
-
await waitFor(() => {
|
|
822
|
-
expect(capturedLogs.length).toBeGreaterThan(0);
|
|
823
|
-
});
|
|
824
|
-
},
|
|
825
|
-
{
|
|
826
|
-
onJobComplete: (jobName, _id, _duration, logs) => {
|
|
827
|
-
if (jobName === "test:job:log-probe") capturedLogs = logs;
|
|
828
|
-
},
|
|
829
|
-
},
|
|
830
|
-
);
|
|
831
|
-
|
|
832
|
-
// debug() is a no-op by design (JobLogEntry.level has no "debug" slot) —
|
|
833
|
-
// info/warn/error from the handler body, plus one from child().info(...).
|
|
834
|
-
expect(capturedLogs).toHaveLength(4);
|
|
835
|
-
expect(capturedLogs.map((l) => l.level)).toEqual(["info", "warn", "error", "info"]);
|
|
836
|
-
expect(capturedLogs[0]?.message).toContain("log-probe-info");
|
|
837
|
-
expect(capturedLogs[3]?.message).toContain("log-probe-child");
|
|
838
|
-
expect(capturedLogs[3]?.message).toContain("probe");
|
|
839
|
-
expect(capturedLogs[3]?.message).toContain("true");
|
|
840
|
-
});
|
|
841
|
-
});
|
|
842
|
-
|
|
843
|
-
describe("correlation propagation", () => {
|
|
844
|
-
test("dispatch inside requestContext.run passes correlationId into the job", async () => {
|
|
845
|
-
clearLog();
|
|
846
|
-
await withRunner(async (runner) => {
|
|
847
|
-
// Enter a synthetic request-context, dispatch → the scheduler should
|
|
848
|
-
// pack the correlationId into the job data; the worker reads it back
|
|
849
|
-
// and re-enters requestContext.run.
|
|
850
|
-
await requestContext.run(
|
|
851
|
-
{ requestId: "req-outer", correlationId: "carry-me-across-bullmq" },
|
|
852
|
-
async () => {
|
|
853
|
-
await runner.dispatch("test:job:correlation-probe", { n: 1 });
|
|
854
|
-
},
|
|
855
|
-
);
|
|
856
|
-
await waitFor(() => {
|
|
857
|
-
const entries = jobLog.filter((e) => e.name === "test:job:correlation-probe");
|
|
858
|
-
expect(entries.length).toBe(1);
|
|
859
|
-
});
|
|
860
|
-
const entry = jobLog.find((e) => e.name === "test:job:correlation-probe");
|
|
861
|
-
expect(entry?.payload["observedCorrelationId"]).toBe("carry-me-across-bullmq");
|
|
862
|
-
// requestId is fresh per job run, NOT the scheduler's requestId.
|
|
863
|
-
expect(entry?.payload["observedRequestId"]).not.toBe("req-outer");
|
|
864
|
-
expect(typeof entry?.payload["observedRequestId"]).toBe("string");
|
|
865
|
-
});
|
|
866
|
-
});
|
|
867
|
-
|
|
868
|
-
test("dispatch outside any request-context: job gets a fresh correlationId (not null)", async () => {
|
|
869
|
-
clearLog();
|
|
870
|
-
await withRunner(async (runner) => {
|
|
871
|
-
await runner.dispatch("test:job:correlation-probe", { n: 2 });
|
|
872
|
-
await waitFor(() => {
|
|
873
|
-
const entries = jobLog.filter((e) => e.name === "test:job:correlation-probe");
|
|
874
|
-
expect(entries.length).toBe(1);
|
|
875
|
-
});
|
|
876
|
-
const entry = jobLog.find((e) => e.name === "test:job:correlation-probe");
|
|
877
|
-
// Fresh correlationId — new requestId mirrored onto correlationId
|
|
878
|
-
// when no parent-context provided one.
|
|
879
|
-
expect(typeof entry?.payload["observedCorrelationId"]).toBe("string");
|
|
880
|
-
expect(entry?.payload["observedCorrelationId"]).toBe(entry?.payload["observedRequestId"]);
|
|
881
|
-
});
|
|
882
|
-
});
|
|
883
|
-
});
|
|
884
|
-
|
|
885
|
-
// --- Error handling ---
|
|
886
|
-
|
|
887
|
-
describe("error handling", () => {
|
|
888
|
-
test("failing job is caught, does not crash worker", async () => {
|
|
889
|
-
clearLog();
|
|
890
|
-
await withRunner(async (runner) => {
|
|
891
|
-
const id = await runner.dispatch("test:job:failing-job");
|
|
892
|
-
expect(id).toBeDefined();
|
|
893
|
-
|
|
894
|
-
// No fixed sleep needed — the follow-up dispatch + waitFor below prove
|
|
895
|
-
// the worker is still alive. If the failing job had crashed the worker,
|
|
896
|
-
// the manual-report would never land and waitFor would time out.
|
|
897
|
-
await runner.dispatch("test:job:manual-report", { after: "failure" });
|
|
898
|
-
await waitFor(() => {
|
|
899
|
-
const entries = jobLog.filter((e) => e.name === "test:job:manual-report");
|
|
900
|
-
expect(entries.length).toBeGreaterThanOrEqual(1);
|
|
901
|
-
});
|
|
902
|
-
});
|
|
903
|
-
});
|
|
904
|
-
|
|
905
|
-
test("onJobFailed receives the handler error on each attempt", async () => {
|
|
906
|
-
clearLog();
|
|
907
|
-
const failures: Array<{ jobName: string; error: string }> = [];
|
|
908
|
-
const starts: JobMeta[] = [];
|
|
909
|
-
await withRunner(
|
|
910
|
-
async (runner) => {
|
|
911
|
-
await runner.dispatch("test:job:failing-job");
|
|
912
|
-
// retries: 1 → attempts = 2 (initial + one retry)
|
|
913
|
-
await waitFor(() => {
|
|
914
|
-
expect(failures.length).toBeGreaterThanOrEqual(2);
|
|
915
|
-
});
|
|
916
|
-
expect(failures.every((f) => f.jobName === "test:job:failing-job")).toBe(true);
|
|
917
|
-
expect(failures.every((f) => f.error === "intentional failure")).toBe(true);
|
|
918
|
-
expect(starts.map((s) => s.attempt)).toEqual([1, 2]);
|
|
919
|
-
|
|
920
|
-
// Worker still alive after exhausted retries
|
|
921
|
-
await runner.dispatch("test:job:manual-report", { after: "retries" });
|
|
922
|
-
await waitFor(() => {
|
|
923
|
-
expect(
|
|
924
|
-
jobLog.some(
|
|
925
|
-
(e) => e.name === "test:job:manual-report" && e.payload["after"] === "retries",
|
|
926
|
-
),
|
|
927
|
-
).toBe(true);
|
|
928
|
-
});
|
|
929
|
-
},
|
|
930
|
-
{
|
|
931
|
-
onJobStart: (name, _id, meta) => {
|
|
932
|
-
if (name === "test:job:failing-job") starts.push(meta);
|
|
933
|
-
},
|
|
934
|
-
onJobFailed: (jobName, _id, error) => {
|
|
935
|
-
if (jobName === "test:job:failing-job") failures.push({ jobName, error });
|
|
936
|
-
},
|
|
937
|
-
},
|
|
938
|
-
);
|
|
939
|
-
});
|
|
940
|
-
|
|
941
|
-
test("ctx.write throws before attachDispatcher() has run (framework#2043)", async () => {
|
|
942
|
-
clearLog();
|
|
943
|
-
const failures: string[] = [];
|
|
944
|
-
await withRunner(
|
|
945
|
-
async (runner) => {
|
|
946
|
-
await runner.dispatch("test:job:write-probe");
|
|
947
|
-
await waitFor(() => {
|
|
948
|
-
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
949
|
-
});
|
|
950
|
-
expect(failures[0]).toContain(
|
|
951
|
-
"JobContext.write called before dispatcher attached — call attachDispatcher() first",
|
|
952
|
-
);
|
|
953
|
-
},
|
|
954
|
-
{
|
|
955
|
-
onJobFailed: (jobName, _id, error) => {
|
|
956
|
-
if (jobName === "test:job:write-probe") failures.push(error);
|
|
957
|
-
},
|
|
958
|
-
},
|
|
959
|
-
);
|
|
960
|
-
});
|
|
961
|
-
|
|
962
|
-
test("perTenant without getActiveTenantIds fails wrapper; worker stays alive", async () => {
|
|
963
|
-
clearLog();
|
|
964
|
-
await withRunner(async (runner) => {
|
|
965
|
-
await runner.dispatch("test:job:per-tenant-fanout", { n: 1 });
|
|
966
|
-
// Wrapper throws before fan-out (and before onJobFailed) — settle, then
|
|
967
|
-
// prove the worker still consumes.
|
|
968
|
-
await sleep(300);
|
|
969
|
-
expect(jobLog.filter((e) => e.name === "test:job:per-tenant-fanout")).toHaveLength(0);
|
|
970
|
-
|
|
971
|
-
await runner.dispatch("test:job:manual-report", { after: "perTenant-miss" });
|
|
972
|
-
await waitFor(() => {
|
|
973
|
-
expect(jobLog.some((e) => e.name === "test:job:manual-report")).toBe(true);
|
|
974
|
-
});
|
|
975
|
-
});
|
|
976
|
-
});
|
|
977
|
-
|
|
978
|
-
test("perTenant with getActiveTenantIds fans out one run per tenant", async () => {
|
|
979
|
-
clearLog();
|
|
980
|
-
// @cast-boundary test fixture: TenantId is a branded string.
|
|
981
|
-
const tenants = ["per-tenant-fanout-a", "per-tenant-fanout-b"] as TenantId[];
|
|
982
|
-
await withRunner(
|
|
983
|
-
async (runner) => {
|
|
984
|
-
await runner.dispatch("test:job:per-tenant-fanout", { n: 7 });
|
|
985
|
-
await waitFor(() => {
|
|
986
|
-
const runs = jobLog.filter((e) => e.name === "test:job:per-tenant-fanout");
|
|
987
|
-
expect(runs.length).toBe(2);
|
|
988
|
-
expect(runs.every((e) => e.payload["n"] === 7)).toBe(true);
|
|
989
|
-
});
|
|
990
|
-
},
|
|
991
|
-
{ getActiveTenantIds: async () => tenants },
|
|
992
|
-
);
|
|
993
|
-
});
|
|
994
|
-
});
|
|
995
|
-
|
|
996
|
-
// --- Multiple runner instances against the same Redis (prod runs N replicas
|
|
997
|
-
// of the worker process) — proves the scheduler dedups across instances and
|
|
998
|
-
// that per-tenant children distribute across whichever worker picks them up,
|
|
999
|
-
// not just the instance that ran the fan-out. Own registries/log per test,
|
|
1000
|
-
// not the shared testFeature/jobLog — a per-second cron must not tick
|
|
1001
|
-
// during every other test in this file, and the two scenarios below must
|
|
1002
|
-
// not observe each other's fan-outs. Job handlers tag their entry with
|
|
1003
|
-
// `ctx.db`, which each runner instance sets to a literal string instead of
|
|
1004
|
-
// a real DbConnection — a cheap already-typed, already-threaded channel for
|
|
1005
|
-
// "which runner instance ran this" (mirrors the `ctx["systemUser"] as
|
|
1006
|
-
// SessionUser` cast the multi-tenant.integration.test.ts billing job uses).
|
|
1007
|
-
describe("perTenant across multiple runner instances", () => {
|
|
1008
|
-
test("a cron tick fires the perTenant wrapper exactly once, not once per runner instance", async () => {
|
|
1009
|
-
const log: Array<{ tenantId: string; runnerTag: string }> = [];
|
|
1010
|
-
const cronFeature = defineFeature("multicron", (r) => {
|
|
1011
|
-
r.job(
|
|
1012
|
-
"fanout",
|
|
1013
|
-
{ trigger: { cron: "* * * * * *" }, perTenant: true },
|
|
1014
|
-
async (_payload, ctx) => {
|
|
1015
|
-
log.push({
|
|
1016
|
-
tenantId: String(ctx.systemUser.tenantId),
|
|
1017
|
-
runnerTag: tenantDbRunner(ctx.db) as unknown as string, // @cast-boundary test fixture — runner context db is a tag string
|
|
1018
|
-
});
|
|
1019
|
-
},
|
|
1020
|
-
);
|
|
1021
|
-
});
|
|
1022
|
-
|
|
1023
|
-
const tenants = ["multi-cron-a", "multi-cron-b"] as TenantId[];
|
|
1024
|
-
let wrapperCalls = 0;
|
|
1025
|
-
const getActiveTenantIds = async () => {
|
|
1026
|
-
wrapperCalls++;
|
|
1027
|
-
return tenants;
|
|
1028
|
-
};
|
|
1029
|
-
const registry = createRegistry([cronFeature]);
|
|
1030
|
-
const queueNamePrefix = `kumiko-test-multi-cron-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1031
|
-
const runnerA = createJobRunner({
|
|
1032
|
-
registry,
|
|
1033
|
-
context: { db: "runner-a" as unknown as AppContext["db"] },
|
|
1034
|
-
redisUrl,
|
|
1035
|
-
consumerLane: "worker",
|
|
1036
|
-
queueNamePrefix,
|
|
1037
|
-
getActiveTenantIds,
|
|
1038
|
-
});
|
|
1039
|
-
const runnerB = createJobRunner({
|
|
1040
|
-
registry,
|
|
1041
|
-
context: { db: "runner-b" as unknown as AppContext["db"] },
|
|
1042
|
-
redisUrl,
|
|
1043
|
-
consumerLane: "worker",
|
|
1044
|
-
queueNamePrefix,
|
|
1045
|
-
getActiveTenantIds,
|
|
1046
|
-
});
|
|
1047
|
-
// Query BullMQ directly rather than inferring dedup from log ratios —
|
|
1048
|
-
// wrapperCalls is incremented by every wrapper run, so a ratio against
|
|
1049
|
-
// it stays constant whether the wrapper fired once or twice per tick.
|
|
1050
|
-
const rawQueue = new Queue(`${queueNamePrefix}-worker`, {
|
|
1051
|
-
connection: { host: testRedis.redis.options.host, port: testRedis.redis.options.port },
|
|
1052
|
-
});
|
|
1053
|
-
// A post-close 'error' here is otherwise unhandled and bun:test
|
|
1054
|
-
// attributes it to whichever test runs next (fw#1805).
|
|
1055
|
-
rawQueue.on("error", () => {});
|
|
1056
|
-
// Snapshot of completed wrapper runs — declared outside try so the
|
|
1057
|
-
// post-finally fan-out check can read it.
|
|
1058
|
-
let drainedCalls = 0;
|
|
1059
|
-
try {
|
|
1060
|
-
// Both instances call start() → both call upsertJobScheduler() with
|
|
1061
|
-
// the SAME schedulerId against the SAME Redis. If that didn't dedup,
|
|
1062
|
-
// there would be two scheduler entries and two independent repeat
|
|
1063
|
-
// timers driving the tick below.
|
|
1064
|
-
await runnerA.start();
|
|
1065
|
-
await runnerB.start();
|
|
1066
|
-
// The actual once-per-tick proof: exactly one scheduler entry exists
|
|
1067
|
-
// for this job in Redis, regardless of how many runner instances
|
|
1068
|
-
// called upsertJobScheduler() against it. Two entries here means two
|
|
1069
|
-
// independent repeat timers, which would double-fire every tick.
|
|
1070
|
-
expect(await rawQueue.getJobSchedulersCount()).toBe(1);
|
|
1071
|
-
// Wait for the asserted drain state while workers are still up —
|
|
1072
|
-
// stop() tears down consumers, so a post-finally sleep/assert races
|
|
1073
|
-
// on unprocessed children (fw#2556: expected 4, got 2). Snapshot
|
|
1074
|
-
// drainedCalls inside the predicate; do not assert a post-stop
|
|
1075
|
-
// log-length ceiling — in-flight children (and sequential multi-
|
|
1076
|
-
// runner stop) can still append after the snapshot.
|
|
1077
|
-
await waitFor(
|
|
1078
|
-
() => {
|
|
1079
|
-
expect(wrapperCalls).toBeGreaterThanOrEqual(1);
|
|
1080
|
-
expect(log.length).toBe(wrapperCalls * tenants.length);
|
|
1081
|
-
drainedCalls = wrapperCalls;
|
|
1082
|
-
},
|
|
1083
|
-
{ delays: [2000, 3000, 5000] },
|
|
1084
|
-
);
|
|
1085
|
-
} finally {
|
|
1086
|
-
await runnerA.stop();
|
|
1087
|
-
await runnerB.stop();
|
|
1088
|
-
await rawQueue.close();
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
// Secondary sanity check only — this ratio holds whether the wrapper
|
|
1092
|
-
// fired once or twice per tick (wrapperCalls scales with it either
|
|
1093
|
-
// way), so it does not by itself prove the once-per-tick invariant.
|
|
1094
|
-
// It only confirms each wrapper run that did happen fanned out to
|
|
1095
|
-
// every tenant exactly once. Slice to the drained prefix so a late
|
|
1096
|
-
// tick that lands during stop() cannot break the multiset check.
|
|
1097
|
-
expect(log.length).toBeGreaterThanOrEqual(drainedCalls * tenants.length);
|
|
1098
|
-
const seenTenants = log
|
|
1099
|
-
.slice(0, drainedCalls * tenants.length)
|
|
1100
|
-
.map((e) => e.tenantId)
|
|
1101
|
-
.sort();
|
|
1102
|
-
const expectedTenants = Array.from({ length: drainedCalls }, () => tenants)
|
|
1103
|
-
.flat()
|
|
1104
|
-
.sort();
|
|
1105
|
-
expect(seenTenants).toEqual(expectedTenants);
|
|
1106
|
-
});
|
|
1107
|
-
|
|
1108
|
-
test("manual per-tenant fan-out distributes children across both worker instances", async () => {
|
|
1109
|
-
const log: Array<{ tenantId: string; runnerTag: string }> = [];
|
|
1110
|
-
const manualFeature = defineFeature("multiworker", (r) => {
|
|
1111
|
-
r.job("fanout", { trigger: { manual: true }, perTenant: true }, async (_payload, ctx) => {
|
|
1112
|
-
// Widen the window both worker instances are actively racing for
|
|
1113
|
-
// children in — without it, a fast single worker could drain a
|
|
1114
|
-
// small batch before the other instance's blocking queue-pop even
|
|
1115
|
-
// wakes up, which would prove nothing either way.
|
|
1116
|
-
await sleep(80);
|
|
1117
|
-
log.push({
|
|
1118
|
-
tenantId: String(ctx.systemUser.tenantId),
|
|
1119
|
-
runnerTag: tenantDbRunner(ctx.db) as unknown as string, // @cast-boundary test fixture — runner context db is a tag string
|
|
1120
|
-
});
|
|
1121
|
-
});
|
|
1122
|
-
});
|
|
1123
|
-
|
|
1124
|
-
// 12 > a single worker's hardcoded concurrency (5) — with both
|
|
1125
|
-
// instances already polling before dispatch, the overflow past one
|
|
1126
|
-
// worker's cap can only be served by the other.
|
|
1127
|
-
const tenants = Array.from({ length: 12 }, (_, i) => `multi-worker-${i}`) as TenantId[];
|
|
1128
|
-
const getActiveTenantIds = async () => tenants;
|
|
1129
|
-
const registry = createRegistry([manualFeature]);
|
|
1130
|
-
const queueNamePrefix = `kumiko-test-multi-worker-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1131
|
-
const runnerA = createJobRunner({
|
|
1132
|
-
registry,
|
|
1133
|
-
context: { db: "runner-a" as unknown as AppContext["db"] },
|
|
1134
|
-
redisUrl,
|
|
1135
|
-
consumerLane: "worker",
|
|
1136
|
-
queueNamePrefix,
|
|
1137
|
-
getActiveTenantIds,
|
|
1138
|
-
});
|
|
1139
|
-
const runnerB = createJobRunner({
|
|
1140
|
-
registry,
|
|
1141
|
-
context: { db: "runner-b" as unknown as AppContext["db"] },
|
|
1142
|
-
redisUrl,
|
|
1143
|
-
consumerLane: "worker",
|
|
1144
|
-
queueNamePrefix,
|
|
1145
|
-
getActiveTenantIds,
|
|
1146
|
-
});
|
|
1147
|
-
try {
|
|
1148
|
-
await runnerA.start();
|
|
1149
|
-
await runnerB.start();
|
|
1150
|
-
await runnerA.dispatch("multiworker:job:fanout");
|
|
1151
|
-
await waitFor(
|
|
1152
|
-
() => {
|
|
1153
|
-
expect(log.length).toBe(tenants.length);
|
|
1154
|
-
},
|
|
1155
|
-
{ delays: [200, 300, 500, 1000] },
|
|
1156
|
-
);
|
|
1157
|
-
} finally {
|
|
1158
|
-
await runnerA.stop();
|
|
1159
|
-
await runnerB.stop();
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
// Every tenant ran exactly once — no duplicate fan-out.
|
|
1163
|
-
expect(log.map((e) => e.tenantId).sort()).toEqual([...tenants].sort());
|
|
1164
|
-
// Both worker instances actually processed children, not just the one
|
|
1165
|
-
// that happened to run the fan-out.
|
|
1166
|
-
const tagsUsed = new Set(log.map((e) => e.runnerTag));
|
|
1167
|
-
expect(tagsUsed.has("runner-a")).toBe(true);
|
|
1168
|
-
expect(tagsUsed.has("runner-b")).toBe(true);
|
|
1169
|
-
});
|
|
1170
|
-
});
|
|
1171
|
-
|
|
1172
|
-
// A perTenant wrapper's own BullMQ job id is reused to derive each child's
|
|
1173
|
-
// job id (see perTenantChildJobId in job-runner.ts) — a wrapper that runs
|
|
1174
|
-
// twice for the SAME trigger (retry after failure, a Redis drop, an
|
|
1175
|
-
// instance restarting mid-run) must not double the fan-out, while two
|
|
1176
|
-
// DIFFERENT triggers (e.g. two cron ticks) must each still fan out fully.
|
|
1177
|
-
// These are the two failure modes on either side of that invariant.
|
|
1178
|
-
describe("perTenant wrapper re-run for the same trigger", () => {
|
|
1179
|
-
test("a wrapper that fires twice for the same trigger still enqueues exactly one child per tenant", async () => {
|
|
1180
|
-
const log: Array<{ tenantId: string }> = [];
|
|
1181
|
-
const dedupFeature = defineFeature("multidedup", (r) => {
|
|
1182
|
-
r.job("fanout", { trigger: { manual: true }, perTenant: true }, async (_payload, ctx) => {
|
|
1183
|
-
log.push({ tenantId: String(ctx.systemUser.tenantId) });
|
|
1184
|
-
});
|
|
1185
|
-
});
|
|
1186
|
-
|
|
1187
|
-
const tenants = ["dedup-a", "dedup-b", "dedup-c"] as TenantId[];
|
|
1188
|
-
const getActiveTenantIds = async () => tenants;
|
|
1189
|
-
const registry = createRegistry([dedupFeature]);
|
|
1190
|
-
const queueNamePrefix = `kumiko-test-dedup-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1191
|
-
const runner = createJobRunner({
|
|
1192
|
-
registry,
|
|
1193
|
-
context: {},
|
|
1194
|
-
redisUrl,
|
|
1195
|
-
consumerLane: "worker",
|
|
1196
|
-
queueNamePrefix,
|
|
1197
|
-
getActiveTenantIds,
|
|
1198
|
-
});
|
|
1199
|
-
const rawQueue = new Queue(`${queueNamePrefix}-worker`, {
|
|
1200
|
-
connection: { host: testRedis.redis.options.host, port: testRedis.redis.options.port },
|
|
1201
|
-
});
|
|
1202
|
-
// A post-close 'error' here is otherwise unhandled and bun:test
|
|
1203
|
-
// attributes it to whichever test runs next (fw#1805).
|
|
1204
|
-
rawQueue.on("error", () => {});
|
|
1205
|
-
|
|
1206
|
-
const wrapperJobId = "fixed-wrapper-run";
|
|
1207
|
-
try {
|
|
1208
|
-
await runner.start();
|
|
1209
|
-
|
|
1210
|
-
// First run of the wrapper for this trigger — the real Worker picks
|
|
1211
|
-
// it up and fans out one child per tenant.
|
|
1212
|
-
await rawQueue.add("_perTenant:multidedup:job:fanout", {}, { jobId: wrapperJobId });
|
|
1213
|
-
await waitFor(() => expect(log.length).toBe(tenants.length), {
|
|
1214
|
-
delays: [200, 300, 500, 1000],
|
|
1215
|
-
});
|
|
1216
|
-
|
|
1217
|
-
// Simulate the SAME trigger firing the wrapper a second time. Remove
|
|
1218
|
-
// the now-completed wrapper's bookkeeping and re-add a genuinely
|
|
1219
|
-
// separate Job with the SAME id, so handleJob() runs again with the
|
|
1220
|
-
// identical bullJob.id — the actual "wrapper ran twice" scenario the
|
|
1221
|
-
// deterministic child id is meant to cover.
|
|
1222
|
-
const completedWrapper = await rawQueue.getJob(wrapperJobId);
|
|
1223
|
-
await completedWrapper?.remove();
|
|
1224
|
-
await rawQueue.add("_perTenant:multidedup:job:fanout", {}, { jobId: wrapperJobId });
|
|
1225
|
-
|
|
1226
|
-
// Give the second run's fan-out a chance to land. It re-derives the
|
|
1227
|
-
// SAME child ids as the first run, so BullMQ's existing-jobId add()
|
|
1228
|
-
// should return the already-completed children rather than re-run
|
|
1229
|
-
// the handler.
|
|
1230
|
-
await sleep(500);
|
|
1231
|
-
} finally {
|
|
1232
|
-
await runner.stop();
|
|
1233
|
-
await rawQueue.close();
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
expect(log.length).toBe(tenants.length);
|
|
1237
|
-
expect(log.map((e) => e.tenantId).sort()).toEqual([...tenants].sort());
|
|
1238
|
-
});
|
|
1239
|
-
|
|
1240
|
-
test("two consecutive cron ticks each still enqueue one child per tenant", async () => {
|
|
1241
|
-
const log: Array<{ tenantId: string }> = [];
|
|
1242
|
-
const cronFeature = defineFeature("multidedupcron", (r) => {
|
|
1243
|
-
r.job(
|
|
1244
|
-
"fanout",
|
|
1245
|
-
{ trigger: { cron: "* * * * * *" }, perTenant: true },
|
|
1246
|
-
async (_payload, ctx) => {
|
|
1247
|
-
log.push({ tenantId: String(ctx.systemUser.tenantId) });
|
|
1248
|
-
},
|
|
1249
|
-
);
|
|
1250
|
-
});
|
|
1251
|
-
|
|
1252
|
-
const tenants = ["dedup-cron-a", "dedup-cron-b"] as TenantId[];
|
|
1253
|
-
let wrapperCalls = 0;
|
|
1254
|
-
const getActiveTenantIds = async () => {
|
|
1255
|
-
wrapperCalls++;
|
|
1256
|
-
return tenants;
|
|
1257
|
-
};
|
|
1258
|
-
const registry = createRegistry([cronFeature]);
|
|
1259
|
-
const queueNamePrefix = `kumiko-test-dedup-cron-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1260
|
-
const runner = createJobRunner({
|
|
1261
|
-
registry,
|
|
1262
|
-
context: {},
|
|
1263
|
-
redisUrl,
|
|
1264
|
-
consumerLane: "worker",
|
|
1265
|
-
queueNamePrefix,
|
|
1266
|
-
getActiveTenantIds,
|
|
1267
|
-
});
|
|
1268
|
-
let drainedCalls = 0;
|
|
1269
|
-
try {
|
|
1270
|
-
await runner.start();
|
|
1271
|
-
// Two distinct ticks get two distinct repeat-job ids (different
|
|
1272
|
-
// millis) — each must still produce its own full batch of children;
|
|
1273
|
-
// a wrongly cross-tick dedup would collapse the second tick's log
|
|
1274
|
-
// entries into the first.
|
|
1275
|
-
await waitFor(
|
|
1276
|
-
() => {
|
|
1277
|
-
expect(wrapperCalls).toBeGreaterThanOrEqual(2);
|
|
1278
|
-
expect(log.length).toBe(wrapperCalls * tenants.length);
|
|
1279
|
-
drainedCalls = wrapperCalls;
|
|
1280
|
-
},
|
|
1281
|
-
{ delays: [1500, 2000, 3000] },
|
|
1282
|
-
);
|
|
1283
|
-
} finally {
|
|
1284
|
-
await runner.stop();
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1287
|
-
expect(log.length).toBeGreaterThanOrEqual(drainedCalls * tenants.length);
|
|
1288
|
-
const seenTenants = log
|
|
1289
|
-
.slice(0, drainedCalls * tenants.length)
|
|
1290
|
-
.map((e) => e.tenantId)
|
|
1291
|
-
.sort();
|
|
1292
|
-
const expectedTenants = Array.from({ length: drainedCalls }, () => tenants)
|
|
1293
|
-
.flat()
|
|
1294
|
-
.sort();
|
|
1295
|
-
expect(seenTenants).toEqual(expectedTenants);
|
|
1296
|
-
});
|
|
1297
|
-
});
|
|
1298
|
-
|
|
1299
|
-
describe("handleEvent maxPerTenant", () => {
|
|
1300
|
-
test("skips enqueue when tenant is already at the cap", async () => {
|
|
1301
|
-
clearLog();
|
|
1302
|
-
await withRunner(async (runner) => {
|
|
1303
|
-
const user = { ...TestUsers.admin, tenantId: "cap-tenant-evt" };
|
|
1304
|
-
await runner.handleEvent("test:write:capped-event", { n: 1 }, user);
|
|
1305
|
-
await runner.handleEvent("test:write:capped-event", { n: 2 }, user);
|
|
1306
|
-
await waitFor(() => {
|
|
1307
|
-
const started = jobLog.filter((e) => e.name === "test:job:per-tenant-limited-event");
|
|
1308
|
-
expect(started.length).toBe(2);
|
|
1309
|
-
});
|
|
1310
|
-
// Third must be skipped by the maxPerTenant guard. handleEvent's cap
|
|
1311
|
-
// check runs synchronously before this call resolves, but a wrongly
|
|
1312
|
-
// enqueued job still needs the worker to pick it up and push its
|
|
1313
|
-
// jobLog entry — polling several times (failing at the first sign of
|
|
1314
|
-
// a 3rd start) is more CI-load-tolerant than a single fixed sleep(200)
|
|
1315
|
-
// racing against the handler's own 500ms sleep, which could land
|
|
1316
|
-
// outside the window on a starved runner and silently pass.
|
|
1317
|
-
await runner.handleEvent("test:write:capped-event", { n: 3 }, user);
|
|
1318
|
-
// @timeout-exception: #3118 asserts a negative (stays capped) at each checkpoint
|
|
1319
|
-
for (const delayMs of [50, 100, 200, 400]) {
|
|
1320
|
-
await sleep(delayMs);
|
|
1321
|
-
const startedNow = jobLog.filter((e) => e.name === "test:job:per-tenant-limited-event");
|
|
1322
|
-
expect(startedNow.length).toBe(2);
|
|
1323
|
-
}
|
|
1324
|
-
});
|
|
1325
|
-
});
|
|
1326
|
-
});
|
|
1327
|
-
|
|
1328
|
-
describe("handleEvent retries", () => {
|
|
1329
|
-
test("an event-triggered job with retries retries on failure and eventually succeeds", async () => {
|
|
1330
|
-
clearLog();
|
|
1331
|
-
eventRetryAttemptCount = 0;
|
|
1332
|
-
await withRunner(async (runner) => {
|
|
1333
|
-
const user = { ...TestUsers.admin, tenantId: "retry-tenant-evt" };
|
|
1334
|
-
await runner.handleEvent("test:write:retry-event-trigger", { n: 1 }, user);
|
|
1335
|
-
// Without retries/backoff reaching the queue, the job fails on
|
|
1336
|
-
// attempt 1 and BullMQ never retries — this would time out.
|
|
1337
|
-
await waitFor(() => {
|
|
1338
|
-
const entries = jobLog.filter((e) => e.name === "test:job:event-retry-succeeds");
|
|
1339
|
-
expect(entries.length).toBe(2);
|
|
1340
|
-
});
|
|
1341
|
-
});
|
|
1342
|
-
expect(eventRetryAttemptCount).toBe(2);
|
|
1343
|
-
});
|
|
1344
|
-
});
|
|
1345
|
-
|
|
1346
|
-
// --- Registry ---
|
|
1347
|
-
|
|
1348
|
-
describe("job registry", () => {
|
|
1349
|
-
test("getAllJobs returns all registered jobs with feature prefix", () => {
|
|
1350
|
-
const registry = createRegistry([testFeature]);
|
|
1351
|
-
const jobs = registry.getAllJobs();
|
|
1352
|
-
expect(jobs.has("test:job:boot-sync")).toBe(true);
|
|
1353
|
-
expect(jobs.has("test:job:scheduled")).toBe(true);
|
|
1354
|
-
expect(jobs.has("test:job:manual-report")).toBe(true);
|
|
1355
|
-
expect(jobs.has("test:job:skip-job")).toBe(true);
|
|
1356
|
-
});
|
|
1357
|
-
|
|
1358
|
-
test("getJob returns job definition", () => {
|
|
1359
|
-
const registry = createRegistry([testFeature]);
|
|
1360
|
-
const job = registry.getJob("test:job:skip-job");
|
|
1361
|
-
expect(job).toBeDefined();
|
|
1362
|
-
expect(job?.concurrency).toBe("skip");
|
|
1363
|
-
});
|
|
1364
|
-
|
|
1365
|
-
test("boot job has runOnBoot flag", () => {
|
|
1366
|
-
const registry = createRegistry([testFeature]);
|
|
1367
|
-
const job = registry.getJob("test:job:boot-sync");
|
|
1368
|
-
expect(job).toBeDefined();
|
|
1369
|
-
expect(job?.runOnBoot).toBe(true);
|
|
1370
|
-
});
|
|
1371
|
-
});
|
|
1372
|
-
|
|
1373
|
-
// --- Boot gates: only an inline gate can abort a boot (fw#2590) ---
|
|
1374
|
-
|
|
1375
|
-
describe("boot gates", () => {
|
|
1376
|
-
const gateLog: string[] = [];
|
|
1377
|
-
const GATE_FAILURE = "required legal blocks are not seeded";
|
|
1378
|
-
|
|
1379
|
-
function uniquePrefix(): string {
|
|
1380
|
-
return `kumiko-gate-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1381
|
-
}
|
|
1382
|
-
|
|
1383
|
-
function createGateRunner(
|
|
1384
|
-
feature: ReturnType<typeof defineFeature>,
|
|
1385
|
-
queueNamePrefix: string,
|
|
1386
|
-
): JobRunner {
|
|
1387
|
-
const context: AppContext = {};
|
|
1388
|
-
return createJobRunner({
|
|
1389
|
-
registry: createRegistry([feature]),
|
|
1390
|
-
context,
|
|
1391
|
-
redisUrl,
|
|
1392
|
-
consumerLane: "worker",
|
|
1393
|
-
queueNamePrefix,
|
|
1394
|
-
});
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
async function purge(queueNamePrefix: string): Promise<void> {
|
|
1398
|
-
const keys = await testRedis.redis.keys(`bull:${queueNamePrefix}-worker:*`);
|
|
1399
|
-
if (keys.length > 0) await testRedis.redis.del(...keys);
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
test("a throwing gate rejects start() and stops the remaining boot wiring", async () => {
|
|
1403
|
-
const feature = defineFeature("failgate", (r) => {
|
|
1404
|
-
r.job("check", { trigger: { manual: true }, bootGate: true }, async () => {
|
|
1405
|
-
throw new Error(GATE_FAILURE);
|
|
1406
|
-
});
|
|
1407
|
-
r.job("afterGate", { trigger: { manual: true }, runOnBoot: true }, async () => {
|
|
1408
|
-
gateLog.push("after-gate");
|
|
1409
|
-
});
|
|
1410
|
-
});
|
|
1411
|
-
const prefix = uniquePrefix();
|
|
1412
|
-
const runner = createGateRunner(feature, prefix);
|
|
1413
|
-
gateLog.length = 0;
|
|
1414
|
-
|
|
1415
|
-
// Pin the qualified name the boot-job-id assertion below is built on —
|
|
1416
|
-
// a typo there would make that assertion pass vacuously.
|
|
1417
|
-
const afterGateName = "failgate:job:after-gate";
|
|
1418
|
-
expect(createRegistry([feature]).getJob(afterGateName)).toBeDefined();
|
|
1419
|
-
|
|
1420
|
-
const queue = new Queue(`${prefix}-worker`, {
|
|
1421
|
-
connection: { host: testRedis.redis.options.host, port: testRedis.redis.options.port },
|
|
1422
|
-
});
|
|
1423
|
-
// A post-close 'error' here is otherwise unhandled and bun:test
|
|
1424
|
-
// attributes it to whichever test runs next (fw#1805).
|
|
1425
|
-
queue.on("error", () => {});
|
|
1426
|
-
|
|
1427
|
-
try {
|
|
1428
|
-
// The gate's own message must survive — which blocks are missing is the
|
|
1429
|
-
// entire operational value, and onJobFailed runs before the re-throw.
|
|
1430
|
-
await expect(runner.start()).rejects.toThrow(GATE_FAILURE);
|
|
1431
|
-
await sleep(300);
|
|
1432
|
-
// The gate aborted start() before any further boot wiring ran: the
|
|
1433
|
-
// runOnBoot job was never even enqueued, and never executed.
|
|
1434
|
-
const bootJob = await queue.getJob(bootJobIdForJobName(afterGateName));
|
|
1435
|
-
expect(bootJob).toBeUndefined();
|
|
1436
|
-
expect(gateLog).toEqual([]);
|
|
1437
|
-
} finally {
|
|
1438
|
-
await queue.close();
|
|
1439
|
-
await runner.stop();
|
|
1440
|
-
await purge(prefix);
|
|
1441
|
-
}
|
|
1442
|
-
});
|
|
1443
|
-
|
|
1444
|
-
test("a gate runs on every start, unlike a deduped runOnBoot job", async () => {
|
|
1445
|
-
const feature = defineFeature("everygate", (r) => {
|
|
1446
|
-
r.job("check", { trigger: { manual: true }, bootGate: true }, async () => {
|
|
1447
|
-
gateLog.push("gate");
|
|
1448
|
-
});
|
|
1449
|
-
r.job("once", { trigger: { manual: true }, runOnBoot: true }, async () => {
|
|
1450
|
-
gateLog.push("boot");
|
|
1451
|
-
});
|
|
1452
|
-
});
|
|
1453
|
-
const prefix = uniquePrefix();
|
|
1454
|
-
gateLog.length = 0;
|
|
1455
|
-
|
|
1456
|
-
const first = createGateRunner(feature, prefix);
|
|
1457
|
-
await first.start();
|
|
1458
|
-
await waitFor(() => {
|
|
1459
|
-
expect(gateLog.filter((e) => e === "boot").length).toBe(1);
|
|
1460
|
-
});
|
|
1461
|
-
await first.stop();
|
|
1462
|
-
|
|
1463
|
-
const second = createGateRunner(feature, prefix);
|
|
1464
|
-
try {
|
|
1465
|
-
await second.start();
|
|
1466
|
-
await sleep(300);
|
|
1467
|
-
expect(gateLog.filter((e) => e === "gate").length).toBe(2);
|
|
1468
|
-
// The persistent boot-enqueued marker set from the first start is
|
|
1469
|
-
// still present in Redis, so the second start skips re-enqueueing —
|
|
1470
|
-
// that dedup is why runOnBoot cannot gate a deploy.
|
|
1471
|
-
expect(gateLog.filter((e) => e === "boot").length).toBe(1);
|
|
1472
|
-
} finally {
|
|
1473
|
-
await second.stop();
|
|
1474
|
-
await purge(prefix);
|
|
1475
|
-
}
|
|
1476
|
-
});
|
|
1477
|
-
|
|
1478
|
-
test("bootGate is rejected for perTenant and sequential jobs", () => {
|
|
1479
|
-
const perTenantGate = defineFeature("pergate", (r) => {
|
|
1480
|
-
r.job("check", { trigger: { manual: true }, bootGate: true, perTenant: true }, async () => {
|
|
1481
|
-
gateLog.push("never");
|
|
1482
|
-
});
|
|
1483
|
-
});
|
|
1484
|
-
expect(() => createRegistry([perTenantGate])).toThrow(/bootGate with perTenant/);
|
|
1485
|
-
|
|
1486
|
-
const sequentialGate = defineFeature("seqgate", (r) => {
|
|
1487
|
-
r.job(
|
|
1488
|
-
"check",
|
|
1489
|
-
{ trigger: { manual: true }, bootGate: true, concurrency: "sequential" },
|
|
1490
|
-
async () => {
|
|
1491
|
-
gateLog.push("never");
|
|
1492
|
-
},
|
|
1493
|
-
);
|
|
1494
|
-
});
|
|
1495
|
-
expect(() => createRegistry([sequentialGate])).toThrow(/bootGate with concurrency/);
|
|
1496
|
-
});
|
|
1497
|
-
|
|
1498
|
-
test("object-form backoff.delayMs must be a positive integer", () => {
|
|
1499
|
-
for (const badDelayMs of [0, -5, 1.5]) {
|
|
1500
|
-
const feature = defineFeature("badbackoff", (r) => {
|
|
1501
|
-
r.job(
|
|
1502
|
-
"check",
|
|
1503
|
-
{ trigger: { manual: true }, backoff: { type: "fixed", delayMs: badDelayMs } },
|
|
1504
|
-
async () => {
|
|
1505
|
-
gateLog.push("never");
|
|
1506
|
-
},
|
|
1507
|
-
);
|
|
1508
|
-
});
|
|
1509
|
-
expect(() => createRegistry([feature])).toThrow(
|
|
1510
|
-
/backoff\.delayMs must be a positive integer/,
|
|
1511
|
-
);
|
|
1512
|
-
}
|
|
1513
|
-
|
|
1514
|
-
const validObjectForm = defineFeature("goodbackoffobject", (r) => {
|
|
1515
|
-
r.job(
|
|
1516
|
-
"check",
|
|
1517
|
-
{ trigger: { manual: true }, backoff: { type: "exponential", delayMs: 100 } },
|
|
1518
|
-
async () => {
|
|
1519
|
-
gateLog.push("never");
|
|
1520
|
-
},
|
|
1521
|
-
);
|
|
1522
|
-
});
|
|
1523
|
-
expect(() => createRegistry([validObjectForm])).not.toThrow();
|
|
1524
|
-
|
|
1525
|
-
const validStringForm = defineFeature("goodbackoffstring", (r) => {
|
|
1526
|
-
r.job("check", { trigger: { manual: true }, backoff: "fixed" }, async () => {
|
|
1527
|
-
gateLog.push("never");
|
|
1528
|
-
});
|
|
1529
|
-
});
|
|
1530
|
-
expect(() => createRegistry([validStringForm])).not.toThrow();
|
|
1531
|
-
});
|
|
1532
|
-
});
|
|
1533
|
-
|
|
1534
|
-
describe("runner lifecycle: immediate stop (fw#1805)", () => {
|
|
1535
|
-
test("stop() right after construction leaves no unhandled rejection", async () => {
|
|
1536
|
-
const unhandled: unknown[] = [];
|
|
1537
|
-
const onUnhandled = (reason: unknown) => {
|
|
1538
|
-
unhandled.push(reason);
|
|
1539
|
-
};
|
|
1540
|
-
process.on("unhandledRejection", onUnhandled);
|
|
1541
|
-
try {
|
|
1542
|
-
// @timeout-exception: #1805 the 0-4ms delay is the variable under test (stop during connect), nothing to poll for
|
|
1543
|
-
for (let i = 0; i < 20; i++) {
|
|
1544
|
-
const runner = createJobRunner({
|
|
1545
|
-
registry: createRegistry([testFeature]),
|
|
1546
|
-
context: {},
|
|
1547
|
-
redisUrl,
|
|
1548
|
-
consumerLane: "worker",
|
|
1549
|
-
queueNamePrefix: `kumiko-test-stop-${Date.now()}-${i}-${Math.random().toString(36).slice(2, 8)}`,
|
|
1550
|
-
});
|
|
1551
|
-
// Deterministic 0-4ms delays hit the window where the Queue
|
|
1552
|
-
// connection is still 'initializing'.
|
|
1553
|
-
await sleep(i % 5);
|
|
1554
|
-
await runner.stop();
|
|
1555
|
-
}
|
|
1556
|
-
// Rejections surface on a later tick.
|
|
1557
|
-
await sleep(200);
|
|
1558
|
-
} finally {
|
|
1559
|
-
process.off("unhandledRejection", onUnhandled);
|
|
1560
|
-
}
|
|
1561
|
-
expect(unhandled).toEqual([]);
|
|
1562
|
-
});
|
|
1563
|
-
});
|