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,18 @@
|
|
|
1
|
+
import type { Token } from "../token";
|
|
2
|
+
import type { ServiceKey } from "../types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A single constructor/factory dependency, normalized once per provider so the
|
|
6
|
+
* hot resolve path skips re-deriving the descriptor (named-token lookup, keyed
|
|
7
|
+
* unwrapping) and the per-dependency object allocation on every resolution.
|
|
8
|
+
*
|
|
9
|
+
* `undefined` entries mean "leave this positional argument unset" (a ctor param
|
|
10
|
+
* with a default value that should not be injected).
|
|
11
|
+
*/
|
|
12
|
+
export interface PlannedDependency {
|
|
13
|
+
readonly token: Token<unknown>;
|
|
14
|
+
readonly key: ServiceKey | undefined;
|
|
15
|
+
readonly lazy: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type ResolutionPlan = readonly (PlannedDependency | undefined)[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class ResolutionScopeState {
|
|
2
|
+
public readonly cache = new Map<number, unknown>();
|
|
3
|
+
// In-flight async creations: dedupes concurrent resolveAsync of the same registration.
|
|
4
|
+
public readonly pendingAsync = new Map<number, Promise<unknown>>();
|
|
5
|
+
// Active async activation wait edges, keyed by registration identity. They
|
|
6
|
+
// are scope-local because scoped registrations may be active independently
|
|
7
|
+
// in different scopes.
|
|
8
|
+
public readonly pendingWaits = new Map<number, Set<number>>();
|
|
9
|
+
public readonly pendingAsyncActivationIds = new Map<number, number>();
|
|
10
|
+
/** Active executions by concrete activation identity. */
|
|
11
|
+
public readonly activeActivationIds = new Set<number>();
|
|
12
|
+
// Every async resolution (including transients), so disposal cannot race a late-created resource.
|
|
13
|
+
public readonly pendingCreations = new Set<Promise<unknown>>();
|
|
14
|
+
public readonly disposables: unknown[] = [];
|
|
15
|
+
public disposed = false;
|
|
16
|
+
public disposalPromise?: Promise<void>;
|
|
17
|
+
|
|
18
|
+
public constructor(public readonly isRoot: boolean) {}
|
|
19
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { CircularDependencyError } from "../errors";
|
|
2
|
+
import type { ResolutionScopeState } from "./ResolutionScopeState";
|
|
3
|
+
import { ServiceRegistration } from "./ServiceRegistration";
|
|
4
|
+
|
|
5
|
+
export interface ResolutionActivation {
|
|
6
|
+
readonly id: number;
|
|
7
|
+
readonly registration: ServiceRegistration;
|
|
8
|
+
readonly scope: ResolutionScopeState;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Tracks active construction chains and scope-local async wait edges. */
|
|
12
|
+
export class ResolutionTracker {
|
|
13
|
+
private nextActivationId = 0;
|
|
14
|
+
private readonly activeActivations = new Map<number, ResolutionActivation>();
|
|
15
|
+
|
|
16
|
+
public assertNoCycle(
|
|
17
|
+
registration: ServiceRegistration,
|
|
18
|
+
scope: ResolutionScopeState,
|
|
19
|
+
stack: readonly ResolutionActivation[],
|
|
20
|
+
): void {
|
|
21
|
+
if (stack.some((entry) => entry.registration.id === registration.id && entry.scope === scope)) {
|
|
22
|
+
throw this.createCircularDependencyError([...stack, this.create(registration, scope)]);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public create(registration: ServiceRegistration, scope: ResolutionScopeState): ResolutionActivation {
|
|
27
|
+
return { id: this.nextActivationId++, registration, scope };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public enter(scopeState: ResolutionScopeState, activation: ResolutionActivation): void {
|
|
31
|
+
scopeState.activeActivationIds.add(activation.id);
|
|
32
|
+
this.activeActivations.set(activation.id, activation);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public leave(scopeState: ResolutionScopeState, activation: ResolutionActivation): void {
|
|
36
|
+
scopeState.activeActivationIds.delete(activation.id);
|
|
37
|
+
this.activeActivations.delete(activation.id);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public capture(resolutionStack: readonly ResolutionActivation[]): () => ResolutionActivation[] {
|
|
41
|
+
const captured = [...resolutionStack];
|
|
42
|
+
const owner = captured[captured.length - 1];
|
|
43
|
+
return () => {
|
|
44
|
+
// Retained resolvers and Lazy wrappers belong to their own activation.
|
|
45
|
+
// After it settles they must not inherit a still-running ancestor.
|
|
46
|
+
if (!owner || !owner.scope.activeActivationIds.has(owner.id)) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
return captured.filter((entry) => entry.scope.activeActivationIds.has(entry.id));
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public join<T>(
|
|
54
|
+
registration: ServiceRegistration<T>,
|
|
55
|
+
scopeState: ResolutionScopeState,
|
|
56
|
+
stack: readonly ResolutionActivation[],
|
|
57
|
+
pending: Promise<unknown>,
|
|
58
|
+
): Promise<T> {
|
|
59
|
+
const owner = stack[stack.length - 1];
|
|
60
|
+
if (!owner) {
|
|
61
|
+
return pending as Promise<T>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const activationId = scopeState.pendingAsyncActivationIds.get(registration.id);
|
|
65
|
+
if (activationId === undefined) {
|
|
66
|
+
return pending as Promise<T>;
|
|
67
|
+
}
|
|
68
|
+
const dependency = this.getActivationById(activationId);
|
|
69
|
+
this.addWait(scopeState, owner, dependency);
|
|
70
|
+
return (async () => {
|
|
71
|
+
try {
|
|
72
|
+
return await pending as T;
|
|
73
|
+
} finally {
|
|
74
|
+
this.removeWait(scopeState, owner, dependency);
|
|
75
|
+
}
|
|
76
|
+
})();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public addWait(
|
|
80
|
+
scopeState: ResolutionScopeState,
|
|
81
|
+
owner: ResolutionActivation,
|
|
82
|
+
dependency: ResolutionActivation,
|
|
83
|
+
): void {
|
|
84
|
+
let dependencies = scopeState.pendingWaits.get(owner.id);
|
|
85
|
+
if (dependencies?.has(dependency.id)) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const path = this.findPendingWaitPath(scopeState, dependency.id, owner.id, new Set<number>());
|
|
90
|
+
if (path) {
|
|
91
|
+
const registrations = [owner, ...path.map((id) => this.getActivationById(id)), dependency];
|
|
92
|
+
throw this.createCircularDependencyError(registrations);
|
|
93
|
+
}
|
|
94
|
+
if (!dependencies) {
|
|
95
|
+
dependencies = new Set<number>();
|
|
96
|
+
scopeState.pendingWaits.set(owner.id, dependencies);
|
|
97
|
+
}
|
|
98
|
+
dependencies.add(dependency.id);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public removeWait(
|
|
102
|
+
scopeState: ResolutionScopeState,
|
|
103
|
+
owner: ResolutionActivation,
|
|
104
|
+
dependency: ResolutionActivation,
|
|
105
|
+
): void {
|
|
106
|
+
const dependencies = scopeState.pendingWaits.get(owner.id);
|
|
107
|
+
if (!dependencies) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
dependencies.delete(dependency.id);
|
|
111
|
+
if (dependencies.size === 0) {
|
|
112
|
+
scopeState.pendingWaits.delete(owner.id);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private findPendingWaitPath(
|
|
117
|
+
scopeState: ResolutionScopeState,
|
|
118
|
+
from: number,
|
|
119
|
+
target: number,
|
|
120
|
+
visited: Set<number>,
|
|
121
|
+
): number[] | undefined {
|
|
122
|
+
if (from === target) {
|
|
123
|
+
return [from];
|
|
124
|
+
}
|
|
125
|
+
if (visited.has(from)) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
visited.add(from);
|
|
129
|
+
const dependencies = scopeState.pendingWaits.get(from);
|
|
130
|
+
if (!dependencies) {
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
for (const dependency of dependencies) {
|
|
134
|
+
const path = this.findPendingWaitPath(scopeState, dependency, target, visited);
|
|
135
|
+
if (path) {
|
|
136
|
+
return [from, ...path];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private getActivationById(id: number): ResolutionActivation {
|
|
143
|
+
const activation = this.activeActivations.get(id);
|
|
144
|
+
if (!activation) throw new Error(`Missing DI activation ${id} while reporting an async dependency cycle.`);
|
|
145
|
+
return activation;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private createCircularDependencyError(activations: readonly (ResolutionActivation | ServiceRegistration)[]): CircularDependencyError {
|
|
149
|
+
return new CircularDependencyError(activations.map((activation) =>
|
|
150
|
+
activation instanceof ServiceRegistration ? activation.token : activation.registration.token,
|
|
151
|
+
));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { ScopeDisposedError, ScopedServiceFromRootError } from "../errors";
|
|
2
|
+
import { isValueProvider, type Provider, type ProviderLifetime } from "../provider";
|
|
3
|
+
import { disposeTracked } from "./disposal";
|
|
4
|
+
import { ResolutionScopeState } from "./ResolutionScopeState";
|
|
5
|
+
import type { ServiceRegistration } from "./ServiceRegistration";
|
|
6
|
+
|
|
7
|
+
/** Owns scopes, resource identities and the shared asynchronous disposal work. */
|
|
8
|
+
export class ScopeLifecycle {
|
|
9
|
+
public readonly root = new ResolutionScopeState(true);
|
|
10
|
+
private readonly children = new Set<ResolutionScopeState>();
|
|
11
|
+
private readonly trackedDisposableIdentities = new WeakSet<object>();
|
|
12
|
+
|
|
13
|
+
public constructor(private readonly owner: object, private readonly validateScopes: boolean) {}
|
|
14
|
+
|
|
15
|
+
public createScope(): ResolutionScopeState {
|
|
16
|
+
this.assertLive(this.root);
|
|
17
|
+
const scope = new ResolutionScopeState(false);
|
|
18
|
+
this.children.add(scope);
|
|
19
|
+
return scope;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Scope/lifetime rules shared by the sync and async resolve paths. Returns the
|
|
23
|
+
// scope that owns the resulting instance (root for singletons), guaranteeing a
|
|
24
|
+
// single source of truth for captive-dependency and disposed-scope checks.
|
|
25
|
+
public targetFor(
|
|
26
|
+
registration: ServiceRegistration,
|
|
27
|
+
scopeState: ResolutionScopeState,
|
|
28
|
+
ownerLifetime: ProviderLifetime | undefined,
|
|
29
|
+
): ResolutionScopeState {
|
|
30
|
+
if (this.validateScopes && registration.lifetime === "scoped") {
|
|
31
|
+
// A singleton consumer or a direct root resolution cannot own a scoped
|
|
32
|
+
// service — that would be a captive dependency.
|
|
33
|
+
if (ownerLifetime === "singleton" || scopeState.isRoot) {
|
|
34
|
+
throw new ScopedServiceFromRootError(registration.token);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const targetScope = registration.lifetime === "singleton" ? this.root : scopeState;
|
|
39
|
+
// A live child scope must not resurrect singletons in a disposed root: the
|
|
40
|
+
// root cache/disposables are already cleared, so the new instance would leak
|
|
41
|
+
// and never be disposed. Mirror .NET's ObjectDisposedException.
|
|
42
|
+
this.assertLive(targetScope);
|
|
43
|
+
return targetScope;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public assertLive(scopeState: ResolutionScopeState): void {
|
|
47
|
+
if (scopeState.disposed) {
|
|
48
|
+
throw new ScopeDisposedError();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public track(
|
|
53
|
+
provider: Provider<unknown>,
|
|
54
|
+
instance: unknown,
|
|
55
|
+
targetScope: ResolutionScopeState,
|
|
56
|
+
): void {
|
|
57
|
+
if (
|
|
58
|
+
isValueProvider(provider)
|
|
59
|
+
|| provider.ownership === "external"
|
|
60
|
+
|| instance === this.owner
|
|
61
|
+
|| !isDisposableInstance(instance)
|
|
62
|
+
) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const identity = instance as object;
|
|
66
|
+
if (this.trackedDisposableIdentities.has(identity)) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
this.trackedDisposableIdentities.add(identity);
|
|
70
|
+
targetScope.disposables.push(instance);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public dispose(): Promise<void> {
|
|
74
|
+
if (this.root.disposalPromise !== undefined) {
|
|
75
|
+
return this.root.disposalPromise;
|
|
76
|
+
}
|
|
77
|
+
this.root.disposed = true;
|
|
78
|
+
const children = [...this.children];
|
|
79
|
+
for (let index = 0; index < children.length; index += 1) {
|
|
80
|
+
children[index]!.disposed = true;
|
|
81
|
+
}
|
|
82
|
+
// Defer cleanup until after the shared promise is published. A disposer is
|
|
83
|
+
// allowed to call container.dispose() re-entrantly and must join this work.
|
|
84
|
+
const disposal = Promise.resolve().then(() => this.disposeRootAndChildren(children));
|
|
85
|
+
this.root.disposalPromise = disposal;
|
|
86
|
+
return disposal;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public disposeScope(scopeState: ResolutionScopeState): Promise<void> {
|
|
90
|
+
if (scopeState.disposalPromise !== undefined) {
|
|
91
|
+
return scopeState.disposalPromise;
|
|
92
|
+
}
|
|
93
|
+
scopeState.disposed = true;
|
|
94
|
+
const disposal = Promise.resolve().then(() => this.disposeScopeState(scopeState)).finally(() => {
|
|
95
|
+
this.children.delete(scopeState);
|
|
96
|
+
});
|
|
97
|
+
scopeState.disposalPromise = disposal;
|
|
98
|
+
return disposal;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private async disposeRootAndChildren(children: readonly ResolutionScopeState[]): Promise<void> {
|
|
102
|
+
const errors: unknown[] = [];
|
|
103
|
+
for (let index = children.length - 1; index >= 0; index -= 1) {
|
|
104
|
+
const child = children[index]!;
|
|
105
|
+
try {
|
|
106
|
+
const disposal = child.disposalPromise ?? Promise.resolve().then(() => this.disposeScopeState(child));
|
|
107
|
+
child.disposalPromise = disposal;
|
|
108
|
+
await disposal;
|
|
109
|
+
} catch (error) {
|
|
110
|
+
errors.push(error);
|
|
111
|
+
} finally {
|
|
112
|
+
this.children.delete(child);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
await this.disposeScopeState(this.root);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
errors.push(error);
|
|
119
|
+
}
|
|
120
|
+
if (errors.length === 1) {
|
|
121
|
+
throw errors[0];
|
|
122
|
+
}
|
|
123
|
+
if (errors.length > 1) {
|
|
124
|
+
throw new AggregateError(errors, "Container disposal finished with errors.");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private async disposeScopeState(scopeState: ResolutionScopeState): Promise<void> {
|
|
129
|
+
// Resolutions observe `disposed` and only register a late-created resource
|
|
130
|
+
// for cleanup; waiting here guarantees it cannot escape after disposal.
|
|
131
|
+
while (scopeState.pendingCreations.size > 0) {
|
|
132
|
+
await Promise.allSettled([...scopeState.pendingCreations]);
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
await disposeTracked(scopeState.disposables);
|
|
136
|
+
} finally {
|
|
137
|
+
scopeState.disposables.length = 0;
|
|
138
|
+
scopeState.cache.clear();
|
|
139
|
+
scopeState.pendingAsync.clear();
|
|
140
|
+
scopeState.pendingCreations.clear();
|
|
141
|
+
scopeState.pendingWaits.clear();
|
|
142
|
+
scopeState.pendingAsyncActivationIds.clear();
|
|
143
|
+
scopeState.activeActivationIds.clear();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function isDisposableInstance(instance: unknown): boolean {
|
|
149
|
+
if (!instance || (typeof instance !== "object" && typeof instance !== "function")) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
const value = instance as Record<PropertyKey, unknown>;
|
|
153
|
+
return (
|
|
154
|
+
typeof value.dispose === "function" ||
|
|
155
|
+
typeof value.disposeAsync === "function" ||
|
|
156
|
+
typeof value[Symbol.dispose] === "function" ||
|
|
157
|
+
typeof value[Symbol.asyncDispose] === "function"
|
|
158
|
+
);
|
|
159
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Provider, ProviderLifetime } from "../provider";
|
|
2
|
+
import type { Token } from "../token";
|
|
3
|
+
import type { ServiceKey } from "../types";
|
|
4
|
+
|
|
5
|
+
export class ServiceRegistration<T = unknown> {
|
|
6
|
+
public constructor(
|
|
7
|
+
public readonly id: number,
|
|
8
|
+
public readonly token: Token<T>,
|
|
9
|
+
public readonly provider: Provider<T>,
|
|
10
|
+
public readonly lifetime: ProviderLifetime,
|
|
11
|
+
public readonly key?: ServiceKey,
|
|
12
|
+
public readonly fromOpenGeneric = false,
|
|
13
|
+
) {}
|
|
14
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { ModuleEncapsulationError } from "../errors";
|
|
2
|
+
import type { Provider, ProviderDefinition } from "../provider";
|
|
3
|
+
import type { Token } from "../token";
|
|
4
|
+
import type { ServiceKey } from "../types";
|
|
5
|
+
import { NamedTokenIndex } from "./NamedTokenIndex";
|
|
6
|
+
import type { OpenGenericRegistration } from "./OpenGenericRegistration";
|
|
7
|
+
import { ServiceRegistration } from "./ServiceRegistration";
|
|
8
|
+
|
|
9
|
+
/** Owns registration identity, keyed lookup and atomic open-generic materialization. */
|
|
10
|
+
export class ServiceRegistry {
|
|
11
|
+
private readonly registrationsByToken = new Map<Token<unknown>, ServiceRegistration[]>();
|
|
12
|
+
private readonly openGenericRegistrations = new Map<symbol, OpenGenericRegistration[]>();
|
|
13
|
+
private readonly openGenericMaterializedKeys = new Map<Token<unknown>, Set<ServiceKey | undefined>>();
|
|
14
|
+
// Cache successful registration selections, not resolved instances or missing keys.
|
|
15
|
+
private lastSelections: WeakMap<
|
|
16
|
+
readonly ServiceRegistration[], Map<ServiceKey | undefined, ServiceRegistration>
|
|
17
|
+
> | undefined;
|
|
18
|
+
private allSelections: WeakMap<
|
|
19
|
+
readonly ServiceRegistration[], Map<ServiceKey | undefined, readonly ServiceRegistration[]>
|
|
20
|
+
> | undefined;
|
|
21
|
+
private readonly namedTokenIndex = new NamedTokenIndex(() => this.registrationsByToken.keys());
|
|
22
|
+
private nextRegistrationId: number;
|
|
23
|
+
|
|
24
|
+
public constructor(
|
|
25
|
+
definitions: readonly ProviderDefinition[],
|
|
26
|
+
openGenericRegistrations: readonly OpenGenericRegistration[],
|
|
27
|
+
) {
|
|
28
|
+
this.nextRegistrationId = definitions.length;
|
|
29
|
+
for (let index = 0; index < definitions.length; index += 1) {
|
|
30
|
+
const definition = definitions[index] as ProviderDefinition;
|
|
31
|
+
const token = definition.provider.provide;
|
|
32
|
+
const registration = new ServiceRegistration(index, token, definition.provider, definition.lifetime, definition.key);
|
|
33
|
+
const existing = this.registrationsByToken.get(token);
|
|
34
|
+
if (existing) {
|
|
35
|
+
existing.push(registration);
|
|
36
|
+
} else {
|
|
37
|
+
this.registrationsByToken.set(token, [registration]);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (let index = 0; index < openGenericRegistrations.length; index += 1) {
|
|
42
|
+
const registration = openGenericRegistrations[index] as OpenGenericRegistration;
|
|
43
|
+
const existing = this.openGenericRegistrations.get(registration.family.id);
|
|
44
|
+
if (existing) {
|
|
45
|
+
existing.push(registration);
|
|
46
|
+
} else {
|
|
47
|
+
this.openGenericRegistrations.set(registration.family.id, [registration]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public groups(): Iterable<readonly ServiceRegistration[]> {
|
|
53
|
+
return this.registrationsByToken.values();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public lookupName(name: string): Token<unknown> | undefined {
|
|
57
|
+
return this.namedTokenIndex.lookup(name);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public all(token: Token<unknown>, key: ServiceKey | undefined): readonly ServiceRegistration[] {
|
|
61
|
+
this.materializeOpenGenericRegistration(token, key, undefined);
|
|
62
|
+
const registrations = this.registrationsByToken.get(token);
|
|
63
|
+
if (!registrations) return [];
|
|
64
|
+
if (registrations.length === 1) return registrations[0]!.key === key ? registrations : [];
|
|
65
|
+
const cached = this.allSelections?.get(registrations)?.get(key);
|
|
66
|
+
if (cached) return cached;
|
|
67
|
+
let selected: readonly ServiceRegistration[] = registrations;
|
|
68
|
+
// The usual single-key list can be consumed without copying it.
|
|
69
|
+
for (const registration of registrations) {
|
|
70
|
+
if (registration.key !== key) {
|
|
71
|
+
selected = registrations.filter((entry) => entry.key === key);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (selected.length > 0) {
|
|
76
|
+
this.allSelections ??= new WeakMap();
|
|
77
|
+
let selections = this.allSelections.get(registrations);
|
|
78
|
+
if (!selections) this.allSelections.set(registrations, selections = new Map());
|
|
79
|
+
selections.set(key, selected);
|
|
80
|
+
}
|
|
81
|
+
return selected;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public find(token: Token<unknown>, key: ServiceKey | undefined): ServiceRegistration | undefined {
|
|
85
|
+
const registrations = this.registrationsByToken.get(token);
|
|
86
|
+
// Short lists use the direct scan; indexing pays off only for larger groups.
|
|
87
|
+
const direct = registrations && registrations.length > 8
|
|
88
|
+
? this.findLastInGroup(registrations, key)
|
|
89
|
+
: this.findLastRegistration(registrations, key);
|
|
90
|
+
if (direct) {
|
|
91
|
+
return direct;
|
|
92
|
+
}
|
|
93
|
+
// Miss: a closed generic may not be materialized yet. materialize is
|
|
94
|
+
// idempotent and returns immediately for non-generic / already-done tokens.
|
|
95
|
+
this.materializeOpenGenericRegistration(token, key, undefined);
|
|
96
|
+
return this.findLastRegistration(this.registrationsByToken.get(token), key);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private findLastInGroup(
|
|
100
|
+
registrations: readonly ServiceRegistration[],
|
|
101
|
+
key: ServiceKey | undefined,
|
|
102
|
+
): ServiceRegistration | undefined {
|
|
103
|
+
const last = registrations[registrations.length - 1]!;
|
|
104
|
+
if (last.key === key && !last.fromOpenGeneric) return last;
|
|
105
|
+
const cached = this.lastSelections?.get(registrations)?.get(key);
|
|
106
|
+
if (cached) return cached;
|
|
107
|
+
const selected = this.findLastRegistration(registrations, key);
|
|
108
|
+
// Remember successful selections only; arbitrary missing keys must not grow this cache.
|
|
109
|
+
if (selected) {
|
|
110
|
+
this.lastSelections ??= new WeakMap();
|
|
111
|
+
let selections = this.lastSelections.get(registrations);
|
|
112
|
+
if (!selections) this.lastSelections.set(registrations, selections = new Map());
|
|
113
|
+
selections.set(key, selected);
|
|
114
|
+
}
|
|
115
|
+
return selected;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private findLastRegistration(
|
|
119
|
+
registrations: readonly ServiceRegistration[] | undefined,
|
|
120
|
+
key: ServiceKey | undefined,
|
|
121
|
+
): ServiceRegistration | undefined {
|
|
122
|
+
if (!registrations) {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
let genericFallback: ServiceRegistration | undefined;
|
|
126
|
+
for (let index = registrations.length - 1; index >= 0; index -= 1) {
|
|
127
|
+
const registration = registrations[index] as ServiceRegistration;
|
|
128
|
+
if (registration.key === key) {
|
|
129
|
+
// Explicit closed registrations retain priority even after resolveAll
|
|
130
|
+
// materializes a family. Enumeration order remains unchanged.
|
|
131
|
+
if (!registration.fromOpenGeneric) {
|
|
132
|
+
return registration;
|
|
133
|
+
}
|
|
134
|
+
genericFallback ??= registration;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return genericFallback;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public validateOpenGenerics(issues: Set<string>): void {
|
|
141
|
+
const tokens = [...this.registrationsByToken.keys()];
|
|
142
|
+
for (const openRegistrations of this.openGenericRegistrations.values()) {
|
|
143
|
+
for (let index = 0; index < openRegistrations.length; index += 1) {
|
|
144
|
+
const openRegistration = openRegistrations[index] as OpenGenericRegistration;
|
|
145
|
+
for (let tokenIndex = 0; tokenIndex < tokens.length; tokenIndex += 1) {
|
|
146
|
+
const argToken = tokens[tokenIndex] as Token<unknown>;
|
|
147
|
+
// Closed generic tokens are not valid generic arguments here:
|
|
148
|
+
// skipping them avoids materializing nested noise like Repo<Repo<T>>.
|
|
149
|
+
if (typeof argToken !== "function" && argToken.genericFamilyId) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const closedToken = openRegistration.family.of(argToken);
|
|
153
|
+
this.materializeOpenGenericRegistration(closedToken, openRegistration.key, issues);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
private materializeOpenGenericRegistration(
|
|
160
|
+
token: Token<unknown>,
|
|
161
|
+
key: ServiceKey | undefined,
|
|
162
|
+
issues: Set<string> | undefined,
|
|
163
|
+
): void {
|
|
164
|
+
if (typeof token === "function") {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const familyId = token.genericFamilyId;
|
|
168
|
+
const argumentToken = token.genericArgToken;
|
|
169
|
+
if (!familyId || !argumentToken) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const registrations = this.openGenericRegistrations.get(familyId);
|
|
173
|
+
if (!registrations || registrations.length === 0) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (this.isOpenGenericMaterialized(token, key)) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const staged: Array<{ readonly registration: OpenGenericRegistration; readonly provider: Provider<unknown> }> = [];
|
|
182
|
+
for (let index = 0; index < registrations.length; index += 1) {
|
|
183
|
+
const registration = registrations[index] as OpenGenericRegistration;
|
|
184
|
+
if (registration.key !== key) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let provider: Provider<unknown>;
|
|
189
|
+
try {
|
|
190
|
+
provider = registration.providerFactory(argumentToken);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
// Module visibility is a separate contract, including during eager
|
|
193
|
+
// graph validation. Keep the same diagnostic as ordinary providers.
|
|
194
|
+
if (error instanceof ModuleEncapsulationError) {
|
|
195
|
+
throw error;
|
|
196
|
+
}
|
|
197
|
+
if (issues) {
|
|
198
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
199
|
+
issues.add(`Open generic "${token.description}" factory failed: ${message}`);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
throw error;
|
|
203
|
+
}
|
|
204
|
+
staged.push({ registration, provider });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (issues && staged.length !== registrations.filter((registration) => registration.key === key).length) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const closedRegistrations = staged.map(
|
|
212
|
+
({ registration, provider }, index) => new ServiceRegistration(
|
|
213
|
+
this.nextRegistrationId + index,
|
|
214
|
+
token,
|
|
215
|
+
provider,
|
|
216
|
+
registration.lifetime,
|
|
217
|
+
registration.key,
|
|
218
|
+
true,
|
|
219
|
+
),
|
|
220
|
+
);
|
|
221
|
+
this.nextRegistrationId += closedRegistrations.length;
|
|
222
|
+
const existing = this.registrationsByToken.get(token);
|
|
223
|
+
if (existing) {
|
|
224
|
+
existing.push(...closedRegistrations);
|
|
225
|
+
if (closedRegistrations.length > 0) {
|
|
226
|
+
this.lastSelections?.delete(existing);
|
|
227
|
+
this.allSelections?.delete(existing);
|
|
228
|
+
}
|
|
229
|
+
} else if (closedRegistrations.length > 0) {
|
|
230
|
+
this.registrationsByToken.set(token, closedRegistrations);
|
|
231
|
+
this.namedTokenIndex.index(token);
|
|
232
|
+
}
|
|
233
|
+
this.markOpenGenericMaterialized(token, key);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private isOpenGenericMaterialized(token: Token<unknown>, key: ServiceKey | undefined): boolean {
|
|
237
|
+
const materializedKeys = this.openGenericMaterializedKeys.get(token);
|
|
238
|
+
if (!materializedKeys) {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
return materializedKeys.has(key);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private markOpenGenericMaterialized(token: Token<unknown>, key: ServiceKey | undefined): void {
|
|
245
|
+
let materializedKeys = this.openGenericMaterializedKeys.get(token);
|
|
246
|
+
if (!materializedKeys) {
|
|
247
|
+
materializedKeys = new Set<ServiceKey | undefined>();
|
|
248
|
+
this.openGenericMaterializedKeys.set(token, materializedKeys);
|
|
249
|
+
}
|
|
250
|
+
materializedKeys.add(key);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Class } from "../token";
|
|
2
|
+
import type { ProviderDependencyList } from "../provider";
|
|
3
|
+
|
|
4
|
+
const classDeps = new WeakMap<Function, ProviderDependencyList>();
|
|
5
|
+
export const CLASS_DEPS = Symbol("bazis.class.deps");
|
|
6
|
+
|
|
7
|
+
export function setClassDeps<C extends Class<unknown>, D extends ProviderDependencyList>(
|
|
8
|
+
useClass: C,
|
|
9
|
+
deps: D,
|
|
10
|
+
): void {
|
|
11
|
+
classDeps.set(useClass as unknown as Function, deps);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getClassDeps(useClass: Class<unknown>): ProviderDependencyList | undefined {
|
|
15
|
+
const fromMap = classDeps.get(useClass as unknown as Function);
|
|
16
|
+
if (fromMap) {
|
|
17
|
+
return fromMap;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const withDeps = useClass as unknown as {
|
|
21
|
+
[CLASS_DEPS]?: ProviderDependencyList;
|
|
22
|
+
inject?: ProviderDependencyList;
|
|
23
|
+
deps?: ProviderDependencyList;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const fromSymbol = withDeps[CLASS_DEPS];
|
|
27
|
+
if (fromSymbol) {
|
|
28
|
+
return fromSymbol;
|
|
29
|
+
}
|
|
30
|
+
if (withDeps.inject) {
|
|
31
|
+
return withDeps.inject;
|
|
32
|
+
}
|
|
33
|
+
if (withDeps.deps) {
|
|
34
|
+
return withDeps.deps;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|