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,225 @@
|
|
|
1
|
+
import { ProtoReader } from "./ProtoReader";
|
|
2
|
+
import { resolveProtoType, type ProtoSchema, type ProtoField, type ProtoLoaderOptions } from "./ProtoSchema";
|
|
3
|
+
|
|
4
|
+
type Field = ProtoField & { readonly resolved: string; readonly jsName: string };
|
|
5
|
+
const MAX_BYTES = 64 * 1024 * 1024;
|
|
6
|
+
const utf8 = new TextDecoder("utf-8", { fatal: true });
|
|
7
|
+
|
|
8
|
+
/** Local proto3 codec: scalar/nested/repeated/packed/map/oneof fields. */
|
|
9
|
+
export class ProtoCodec {
|
|
10
|
+
private readonly plans = new Map<string, { fields: Field[]; byNumber: Map<number, Field> }>();
|
|
11
|
+
constructor(private readonly schema: ProtoSchema, private readonly options: ProtoLoaderOptions) {
|
|
12
|
+
for (const message of schema.messages.values()) {
|
|
13
|
+
const fields = message.fields.map((field) => ({
|
|
14
|
+
...field, resolved: resolveProtoType(schema, field.type, message.name),
|
|
15
|
+
jsName: options.keepCase ? field.name : camel(field.name),
|
|
16
|
+
}));
|
|
17
|
+
if (new Set(fields.map((field) => field.jsName)).size !== fields.length) throw new TypeError("Protobuf field names collide after case conversion.");
|
|
18
|
+
this.plans.set(message.name, { fields, byNumber: new Map(fields.map((field) => [field.number, field])) });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
encode(name: string, value: unknown, depth = 0): Buffer {
|
|
23
|
+
this.depth(depth);
|
|
24
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Expected protobuf message object.");
|
|
25
|
+
const input = value as Record<string, unknown>;
|
|
26
|
+
const fields = this.plans.get(name)?.fields;
|
|
27
|
+
if (!fields) throw new TypeError("Unknown protobuf message " + name);
|
|
28
|
+
const parts: Buffer[] = [];
|
|
29
|
+
let size = 0;
|
|
30
|
+
const push = (part: Buffer): void => {
|
|
31
|
+
if ((size += part.length) > MAX_BYTES) throw new TypeError("Protobuf message exceeds 64 MiB.");
|
|
32
|
+
parts.push(part);
|
|
33
|
+
};
|
|
34
|
+
const oneofs = new Set<string>();
|
|
35
|
+
for (const field of fields) {
|
|
36
|
+
if (!Object.hasOwn(input, field.jsName) || input[field.jsName] === undefined || input[field.jsName] === null) continue;
|
|
37
|
+
const item = input[field.jsName];
|
|
38
|
+
if (field.oneof) {
|
|
39
|
+
if (oneofs.has(field.oneof)) throw new TypeError("Multiple protobuf oneof values.");
|
|
40
|
+
oneofs.add(field.oneof);
|
|
41
|
+
}
|
|
42
|
+
if (field.mapKey) {
|
|
43
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) throw new TypeError("Expected protobuf map.");
|
|
44
|
+
for (const [key, value] of Object.entries(item)) {
|
|
45
|
+
const keyValue = field.mapKey === "bool" ? key === "true" ? true : key === "false" ? false : invalid("Invalid boolean map key.") : key;
|
|
46
|
+
const keyBytes = this.scalar(field.mapKey, keyValue, depth + 1);
|
|
47
|
+
const valueBytes = this.scalar(field.resolved, value, depth + 1);
|
|
48
|
+
const entry = Buffer.concat([tag(1, this.wire(field.mapKey)), keyBytes, tag(2, this.wire(field.resolved)), valueBytes]);
|
|
49
|
+
push(tag(field.number, 2)); push(lengthPrefix(entry));
|
|
50
|
+
}
|
|
51
|
+
} else if (field.repeated) {
|
|
52
|
+
if (!Array.isArray(item)) throw new TypeError("Expected repeated protobuf field.");
|
|
53
|
+
if (field.packed && this.wire(field.resolved) !== 2) {
|
|
54
|
+
const values: Buffer[] = []; let packedSize = 0;
|
|
55
|
+
for (const element of item) {
|
|
56
|
+
const bytes = this.scalar(field.resolved, element, depth + 1);
|
|
57
|
+
if ((packedSize += bytes.length) > MAX_BYTES) throw new TypeError("Packed protobuf field exceeds limit.");
|
|
58
|
+
values.push(bytes);
|
|
59
|
+
}
|
|
60
|
+
if (item.length) { push(tag(field.number, 2)); push(lengthPrefix(Buffer.concat(values))); }
|
|
61
|
+
} else for (const element of item) { push(tag(field.number, this.wire(field.resolved))); push(this.scalar(field.resolved, element, depth + 1)); }
|
|
62
|
+
} else {
|
|
63
|
+
push(tag(field.number, this.wire(field.resolved)));
|
|
64
|
+
push(this.scalar(field.resolved, item, depth + 1));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return Buffer.concat(parts, size);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
decode(name: string, buffer: Buffer, depth = 0, target?: Record<string, unknown>): Record<string, unknown> {
|
|
71
|
+
this.depth(depth);
|
|
72
|
+
if (buffer.length > MAX_BYTES) throw new TypeError("Protobuf message exceeds 64 MiB.");
|
|
73
|
+
const plan = this.plans.get(name);
|
|
74
|
+
if (!plan) throw new TypeError("Unknown protobuf message " + name);
|
|
75
|
+
const result = target ?? {};
|
|
76
|
+
if (!target) for (const field of plan.fields) {
|
|
77
|
+
if (field.mapKey && (this.options.defaults || this.options.objects)) set(result, field.jsName, {});
|
|
78
|
+
else if (field.repeated && (this.options.defaults || this.options.arrays)) set(result, field.jsName, []);
|
|
79
|
+
else if (this.options.defaults && !field.repeated && !field.mapKey && !field.oneof && !field.optional) set(result, field.jsName, this.default(field.resolved));
|
|
80
|
+
}
|
|
81
|
+
const reader = new ProtoReader(buffer);
|
|
82
|
+
while (!reader.done) {
|
|
83
|
+
const raw = reader.varint();
|
|
84
|
+
const number = Number(raw >> 3n), wire = Number(raw & 7n);
|
|
85
|
+
if (number < 1 || number > 536870911) throw new TypeError("Invalid protobuf field tag.");
|
|
86
|
+
const field = plan.byNumber.get(number);
|
|
87
|
+
if (!field) { reader.skip(wire); continue; }
|
|
88
|
+
if (field.mapKey) {
|
|
89
|
+
if (wire !== 2) throw new TypeError("Invalid protobuf map wire type.");
|
|
90
|
+
const entry = new ProtoReader(reader.delimited());
|
|
91
|
+
let key = this.default(field.mapKey), value = this.default(field.resolved);
|
|
92
|
+
while (!entry.done) {
|
|
93
|
+
const entryTag = entry.varint(), number = Number(entryTag >> 3n), wire = Number(entryTag & 7n);
|
|
94
|
+
if (number === 1) key = this.readScalar(field.mapKey, wire, entry, depth + 1);
|
|
95
|
+
else if (number === 2) value = this.readScalar(field.resolved, wire, entry, depth + 1);
|
|
96
|
+
else { if (number < 1) throw new TypeError("Invalid map entry."); entry.skip(wire); }
|
|
97
|
+
}
|
|
98
|
+
const map = Object.hasOwn(result, field.jsName) ? result[field.jsName] as Record<string, unknown> : {};
|
|
99
|
+
set(map, String(key), value); set(result, field.jsName, map);
|
|
100
|
+
} else if (field.repeated) {
|
|
101
|
+
const values = Object.hasOwn(result, field.jsName) ? result[field.jsName] as unknown[] : [];
|
|
102
|
+
if (wire === 2 && this.wire(field.resolved) !== 2) {
|
|
103
|
+
const packed = new ProtoReader(reader.delimited());
|
|
104
|
+
while (!packed.done) values.push(this.readScalar(field.resolved, this.wire(field.resolved), packed, depth + 1));
|
|
105
|
+
} else values.push(this.readScalar(field.resolved, wire, reader, depth + 1));
|
|
106
|
+
set(result, field.jsName, values);
|
|
107
|
+
} else {
|
|
108
|
+
if (field.oneof) {
|
|
109
|
+
for (const sibling of plan.fields) if (sibling.oneof === field.oneof && sibling !== field) delete result[sibling.jsName];
|
|
110
|
+
if (this.options.oneofs) set(result, this.options.keepCase ? field.oneof : camel(field.oneof), field.jsName);
|
|
111
|
+
}
|
|
112
|
+
const previous = this.schema.messages.has(field.resolved) && Object.hasOwn(result, field.jsName) ? result[field.jsName] as Record<string, unknown> | null : undefined;
|
|
113
|
+
set(result, field.jsName, this.readScalar(field.resolved, wire, reader, depth + 1, previous ?? undefined));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private scalar(type: string, value: unknown, depth: number): Buffer {
|
|
120
|
+
if (this.schema.messages.has(type)) return lengthPrefix(this.encode(type, value, depth));
|
|
121
|
+
if (this.schema.enums.has(type)) {
|
|
122
|
+
if (typeof value === "string") {
|
|
123
|
+
const values = this.schema.enums.get(type)!.values;
|
|
124
|
+
if (!Object.hasOwn(values, value)) throw new TypeError("Unknown protobuf enum value.");
|
|
125
|
+
value = values[value];
|
|
126
|
+
}
|
|
127
|
+
return varint(BigInt.asUintN(64, integer(value, 32, true)));
|
|
128
|
+
}
|
|
129
|
+
if (type === "string") {
|
|
130
|
+
if (typeof value !== "string") throw new TypeError("Expected protobuf string.");
|
|
131
|
+
return lengthPrefix(Buffer.from(value, "utf8"));
|
|
132
|
+
}
|
|
133
|
+
if (type === "bytes") {
|
|
134
|
+
if (typeof value === "string") return lengthPrefix(Buffer.from(value, "base64"));
|
|
135
|
+
if (!(value instanceof Uint8Array) && !Array.isArray(value)) throw new TypeError("Expected protobuf bytes.");
|
|
136
|
+
return lengthPrefix(Buffer.from(value));
|
|
137
|
+
}
|
|
138
|
+
if (type === "bool") {
|
|
139
|
+
if (typeof value !== "boolean") throw new TypeError("Expected protobuf boolean.");
|
|
140
|
+
return Buffer.from([value ? 1 : 0]);
|
|
141
|
+
}
|
|
142
|
+
if (type === "float" || type === "double") {
|
|
143
|
+
if (typeof value !== "number") throw new TypeError("Expected protobuf number.");
|
|
144
|
+
const bytes = Buffer.alloc(type === "float" ? 4 : 8);
|
|
145
|
+
if (type === "float") bytes.writeFloatLE(value); else bytes.writeDoubleLE(value);
|
|
146
|
+
return bytes;
|
|
147
|
+
}
|
|
148
|
+
const bits = type.endsWith("64") ? 64 : 32;
|
|
149
|
+
const signed = !type.startsWith("uint") && !type.startsWith("fixed");
|
|
150
|
+
const number = integer(value, bits, signed);
|
|
151
|
+
if (type.includes("fixed")) {
|
|
152
|
+
const bytes = Buffer.alloc(bits / 8);
|
|
153
|
+
if (bits === 64) bytes.writeBigUInt64LE(BigInt.asUintN(64, number));
|
|
154
|
+
else bytes.writeUInt32LE(Number(BigInt.asUintN(32, number)));
|
|
155
|
+
return bytes;
|
|
156
|
+
}
|
|
157
|
+
return varint(type.startsWith("sint") ? (number << 1n) ^ (number >> BigInt(bits - 1)) : BigInt.asUintN(64, number));
|
|
158
|
+
}
|
|
159
|
+
private readScalar(type: string, wire: number, reader: ProtoReader, depth: number, target?: Record<string, unknown>): unknown {
|
|
160
|
+
if (wire !== this.wire(type)) throw new TypeError("Incorrect protobuf wire type.");
|
|
161
|
+
if (this.schema.messages.has(type)) return this.decode(type, reader.delimited(), depth, target);
|
|
162
|
+
if (type === "string") return utf8.decode(reader.delimited());
|
|
163
|
+
if (type === "bytes") {
|
|
164
|
+
const value = reader.delimited();
|
|
165
|
+
return this.options.bytes === String ? value.toString("base64") : this.options.bytes === Array ? [...value] : Buffer.from(value);
|
|
166
|
+
}
|
|
167
|
+
if (type === "double") return reader.bytes(8).readDoubleLE();
|
|
168
|
+
if (type === "float") return reader.bytes(4).readFloatLE();
|
|
169
|
+
if (type === "bool") return reader.varint() !== 0n;
|
|
170
|
+
let value = wire === 1 ? reader.bytes(8).readBigUInt64LE() : wire === 5 ? BigInt(reader.bytes(4).readUInt32LE()) : reader.varint();
|
|
171
|
+
if (this.schema.enums.has(type)) {
|
|
172
|
+
const number = Number(BigInt.asIntN(32, value));
|
|
173
|
+
return this.options.enums === String ? Object.entries(this.schema.enums.get(type)!.values).find(([, n]) => n === number)?.[0] ?? number : number;
|
|
174
|
+
}
|
|
175
|
+
const bits = type.endsWith("64") ? 64 : 32;
|
|
176
|
+
if (type.startsWith("sint")) value = (value >> 1n) ^ -(value & 1n);
|
|
177
|
+
value = type.startsWith("uint") || type.startsWith("fixed") ? BigInt.asUintN(bits, value) : BigInt.asIntN(bits, value);
|
|
178
|
+
if (bits === 32 || this.options.longs === Number) return Number(value);
|
|
179
|
+
return this.options.longs === String ? value.toString() : value;
|
|
180
|
+
}
|
|
181
|
+
private wire(type: string): number {
|
|
182
|
+
if (type === "double" || type.endsWith("fixed64")) return 1;
|
|
183
|
+
if (type === "float" || type.endsWith("fixed32")) return 5;
|
|
184
|
+
if (type === "string" || type === "bytes" || this.schema.messages.has(type)) return 2;
|
|
185
|
+
return 0;
|
|
186
|
+
}
|
|
187
|
+
private default(type: string): unknown {
|
|
188
|
+
if (this.schema.messages.has(type)) return null;
|
|
189
|
+
if (this.schema.enums.has(type)) return this.options.enums === String ? Object.keys(this.schema.enums.get(type)!.values)[0] : 0;
|
|
190
|
+
if (type === "string") return "";
|
|
191
|
+
if (type === "bool") return false;
|
|
192
|
+
if (type === "bytes") return this.options.bytes === String ? "" : this.options.bytes === Array ? [] : Buffer.alloc(0);
|
|
193
|
+
if (type.endsWith("64")) return this.options.longs === String ? "0" : this.options.longs === Number ? 0 : 0n;
|
|
194
|
+
return 0;
|
|
195
|
+
}
|
|
196
|
+
private depth(depth: number): void { if (depth > 64) throw new TypeError("Protobuf message nesting exceeds 64."); }
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function integer(value: unknown, bits: number, signed: boolean): bigint {
|
|
200
|
+
if (typeof value === "number" && !Number.isSafeInteger(value)) throw new TypeError("Use bigint or string for exact protobuf 64-bit integers.");
|
|
201
|
+
if (typeof value !== "number" && typeof value !== "bigint" && (typeof value !== "string" || !/^-?\d+$/.test(value))) throw new TypeError("Expected protobuf integer.");
|
|
202
|
+
const number = BigInt(value);
|
|
203
|
+
const min = signed ? -(1n << BigInt(bits - 1)) : 0n;
|
|
204
|
+
const max = (1n << BigInt(signed ? bits - 1 : bits)) - 1n;
|
|
205
|
+
if (number < min || number > max) throw new TypeError("Protobuf integer out of range.");
|
|
206
|
+
return number;
|
|
207
|
+
}
|
|
208
|
+
function varint(value: bigint): Buffer {
|
|
209
|
+
const bytes: number[] = [];
|
|
210
|
+
do {
|
|
211
|
+
const byte = Number(value & 127n); value >>= 7n;
|
|
212
|
+
bytes.push(value ? byte | 128 : byte);
|
|
213
|
+
} while (value !== 0n);
|
|
214
|
+
return Buffer.from(bytes);
|
|
215
|
+
}
|
|
216
|
+
function tag(number: number, wire: number): Buffer { return varint(BigInt(number) * 8n + BigInt(wire)); }
|
|
217
|
+
function lengthPrefix(bytes: Buffer): Buffer {
|
|
218
|
+
if (bytes.length > MAX_BYTES) throw new TypeError("Protobuf field exceeds 64 MiB.");
|
|
219
|
+
return Buffer.concat([varint(BigInt(bytes.length)), bytes]);
|
|
220
|
+
}
|
|
221
|
+
function camel(name: string): string { return name.replace(/_([a-z])/g, (_match, letter: string) => letter.toUpperCase()); }
|
|
222
|
+
function set(target: Record<string, unknown>, key: string, value: unknown): void {
|
|
223
|
+
Object.defineProperty(target, key, { value, writable: true, enumerable: true, configurable: true });
|
|
224
|
+
}
|
|
225
|
+
function invalid(message: string): never { throw new TypeError(message); }
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type { ProtoSchema, ProtoMessage, ProtoField, ProtoRpc } from "./ProtoSchema";
|
|
2
|
+
|
|
3
|
+
/** Bounded proto3 parser. Unsupported dialects fail instead of changing the wire contract. */
|
|
4
|
+
export class ProtoParser {
|
|
5
|
+
private readonly tokens: string[] = [];
|
|
6
|
+
private cursor = 0;
|
|
7
|
+
private packageName = "";
|
|
8
|
+
readonly imports: string[] = [];
|
|
9
|
+
|
|
10
|
+
constructor(source: string, private readonly schema: ProtoSchema, private readonly filename: string) {
|
|
11
|
+
if (source.length > 4 * 1024 * 1024) this.fail("Schema exceeds 4 MiB.");
|
|
12
|
+
const lexer = /\s+|\/\/[^\n]*|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|[A-Za-z_][A-Za-z_0-9]*|0[xX][0-9a-fA-F]+|\d+|[{}()[\];=.,<>:+-]/gy;
|
|
13
|
+
let offset = 0;
|
|
14
|
+
while (offset < source.length) {
|
|
15
|
+
lexer.lastIndex = offset;
|
|
16
|
+
const match = lexer.exec(source);
|
|
17
|
+
if (!match) this.fail("Unexpected character at offset " + offset + ".");
|
|
18
|
+
const token = match![0];
|
|
19
|
+
offset = lexer.lastIndex;
|
|
20
|
+
if (!/^\s|^\/\//.test(token) && !token.startsWith("/*")) this.tokens.push(token);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
parse(): void {
|
|
25
|
+
this.expect("syntax"); this.expect("=");
|
|
26
|
+
if (this.string() !== "proto3") this.fail("Only syntax = proto3 is supported.");
|
|
27
|
+
this.expect(";");
|
|
28
|
+
while (this.peek() !== undefined) {
|
|
29
|
+
switch (this.take()) {
|
|
30
|
+
case "package": this.packageName = this.type(); this.expect(";"); break;
|
|
31
|
+
case "import":
|
|
32
|
+
if (this.peek() === "public") this.take();
|
|
33
|
+
if (this.peek() === "weak") this.fail("Weak imports are not supported.");
|
|
34
|
+
this.imports.push(this.string()); this.expect(";"); break;
|
|
35
|
+
case "message": this.message(this.packageName, 0); break;
|
|
36
|
+
case "enum": this.enumeration(this.packageName); break;
|
|
37
|
+
case "service": this.service(); break;
|
|
38
|
+
case "option": this.skipStatement(); break;
|
|
39
|
+
case ";": break;
|
|
40
|
+
default: this.fail("Unsupported top-level declaration.");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
private message(parent: string, depth: number): void {
|
|
45
|
+
if (depth >= 64) this.fail("Schema nesting exceeds 64.");
|
|
46
|
+
const name = qualify(parent, this.identifier());
|
|
47
|
+
this.unique(name);
|
|
48
|
+
const message: ProtoMessage = { name, fields: [] };
|
|
49
|
+
this.schema.messages.set(name, message);
|
|
50
|
+
this.expect("{");
|
|
51
|
+
while (!this.accept("}")) {
|
|
52
|
+
if (this.accept("message")) this.message(name, depth + 1);
|
|
53
|
+
else if (this.accept("enum")) this.enumeration(name);
|
|
54
|
+
else if (this.accept("option") || this.accept("reserved")) this.skipStatement();
|
|
55
|
+
else if (this.accept("oneof")) {
|
|
56
|
+
const oneof = this.identifier(); this.expect("{");
|
|
57
|
+
while (!this.accept("}")) {
|
|
58
|
+
if (this.accept("option")) this.skipStatement();
|
|
59
|
+
else message.fields.push(this.field(oneof));
|
|
60
|
+
}
|
|
61
|
+
} else if (!this.accept(";")) message.fields.push(this.field());
|
|
62
|
+
}
|
|
63
|
+
const numbers = new Set<number>(), names = new Set<string>();
|
|
64
|
+
for (const field of message.fields) {
|
|
65
|
+
if (numbers.has(field.number) || names.has(field.name)) this.fail("Duplicate field in " + name + ".");
|
|
66
|
+
numbers.add(field.number); names.add(field.name);
|
|
67
|
+
if (field.oneof && message.fields.some((entry) => entry.name === field.oneof)) this.fail("oneof name collides with a field.");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
private field(oneof?: string): ProtoField {
|
|
71
|
+
const repeated = this.accept("repeated");
|
|
72
|
+
const optional = this.accept("optional");
|
|
73
|
+
if (repeated && optional) this.fail("A field cannot be both repeated and optional.");
|
|
74
|
+
if (oneof && (repeated || optional)) this.fail("oneof fields cannot have labels.");
|
|
75
|
+
let type: string, mapKey: string | undefined;
|
|
76
|
+
if (this.accept("map")) {
|
|
77
|
+
if (repeated || optional || oneof) this.fail("Invalid map field label.");
|
|
78
|
+
this.expect("<"); mapKey = this.type(); this.expect(","); type = this.type(); this.expect(">");
|
|
79
|
+
if (!/^(?:u?int(?:32|64)|sint(?:32|64)|s?fixed(?:32|64)|bool|string)$/.test(mapKey)) this.fail("Invalid map key type.");
|
|
80
|
+
} else type = this.type();
|
|
81
|
+
const name = this.identifier(); this.expect("=");
|
|
82
|
+
const number = this.number();
|
|
83
|
+
if (number < 1 || number > 536870911 || number >= 19000 && number <= 19999) this.fail("Invalid protobuf field number.");
|
|
84
|
+
let packed = true;
|
|
85
|
+
if (this.accept("[")) {
|
|
86
|
+
while (!this.accept("]")) {
|
|
87
|
+
if (this.accept("packed")) {
|
|
88
|
+
this.expect("=");
|
|
89
|
+
const value = this.take();
|
|
90
|
+
if (value !== "true" && value !== "false") this.fail("Invalid packed option.");
|
|
91
|
+
packed = value === "true";
|
|
92
|
+
} else this.skipFieldOption();
|
|
93
|
+
if (this.peek() !== "]") this.expect(",");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
this.expect(";");
|
|
97
|
+
return { name, number, type, repeated, optional, oneof, mapKey, packed };
|
|
98
|
+
}
|
|
99
|
+
private enumeration(parent: string): void {
|
|
100
|
+
const name = qualify(parent, this.identifier());
|
|
101
|
+
this.unique(name);
|
|
102
|
+
const values: Record<string, number> = Object.create(null);
|
|
103
|
+
this.expect("{");
|
|
104
|
+
while (!this.accept("}")) {
|
|
105
|
+
if (this.accept("option") || this.accept("reserved")) { this.skipStatement(); continue; }
|
|
106
|
+
if (this.accept(";")) continue;
|
|
107
|
+
const key = this.identifier(); this.expect("="); const value = this.number();
|
|
108
|
+
if (value < -2147483648 || value > 2147483647 || Object.hasOwn(values, key)) this.fail("Invalid enum entry.");
|
|
109
|
+
if (Object.keys(values).length === 0 && value !== 0) this.fail("The first proto3 enum value must be zero.");
|
|
110
|
+
values[key] = value;
|
|
111
|
+
if (this.accept("[")) { while (!this.accept("]")) this.take(); }
|
|
112
|
+
this.expect(";");
|
|
113
|
+
}
|
|
114
|
+
if (Object.keys(values).length === 0) this.fail("Empty protobuf enum.");
|
|
115
|
+
this.schema.enums.set(name, { name, values });
|
|
116
|
+
}
|
|
117
|
+
private service(): void {
|
|
118
|
+
const name = qualify(this.packageName, this.identifier());
|
|
119
|
+
this.unique(name);
|
|
120
|
+
const methods: ProtoRpc[] = [];
|
|
121
|
+
this.expect("{");
|
|
122
|
+
while (!this.accept("}")) {
|
|
123
|
+
if (this.accept("option")) { this.skipStatement(); continue; }
|
|
124
|
+
if (this.accept(";")) continue;
|
|
125
|
+
this.expect("rpc");
|
|
126
|
+
const method = this.identifier();
|
|
127
|
+
if (methods.some((entry) => entry.name === method)) this.fail("Duplicate RPC method.");
|
|
128
|
+
this.expect("("); const requestStream = this.accept("stream"); const input = this.type(); this.expect(")");
|
|
129
|
+
this.expect("returns"); this.expect("("); const responseStream = this.accept("stream"); const output = this.type(); this.expect(")");
|
|
130
|
+
if (this.accept("{")) {
|
|
131
|
+
while (!this.accept("}")) { this.expect("option"); this.skipStatement(); }
|
|
132
|
+
} else this.expect(";");
|
|
133
|
+
methods.push({ name: method, input, output, requestStream, responseStream });
|
|
134
|
+
}
|
|
135
|
+
this.schema.services.set(name, methods);
|
|
136
|
+
}
|
|
137
|
+
private skipStatement(): void {
|
|
138
|
+
let depth = 0;
|
|
139
|
+
while (true) {
|
|
140
|
+
const token = this.take();
|
|
141
|
+
if (token === ";" && depth === 0) return;
|
|
142
|
+
if (["{", "(", "["].includes(token)) depth++;
|
|
143
|
+
if (["}", ")", "]"].includes(token) && --depth < 0) this.fail("Unbalanced option.");
|
|
144
|
+
if (depth > 64) this.fail("Option nesting exceeds 64.");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
private skipFieldOption(): void {
|
|
148
|
+
let depth = 0;
|
|
149
|
+
while (depth > 0 || this.peek() !== "," && this.peek() !== "]") {
|
|
150
|
+
const token = this.take();
|
|
151
|
+
if (["{", "(", "["].includes(token)) depth++;
|
|
152
|
+
if (["}", ")", "]"].includes(token) && --depth < 0) this.fail("Unbalanced field option.");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
private unique(name: string): void {
|
|
156
|
+
if (this.schema.messages.has(name) || this.schema.enums.has(name) || this.schema.services.has(name)) this.fail("Duplicate protobuf symbol " + name + ".");
|
|
157
|
+
}
|
|
158
|
+
private type(): string {
|
|
159
|
+
let value = this.accept(".") ? "." : "";
|
|
160
|
+
value += this.identifier();
|
|
161
|
+
while (this.accept(".")) value += "." + this.identifier();
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
private identifier(): string {
|
|
165
|
+
const value = this.take();
|
|
166
|
+
if (!/^[A-Za-z_][A-Za-z_0-9]*$/.test(value)) this.fail("Expected identifier.");
|
|
167
|
+
return value;
|
|
168
|
+
}
|
|
169
|
+
private number(): number {
|
|
170
|
+
const sign = this.accept("-") ? -1 : 1;
|
|
171
|
+
const text = this.take();
|
|
172
|
+
if (!/^(?:\d+|0[xX][0-9a-fA-F]+)$/.test(text)) this.fail("Expected integer.");
|
|
173
|
+
const value = sign * Number(text);
|
|
174
|
+
if (!Number.isSafeInteger(value)) this.fail("Integer out of range.");
|
|
175
|
+
return value;
|
|
176
|
+
}
|
|
177
|
+
private string(): string {
|
|
178
|
+
const value = this.take();
|
|
179
|
+
if (!value.startsWith('"')) this.fail("Expected double-quoted string.");
|
|
180
|
+
try { return JSON.parse(value) as string; } catch { return this.fail("Invalid quoted string."); }
|
|
181
|
+
}
|
|
182
|
+
private peek(): string | undefined { return this.tokens[this.cursor]; }
|
|
183
|
+
private take(): string {
|
|
184
|
+
const value = this.tokens[this.cursor++];
|
|
185
|
+
if (value === undefined) this.fail("Unexpected end of schema.");
|
|
186
|
+
return value!;
|
|
187
|
+
}
|
|
188
|
+
private accept(value: string): boolean { if (this.peek() !== value) return false; this.cursor++; return true; }
|
|
189
|
+
private expect(value: string): void { if (!this.accept(value)) this.fail("Expected " + value + ", got " + String(this.peek()) + "."); }
|
|
190
|
+
private fail(message: string): never { throw new TypeError(this.filename + ": " + message); }
|
|
191
|
+
}
|
|
192
|
+
function qualify(parent: string, name: string): string { return parent ? parent + "." + name : name; }
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Bounds-checked protobuf wire reader; every loop consumes bytes or throws. */
|
|
2
|
+
export class ProtoReader {
|
|
3
|
+
offset = 0;
|
|
4
|
+
constructor(readonly buffer: Buffer) {}
|
|
5
|
+
get done(): boolean { return this.offset === this.buffer.length; }
|
|
6
|
+
varint(): bigint {
|
|
7
|
+
let value = 0n;
|
|
8
|
+
for (let i = 0; i < 10; i++) {
|
|
9
|
+
const byte = this.bytes(1)[0]!;
|
|
10
|
+
if (i === 9 && byte > 1) throw new TypeError("Protobuf varint exceeds 64 bits.");
|
|
11
|
+
value |= BigInt(byte & 127) << BigInt(i * 7);
|
|
12
|
+
if (byte < 128) return value;
|
|
13
|
+
}
|
|
14
|
+
throw new TypeError("Invalid protobuf varint.");
|
|
15
|
+
}
|
|
16
|
+
bytes(length: number): Buffer {
|
|
17
|
+
if (!Number.isSafeInteger(length) || length < 0 || length > this.buffer.length - this.offset) throw new TypeError("Truncated protobuf field.");
|
|
18
|
+
const result = this.buffer.subarray(this.offset, this.offset + length);
|
|
19
|
+
this.offset += length;
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
delimited(): Buffer {
|
|
23
|
+
const length = this.varint();
|
|
24
|
+
if (length > BigInt(this.buffer.length - this.offset)) throw new TypeError("Truncated protobuf field.");
|
|
25
|
+
return this.bytes(Number(length));
|
|
26
|
+
}
|
|
27
|
+
skip(wire: number): void {
|
|
28
|
+
if (wire === 0) this.varint();
|
|
29
|
+
else if (wire === 1) this.bytes(8);
|
|
30
|
+
else if (wire === 2) this.delimited();
|
|
31
|
+
else if (wire === 5) this.bytes(4);
|
|
32
|
+
else throw new TypeError("Unsupported protobuf wire type.");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface ProtoField {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly number: number;
|
|
4
|
+
readonly type: string;
|
|
5
|
+
readonly repeated: boolean;
|
|
6
|
+
readonly optional: boolean;
|
|
7
|
+
readonly oneof?: string;
|
|
8
|
+
readonly mapKey?: string;
|
|
9
|
+
readonly packed: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface ProtoMessage { readonly name: string; readonly fields: ProtoField[] }
|
|
12
|
+
export interface ProtoEnum { readonly name: string; readonly values: Record<string, number> }
|
|
13
|
+
export interface ProtoRpc { readonly name: string; readonly input: string; readonly output: string; readonly requestStream: boolean; readonly responseStream: boolean }
|
|
14
|
+
export interface ProtoSchema {
|
|
15
|
+
readonly messages: Map<string, ProtoMessage>;
|
|
16
|
+
readonly enums: Map<string, ProtoEnum>;
|
|
17
|
+
readonly services: Map<string, ProtoRpc[]>;
|
|
18
|
+
}
|
|
19
|
+
export interface ProtoLoaderOptions {
|
|
20
|
+
readonly keepCase?: boolean;
|
|
21
|
+
readonly defaults?: boolean;
|
|
22
|
+
readonly arrays?: boolean;
|
|
23
|
+
readonly objects?: boolean;
|
|
24
|
+
readonly oneofs?: boolean;
|
|
25
|
+
/** Exact 64-bit values are bigint by default; String and Number are opt-in. */
|
|
26
|
+
readonly longs?: typeof String | typeof Number | typeof BigInt;
|
|
27
|
+
readonly enums?: typeof String | typeof Number;
|
|
28
|
+
readonly bytes?: typeof String | typeof Array | typeof Buffer;
|
|
29
|
+
readonly includeDirs?: readonly string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const SCALAR_TYPES = new Set([
|
|
33
|
+
"double", "float", "int32", "int64", "uint32", "uint64", "sint32", "sint64",
|
|
34
|
+
"fixed32", "fixed64", "sfixed32", "sfixed64", "bool", "string", "bytes",
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
export function resolveProtoType(schema: ProtoSchema, type: string, owner: string): string {
|
|
38
|
+
if (SCALAR_TYPES.has(type)) return type;
|
|
39
|
+
const has = (name: string): boolean => schema.messages.has(name) || schema.enums.has(name);
|
|
40
|
+
if (type.startsWith(".")) {
|
|
41
|
+
if (has(type.slice(1))) return type.slice(1);
|
|
42
|
+
} else {
|
|
43
|
+
const parts = owner.split(".");
|
|
44
|
+
while (parts.length > 0) {
|
|
45
|
+
const name = [...parts, type].join(".");
|
|
46
|
+
if (has(name)) return name;
|
|
47
|
+
parts.pop();
|
|
48
|
+
}
|
|
49
|
+
if (has(type)) return type;
|
|
50
|
+
}
|
|
51
|
+
throw new TypeError("Unknown protobuf type " + type + " in " + owner + ".");
|
|
52
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SecureServerOptions } from "node:http2";
|
|
2
|
+
|
|
3
|
+
/** TLS configuration uses only the runtime's built-in HTTP/2/TLS implementation. */
|
|
4
|
+
export class ServerCredentials {
|
|
5
|
+
private constructor(private readonly settings: SecureServerOptions | undefined) {}
|
|
6
|
+
|
|
7
|
+
static createInsecure(): ServerCredentials { return new ServerCredentials(undefined); }
|
|
8
|
+
static createSsl(
|
|
9
|
+
rootCerts: Buffer | null,
|
|
10
|
+
keyCertPairs: readonly { private_key: Buffer; cert_chain: Buffer }[],
|
|
11
|
+
checkClientCertificate = false,
|
|
12
|
+
): ServerCredentials {
|
|
13
|
+
if (rootCerts !== null && !Buffer.isBuffer(rootCerts)) throw new TypeError("TLS rootCerts must be Buffer or null.");
|
|
14
|
+
if (!Array.isArray(keyCertPairs) || keyCertPairs.length === 0
|
|
15
|
+
|| keyCertPairs.some((pair) => !Buffer.isBuffer(pair.private_key) || !Buffer.isBuffer(pair.cert_chain))) {
|
|
16
|
+
throw new TypeError("TLS requires private_key/cert_chain Buffer pairs.");
|
|
17
|
+
}
|
|
18
|
+
if (typeof checkClientCertificate !== "boolean") throw new TypeError("Invalid TLS client certificate policy.");
|
|
19
|
+
return new ServerCredentials({
|
|
20
|
+
ca: rootCerts === null ? undefined : Buffer.from(rootCerts),
|
|
21
|
+
key: keyCertPairs.map((pair) => Buffer.from(pair.private_key)),
|
|
22
|
+
cert: keyCertPairs.map((pair) => Buffer.from(pair.cert_chain)),
|
|
23
|
+
requestCert: checkClientCertificate,
|
|
24
|
+
rejectUnauthorized: checkClientCertificate,
|
|
25
|
+
allowHTTP1: false,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/** @internal Snapshot for this listener; not a second networking stack. */
|
|
29
|
+
http2Options(): SecureServerOptions | undefined { return this.settings && { ...this.settings }; }
|
|
30
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Metadata } from "./Metadata";
|
|
2
|
+
|
|
3
|
+
/** TLS always verifies the server certificate; plaintext requires an http address. */
|
|
4
|
+
export interface GrpcClientTlsOptions {
|
|
5
|
+
readonly ca?: string | Buffer;
|
|
6
|
+
readonly cert?: string | Buffer;
|
|
7
|
+
readonly key?: string | Buffer;
|
|
8
|
+
readonly servername?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface GrpcClientOptions {
|
|
12
|
+
readonly address: string;
|
|
13
|
+
readonly tls?: GrpcClientTlsOptions;
|
|
14
|
+
readonly metadata?: Metadata;
|
|
15
|
+
readonly timeoutMs?: number;
|
|
16
|
+
readonly maxSendMessageLength?: number;
|
|
17
|
+
readonly maxReceiveMessageLength?: number;
|
|
18
|
+
readonly maxConcurrentCalls?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface GrpcCallOptions {
|
|
22
|
+
readonly metadata?: Metadata;
|
|
23
|
+
readonly timeoutMs?: number;
|
|
24
|
+
readonly deadline?: Date | number;
|
|
25
|
+
readonly signal?: AbortSignal;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface GrpcResponse<T> {
|
|
29
|
+
readonly data: T;
|
|
30
|
+
readonly metadata: Metadata;
|
|
31
|
+
readonly trailers: Metadata;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Consume once. Early for-await exit cancels the call, as does cancel(). */
|
|
35
|
+
export interface GrpcResponseStream<T> extends AsyncIterable<T> {
|
|
36
|
+
readonly metadata: Promise<Metadata>;
|
|
37
|
+
readonly trailers: Promise<Metadata>;
|
|
38
|
+
cancel(): void;
|
|
39
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Metadata } from "./Metadata";
|
|
2
|
+
import type { ServerCredentials } from "./ServerCredentials";
|
|
3
|
+
import type { ServerOptions, ServiceDefinition } from "./serviceDefinition";
|
|
4
|
+
import type { Class, BazisModuleRef } from "../di";
|
|
5
|
+
import type { ModelValidator } from "../http/Binding/modelValidator";
|
|
6
|
+
import type { RequestModelClass } from "../http/Binding/requestModelRegistry";
|
|
7
|
+
|
|
8
|
+
/** One instance per RPC, including the complete lifetime of a streaming RPC. */
|
|
9
|
+
export interface GrpcContext {
|
|
10
|
+
readonly metadata: Metadata;
|
|
11
|
+
readonly signal: AbortSignal;
|
|
12
|
+
readonly deadline: Date | number;
|
|
13
|
+
readonly peer: string;
|
|
14
|
+
readonly path: string;
|
|
15
|
+
sendMetadata(metadata: Metadata): void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface GrpcModuleOptions {
|
|
19
|
+
readonly imports?: readonly BazisModuleRef[];
|
|
20
|
+
/** Normally contributed by feature-module grpcControllers. */
|
|
21
|
+
readonly controllers?: readonly Class<object>[];
|
|
22
|
+
/** DTO validation, captured per server. Default: Bazis's modelValidatorAdapter. */
|
|
23
|
+
readonly validator?: ModelValidator;
|
|
24
|
+
/** host:port or [IPv6]:port, default 127.0.0.1:50051. Port 0 selects a free port. */
|
|
25
|
+
readonly address?: string;
|
|
26
|
+
/** Default: plaintext. Pass ServerCredentials.createSsl(...) for TLS/mTLS. */
|
|
27
|
+
readonly credentials?: ServerCredentials;
|
|
28
|
+
/** Bazis transport limits; unknown options fail at startup. */
|
|
29
|
+
readonly serverOptions?: ServerOptions;
|
|
30
|
+
/** Includes handlers still running after client cancellation. Default 1024. */
|
|
31
|
+
readonly maxConcurrentCalls?: number;
|
|
32
|
+
/** Grace period before forced transport shutdown. Default 5000 ms. */
|
|
33
|
+
readonly shutdownTimeoutMs?: number;
|
|
34
|
+
/** Hosted service startup phase, default 10 (after infrastructure). */
|
|
35
|
+
readonly phase?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface GrpcControllerDefinition {
|
|
39
|
+
readonly controller: Class<object>;
|
|
40
|
+
readonly service: ServiceDefinition;
|
|
41
|
+
/** Service method key -> instance method name. */
|
|
42
|
+
readonly methods: ReadonlyMap<string, string | symbol>;
|
|
43
|
+
/** Explicit DTO overrides keyed by instance method; optional for compatibility. */
|
|
44
|
+
readonly requestModels?: ReadonlyMap<string | symbol, RequestModelClass>;
|
|
45
|
+
}
|