bazis 0.96.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +146 -0
- package/cli/build.ts +147 -0
- package/cli/codegen.ts +40 -0
- package/cli/generateModule.ts +187 -0
- package/cli/generateProject.ts +183 -0
- package/cli/main.ts +125 -0
- package/cli/moduleRegistration.ts +127 -0
- package/cli/naming.ts +124 -0
- package/cli/parseCli.ts +151 -0
- package/cli/templates/module.ts +497 -0
- package/cli/templates/pack.ts +76 -0
- package/cli/templates/passport.ts +178 -0
- package/core/agent/AgentContextBuilder.ts +567 -0
- package/core/agent/AgentDataDefinition.ts +8 -0
- package/core/agent/AgentRegistry.ts +539 -0
- package/core/agent/AgentRuntime.ts +47 -0
- package/core/agent/AgentToolExecutor.ts +2130 -0
- package/core/agent/AgentToolHooks.ts +39 -0
- package/core/agent/ModelProvider.ts +21 -0
- package/core/agent/README.md +229 -0
- package/core/agent/Tool.contract.ts +20 -0
- package/core/agent/decorators/Agent.ts +11 -0
- package/core/agent/decorators/Prompt.ts +11 -0
- package/core/agent/decorators/Task.ts +29 -0
- package/core/agent/decorators/Tool.ts +12 -0
- package/core/agent/errors.ts +43 -0
- package/core/agent/generated/catalog.ts +26 -0
- package/core/agent/index.ts +170 -0
- package/core/agent/internal/AgentExecutionDriver.ts +1497 -0
- package/core/agent/internal/AgentExecutionState.ts +775 -0
- package/core/agent/internal/AgentJsonSchema.ts +150 -0
- package/core/agent/internal/AgentModelBinding.ts +57 -0
- package/core/agent/internal/Schema.contract.ts +36 -0
- package/core/agent/internal/ToolAudit.projector.ts +163 -0
- package/core/agent/internal/ToolContract.validator.ts +102 -0
- package/core/agent/metadata.ts +398 -0
- package/core/agent/moduleContributions-v1.ts +113 -0
- package/core/agent/semantic.ts +903 -0
- package/core/agent/session/codec.ts +33 -0
- package/core/agent/session/contracts.ts +96 -0
- package/core/agent/session/entities.ts +84 -0
- package/core/agent/session/protector.ts +92 -0
- package/core/app/index.ts +5 -0
- package/core/app/runApp.ts +293 -0
- package/core/app/ui/index.ts +29 -0
- package/core/app/ui/uiProfileResolver.ts +966 -0
- package/core/app/ui/uiSurfaceHosting.ts +38 -0
- package/core/app/ui/uiSurfaceHttp.ts +476 -0
- package/core/background/BackgroundService.ts +223 -0
- package/core/background/backgroundModule.ts +42 -0
- package/core/background/decorator.ts +43 -0
- package/core/background/delay.ts +27 -0
- package/core/background/index.ts +15 -0
- package/core/cache/COMPATIBILITY.md +13 -0
- package/core/cache/ICache.ts +71 -0
- package/core/cache/MemoryCache.ts +394 -0
- package/core/cache/README.md +83 -0
- package/core/cache/SPEC.md +1355 -0
- package/core/cache/cacheModule.ts +21 -0
- package/core/cache/decorators/Cacheable.ts +38 -0
- package/core/cache/decorators/CacheableRedis.ts +39 -0
- package/core/cache/decorators/OutputCache.ts +33 -0
- package/core/cache/decorators/OutputRedisCache.ts +33 -0
- package/core/cache/decorators/cacheableMetadata.ts +78 -0
- package/core/cache/decorators/cacheableRedisMetadata.ts +81 -0
- package/core/cache/decorators/outputCacheMetadata.ts +71 -0
- package/core/cache/decorators/outputRedisCacheMetadata.ts +77 -0
- package/core/cache/di/classProviderHook.ts +26 -0
- package/core/cache/distributed/CacheCodec.ts +5 -0
- package/core/cache/distributed/DistributedCache.ts +403 -0
- package/core/cache/distributed/DistributedCacheDriver.ts +83 -0
- package/core/cache/distributed/DistributedCacheStores.ts +28 -0
- package/core/cache/distributed/IDistributedCache.ts +40 -0
- package/core/cache/distributed/NamedCacheRegistry.ts +23 -0
- package/core/cache/distributed/codecs.ts +32 -0
- package/core/cache/distributed/index.ts +19 -0
- package/core/cache/errors/CacheError.ts +16 -0
- package/core/cache/http/CachedHttpPayload.ts +213 -0
- package/core/cache/http/applyClientCacheHeaders.ts +61 -0
- package/core/cache/http/buildOutputCacheKey.ts +154 -0
- package/core/cache/http/buildRedisOutputCacheKey.ts +16 -0
- package/core/cache/http/composeOutputCache.ts +130 -0
- package/core/cache/http/outputCacheMiddleware.ts +111 -0
- package/core/cache/http/outputCacheSecurityWarning.ts +58 -0
- package/core/cache/http/outputRedisCacheMiddleware.ts +118 -0
- package/core/cache/index.ts +97 -0
- package/core/cache/internal/AutomaticCacheKey.ts +106 -0
- package/core/cache/internal/CacheKeyGuard.ts +56 -0
- package/core/cache/internal/buildCacheProviders.ts +146 -0
- package/core/cache/internal/normalizeCacheKey.ts +9 -0
- package/core/cache/internal/resolveCachePolicy.ts +32 -0
- package/core/cache/internal/resolveCacheableRedisPolicy.ts +17 -0
- package/core/cache/internal/resolveOutputRedisCachePolicy.ts +17 -0
- package/core/cache/providers/cachedProviders.ts +68 -0
- package/core/cache/services/cacheProxy.ts +243 -0
- package/core/cache/tokens/CACHE_POLICIES.ts +5 -0
- package/core/cache/tokens/DISTRIBUTED_CACHE.ts +30 -0
- package/core/cache/types/CacheEntry.ts +7 -0
- package/core/cache/types/CacheOptions.ts +60 -0
- package/core/cache/types/CachePolicy.ts +74 -0
- package/core/cache/types/CacheableRedisOptions.ts +23 -0
- package/core/cache/types/OutputRedisCacheOptions.ts +25 -0
- package/core/di/README.md +104 -0
- package/core/di/ServiceCollection.ts +185 -0
- package/core/di/ServiceProvider.ts +689 -0
- package/core/di/ServiceScope.ts +61 -0
- package/core/di/container.ts +38 -0
- package/core/di/errors/AmbiguousNamedDependencyError.ts +10 -0
- package/core/di/errors/AsyncResolutionRequiredError.ts +12 -0
- package/core/di/errors/CircularDependencyError.ts +10 -0
- package/core/di/errors/ClassDependenciesMismatchError.ts +15 -0
- package/core/di/errors/DiError.ts +6 -0
- package/core/di/errors/InvalidProviderError.ts +9 -0
- package/core/di/errors/ModuleEncapsulationError.ts +7 -0
- package/core/di/errors/ModuleOwnedProviderConflictError.ts +8 -0
- package/core/di/errors/NamedDependencyNotFoundError.ts +7 -0
- package/core/di/errors/OptionsValidationError.ts +7 -0
- package/core/di/errors/ProviderNotFoundError.ts +10 -0
- package/core/di/errors/ScopeDisposedError.ts +7 -0
- package/core/di/errors/ScopedServiceFromRootError.ts +9 -0
- package/core/di/errors/ServiceValidationError.ts +7 -0
- package/core/di/errors/index.ts +14 -0
- package/core/di/extensions/activator.ts +39 -0
- package/core/di/extensions/application.ts +117 -0
- package/core/di/extensions/hosted-service.ts +124 -0
- package/core/di/extensions/index.ts +23 -0
- package/core/di/extensions/options-reloadable.ts +137 -0
- package/core/di/extensions/options.ts +91 -0
- package/core/di/extensions/service-provider-token.ts +21 -0
- package/core/di/index.ts +97 -0
- package/core/di/internal/GraphValidator.ts +119 -0
- package/core/di/internal/HostedServicePlan.ts +158 -0
- package/core/di/internal/NamedTokenIndex.ts +55 -0
- package/core/di/internal/OpenGenericRegistration.ts +14 -0
- package/core/di/internal/ResolutionPlan.ts +18 -0
- package/core/di/internal/ResolutionScopeState.ts +19 -0
- package/core/di/internal/ResolutionTracker.ts +153 -0
- package/core/di/internal/ScopeLifecycle.ts +159 -0
- package/core/di/internal/ServiceRegistration.ts +14 -0
- package/core/di/internal/ServiceRegistry.ts +252 -0
- package/core/di/internal/classDeps.ts +38 -0
- package/core/di/internal/disposal.ts +58 -0
- package/core/di/internal/providerDeps.ts +26 -0
- package/core/di/module/DI.ts +146 -0
- package/core/di/module/Global.ts +25 -0
- package/core/di/module/Module.ts +44 -0
- package/core/di/module/ModuleRegistrar.ts +69 -0
- package/core/di/module/autoDeps.ts +39 -0
- package/core/di/module/classProviderHooks.ts +66 -0
- package/core/di/module/collectModuleConfigs.ts +57 -0
- package/core/di/module/collectModuleControllers.ts +53 -0
- package/core/di/module/collectModuleUiProfiles.ts +53 -0
- package/core/di/module/createContainer.ts +261 -0
- package/core/di/module/encapsulation.ts +416 -0
- package/core/di/module/encapsulationHooks.ts +36 -0
- package/core/di/module/generatedProviderAttachments.ts +102 -0
- package/core/di/module/index.ts +41 -0
- package/core/di/module/moduleExtensions.ts +35 -0
- package/core/di/module/moduleNameBinding.ts +136 -0
- package/core/di/module/moduleOwnedProviderContributors.ts +409 -0
- package/core/di/module/providerSelection.ts +90 -0
- package/core/di/module/shortcuts.ts +111 -0
- package/core/di/module/types/BazisModule.ts +71 -0
- package/core/di/module/types/DiRegistrar.ts +24 -0
- package/core/di/module/types/index.ts +2 -0
- package/core/di/provider/index.ts +26 -0
- package/core/di/provider/providerGuards.ts +17 -0
- package/core/di/provider/types/AsyncFactoryProvider.ts +15 -0
- package/core/di/provider/types/ClassProvider.ts +18 -0
- package/core/di/provider/types/FactoryProvider.ts +20 -0
- package/core/di/provider/types/KeyedDependency.ts +20 -0
- package/core/di/provider/types/LazyDependency.ts +31 -0
- package/core/di/provider/types/NamedDependency.ts +16 -0
- package/core/di/provider/types/Provider.ts +10 -0
- package/core/di/provider/types/ProviderDefinition.ts +11 -0
- package/core/di/provider/types/ProviderDependencyList.ts +11 -0
- package/core/di/provider/types/ProviderLifetime.ts +1 -0
- package/core/di/provider/types/ProviderOwnership.ts +7 -0
- package/core/di/provider/types/ResolvedDeps.ts +18 -0
- package/core/di/provider/types/ValueProvider.ts +6 -0
- package/core/di/provider/types/index.ts +13 -0
- package/core/di/token.ts +84 -0
- package/core/di/types/BuildServiceProviderOptions.ts +4 -0
- package/core/di/types/ServiceKey.ts +1 -0
- package/core/di/types/ServiceResolver.ts +16 -0
- package/core/di/types/index.ts +3 -0
- package/core/generatedFingerprint.ts +60 -0
- package/core/generatedRuntime.ts +187 -0
- package/core/grpc/Grpc.module.ts +23 -0
- package/core/grpc/GrpcBinding.contract.ts +35 -0
- package/core/grpc/GrpcCall.ts +73 -0
- package/core/grpc/GrpcClient.ts +172 -0
- package/core/grpc/GrpcClientCall.ts +267 -0
- package/core/grpc/GrpcError.ts +19 -0
- package/core/grpc/GrpcRequest.binding.ts +45 -0
- package/core/grpc/GrpcServer.ts +204 -0
- package/core/grpc/GrpcStatus.ts +8 -0
- package/core/grpc/GrpcTransport.ts +174 -0
- package/core/grpc/Metadata.ts +73 -0
- package/core/grpc/ProtoCodec.ts +225 -0
- package/core/grpc/ProtoParser.ts +192 -0
- package/core/grpc/ProtoReader.ts +34 -0
- package/core/grpc/ProtoSchema.ts +52 -0
- package/core/grpc/ServerCredentials.ts +30 -0
- package/core/grpc/clientContracts.ts +39 -0
- package/core/grpc/contracts.ts +45 -0
- package/core/grpc/decorators.ts +82 -0
- package/core/grpc/grpcClientProvider.ts +9 -0
- package/core/grpc/index.ts +17 -0
- package/core/grpc/moduleControllers.ts +38 -0
- package/core/grpc/protobuf.ts +80 -0
- package/core/grpc/serviceDefinition.ts +20 -0
- package/core/http/Authorization/Authorize.ts +52 -0
- package/core/http/Authorization/authorizeComposer.ts +31 -0
- package/core/http/Authorization/metadata.ts +158 -0
- package/core/http/Binding/ParameterBinder.ts +109 -0
- package/core/http/Binding/RequestModel.ts +27 -0
- package/core/http/Binding/autoBindings.ts +125 -0
- package/core/http/Binding/bindings.ts +19 -0
- package/core/http/Binding/convert.ts +48 -0
- package/core/http/Binding/generatedSpec.ts +18 -0
- package/core/http/Binding/listModelRegistry.ts +47 -0
- package/core/http/Binding/modelBinder.ts +345 -0
- package/core/http/Binding/modelValidator.ts +30 -0
- package/core/http/Binding/requestModelRegistry.ts +117 -0
- package/core/http/Decorators/attributes.ts +92 -0
- package/core/http/Decorators/controller.ts +24 -0
- package/core/http/Decorators/metadata.ts +107 -0
- package/core/http/Decorators/routes.ts +131 -0
- package/core/http/Errors/HttpError.ts +92 -0
- package/core/http/HttpContext/HttpContext.ts +148 -0
- package/core/http/HttpContext/ResponseBuilder.ts +37 -0
- package/core/http/HttpContext/inspectableRedirects.ts +47 -0
- package/core/http/HttpContext/principal.ts +24 -0
- package/core/http/HttpContext/responseLifetime.ts +45 -0
- package/core/http/HttpServer.ts +627 -0
- package/core/http/Middleware/accessLog.ts +90 -0
- package/core/http/Middleware/cors.ts +160 -0
- package/core/http/Middleware/errorHandler.ts +100 -0
- package/core/http/Middleware/pipeline.ts +21 -0
- package/core/http/Middleware/rateLimit.ts +104 -0
- package/core/http/Middleware/securityHeaders.ts +118 -0
- package/core/http/Middleware/types.ts +19 -0
- package/core/http/OpenApi/generatedOpenApiRegistry.ts +102 -0
- package/core/http/OpenApi/openApiDocs.ts +75 -0
- package/core/http/OpenApi/openApiDocument.ts +356 -0
- package/core/http/README.md +139 -0
- package/core/http/Results/HttpResult.ts +19 -0
- package/core/http/Results/normalize.ts +93 -0
- package/core/http/Results/results.ts +70 -0
- package/core/http/Routing/Router.ts +201 -0
- package/core/http/Routing/RouterBuilder.ts +184 -0
- package/core/http/Routing/template.ts +112 -0
- package/core/http/SPEC.md +981 -0
- package/core/http/Versioning/VersionReader.ts +20 -0
- package/core/http/WebSocketUpgrade.ts +29 -0
- package/core/http/composeRouteMiddlewareComposers.ts +21 -0
- package/core/http/correlation/createCorrelationIdMiddleware.ts +79 -0
- package/core/http/httpModule.ts +48 -0
- package/core/http/index.ts +140 -0
- package/core/http/middlewareTokens.ts +48 -0
- package/core/http/options.ts +134 -0
- package/core/http-client/index.ts +105 -0
- package/core/infra/Infra.ts +158 -0
- package/core/infra/InfraConnector.ts +86 -0
- package/core/infra/InfraLifecycle.ts +86 -0
- package/core/infra/cache/RedisDistributedCacheBackend.ts +88 -0
- package/core/infra/cache/RedisDistributedCacheDriver.ts +186 -0
- package/core/infra/cache/index.ts +7 -0
- package/core/infra/connectorConfig.ts +29 -0
- package/core/infra/connectorIdentity.ts +39 -0
- package/core/infra/connectors/codex/CodexAppServer.ts +146 -0
- package/core/infra/connectors/codex/CodexAppServerClient.ts +258 -0
- package/core/infra/connectors/codex/CodexPolicy.ts +114 -0
- package/core/infra/connectors/codex/CodexTurn.ts +133 -0
- package/core/infra/connectors/codex/contracts.ts +82 -0
- package/core/infra/connectors/codex.ts +26 -0
- package/core/infra/connectors/llm.ts +78 -0
- package/core/infra/connectors/llmRouter.ts +443 -0
- package/core/infra/connectors/openaiCompatible.ts +590 -0
- package/core/infra/connectors/openaiTextStream.ts +134 -0
- package/core/infra/connectors/opensearch.ts +307 -0
- package/core/infra/connectors/postgres.ts +105 -0
- package/core/infra/connectors/redis.ts +132 -0
- package/core/infra/index.ts +58 -0
- package/core/kernel/ApplicationLifetime.ts +91 -0
- package/core/kernel/Bazis.ts +73 -0
- package/core/kernel/Environment.ts +53 -0
- package/core/kernel/Kernel.ts +391 -0
- package/core/kernel/KernelBuilder.ts +172 -0
- package/core/kernel/LifecycleCoordinator.ts +204 -0
- package/core/kernel/README.md +66 -0
- package/core/kernel/SupervisedHostedService.ts +147 -0
- package/core/kernel/config/ConfigRegistry.ts +48 -0
- package/core/kernel/config/Configuration.ts +110 -0
- package/core/kernel/config/README.md +62 -0
- package/core/kernel/config/Secret.ts +29 -0
- package/core/kernel/config/addConfigOptions.ts +63 -0
- package/core/kernel/config/defineConfig.ts +211 -0
- package/core/kernel/config/sources.ts +123 -0
- package/core/kernel/correlation/requestContext.ts +57 -0
- package/core/kernel/errors/ConfigKeyMissingError.ts +7 -0
- package/core/kernel/errors/KernelError.ts +7 -0
- package/core/kernel/errors/ShutdownTimeoutError.ts +7 -0
- package/core/kernel/errors/StartupAbortedError.ts +7 -0
- package/core/kernel/errors/StartupTimeoutError.ts +7 -0
- package/core/kernel/errors/index.ts +5 -0
- package/core/kernel/events/EventBus.ts +140 -0
- package/core/kernel/events/EventToken.ts +17 -0
- package/core/kernel/events/eventSubscribers.ts +126 -0
- package/core/kernel/events/kernelEvents.ts +16 -0
- package/core/kernel/events/onEvent.ts +32 -0
- package/core/kernel/health/HealthCheckContracts.ts +42 -0
- package/core/kernel/health/HealthService.ts +93 -0
- package/core/kernel/index.ts +96 -0
- package/core/kernel/internal/awaitAbortable.ts +18 -0
- package/core/kernel/internal/awaitShutdown.ts +21 -0
- package/core/kernel/internal/reportDiagnosticFailure.ts +8 -0
- package/core/kernel/internal/validateTimeout.ts +8 -0
- package/core/kernel/lifecycleHooks.ts +18 -0
- package/core/kernel/logging/ConsoleLogger.ts +68 -0
- package/core/kernel/logging/Logger.ts +22 -0
- package/core/kernel/types/ConfigSource.ts +9 -0
- package/core/kernel/types/EnvironmentName.ts +1 -0
- package/core/kernel/types/KernelOptions.ts +23 -0
- package/core/kernel/types/LifecycleHook.ts +18 -0
- package/core/kernel/types/index.ts +4 -0
- package/core/orm/DATABASE_PROVIDER.ts +5 -0
- package/core/orm/OrmHostedPlan.validator.ts +55 -0
- package/core/orm/OrmLifecycle.ts +146 -0
- package/core/orm/OrmOwnedStoreLifecycle.ts +96 -0
- package/core/orm/buildOrmProviders.ts +152 -0
- package/core/orm/databaseConnector.ts +108 -0
- package/core/orm/encapsulationHook.ts +19 -0
- package/core/orm/index.ts +95 -0
- package/core/orm/listQuery.ts +198 -0
- package/core/orm/ormModule.ts +173 -0
- package/core/orm/ownedStoreContributions.ts +195 -0
- package/core/orm/registerRepositories.ts +27 -0
- package/core/orm/repository.ts +45 -0
- package/core/orm/strictSchemaHostedIdentity.ts +17 -0
- package/core/scripts/agent-codegen.ts +1166 -0
- package/core/scripts/di-generate-target.ts +90 -0
- package/core/scripts/di-generate.ts +1837 -0
- package/core/scripts/orm-predicate-codegen.ts +33 -0
- package/core/scripts/request-model-codegen.ts +326 -0
- package/core/websocket/DESIGN.md +297 -0
- package/core/websocket/WsRateLimiter.ts +101 -0
- package/core/websocket/adapter/adapter.interface.ts +45 -0
- package/core/websocket/adapter/in-memory.adapter.ts +190 -0
- package/core/websocket/adapter/redis-delivery-scripts.ts +135 -0
- package/core/websocket/adapter/redis-delivery-store.ts +86 -0
- package/core/websocket/adapter/redis-operations.ts +33 -0
- package/core/websocket/adapter/redis.adapter.ts +218 -0
- package/core/websocket/codec/binary.codec.ts +87 -0
- package/core/websocket/codec/json.codec.ts +34 -0
- package/core/websocket/codec/packet-codec.interface.ts +17 -0
- package/core/websocket/decorators.ts +165 -0
- package/core/websocket/explorer.ts +126 -0
- package/core/websocket/index.ts +78 -0
- package/core/websocket/middleware.ts +146 -0
- package/core/websocket/packet-codec.ts +75 -0
- package/core/websocket/reliable-delivery.ts +56 -0
- package/core/websocket/session-creation.ts +16 -0
- package/core/websocket/session-manager.ts +856 -0
- package/core/websocket/socket-wrapper.ts +314 -0
- package/core/websocket/topic-cache.ts +59 -0
- package/core/websocket/types.ts +122 -0
- package/core/websocket/websocketModule.ts +96 -0
- package/core/websocket/ws-dispatch.ts +123 -0
- package/core/websocket/ws-server.ts +1707 -0
- package/index.ts +281 -0
- package/library/boundary/diagnostics-v1.ts +136 -0
- package/library/boundary/index.ts +73 -0
- package/library/boundary/json/decodeBoundedJsonV1.ts +518 -0
- package/library/boundary/json/limits-v1.ts +46 -0
- package/library/boundary/json/normalizeBoundedJsonV1.ts +256 -0
- package/library/boundary/json/types-v1.ts +11 -0
- package/library/boundary/schema/boundarySchemaHashV1.ts +6 -0
- package/library/boundary/schema/collectBoundaryValueDiagnosticsV1.ts +325 -0
- package/library/boundary/schema/decodeBoundarySchemaV1.ts +646 -0
- package/library/boundary/schema/index.ts +8 -0
- package/library/boundary/schema/types-v1.ts +99 -0
- package/library/boundary/schema/validateBoundaryValueV1.ts +58 -0
- package/library/boundary/serialization/canonicalJsonV1.ts +66 -0
- package/library/http-client/HttpClient.ts +969 -0
- package/library/http-client/HttpClientFactory.ts +45 -0
- package/library/http-client/errors.ts +68 -0
- package/library/http-client/index.ts +43 -0
- package/library/http-client/interceptors.ts +40 -0
- package/library/http-client/progress.ts +62 -0
- package/library/http-client/redirectProtocol.ts +6 -0
- package/library/http-client/serialize.ts +133 -0
- package/library/http-client/types.ts +174 -0
- package/library/jsonapi/ListQueryError.ts +25 -0
- package/library/jsonapi/ListRequest.ts +37 -0
- package/library/jsonapi/decorators.ts +161 -0
- package/library/jsonapi/document.ts +124 -0
- package/library/jsonapi/index.ts +40 -0
- package/library/jsonapi/parseListQuery.ts +291 -0
- package/library/jsonapi/types.ts +125 -0
- package/library/jwt/JwtEncoder.ts +40 -0
- package/library/jwt/JwtKeyRing.ts +164 -0
- package/library/jwt/JwtValidator.ts +210 -0
- package/library/jwt/TokenIssuer.ts +149 -0
- package/library/jwt/TokenService.ts +51 -0
- package/library/jwt/base64url.ts +61 -0
- package/library/jwt/claims.ts +36 -0
- package/library/jwt/errors.ts +44 -0
- package/library/jwt/index.ts +59 -0
- package/library/jwt/limits.ts +8 -0
- package/library/jwt/signing/Hs256Algorithm.ts +62 -0
- package/library/jwt/signing/Rs256Algorithm.ts +133 -0
- package/library/jwt/signing/SigningAlgorithm.ts +18 -0
- package/library/jwt/signing/pem.ts +30 -0
- package/library/openapi/codegen.ts +875 -0
- package/library/openapi/document.ts +326 -0
- package/library/openapi/index.ts +13 -0
- package/library/openapi/types.ts +69 -0
- package/library/openapi/ui.ts +182 -0
- package/library/orm/DatabaseFacade.ts +209 -0
- package/library/orm/DbContext.ts +107 -0
- package/library/orm/DbContextFactory.ts +25 -0
- package/library/orm/DbContextOptions.ts +33 -0
- package/library/orm/Metadata/DynamicModelBuilder.ts +497 -0
- package/library/orm/Metadata/KeyTuple.ts +36 -0
- package/library/orm/Metadata/ModelBuilder.ts +299 -0
- package/library/orm/Metadata/OrmModel.ts +80 -0
- package/library/orm/Metadata/ValueConverter.ts +57 -0
- package/library/orm/Metadata/conventions.ts +54 -0
- package/library/orm/Metadata/decorators.ts +396 -0
- package/library/orm/Metadata/types.ts +140 -0
- package/library/orm/Providers/OwnedStoreCatalog.reader.ts +1802 -0
- package/library/orm/Providers/PostgresDialect.ts +234 -0
- package/library/orm/Providers/PostgresProvider.ts +1494 -0
- package/library/orm/Providers/PostgresSchema.decoder.ts +107 -0
- package/library/orm/Providers/limits.ts +29 -0
- package/library/orm/Providers/operationDeadline.ts +43 -0
- package/library/orm/Providers/ormOwnedStoreRuntime.ts +19 -0
- package/library/orm/Providers/ormTransactionRuntime.ts +117 -0
- package/library/orm/Providers/propertyConversion.ts +14 -0
- package/library/orm/Providers/resolvedForeignKey.ts +16 -0
- package/library/orm/Providers/transactionCallbacks.ts +45 -0
- package/library/orm/Providers/transactionOutcome.ts +82 -0
- package/library/orm/Providers/transactionScopes.ts +78 -0
- package/library/orm/Providers/types.ts +207 -0
- package/library/orm/Query/DbSet.ts +78 -0
- package/library/orm/Query/EntityQuery.ts +247 -0
- package/library/orm/Query/ImmediateMutations.ts +226 -0
- package/library/orm/Query/IncludeLoader.ts +200 -0
- package/library/orm/Query/QueryPlan.ts +55 -0
- package/library/orm/Query/SqlTranslator.ts +195 -0
- package/library/orm/Query/conditions.ts +127 -0
- package/library/orm/Query/materialize.ts +39 -0
- package/library/orm/README.md +256 -0
- package/library/orm/Repository/README.md +684 -0
- package/library/orm/Repository/Repository.ts +68 -0
- package/library/orm/Saving/CommandBuilder.ts +139 -0
- package/library/orm/Saving/ExecutionStrategy.ts +128 -0
- package/library/orm/Saving/SaveExecutor.ts +413 -0
- package/library/orm/Saving/applyConventions.ts +64 -0
- package/library/orm/Schema/CheckExpression.ts +327 -0
- package/library/orm/Schema/ExactSchemaVerifier.ts +168 -0
- package/library/orm/Schema/ExpectedSchema.ts +43 -0
- package/library/orm/Schema/MigrationRunner.ts +146 -0
- package/library/orm/Schema/Migrator.ts +73 -0
- package/library/orm/Schema/OrmOwnedStore.ts +123 -0
- package/library/orm/Schema/OwnedStoreAdmission.ts +752 -0
- package/library/orm/Schema/OwnedStoreCanonical.ts +273 -0
- package/library/orm/Schema/OwnedStoreCatalog.ts +1325 -0
- package/library/orm/Schema/SafeAdditiveSchema.ts +100 -0
- package/library/orm/Schema/SchemaAdmission.ts +62 -0
- package/library/orm/Schema/SchemaDiffer.ts +78 -0
- package/library/orm/Schema/formatSchemaDifferences.ts +62 -0
- package/library/orm/Schema/introspection.ts +52 -0
- package/library/orm/Schema/physicalColumnTypes.ts +37 -0
- package/library/orm/Schema/tableKey.ts +26 -0
- package/library/orm/Tracking/ChangeTracker.ts +448 -0
- package/library/orm/Tracking/EntityState.ts +13 -0
- package/library/orm/Transactions/OrmTransaction.ts +30 -0
- package/library/orm/Transactions/TransactionScopeCoordinator.ts +377 -0
- package/library/orm/errors.ts +190 -0
- package/library/orm/index.ts +162 -0
- package/library/orm/runtime.ts +14 -0
- package/library/redaction/index.ts +166 -0
- package/library/ui/UiProfile.ts +77 -0
- package/library/ui/compiled-v1.ts +131 -0
- package/library/ui/compiler/compileUiSurfaceV1.ts +717 -0
- package/library/ui/compiler/contracts-v1.ts +25 -0
- package/library/ui/compiler/index.ts +12 -0
- package/library/ui/compiler/openApiIndex.ts +246 -0
- package/library/ui/defineUiProfile.ts +340 -0
- package/library/ui/diagnostics-v1.ts +33 -0
- package/library/ui/index.ts +129 -0
- package/library/ui/profile-v1.ts +191 -0
- package/library/ui/serialization.ts +130 -0
- package/library/ui/uiProfileAuthoring.ts +289 -0
- package/library/ui/uiProfileAuthoringMetadata.ts +78 -0
- package/library/validation/MessageRegistry.ts +144 -0
- package/library/validation/README.md +62 -0
- package/library/validation/RuleCompiler.ts +183 -0
- package/library/validation/RuleEngine.ts +401 -0
- package/library/validation/SPEC.md +579 -0
- package/library/validation/ValidationError.ts +37 -0
- package/library/validation/ValidationResult.ts +63 -0
- package/library/validation/Validator.ts +101 -0
- package/library/validation/index.ts +16 -0
- package/library/validation/metadata.ts +69 -0
- package/library/validation/modelValidatorAdapter.ts +119 -0
- package/library/validation/types/ValidationCode.ts +69 -0
- package/library/validation/types/ValidatorOptions.ts +153 -0
- package/package.json +80 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { UiLabels } from "./uiProfileResolver";
|
|
2
|
+
import type { AuthorizeCheck, HttpContext } from "../../http";
|
|
3
|
+
import type {
|
|
4
|
+
UiSurfacePolicyDecision,
|
|
5
|
+
UiSurfacePolicyInput,
|
|
6
|
+
UiSurfaceSessionUser,
|
|
7
|
+
} from "./uiSurfaceHttp";
|
|
8
|
+
|
|
9
|
+
export interface RunAppUiAppInfo {
|
|
10
|
+
readonly name?: string;
|
|
11
|
+
readonly version?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** One explicitly published and protected UI surface. */
|
|
15
|
+
export interface RunAppUiSurfaceOptions {
|
|
16
|
+
readonly surface: string;
|
|
17
|
+
readonly authorize: AuthorizeCheck;
|
|
18
|
+
readonly policy: (
|
|
19
|
+
ctx: HttpContext,
|
|
20
|
+
input: UiSurfacePolicyInput,
|
|
21
|
+
) => UiSurfacePolicyDecision | Promise<UiSurfacePolicyDecision>;
|
|
22
|
+
readonly session: (ctx: HttpContext) => UiSurfaceSessionUser | Promise<UiSurfaceSessionUser>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Declarative UI hosting options accepted by `runApp`. */
|
|
26
|
+
export interface RunAppUiOptions {
|
|
27
|
+
readonly app?: RunAppUiAppInfo;
|
|
28
|
+
readonly surfaces: readonly RunAppUiSurfaceOptions[];
|
|
29
|
+
/** Texts of generated profiles; default English, `RU_UI_LABELS` for Russian. */
|
|
30
|
+
readonly labels?: UiLabels;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Fully normalized options used by the UI surface HTTP runtime. */
|
|
34
|
+
export interface UiSurfaceHostingOptions {
|
|
35
|
+
readonly app: Required<RunAppUiAppInfo>;
|
|
36
|
+
readonly apiBasePath: string;
|
|
37
|
+
readonly surfaces: readonly RunAppUiSurfaceOptions[];
|
|
38
|
+
}
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Controller,
|
|
3
|
+
ForbiddenError,
|
|
4
|
+
Get,
|
|
5
|
+
HttpContext,
|
|
6
|
+
NotFoundError,
|
|
7
|
+
} from "../../http";
|
|
8
|
+
import {
|
|
9
|
+
normalizeUiJsonObject,
|
|
10
|
+
uiDocumentRevision,
|
|
11
|
+
type CompiledUiResourceOperationsV1,
|
|
12
|
+
type CompiledUiResourceV1,
|
|
13
|
+
type CompiledUiCustomPageV1,
|
|
14
|
+
type CompiledUiSurfaceV1,
|
|
15
|
+
} from "../../../library/ui";
|
|
16
|
+
import { projectOpenApiByOperationIds, type OpenApiSchema } from "../../../library/openapi";
|
|
17
|
+
import type {
|
|
18
|
+
RunAppUiSurfaceOptions,
|
|
19
|
+
UiSurfaceHostingOptions,
|
|
20
|
+
} from "./uiSurfaceHosting";
|
|
21
|
+
import { UiProfileV1Registry } from "./uiProfileResolver";
|
|
22
|
+
|
|
23
|
+
export const UI_SURFACE_SESSION_V1_API_VERSION = "ui.bazis.dev/v1" as const;
|
|
24
|
+
export const UI_SURFACE_SESSION_V1_KIND = "UiSurfaceSession" as const;
|
|
25
|
+
|
|
26
|
+
export type UiSurfaceOperationRole = keyof CompiledUiResourceOperationsV1;
|
|
27
|
+
|
|
28
|
+
export interface UiSurfacePolicyResourceInput {
|
|
29
|
+
readonly id: string;
|
|
30
|
+
readonly operations: readonly UiSurfaceOperationRole[];
|
|
31
|
+
readonly actions: readonly string[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface UiSurfacePolicyInput {
|
|
35
|
+
readonly surface: string;
|
|
36
|
+
readonly resources: readonly UiSurfacePolicyResourceInput[];
|
|
37
|
+
readonly pages: readonly UiSurfacePolicyPageInput[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface UiSurfacePolicyPageInput {
|
|
41
|
+
readonly id: string;
|
|
42
|
+
readonly operations: readonly string[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface UiSurfaceResourceDecision {
|
|
46
|
+
readonly resource: string;
|
|
47
|
+
readonly visible: boolean;
|
|
48
|
+
/** Missing/false operation entries are denied. */
|
|
49
|
+
readonly operations?: Readonly<Partial<Record<UiSurfaceOperationRole, boolean>>>;
|
|
50
|
+
/** Explicit action id allow-list. Missing actions are denied. */
|
|
51
|
+
readonly actions?: readonly string[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface UiSurfacePolicyDecision {
|
|
55
|
+
readonly resources: readonly UiSurfaceResourceDecision[];
|
|
56
|
+
/** Missing page decisions are denied. */
|
|
57
|
+
readonly pages?: readonly UiSurfacePageDecision[];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface UiSurfacePageDecision {
|
|
61
|
+
readonly page: string;
|
|
62
|
+
readonly visible: boolean;
|
|
63
|
+
/** Semantic slot allow-list (`read`, `update`, `load`, `blocks.<id>`). */
|
|
64
|
+
readonly operations?: Readonly<Record<string, boolean>>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface UiSurfaceSessionUser {
|
|
68
|
+
readonly id: string;
|
|
69
|
+
readonly kind: string;
|
|
70
|
+
readonly displayName: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface UiSurfaceSessionV1 {
|
|
74
|
+
readonly apiVersion: typeof UI_SURFACE_SESSION_V1_API_VERSION;
|
|
75
|
+
readonly kind: typeof UI_SURFACE_SESSION_V1_KIND;
|
|
76
|
+
readonly metadata: {
|
|
77
|
+
readonly surface: string;
|
|
78
|
+
readonly revision: string;
|
|
79
|
+
};
|
|
80
|
+
readonly app: UiSurfaceHostingOptions["app"];
|
|
81
|
+
readonly currentUser: UiSurfaceSessionUser;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
interface EffectiveSurface {
|
|
85
|
+
readonly options: RunAppUiSurfaceOptions;
|
|
86
|
+
readonly document: CompiledUiSurfaceV1;
|
|
87
|
+
readonly openApi: OpenApiSchema;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface StaticSurface {
|
|
91
|
+
readonly document: CompiledUiSurfaceV1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Compiles declarative profiles once, then applies request policy monotonically. */
|
|
95
|
+
export class UiSurfaceDocumentProvider {
|
|
96
|
+
readonly #surfaces = new Map<string, StaticSurface>();
|
|
97
|
+
|
|
98
|
+
public constructor(
|
|
99
|
+
private readonly options: UiSurfaceHostingOptions,
|
|
100
|
+
profiles: UiProfileV1Registry,
|
|
101
|
+
private readonly openApiDocument: OpenApiSchema,
|
|
102
|
+
) {
|
|
103
|
+
const seen = new Set<string>();
|
|
104
|
+
for (const surface of options.surfaces) {
|
|
105
|
+
validateSurfaceRegistration(surface, seen);
|
|
106
|
+
const path = uiSurfacePath(options.apiBasePath, surface.surface);
|
|
107
|
+
const links = Object.freeze({
|
|
108
|
+
openapi: `${path}/openapi`,
|
|
109
|
+
session: `${path}/session`,
|
|
110
|
+
});
|
|
111
|
+
const compiled = profiles.compile(surface.surface, links, openApiDocument);
|
|
112
|
+
this.#surfaces.set(surface.surface, Object.freeze({ document: compiled }));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public async effective(ctx: HttpContext): Promise<CompiledUiSurfaceV1> {
|
|
117
|
+
return (await this.resolveEffective(ctx)).document;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public async openApi(ctx: HttpContext): Promise<OpenApiSchema> {
|
|
121
|
+
const effective = await this.resolveEffective(ctx);
|
|
122
|
+
return projectOpenApiByOperationIds(effective.openApi, operationIdsOf(effective.document));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
public async session(ctx: HttpContext): Promise<UiSurfaceSessionV1> {
|
|
126
|
+
const effective = await this.resolveEffective(ctx);
|
|
127
|
+
const user = safeSessionUser(await effective.options.session(ctx));
|
|
128
|
+
return Object.freeze({
|
|
129
|
+
apiVersion: UI_SURFACE_SESSION_V1_API_VERSION,
|
|
130
|
+
kind: UI_SURFACE_SESSION_V1_KIND,
|
|
131
|
+
metadata: {
|
|
132
|
+
surface: effective.document.metadata.surface,
|
|
133
|
+
revision: effective.document.metadata.revision,
|
|
134
|
+
},
|
|
135
|
+
app: this.options.app,
|
|
136
|
+
currentUser: user,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private async resolveEffective(ctx: HttpContext): Promise<EffectiveSurface> {
|
|
141
|
+
const surface = String(ctx.params["surface"] ?? "").trim();
|
|
142
|
+
const registration = this.options.surfaces.find((item) => item.surface === surface);
|
|
143
|
+
const staticSurface = this.#surfaces.get(surface);
|
|
144
|
+
// Surface enumeration is deliberately checked before invoking auth.
|
|
145
|
+
if (surface.length === 0 || registration === undefined || staticSurface === undefined) {
|
|
146
|
+
throw new NotFoundError("UI surface not found");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (!await registration.authorize(ctx)) {
|
|
150
|
+
throw new ForbiddenError();
|
|
151
|
+
}
|
|
152
|
+
const decision = await registration.policy(ctx, policyInputOf(staticSurface.document));
|
|
153
|
+
return {
|
|
154
|
+
options: registration,
|
|
155
|
+
document: effectiveDocument(staticSurface.document, decision),
|
|
156
|
+
openApi: this.openApiDocument,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@Controller("ui")
|
|
162
|
+
export class UiSurfaceHttpController {
|
|
163
|
+
public constructor(private readonly documents: UiSurfaceDocumentProvider) {}
|
|
164
|
+
|
|
165
|
+
@Get(":surface/openapi")
|
|
166
|
+
async openapi(ctx: HttpContext): Promise<Response> {
|
|
167
|
+
const document = await this.documents.openApi(ctx);
|
|
168
|
+
return versionedJson(ctx, document, uiDocumentRevision(document));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@Get(":surface/session")
|
|
172
|
+
async session(ctx: HttpContext): Promise<Response> {
|
|
173
|
+
const document = await this.documents.session(ctx);
|
|
174
|
+
return jsonResponse(document, {
|
|
175
|
+
"cache-control": "private, no-store",
|
|
176
|
+
vary: "Authorization",
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@Get(":surface")
|
|
181
|
+
async surface(ctx: HttpContext): Promise<Response> {
|
|
182
|
+
const document = await this.documents.effective(ctx);
|
|
183
|
+
return versionedJson(ctx, document, document.metadata.revision);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function validateSurfaceRegistration(
|
|
188
|
+
options: RunAppUiSurfaceOptions,
|
|
189
|
+
seen: Set<string>,
|
|
190
|
+
): void {
|
|
191
|
+
const surface = options.surface.trim();
|
|
192
|
+
if (surface.length === 0) {
|
|
193
|
+
throw new TypeError("UI surface name must be a non-empty string.");
|
|
194
|
+
}
|
|
195
|
+
if (seen.has(surface)) {
|
|
196
|
+
throw new TypeError(`UI surface ${surface} is registered more than once.`);
|
|
197
|
+
}
|
|
198
|
+
seen.add(surface);
|
|
199
|
+
if (typeof options.authorize !== "function") {
|
|
200
|
+
throw new TypeError(`UI surface ${surface} must declare authorize.`);
|
|
201
|
+
}
|
|
202
|
+
if (typeof options.policy !== "function") {
|
|
203
|
+
throw new TypeError(`UI surface ${surface} must declare a policy projector.`);
|
|
204
|
+
}
|
|
205
|
+
if (typeof options.session !== "function") {
|
|
206
|
+
throw new TypeError(`UI surface ${surface} must declare a safe session mapper.`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function policyInputOf(document: CompiledUiSurfaceV1): UiSurfacePolicyInput {
|
|
211
|
+
return Object.freeze({
|
|
212
|
+
surface: document.metadata.surface,
|
|
213
|
+
resources: Object.freeze(document.spec.resources.map((resource) => Object.freeze({
|
|
214
|
+
id: resource.id,
|
|
215
|
+
operations: Object.freeze(Object.keys(resource.operations) as UiSurfaceOperationRole[]),
|
|
216
|
+
actions: Object.freeze(resource.actions.map((action) => action.id)),
|
|
217
|
+
}))),
|
|
218
|
+
pages: Object.freeze((document.spec.customPages ?? []).map((page) => Object.freeze({
|
|
219
|
+
id: page.id,
|
|
220
|
+
operations: Object.freeze(pageOperationSlots(page)),
|
|
221
|
+
}))),
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function effectiveDocument(
|
|
226
|
+
source: CompiledUiSurfaceV1,
|
|
227
|
+
policy: UiSurfacePolicyDecision,
|
|
228
|
+
): CompiledUiSurfaceV1 {
|
|
229
|
+
if (typeof policy !== "object" || policy === null || !Array.isArray(policy.resources)) {
|
|
230
|
+
throw new TypeError(`UI surface ${source.metadata.surface} policy returned an invalid decision.`);
|
|
231
|
+
}
|
|
232
|
+
const decisions = new Map<string, UiSurfaceResourceDecision>();
|
|
233
|
+
for (const decision of policy.resources) {
|
|
234
|
+
if (decisions.has(decision.resource)) {
|
|
235
|
+
throw new TypeError(`UI policy returned duplicate resource decision ${decision.resource}.`);
|
|
236
|
+
}
|
|
237
|
+
decisions.set(decision.resource, decision);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const resources = source.spec.resources.flatMap((resource) => {
|
|
241
|
+
const decision = decisions.get(resource.id);
|
|
242
|
+
return decision?.visible === true ? [projectResource(resource, decision)] : [];
|
|
243
|
+
});
|
|
244
|
+
const pageDecisions = new Map<string, UiSurfacePageDecision>();
|
|
245
|
+
for (const decision of policy.pages ?? []) {
|
|
246
|
+
if (pageDecisions.has(decision.page)) {
|
|
247
|
+
throw new TypeError(`UI policy returned duplicate page decision ${decision.page}.`);
|
|
248
|
+
}
|
|
249
|
+
pageDecisions.set(decision.page, decision);
|
|
250
|
+
}
|
|
251
|
+
const customPages = (source.spec.customPages ?? []).flatMap((page) => {
|
|
252
|
+
const decision = pageDecisions.get(page.id);
|
|
253
|
+
if (decision?.visible !== true) {
|
|
254
|
+
return [];
|
|
255
|
+
}
|
|
256
|
+
const projected = projectCustomPage(page, decision);
|
|
257
|
+
return projected === undefined ? [] : [projected];
|
|
258
|
+
});
|
|
259
|
+
const resourceIds = new Set(resources.map((resource) => resource.id));
|
|
260
|
+
const pageIds = new Set(customPages.map((page) => page.id));
|
|
261
|
+
const navigation = source.spec.navigation.filter((item) =>
|
|
262
|
+
(item.resource === undefined || resourceIds.has(item.resource))
|
|
263
|
+
&& (item.page === undefined || pageIds.has(item.page)));
|
|
264
|
+
const semanticDocument = {
|
|
265
|
+
apiVersion: source.apiVersion,
|
|
266
|
+
kind: source.kind,
|
|
267
|
+
metadata: { surface: source.metadata.surface },
|
|
268
|
+
links: source.links,
|
|
269
|
+
spec: {
|
|
270
|
+
navigation,
|
|
271
|
+
resources,
|
|
272
|
+
...(customPages.length > 0 ? { customPages } : {}),
|
|
273
|
+
requiredRendererCapabilities: projectedRendererCapabilities(source, customPages),
|
|
274
|
+
...(source.spec.extensions !== undefined ? { extensions: source.spec.extensions } : {}),
|
|
275
|
+
},
|
|
276
|
+
...(source.diagnostics !== undefined ? { diagnostics: source.diagnostics } : {}),
|
|
277
|
+
};
|
|
278
|
+
const revision = uiDocumentRevision({
|
|
279
|
+
document: semanticDocument,
|
|
280
|
+
sourceRevision: source.metadata.revision,
|
|
281
|
+
});
|
|
282
|
+
return normalizeUiJsonObject({
|
|
283
|
+
...semanticDocument,
|
|
284
|
+
metadata: { surface: source.metadata.surface, revision },
|
|
285
|
+
}, "effectiveUiSurface") as unknown as CompiledUiSurfaceV1;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function pageOperationSlots(page: CompiledUiCustomPageV1): string[] {
|
|
289
|
+
switch (page.kind) {
|
|
290
|
+
case "feature": return [];
|
|
291
|
+
case "settings": return ["read", ...(page.operations.update === undefined ? [] : ["update"])];
|
|
292
|
+
case "document": return ["load"];
|
|
293
|
+
case "dashboard": return page.blocks.map((block) => `blocks.${block.id}`);
|
|
294
|
+
default: return assertNeverCompiledCustomPage(page);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function projectCustomPage(
|
|
299
|
+
page: CompiledUiCustomPageV1,
|
|
300
|
+
decision: UiSurfacePageDecision,
|
|
301
|
+
): CompiledUiCustomPageV1 | undefined {
|
|
302
|
+
switch (page.kind) {
|
|
303
|
+
case "feature":
|
|
304
|
+
return page;
|
|
305
|
+
case "settings":
|
|
306
|
+
if (decision.operations?.["read"] !== true) {
|
|
307
|
+
return undefined;
|
|
308
|
+
}
|
|
309
|
+
const canUpdate = page.operations.update !== undefined && decision.operations?.["update"] === true;
|
|
310
|
+
return Object.freeze({
|
|
311
|
+
id: page.id,
|
|
312
|
+
title: page.title,
|
|
313
|
+
route: page.route,
|
|
314
|
+
kind: page.kind,
|
|
315
|
+
operations: {
|
|
316
|
+
read: page.operations.read,
|
|
317
|
+
...(canUpdate ? { update: page.operations.update } : {}),
|
|
318
|
+
},
|
|
319
|
+
...(canUpdate && page.form !== undefined ? { form: page.form } : {}),
|
|
320
|
+
});
|
|
321
|
+
case "document":
|
|
322
|
+
return decision.operations?.["load"] === true ? page : undefined;
|
|
323
|
+
case "dashboard": {
|
|
324
|
+
const blocks = page.blocks.filter((block) => decision.operations?.[`blocks.${block.id}`] === true);
|
|
325
|
+
return blocks.length === 0 ? undefined : Object.freeze({ ...page, blocks: Object.freeze(blocks) });
|
|
326
|
+
}
|
|
327
|
+
default:
|
|
328
|
+
return assertNeverCompiledCustomPage(page);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function projectedRendererCapabilities(
|
|
333
|
+
source: CompiledUiSurfaceV1,
|
|
334
|
+
visiblePages: readonly CompiledUiCustomPageV1[],
|
|
335
|
+
): readonly string[] {
|
|
336
|
+
// The wire contract does not retain provenance for arbitrary explicit/field
|
|
337
|
+
// capabilities, so keep them intact. Feature renderer ids are compiler-owned
|
|
338
|
+
// capabilities and can be projected exactly from source versus visible pages.
|
|
339
|
+
const sourceFeatureRenderers = new Set(
|
|
340
|
+
(source.spec.customPages ?? [])
|
|
341
|
+
.filter((page) => page.kind === "feature")
|
|
342
|
+
.map((page) => page.renderer),
|
|
343
|
+
);
|
|
344
|
+
const capabilities = new Set(
|
|
345
|
+
source.spec.requiredRendererCapabilities.filter((capability) =>
|
|
346
|
+
!sourceFeatureRenderers.has(capability)),
|
|
347
|
+
);
|
|
348
|
+
for (const page of visiblePages) {
|
|
349
|
+
if (page.kind === "feature") {
|
|
350
|
+
capabilities.add(page.renderer);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return [...capabilities].sort();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function assertNeverCompiledCustomPage(value: never): never {
|
|
357
|
+
throw new TypeError(`Unsupported compiled UI custom page: ${String(value)}`);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function projectResource(
|
|
361
|
+
source: CompiledUiResourceV1,
|
|
362
|
+
decision: UiSurfaceResourceDecision,
|
|
363
|
+
): CompiledUiResourceV1 {
|
|
364
|
+
const operations = Object.fromEntries(
|
|
365
|
+
Object.entries(source.operations).filter(([role]) => decision.operations?.[role as UiSurfaceOperationRole] === true),
|
|
366
|
+
) as CompiledUiResourceOperationsV1;
|
|
367
|
+
const allowedActions = new Set(decision.actions ?? []);
|
|
368
|
+
const actions = source.actions.filter((action) => allowedActions.has(action.id));
|
|
369
|
+
return Object.freeze({
|
|
370
|
+
id: source.id,
|
|
371
|
+
title: source.title,
|
|
372
|
+
...(source.singularTitle !== undefined ? { singularTitle: source.singularTitle } : {}),
|
|
373
|
+
...(source.keyField !== undefined ? { keyField: source.keyField } : {}),
|
|
374
|
+
route: source.route,
|
|
375
|
+
operations,
|
|
376
|
+
...(operations.list !== undefined && source.list !== undefined ? { list: source.list } : {}),
|
|
377
|
+
...(operations.read !== undefined && source.detail !== undefined ? { detail: source.detail } : {}),
|
|
378
|
+
...(source.forms !== undefined && (operations.create !== undefined || operations.update !== undefined)
|
|
379
|
+
? {
|
|
380
|
+
forms: {
|
|
381
|
+
...(operations.create !== undefined && source.forms.create !== undefined
|
|
382
|
+
? { create: source.forms.create }
|
|
383
|
+
: {}),
|
|
384
|
+
...(operations.update !== undefined && source.forms.edit !== undefined
|
|
385
|
+
? { edit: source.forms.edit }
|
|
386
|
+
: {}),
|
|
387
|
+
},
|
|
388
|
+
}
|
|
389
|
+
: {}),
|
|
390
|
+
actions,
|
|
391
|
+
...(source.extensions !== undefined ? { extensions: source.extensions } : {}),
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function operationIdsOf(document: CompiledUiSurfaceV1): Set<string> {
|
|
396
|
+
const operationIds = new Set<string>();
|
|
397
|
+
for (const resource of document.spec.resources) {
|
|
398
|
+
for (const operation of Object.values(resource.operations)) {
|
|
399
|
+
if (operation !== undefined) {
|
|
400
|
+
operationIds.add(operation.operationId);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
for (const action of resource.actions) {
|
|
404
|
+
operationIds.add(action.operation.operationId);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
for (const page of document.spec.customPages ?? []) {
|
|
408
|
+
switch (page.kind) {
|
|
409
|
+
case "feature":
|
|
410
|
+
break;
|
|
411
|
+
case "settings":
|
|
412
|
+
operationIds.add(page.operations.read.operationId);
|
|
413
|
+
if (page.operations.update !== undefined) {
|
|
414
|
+
operationIds.add(page.operations.update.operationId);
|
|
415
|
+
}
|
|
416
|
+
break;
|
|
417
|
+
case "document":
|
|
418
|
+
operationIds.add(page.operation.operationId);
|
|
419
|
+
break;
|
|
420
|
+
case "dashboard":
|
|
421
|
+
for (const block of page.blocks) {
|
|
422
|
+
operationIds.add(block.operation.operationId);
|
|
423
|
+
}
|
|
424
|
+
break;
|
|
425
|
+
default:
|
|
426
|
+
assertNeverCompiledCustomPage(page);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return operationIds;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function safeSessionUser(value: UiSurfaceSessionUser): UiSurfaceSessionUser {
|
|
433
|
+
if (typeof value !== "object" || value === null) {
|
|
434
|
+
throw new TypeError("UI surface session mapper must return a user object.");
|
|
435
|
+
}
|
|
436
|
+
const id = requiredSessionText(value.id, "id");
|
|
437
|
+
const kind = requiredSessionText(value.kind, "kind");
|
|
438
|
+
const displayName = requiredSessionText(value.displayName, "displayName");
|
|
439
|
+
// Reconstructing the object prevents accidental claim/role leakage.
|
|
440
|
+
return Object.freeze({ id, kind, displayName });
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function requiredSessionText(value: unknown, field: string): string {
|
|
444
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
445
|
+
throw new TypeError(`UI surface session user ${field} must be a non-empty string.`);
|
|
446
|
+
}
|
|
447
|
+
return value;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function uiSurfacePath(apiBasePath: string, surface: string): string {
|
|
451
|
+
const base = apiBasePath === "/" ? "" : apiBasePath.replace(/\/+$/, "");
|
|
452
|
+
return `${base}/ui/${encodeURIComponent(surface)}`;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function versionedJson(ctx: HttpContext, document: unknown, revision: string): Response {
|
|
456
|
+
const etag = `"${revision}"`;
|
|
457
|
+
const headers = {
|
|
458
|
+
"cache-control": "private, no-cache",
|
|
459
|
+
etag,
|
|
460
|
+
vary: "Authorization",
|
|
461
|
+
};
|
|
462
|
+
if (ctx.header("if-none-match") === etag) {
|
|
463
|
+
return new Response(null, { status: 304, headers });
|
|
464
|
+
}
|
|
465
|
+
return jsonResponse(document, headers);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function jsonResponse(document: unknown, headers: Record<string, string>): Response {
|
|
469
|
+
return new Response(JSON.stringify(document), {
|
|
470
|
+
status: 200,
|
|
471
|
+
headers: {
|
|
472
|
+
"content-type": "application/json; charset=utf-8",
|
|
473
|
+
...headers,
|
|
474
|
+
},
|
|
475
|
+
});
|
|
476
|
+
}
|