@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,125 @@
|
|
|
1
|
+
// Erzeugt aus einer Server-Registry das client-safe AppSchema das die
|
|
2
|
+
// Browser-Renderer-Pipeline konsumiert. Genauer Zweck: dev-server kann
|
|
3
|
+
// die ganze hand-geschriebene `clientSchema`-Spiegelung abschaffen, der
|
|
4
|
+
// Server schickt einfach das aufgelöste AppSchema beim Boot mit.
|
|
5
|
+
//
|
|
6
|
+
// JSON-Safety: Wir projezieren explizit auf eine Whitelist statt
|
|
7
|
+
// JSON.stringify-roundtripping. Functions würden silent gedroppt und
|
|
8
|
+
// Zod-Schemas (v4 hat .toJSON, aber emittiert ein _zod-Envelope) würden
|
|
9
|
+
// als komische Ghost-Properties auftauchen. Das hier ist ein bewusster
|
|
10
|
+
// Vertrag: was die Browser-Renderer-Pipeline liest, taucht hier auf.
|
|
11
|
+
// Neue Browser-needed-Fields müssen explizit erweitert werden.
|
|
12
|
+
//
|
|
13
|
+
// Aktuell projeziert (Stand 2026-04-25):
|
|
14
|
+
// Entity: { table?, fields: { type, required?, sortable?, default? } }
|
|
15
|
+
// Screen: verbatim (ScreenDefinition ist von Haus aus JSON-safe —
|
|
16
|
+
// custom-screens haben keine functions, layout/columns/etc.
|
|
17
|
+
// sind plain literals)
|
|
18
|
+
// Nav: verbatim (NavDefinition ist nur strings + literals)
|
|
19
|
+
// Workspace: verbatim definition + getWorkspaceNavs() von der Registry
|
|
20
|
+
//
|
|
21
|
+
// Feature-Toggles: BISHER NICHT GEFILTERT. Wenn ein Feature über die
|
|
22
|
+
// feature-toggles-bundled-feature global deaktiviert ist, erscheint es
|
|
23
|
+
// trotzdem im AppSchema. Reason: die Toggle-Auflösung lebt im pipeline-
|
|
24
|
+
// dispatcher, nicht in der Registry, und wir haben hier keinen TenantDb-
|
|
25
|
+
// Kontext um sie zu lesen. TODO wenn das ein realer Use-Case wird:
|
|
26
|
+
// `effectiveFeatures` Argument annehmen und über alle iterations filtern.
|
|
27
|
+
|
|
28
|
+
import type { AppSchema, EntityDefinition, FeatureSchema, WorkspaceSchema } from "../ui-types";
|
|
29
|
+
import type { Registry } from "./types/feature";
|
|
30
|
+
import type { FieldDefinition } from "./types/fields";
|
|
31
|
+
|
|
32
|
+
export function buildAppSchema(registry: Registry): AppSchema {
|
|
33
|
+
const features: FeatureSchema[] = [];
|
|
34
|
+
for (const [featureName, feature] of registry.features) {
|
|
35
|
+
const navs = Object.values(feature.navs);
|
|
36
|
+
const featureSchema: FeatureSchema = {
|
|
37
|
+
featureName,
|
|
38
|
+
entities: projectEntities(feature.entities),
|
|
39
|
+
screens: Object.values(feature.screens),
|
|
40
|
+
...(navs.length > 0 && { navs }),
|
|
41
|
+
};
|
|
42
|
+
features.push(featureSchema);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Workspaces: getAllWorkspaces() liefert mit QUALIFIZIERTEN ids (das
|
|
46
|
+
// schreibt die Registry beim Store-Overwrite ein). Die Browser-
|
|
47
|
+
// Renderer erwartet aber kurze ids (matcht gegen URL-Segment, gegen
|
|
48
|
+
// navigate({ workspaceId })). Wir gehen direkt durch `feature.workspaces`
|
|
49
|
+
// — dort sind die ids noch in der Autor-Form (short) — und ziehen die
|
|
50
|
+
// pre-resolved navMembers aus der Registry.
|
|
51
|
+
const workspaces: WorkspaceSchema[] = [];
|
|
52
|
+
for (const [featureName, feature] of registry.features) {
|
|
53
|
+
for (const [shortId, definition] of Object.entries(feature.workspaces)) {
|
|
54
|
+
const qualified = `${featureName}:workspace:${shortId}`;
|
|
55
|
+
workspaces.push({
|
|
56
|
+
definition: { ...definition, id: shortId },
|
|
57
|
+
navMembers: registry.getWorkspaceNavs(qualified),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
features,
|
|
64
|
+
...(workspaces.length > 0 && { workspaces }),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function projectEntities(
|
|
69
|
+
entities: Readonly<Record<string, EntityDefinition>>,
|
|
70
|
+
): Readonly<Record<string, EntityDefinition>> {
|
|
71
|
+
const out: Record<string, EntityDefinition> = {};
|
|
72
|
+
for (const [name, entity] of Object.entries(entities)) {
|
|
73
|
+
out[name] = projectEntity(entity);
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// EntityDefinition ist eine Discriminated-Union an Field-Types — wir
|
|
79
|
+
// kennen alle JSON-safe Properties pro Field-Type. Statt jede Variante
|
|
80
|
+
// einzeln auszuhandeln, walken wir die Field-Map und filtern auf die
|
|
81
|
+
// Whitelist. Was nicht durchkommt: Server-only-runtime wie ZodValidate-
|
|
82
|
+
// Functions, Computed-Functions, Default-Functions.
|
|
83
|
+
function projectEntity(entity: EntityDefinition): EntityDefinition {
|
|
84
|
+
const fieldsOut: Record<string, FieldDefinition> = {};
|
|
85
|
+
for (const [fieldName, fieldDef] of Object.entries(entity.fields)) {
|
|
86
|
+
fieldsOut[fieldName] = projectField(fieldDef);
|
|
87
|
+
}
|
|
88
|
+
// EntityDefinition akzeptiert idType/access/searchWeight als optional —
|
|
89
|
+
// wir lassen die weg weil der Browser-Renderer sie nicht liest. `table`
|
|
90
|
+
// schicken wir mit, falls Apps `entity.table` direkt referenzieren.
|
|
91
|
+
// Kein Cast nötig: alle weggelassenen Felder sind `?`-optional.
|
|
92
|
+
return {
|
|
93
|
+
fields: fieldsOut,
|
|
94
|
+
...(typeof entity.table === "string" && { table: entity.table }),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Whitelist pro Field. `default` darf nur durch wenn Literal (string/
|
|
99
|
+
// number/boolean/null) — auch wenn die FieldDefinition-Types „default"
|
|
100
|
+
// nur als Literal typisieren, hat das Sample-Pattern
|
|
101
|
+
// `as unknown as EntityDefinition` Authorinnen schon Function-Defaults
|
|
102
|
+
// reinschmuggeln lassen. Diese Defense-in-Depth fängt sie ab BEVOR
|
|
103
|
+
// JSON.stringify sie in der Browser-Injection-Pipeline droppt.
|
|
104
|
+
//
|
|
105
|
+
// Cast am Exit `as FieldDefinition`: type-system-wise erfüllt unsere
|
|
106
|
+
// Out-Map die Discriminated-Union nur mit unverengtem `type`-String —
|
|
107
|
+
// der Cast bridged die Variant-Inferenz, die TS aus einem Generic
|
|
108
|
+
// Record nicht zurückrechnet.
|
|
109
|
+
function projectField(fieldDef: FieldDefinition): FieldDefinition {
|
|
110
|
+
const def = fieldDef as Record<string, unknown>; // @cast-boundary schema-walk
|
|
111
|
+
const out: Record<string, unknown> = {};
|
|
112
|
+
if (typeof def["type"] === "string") out["type"] = def["type"];
|
|
113
|
+
if (typeof def["required"] === "boolean") out["required"] = def["required"];
|
|
114
|
+
if (typeof def["sortable"] === "boolean") out["sortable"] = def["sortable"];
|
|
115
|
+
if (isLiteral(def["default"])) out["default"] = def["default"];
|
|
116
|
+
// Select: options-Liste ist plain JSON, durchschicken.
|
|
117
|
+
if (Array.isArray(def["options"])) out["options"] = def["options"];
|
|
118
|
+
return out as FieldDefinition;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function isLiteral(value: unknown): boolean {
|
|
122
|
+
if (value === null) return true;
|
|
123
|
+
const t = typeof value;
|
|
124
|
+
return t === "string" || t === "number" || t === "boolean";
|
|
125
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { ConfigScope } from "./constants";
|
|
2
|
+
import type {
|
|
3
|
+
ConfigBounds,
|
|
4
|
+
ConfigComputedFn,
|
|
5
|
+
ConfigKeyDefinition,
|
|
6
|
+
ConfigKeyType,
|
|
7
|
+
ConfigValue,
|
|
8
|
+
} from "./types";
|
|
9
|
+
|
|
10
|
+
// --- Access Presets ---
|
|
11
|
+
|
|
12
|
+
export const access = {
|
|
13
|
+
all: ["all"] as readonly string[],
|
|
14
|
+
admin: ["Admin", "SystemAdmin"] as readonly string[],
|
|
15
|
+
systemAdmin: ["SystemAdmin"] as readonly string[],
|
|
16
|
+
system: ["system"] as readonly string[],
|
|
17
|
+
// system + SystemAdmin — use for field-access on identity columns that
|
|
18
|
+
// framework auth code (SYSTEM_USER) writes during login/registration, but
|
|
19
|
+
// that a SystemAdmin should also be able to fix manually.
|
|
20
|
+
privileged: ["system", "SystemAdmin"] as readonly string[],
|
|
21
|
+
// Any signed-in user role. Use on authenticated-but-not-privileged handlers
|
|
22
|
+
// (change-password, logout, me-style queries). Does NOT include "system"
|
|
23
|
+
// since an unauthenticated system call shouldn't be able to hit these.
|
|
24
|
+
authenticated: ["User", "Admin", "SystemAdmin"] as readonly string[],
|
|
25
|
+
// Unauthenticated callers reaching public endpoints (server must opt in
|
|
26
|
+
// via `anonymousAccess`). Combine with authenticated roles when an
|
|
27
|
+
// endpoint should serve both — e.g. `roles: ["anonymous", "customer"]`
|
|
28
|
+
// for a product-listing that personalises when a session is present.
|
|
29
|
+
anonymous: ["anonymous"] as readonly string[],
|
|
30
|
+
roles: (...roles: string[]): readonly string[] => roles,
|
|
31
|
+
} as const;
|
|
32
|
+
|
|
33
|
+
// --- Config Key Options ---
|
|
34
|
+
|
|
35
|
+
// Generic so `default` narrows per type-tag — without it,
|
|
36
|
+
// `createUserConfig("boolean", { default: 19 })` would compile.
|
|
37
|
+
//
|
|
38
|
+
// `bounds` is conditional: only `type="number"` admits it. For any other
|
|
39
|
+
// type-tag the field is `never`, so `createTenantConfig("text", { bounds })`
|
|
40
|
+
// fails at the call site. Matches the same pattern as `default`.
|
|
41
|
+
//
|
|
42
|
+
// `computed` is a fallback-resolver the registry calls when no row + no
|
|
43
|
+
// app-override exists — used for plan-based limits (see
|
|
44
|
+
// configuration-layers.md, "Frage 3: Hängt Geld dran?").
|
|
45
|
+
//
|
|
46
|
+
// `allowPerRequest` is conditional against `text`: text keys can never
|
|
47
|
+
// opt in to per-request overrides (XSS/SQL/Shell risk). For other types
|
|
48
|
+
// it's a plain boolean opt-in consumed by resolveConfigOrParam.
|
|
49
|
+
type ConfigKeyOptions<T extends ConfigKeyType> = {
|
|
50
|
+
write?: readonly string[];
|
|
51
|
+
read?: readonly string[];
|
|
52
|
+
default?: ConfigValue<T>;
|
|
53
|
+
encrypted?: boolean;
|
|
54
|
+
options?: readonly string[]; // for select type
|
|
55
|
+
bounds?: T extends "number" ? ConfigBounds : never;
|
|
56
|
+
computed?: ConfigComputedFn<T>;
|
|
57
|
+
allowPerRequest?: T extends "text" ? never : boolean;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// --- Scope Defaults ---
|
|
61
|
+
|
|
62
|
+
const SCOPE_DEFAULTS: Record<ConfigScope, { write: readonly string[]; read: readonly string[] }> = {
|
|
63
|
+
tenant: { write: access.admin, read: access.all },
|
|
64
|
+
system: { write: access.system, read: access.admin },
|
|
65
|
+
user: { write: access.all, read: access.all },
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// --- Factory ---
|
|
69
|
+
|
|
70
|
+
function createConfigKey<T extends ConfigKeyType>(
|
|
71
|
+
scope: ConfigScope,
|
|
72
|
+
type: T,
|
|
73
|
+
opts: ConfigKeyOptions<T> = {},
|
|
74
|
+
): ConfigKeyDefinition<T> {
|
|
75
|
+
const defaults = SCOPE_DEFAULTS[scope];
|
|
76
|
+
return {
|
|
77
|
+
type,
|
|
78
|
+
scope,
|
|
79
|
+
access: {
|
|
80
|
+
write: opts.write ?? defaults.write,
|
|
81
|
+
read: opts.read ?? defaults.read,
|
|
82
|
+
},
|
|
83
|
+
default: opts.default,
|
|
84
|
+
...(opts.encrypted ? { encrypted: true } : {}),
|
|
85
|
+
...(opts.options ? { options: opts.options } : {}),
|
|
86
|
+
bounds: opts.bounds as ConfigBounds | undefined,
|
|
87
|
+
computed: opts.computed,
|
|
88
|
+
...(opts.allowPerRequest === true ? { allowPerRequest: true } : {}),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// --- Public API ---
|
|
93
|
+
// Generic on the type-tag so `r.config({keys})` can propagate it into the
|
|
94
|
+
// returned `ConfigKeyHandle<T>` — that's what narrows `ctx.config(handle)`.
|
|
95
|
+
|
|
96
|
+
export function createTenantConfig<T extends ConfigKeyType>(
|
|
97
|
+
type: T,
|
|
98
|
+
opts?: ConfigKeyOptions<T>,
|
|
99
|
+
): ConfigKeyDefinition<T> {
|
|
100
|
+
return createConfigKey("tenant", type, opts);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function createSystemConfig<T extends ConfigKeyType>(
|
|
104
|
+
type: T,
|
|
105
|
+
opts?: ConfigKeyOptions<T>,
|
|
106
|
+
): ConfigKeyDefinition<T> {
|
|
107
|
+
return createConfigKey("system", type, opts);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function createUserConfig<T extends ConfigKeyType>(
|
|
111
|
+
type: T,
|
|
112
|
+
opts?: ConfigKeyOptions<T>,
|
|
113
|
+
): ConfigKeyDefinition<T> {
|
|
114
|
+
return createConfigKey("user", type, opts);
|
|
115
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
|
|
3
|
+
// All framework constants as `as const` objects with inferred union types.
|
|
4
|
+
// No enums — only const objects + typeof inference.
|
|
5
|
+
|
|
6
|
+
// Error codes — the canonical list lives on the KumikoError subclasses in
|
|
7
|
+
// `errors/classes.ts`. Features that need to surface a feature-specific reason
|
|
8
|
+
// attach it under `details.reason` on the relevant Kumiko error class.
|
|
9
|
+
|
|
10
|
+
// --- System Hook Names ---
|
|
11
|
+
|
|
12
|
+
export const SystemHookNames = {
|
|
13
|
+
cascadeDelete: "system:hook:cascade-delete",
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
16
|
+
export type SystemHookName = (typeof SystemHookNames)[keyof typeof SystemHookNames];
|
|
17
|
+
|
|
18
|
+
// --- System Hook Priorities ---
|
|
19
|
+
|
|
20
|
+
export const SystemHookPriorities = {
|
|
21
|
+
cascadeDelete: 500,
|
|
22
|
+
} as const;
|
|
23
|
+
|
|
24
|
+
// --- Message Kinds ---
|
|
25
|
+
|
|
26
|
+
export const MessageKind = {
|
|
27
|
+
write: "write",
|
|
28
|
+
query: "query",
|
|
29
|
+
command: "command",
|
|
30
|
+
shared: "shared",
|
|
31
|
+
broadcast: "broadcast",
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
export type MessageKind = (typeof MessageKind)[keyof typeof MessageKind];
|
|
35
|
+
|
|
36
|
+
// --- Lifecycle Hook Types ---
|
|
37
|
+
|
|
38
|
+
export const LifecycleHookTypes = {
|
|
39
|
+
preSave: "preSave",
|
|
40
|
+
postSave: "postSave",
|
|
41
|
+
preDelete: "preDelete",
|
|
42
|
+
postDelete: "postDelete",
|
|
43
|
+
preQuery: "preQuery",
|
|
44
|
+
} as const;
|
|
45
|
+
|
|
46
|
+
export type LifecycleHookType = (typeof LifecycleHookTypes)[keyof typeof LifecycleHookTypes];
|
|
47
|
+
|
|
48
|
+
// --- Config Scopes ---
|
|
49
|
+
|
|
50
|
+
export const ConfigScopes = {
|
|
51
|
+
system: "system",
|
|
52
|
+
tenant: "tenant",
|
|
53
|
+
user: "user",
|
|
54
|
+
} as const;
|
|
55
|
+
|
|
56
|
+
export type ConfigScope = (typeof ConfigScopes)[keyof typeof ConfigScopes];
|
|
57
|
+
|
|
58
|
+
// --- On Delete Strategies ---
|
|
59
|
+
|
|
60
|
+
export const OnDeleteStrategies = {
|
|
61
|
+
cascade: "cascade",
|
|
62
|
+
restrict: "restrict",
|
|
63
|
+
setNull: "setNull",
|
|
64
|
+
nothing: "nothing",
|
|
65
|
+
} as const;
|
|
66
|
+
|
|
67
|
+
export type OnDeleteStrategy = (typeof OnDeleteStrategies)[keyof typeof OnDeleteStrategies];
|
|
68
|
+
|
|
69
|
+
// --- Concurrency Modes ---
|
|
70
|
+
|
|
71
|
+
export const ConcurrencyModes = {
|
|
72
|
+
parallel: "parallel",
|
|
73
|
+
skip: "skip",
|
|
74
|
+
replace: "replace",
|
|
75
|
+
sequential: "sequential",
|
|
76
|
+
debounce: "debounce",
|
|
77
|
+
} as const;
|
|
78
|
+
|
|
79
|
+
export type ConcurrencyMode = (typeof ConcurrencyModes)[keyof typeof ConcurrencyModes];
|
|
80
|
+
|
|
81
|
+
// --- SSE Channels ---
|
|
82
|
+
|
|
83
|
+
export function tenantChannel(tenantId: TenantId): string {
|
|
84
|
+
return `tenant:${tenantId}`;
|
|
85
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { validateBoot } from "./boot-validator";
|
|
2
|
+
import { createRegistry } from "./registry";
|
|
3
|
+
import type { FeatureDefinition, Registry } from "./types";
|
|
4
|
+
import { DEFAULT_CURRENCIES } from "./types";
|
|
5
|
+
|
|
6
|
+
export type AppConfig = {
|
|
7
|
+
roles: readonly string[];
|
|
8
|
+
features: readonly FeatureDefinition[];
|
|
9
|
+
softDelete?: boolean; // Global default for all entities (default: true)
|
|
10
|
+
currencies?: readonly string[]; // Extends DEFAULT_CURRENCIES
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type App = {
|
|
14
|
+
registry: Registry;
|
|
15
|
+
roles: readonly string[];
|
|
16
|
+
softDeleteDefault: boolean;
|
|
17
|
+
currencies: readonly string[];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export function createApp(config: AppConfig): App {
|
|
21
|
+
const validRoles = new Set(config.roles);
|
|
22
|
+
|
|
23
|
+
// "system" is reserved for SYSTEM_USER — cannot be used as an app role
|
|
24
|
+
if (validRoles.has("system")) {
|
|
25
|
+
throw new Error('Role "system" is reserved for SYSTEM_USER and cannot be used as an app role');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Special roles that don't need to be in the app's role list
|
|
29
|
+
const systemRoles = new Set(["all", "system"]);
|
|
30
|
+
|
|
31
|
+
// Validate all roles referenced by features exist in app-defined roles.
|
|
32
|
+
// openToAll access has no role list — nothing to validate there.
|
|
33
|
+
for (const feature of config.features) {
|
|
34
|
+
for (const handler of Object.values(feature.writeHandlers)) {
|
|
35
|
+
if (handler.access && "roles" in handler.access) {
|
|
36
|
+
for (const role of handler.access.roles) {
|
|
37
|
+
if (!validRoles.has(role)) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Unknown role "${role}" in write handler "${handler.name}" of feature "${feature.name}". Valid roles: ${config.roles.join(", ")}`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
for (const handler of Object.values(feature.queryHandlers)) {
|
|
46
|
+
if (handler.access && "roles" in handler.access) {
|
|
47
|
+
for (const role of handler.access.roles) {
|
|
48
|
+
if (!validRoles.has(role)) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`Unknown role "${role}" in query handler "${handler.name}" of feature "${feature.name}". Valid roles: ${config.roles.join(", ")}`,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (const [key, keyDef] of Object.entries(feature.configKeys)) {
|
|
57
|
+
for (const role of [...keyDef.access.read, ...keyDef.access.write]) {
|
|
58
|
+
if (!systemRoles.has(role) && !validRoles.has(role)) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`Unknown role "${role}" in config key "${feature.name}.${key}" of feature "${feature.name}". Valid roles: ${config.roles.join(", ")}`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const softDeleteDefault = config.softDelete ?? true;
|
|
68
|
+
|
|
69
|
+
// Merge default + custom currencies, deduplicate
|
|
70
|
+
const currencies = [...new Set([...DEFAULT_CURRENCIES, ...(config.currencies ?? [])])];
|
|
71
|
+
|
|
72
|
+
// Validate defaultCurrency on entities that have money fields
|
|
73
|
+
for (const feature of config.features) {
|
|
74
|
+
for (const [entityName, entity] of Object.entries(feature.entities)) {
|
|
75
|
+
const hasMoneyField = Object.values(entity.fields).some((f) => f.type === "money");
|
|
76
|
+
if (entity.defaultCurrency && !currencies.includes(entity.defaultCurrency)) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Entity "${entityName}" in feature "${feature.name}" has defaultCurrency "${entity.defaultCurrency}" which is not in the currencies list. Available: ${currencies.join(", ")}`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
if (hasMoneyField && !entity.defaultCurrency) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Entity "${entityName}" in feature "${feature.name}" has money fields but no defaultCurrency. Set defaultCurrency on the entity definition.`,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Run boot-time validation before creating registry
|
|
90
|
+
validateBoot(config.features);
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
registry: createRegistry(config.features),
|
|
94
|
+
roles: config.roles,
|
|
95
|
+
softDeleteDefault,
|
|
96
|
+
currencies,
|
|
97
|
+
};
|
|
98
|
+
}
|