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.
Files changed (513) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -0
  3. package/cli/build.ts +147 -0
  4. package/cli/codegen.ts +40 -0
  5. package/cli/generateModule.ts +187 -0
  6. package/cli/generateProject.ts +183 -0
  7. package/cli/main.ts +125 -0
  8. package/cli/moduleRegistration.ts +127 -0
  9. package/cli/naming.ts +124 -0
  10. package/cli/parseCli.ts +151 -0
  11. package/cli/templates/module.ts +497 -0
  12. package/cli/templates/pack.ts +76 -0
  13. package/cli/templates/passport.ts +178 -0
  14. package/core/agent/AgentContextBuilder.ts +567 -0
  15. package/core/agent/AgentDataDefinition.ts +8 -0
  16. package/core/agent/AgentRegistry.ts +539 -0
  17. package/core/agent/AgentRuntime.ts +47 -0
  18. package/core/agent/AgentToolExecutor.ts +2130 -0
  19. package/core/agent/AgentToolHooks.ts +39 -0
  20. package/core/agent/ModelProvider.ts +21 -0
  21. package/core/agent/README.md +229 -0
  22. package/core/agent/Tool.contract.ts +20 -0
  23. package/core/agent/decorators/Agent.ts +11 -0
  24. package/core/agent/decorators/Prompt.ts +11 -0
  25. package/core/agent/decorators/Task.ts +29 -0
  26. package/core/agent/decorators/Tool.ts +12 -0
  27. package/core/agent/errors.ts +43 -0
  28. package/core/agent/generated/catalog.ts +26 -0
  29. package/core/agent/index.ts +170 -0
  30. package/core/agent/internal/AgentExecutionDriver.ts +1497 -0
  31. package/core/agent/internal/AgentExecutionState.ts +775 -0
  32. package/core/agent/internal/AgentJsonSchema.ts +150 -0
  33. package/core/agent/internal/AgentModelBinding.ts +57 -0
  34. package/core/agent/internal/Schema.contract.ts +36 -0
  35. package/core/agent/internal/ToolAudit.projector.ts +163 -0
  36. package/core/agent/internal/ToolContract.validator.ts +102 -0
  37. package/core/agent/metadata.ts +398 -0
  38. package/core/agent/moduleContributions-v1.ts +113 -0
  39. package/core/agent/semantic.ts +903 -0
  40. package/core/agent/session/codec.ts +33 -0
  41. package/core/agent/session/contracts.ts +96 -0
  42. package/core/agent/session/entities.ts +84 -0
  43. package/core/agent/session/protector.ts +92 -0
  44. package/core/app/index.ts +5 -0
  45. package/core/app/runApp.ts +293 -0
  46. package/core/app/ui/index.ts +29 -0
  47. package/core/app/ui/uiProfileResolver.ts +966 -0
  48. package/core/app/ui/uiSurfaceHosting.ts +38 -0
  49. package/core/app/ui/uiSurfaceHttp.ts +476 -0
  50. package/core/background/BackgroundService.ts +223 -0
  51. package/core/background/backgroundModule.ts +42 -0
  52. package/core/background/decorator.ts +43 -0
  53. package/core/background/delay.ts +27 -0
  54. package/core/background/index.ts +15 -0
  55. package/core/cache/COMPATIBILITY.md +13 -0
  56. package/core/cache/ICache.ts +71 -0
  57. package/core/cache/MemoryCache.ts +394 -0
  58. package/core/cache/README.md +83 -0
  59. package/core/cache/SPEC.md +1355 -0
  60. package/core/cache/cacheModule.ts +21 -0
  61. package/core/cache/decorators/Cacheable.ts +38 -0
  62. package/core/cache/decorators/CacheableRedis.ts +39 -0
  63. package/core/cache/decorators/OutputCache.ts +33 -0
  64. package/core/cache/decorators/OutputRedisCache.ts +33 -0
  65. package/core/cache/decorators/cacheableMetadata.ts +78 -0
  66. package/core/cache/decorators/cacheableRedisMetadata.ts +81 -0
  67. package/core/cache/decorators/outputCacheMetadata.ts +71 -0
  68. package/core/cache/decorators/outputRedisCacheMetadata.ts +77 -0
  69. package/core/cache/di/classProviderHook.ts +26 -0
  70. package/core/cache/distributed/CacheCodec.ts +5 -0
  71. package/core/cache/distributed/DistributedCache.ts +403 -0
  72. package/core/cache/distributed/DistributedCacheDriver.ts +83 -0
  73. package/core/cache/distributed/DistributedCacheStores.ts +28 -0
  74. package/core/cache/distributed/IDistributedCache.ts +40 -0
  75. package/core/cache/distributed/NamedCacheRegistry.ts +23 -0
  76. package/core/cache/distributed/codecs.ts +32 -0
  77. package/core/cache/distributed/index.ts +19 -0
  78. package/core/cache/errors/CacheError.ts +16 -0
  79. package/core/cache/http/CachedHttpPayload.ts +213 -0
  80. package/core/cache/http/applyClientCacheHeaders.ts +61 -0
  81. package/core/cache/http/buildOutputCacheKey.ts +154 -0
  82. package/core/cache/http/buildRedisOutputCacheKey.ts +16 -0
  83. package/core/cache/http/composeOutputCache.ts +130 -0
  84. package/core/cache/http/outputCacheMiddleware.ts +111 -0
  85. package/core/cache/http/outputCacheSecurityWarning.ts +58 -0
  86. package/core/cache/http/outputRedisCacheMiddleware.ts +118 -0
  87. package/core/cache/index.ts +97 -0
  88. package/core/cache/internal/AutomaticCacheKey.ts +106 -0
  89. package/core/cache/internal/CacheKeyGuard.ts +56 -0
  90. package/core/cache/internal/buildCacheProviders.ts +146 -0
  91. package/core/cache/internal/normalizeCacheKey.ts +9 -0
  92. package/core/cache/internal/resolveCachePolicy.ts +32 -0
  93. package/core/cache/internal/resolveCacheableRedisPolicy.ts +17 -0
  94. package/core/cache/internal/resolveOutputRedisCachePolicy.ts +17 -0
  95. package/core/cache/providers/cachedProviders.ts +68 -0
  96. package/core/cache/services/cacheProxy.ts +243 -0
  97. package/core/cache/tokens/CACHE_POLICIES.ts +5 -0
  98. package/core/cache/tokens/DISTRIBUTED_CACHE.ts +30 -0
  99. package/core/cache/types/CacheEntry.ts +7 -0
  100. package/core/cache/types/CacheOptions.ts +60 -0
  101. package/core/cache/types/CachePolicy.ts +74 -0
  102. package/core/cache/types/CacheableRedisOptions.ts +23 -0
  103. package/core/cache/types/OutputRedisCacheOptions.ts +25 -0
  104. package/core/di/README.md +104 -0
  105. package/core/di/ServiceCollection.ts +185 -0
  106. package/core/di/ServiceProvider.ts +689 -0
  107. package/core/di/ServiceScope.ts +61 -0
  108. package/core/di/container.ts +38 -0
  109. package/core/di/errors/AmbiguousNamedDependencyError.ts +10 -0
  110. package/core/di/errors/AsyncResolutionRequiredError.ts +12 -0
  111. package/core/di/errors/CircularDependencyError.ts +10 -0
  112. package/core/di/errors/ClassDependenciesMismatchError.ts +15 -0
  113. package/core/di/errors/DiError.ts +6 -0
  114. package/core/di/errors/InvalidProviderError.ts +9 -0
  115. package/core/di/errors/ModuleEncapsulationError.ts +7 -0
  116. package/core/di/errors/ModuleOwnedProviderConflictError.ts +8 -0
  117. package/core/di/errors/NamedDependencyNotFoundError.ts +7 -0
  118. package/core/di/errors/OptionsValidationError.ts +7 -0
  119. package/core/di/errors/ProviderNotFoundError.ts +10 -0
  120. package/core/di/errors/ScopeDisposedError.ts +7 -0
  121. package/core/di/errors/ScopedServiceFromRootError.ts +9 -0
  122. package/core/di/errors/ServiceValidationError.ts +7 -0
  123. package/core/di/errors/index.ts +14 -0
  124. package/core/di/extensions/activator.ts +39 -0
  125. package/core/di/extensions/application.ts +117 -0
  126. package/core/di/extensions/hosted-service.ts +124 -0
  127. package/core/di/extensions/index.ts +23 -0
  128. package/core/di/extensions/options-reloadable.ts +137 -0
  129. package/core/di/extensions/options.ts +91 -0
  130. package/core/di/extensions/service-provider-token.ts +21 -0
  131. package/core/di/index.ts +97 -0
  132. package/core/di/internal/GraphValidator.ts +119 -0
  133. package/core/di/internal/HostedServicePlan.ts +158 -0
  134. package/core/di/internal/NamedTokenIndex.ts +55 -0
  135. package/core/di/internal/OpenGenericRegistration.ts +14 -0
  136. package/core/di/internal/ResolutionPlan.ts +18 -0
  137. package/core/di/internal/ResolutionScopeState.ts +19 -0
  138. package/core/di/internal/ResolutionTracker.ts +153 -0
  139. package/core/di/internal/ScopeLifecycle.ts +159 -0
  140. package/core/di/internal/ServiceRegistration.ts +14 -0
  141. package/core/di/internal/ServiceRegistry.ts +252 -0
  142. package/core/di/internal/classDeps.ts +38 -0
  143. package/core/di/internal/disposal.ts +58 -0
  144. package/core/di/internal/providerDeps.ts +26 -0
  145. package/core/di/module/DI.ts +146 -0
  146. package/core/di/module/Global.ts +25 -0
  147. package/core/di/module/Module.ts +44 -0
  148. package/core/di/module/ModuleRegistrar.ts +69 -0
  149. package/core/di/module/autoDeps.ts +39 -0
  150. package/core/di/module/classProviderHooks.ts +66 -0
  151. package/core/di/module/collectModuleConfigs.ts +57 -0
  152. package/core/di/module/collectModuleControllers.ts +53 -0
  153. package/core/di/module/collectModuleUiProfiles.ts +53 -0
  154. package/core/di/module/createContainer.ts +261 -0
  155. package/core/di/module/encapsulation.ts +416 -0
  156. package/core/di/module/encapsulationHooks.ts +36 -0
  157. package/core/di/module/generatedProviderAttachments.ts +102 -0
  158. package/core/di/module/index.ts +41 -0
  159. package/core/di/module/moduleExtensions.ts +35 -0
  160. package/core/di/module/moduleNameBinding.ts +136 -0
  161. package/core/di/module/moduleOwnedProviderContributors.ts +409 -0
  162. package/core/di/module/providerSelection.ts +90 -0
  163. package/core/di/module/shortcuts.ts +111 -0
  164. package/core/di/module/types/BazisModule.ts +71 -0
  165. package/core/di/module/types/DiRegistrar.ts +24 -0
  166. package/core/di/module/types/index.ts +2 -0
  167. package/core/di/provider/index.ts +26 -0
  168. package/core/di/provider/providerGuards.ts +17 -0
  169. package/core/di/provider/types/AsyncFactoryProvider.ts +15 -0
  170. package/core/di/provider/types/ClassProvider.ts +18 -0
  171. package/core/di/provider/types/FactoryProvider.ts +20 -0
  172. package/core/di/provider/types/KeyedDependency.ts +20 -0
  173. package/core/di/provider/types/LazyDependency.ts +31 -0
  174. package/core/di/provider/types/NamedDependency.ts +16 -0
  175. package/core/di/provider/types/Provider.ts +10 -0
  176. package/core/di/provider/types/ProviderDefinition.ts +11 -0
  177. package/core/di/provider/types/ProviderDependencyList.ts +11 -0
  178. package/core/di/provider/types/ProviderLifetime.ts +1 -0
  179. package/core/di/provider/types/ProviderOwnership.ts +7 -0
  180. package/core/di/provider/types/ResolvedDeps.ts +18 -0
  181. package/core/di/provider/types/ValueProvider.ts +6 -0
  182. package/core/di/provider/types/index.ts +13 -0
  183. package/core/di/token.ts +84 -0
  184. package/core/di/types/BuildServiceProviderOptions.ts +4 -0
  185. package/core/di/types/ServiceKey.ts +1 -0
  186. package/core/di/types/ServiceResolver.ts +16 -0
  187. package/core/di/types/index.ts +3 -0
  188. package/core/generatedFingerprint.ts +60 -0
  189. package/core/generatedRuntime.ts +187 -0
  190. package/core/grpc/Grpc.module.ts +23 -0
  191. package/core/grpc/GrpcBinding.contract.ts +35 -0
  192. package/core/grpc/GrpcCall.ts +73 -0
  193. package/core/grpc/GrpcClient.ts +172 -0
  194. package/core/grpc/GrpcClientCall.ts +267 -0
  195. package/core/grpc/GrpcError.ts +19 -0
  196. package/core/grpc/GrpcRequest.binding.ts +45 -0
  197. package/core/grpc/GrpcServer.ts +204 -0
  198. package/core/grpc/GrpcStatus.ts +8 -0
  199. package/core/grpc/GrpcTransport.ts +174 -0
  200. package/core/grpc/Metadata.ts +73 -0
  201. package/core/grpc/ProtoCodec.ts +225 -0
  202. package/core/grpc/ProtoParser.ts +192 -0
  203. package/core/grpc/ProtoReader.ts +34 -0
  204. package/core/grpc/ProtoSchema.ts +52 -0
  205. package/core/grpc/ServerCredentials.ts +30 -0
  206. package/core/grpc/clientContracts.ts +39 -0
  207. package/core/grpc/contracts.ts +45 -0
  208. package/core/grpc/decorators.ts +82 -0
  209. package/core/grpc/grpcClientProvider.ts +9 -0
  210. package/core/grpc/index.ts +17 -0
  211. package/core/grpc/moduleControllers.ts +38 -0
  212. package/core/grpc/protobuf.ts +80 -0
  213. package/core/grpc/serviceDefinition.ts +20 -0
  214. package/core/http/Authorization/Authorize.ts +52 -0
  215. package/core/http/Authorization/authorizeComposer.ts +31 -0
  216. package/core/http/Authorization/metadata.ts +158 -0
  217. package/core/http/Binding/ParameterBinder.ts +109 -0
  218. package/core/http/Binding/RequestModel.ts +27 -0
  219. package/core/http/Binding/autoBindings.ts +125 -0
  220. package/core/http/Binding/bindings.ts +19 -0
  221. package/core/http/Binding/convert.ts +48 -0
  222. package/core/http/Binding/generatedSpec.ts +18 -0
  223. package/core/http/Binding/listModelRegistry.ts +47 -0
  224. package/core/http/Binding/modelBinder.ts +345 -0
  225. package/core/http/Binding/modelValidator.ts +30 -0
  226. package/core/http/Binding/requestModelRegistry.ts +117 -0
  227. package/core/http/Decorators/attributes.ts +92 -0
  228. package/core/http/Decorators/controller.ts +24 -0
  229. package/core/http/Decorators/metadata.ts +107 -0
  230. package/core/http/Decorators/routes.ts +131 -0
  231. package/core/http/Errors/HttpError.ts +92 -0
  232. package/core/http/HttpContext/HttpContext.ts +148 -0
  233. package/core/http/HttpContext/ResponseBuilder.ts +37 -0
  234. package/core/http/HttpContext/inspectableRedirects.ts +47 -0
  235. package/core/http/HttpContext/principal.ts +24 -0
  236. package/core/http/HttpContext/responseLifetime.ts +45 -0
  237. package/core/http/HttpServer.ts +627 -0
  238. package/core/http/Middleware/accessLog.ts +90 -0
  239. package/core/http/Middleware/cors.ts +160 -0
  240. package/core/http/Middleware/errorHandler.ts +100 -0
  241. package/core/http/Middleware/pipeline.ts +21 -0
  242. package/core/http/Middleware/rateLimit.ts +104 -0
  243. package/core/http/Middleware/securityHeaders.ts +118 -0
  244. package/core/http/Middleware/types.ts +19 -0
  245. package/core/http/OpenApi/generatedOpenApiRegistry.ts +102 -0
  246. package/core/http/OpenApi/openApiDocs.ts +75 -0
  247. package/core/http/OpenApi/openApiDocument.ts +356 -0
  248. package/core/http/README.md +139 -0
  249. package/core/http/Results/HttpResult.ts +19 -0
  250. package/core/http/Results/normalize.ts +93 -0
  251. package/core/http/Results/results.ts +70 -0
  252. package/core/http/Routing/Router.ts +201 -0
  253. package/core/http/Routing/RouterBuilder.ts +184 -0
  254. package/core/http/Routing/template.ts +112 -0
  255. package/core/http/SPEC.md +981 -0
  256. package/core/http/Versioning/VersionReader.ts +20 -0
  257. package/core/http/WebSocketUpgrade.ts +29 -0
  258. package/core/http/composeRouteMiddlewareComposers.ts +21 -0
  259. package/core/http/correlation/createCorrelationIdMiddleware.ts +79 -0
  260. package/core/http/httpModule.ts +48 -0
  261. package/core/http/index.ts +140 -0
  262. package/core/http/middlewareTokens.ts +48 -0
  263. package/core/http/options.ts +134 -0
  264. package/core/http-client/index.ts +105 -0
  265. package/core/infra/Infra.ts +158 -0
  266. package/core/infra/InfraConnector.ts +86 -0
  267. package/core/infra/InfraLifecycle.ts +86 -0
  268. package/core/infra/cache/RedisDistributedCacheBackend.ts +88 -0
  269. package/core/infra/cache/RedisDistributedCacheDriver.ts +186 -0
  270. package/core/infra/cache/index.ts +7 -0
  271. package/core/infra/connectorConfig.ts +29 -0
  272. package/core/infra/connectorIdentity.ts +39 -0
  273. package/core/infra/connectors/codex/CodexAppServer.ts +146 -0
  274. package/core/infra/connectors/codex/CodexAppServerClient.ts +258 -0
  275. package/core/infra/connectors/codex/CodexPolicy.ts +114 -0
  276. package/core/infra/connectors/codex/CodexTurn.ts +133 -0
  277. package/core/infra/connectors/codex/contracts.ts +82 -0
  278. package/core/infra/connectors/codex.ts +26 -0
  279. package/core/infra/connectors/llm.ts +78 -0
  280. package/core/infra/connectors/llmRouter.ts +443 -0
  281. package/core/infra/connectors/openaiCompatible.ts +590 -0
  282. package/core/infra/connectors/openaiTextStream.ts +134 -0
  283. package/core/infra/connectors/opensearch.ts +307 -0
  284. package/core/infra/connectors/postgres.ts +105 -0
  285. package/core/infra/connectors/redis.ts +132 -0
  286. package/core/infra/index.ts +58 -0
  287. package/core/kernel/ApplicationLifetime.ts +91 -0
  288. package/core/kernel/Bazis.ts +73 -0
  289. package/core/kernel/Environment.ts +53 -0
  290. package/core/kernel/Kernel.ts +391 -0
  291. package/core/kernel/KernelBuilder.ts +172 -0
  292. package/core/kernel/LifecycleCoordinator.ts +204 -0
  293. package/core/kernel/README.md +66 -0
  294. package/core/kernel/SupervisedHostedService.ts +147 -0
  295. package/core/kernel/config/ConfigRegistry.ts +48 -0
  296. package/core/kernel/config/Configuration.ts +110 -0
  297. package/core/kernel/config/README.md +62 -0
  298. package/core/kernel/config/Secret.ts +29 -0
  299. package/core/kernel/config/addConfigOptions.ts +63 -0
  300. package/core/kernel/config/defineConfig.ts +211 -0
  301. package/core/kernel/config/sources.ts +123 -0
  302. package/core/kernel/correlation/requestContext.ts +57 -0
  303. package/core/kernel/errors/ConfigKeyMissingError.ts +7 -0
  304. package/core/kernel/errors/KernelError.ts +7 -0
  305. package/core/kernel/errors/ShutdownTimeoutError.ts +7 -0
  306. package/core/kernel/errors/StartupAbortedError.ts +7 -0
  307. package/core/kernel/errors/StartupTimeoutError.ts +7 -0
  308. package/core/kernel/errors/index.ts +5 -0
  309. package/core/kernel/events/EventBus.ts +140 -0
  310. package/core/kernel/events/EventToken.ts +17 -0
  311. package/core/kernel/events/eventSubscribers.ts +126 -0
  312. package/core/kernel/events/kernelEvents.ts +16 -0
  313. package/core/kernel/events/onEvent.ts +32 -0
  314. package/core/kernel/health/HealthCheckContracts.ts +42 -0
  315. package/core/kernel/health/HealthService.ts +93 -0
  316. package/core/kernel/index.ts +96 -0
  317. package/core/kernel/internal/awaitAbortable.ts +18 -0
  318. package/core/kernel/internal/awaitShutdown.ts +21 -0
  319. package/core/kernel/internal/reportDiagnosticFailure.ts +8 -0
  320. package/core/kernel/internal/validateTimeout.ts +8 -0
  321. package/core/kernel/lifecycleHooks.ts +18 -0
  322. package/core/kernel/logging/ConsoleLogger.ts +68 -0
  323. package/core/kernel/logging/Logger.ts +22 -0
  324. package/core/kernel/types/ConfigSource.ts +9 -0
  325. package/core/kernel/types/EnvironmentName.ts +1 -0
  326. package/core/kernel/types/KernelOptions.ts +23 -0
  327. package/core/kernel/types/LifecycleHook.ts +18 -0
  328. package/core/kernel/types/index.ts +4 -0
  329. package/core/orm/DATABASE_PROVIDER.ts +5 -0
  330. package/core/orm/OrmHostedPlan.validator.ts +55 -0
  331. package/core/orm/OrmLifecycle.ts +146 -0
  332. package/core/orm/OrmOwnedStoreLifecycle.ts +96 -0
  333. package/core/orm/buildOrmProviders.ts +152 -0
  334. package/core/orm/databaseConnector.ts +108 -0
  335. package/core/orm/encapsulationHook.ts +19 -0
  336. package/core/orm/index.ts +95 -0
  337. package/core/orm/listQuery.ts +198 -0
  338. package/core/orm/ormModule.ts +173 -0
  339. package/core/orm/ownedStoreContributions.ts +195 -0
  340. package/core/orm/registerRepositories.ts +27 -0
  341. package/core/orm/repository.ts +45 -0
  342. package/core/orm/strictSchemaHostedIdentity.ts +17 -0
  343. package/core/scripts/agent-codegen.ts +1166 -0
  344. package/core/scripts/di-generate-target.ts +90 -0
  345. package/core/scripts/di-generate.ts +1837 -0
  346. package/core/scripts/orm-predicate-codegen.ts +33 -0
  347. package/core/scripts/request-model-codegen.ts +326 -0
  348. package/core/websocket/DESIGN.md +297 -0
  349. package/core/websocket/WsRateLimiter.ts +101 -0
  350. package/core/websocket/adapter/adapter.interface.ts +45 -0
  351. package/core/websocket/adapter/in-memory.adapter.ts +190 -0
  352. package/core/websocket/adapter/redis-delivery-scripts.ts +135 -0
  353. package/core/websocket/adapter/redis-delivery-store.ts +86 -0
  354. package/core/websocket/adapter/redis-operations.ts +33 -0
  355. package/core/websocket/adapter/redis.adapter.ts +218 -0
  356. package/core/websocket/codec/binary.codec.ts +87 -0
  357. package/core/websocket/codec/json.codec.ts +34 -0
  358. package/core/websocket/codec/packet-codec.interface.ts +17 -0
  359. package/core/websocket/decorators.ts +165 -0
  360. package/core/websocket/explorer.ts +126 -0
  361. package/core/websocket/index.ts +78 -0
  362. package/core/websocket/middleware.ts +146 -0
  363. package/core/websocket/packet-codec.ts +75 -0
  364. package/core/websocket/reliable-delivery.ts +56 -0
  365. package/core/websocket/session-creation.ts +16 -0
  366. package/core/websocket/session-manager.ts +856 -0
  367. package/core/websocket/socket-wrapper.ts +314 -0
  368. package/core/websocket/topic-cache.ts +59 -0
  369. package/core/websocket/types.ts +122 -0
  370. package/core/websocket/websocketModule.ts +96 -0
  371. package/core/websocket/ws-dispatch.ts +123 -0
  372. package/core/websocket/ws-server.ts +1707 -0
  373. package/index.ts +281 -0
  374. package/library/boundary/diagnostics-v1.ts +136 -0
  375. package/library/boundary/index.ts +73 -0
  376. package/library/boundary/json/decodeBoundedJsonV1.ts +518 -0
  377. package/library/boundary/json/limits-v1.ts +46 -0
  378. package/library/boundary/json/normalizeBoundedJsonV1.ts +256 -0
  379. package/library/boundary/json/types-v1.ts +11 -0
  380. package/library/boundary/schema/boundarySchemaHashV1.ts +6 -0
  381. package/library/boundary/schema/collectBoundaryValueDiagnosticsV1.ts +325 -0
  382. package/library/boundary/schema/decodeBoundarySchemaV1.ts +646 -0
  383. package/library/boundary/schema/index.ts +8 -0
  384. package/library/boundary/schema/types-v1.ts +99 -0
  385. package/library/boundary/schema/validateBoundaryValueV1.ts +58 -0
  386. package/library/boundary/serialization/canonicalJsonV1.ts +66 -0
  387. package/library/http-client/HttpClient.ts +969 -0
  388. package/library/http-client/HttpClientFactory.ts +45 -0
  389. package/library/http-client/errors.ts +68 -0
  390. package/library/http-client/index.ts +43 -0
  391. package/library/http-client/interceptors.ts +40 -0
  392. package/library/http-client/progress.ts +62 -0
  393. package/library/http-client/redirectProtocol.ts +6 -0
  394. package/library/http-client/serialize.ts +133 -0
  395. package/library/http-client/types.ts +174 -0
  396. package/library/jsonapi/ListQueryError.ts +25 -0
  397. package/library/jsonapi/ListRequest.ts +37 -0
  398. package/library/jsonapi/decorators.ts +161 -0
  399. package/library/jsonapi/document.ts +124 -0
  400. package/library/jsonapi/index.ts +40 -0
  401. package/library/jsonapi/parseListQuery.ts +291 -0
  402. package/library/jsonapi/types.ts +125 -0
  403. package/library/jwt/JwtEncoder.ts +40 -0
  404. package/library/jwt/JwtKeyRing.ts +164 -0
  405. package/library/jwt/JwtValidator.ts +210 -0
  406. package/library/jwt/TokenIssuer.ts +149 -0
  407. package/library/jwt/TokenService.ts +51 -0
  408. package/library/jwt/base64url.ts +61 -0
  409. package/library/jwt/claims.ts +36 -0
  410. package/library/jwt/errors.ts +44 -0
  411. package/library/jwt/index.ts +59 -0
  412. package/library/jwt/limits.ts +8 -0
  413. package/library/jwt/signing/Hs256Algorithm.ts +62 -0
  414. package/library/jwt/signing/Rs256Algorithm.ts +133 -0
  415. package/library/jwt/signing/SigningAlgorithm.ts +18 -0
  416. package/library/jwt/signing/pem.ts +30 -0
  417. package/library/openapi/codegen.ts +875 -0
  418. package/library/openapi/document.ts +326 -0
  419. package/library/openapi/index.ts +13 -0
  420. package/library/openapi/types.ts +69 -0
  421. package/library/openapi/ui.ts +182 -0
  422. package/library/orm/DatabaseFacade.ts +209 -0
  423. package/library/orm/DbContext.ts +107 -0
  424. package/library/orm/DbContextFactory.ts +25 -0
  425. package/library/orm/DbContextOptions.ts +33 -0
  426. package/library/orm/Metadata/DynamicModelBuilder.ts +497 -0
  427. package/library/orm/Metadata/KeyTuple.ts +36 -0
  428. package/library/orm/Metadata/ModelBuilder.ts +299 -0
  429. package/library/orm/Metadata/OrmModel.ts +80 -0
  430. package/library/orm/Metadata/ValueConverter.ts +57 -0
  431. package/library/orm/Metadata/conventions.ts +54 -0
  432. package/library/orm/Metadata/decorators.ts +396 -0
  433. package/library/orm/Metadata/types.ts +140 -0
  434. package/library/orm/Providers/OwnedStoreCatalog.reader.ts +1802 -0
  435. package/library/orm/Providers/PostgresDialect.ts +234 -0
  436. package/library/orm/Providers/PostgresProvider.ts +1494 -0
  437. package/library/orm/Providers/PostgresSchema.decoder.ts +107 -0
  438. package/library/orm/Providers/limits.ts +29 -0
  439. package/library/orm/Providers/operationDeadline.ts +43 -0
  440. package/library/orm/Providers/ormOwnedStoreRuntime.ts +19 -0
  441. package/library/orm/Providers/ormTransactionRuntime.ts +117 -0
  442. package/library/orm/Providers/propertyConversion.ts +14 -0
  443. package/library/orm/Providers/resolvedForeignKey.ts +16 -0
  444. package/library/orm/Providers/transactionCallbacks.ts +45 -0
  445. package/library/orm/Providers/transactionOutcome.ts +82 -0
  446. package/library/orm/Providers/transactionScopes.ts +78 -0
  447. package/library/orm/Providers/types.ts +207 -0
  448. package/library/orm/Query/DbSet.ts +78 -0
  449. package/library/orm/Query/EntityQuery.ts +247 -0
  450. package/library/orm/Query/ImmediateMutations.ts +226 -0
  451. package/library/orm/Query/IncludeLoader.ts +200 -0
  452. package/library/orm/Query/QueryPlan.ts +55 -0
  453. package/library/orm/Query/SqlTranslator.ts +195 -0
  454. package/library/orm/Query/conditions.ts +127 -0
  455. package/library/orm/Query/materialize.ts +39 -0
  456. package/library/orm/README.md +256 -0
  457. package/library/orm/Repository/README.md +684 -0
  458. package/library/orm/Repository/Repository.ts +68 -0
  459. package/library/orm/Saving/CommandBuilder.ts +139 -0
  460. package/library/orm/Saving/ExecutionStrategy.ts +128 -0
  461. package/library/orm/Saving/SaveExecutor.ts +413 -0
  462. package/library/orm/Saving/applyConventions.ts +64 -0
  463. package/library/orm/Schema/CheckExpression.ts +327 -0
  464. package/library/orm/Schema/ExactSchemaVerifier.ts +168 -0
  465. package/library/orm/Schema/ExpectedSchema.ts +43 -0
  466. package/library/orm/Schema/MigrationRunner.ts +146 -0
  467. package/library/orm/Schema/Migrator.ts +73 -0
  468. package/library/orm/Schema/OrmOwnedStore.ts +123 -0
  469. package/library/orm/Schema/OwnedStoreAdmission.ts +752 -0
  470. package/library/orm/Schema/OwnedStoreCanonical.ts +273 -0
  471. package/library/orm/Schema/OwnedStoreCatalog.ts +1325 -0
  472. package/library/orm/Schema/SafeAdditiveSchema.ts +100 -0
  473. package/library/orm/Schema/SchemaAdmission.ts +62 -0
  474. package/library/orm/Schema/SchemaDiffer.ts +78 -0
  475. package/library/orm/Schema/formatSchemaDifferences.ts +62 -0
  476. package/library/orm/Schema/introspection.ts +52 -0
  477. package/library/orm/Schema/physicalColumnTypes.ts +37 -0
  478. package/library/orm/Schema/tableKey.ts +26 -0
  479. package/library/orm/Tracking/ChangeTracker.ts +448 -0
  480. package/library/orm/Tracking/EntityState.ts +13 -0
  481. package/library/orm/Transactions/OrmTransaction.ts +30 -0
  482. package/library/orm/Transactions/TransactionScopeCoordinator.ts +377 -0
  483. package/library/orm/errors.ts +190 -0
  484. package/library/orm/index.ts +162 -0
  485. package/library/orm/runtime.ts +14 -0
  486. package/library/redaction/index.ts +166 -0
  487. package/library/ui/UiProfile.ts +77 -0
  488. package/library/ui/compiled-v1.ts +131 -0
  489. package/library/ui/compiler/compileUiSurfaceV1.ts +717 -0
  490. package/library/ui/compiler/contracts-v1.ts +25 -0
  491. package/library/ui/compiler/index.ts +12 -0
  492. package/library/ui/compiler/openApiIndex.ts +246 -0
  493. package/library/ui/defineUiProfile.ts +340 -0
  494. package/library/ui/diagnostics-v1.ts +33 -0
  495. package/library/ui/index.ts +129 -0
  496. package/library/ui/profile-v1.ts +191 -0
  497. package/library/ui/serialization.ts +130 -0
  498. package/library/ui/uiProfileAuthoring.ts +289 -0
  499. package/library/ui/uiProfileAuthoringMetadata.ts +78 -0
  500. package/library/validation/MessageRegistry.ts +144 -0
  501. package/library/validation/README.md +62 -0
  502. package/library/validation/RuleCompiler.ts +183 -0
  503. package/library/validation/RuleEngine.ts +401 -0
  504. package/library/validation/SPEC.md +579 -0
  505. package/library/validation/ValidationError.ts +37 -0
  506. package/library/validation/ValidationResult.ts +63 -0
  507. package/library/validation/Validator.ts +101 -0
  508. package/library/validation/index.ts +16 -0
  509. package/library/validation/metadata.ts +69 -0
  510. package/library/validation/modelValidatorAdapter.ts +119 -0
  511. package/library/validation/types/ValidationCode.ts +69 -0
  512. package/library/validation/types/ValidatorOptions.ts +153 -0
  513. package/package.json +80 -0
