@cosmicdrift/kumiko-framework 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +159 -0
- package/package.json +91 -0
- package/src/__tests__/anonymous-access.integration.ts +325 -0
- package/src/__tests__/error-contract.integration.ts +435 -0
- package/src/__tests__/field-access.integration.ts +269 -0
- package/src/__tests__/full-stack.integration.ts +914 -0
- package/src/__tests__/ownership.integration.ts +449 -0
- package/src/__tests__/reference-data.integration.ts +198 -0
- package/src/__tests__/transition-guard.integration.ts +340 -0
- package/src/api/__tests__/api.test.ts +337 -0
- package/src/api/__tests__/auth-middleware-transport.test.ts +80 -0
- package/src/api/__tests__/auth-routes-cookie.test.ts +179 -0
- package/src/api/__tests__/batch.integration.ts +404 -0
- package/src/api/__tests__/body-limit.test.ts +88 -0
- package/src/api/__tests__/csrf-middleware.test.ts +97 -0
- package/src/api/__tests__/dispatcher-live.integration.ts +216 -0
- package/src/api/__tests__/metrics-endpoint.test.ts +126 -0
- package/src/api/__tests__/nested-write.integration.ts +213 -0
- package/src/api/__tests__/readiness.test.ts +76 -0
- package/src/api/__tests__/request-id-middleware.test.ts +72 -0
- package/src/api/__tests__/sse-broker.test.ts +58 -0
- package/src/api/__tests__/sse-route.test.ts +112 -0
- package/src/api/anonymous-cookie.ts +60 -0
- package/src/api/api-constants.ts +64 -0
- package/src/api/auth-middleware.ts +418 -0
- package/src/api/auth-routes.ts +982 -0
- package/src/api/csrf-middleware.ts +77 -0
- package/src/api/index.ts +31 -0
- package/src/api/jwt.ts +66 -0
- package/src/api/observability-middleware.ts +89 -0
- package/src/api/readiness.ts +132 -0
- package/src/api/request-context.ts +49 -0
- package/src/api/request-id-middleware.ts +50 -0
- package/src/api/route-registrars.ts +195 -0
- package/src/api/routes.ts +135 -0
- package/src/api/server.ts +640 -0
- package/src/api/sse-broker.ts +71 -0
- package/src/api/sse-route.ts +62 -0
- package/src/api/tokens.ts +16 -0
- package/src/db/__tests__/apply-entity-event-tenant.integration.ts +159 -0
- package/src/db/__tests__/compound-types.test.ts +114 -0
- package/src/db/__tests__/connection-options.test.ts +68 -0
- package/src/db/__tests__/cursor.test.ts +41 -0
- package/src/db/__tests__/db-helpers.test.ts +369 -0
- package/src/db/__tests__/dialect-instant.test.ts +50 -0
- package/src/db/__tests__/drizzle-helpers.integration.ts +186 -0
- package/src/db/__tests__/drizzle-table-types.test.ts +162 -0
- package/src/db/__tests__/encryption.test.ts +39 -0
- package/src/db/__tests__/event-store-executor-list.integration.ts +313 -0
- package/src/db/__tests__/event-store-executor.integration.ts +235 -0
- package/src/db/__tests__/implicit-projection-equivalence.integration.ts +304 -0
- package/src/db/__tests__/located-timestamp.test.ts +184 -0
- package/src/db/__tests__/money.test.ts +199 -0
- package/src/db/__tests__/multi-row-insert.integration.ts +76 -0
- package/src/db/__tests__/parse-auto-verb.test.ts +70 -0
- package/src/db/__tests__/required-not-null-migration-safety.integration.ts +105 -0
- package/src/db/__tests__/row-helpers.test.ts +59 -0
- package/src/db/__tests__/schema-migration.integration.ts +273 -0
- package/src/db/__tests__/table-builder-indexes.test.ts +153 -0
- package/src/db/__tests__/table-builder-required.test.ts +216 -0
- package/src/db/__tests__/tenant-db.integration.ts +606 -0
- package/src/db/__tests__/unique-violation-mapping.integration.ts +166 -0
- package/src/db/apply-entity-event.ts +188 -0
- package/src/db/assert-exists-in.ts +59 -0
- package/src/db/compound-types.ts +47 -0
- package/src/db/connection.ts +104 -0
- package/src/db/cursor.ts +83 -0
- package/src/db/dialect.ts +109 -0
- package/src/db/eagerload.ts +174 -0
- package/src/db/encryption.ts +39 -0
- package/src/db/event-store-executor.ts +906 -0
- package/src/db/index.ts +55 -0
- package/src/db/located-timestamp.ts +114 -0
- package/src/db/money.ts +120 -0
- package/src/db/pg-error.ts +46 -0
- package/src/db/reference-data.ts +77 -0
- package/src/db/row-helpers.ts +53 -0
- package/src/db/schema-inspection.ts +25 -0
- package/src/db/table-builder.ts +475 -0
- package/src/db/tenant-db.ts +434 -0
- package/src/engine/__tests__/auth-claims-registrar.test.ts +74 -0
- package/src/engine/__tests__/boot-validator-located-timestamps.test.ts +108 -0
- package/src/engine/__tests__/boot-validator.test.ts +1865 -0
- package/src/engine/__tests__/build-app-schema.test.ts +154 -0
- package/src/engine/__tests__/claim-keys.test.ts +274 -0
- package/src/engine/__tests__/config-helpers.test.ts +236 -0
- package/src/engine/__tests__/effective-features.test.ts +86 -0
- package/src/engine/__tests__/engine.test.ts +1461 -0
- package/src/engine/__tests__/entity-handlers.test.ts +274 -0
- package/src/engine/__tests__/event-helpers.test.ts +68 -0
- package/src/engine/__tests__/extends-registrar.test.ts +159 -0
- package/src/engine/__tests__/factories-long-text.test.ts +84 -0
- package/src/engine/__tests__/factories-time.test.ts +158 -0
- package/src/engine/__tests__/field-predicates.test.ts +48 -0
- package/src/engine/__tests__/hook-phases.test.ts +132 -0
- package/src/engine/__tests__/identifiers.test.ts +35 -0
- package/src/engine/__tests__/lifecycle-hooks.test.ts +237 -0
- package/src/engine/__tests__/nav.test.ts +267 -0
- package/src/engine/__tests__/ownership.test.ts +421 -0
- package/src/engine/__tests__/parse-ref-target.test.ts +43 -0
- package/src/engine/__tests__/projection-helpers.test.ts +62 -0
- package/src/engine/__tests__/projection.test.ts +191 -0
- package/src/engine/__tests__/qualified-name.test.ts +264 -0
- package/src/engine/__tests__/resolve-config-or-param.test.ts +315 -0
- package/src/engine/__tests__/run-in.test.ts +38 -0
- package/src/engine/__tests__/schema-builder.test.ts +380 -0
- package/src/engine/__tests__/screen.test.ts +408 -0
- package/src/engine/__tests__/state-machine.test.ts +148 -0
- package/src/engine/__tests__/system-user.test.ts +57 -0
- package/src/engine/__tests__/validation-hooks.test.ts +71 -0
- package/src/engine/access.ts +23 -0
- package/src/engine/boot-validator.ts +1528 -0
- package/src/engine/build-app-schema.ts +125 -0
- package/src/engine/config-helpers.ts +115 -0
- package/src/engine/constants.ts +85 -0
- package/src/engine/create-app.ts +98 -0
- package/src/engine/define-feature.ts +702 -0
- package/src/engine/define-handler.ts +78 -0
- package/src/engine/define-roles.ts +19 -0
- package/src/engine/effective-features.ts +87 -0
- package/src/engine/entity-handlers.ts +364 -0
- package/src/engine/event-helpers.ts +73 -0
- package/src/engine/factories.ts +328 -0
- package/src/engine/feature-ast/__tests__/canonical-form.test.ts +416 -0
- package/src/engine/feature-ast/__tests__/parse-happy-path.test.ts +197 -0
- package/src/engine/feature-ast/__tests__/parse-real-features.test.ts +128 -0
- package/src/engine/feature-ast/__tests__/parse.test.ts +888 -0
- package/src/engine/feature-ast/__tests__/patch.test.ts +360 -0
- package/src/engine/feature-ast/__tests__/patcher.test.ts +469 -0
- package/src/engine/feature-ast/__tests__/render-roundtrip.test.ts +287 -0
- package/src/engine/feature-ast/extractors.ts +2562 -0
- package/src/engine/feature-ast/index.ts +105 -0
- package/src/engine/feature-ast/parse.ts +369 -0
- package/src/engine/feature-ast/patch.ts +525 -0
- package/src/engine/feature-ast/patcher.ts +518 -0
- package/src/engine/feature-ast/patterns.ts +434 -0
- package/src/engine/feature-ast/render.ts +602 -0
- package/src/engine/feature-ast/source-location.ts +45 -0
- package/src/engine/field-access.ts +120 -0
- package/src/engine/index.ts +254 -0
- package/src/engine/ownership.ts +337 -0
- package/src/engine/parse-ref-target.ts +22 -0
- package/src/engine/pattern-library/__tests__/library.test.ts +351 -0
- package/src/engine/pattern-library/index.ts +24 -0
- package/src/engine/pattern-library/library.ts +1117 -0
- package/src/engine/pattern-library/types.ts +255 -0
- package/src/engine/projection-helpers.ts +85 -0
- package/src/engine/qualified-name.ts +122 -0
- package/src/engine/read-claim.ts +31 -0
- package/src/engine/registry.ts +1325 -0
- package/src/engine/resolve-config-or-param.ts +153 -0
- package/src/engine/run-in.ts +29 -0
- package/src/engine/schema-builder.ts +175 -0
- package/src/engine/screen-filter-ops.ts +51 -0
- package/src/engine/state-machine.ts +70 -0
- package/src/engine/system-user.ts +32 -0
- package/src/engine/types/config.ts +306 -0
- package/src/engine/types/event-type-map.ts +37 -0
- package/src/engine/types/feature.ts +574 -0
- package/src/engine/types/fields.ts +422 -0
- package/src/engine/types/handlers.ts +742 -0
- package/src/engine/types/hooks.ts +142 -0
- package/src/engine/types/http-route.ts +54 -0
- package/src/engine/types/identifiers.ts +47 -0
- package/src/engine/types/index.ts +208 -0
- package/src/engine/types/nav.ts +46 -0
- package/src/engine/types/projection.ts +132 -0
- package/src/engine/types/relations.ts +51 -0
- package/src/engine/types/screen.ts +452 -0
- package/src/engine/types/workspace.ts +42 -0
- package/src/engine/validation.ts +33 -0
- package/src/entrypoint/__tests__/entrypoint-job-wiring.integration.ts +173 -0
- package/src/entrypoint/__tests__/split-deploy.integration.ts +297 -0
- package/src/entrypoint/index.ts +442 -0
- package/src/errors/__tests__/classes.test.ts +371 -0
- package/src/errors/__tests__/write-failures.test.ts +109 -0
- package/src/errors/classes.ts +249 -0
- package/src/errors/i18n/de.yaml +83 -0
- package/src/errors/i18n/en.yaml +80 -0
- package/src/errors/index.ts +41 -0
- package/src/errors/kumiko-error.ts +67 -0
- package/src/errors/reasons.ts +36 -0
- package/src/errors/serialize.ts +136 -0
- package/src/errors/transition-details.ts +30 -0
- package/src/errors/write-error-info.ts +123 -0
- package/src/errors/zod-bridge.ts +49 -0
- package/src/event-store/__tests__/admin-api.integration.ts +361 -0
- package/src/event-store/__tests__/event-store.integration.ts +584 -0
- package/src/event-store/__tests__/get-stream-version-perf.integration.ts +83 -0
- package/src/event-store/__tests__/perf.integration.ts +255 -0
- package/src/event-store/__tests__/snapshot.integration.ts +267 -0
- package/src/event-store/__tests__/upcaster-dead-letter.integration.ts +204 -0
- package/src/event-store/__tests__/upcaster.integration.ts +460 -0
- package/src/event-store/admin-api.ts +257 -0
- package/src/event-store/archive.ts +106 -0
- package/src/event-store/errors.ts +35 -0
- package/src/event-store/event-store.ts +405 -0
- package/src/event-store/events-schema.ts +90 -0
- package/src/event-store/index.ts +50 -0
- package/src/event-store/snapshot.ts +210 -0
- package/src/event-store/upcaster-dead-letter.ts +119 -0
- package/src/event-store/upcaster.ts +147 -0
- package/src/files/__tests__/content-disposition.test.ts +123 -0
- package/src/files/__tests__/file-field-column.integration.ts +103 -0
- package/src/files/__tests__/file-field-pipeline.integration.ts +211 -0
- package/src/files/__tests__/file-handle.test.ts +122 -0
- package/src/files/__tests__/files.integration.ts +830 -0
- package/src/files/__tests__/storage-tracking.integration.ts +153 -0
- package/src/files/content-disposition.ts +55 -0
- package/src/files/file-handle.ts +63 -0
- package/src/files/file-ref-table.ts +22 -0
- package/src/files/file-routes.ts +353 -0
- package/src/files/in-memory-provider.ts +62 -0
- package/src/files/index.ts +29 -0
- package/src/files/local-provider.ts +35 -0
- package/src/files/storage-tracking.ts +60 -0
- package/src/files/types.ts +118 -0
- package/src/i18n/__tests__/i18n.test.ts +72 -0
- package/src/i18n/index.ts +29 -0
- package/src/jobs/__tests__/job-event-trigger.integration.ts +172 -0
- package/src/jobs/__tests__/job-multi-trigger.integration.ts +144 -0
- package/src/jobs/__tests__/jobs.integration.ts +566 -0
- package/src/jobs/index.ts +2 -0
- package/src/jobs/job-runner.ts +574 -0
- package/src/lifecycle/__tests__/create-test-lifecycle.ts +19 -0
- package/src/lifecycle/__tests__/lifecycle-server.integration.ts +108 -0
- package/src/lifecycle/__tests__/lifecycle.test.ts +212 -0
- package/src/lifecycle/__tests__/signal-handlers.test.ts +106 -0
- package/src/lifecycle/index.ts +13 -0
- package/src/lifecycle/lifecycle.ts +160 -0
- package/src/lifecycle/signal-handlers.ts +62 -0
- package/src/logging/__tests__/pino-trace-bridge.test.ts +50 -0
- package/src/logging/index.ts +3 -0
- package/src/logging/pino-logger.ts +64 -0
- package/src/logging/types.ts +7 -0
- package/src/migrations/__tests__/compare-snapshots.test.ts +150 -0
- package/src/migrations/__tests__/detect-drift.integration.ts +320 -0
- package/src/migrations/__tests__/detect-projections-to-rebuild.integration.ts +134 -0
- package/src/migrations/__tests__/rebuild-marker.test.ts +79 -0
- package/src/migrations/index.ts +28 -0
- package/src/migrations/projection-detection.ts +149 -0
- package/src/migrations/rebuild-marker.ts +64 -0
- package/src/migrations/schema-drift.ts +395 -0
- package/src/observability/__tests__/console-provider.test.ts +67 -0
- package/src/observability/__tests__/metric-validator.test.ts +87 -0
- package/src/observability/__tests__/noop-provider.test.ts +82 -0
- package/src/observability/__tests__/observability.integration.ts +559 -0
- package/src/observability/__tests__/prometheus-meter.test.ts +144 -0
- package/src/observability/__tests__/recording-meter.test.ts +101 -0
- package/src/observability/__tests__/recording-tracer.test.ts +110 -0
- package/src/observability/__tests__/sensitive-filter.test.ts +98 -0
- package/src/observability/console-provider.ts +130 -0
- package/src/observability/context.ts +26 -0
- package/src/observability/fallback.ts +34 -0
- package/src/observability/ids.ts +25 -0
- package/src/observability/index.ts +79 -0
- package/src/observability/metric-validator.ts +86 -0
- package/src/observability/metrics-handle.ts +56 -0
- package/src/observability/noop-provider.ts +146 -0
- package/src/observability/prometheus-meter.ts +284 -0
- package/src/observability/recording-meter.ts +156 -0
- package/src/observability/recording-tracer.ts +198 -0
- package/src/observability/redis-wrapper.ts +132 -0
- package/src/observability/sensitive-filter.ts +108 -0
- package/src/observability/standard-metrics.ts +213 -0
- package/src/observability/types/index.ts +29 -0
- package/src/observability/types/metric.ts +56 -0
- package/src/observability/types/provider.ts +32 -0
- package/src/observability/types/span.ts +64 -0
- package/src/pipeline/__tests__/archive-stream.integration.ts +220 -0
- package/src/pipeline/__tests__/auth-claims-resolver.test.ts +279 -0
- package/src/pipeline/__tests__/cascade-handler.integration.ts +419 -0
- package/src/pipeline/__tests__/cascade-handler.test.ts +52 -0
- package/src/pipeline/__tests__/causation-chain.integration.ts +206 -0
- package/src/pipeline/__tests__/ctx-bridge.integration.ts +234 -0
- package/src/pipeline/__tests__/dispatcher.test.ts +379 -0
- package/src/pipeline/__tests__/distributed-lock.integration.ts +67 -0
- package/src/pipeline/__tests__/domain-events-projections.integration.ts +323 -0
- package/src/pipeline/__tests__/event-dedup.integration.ts +153 -0
- package/src/pipeline/__tests__/event-define-event-strict.integration.ts +202 -0
- package/src/pipeline/__tests__/event-dispatcher-lifecycle.integration.ts +220 -0
- package/src/pipeline/__tests__/event-dispatcher-multi-instance.integration.ts +423 -0
- package/src/pipeline/__tests__/event-dispatcher-pg-listen.integration.ts +123 -0
- package/src/pipeline/__tests__/event-dispatcher-recovery.integration.ts +202 -0
- package/src/pipeline/__tests__/event-dispatcher-second-audit.integration.ts +290 -0
- package/src/pipeline/__tests__/event-dispatcher-strict.test.ts +65 -0
- package/src/pipeline/__tests__/event-dispatcher.integration.ts +287 -0
- package/src/pipeline/__tests__/event-retention.integration.ts +239 -0
- package/src/pipeline/__tests__/fetch-for-writing.integration.ts +281 -0
- package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +430 -0
- package/src/pipeline/__tests__/load-aggregate-query.integration.ts +266 -0
- package/src/pipeline/__tests__/msp-error-mode.integration.ts +149 -0
- package/src/pipeline/__tests__/msp-multi-hop.integration.ts +228 -0
- package/src/pipeline/__tests__/msp-rebuild.integration.ts +368 -0
- package/src/pipeline/__tests__/multi-stream-projection.integration.ts +341 -0
- package/src/pipeline/__tests__/perf-rebuild.integration.ts +147 -0
- package/src/pipeline/__tests__/projection-rebuild.integration.ts +551 -0
- package/src/pipeline/__tests__/query-projection.integration.ts +201 -0
- package/src/pipeline/__tests__/redis-pipeline.integration.ts +306 -0
- package/src/pipeline/append-event-core.ts +117 -0
- package/src/pipeline/auth-claims-resolver.ts +103 -0
- package/src/pipeline/cascade-handler.ts +113 -0
- package/src/pipeline/dispatcher.ts +1585 -0
- package/src/pipeline/distributed-lock.ts +37 -0
- package/src/pipeline/entity-cache.ts +113 -0
- package/src/pipeline/event-consumer-state.ts +108 -0
- package/src/pipeline/event-dedup.ts +23 -0
- package/src/pipeline/event-dispatcher.ts +1016 -0
- package/src/pipeline/event-retention.ts +154 -0
- package/src/pipeline/idempotency.ts +76 -0
- package/src/pipeline/index.ts +66 -0
- package/src/pipeline/lifecycle-pipeline.ts +409 -0
- package/src/pipeline/msp-rebuild.ts +242 -0
- package/src/pipeline/multi-stream-apply-context.ts +115 -0
- package/src/pipeline/projection-rebuild.ts +334 -0
- package/src/pipeline/projection-state.ts +72 -0
- package/src/pipeline/projections-runner.ts +56 -0
- package/src/pipeline/redis-keys.ts +11 -0
- package/src/pipeline/system-hooks.ts +190 -0
- package/src/random/__tests__/generate.test.ts +149 -0
- package/src/random/generate.ts +141 -0
- package/src/random/index.ts +8 -0
- package/src/random/words.ts +392 -0
- package/src/rate-limit/__tests__/dispatcher-l3.integration.ts +111 -0
- package/src/rate-limit/__tests__/middleware.integration.ts +189 -0
- package/src/rate-limit/__tests__/resolver.integration.ts +189 -0
- package/src/rate-limit/bucket.ts +36 -0
- package/src/rate-limit/index.ts +14 -0
- package/src/rate-limit/middleware.ts +152 -0
- package/src/rate-limit/resolver.ts +267 -0
- package/src/redis/__tests__/redis-options.test.ts +54 -0
- package/src/redis/index.ts +74 -0
- package/src/search/__tests__/meilisearch-adapter.integration.ts +236 -0
- package/src/search/__tests__/search-adapter.test.ts +256 -0
- package/src/search/in-memory-adapter.ts +123 -0
- package/src/search/index.ts +12 -0
- package/src/search/meilisearch-adapter.ts +106 -0
- package/src/search/types.ts +39 -0
- package/src/secrets/__tests__/dek-cache.test.ts +213 -0
- package/src/secrets/__tests__/env-master-key-provider.test.ts +119 -0
- package/src/secrets/__tests__/envelope.test.ts +74 -0
- package/src/secrets/__tests__/leak-guard.test.ts +92 -0
- package/src/secrets/__tests__/rotation.test.ts +149 -0
- package/src/secrets/dek-cache.ts +116 -0
- package/src/secrets/env-master-key-provider.ts +162 -0
- package/src/secrets/envelope.ts +55 -0
- package/src/secrets/index.ts +19 -0
- package/src/secrets/leak-guard.ts +87 -0
- package/src/secrets/rotation.ts +34 -0
- package/src/secrets/types.ts +107 -0
- package/src/stack/db.ts +104 -0
- package/src/stack/event-collector.ts +23 -0
- package/src/stack/index.ts +32 -0
- package/src/stack/redis.ts +44 -0
- package/src/stack/request-helper.ts +168 -0
- package/src/stack/table-helpers.ts +104 -0
- package/src/stack/test-stack.ts +357 -0
- package/src/stack/test-users.ts +37 -0
- package/src/testing/__tests__/e2e-generator.test.ts +230 -0
- package/src/testing/__tests__/ensure-entity-table.integration.ts +54 -0
- package/src/testing/access-assertions.ts +15 -0
- package/src/testing/assertions.ts +35 -0
- package/src/testing/e2e-generator.ts +465 -0
- package/src/testing/expect-error.ts +25 -0
- package/src/testing/handler-context.ts +125 -0
- package/src/testing/http-cookies.ts +52 -0
- package/src/testing/index.ts +41 -0
- package/src/testing/late-bound.ts +39 -0
- package/src/testing/mutable-master-key-provider.ts +31 -0
- package/src/testing/observability-recorder.ts +54 -0
- package/src/testing/shared-entities.ts +49 -0
- package/src/testing/utils.ts +1 -0
- package/src/testing/wait-for.ts +31 -0
- package/src/time/__tests__/polyfill.test.ts +73 -0
- package/src/time/__tests__/tz-context.test.ts +121 -0
- package/src/time/index.ts +21 -0
- package/src/time/polyfill.ts +70 -0
- package/src/time/tz-context.ts +107 -0
- package/src/ui-types/app-schema.ts +57 -0
- package/src/ui-types/index.ts +65 -0
- package/src/utils/__tests__/assert.test.ts +17 -0
- package/src/utils/__tests__/env-parse.test.ts +54 -0
- package/src/utils/assert.ts +18 -0
- package/src/utils/env-parse.ts +16 -0
- package/src/utils/ids.ts +16 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/safe-json.ts +30 -0
- package/src/utils/serialization.ts +7 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BooleanFieldDef,
|
|
3
|
+
DateFieldDef,
|
|
4
|
+
EmbeddedFieldDef,
|
|
5
|
+
EntityDefinition,
|
|
6
|
+
FieldsMap,
|
|
7
|
+
FileFieldDef,
|
|
8
|
+
FilesFieldDef,
|
|
9
|
+
ImageFieldDef,
|
|
10
|
+
ImagesFieldDef,
|
|
11
|
+
LocatedTimestampFieldDef,
|
|
12
|
+
LongTextFieldDef,
|
|
13
|
+
MoneyFieldDef,
|
|
14
|
+
MultiSelectFieldDef,
|
|
15
|
+
NumberFieldDef,
|
|
16
|
+
SelectFieldDef,
|
|
17
|
+
TextFieldDef,
|
|
18
|
+
TimestampFieldDef,
|
|
19
|
+
TzFieldDef,
|
|
20
|
+
} from "./types";
|
|
21
|
+
|
|
22
|
+
// Generic über `R extends true | false` (statt `boolean`) damit
|
|
23
|
+
// `createTextField({ required: true })` literal `required: true` im
|
|
24
|
+
// Return-Type behält. `boolean` würde widenen — DrizzleTable<E>'s
|
|
25
|
+
// Mapped-Type könnte dann nicht zwischen `required: true` und
|
|
26
|
+
// `required: false` dispatchen, jede Column würde zu nullable
|
|
27
|
+
// degradieren. Default `R = false` matcht den runtime-default. Pattern
|
|
28
|
+
// in jeder required-bearing factory unten.
|
|
29
|
+
export function createTextField<R extends true | false = false>(
|
|
30
|
+
overrides?: Partial<Omit<TextFieldDef, "type" | "required">> & { required?: R },
|
|
31
|
+
): TextFieldDef & { required: R } {
|
|
32
|
+
return {
|
|
33
|
+
type: "text",
|
|
34
|
+
maxLength: 200,
|
|
35
|
+
required: false,
|
|
36
|
+
searchable: false,
|
|
37
|
+
sortable: false,
|
|
38
|
+
...overrides,
|
|
39
|
+
} as TextFieldDef & { required: R };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Long-form text field for source-code, markdown, blog-posts, email-
|
|
44
|
+
* templates — anything that can be megabytes large. Type-level differs
|
|
45
|
+
* from `text`: keine sortable/searchable/filterable/format options.
|
|
46
|
+
* DB-mapping ist identisch zu text (PG text ist unbounded).
|
|
47
|
+
*
|
|
48
|
+
* Soft-cap default: kein maxLength (PG text ist 1 GB hart begrenzt).
|
|
49
|
+
* Setze einen explicit `maxLength` wenn du ein verirrtes Browser-Paste
|
|
50
|
+
* früh ablehnen willst (z.B. 1_000_000 = 1 MB).
|
|
51
|
+
*/
|
|
52
|
+
export function createLongTextField<R extends true | false = false>(
|
|
53
|
+
overrides?: Partial<Omit<LongTextFieldDef, "type" | "required">> & { required?: R },
|
|
54
|
+
): LongTextFieldDef & { required: R } {
|
|
55
|
+
return {
|
|
56
|
+
type: "longText",
|
|
57
|
+
required: false,
|
|
58
|
+
...overrides,
|
|
59
|
+
} as LongTextFieldDef & { required: R };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function createBooleanField<R extends true | false = false>(
|
|
63
|
+
overrides?: Partial<Omit<BooleanFieldDef, "type" | "required">> & { required?: R },
|
|
64
|
+
): BooleanFieldDef & { required: R } {
|
|
65
|
+
return {
|
|
66
|
+
type: "boolean",
|
|
67
|
+
required: false,
|
|
68
|
+
default: false,
|
|
69
|
+
...overrides,
|
|
70
|
+
} as BooleanFieldDef & { required: R };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function createSelectField<
|
|
74
|
+
const TOptions extends readonly string[],
|
|
75
|
+
R extends true | false = false,
|
|
76
|
+
>(
|
|
77
|
+
opts: { options: TOptions } & Partial<
|
|
78
|
+
Omit<SelectFieldDef<TOptions>, "type" | "options" | "required">
|
|
79
|
+
> & { required?: R },
|
|
80
|
+
): SelectFieldDef<TOptions> & { required: R } {
|
|
81
|
+
return {
|
|
82
|
+
type: "select",
|
|
83
|
+
required: false,
|
|
84
|
+
...opts,
|
|
85
|
+
} as SelectFieldDef<TOptions> & { required: R };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Multi-Select-Field — N Werte aus einer festen Options-Liste.
|
|
90
|
+
*
|
|
91
|
+
* Storage: jsonb-Array<string>. Jeder Eintrag muss in `options` enthalten
|
|
92
|
+
* sein (Boot-Validator). UI-Renderer rendert das als Checkbox-Group oder
|
|
93
|
+
* Multi-Select-Dropdown.
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* licenceClasses: createMultiSelectField({
|
|
97
|
+
* options: ["B", "BE", "C", "C1", "CE", "C1E", "D", "D1"] as const,
|
|
98
|
+
* default: ["B"],
|
|
99
|
+
* }),
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* Caller-API:
|
|
103
|
+
* Write: `{ licenceClasses: ["B", "BE", "C1"] }`
|
|
104
|
+
* Read: `{ licenceClasses: ["B", "BE", "C1"] }`
|
|
105
|
+
*
|
|
106
|
+
* Wann statt `select`: wenn mehrere Werte gleichzeitig erlaubt sind.
|
|
107
|
+
* Wann statt `embedded` mit Booleans: bei mehr als ~5 Optionen.
|
|
108
|
+
*/
|
|
109
|
+
export function createMultiSelectField<const TOptions extends readonly string[]>(
|
|
110
|
+
opts: { options: TOptions } & Partial<Omit<MultiSelectFieldDef<TOptions>, "type" | "options">>,
|
|
111
|
+
): MultiSelectFieldDef<TOptions> {
|
|
112
|
+
return {
|
|
113
|
+
type: "multiSelect",
|
|
114
|
+
required: false,
|
|
115
|
+
...opts,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function createNumberField<R extends true | false = false>(
|
|
120
|
+
overrides?: Partial<Omit<NumberFieldDef, "type" | "required">> & { required?: R },
|
|
121
|
+
): NumberFieldDef & { required: R } {
|
|
122
|
+
return {
|
|
123
|
+
type: "number",
|
|
124
|
+
required: false,
|
|
125
|
+
...overrides,
|
|
126
|
+
} as NumberFieldDef & { required: R };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function createMoneyField<R extends true | false = false>(
|
|
130
|
+
overrides?: Partial<Omit<MoneyFieldDef, "type" | "required">> & { required?: R },
|
|
131
|
+
): MoneyFieldDef & { required: R } {
|
|
132
|
+
return {
|
|
133
|
+
type: "money",
|
|
134
|
+
...overrides,
|
|
135
|
+
} as MoneyFieldDef & { required: R };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function createEmbeddedField(
|
|
139
|
+
schema: EmbeddedFieldDef["schema"],
|
|
140
|
+
overrides?: Partial<Omit<EmbeddedFieldDef, "type" | "schema">>,
|
|
141
|
+
): EmbeddedFieldDef {
|
|
142
|
+
return {
|
|
143
|
+
type: "embedded",
|
|
144
|
+
schema,
|
|
145
|
+
...overrides,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function createDateField<R extends true | false = false>(
|
|
150
|
+
overrides?: Partial<Omit<DateFieldDef, "type" | "required">> & { required?: R },
|
|
151
|
+
): DateFieldDef & { required: R } {
|
|
152
|
+
return {
|
|
153
|
+
type: "date",
|
|
154
|
+
required: false,
|
|
155
|
+
...overrides,
|
|
156
|
+
} as DateFieldDef & { required: R };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* UTC-Instant — für Ereignisse die zu einem bestimmten Zeitpunkt passieren
|
|
161
|
+
* (createdAt, loginAt, actualPickupAt). Temporal.Instant intern.
|
|
162
|
+
*
|
|
163
|
+
* Mit `locatedBy: "<name>Tz"` wird das Feld zum Wall-Clock-Pair eines
|
|
164
|
+
* Termins an einem Ort — bevorzuge dafür den `locatedTimestamp(name)`
|
|
165
|
+
* Helper, der Pair + Marker atomar erzeugt.
|
|
166
|
+
*/
|
|
167
|
+
export function createTimestampField<R extends true | false = false>(
|
|
168
|
+
overrides?: Partial<Omit<TimestampFieldDef, "type" | "required">> & { required?: R },
|
|
169
|
+
): TimestampFieldDef & { required: R } {
|
|
170
|
+
// Object-Build vermeidet hartcodiertes `required: false` im literal —
|
|
171
|
+
// das würde TS dazu bringen, R auf `boolean` zu widenen statt das
|
|
172
|
+
// literal `true`/`false` aus dem overrides-Argument zu inferieren.
|
|
173
|
+
return {
|
|
174
|
+
...overrides,
|
|
175
|
+
type: "timestamp",
|
|
176
|
+
required: (overrides?.required ?? false) as R,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* IANA-Zonenname (z.B. "Europe/Berlin"). Wird im Boot/Schema-Validator
|
|
182
|
+
* via `Intl.supportedValuesOf("timeZone")` geprüft (kommt im Zod-Schritt).
|
|
183
|
+
*/
|
|
184
|
+
export function createTzField<R extends true | false = false>(
|
|
185
|
+
overrides?: Partial<Omit<TzFieldDef, "type" | "required">> & { required?: R },
|
|
186
|
+
): TzFieldDef & { required: R } {
|
|
187
|
+
return {
|
|
188
|
+
type: "tz",
|
|
189
|
+
required: false,
|
|
190
|
+
...overrides,
|
|
191
|
+
} as TzFieldDef & { required: R };
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Wall-Clock-Termin an einem Ort als ATOMARES Field. Empfohlene Form für
|
|
196
|
+
* jeden Date-Wert mit Location-Bezug (Pickup, Delivery, Meeting, Schedule).
|
|
197
|
+
*
|
|
198
|
+
* EIN Schema-Feld → ZWEI DB-Spalten (`<name>_utc TIMESTAMPTZ` + `<name>_tz TEXT`)
|
|
199
|
+
* → DREI API-Felder beim Read (`{ at, tz, utc }`).
|
|
200
|
+
*
|
|
201
|
+
* ```ts
|
|
202
|
+
* r.entity("order", {
|
|
203
|
+
* fields: {
|
|
204
|
+
* pickup: createLocatedTimestampField(),
|
|
205
|
+
* delivery: createLocatedTimestampField(),
|
|
206
|
+
* },
|
|
207
|
+
* });
|
|
208
|
+
*
|
|
209
|
+
* // Write — Caller schickt at+tz, Framework rechnet utc aus
|
|
210
|
+
* await create({ pickup: { at: "2026-04-15T10:00:00", tz: "Europe/Lisbon" } });
|
|
211
|
+
*
|
|
212
|
+
* // Read — Framework liefert alle drei Felder zurück
|
|
213
|
+
* // → { pickup: { at: "10:00", tz: "Europe/Lisbon", utc: "09:00Z" } }
|
|
214
|
+
*
|
|
215
|
+
* // Sort/Filter über die UTC-Spalte
|
|
216
|
+
* orderBy(asc(orderTable.pickupUtc))
|
|
217
|
+
* where(between(orderTable.pickupUtc, start, end))
|
|
218
|
+
* ```
|
|
219
|
+
*
|
|
220
|
+
* Default-Sicht für `at` ist Pickup-Ort-lokal (was eingegeben wurde, kommt
|
|
221
|
+
* mit demselben Tag zurück). User-lokale Sicht kommt aus `utc` per
|
|
222
|
+
* separater Berechnung.
|
|
223
|
+
*/
|
|
224
|
+
export function createLocatedTimestampField<R extends true | false = false>(
|
|
225
|
+
overrides?: Partial<Omit<LocatedTimestampFieldDef, "type" | "required">> & { required?: R },
|
|
226
|
+
): LocatedTimestampFieldDef & { required: R } {
|
|
227
|
+
return {
|
|
228
|
+
type: "locatedTimestamp",
|
|
229
|
+
required: false,
|
|
230
|
+
...overrides,
|
|
231
|
+
} as LocatedTimestampFieldDef & { required: R };
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @deprecated Verwende stattdessen `createLocatedTimestampField()` —
|
|
236
|
+
* EIN Field-Type statt zwei lose Pair-Felder. Migration: ersetze
|
|
237
|
+
* `...locatedTimestamp("pickup")` durch `pickup: createLocatedTimestampField()`.
|
|
238
|
+
*
|
|
239
|
+
* Wall-Clock-Termin an einem Ort — Helper der ZWEI verbundene Felder
|
|
240
|
+
* erzeugt. Bevorzugte Form für jeden Date-Wert mit Location-Bezug
|
|
241
|
+
* (Pickup, Delivery, Meeting, Schedule).
|
|
242
|
+
*
|
|
243
|
+
* ```ts
|
|
244
|
+
* r.entity("order", {
|
|
245
|
+
* fields: {
|
|
246
|
+
* ...locatedTimestamp("pickup"), // → pickupAt + pickupTz
|
|
247
|
+
* ...locatedTimestamp("delivery"), // → deliveryAt + deliveryTz
|
|
248
|
+
* },
|
|
249
|
+
* });
|
|
250
|
+
* ```
|
|
251
|
+
*
|
|
252
|
+
* Zur Laufzeit wird:
|
|
253
|
+
* - DB: `<name>_at TIMESTAMPTZ` (UTC) + `<name>_tz TEXT` (IANA-Name)
|
|
254
|
+
* - JSON: `{ <name>At: "2026-04-03T10:00:00", <name>Tz: "Europe/Lisbon" }`
|
|
255
|
+
* (Wall-Clock OHNE Offset, plus IANA-Name — zwei getrennte Felder)
|
|
256
|
+
* - Reducer/Apply: kann mit Temporal.ZonedDateTime arbeiten
|
|
257
|
+
*
|
|
258
|
+
* Optionen pro Feld (z.B. `required` auf den At-Teil) per zweitem Argument.
|
|
259
|
+
*/
|
|
260
|
+
export function locatedTimestamp(
|
|
261
|
+
name: string,
|
|
262
|
+
overrides?: { readonly required?: boolean; readonly access?: TimestampFieldDef["access"] },
|
|
263
|
+
): Readonly<Record<string, TimestampFieldDef | TzFieldDef>> {
|
|
264
|
+
const atName = `${name}At`;
|
|
265
|
+
const tzName = `${name}Tz`;
|
|
266
|
+
return {
|
|
267
|
+
[atName]: {
|
|
268
|
+
type: "timestamp",
|
|
269
|
+
locatedBy: tzName,
|
|
270
|
+
required: overrides?.required,
|
|
271
|
+
access: overrides?.access,
|
|
272
|
+
},
|
|
273
|
+
[tzName]: {
|
|
274
|
+
type: "tz",
|
|
275
|
+
required: overrides?.required,
|
|
276
|
+
access: overrides?.access,
|
|
277
|
+
},
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export function createFileField(overrides?: Partial<Omit<FileFieldDef, "type">>): FileFieldDef {
|
|
282
|
+
return { type: "file", ...overrides };
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export function createImageField(overrides?: Partial<Omit<ImageFieldDef, "type">>): ImageFieldDef {
|
|
286
|
+
return { type: "image", ...overrides };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function createFilesField(overrides?: Partial<Omit<FilesFieldDef, "type">>): FilesFieldDef {
|
|
290
|
+
return { type: "files", ...overrides };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function createImagesField(
|
|
294
|
+
overrides?: Partial<Omit<ImagesFieldDef, "type">>,
|
|
295
|
+
): ImagesFieldDef {
|
|
296
|
+
return { type: "images", ...overrides };
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// `F` läuft OHNE Constraint im Generic-Param damit TS die literal-types
|
|
300
|
+
// einzelner Field-Defs durchzieht (required: true bleibt true, nicht
|
|
301
|
+
// boolean). Constraint-Match gegen FieldsMap würde widenen — siehe TS-
|
|
302
|
+
// Issue um Constraint-Inferenz auf strukturellen Records. Stattdessen
|
|
303
|
+
// validieren wir die Conformance via conditional return type: wenn F
|
|
304
|
+
// nicht FieldsMap-compat ist, kollabiert der Return zu `never`.
|
|
305
|
+
export function createEntity<F>(def: {
|
|
306
|
+
readonly table?: string;
|
|
307
|
+
readonly fields: F;
|
|
308
|
+
readonly softDelete?: boolean;
|
|
309
|
+
readonly searchWeight?: number;
|
|
310
|
+
readonly defaultCurrency?: string;
|
|
311
|
+
readonly transitions?: Readonly<Record<string, Readonly<Record<string, readonly string[]>>>>;
|
|
312
|
+
readonly indexes?: readonly {
|
|
313
|
+
readonly columns: readonly [string, ...string[]];
|
|
314
|
+
readonly unique?: boolean;
|
|
315
|
+
readonly name?: string;
|
|
316
|
+
}[];
|
|
317
|
+
readonly idType?: "serial" | "uuid";
|
|
318
|
+
readonly access?: EntityDefinition["access"];
|
|
319
|
+
}): F extends FieldsMap ? EntityDefinition<F> : never {
|
|
320
|
+
return {
|
|
321
|
+
softDelete: false,
|
|
322
|
+
searchWeight: 1,
|
|
323
|
+
// Default to UUID — post-ES-pivot every entity is event-sourced and
|
|
324
|
+
// aggregate-ids are UUID. Opt-out with `idType: "serial"` for pre-ES
|
|
325
|
+
// legacy tables (should be rare).
|
|
326
|
+
...def,
|
|
327
|
+
} as F extends FieldsMap ? EntityDefinition<F> : never;
|
|
328
|
+
}
|