@cosmicdrift/kumiko-framework 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -6
- package/src/__tests__/{anonymous-access.integration.ts → anonymous-access.integration.test.ts} +12 -9
- package/src/__tests__/{error-contract.integration.ts → error-contract.integration.test.ts} +5 -4
- package/src/__tests__/{field-access.integration.ts → field-access.integration.test.ts} +3 -3
- package/src/__tests__/{full-stack.integration.ts → full-stack.integration.test.ts} +7 -16
- package/src/__tests__/{ownership.integration.ts → ownership.integration.test.ts} +3 -2
- package/src/__tests__/{raw-table.integration.ts → raw-table.integration.test.ts} +18 -30
- package/src/__tests__/{reference-data.integration.ts → reference-data.integration.test.ts} +24 -11
- package/src/__tests__/{transition-guard.integration.ts → transition-guard.integration.test.ts} +12 -10
- package/src/api/__tests__/api.test.ts +1 -1
- package/src/api/__tests__/auth-middleware-transport.test.ts +1 -1
- package/src/api/__tests__/auth-routes-cookie.test.ts +1 -1
- package/src/api/__tests__/{batch.integration.ts → batch.integration.test.ts} +30 -30
- package/src/api/__tests__/body-limit.test.ts +1 -1
- package/src/api/__tests__/csrf-middleware.test.ts +1 -1
- package/src/api/__tests__/{dispatcher-live.integration.ts → dispatcher-live.integration.test.ts} +10 -9
- package/src/api/__tests__/metrics-endpoint.test.ts +1 -1
- package/src/api/__tests__/{nested-write.integration.ts → nested-write.integration.test.ts} +13 -16
- package/src/api/__tests__/readiness.test.ts +1 -1
- package/src/api/__tests__/request-id-middleware.test.ts +1 -1
- package/src/api/__tests__/sse-broker.test.ts +12 -12
- package/src/api/__tests__/sse-route.test.ts +1 -1
- package/src/api/auth-routes.ts +2 -5
- package/src/api/readiness.ts +2 -2
- package/src/auth/__tests__/roles.test.ts +2 -2
- package/src/bun-db/__tests__/PATTERN.md +73 -0
- package/src/bun-db/__tests__/_helpers.ts +103 -0
- package/src/bun-db/__tests__/batch-methods.integration.test.ts +143 -0
- package/src/bun-db/__tests__/batch-methods.test.ts +20 -0
- package/src/bun-db/__tests__/bun-test-db.ts +19 -0
- package/src/bun-db/__tests__/bun-test-stack.ts +6 -0
- package/src/bun-db/__tests__/column-types.integration.test.ts +132 -0
- package/src/bun-db/__tests__/compound-types.integration.test.ts +134 -0
- package/src/bun-db/__tests__/jsonb-edge-cases.integration.test.ts +235 -0
- package/src/bun-db/__tests__/smoke.integration.test.ts +43 -0
- package/src/bun-db/__tests__/sql-methods.integration.test.ts +231 -0
- package/src/bun-db/__tests__/where-patterns.integration.test.ts +185 -0
- package/src/bun-db/connection.ts +84 -0
- package/src/bun-db/index.ts +31 -0
- package/src/bun-db/query.ts +842 -0
- package/src/compliance/__tests__/duration-spec.test.ts +1 -1
- package/src/compliance/__tests__/profiles.test.ts +1 -1
- package/src/compliance/__tests__/sub-processors.test.ts +1 -1
- package/src/compliance/profiles.ts +1 -4
- package/src/db/__tests__/{apply-entity-event-tenant.integration.ts → apply-entity-event-tenant.integration.test.ts} +13 -11
- package/src/db/__tests__/big-int-field.test.ts +15 -14
- package/src/db/__tests__/column-ddl.integration.test.ts +113 -0
- package/src/db/__tests__/compound-types.test.ts +1 -1
- package/src/db/__tests__/{config-seed.integration.ts → config-seed.integration.test.ts} +32 -27
- package/src/db/__tests__/connection-options.test.ts +1 -1
- package/src/db/__tests__/cursor.test.ts +8 -32
- package/src/db/__tests__/dialect-instant.test.ts +1 -1
- package/src/db/__tests__/encryption.test.ts +1 -1
- package/src/db/__tests__/{drizzle-table-types.test.ts → entity-table-types.test.ts} +16 -16
- package/src/db/__tests__/{event-store-executor-list.integration.ts → event-store-executor-list.integration.test.ts} +12 -7
- package/src/db/__tests__/{event-store-executor.integration.ts → event-store-executor.integration.test.ts} +19 -12
- package/src/db/__tests__/{implicit-projection-equivalence.integration.ts → implicit-projection-equivalence.integration.test.ts} +35 -29
- package/src/db/__tests__/located-timestamp.test.ts +1 -1
- package/src/db/__tests__/migrate-generator.test.ts +71 -0
- package/src/db/__tests__/migrate-runner.test.ts +19 -0
- package/src/db/__tests__/money.test.ts +1 -1
- package/src/db/__tests__/{multi-row-insert.integration.ts → multi-row-insert.integration.test.ts} +18 -11
- package/src/db/__tests__/parse-auto-verb.test.ts +1 -1
- package/src/db/__tests__/pg-error.test.ts +43 -0
- package/src/db/__tests__/{required-not-null-migration-safety.integration.ts → required-not-null-migration-safety.integration.test.ts} +28 -24
- package/src/db/__tests__/{schema-migration.integration.ts → schema-migration.integration.test.ts} +32 -28
- package/src/db/__tests__/sql-inventory.test.ts +56 -0
- package/src/db/__tests__/table-builder-indexes.test.ts +30 -11
- package/src/db/__tests__/table-builder-required.test.ts +20 -22
- package/src/db/__tests__/{tenant-db.integration.ts → tenant-db.integration.test.ts} +106 -144
- package/src/db/__tests__/{unique-violation-mapping.integration.ts → unique-violation-mapping.integration.test.ts} +13 -8
- package/src/db/api.ts +46 -0
- package/src/db/apply-entity-event.ts +45 -36
- package/src/db/assert-exists-in.ts +5 -16
- package/src/db/bun-provider.ts +37 -0
- package/src/db/config-seed.ts +4 -4
- package/src/db/connection.ts +14 -57
- package/src/db/cursor.ts +5 -56
- package/src/db/dialect.ts +472 -99
- package/src/db/eagerload.ts +5 -12
- package/src/db/entity-table-meta.ts +390 -0
- package/src/db/event-store-executor.ts +158 -100
- package/src/db/index.ts +33 -5
- package/src/db/migrate-generator.ts +350 -0
- package/src/db/migrate-runner.ts +206 -0
- package/src/db/postgres-provider.ts +25 -0
- package/src/db/queries/entity-read.ts +15 -0
- package/src/db/queries/es-ops.ts +17 -0
- package/src/db/queries/event-consumer.ts +170 -0
- package/src/db/queries/event-store-admin.ts +127 -0
- package/src/db/queries/event-store.ts +155 -0
- package/src/db/queries/projection-rebuild.ts +59 -0
- package/src/db/queries/raw-sql.ts +15 -0
- package/src/db/queries/schema-drift.ts +35 -0
- package/src/db/queries/seed-context.ts +58 -0
- package/src/db/queries/table-ops.ts +11 -0
- package/src/db/queries/test-stack.ts +56 -0
- package/src/db/query-api.ts +22 -0
- package/src/db/query.ts +30 -0
- package/src/db/reference-data.ts +19 -22
- package/src/db/render-ddl.ts +57 -0
- package/src/db/row-helpers.ts +3 -52
- package/src/db/schema-inspection.ts +17 -4
- package/src/db/sql-inventory.ts +208 -0
- package/src/db/table-builder.ts +54 -46
- package/src/db/tenant-db.ts +105 -326
- package/src/engine/__tests__/auth-claims-registrar.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-api-exposure.test.ts +3 -3
- package/src/engine/__tests__/boot-validator-located-timestamps.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-pii-retention.test.ts +5 -5
- package/src/engine/__tests__/boot-validator-s0-integration.test.ts +3 -3
- package/src/engine/__tests__/boot-validator.test.ts +4 -3
- package/src/engine/__tests__/build-app-schema.test.ts +1 -1
- package/src/engine/__tests__/build-target.test.ts +1 -1
- package/src/engine/__tests__/claim-keys.test.ts +1 -1
- package/src/engine/__tests__/codemod-pipeline.test.ts +3 -3
- package/src/engine/__tests__/config-helpers.test.ts +1 -1
- package/src/engine/__tests__/duration-utils.test.ts +16 -0
- package/src/engine/__tests__/effective-features.test.ts +1 -1
- package/src/engine/__tests__/engine.test.ts +1 -1
- package/src/engine/__tests__/entity-handlers.test.ts +3 -3
- package/src/engine/__tests__/event-helpers.test.ts +3 -3
- package/src/engine/__tests__/extends-registrar.test.ts +4 -4
- package/src/engine/__tests__/factories-long-text.test.ts +1 -1
- package/src/engine/__tests__/factories-time.test.ts +1 -1
- package/src/engine/__tests__/field-access.test.ts +38 -0
- package/src/engine/__tests__/field-predicates.test.ts +1 -1
- package/src/engine/__tests__/hook-phases.test.ts +1 -1
- package/src/engine/__tests__/identifiers.test.ts +1 -1
- package/src/engine/__tests__/lifecycle-hooks.test.ts +1 -1
- package/src/engine/__tests__/nav.test.ts +1 -1
- package/src/engine/__tests__/no-return-guard.test.ts +17 -0
- package/src/engine/__tests__/ownership.test.ts +10 -11
- package/src/engine/__tests__/parse-ref-target.test.ts +1 -1
- package/src/engine/__tests__/pipeline-engine.test.ts +1 -1
- package/src/engine/__tests__/{pipeline-handler.integration.ts → pipeline-handler.integration.test.ts} +38 -52
- package/src/engine/__tests__/{pipeline-observability.integration.ts → pipeline-observability.integration.test.ts} +1 -1
- package/src/engine/__tests__/{pipeline-performance.integration.ts → pipeline-performance.integration.test.ts} +1 -1
- package/src/engine/__tests__/pipeline-sub-pipelines.test.ts +1 -1
- package/src/engine/__tests__/post-query-hook.test.ts +1 -1
- package/src/engine/__tests__/projection-helpers.test.ts +25 -17
- package/src/engine/__tests__/projection.test.ts +4 -4
- package/src/engine/__tests__/qualified-name.test.ts +1 -1
- package/src/engine/__tests__/raw-table.test.ts +9 -8
- package/src/engine/__tests__/resolve-config-or-param.test.ts +5 -5
- package/src/engine/__tests__/run-in.test.ts +1 -1
- package/src/engine/__tests__/schema-builder.test.ts +1 -1
- package/src/engine/__tests__/screen.test.ts +1 -1
- package/src/engine/__tests__/search-payload-extension.test.ts +3 -3
- package/src/engine/__tests__/state-machine.test.ts +1 -1
- package/src/engine/__tests__/steps-aggregate-append-event.test.ts +7 -7
- package/src/engine/__tests__/steps-aggregate-create.test.ts +4 -4
- package/src/engine/__tests__/steps-aggregate-update.test.ts +3 -3
- package/src/engine/__tests__/steps-call-feature.test.ts +5 -5
- package/src/engine/__tests__/steps-mail-send.test.ts +7 -7
- package/src/engine/__tests__/steps-read.test.ts +34 -40
- package/src/engine/__tests__/steps-resolver-utils.test.ts +6 -6
- package/src/engine/__tests__/steps-unsafe-projection-delete.test.ts +24 -19
- package/src/engine/__tests__/steps-unsafe-projection-upsert.test.ts +28 -17
- package/src/engine/__tests__/steps-webhook-send.test.ts +6 -6
- package/src/engine/__tests__/steps-workflow.test.ts +7 -7
- package/src/engine/__tests__/system-user.test.ts +1 -1
- package/src/engine/__tests__/unmanaged-table.test.ts +98 -0
- package/src/engine/__tests__/validate-projection-allowlist.test.ts +4 -5
- package/src/engine/__tests__/validation-hooks.test.ts +1 -1
- package/src/engine/__tests__/visual-tree-patterns.test.ts +1 -1
- package/src/engine/boot-validator/entity-handler.ts +3 -3
- package/src/engine/boot-validator/ownership.ts +1 -1
- package/src/engine/define-feature.ts +37 -2
- package/src/engine/entity-handlers.ts +5 -5
- package/src/engine/factories.ts +1 -1
- package/src/engine/feature-ast/__tests__/canonical-form.test.ts +1 -1
- package/src/engine/feature-ast/__tests__/parse-happy-path.test.ts +1 -1
- package/src/engine/feature-ast/__tests__/parse-real-features.test.ts +2 -2
- package/src/engine/feature-ast/__tests__/parse.test.ts +1 -1
- package/src/engine/feature-ast/__tests__/patch.test.ts +1 -1
- package/src/engine/feature-ast/__tests__/patcher.test.ts +1 -1
- package/src/engine/feature-ast/__tests__/render-roundtrip.test.ts +1 -1
- package/src/engine/feature-ast/__tests__/visual-tree-parse.test.ts +1 -1
- package/src/engine/feature-ast/extractors/shared.ts +2 -3
- package/src/engine/ownership.ts +113 -41
- package/src/engine/pattern-library/__tests__/library.test.ts +2 -2
- package/src/engine/projection-helpers.ts +2 -11
- package/src/engine/registry.ts +21 -2
- package/src/engine/steps/read-find-many.ts +13 -13
- package/src/engine/steps/read-find-one.ts +7 -9
- package/src/engine/steps/unsafe-projection-delete.ts +4 -5
- package/src/engine/steps/unsafe-projection-upsert.ts +63 -31
- package/src/engine/types/feature.ts +47 -2
- package/src/engine/types/fields.ts +4 -5
- package/src/engine/types/index.ts +2 -0
- package/src/engine/types/step.ts +10 -10
- package/src/engine/validate-projection-allowlist.ts +23 -3
- package/src/entrypoint/__tests__/{entrypoint-job-wiring.integration.ts → entrypoint-job-wiring.integration.test.ts} +4 -3
- package/src/entrypoint/__tests__/{split-deploy.integration.ts → split-deploy.integration.test.ts} +4 -3
- package/src/env/__tests__/compose-env-schema.test.ts +1 -1
- package/src/env/__tests__/dry-run.test.ts +1 -1
- package/src/errors/__tests__/classes.test.ts +1 -1
- package/src/errors/__tests__/error-helpers.test.ts +44 -0
- package/src/errors/__tests__/field-issue-compat.test.ts +16 -0
- package/src/errors/__tests__/write-failures.test.ts +1 -1
- package/src/errors/classes.ts +5 -19
- package/src/errors/field-issue.ts +11 -0
- package/src/errors/index.ts +1 -0
- package/src/errors/zod-bridge.ts +3 -2
- package/src/es-ops/__tests__/{context.integration.ts → context.integration.test.ts} +43 -29
- package/src/es-ops/__tests__/{runner.integration.ts → runner.integration.test.ts} +25 -23
- package/src/es-ops/__tests__/runner.test.ts +29 -19
- package/src/es-ops/context.ts +11 -56
- package/src/es-ops/operations-schema.ts +2 -2
- package/src/es-ops/runner.ts +12 -26
- package/src/event-store/__tests__/{admin-api.integration.ts → admin-api.integration.test.ts} +71 -45
- package/src/event-store/__tests__/{event-store.integration.ts → event-store.integration.test.ts} +7 -5
- package/src/event-store/__tests__/{get-stream-version-perf.integration.ts → get-stream-version-perf.integration.test.ts} +5 -3
- package/src/event-store/__tests__/{perf.integration.ts → perf.integration.test.ts} +24 -16
- package/src/event-store/__tests__/{snapshot.integration.ts → snapshot.integration.test.ts} +34 -28
- package/src/event-store/__tests__/{upcaster-dead-letter.integration.ts → upcaster-dead-letter.integration.test.ts} +11 -12
- package/src/event-store/__tests__/{upcaster.integration.ts → upcaster.integration.test.ts} +19 -32
- package/src/event-store/admin-api.ts +55 -83
- package/src/event-store/archive.ts +15 -39
- package/src/event-store/event-store.ts +92 -86
- package/src/event-store/events-schema.ts +2 -1
- package/src/event-store/index.ts +1 -0
- package/src/event-store/snapshot.ts +26 -24
- package/src/event-store/upcaster-dead-letter.ts +19 -18
- package/src/files/__tests__/content-disposition.test.ts +1 -1
- package/src/files/__tests__/{file-field-pipeline.integration.ts → file-field-pipeline.integration.test.ts} +8 -5
- package/src/files/__tests__/file-handle.test.ts +1 -1
- package/src/files/__tests__/{files.integration.ts → files.integration.test.ts} +32 -17
- package/src/files/__tests__/read-stream.test.ts +1 -1
- package/src/files/__tests__/{storage-tracking.integration.ts → storage-tracking.integration.test.ts} +26 -30
- package/src/files/__tests__/write-stream.test.ts +1 -1
- package/src/files/__tests__/zip-stream.test.ts +1 -1
- package/src/files/file-ref-table.ts +2 -2
- package/src/files/file-routes.ts +7 -9
- package/src/files/storage-tracking.ts +9 -17
- package/src/i18n/__tests__/i18n.test.ts +1 -1
- package/src/jobs/__tests__/{job-event-trigger.integration.ts → job-event-trigger.integration.test.ts} +6 -3
- package/src/jobs/__tests__/{job-multi-trigger.integration.ts → job-multi-trigger.integration.test.ts} +6 -3
- package/src/jobs/__tests__/{jobs.integration.ts → jobs.integration.test.ts} +5 -7
- package/src/lifecycle/__tests__/{lifecycle-server.integration.ts → lifecycle-server.integration.test.ts} +1 -1
- package/src/lifecycle/__tests__/lifecycle.test.ts +6 -6
- package/src/lifecycle/__tests__/signal-handlers.test.ts +6 -6
- package/src/logging/__tests__/pino-trace-bridge.test.ts +1 -1
- package/src/migrations/__tests__/compare-snapshots.test.ts +1 -1
- package/src/migrations/__tests__/{detect-drift.integration.ts → detect-drift.integration.test.ts} +34 -26
- package/src/migrations/__tests__/{detect-projections-to-rebuild.integration.ts → detect-projections-to-rebuild.integration.test.ts} +1 -1
- package/src/migrations/__tests__/rebuild-marker.test.ts +1 -1
- package/src/migrations/projection-detection.ts +12 -1
- package/src/migrations/schema-drift.ts +7 -23
- package/src/observability/__tests__/console-provider.test.ts +1 -1
- package/src/observability/__tests__/metric-validator.test.ts +1 -1
- package/src/observability/__tests__/noop-provider.test.ts +1 -1
- package/src/observability/__tests__/{observability.integration.ts → observability.integration.test.ts} +5 -8
- package/src/observability/__tests__/prometheus-meter.test.ts +1 -1
- package/src/observability/__tests__/recording-meter.test.ts +1 -1
- package/src/observability/__tests__/recording-tracer.test.ts +1 -1
- package/src/observability/__tests__/sensitive-filter.test.ts +1 -1
- package/src/pipeline/__tests__/{archive-stream.integration.ts → archive-stream.integration.test.ts} +3 -3
- package/src/pipeline/__tests__/auth-claims-resolver.test.ts +9 -9
- package/src/pipeline/__tests__/{cascade-handler.integration.ts → cascade-handler.integration.test.ts} +18 -15
- package/src/pipeline/__tests__/cascade-handler.test.ts +1 -1
- package/src/pipeline/__tests__/{causation-chain.integration.ts → causation-chain.integration.test.ts} +12 -13
- package/src/pipeline/__tests__/{ctx-bridge.integration.ts → ctx-bridge.integration.test.ts} +12 -11
- package/src/pipeline/__tests__/dispatcher-utils.test.ts +107 -0
- package/src/pipeline/__tests__/dispatcher.test.ts +2 -2
- package/src/pipeline/__tests__/{distributed-lock.integration.ts → distributed-lock.integration.test.ts} +1 -1
- package/src/pipeline/__tests__/{domain-events-projections.integration.ts → domain-events-projections.integration.test.ts} +13 -15
- package/src/pipeline/__tests__/{event-dedup.integration.ts → event-dedup.integration.test.ts} +1 -1
- package/src/pipeline/__tests__/{event-define-event-strict.integration.ts → event-define-event-strict.integration.test.ts} +6 -16
- package/src/pipeline/__tests__/{event-dispatcher-lifecycle.integration.ts → event-dispatcher-lifecycle.integration.test.ts} +1 -1
- package/src/pipeline/__tests__/{event-dispatcher-multi-instance.integration.ts → event-dispatcher-multi-instance.integration.test.ts} +3 -2
- package/src/pipeline/__tests__/{event-dispatcher-pg-listen.integration.ts → event-dispatcher-pg-listen.integration.test.ts} +1 -1
- package/src/pipeline/__tests__/{event-dispatcher-recovery.integration.ts → event-dispatcher-recovery.integration.test.ts} +2 -2
- package/src/pipeline/__tests__/{event-dispatcher-second-audit.integration.ts → event-dispatcher-second-audit.integration.test.ts} +17 -16
- package/src/pipeline/__tests__/event-dispatcher-strict.test.ts +14 -12
- package/src/pipeline/__tests__/{event-dispatcher.integration.ts → event-dispatcher.integration.test.ts} +8 -15
- package/src/pipeline/__tests__/{event-retention.integration.ts → event-retention.integration.test.ts} +28 -25
- package/src/pipeline/__tests__/{fetch-for-writing.integration.ts → fetch-for-writing.integration.test.ts} +6 -6
- package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +4 -4
- package/src/pipeline/__tests__/{load-aggregate-query.integration.ts → load-aggregate-query.integration.test.ts} +9 -5
- package/src/pipeline/__tests__/{msp-error-mode.integration.ts → msp-error-mode.integration.test.ts} +1 -1
- package/src/pipeline/__tests__/{msp-multi-hop.integration.ts → msp-multi-hop.integration.test.ts} +9 -8
- package/src/pipeline/__tests__/{msp-rebuild.integration.ts → msp-rebuild.integration.test.ts} +47 -55
- package/src/pipeline/__tests__/{multi-stream-projection.integration.ts → multi-stream-projection.integration.test.ts} +19 -53
- package/src/pipeline/__tests__/{perf-rebuild.integration.ts → perf-rebuild.integration.test.ts} +36 -34
- package/src/pipeline/__tests__/{post-query-hook.integration.ts → post-query-hook.integration.test.ts} +1 -1
- package/src/pipeline/__tests__/{projection-rebuild.integration.ts → projection-rebuild.integration.test.ts} +21 -30
- package/src/pipeline/__tests__/{query-projection.integration.ts → query-projection.integration.test.ts} +6 -5
- package/src/pipeline/__tests__/redis-keys.test.ts +12 -0
- package/src/pipeline/__tests__/{redis-pipeline.integration.ts → redis-pipeline.integration.test.ts} +3 -1
- package/src/pipeline/cascade-handler.ts +13 -21
- package/src/pipeline/dispatcher-utils.ts +8 -7
- package/src/pipeline/dispatcher.ts +43 -48
- package/src/pipeline/event-consumer-state.ts +11 -2
- package/src/pipeline/event-dispatcher.ts +86 -146
- package/src/pipeline/event-retention.ts +14 -24
- package/src/pipeline/msp-rebuild.ts +54 -78
- package/src/pipeline/projection-rebuild.ts +65 -67
- package/src/pipeline/projection-state.ts +2 -2
- package/src/random/__tests__/generate.test.ts +13 -13
- package/src/rate-limit/__tests__/{dispatcher-l3.integration.ts → dispatcher-l3.integration.test.ts} +1 -1
- package/src/rate-limit/__tests__/{middleware.integration.ts → middleware.integration.test.ts} +1 -1
- package/src/rate-limit/__tests__/{resolver.integration.ts → resolver.integration.test.ts} +1 -1
- package/src/redis/__tests__/redis-options.test.ts +1 -1
- package/src/search/__tests__/{meilisearch-adapter.integration.ts → meilisearch-adapter.integration.test.ts} +1 -1
- package/src/search/__tests__/search-adapter.test.ts +1 -1
- package/src/secrets/__tests__/dek-cache.test.ts +1 -3
- package/src/secrets/__tests__/env-master-key-provider.test.ts +1 -1
- package/src/secrets/__tests__/envelope.test.ts +1 -1
- package/src/secrets/__tests__/leak-guard.test.ts +1 -1
- package/src/secrets/__tests__/rotation.test.ts +1 -1
- package/src/stack/db.ts +25 -48
- package/src/stack/push-entity-projection-tables.ts +2 -4
- package/src/stack/table-helpers.ts +98 -61
- package/src/stack/test-stack.ts +10 -9
- package/src/testing/__tests__/db-cleanup.test.ts +40 -0
- package/src/testing/__tests__/e2e-generator.test.ts +1 -1
- package/src/testing/__tests__/{ensure-entity-table.integration.ts → ensure-entity-table.integration.test.ts} +7 -14
- package/src/testing/db-cleanup.ts +44 -0
- package/src/testing/expect-error.ts +1 -1
- package/src/testing/index.ts +2 -0
- package/src/testing/multipart-helper.ts +94 -0
- package/src/testing/shared-entities.ts +5 -5
- package/src/time/__tests__/polyfill.test.ts +1 -1
- package/src/time/__tests__/tz-context.test.ts +1 -1
- package/src/utils/__tests__/assert.test.ts +1 -1
- package/src/utils/__tests__/case.test.ts +16 -0
- package/src/utils/__tests__/env-parse.test.ts +1 -1
- package/src/utils/__tests__/is-plain-object.test.ts +16 -0
- package/src/utils/__tests__/parse-string-array-json.test.ts +16 -0
- package/src/utils/__tests__/safe-json.test.ts +22 -0
- package/src/utils/case.ts +6 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/is-plain-object.ts +4 -0
- package/src/utils/parse-string-array-json.ts +14 -0
- package/CHANGELOG.md +0 -474
- package/src/db/__tests__/db-helpers.test.ts +0 -369
- package/src/db/__tests__/drizzle-helpers.integration.ts +0 -186
- package/src/db/__tests__/row-helpers.test.ts +0 -59
- package/src/engine/steps/_drizzle-boundary.ts +0 -19
- package/src/files/__tests__/file-field-column.integration.ts +0 -103
package/src/db/__tests__/{schema-migration.integration.ts → schema-migration.integration.test.ts}
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
2
|
+
import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
|
|
3
|
+
import { asRawClient, insertOne, selectMany } from "../../db/query";
|
|
3
4
|
import {
|
|
4
5
|
createBooleanField,
|
|
5
6
|
createDateField,
|
|
@@ -9,8 +10,9 @@ import {
|
|
|
9
10
|
defineFeature,
|
|
10
11
|
} from "../../engine";
|
|
11
12
|
import type { FeatureDefinition } from "../../engine/types";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
13
|
+
import { unsafePushTables } from "../../stack";
|
|
14
|
+
import { ensureTemporalPolyfill } from "../../time/polyfill";
|
|
15
|
+
import { buildEntityTable } from "../table-builder";
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Integration tests for the schema migration workflow.
|
|
@@ -18,14 +20,15 @@ import { buildDrizzleTable } from "../table-builder";
|
|
|
18
20
|
*
|
|
19
21
|
* Each test simulates:
|
|
20
22
|
* 1. Developer defines/changes entities
|
|
21
|
-
* 2.
|
|
23
|
+
* 2. buildEntityTable creates Drizzle table objects
|
|
22
24
|
* 3. Schema is applied to a real database via unsafePushTables (drizzle-kit push)
|
|
23
25
|
* 4. We verify the DB state matches expectations
|
|
24
26
|
*/
|
|
25
27
|
|
|
26
|
-
let testDb:
|
|
28
|
+
let testDb: BunTestDb;
|
|
27
29
|
|
|
28
30
|
beforeAll(async () => {
|
|
31
|
+
await ensureTemporalPolyfill();
|
|
29
32
|
testDb = await createTestDb();
|
|
30
33
|
});
|
|
31
34
|
|
|
@@ -38,7 +41,7 @@ async function applySchema(features: readonly FeatureDefinition[]): Promise<void
|
|
|
38
41
|
const tables: Record<string, unknown> = {};
|
|
39
42
|
for (const feature of features) {
|
|
40
43
|
for (const [entityName, entity] of Object.entries(feature.entities)) {
|
|
41
|
-
tables[entityName] =
|
|
44
|
+
tables[entityName] = buildEntityTable(entityName, entity);
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
47
|
await unsafePushTables(testDb.db, tables);
|
|
@@ -48,12 +51,13 @@ async function applySchema(features: readonly FeatureDefinition[]): Promise<void
|
|
|
48
51
|
async function getTableColumns(
|
|
49
52
|
tableName: string,
|
|
50
53
|
): Promise<Map<string, { dataType: string; isNullable: boolean }>> {
|
|
51
|
-
const rows = await testDb.db.
|
|
54
|
+
const rows = await asRawClient(testDb.db).unsafe<{
|
|
52
55
|
column_name: string;
|
|
53
56
|
data_type: string;
|
|
54
57
|
is_nullable: string;
|
|
55
58
|
}>(
|
|
56
|
-
|
|
59
|
+
`SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_name = $1 ORDER BY ordinal_position`,
|
|
60
|
+
[tableName],
|
|
57
61
|
);
|
|
58
62
|
|
|
59
63
|
const result = new Map<string, { dataType: string; isNullable: boolean }>();
|
|
@@ -121,10 +125,8 @@ describe("schema migration workflows", () => {
|
|
|
121
125
|
});
|
|
122
126
|
await applySchema([feature]);
|
|
123
127
|
|
|
124
|
-
const indexRows = await testDb.db.
|
|
125
|
-
|
|
126
|
-
`SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'wf1b_articles' AND indexname = 'wf1b_articles_tenant_id_idx'`,
|
|
127
|
-
),
|
|
128
|
+
const indexRows = await asRawClient(testDb.db).unsafe<{ indexname: string; indexdef: string }>(
|
|
129
|
+
`SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'wf1b_articles' AND indexname = 'wf1b_articles_tenant_id_idx'`,
|
|
128
130
|
);
|
|
129
131
|
expect(indexRows.length).toBe(1);
|
|
130
132
|
expect(indexRows[0]?.indexdef).toContain("tenant_id");
|
|
@@ -136,7 +138,7 @@ describe("schema migration workflows", () => {
|
|
|
136
138
|
table: "wf2_users",
|
|
137
139
|
fields: { email: createTextField() },
|
|
138
140
|
});
|
|
139
|
-
await unsafePushTables(testDb.db, { user:
|
|
141
|
+
await unsafePushTables(testDb.db, { user: buildEntityTable("user", initialEntity) });
|
|
140
142
|
|
|
141
143
|
// Developer adds a new field
|
|
142
144
|
const updatedEntity = createEntity({
|
|
@@ -150,8 +152,8 @@ describe("schema migration workflows", () => {
|
|
|
150
152
|
// Push updated schema — drizzle-kit generates ALTER TABLE ADD COLUMN
|
|
151
153
|
await unsafePushTables(
|
|
152
154
|
testDb.db,
|
|
153
|
-
{ user:
|
|
154
|
-
{ user:
|
|
155
|
+
{ user: buildEntityTable("user", updatedEntity) },
|
|
156
|
+
{ user: buildEntityTable("user", initialEntity) },
|
|
155
157
|
);
|
|
156
158
|
|
|
157
159
|
const columns = await getTableColumns("wf2_users");
|
|
@@ -166,24 +168,25 @@ describe("schema migration workflows", () => {
|
|
|
166
168
|
table: "wf3_projects",
|
|
167
169
|
fields: { name: createTextField() },
|
|
168
170
|
});
|
|
169
|
-
const initialTable =
|
|
171
|
+
const initialTable = buildEntityTable("project", initialEntity);
|
|
170
172
|
await unsafePushTables(testDb.db, { project: initialTable });
|
|
171
173
|
|
|
172
174
|
// Insert a row first (to prove ADD COLUMN with default doesn't break existing rows)
|
|
173
|
-
await testDb.db
|
|
174
|
-
|
|
175
|
-
|
|
175
|
+
await insertOne(testDb.db, initialTable, {
|
|
176
|
+
tenantId: "00000000-0000-4000-8000-000000000001",
|
|
177
|
+
name: "Test Project",
|
|
178
|
+
});
|
|
176
179
|
|
|
177
180
|
// Developer adds boolean field with default
|
|
178
181
|
const updatedEntity = createEntity({
|
|
179
182
|
table: "wf3_projects",
|
|
180
183
|
fields: { name: createTextField(), isArchived: createBooleanField({ default: false }) },
|
|
181
184
|
});
|
|
182
|
-
const updatedTable =
|
|
185
|
+
const updatedTable = buildEntityTable("project", updatedEntity);
|
|
183
186
|
await unsafePushTables(testDb.db, { project: updatedTable }, { project: initialTable });
|
|
184
187
|
|
|
185
188
|
// Existing row should have the default value
|
|
186
|
-
const rows = await testDb.db
|
|
189
|
+
const rows = await selectMany(testDb.db, updatedTable);
|
|
187
190
|
|
|
188
191
|
expect(rows[0]).toMatchObject({ name: "Test Project", isArchived: false });
|
|
189
192
|
});
|
|
@@ -199,12 +202,13 @@ describe("schema migration workflows", () => {
|
|
|
199
202
|
table: "wf3b_users",
|
|
200
203
|
fields: { email: createTextField({ required: true }) },
|
|
201
204
|
});
|
|
202
|
-
const initialTable =
|
|
205
|
+
const initialTable = buildEntityTable("user", initialEntity);
|
|
203
206
|
await unsafePushTables(testDb.db, { user: initialTable });
|
|
204
207
|
|
|
205
|
-
await testDb.db
|
|
206
|
-
|
|
207
|
-
|
|
208
|
+
await insertOne(testDb.db, initialTable, {
|
|
209
|
+
tenantId: "00000000-0000-4000-8000-000000000001",
|
|
210
|
+
email: "x@y.z",
|
|
211
|
+
});
|
|
208
212
|
|
|
209
213
|
const updatedEntity = createEntity({
|
|
210
214
|
table: "wf3b_users",
|
|
@@ -213,10 +217,10 @@ describe("schema migration workflows", () => {
|
|
|
213
217
|
roles: createTextField({ required: true, default: "[]" }),
|
|
214
218
|
},
|
|
215
219
|
});
|
|
216
|
-
const updatedTable =
|
|
220
|
+
const updatedTable = buildEntityTable("user", updatedEntity);
|
|
217
221
|
await unsafePushTables(testDb.db, { user: updatedTable }, { user: initialTable });
|
|
218
222
|
|
|
219
|
-
const rows = await testDb.db
|
|
223
|
+
const rows = await selectMany(testDb.db, updatedTable);
|
|
220
224
|
expect(rows[0]).toMatchObject({ email: "x@y.z", roles: "[]" });
|
|
221
225
|
});
|
|
222
226
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { afterEach, describe, expect, test } from "bun:test";
|
|
2
|
+
import { formatReport, isRawSqlAllowed, joinPath, scanRepo } from "../sql-inventory";
|
|
3
|
+
|
|
4
|
+
const cleanups: string[] = [];
|
|
5
|
+
|
|
6
|
+
afterEach(async () => {
|
|
7
|
+
for (const dir of cleanups) {
|
|
8
|
+
await Bun.spawn(["rm", "-rf", dir]).exited;
|
|
9
|
+
}
|
|
10
|
+
cleanups.length = 0;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
async function tempRepo(files: Record<string, string>): Promise<string> {
|
|
14
|
+
const root = joinPath(import.meta.dir, `.tmp-sql-inv-${crypto.randomUUID()}`);
|
|
15
|
+
cleanups.push(root);
|
|
16
|
+
await Promise.all(
|
|
17
|
+
Object.entries(files).map(([rel, content]) => Bun.write(joinPath(root, rel), content)),
|
|
18
|
+
);
|
|
19
|
+
return root;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe("sql-inventory", () => {
|
|
23
|
+
test("isRawSqlAllowed permits db/queries and bun-db/query", () => {
|
|
24
|
+
expect(isRawSqlAllowed("/repo/packages/framework/src/db/queries/event-store.ts")).toBe(true);
|
|
25
|
+
expect(isRawSqlAllowed("/repo/packages/framework/src/bun-db/query.ts")).toBe(true);
|
|
26
|
+
expect(
|
|
27
|
+
isRawSqlAllowed("/repo/packages/bundled-features/src/sessions/db/queries/cleanup.ts"),
|
|
28
|
+
).toBe(true);
|
|
29
|
+
expect(isRawSqlAllowed("/repo/samples/apps/marketing-demo/src/db/queries/seed-counts.ts")).toBe(
|
|
30
|
+
true,
|
|
31
|
+
);
|
|
32
|
+
expect(isRawSqlAllowed("/repo/bin/commands/schema.ts")).toBe(true);
|
|
33
|
+
expect(isRawSqlAllowed("/repo/scripts/codemod-drizzle-chain-to-bun-db.ts")).toBe(true);
|
|
34
|
+
expect(
|
|
35
|
+
isRawSqlAllowed("/repo/packages/bundled-features/src/sessions/handlers/cleanup.job.ts"),
|
|
36
|
+
).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("scanRepo classifies production vs test hits", async () => {
|
|
40
|
+
const root = await tempRepo({
|
|
41
|
+
"packages/framework/src/db/queries/demo.ts": `export async function x(db: unknown) {
|
|
42
|
+
return asRawClient(db).unsafe("SELECT 1");
|
|
43
|
+
}`,
|
|
44
|
+
"packages/framework/src/handlers/bad.ts": `export async function y(db: unknown) {
|
|
45
|
+
return asRawClient(db).unsafe("DELETE FROM read_users");
|
|
46
|
+
}`,
|
|
47
|
+
"packages/framework/src/__tests__/ok.integration.ts": `await asRawClient(db).unsafe("DELETE FROM read_users");`,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const report = await scanRepo(root);
|
|
51
|
+
expect(report.summary.byBucket.allowed).toBeGreaterThanOrEqual(1);
|
|
52
|
+
expect(report.summary.byBucket.tests).toBeGreaterThanOrEqual(1);
|
|
53
|
+
expect(report.summary.byBucket.disallowed).toBeGreaterThanOrEqual(1);
|
|
54
|
+
expect(formatReport(report)).toContain("sql inventory");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
// Vorher mussten Apps für unique-indices über mehrere Spalten daneben eine
|
|
4
4
|
// hand-written pgTable-Definition halten — Single-Source-of-Truth gebrochen,
|
|
5
5
|
// Schema-Drift programmiert. Mit entity.indexes pflegen Author die
|
|
6
|
-
// Constraint deklarativ in der EntityDefinition;
|
|
6
|
+
// Constraint deklarativ in der EntityDefinition; buildEntityTable rendert
|
|
7
7
|
// sie via uniqueIndex/index.
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
import { describe, expect, test } from "vitest";
|
|
9
|
+
import { describe, expect, test } from "bun:test";
|
|
11
10
|
import {
|
|
12
11
|
createBooleanField,
|
|
13
12
|
createEntity,
|
|
@@ -15,9 +14,29 @@ import {
|
|
|
15
14
|
defineFeature,
|
|
16
15
|
validateBoot,
|
|
17
16
|
} from "../../engine";
|
|
18
|
-
import {
|
|
17
|
+
import { buildEntityTable } from "../table-builder";
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
// Native dialect equivalent of drizzle's getTableConfig: reads the
|
|
20
|
+
// EntityTableMeta-shape exposed on every SchemaTable.
|
|
21
|
+
// biome-ignore lint/suspicious/noExplicitAny: DDL index test helper
|
|
22
|
+
function getTableConfig(table: any): {
|
|
23
|
+
indexes: Array<{ config: { name: string; unique: boolean; columns: Array<{ name: string }> } }>;
|
|
24
|
+
} {
|
|
25
|
+
const meta = table as unknown as {
|
|
26
|
+
indexes: ReadonlyArray<{ name: string; columns: readonly string[]; unique?: boolean }>;
|
|
27
|
+
};
|
|
28
|
+
return {
|
|
29
|
+
indexes: meta.indexes.map((idx) => ({
|
|
30
|
+
config: {
|
|
31
|
+
name: idx.name,
|
|
32
|
+
unique: idx.unique === true,
|
|
33
|
+
columns: idx.columns.map((c) => ({ name: c })),
|
|
34
|
+
},
|
|
35
|
+
})),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe("buildEntityTable — entity.indexes", () => {
|
|
21
40
|
test("composite unique-index landet als unique=true in Drizzle table-config", () => {
|
|
22
41
|
const entity = createEntity({
|
|
23
42
|
fields: {
|
|
@@ -26,7 +45,7 @@ describe("buildDrizzleTable — entity.indexes", () => {
|
|
|
26
45
|
},
|
|
27
46
|
indexes: [{ unique: true, columns: ["key", "tenantId", "userId"] }],
|
|
28
47
|
});
|
|
29
|
-
const tbl =
|
|
48
|
+
const tbl = buildEntityTable("config-value", entity);
|
|
30
49
|
const { indexes } = getTableConfig(tbl);
|
|
31
50
|
const composite = indexes.find(
|
|
32
51
|
(i) => i.config.name === "read_config_values_key_tenant_id_user_id_unique",
|
|
@@ -48,7 +67,7 @@ describe("buildDrizzleTable — entity.indexes", () => {
|
|
|
48
67
|
},
|
|
49
68
|
indexes: [{ columns: ["startedAt", "endedAt"] }],
|
|
50
69
|
});
|
|
51
|
-
const tbl =
|
|
70
|
+
const tbl = buildEntityTable("session", entity);
|
|
52
71
|
const { indexes } = getTableConfig(tbl);
|
|
53
72
|
const composite = indexes.find(
|
|
54
73
|
(i) => i.config.name === "read_sessions_started_at_ended_at_idx",
|
|
@@ -62,7 +81,7 @@ describe("buildDrizzleTable — entity.indexes", () => {
|
|
|
62
81
|
fields: { slug: createTextField({ required: true }) },
|
|
63
82
|
indexes: [{ unique: true, columns: ["slug"], name: "my_custom_idx" }],
|
|
64
83
|
});
|
|
65
|
-
const tbl =
|
|
84
|
+
const tbl = buildEntityTable("page", entity);
|
|
66
85
|
const { indexes } = getTableConfig(tbl);
|
|
67
86
|
const idx = indexes.find((i) => i.config.name === "my_custom_idx");
|
|
68
87
|
expect(idx).toBeDefined();
|
|
@@ -75,11 +94,11 @@ describe("buildDrizzleTable — entity.indexes", () => {
|
|
|
75
94
|
title: createTextField({}),
|
|
76
95
|
},
|
|
77
96
|
});
|
|
78
|
-
expect(() =>
|
|
97
|
+
expect(() => buildEntityTable("widget", entity)).not.toThrow();
|
|
79
98
|
});
|
|
80
99
|
|
|
81
100
|
test("Spalten die keine DB-Spalte haben (multi-files) werden via Boot-Validator gecatched", () => {
|
|
82
|
-
//
|
|
101
|
+
// buildEntityTable selbst überspringt fehlende Columns silently —
|
|
83
102
|
// der Boot-Validator wirft.
|
|
84
103
|
const entity = createEntity({
|
|
85
104
|
fields: {
|
|
@@ -88,7 +107,7 @@ describe("buildDrizzleTable — entity.indexes", () => {
|
|
|
88
107
|
indexes: [{ columns: ["attachments"] }],
|
|
89
108
|
});
|
|
90
109
|
// No throw at build time.
|
|
91
|
-
expect(() =>
|
|
110
|
+
expect(() => buildEntityTable("widget", entity)).not.toThrow();
|
|
92
111
|
// But validateBoot does.
|
|
93
112
|
const feature = defineFeature("widgetFeature", (r) => {
|
|
94
113
|
r.entity("widget", entity);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// generierte Variante gedriftet sind. Hier: required muss durchschlagen,
|
|
8
8
|
// für jeden Field-Type.
|
|
9
9
|
|
|
10
|
-
import { describe, expect, test } from "
|
|
10
|
+
import { describe, expect, test } from "bun:test";
|
|
11
11
|
import {
|
|
12
12
|
createBooleanField,
|
|
13
13
|
createDateField,
|
|
@@ -24,25 +24,23 @@ import {
|
|
|
24
24
|
createTzField,
|
|
25
25
|
} from "../../engine";
|
|
26
26
|
import type { ReferenceFieldDef } from "../../engine/types";
|
|
27
|
-
import {
|
|
27
|
+
import { buildEntityTable } from "../table-builder";
|
|
28
28
|
|
|
29
29
|
// Reference-fields haben keinen Factory-Helper — direkt-typed inline.
|
|
30
30
|
function refField(args: Omit<ReferenceFieldDef, "type">): ReferenceFieldDef {
|
|
31
31
|
return { type: "reference", ...args };
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function colByName(table:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
for (const col of Object.values(table) as Array<{ name?: string; notNull?: boolean }>) {
|
|
40
|
-
if (col && typeof col === "object" && col.name === dbName) return col;
|
|
34
|
+
function colByName(table: unknown, dbName: string) {
|
|
35
|
+
const cols = (table as { columns?: ReadonlyArray<{ name: string; notNull?: boolean }> }).columns;
|
|
36
|
+
if (!cols) throw new Error("Table has no columns metadata");
|
|
37
|
+
for (const c of cols) {
|
|
38
|
+
if (c.name === dbName) return { name: c.name, notNull: c.notNull };
|
|
41
39
|
}
|
|
42
40
|
throw new Error(`Column ${dbName} not found in table`);
|
|
43
41
|
}
|
|
44
42
|
|
|
45
|
-
describe("
|
|
43
|
+
describe("buildEntityTable — required: true → NOT NULL", () => {
|
|
46
44
|
test("text field — required true makes column NOT NULL", () => {
|
|
47
45
|
const entity = createEntity({
|
|
48
46
|
fields: {
|
|
@@ -50,7 +48,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
50
48
|
subtitle: createTextField({}),
|
|
51
49
|
},
|
|
52
50
|
});
|
|
53
|
-
const tbl =
|
|
51
|
+
const tbl = buildEntityTable("widget", entity);
|
|
54
52
|
expect(colByName(tbl, "title").notNull).toBe(true);
|
|
55
53
|
expect(colByName(tbl, "subtitle").notNull).toBe(false);
|
|
56
54
|
});
|
|
@@ -62,7 +60,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
62
60
|
tag: createSelectField({ options: ["x"] as const }),
|
|
63
61
|
},
|
|
64
62
|
});
|
|
65
|
-
const tbl =
|
|
63
|
+
const tbl = buildEntityTable("widget", entity);
|
|
66
64
|
expect(colByName(tbl, "status").notNull).toBe(true);
|
|
67
65
|
expect(colByName(tbl, "tag").notNull).toBe(false);
|
|
68
66
|
});
|
|
@@ -74,7 +72,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
74
72
|
optional: createNumberField({}),
|
|
75
73
|
},
|
|
76
74
|
});
|
|
77
|
-
const tbl =
|
|
75
|
+
const tbl = buildEntityTable("widget", entity);
|
|
78
76
|
expect(colByName(tbl, "count").notNull).toBe(true);
|
|
79
77
|
expect(colByName(tbl, "optional").notNull).toBe(false);
|
|
80
78
|
});
|
|
@@ -86,7 +84,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
86
84
|
archived: createBooleanField({}),
|
|
87
85
|
},
|
|
88
86
|
});
|
|
89
|
-
const tbl =
|
|
87
|
+
const tbl = buildEntityTable("widget", entity);
|
|
90
88
|
expect(colByName(tbl, "active").notNull).toBe(true);
|
|
91
89
|
// Default ohne required ergibt notNull (default macht Spalte never-null)
|
|
92
90
|
expect(colByName(tbl, "archived").notNull).toBe(true);
|
|
@@ -99,7 +97,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
99
97
|
assignee: refField({ entity: "user" }),
|
|
100
98
|
},
|
|
101
99
|
});
|
|
102
|
-
const tbl =
|
|
100
|
+
const tbl = buildEntityTable("task", entity);
|
|
103
101
|
expect(colByName(tbl, "owner").notNull).toBe(true);
|
|
104
102
|
expect(colByName(tbl, "assignee").notNull).toBe(false);
|
|
105
103
|
});
|
|
@@ -115,7 +113,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
115
113
|
zoneOpt: createTzField({}),
|
|
116
114
|
},
|
|
117
115
|
});
|
|
118
|
-
const tbl =
|
|
116
|
+
const tbl = buildEntityTable("event", entity);
|
|
119
117
|
expect(colByName(tbl, "born_on").notNull).toBe(true);
|
|
120
118
|
expect(colByName(tbl, "born_on_opt").notNull).toBe(false);
|
|
121
119
|
expect(colByName(tbl, "observed_at").notNull).toBe(true);
|
|
@@ -131,7 +129,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
131
129
|
dropoff: createLocatedTimestampField({}),
|
|
132
130
|
},
|
|
133
131
|
});
|
|
134
|
-
const tbl =
|
|
132
|
+
const tbl = buildEntityTable("transport", entity);
|
|
135
133
|
expect(colByName(tbl, "pickup_utc").notNull).toBe(true);
|
|
136
134
|
expect(colByName(tbl, "pickup_tz").notNull).toBe(true);
|
|
137
135
|
expect(colByName(tbl, "dropoff_utc").notNull).toBe(false);
|
|
@@ -156,7 +154,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
156
154
|
}),
|
|
157
155
|
},
|
|
158
156
|
});
|
|
159
|
-
const tbl =
|
|
157
|
+
const tbl = buildEntityTable("acl", entity);
|
|
160
158
|
expect(colByName(tbl, "roles_default").notNull).toBe(true);
|
|
161
159
|
expect(colByName(tbl, "roles_optional").notNull).toBe(true);
|
|
162
160
|
expect(colByName(tbl, "roles_required").notNull).toBe(true);
|
|
@@ -170,7 +168,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
170
168
|
metaOptional: createEmbeddedField({ note: { type: "text" } }, { required: false }),
|
|
171
169
|
},
|
|
172
170
|
});
|
|
173
|
-
const tbl =
|
|
171
|
+
const tbl = buildEntityTable("widget", entity);
|
|
174
172
|
expect(colByName(tbl, "meta").notNull).toBe(true);
|
|
175
173
|
expect(colByName(tbl, "meta_optional").notNull).toBe(true);
|
|
176
174
|
});
|
|
@@ -183,7 +181,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
183
181
|
tagsOptional: refField({ entity: "tag", multiple: true, required: false }),
|
|
184
182
|
},
|
|
185
183
|
});
|
|
186
|
-
const tbl =
|
|
184
|
+
const tbl = buildEntityTable("post", entity);
|
|
187
185
|
expect(colByName(tbl, "tags").notNull).toBe(true);
|
|
188
186
|
expect(colByName(tbl, "tags_optional").notNull).toBe(true);
|
|
189
187
|
});
|
|
@@ -195,7 +193,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
195
193
|
discount: createMoneyField({}),
|
|
196
194
|
},
|
|
197
195
|
});
|
|
198
|
-
const tbl =
|
|
196
|
+
const tbl = buildEntityTable("listing", entity);
|
|
199
197
|
expect(colByName(tbl, "price").notNull).toBe(true);
|
|
200
198
|
expect(colByName(tbl, "price_currency").notNull).toBe(true);
|
|
201
199
|
expect(colByName(tbl, "discount").notNull).toBe(false);
|
|
@@ -209,7 +207,7 @@ describe("buildDrizzleTable — required: true → NOT NULL", () => {
|
|
|
209
207
|
cover: createImageField({}),
|
|
210
208
|
},
|
|
211
209
|
});
|
|
212
|
-
const tbl =
|
|
210
|
+
const tbl = buildEntityTable("profile", entity);
|
|
213
211
|
expect(colByName(tbl, "avatar").notNull).toBe(true);
|
|
214
212
|
expect(colByName(tbl, "cover").notNull).toBe(false);
|
|
215
213
|
});
|