@@ -0,0 +1,108 @@
1
+ import { InfraError, reader, requireValue, postgresConnectionOptions, type InfraConnector, type PostgresConfigShape } from "../infra";
2
+ import type { AppConfig, ConfigRegistry } from "../kernel";
3
+ import { postgres, type DatabaseProvider, type PostgresServerTimeouts } from "../../library/orm";
4
+ import { DATABASE_PROVIDER } from "./DATABASE_PROVIDER";
5
+
6
+ /** Connect before the servers and ORM features: open the database before anyone asks for it. */
7
+ const DATABASE_PHASE = -110;
8
+
9
+ /** Optional operational fields belong to the ORM connection contract. */
10
+ export interface PostgresOrmConfigShape extends PostgresConfigShape {
11
+ readonly max?: number;
12
+ readonly connectionTimeout?: number;
13
+ readonly idleTimeout?: number;
14
+ readonly maxLifetime?: number;
15
+ readonly tls?: "disable" | "allow" | "prefer" | "require" | "verify-ca" | "verify-full";
16
+ readonly tlsCa?: string;
17
+ readonly operationTimeoutMs?: number;
18
+ readonly cancellationTimeoutMs?: number;
19
+ readonly cancellationMode?: "server" | "close";
20
+ readonly maxPendingOperations?: number;
21
+ readonly statementTimeoutMs?: number;
22
+ readonly lockTimeoutMs?: number;
23
+ readonly idleInTransactionTimeoutMs?: number;
24
+ readonly transactionTimeoutMs?: number;
25
+ }
26
+
27
+ function buildPostgresProvider<T extends PostgresOrmConfigShape>(config: AppConfig<T>, configs?: ConfigRegistry): DatabaseProvider {
28
+ const c = reader(config, configs);
29
+ const optional = (key: string) => c.has(key) ? c.get(key) : undefined;
30
+ const number = (key: string, allowZero = false): number | undefined => {
31
+ const value = optional(key);
32
+ if (value === undefined) return undefined;
33
+ if (typeof value !== "number" || !Number.isInteger(value) || value < (allowZero ? 0 : 1) || value > 2_147_483_647) throw new InfraError(`Invalid PostgreSQL configuration field: ${key}.`);
34
+ return value;
35
+ };
36
+ const hostname = requireValue(c.get("host"), "host", "database");
37
+ const options: Record<string, unknown> = { ...postgresConnectionOptions(config, configs) };
38
+ for (const key of ["max", "connectionTimeout", "idleTimeout", "maxLifetime"] as const) {
39
+ const value = number(key, key === "idleTimeout" || key === "maxLifetime");
40
+ if (value !== undefined) options[key] = value;
41
+ }
42
+ // defineConfig keys are always present, so an empty tlsCa means "no additional CA".
43
+ const tls = optional("tls"), configuredCa = optional("tlsCa"), ca = configuredCa === "" ? undefined : configuredCa;
44
+ if (tls !== undefined) {
45
+ if (typeof tls !== "string" || !["disable", "allow", "prefer", "require", "verify-ca", "verify-full"].includes(tls)) throw new InfraError("Invalid PostgreSQL configuration field: tls.");
46
+ options.tls = tls;
47
+ }
48
+ if (ca !== undefined) {
49
+ if (typeof ca !== "string" || !ca.trim() || tls !== "verify-full") throw new InfraError("tlsCa requires a non-empty certificate and tls=verify-full.");
50
+ options.tls = { ca, serverName: hostname, rejectUnauthorized: true };
51
+ }
52
+ const serverTimeouts: Record<string, number> = {};
53
+ const cancellationMode = optional("cancellationMode");
54
+ if (cancellationMode !== undefined && cancellationMode !== "server" && cancellationMode !== "close") throw new InfraError("Invalid PostgreSQL configuration field: cancellationMode.");
55
+ for (const key of ["statementTimeoutMs", "lockTimeoutMs", "idleInTransactionTimeoutMs", "transactionTimeoutMs"] as const) {
56
+ const value = number(key); if (value !== undefined) serverTimeouts[key] = value;
57
+ }
58
+ return postgres({ options, operationTimeoutMs: number("operationTimeoutMs"), cancellationTimeoutMs: number("cancellationTimeoutMs"), cancellationMode, maxPendingOperations: number("maxPendingOperations"), serverTimeouts: serverTimeouts as PostgresServerTimeouts });
59
+ }
60
+
61
+ /**
62
+ * Database connection connector for `@Infra`: the bridge between infrastructure
63
+ * and the ORM (the EF Core model: the connection comes from outside, the ORM
64
+ * works on top of it).
65
+ *
66
+ * Takes the whole PostgreSQL subsystem config (`dbConfig` from
67
+ * `defineConfig("db", ...)`) and reads the declared keys itself. Publishes a
68
+ * `DatabaseProvider` under the shared {@link DATABASE_PROVIDER} token, opens it
69
+ * at start (phase −110, before ORM features and servers) and closes it at shutdown.
70
+ *
71
+ * Migrations stay with the feature (they depend on the model): `ormBazis: { context,
72
+ * entities, ensureCreated }` without `provider` works on top of this shared connection.
73
+ *
74
+ * ```ts
75
+ * export const dbConfig = defineConfig("db", {
76
+ * default: { host: "db", port: 5432, database: "app", username: "postgres", password: secret("dev") },
77
+ * });
78
+ * @Infra({ db: ormBazisConnect(dbConfig) })
79
+ * export class AppInfra {}
80
+ *
81
+ * @Module({ ormBazis: { context: UsersDbContext, entities: [User], ensureCreated: true } })
82
+ * export class UsersModule {} // consumer of the shared DATABASE_PROVIDER
83
+ * ```
84
+ */
85
+ export function ormBazisConnect<T extends PostgresOrmConfigShape>(config: AppConfig<T>): InfraConnector<DatabaseProvider>;
86
+ export function ormBazisConnect(
87
+ config: AppConfig<PostgresOrmConfigShape>,
88
+ ): InfraConnector<DatabaseProvider> {
89
+ return {
90
+ token: DATABASE_PROVIDER,
91
+ config,
92
+ phase: DATABASE_PHASE,
93
+ create(configs) {
94
+ return buildPostgresProvider(config, configs);
95
+ },
96
+ async connect(provider, signal) {
97
+ if (!(await provider.ping(signal))) {
98
+ throw new InfraError('Infra connector "database": postgres is not reachable.');
99
+ }
100
+ },
101
+ async dispose(provider) {
102
+ await provider.close();
103
+ },
104
+ healthCheck(provider, signal) {
105
+ return provider.ping(signal);
106
+ },
107
+ };
108
+ }
@@ -0,0 +1,19 @@
1
+ import { registerNamedDependencyEncapsulationHook } from "../di/module/encapsulationHooks";
2
+ import { IRepository } from "./repository";
3
+
4
+ let registered = false;
5
+
6
+ /** Allows closed `IRepository<Entity>` named deps when the module exports open generic `IRepository`. */
7
+ export function registerRepositoryEncapsulationHook(): void {
8
+ if (registered) {
9
+ return;
10
+ }
11
+ registered = true;
12
+
13
+ registerNamedDependencyEncapsulationHook(({ depName, familiesVisible }) => {
14
+ if (depName.startsWith("IRepository<") && familiesVisible.has(IRepository.id)) {
15
+ return true;
16
+ }
17
+ return undefined;
18
+ });
19
+ }
@@ -0,0 +1,95 @@
1
+ // Integration of the ORM with the framework (DI/kernel). The pure engine is
2
+ // `@/library/orm`; this layer adds the DI module, tokens, lifecycle
3
+ // and health check. The engine is re-exported in full for convenience.
4
+ export * from "../../library/orm";
5
+
6
+ export { ormModule, type OrmModuleConfig } from "./ormModule";
7
+ export { ormBazisConnect, type PostgresOrmConfigShape } from "./databaseConnector";
8
+ export { DATABASE_PROVIDER } from "./DATABASE_PROVIDER";
9
+ export { OrmConnectionLifecycle, OrmLifecycle, OrmProviderReadyLifecycle } from "./OrmLifecycle";
10
+ export { IRepository, repositoryFor } from "./repository";
11
+ export { registerRepositories } from "./registerRepositories";
12
+ export { paginate, type PageResult } from "./listQuery";
13
+
14
+ import { registerModuleMetadataExpander, type BazisModuleRef } from "../di";
15
+ import { OrmOwnedStoreAdmissionError, type DbContext } from "../../library/orm";
16
+ import { registerRepositoryEncapsulationHook } from "./encapsulationHook";
17
+ import { ormModule, type OrmModuleConfig } from "./ormModule";
18
+ import { readOwnedStoreRegistration, revalidateOwnedStoreRegistration } from "./ownedStoreContributions";
19
+
20
+ registerRepositoryEncapsulationHook();
21
+
22
+ /**
23
+ * Declarative `ormBazis` key for `@Module(...)`: a shorthand for
24
+ * `imports: [ormModule(config)]`. Accepts one config or an array. The DI core
25
+ * stays unaware of the ORM — this expander is registered here (side effect of
26
+ * importing `@/core/orm`) and run by `createContainer`.
27
+ *
28
+ * ```ts
29
+ * @Module({ ormBazis: { context: UsersDbContext, entities: [User], ensureCreated: true } })
30
+ * class UsersModule {}
31
+ * ```
32
+ */
33
+ // Augment the declaring file, not the "../di" re-export: re-export targets
34
+ // depend on program file order and silently stop merging in some projects.
35
+ declare module "../di/module/types/BazisModule" {
36
+ interface BazisModuleMetadata {
37
+ readonly ormBazis?: OrmModuleConfig<DbContext> | readonly OrmModuleConfig<DbContext>[];
38
+ }
39
+ }
40
+
41
+ interface CachedDeclarativeOrm {
42
+ readonly config: object;
43
+ readonly module: BazisModuleRef;
44
+ readonly registration?: ReturnType<typeof readOwnedStoreRegistration>;
45
+ readonly context: unknown;
46
+ readonly entities: readonly unknown[] | undefined;
47
+ readonly ownedStore: unknown;
48
+ readonly ensureCreated: boolean | undefined;
49
+ readonly migrateOnStart: boolean | undefined;
50
+ readonly runMigrationsOnStart: boolean | undefined;
51
+ readonly migrations: readonly unknown[] | undefined;
52
+ }
53
+ const declarativeCache = new WeakMap<object, readonly CachedDeclarativeOrm[]>();
54
+
55
+ function declaredOwnedStore(config: OrmModuleConfig<DbContext>): unknown {
56
+ const descriptor = Object.getOwnPropertyDescriptor(config, "ownedStore");
57
+ if (descriptor === undefined) return undefined;
58
+ if (!("value" in descriptor)) throw new OrmOwnedStoreAdmissionError("ORM_OWNED_STORE_IDENTITY_MISMATCH", "ORM_OWNED_STORE_IDENTITY_MISMATCH");
59
+ return descriptor.value;
60
+ }
61
+
62
+ registerModuleMetadataExpander((metadata): readonly BazisModuleRef[] => {
63
+ const orm = (metadata as { ormBazis?: OrmModuleConfig<DbContext> | readonly OrmModuleConfig<DbContext>[] }).ormBazis;
64
+ if (orm === undefined) {
65
+ return [];
66
+ }
67
+ const configs = Array.isArray(orm) ? orm : [orm];
68
+ const owned = configs.map((config) => declaredOwnedStore(config));
69
+ const cached = declarativeCache.get(metadata as object);
70
+ if (cached) {
71
+ if (cached.length !== configs.length || cached.some((entry, index) => entry.config !== configs[index])) throw new OrmOwnedStoreAdmissionError("ORM_OWNED_STORE_IDENTITY_MISMATCH", "ORM_OWNED_STORE_IDENTITY_MISMATCH");
72
+ for (let index = 0; index < cached.length; index += 1) {
73
+ const entry = cached[index]!;
74
+ const config = configs[index]!;
75
+ if (config.context !== entry.context
76
+ || config.entities?.length !== entry.entities?.length
77
+ || config.entities?.some((entity: unknown, entityIndex: number) => entity !== entry.entities?.[entityIndex])
78
+ || owned[index] !== entry.ownedStore
79
+ || config.ensureCreated !== entry.ensureCreated
80
+ || config.migrateOnStart !== entry.migrateOnStart
81
+ || config.runMigrationsOnStart !== entry.runMigrationsOnStart
82
+ || config.migrations !== entry.migrations) {
83
+ throw new OrmOwnedStoreAdmissionError("ORM_OWNED_STORE_IDENTITY_MISMATCH", "ORM_OWNED_STORE_IDENTITY_MISMATCH");
84
+ }
85
+ if (entry.registration) revalidateOwnedStoreRegistration(entry.registration);
86
+ }
87
+ return cached.map((entry) => entry.module);
88
+ }
89
+ const created = configs.map((config, index) => {
90
+ const module = ormModule(config);
91
+ return Object.freeze({ config: config as object, module, registration: readOwnedStoreRegistration(module), context: config.context, entities: config.entities === undefined ? undefined : Object.freeze([...config.entities]), ownedStore: owned[index], ensureCreated: config.ensureCreated, migrateOnStart: config.migrateOnStart, runMigrationsOnStart: config.runMigrationsOnStart, migrations: config.migrations });
92
+ });
93
+ if (owned.some((value) => value !== undefined)) declarativeCache.set(metadata as object, Object.freeze(created));
94
+ return created.map((entry) => entry.module);
95
+ });
@@ -0,0 +1,198 @@
1
+ import type { FilterRule, ListQuery } from "../../library/jsonapi";
2
+ import type { ColumnType, EntityModel, EntityQuery, FieldSelector, Operand, Predicate } from "../../library/orm";
3
+ import { OrmError } from "../../library/orm";
4
+
5
+ const MAX_ORM_PAGE_SIZE = 1_000;
6
+ const MAX_ORM_PAGE_OFFSET = 10_000_000;
7
+
8
+ /** Result page: the items and the total number of records (with filters applied). */
9
+ export interface PageResult<T> {
10
+ readonly items: readonly T[];
11
+ readonly total: number;
12
+ }
13
+
14
+ /**
15
+ * Applies a universal {@link ListQuery} (filters/sorting/paging) to an ORM query
16
+ * and returns a page of items together with the total number of records.
17
+ *
18
+ * `total` is computed by a separate `count()` with the same filters but without
19
+ * paging, so the client can build page navigation.
20
+ *
21
+ * Field names in the `ListQuery` were already validated against the allow list
22
+ * by the parser (`parseListQuery`), so they are applied directly here. The ORM
23
+ * engine always parameterizes SQL: user values never get into the SQL text.
24
+ *
25
+ * ```ts
26
+ * const { items, total } = await paginate(repo.query(), query);
27
+ * return buildListDocument(items, query, total, { basePath: "/api/users" });
28
+ * ```
29
+ */
30
+ export async function paginate<T extends object, R = T>(
31
+ query: EntityQuery<T, R>,
32
+ list: ListQuery,
33
+ ): Promise<PageResult<R>> {
34
+ validatePage(list);
35
+ const model = queryModel(query);
36
+ const hasFilter = list.filters.length > 0 || list.or.length > 0;
37
+ const filtered = hasFilter ? query.where((entity) => buildWhere(entity, list, model)) : query;
38
+
39
+ const total = await filtered.count();
40
+
41
+ let paged = filtered;
42
+ for (const sort of list.sort) {
43
+ paged =
44
+ sort.dir === "desc"
45
+ ? paged.orderByDescending((entity) => fieldOperand(entity, sort.field))
46
+ : paged.orderBy((entity) => fieldOperand(entity, sort.field));
47
+ }
48
+
49
+ // Pagination without every primary-key component as a tiebreaker is
50
+ // unstable: rows with equal sort values can move between pages. `key` is
51
+ // deliberately absent for composite models, so the ordered `primaryKey`
52
+ // metadata is the authority here.
53
+ for (const keyField of primaryKeyFields(model)) {
54
+ if (!list.sort.some((sort) => sort.field === keyField)) {
55
+ paged = paged.orderBy((entity) => fieldOperand(entity, keyField));
56
+ }
57
+ }
58
+
59
+ const items = await paged.skip(list.page.offset).take(list.page.limit).toList();
60
+ return { items, total };
61
+ }
62
+
63
+ function validatePage(list: ListQuery): void {
64
+ const { limit, offset, number, size } = list.page;
65
+ if (!Number.isSafeInteger(limit) || limit <= 0 || limit > MAX_ORM_PAGE_SIZE) {
66
+ throw new OrmError(`List page limit must be an integer between 1 and ${MAX_ORM_PAGE_SIZE}.`);
67
+ }
68
+ if (!Number.isSafeInteger(size) || size <= 0 || size > MAX_ORM_PAGE_SIZE) {
69
+ throw new OrmError(`List page size must be an integer between 1 and ${MAX_ORM_PAGE_SIZE}.`);
70
+ }
71
+ if (!Number.isSafeInteger(offset) || offset < 0 || offset > MAX_ORM_PAGE_OFFSET) {
72
+ throw new OrmError(`List page offset must be an integer between 0 and ${MAX_ORM_PAGE_OFFSET}.`);
73
+ }
74
+ if (!Number.isSafeInteger(number) || number <= 0) {
75
+ throw new OrmError("List page number must be a positive integer.");
76
+ }
77
+ }
78
+
79
+ function queryModel<T extends object, R>(query: EntityQuery<T, R>): EntityModel {
80
+ // EntityQuery intentionally keeps its model protected. The core integration
81
+ // reads the stable metadata contract for typed filters and deterministic order.
82
+ return (query as unknown as { readonly model: EntityModel }).model;
83
+ }
84
+
85
+ function primaryKeyFields(model: EntityModel): readonly string[] {
86
+ if (model.key.length === 0) {
87
+ throw new OrmError("List pagination requires an entity primary key.");
88
+ }
89
+ return model.key.map((property) => property.propertyName);
90
+ }
91
+
92
+ /**
93
+ * Builds the final predicate: `filters` (AND) and OR groups (`(g0) OR (g1) OR ...`)
94
+ * joined with AND: `filters AND (g0 OR g1 ...)`.
95
+ * Called only when there is at least one condition (see `hasFilter` in paginate).
96
+ */
97
+ function buildWhere<T extends object>(entity: FieldSelector<T>, list: ListQuery, model: EntityModel): Predicate {
98
+ const base = combineAnd(entity, list.filters, model);
99
+
100
+ let orCombined: Predicate | undefined;
101
+ for (const group of list.or) {
102
+ const groupPredicate = combineAnd(entity, group, model);
103
+ if (groupPredicate === undefined) {
104
+ continue;
105
+ }
106
+ orCombined = orCombined === undefined ? groupPredicate : orCombined.or(groupPredicate);
107
+ }
108
+
109
+ if (base === undefined) {
110
+ return orCombined as Predicate;
111
+ }
112
+ return orCombined === undefined ? base : base.and(orCombined);
113
+ }
114
+
115
+ function combineAnd<T extends object>(
116
+ entity: FieldSelector<T>,
117
+ rules: readonly FilterRule[],
118
+ model: EntityModel,
119
+ ): Predicate | undefined {
120
+ let combined: Predicate | undefined;
121
+ for (const rule of rules) {
122
+ const predicate = applyRule(fieldOperand(entity, rule.field), rule, model.propertyByName(rule.field)?.type);
123
+ combined = combined === undefined ? predicate : combined.and(predicate);
124
+ }
125
+ return combined;
126
+ }
127
+
128
+ function applyRule(operand: Operand, rule: FilterRule, type: ColumnType | undefined): Predicate {
129
+ switch (rule.op) {
130
+ case "eq":
131
+ return operand.eq(coerce(asScalar(rule.value), type));
132
+ case "ne":
133
+ return operand.ne(coerce(asScalar(rule.value), type));
134
+ case "gt":
135
+ return operand.gt(coerce(asScalar(rule.value), type));
136
+ case "gte":
137
+ return operand.gte(coerce(asScalar(rule.value), type));
138
+ case "lt":
139
+ return operand.lt(coerce(asScalar(rule.value), type));
140
+ case "lte":
141
+ return operand.lte(coerce(asScalar(rule.value), type));
142
+ case "like":
143
+ return operand.like(asScalar(rule.value));
144
+ case "contains":
145
+ return operand.contains(asScalar(rule.value));
146
+ case "startsWith":
147
+ return operand.startsWith(asScalar(rule.value));
148
+ case "endsWith":
149
+ return operand.endsWith(asScalar(rule.value));
150
+ case "in":
151
+ return operand.in(asArray(rule.value).map((value) => coerce(value, type)));
152
+ case "nin":
153
+ return operand.in(asArray(rule.value).map((value) => coerce(value, type))).not();
154
+ case "isNull":
155
+ return operand.isNull();
156
+ case "isNotNull":
157
+ return operand.isNotNull();
158
+ }
159
+ }
160
+
161
+ function fieldOperand<T extends object>(entity: FieldSelector<T>, field: string): Operand {
162
+ return (entity as Record<string, Operand>)[field] as Operand;
163
+ }
164
+
165
+ const NUMERIC = /^-?\d+(\.\d+)?$/;
166
+ const INTEGER = /^-?\d+$/;
167
+
168
+ /**
169
+ * The type is chosen by the column: text values must not go through Number, or
170
+ * leading zeros and precision are lost. The converter and dialect apply later.
171
+ */
172
+ function coerce(value: string, type: ColumnType | undefined): string | number | bigint | boolean {
173
+ if (type !== "integer" && type !== "real" && type !== "boolean") {
174
+ return value;
175
+ }
176
+ if (type === "boolean") {
177
+ if (value === "true") return true;
178
+ if (value === "false") return false;
179
+ }
180
+ if (value !== "" && NUMERIC.test(value)) {
181
+ const numeric = Number(value);
182
+ if (type === "integer" && INTEGER.test(value) && !Number.isSafeInteger(numeric)) {
183
+ return BigInt(value);
184
+ }
185
+ if (Number.isFinite(numeric)) {
186
+ return numeric;
187
+ }
188
+ }
189
+ return value;
190
+ }
191
+
192
+ function asScalar(value: string | readonly string[]): string {
193
+ return Array.isArray(value) ? (value[0] ?? "") : (value as string);
194
+ }
195
+
196
+ function asArray(value: string | readonly string[]): string[] {
197
+ return Array.isArray(value) ? [...value] : [value as string];
198
+ }
@@ -0,0 +1,173 @@
1
+ import { DI, HOSTED_SERVICE, singletonValue, type BazisModuleRef, type ProviderDefinition } from "../di";
2
+ import {
3
+ OrmError,
4
+ type DatabaseProvider,
5
+ type DbContext,
6
+ DbContextOptions,
7
+ type DbContextOptionsConfig,
8
+ type Migration,
9
+ } from "../../library/orm";
10
+ import { DATABASE_PROVIDER } from "./DATABASE_PROVIDER";
11
+ import { IRepository } from "./repository";
12
+ import { registerRepositories } from "./registerRepositories";
13
+ import {
14
+ buildOrmHealthCheck,
15
+ buildOrmHealthCheckFromToken,
16
+ buildOrmModuleProviders,
17
+ type OrmBuildConfig,
18
+ } from "./buildOrmProviders";
19
+ import { OrmConnectionLifecycle } from "./OrmLifecycle";
20
+ import { attachOrmGraphContribution, attachOwnedStoreRegistration } from "./ownedStoreContributions";
21
+
22
+ type EntityClass = new () => object;
23
+ type ContextClass<TContext extends DbContext> = new (options: DbContextOptions) => TContext;
24
+
25
+ /**
26
+ * The single ORM registration shape. One function, three scenarios depending
27
+ * on which fields are passed:
28
+ *
29
+ * - **Connection** (`{ provider }`, no `context`): a global module that
30
+ * publishes the shared {@link DATABASE_PROVIDER}. Created once at the root.
31
+ * - **Feature** (`{ context, entities }`, no `provider`): a context and its
32
+ * repositories connected to the shared {@link DATABASE_PROVIDER}.
33
+ * - **Standalone** (`{ context, entities, provider }`): a context with its own
34
+ * provider (tests, isolated modules).
35
+ *
36
+ * The provider is a value (the ORM `postgres(...)`), not a nested module.
37
+ */
38
+ export interface OrmModuleConfig<TContext extends DbContext> {
39
+ /** Context class (a DbContext subclass). Omitted in the "connection" mode. */
40
+ readonly context?: ContextClass<TContext>;
41
+ /** Entities mapped by this context. */
42
+ readonly entities?: readonly EntityClass[];
43
+ /**
44
+ * Database provider value (`postgres(...)`). Without it the context connects
45
+ * to the shared {@link DATABASE_PROVIDER} (feature mode).
46
+ */
47
+ readonly provider?: DatabaseProvider;
48
+ /** Validate entities before SaveChanges (default true). */
49
+ readonly validateOnSave?: boolean;
50
+ /** Create the schema at start (`CREATE TABLE IF NOT EXISTS`). Default false. */
51
+ readonly ensureCreated?: boolean;
52
+ /**
53
+ * Run the additive auto-migration at start for all context entities.
54
+ * Only the module decides how the schema is created. Default false.
55
+ */
56
+ readonly migrateOnStart?: boolean;
57
+ /** Versioned migrations (a compile-safe array). History is kept in `__BazisMigrations`. */
58
+ readonly migrations?: readonly Migration[];
59
+ /** Run `migrateVersioned` at start (default false). */
60
+ readonly runMigrationsOnStart?: boolean;
61
+ /** Retries on transient database errors in SaveChanges. */
62
+ readonly executionStrategy?: DbContextOptionsConfig["executionStrategy"];
63
+ /**
64
+ * Register the connection health check. Default: on for the "connection" and
65
+ * "standalone" modes, off for feature (the root turns it on).
66
+ */
67
+ readonly healthCheck?: boolean;
68
+ /** Register scoped `IRepository<T>` for the entities (default true). */
69
+ readonly registerRepositories?: boolean;
70
+ /** Modules holding the context's dependencies. */
71
+ readonly imports?: readonly BazisModuleRef[];
72
+ /** Approved owned PostgreSQL store descriptor; admission is owned by the core lifecycle. */
73
+ readonly ownedStore?: import("../../library/orm").OrmOwnedStoreDefinitionV1;
74
+ }
75
+
76
+ function defineFeatureOrmModule<TContext extends DbContext>(
77
+ config: OrmBuildConfig<TContext>,
78
+ providers: ProviderDefinition[],
79
+ ): BazisModuleRef {
80
+ const withRepositories = config.registerRepositories !== false;
81
+
82
+ return {
83
+ imports: config.imports,
84
+ providers,
85
+ exports: withRepositories ? [config.context, IRepository] : [config.context],
86
+ configure: withRepositories
87
+ ? (di) => registerRepositories(di, config.context, config.entities ?? [])
88
+ : undefined,
89
+ };
90
+ }
91
+
92
+ function defineConnectionModule(provider: DatabaseProvider, healthCheck: boolean): BazisModuleRef {
93
+ const providers: ProviderDefinition[] = [
94
+ singletonValue(DATABASE_PROVIDER, provider),
95
+ DI.singleton(
96
+ DI.factoryProvider(
97
+ HOSTED_SERVICE,
98
+ [DATABASE_PROVIDER],
99
+ (registered: DatabaseProvider) => new OrmConnectionLifecycle(registered),
100
+ ),
101
+ ),
102
+ ];
103
+ if (healthCheck) {
104
+ providers.push(buildOrmHealthCheck(provider));
105
+ }
106
+
107
+ return { global: true, providers, exports: [DATABASE_PROVIDER] };
108
+ }
109
+
110
+ /** Single ORM registration entry point (see {@link OrmModuleConfig}). */
111
+ export function ormModule<TContext extends DbContext>(config: OrmModuleConfig<TContext>): BazisModuleRef {
112
+ if (config.ownedStore !== undefined) {
113
+ if (!config.context || !config.entities || config.entities.length === 0 || config.provider || config.ensureCreated || config.migrateOnStart || config.runMigrationsOnStart || config.migrations !== undefined) {
114
+ throw new OrmError("ORM owned store requires a context and entities and cannot compose startup schema or migration authority.");
115
+ }
116
+ // Provider factories outlive this call. Keep their context/entity view
117
+ // registration-local so a caller cannot mutate the descriptor afterwards
118
+ // and silently change the runtime graph behind its owned receipt.
119
+ const buildConfig = Object.freeze({ ...config, context: config.context, entities: Object.freeze([...config.entities]) }) as OrmBuildConfig<TContext>;
120
+ const module = defineFeatureOrmModule(buildConfig, buildOrmModuleProviders(buildConfig, DATABASE_PROVIDER));
121
+ attachOwnedStoreRegistration(module, buildConfig.context, buildConfig.entities ?? [], config.ownedStore);
122
+ return module;
123
+ }
124
+ if (config.ensureCreated && (config.migrateOnStart || config.runMigrationsOnStart || (config.migrations?.length ?? 0) > 0)) throw new OrmError("ensureCreated is mutually exclusive with ORM migration startup options.");
125
+ if (config.ensureCreated && config.provider?.name === "postgres" && config.context) throw new OrmError("PostgreSQL ensureCreated requires the shared DATABASE_PROVIDER from @Infra.");
126
+ // "Connection" mode: a provider only, no context.
127
+ if (!config.context) {
128
+ if (!config.provider) {
129
+ throw new OrmError("ormModule requires a `provider` (connection) and/or a `context` (feature).");
130
+ }
131
+ return defineConnectionModule(config.provider, config.healthCheck !== false);
132
+ }
133
+
134
+ const buildConfig = config as OrmBuildConfig<TContext>;
135
+
136
+ // Standalone: a context with its own provider value.
137
+ if (config.provider) {
138
+ // Only the static DbContextOptions are built eagerly here. Schema lifecycle
139
+ // flags and migrations are read at resolve time, because an owned-store graph
140
+ // may replace them with a container-local snapshot.
141
+ const standaloneOptions = new DbContextOptions({
142
+ provider: config.provider,
143
+ entities: config.entities ?? [],
144
+ validateOnSave: config.validateOnSave,
145
+ executionStrategy: config.executionStrategy,
146
+ });
147
+ const registration = Object.freeze({});
148
+ const providers = buildOrmModuleProviders(buildConfig, config.provider, registration, standaloneOptions);
149
+ if (buildConfig.healthCheck !== false) {
150
+ providers.push(buildOrmHealthCheck(config.provider));
151
+ }
152
+ const module = defineFeatureOrmModule(buildConfig, providers);
153
+ attachOrmGraphContribution(module, buildConfig.context, buildConfig.entities ?? [], config, registration);
154
+ return module;
155
+ }
156
+
157
+ // Feature: a context on the shared DATABASE_PROVIDER.
158
+ // The source config remains the ordinary-only compatibility path. When an
159
+ // owned store is present in this container, the graph compiler snapshots it
160
+ // once and the factories below resolve that same opaque registration view.
161
+ const registration = Object.freeze({});
162
+ const providers = buildOrmModuleProviders(buildConfig, DATABASE_PROVIDER, registration);
163
+ if (config.healthCheck === true) {
164
+ providers.push(buildOrmHealthCheckFromToken(DATABASE_PROVIDER));
165
+ }
166
+ const module = defineFeatureOrmModule(buildConfig, providers);
167
+ // `registration` is deliberately per ormModule call, not a token or public
168
+ // identity. It links this factory to its container-local graph snapshot.
169
+ attachOrmGraphContribution(module, buildConfig.context, buildConfig.entities ?? [], config, registration);
170
+ return module;
171
+ }
172
+
173
+ export { DATABASE_PROVIDER };