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,195 @@
1
+ import { OrmError } from "../errors";
2
+ import { renderPostgresOnConflictDoNothing, renderPostgresSkipLocked } from "../Providers/PostgresDialect";
3
+ import type { EntityModel, PropertyModel } from "../Metadata/types";
4
+ import type { SqlDialect, SqlParam } from "../Providers/types";
5
+ import { encodeProperty } from "../Providers/propertyConversion";
6
+ import type { Condition } from "./conditions";
7
+ import type { QueryPlan } from "./QueryPlan";
8
+
9
+ export interface CompiledSql {
10
+ readonly sql: string;
11
+ readonly params: SqlParam[];
12
+ }
13
+ type ConditionValueEncoder = (property: PropertyModel, value: unknown) => SqlParam;
14
+
15
+ /** Cache of the quoted column list per (model, dialect), built once. */
16
+ const columnListCache = new WeakMap<EntityModel, Map<string, string>>();
17
+
18
+ /** Quoted `"a", "b", ...` list of all entity columns (memoized). */
19
+ export function quotedColumnList(model: EntityModel, dialect: SqlDialect): string {
20
+ let byDialect = columnListCache.get(model);
21
+ if (!byDialect) {
22
+ byDialect = new Map();
23
+ columnListCache.set(model, byDialect);
24
+ }
25
+ let list = byDialect.get(dialect.name);
26
+ if (list === undefined) {
27
+ list = model.properties.map((property) => dialect.quoteId(property.columnName)).join(", ");
28
+ byDialect.set(dialect.name, list);
29
+ }
30
+ return list;
31
+ }
32
+
33
+ /**
34
+ * Translates a query plan into parameterized SQL. Values go only into the
35
+ * parameter array (no concatenation of user data).
36
+ */
37
+ export class SqlTranslator {
38
+ constructor(
39
+ private readonly model: EntityModel,
40
+ private readonly dialect: SqlDialect,
41
+ ) {}
42
+
43
+ /** SELECT of all columns (or a projection) with WHERE/ORDER/LIMIT/OFFSET. */
44
+ selectAll(plan: QueryPlan): CompiledSql {
45
+ const params: SqlParam[] = [];
46
+ const columns =
47
+ plan.projections.length > 0
48
+ ? plan.projections
49
+ .map(({ alias, property }) => {
50
+ const prop = this.requireProperty(property);
51
+ return `${this.dialect.quoteId(prop.columnName)} AS ${this.dialect.quoteId(alias)}`;
52
+ })
53
+ .join(", ")
54
+ : quotedColumnList(this.model, this.dialect);
55
+ let sql = `SELECT ${columns} FROM ${this.dialect.qualifyTable(this.model)}`;
56
+ sql += this.whereClause(plan, params);
57
+ sql += this.orderClause(plan);
58
+ sql += this.limitClause(plan, params);
59
+ if (plan.rowLock) {
60
+ sql += this.dialect.rowLockClause(plan.rowLock);
61
+ if (plan.skipLocked) sql += renderPostgresSkipLocked(this.dialect);
62
+ }
63
+ return { sql, params };
64
+ }
65
+
66
+ /** SELECT COUNT(*) with the same filters (without order/limit). */
67
+ selectCount(plan: QueryPlan): CompiledSql {
68
+ const params: SqlParam[] = [];
69
+ let sql = `SELECT COUNT(*) AS count FROM ${this.dialect.qualifyTable(this.model)}`;
70
+ sql += this.whereClause(plan, params);
71
+ return { sql, params };
72
+ }
73
+
74
+ /** Private immediate-DML renderers; the public query DSL remains unchanged. */
75
+ immediateUpdate(values: readonly { readonly property: PropertyModel; readonly value: SqlParam }[], conditions: readonly Condition[], encode: ConditionValueEncoder): CompiledSql {
76
+ const params: SqlParam[] = values.map((value) => value.value);
77
+ const assignments = values.map((value, index) => `${this.dialect.quoteId(value.property.columnName)} = ${this.dialect.parameter(index)}`).join(", ");
78
+ return { sql: `UPDATE ${this.dialect.qualifyTable(this.model)} SET ${assignments}${this.immediateWhere(conditions, params, encode)}`, params };
79
+ }
80
+
81
+ immediateDelete(conditions: readonly Condition[], encode: ConditionValueEncoder): CompiledSql {
82
+ const params: SqlParam[] = [];
83
+ return { sql: `DELETE FROM ${this.dialect.qualifyTable(this.model)}${this.immediateWhere(conditions, params, encode)}`, params };
84
+ }
85
+
86
+ private immediateWhere(conditions: readonly Condition[], params: SqlParam[], encode: ConditionValueEncoder): string {
87
+ if (conditions.length === 0) return "";
88
+ return ` WHERE ${conditions.map((condition) => this.condition(condition, params, encode)).join(" AND ")}`;
89
+ }
90
+
91
+ immediateInsert(values: readonly { readonly property: PropertyModel; readonly value: SqlParam }[], conflictColumns: readonly string[]): CompiledSql {
92
+ const params = values.map((value) => value.value);
93
+ const columns = values.map((value) => this.dialect.quoteId(value.property.columnName)).join(", ");
94
+ const placeholders = values.map((_value, index) => this.dialect.parameter(index)).join(", ");
95
+ return { sql: `INSERT INTO ${this.dialect.qualifyTable(this.model)} (${columns}) VALUES (${placeholders})${renderPostgresOnConflictDoNothing(this.dialect, conflictColumns)}`, params };
96
+ }
97
+
98
+ private whereClause(plan: QueryPlan, params: SqlParam[], encode: ConditionValueEncoder = (property, value) => encodeProperty(property, value, this.dialect)): string {
99
+ const parts: string[] = [];
100
+ if (!plan.ignoreQueryFilters) {
101
+ for (const filter of this.model.queryFilters) {
102
+ parts.push(this.condition(filter, params, encode));
103
+ }
104
+ if (this.model.softDeleteProperty) {
105
+ parts.push(this.condition({ kind: "null", property: this.model.softDeleteProperty, negated: false }, params, encode));
106
+ }
107
+ }
108
+ for (const condition of plan.conditions) {
109
+ parts.push(this.condition(condition, params, encode));
110
+ }
111
+ if (parts.length === 0) {
112
+ return "";
113
+ }
114
+ return ` WHERE ${parts.join(" AND ")}`;
115
+ }
116
+
117
+ private orderClause(plan: QueryPlan): string {
118
+ if (plan.orders.length === 0) {
119
+ return "";
120
+ }
121
+ const parts = plan.orders.map((order) => {
122
+ const column = this.requireProperty(order.property).columnName;
123
+ return `${this.dialect.quoteId(column)}${order.descending ? " DESC" : " ASC"}`;
124
+ });
125
+ return ` ORDER BY ${parts.join(", ")}`;
126
+ }
127
+
128
+ private limitClause(plan: QueryPlan, params: SqlParam[]): string {
129
+ let sql = "";
130
+ if (plan.limit !== undefined) {
131
+ sql += ` LIMIT ${this.dialect.parameter(params.length)}`;
132
+ params.push(plan.limit);
133
+ }
134
+ if (plan.offset !== undefined) {
135
+ sql += ` OFFSET ${this.dialect.parameter(params.length)}`;
136
+ params.push(plan.offset);
137
+ }
138
+ return sql;
139
+ }
140
+
141
+ private condition(condition: Condition, params: SqlParam[], encode: ConditionValueEncoder): string {
142
+ switch (condition.kind) {
143
+ case "compare": {
144
+ const property = this.requireProperty(condition.property);
145
+ const placeholder = this.dialect.parameter(params.length);
146
+ params.push(encode(property, condition.value));
147
+ // startsWith/endsWith/contains escape wildcards with `\`; this works
148
+ // only with an explicit `ESCAPE '\'` (otherwise `%`/`_` stay wildcards).
149
+ const escape = condition.escaped ? " ESCAPE '\\'" : "";
150
+ return `${this.dialect.quoteId(property.columnName)} ${condition.op} ${placeholder}${escape}`;
151
+ }
152
+ case "in": {
153
+ const property = this.requireProperty(condition.property);
154
+ if (condition.values.length === 0) {
155
+ return "0 = 1"; // an empty IN is always false
156
+ }
157
+ const placeholders = condition.values.map((value) => {
158
+ const placeholder = this.dialect.parameter(params.length);
159
+ params.push(encode(property, value));
160
+ return placeholder;
161
+ });
162
+ return `${this.dialect.quoteId(property.columnName)} IN (${placeholders.join(", ")})`;
163
+ }
164
+ case "tuples": {
165
+ if (condition.properties.length === 0 || condition.values.length === 0) return "0 = 1";
166
+ return `(${condition.values.map((tuple) => {
167
+ if (tuple.length !== condition.properties.length) throw new OrmError("Tuple predicate component count mismatch.");
168
+ return `(${tuple.map((value, index) => { const property = this.requireProperty(condition.properties[index]!); const placeholder = this.dialect.parameter(params.length); params.push(encode(property, value)); return `${this.dialect.quoteId(property.columnName)} = ${placeholder}`; }).join(" AND ")})`;
169
+ }).join(" OR ")})`;
170
+ }
171
+ case "null": {
172
+ const property = this.requireProperty(condition.property);
173
+ return `${this.dialect.quoteId(property.columnName)} IS ${condition.negated ? "NOT " : ""}NULL`;
174
+ }
175
+ case "and":
176
+ case "or": {
177
+ const left = this.condition(condition.left, params, encode);
178
+ const right = this.condition(condition.right, params, encode);
179
+ return `(${left} ${condition.kind === "and" ? "AND" : "OR"} ${right})`;
180
+ }
181
+ case "not":
182
+ return `NOT (${this.condition(condition.inner, params, encode)})`;
183
+ }
184
+ }
185
+
186
+ private requireProperty(propertyName: string): PropertyModel {
187
+ const property = this.model.propertyByName(propertyName);
188
+ if (!property) {
189
+ throw new OrmError(
190
+ `Property "${propertyName}" is not mapped on entity "${this.model.name}". Did you forget @Column()?`,
191
+ );
192
+ }
193
+ return property;
194
+ }
195
+ }
@@ -0,0 +1,127 @@
1
+ /**
2
+ * AST of WHERE conditions and a Proxy DSL to build it.
3
+ *
4
+ * Instead of parsing JS lambdas (unsafe and slow), the predicate is built
5
+ * through a Proxy: `x => x.age.gt(18).and(x.name.startsWith("A"))`. `x.age`
6
+ * returns a column operand, comparison methods produce AST nodes, and
7
+ * `.and()/.or()/.not()` combine them. No user strings in the SQL, only parameters.
8
+ *
9
+ * Note: `&&`/`||` are not intercepted; use `.and()/.or()`.
10
+ */
11
+
12
+ export type CompareOp = "=" | "<>" | ">" | ">=" | "<" | "<=" | "LIKE";
13
+
14
+ export type Condition =
15
+ | {
16
+ readonly kind: "compare";
17
+ readonly property: string;
18
+ readonly op: CompareOp;
19
+ readonly value: unknown;
20
+ /** For LIKE from startsWith/endsWith/contains: add `ESCAPE '\'`. */
21
+ readonly escaped?: boolean;
22
+ }
23
+ | { readonly kind: "in"; readonly property: string; readonly values: readonly unknown[] }
24
+ | { readonly kind: "tuples"; readonly properties: readonly string[]; readonly values: readonly (readonly unknown[])[] }
25
+ | { readonly kind: "null"; readonly property: string; readonly negated: boolean }
26
+ | { readonly kind: "and" | "or"; readonly left: Condition; readonly right: Condition }
27
+ | { readonly kind: "not"; readonly inner: Condition };
28
+
29
+ /** Predicate result: a wrapper over an AST node with logical combinators. */
30
+ export class Predicate {
31
+ constructor(readonly node: Condition) {}
32
+
33
+ and(other: Predicate): Predicate {
34
+ return new Predicate({ kind: "and", left: this.node, right: other.node });
35
+ }
36
+ or(other: Predicate): Predicate {
37
+ return new Predicate({ kind: "or", left: this.node, right: other.node });
38
+ }
39
+ not(): Predicate {
40
+ return new Predicate({ kind: "not", inner: this.node });
41
+ }
42
+ }
43
+
44
+ /** Column operand: the entry point for building conditions on a property. */
45
+ export class Operand<T = unknown> {
46
+ constructor(readonly property: string) {}
47
+
48
+ private compare(op: CompareOp, value: unknown): Predicate {
49
+ return new Predicate({ kind: "compare", property: this.property, op, value });
50
+ }
51
+
52
+ /** LIKE with escaped wildcards (needs `ESCAPE '\'` in SQL). */
53
+ private likeEscaped(pattern: string): Predicate {
54
+ return new Predicate({ kind: "compare", property: this.property, op: "LIKE", value: pattern, escaped: true });
55
+ }
56
+
57
+ eq(value: T): Predicate {
58
+ return value === null ? this.isNull() : this.compare("=", value);
59
+ }
60
+ ne(value: T): Predicate {
61
+ return value === null ? this.isNotNull() : this.compare("<>", value);
62
+ }
63
+ gt(value: OrderedValue<T>): Predicate {
64
+ return this.compare(">", value);
65
+ }
66
+ gte(value: OrderedValue<T>): Predicate {
67
+ return this.compare(">=", value);
68
+ }
69
+ lt(value: OrderedValue<T>): Predicate {
70
+ return this.compare("<", value);
71
+ }
72
+ lte(value: OrderedValue<T>): Predicate {
73
+ return this.compare("<=", value);
74
+ }
75
+ like(pattern: TextValue<T>): Predicate {
76
+ return this.compare("LIKE", pattern);
77
+ }
78
+ startsWith(value: TextValue<T>): Predicate {
79
+ return this.likeEscaped(`${escapeLike(value)}%`);
80
+ }
81
+ endsWith(value: TextValue<T>): Predicate {
82
+ return this.likeEscaped(`%${escapeLike(value)}`);
83
+ }
84
+ contains(value: TextValue<T>): Predicate {
85
+ return this.likeEscaped(`%${escapeLike(value)}%`);
86
+ }
87
+ in(values: readonly T[]): Predicate {
88
+ return new Predicate({ kind: "in", property: this.property, values: [...values] });
89
+ }
90
+ isNull(): Predicate {
91
+ return new Predicate({ kind: "null", property: this.property, negated: false });
92
+ }
93
+ isNotNull(): Predicate {
94
+ return new Predicate({ kind: "null", property: this.property, negated: true });
95
+ }
96
+ }
97
+
98
+ /** `%` and `_` in startsWith/endsWith/contains must not act as wildcards. */
99
+ function escapeLike(value: string): string {
100
+ return value.replace(/[%_\\]/g, (char) => `\\${char}`);
101
+ }
102
+
103
+ type OrderedValue<T> = unknown extends T ? unknown
104
+ : NonNullable<T> extends string | number | bigint | Date ? NonNullable<T> : never;
105
+ type TextValue<T> = unknown extends T ? string : NonNullable<T> extends string ? string : never;
106
+
107
+ /** Field selector (for where/orderBy). Returns a typed property operand. */
108
+ export type FieldSelector<T> = {
109
+ readonly [K in keyof T]-?: Operand<T[K]>;
110
+ };
111
+
112
+ /** Predicate function passed to where. */
113
+ export type PredicateFn<T> = (entity: FieldSelector<T>) => Predicate;
114
+
115
+ /** Sorting needs only the column name, whatever the type of its value. */
116
+ export type KeySelectorFn<T> = (entity: FieldSelector<T>) => Pick<Operand, "property">;
117
+
118
+ const FIELD_PROXY: ProxyHandler<object> = {
119
+ get(_target, property): Operand {
120
+ return new Operand(String(property));
121
+ },
122
+ };
123
+
124
+ /** Creates a Proxy selector of the entity fields. */
125
+ export function fieldSelector<T>(): FieldSelector<T> {
126
+ return new Proxy({}, FIELD_PROXY) as FieldSelector<T>;
127
+ }
@@ -0,0 +1,39 @@
1
+ import type { EntityModel } from "../Metadata/types";
2
+ import type { Row, SqlDialect } from "../Providers/types";
3
+ import { decodeProperty } from "../Providers/propertyConversion";
4
+
5
+ /**
6
+ * Hydrates a result row into an entity instance. A real class instance is
7
+ * created (the constructor is called without arguments), then columns are
8
+ * mapped to properties with reverse type conversion (through the dialect).
9
+ */
10
+ export function materialize<T extends object>(model: EntityModel, row: Row, dialect: SqlDialect): T {
11
+ const entity = new model.ctor() as Record<string, unknown>;
12
+ for (const property of model.properties) {
13
+ if (property.columnName in row) {
14
+ entity[property.propertyName] = decodeProperty(property, row[property.columnName], dialect);
15
+ }
16
+ }
17
+ return entity as T;
18
+ }
19
+
20
+ /** Projects a row into a plain object by the alias -> property list. */
21
+ export function materializeProjection(
22
+ model: EntityModel,
23
+ row: Row,
24
+ dialect: SqlDialect,
25
+ projections: readonly { readonly alias: string; readonly property: string }[],
26
+ ): Record<string, unknown> {
27
+ const result: Record<string, unknown> = {};
28
+ for (const { alias, property: propertyName } of projections) {
29
+ const property = model.propertyByName(propertyName);
30
+ if (!property) {
31
+ continue;
32
+ }
33
+ const column = alias in row ? alias : property.columnName;
34
+ if (column in row) {
35
+ result[alias] = decodeProperty(property, row[column], dialect);
36
+ }
37
+ }
38
+ return result;
39
+ }
@@ -0,0 +1,256 @@
1
+ # ORM (`bazis` / `bazis/library/orm`)
2
+
3
+ The ORM uses TC39 decorators, `DbContext`/`DbSet`, a scoped Unit of Work and
4
+ parameterized SQL without runtime npm dependencies.
5
+
6
+ ## Queries and saving
7
+
8
+ ```ts
9
+ // db.users is the DbSet of a model with the fields tenantId:string and age:number.
10
+ const adults = await db.users
11
+ .where(user => user.tenantId.eq("team-a").and(user.age.gte(18)))
12
+ .orderBy(user => user.id)
13
+ .take(20)
14
+ .asNoTracking()
15
+ .toList();
16
+ ```
17
+
18
+ The field type is kept in Operand<T>: age.eq("18") and age.contains("18") are
19
+ TypeScript errors. eq/ne/in take the field type; strings support LIKE/contains,
20
+ ordered values gt/gte/lt/lte. For null there are isNull/isNotNull, and eq(null) is
21
+ allowed on nullable fields. Dynamic models with unknown keep the dynamic API.
22
+
23
+ Conditions are combined with .and/.or/.not. JavaScript `&&`, `||` and `!` create no
24
+ SQL conditions. `di:generate` reports such operations over the Predicate type in the
25
+ sources of the chosen target and stops generation before files are replaced. This is
26
+ a build check: running JS/any or sources without codegen does not get this guarantee.
27
+ After changing a query, run `di:generate` and the TypeScript check.
28
+
29
+ The write boundary is DbContext.saveChanges(), which saves all changes of the context.
30
+ IRepository.saveChanges() stays an alias of the same operation. For new services,
31
+ inject the domain DbContext so the save scope is visible in the code.
32
+ [More about repositories](Repository/README.md).
33
+
34
+ ## PostgreSQL exact ensureCreated
35
+
36
+ A production PostgreSQL schema is described once with the explicit
37
+ `ormBazis.entities` list and entity decorators. The shared connection belongs to
38
+ `@Infra`; a feature does not create its own PostgreSQL provider.
39
+
40
+ ```ts
41
+ import { Column, DbContext, Entity, ForeignKey, Infra, Key, Module, Schema, ormBazisConnect } from "bazis";
42
+
43
+ @Schema("billing")
44
+ @Entity({ table: "orders" })
45
+ class Order {
46
+ @Key(["tenantId", "orderId"], { name: "pk_orders" })
47
+ @Column({ type: "text" }) tenantId = "";
48
+ @Column({ type: "text" }) orderId = "";
49
+ }
50
+
51
+ @Schema("billing")
52
+ @Entity({ table: "lines" })
53
+ @ForeignKey(() => Order, { name: "fk_lines_order", properties: ["tenantId", "orderId"] })
54
+ class OrderLine {
55
+ @Key(["tenantId", "lineId"]) @Column({ type: "text" }) tenantId = "";
56
+ @Column({ type: "text" }) lineId = "";
57
+ @Column({ type: "text" }) orderId = "";
58
+ }
59
+
60
+ class BillingContext extends DbContext {}
61
+ @Infra({ db: ormBazisConnect(dbConfig) }) class AppInfra {}
62
+ @Module({ ormBazis: { context: BillingContext, entities: [Order, OrderLine], ensureCreated: true } })
63
+ class BillingModule {}
64
+ ```
65
+
66
+ `@Key()` declares a single primary-key component. `@Key(["a", "b"])`
67
+ declares the sole ordered composite key tuple; `@UUID()` declares a v4 UUID
68
+ key generated by PostgreSQL, and `@UUID({ version: "v7" })` a time-ordered v7
69
+ key that the ORM assigns before INSERT (native `uuid` column, no default). `@ForeignKey`, `@Index`, `@Check` and `@Schema` contribute to the same
70
+ expected physical schema.
71
+
72
+ For PostgreSQL, `ensureCreated()` acquires sorted advisory locks per physical
73
+ schema and runs all catalog reads and DDL on one reserved-session transaction:
74
+
75
+ 1. classifies the complete declared PostgreSQL diff before any DDL;
76
+ 2. creates missing schemas and whole missing tables, or applies only safe additions;
77
+ 3. safe existing-table additions are nullable columns, non-null columns with a closed literal `@Column({ default })`, immediate CHECK/FK and ordinary/unique B-tree indexes;
78
+ 4. re-introspect and exact-verify before commit.
79
+
80
+ Column order is ignored, but type/nullability/default/generation and named,
81
+ ordered PK/FK/index/CHECK contracts are exact. A type/null/default/generation/
82
+ PK change, rename/drop, generated/UUID existing-table column, `NOT NULL`
83
+ column without a usable literal default, or changed/unknown object stops startup
84
+ with `ORM_SCHEMA_MIGRATION_REQUIRED` and executes zero DDL. No backfill,
85
+ rebuild, `IF NOT EXISTS` or concurrent index build is performed.
86
+
87
+ `SchemaMigrationRequiredError` and `SchemaVerificationError` include the table,
88
+ object, difference code, expected ORM state and actual database state in `message`.
89
+ The existing `code` and structured `verification.differences` remain available.
90
+ For example, an extra column produces:
91
+
92
+ ```text
93
+ PostgreSQL schema change requires an explicit migration.
94
+ - Table "public"."dm_table", object "bazis_drill_unexpected": column exists in the database but is absent from the ORM model (column.unexpected); expected (ORM): absent; actual (database): present.
95
+ Check the application version and target database. Align the ORM model and database schema; apply an explicit migration if a database change is intended.
96
+ ```
97
+
98
+ These diagnostics use the verifier's safe descriptors. Literal defaults and CHECK
99
+ expressions remain represented by SHA-256 fingerprints; SQL, driver errors and row
100
+ values are not added to the message. The message alone does not establish that the
101
+ target database is outdated or should be modified: first check the application and
102
+ database pairing. `Bazis.run()` prints the redacted nested error details without
103
+ console depth collapsing them to `[Object ...]`.
104
+
105
+ `ColumnOptions.default` is a closed physical literal (`null | boolean | number |
106
+ string`), not SQL and not an entity initializer. It is supported only by the
107
+ PostgreSQL exact path.
108
+
109
+ Direct `context.database.ensureCreated()` uses the same PostgreSQL admission
110
+ engine.
111
+
112
+ ## Other ORM capabilities
113
+
114
+ - `where`, ordering, pagination, include and typed scalar/composite lookup;
115
+ - snapshot tracking and transactional `saveChanges()`;
116
+ - declarative FK/index/CHECK metadata;
117
+ - explicit additive `migrate()` and legacy versioned `Migration[]` paths.
118
+
119
+ The additive migration paths are separate from PostgreSQL exact admission.
120
+
121
+ ## Saving and retrying after an error
122
+
123
+ `saveChanges()` inside `database.transaction()` joins the current transaction. An
124
+ error of such a save forbids its COMMIT, even if the calling code caught the
125
+ exception. To recover inside an outer transaction, use `transactionScope()` with a
126
+ savepoint. Automatic save retries inside an active transaction are disabled.
127
+
128
+ A unique constraint violation (SQLSTATE 23505) in `saveChanges()` arrives as
129
+ `UniqueViolationError` (a `DbUpdateError` subclass) with the `constraint` and
130
+ `table` fields and the original driver error in `cause`; the changes of this save are
131
+ rolled back. Catch it to answer 409 without a check up front: the index decides, so
132
+ there is no race. Other driver errors are not wrapped.
133
+
134
+ If there is no reliable answer after COMMIT is sent, the ORM throws `DbUpdateError`
135
+ with `code: "ORM_TRANSACTION_OUTCOME_UNKNOWN"`. `ExecutionStrategy` and `withRetry`
136
+ do not retry such an operation, including a user `isTransient`.
137
+ All contexts that saved changes in this transaction block further `saveChanges()`.
138
+ First reconcile the result against the database data, then continue in a new
139
+ `DbContext`. The received keys are kept for the reconciliation; having a key or the
140
+ `Unchanged` state does not prove COMMIT. User `afterCommit` and `afterRollback` are
141
+ not called on an unknown outcome.
142
+
143
+ After a confirmed rollback the keys and tracking are restored. A confirmed COMMIT
144
+ with a handler error keeps the existing `PostCommitError` contract.
145
+
146
+ The native `Bun.SQL Query.cancel()` on the pinned Bun 1.4.0 did not confirm
147
+ cancelling an already running query: six checks on PostgreSQL 17.11 left the query
148
+ active after 1.5 seconds. `cancelled === true` alone does not prove cancellation.
149
+ On leaving `transactionScope()` with an unfinished operation the ORM forbids COMMIT.
150
+ If an unfinished PostgreSQL query remains, the ORM forbids further work on this
151
+ reservation and calls `pg_cancel_backend` through a separate service Bun.SQL
152
+ connection. It waits for the cancel command's response, the completion of the
153
+ original native queries, a confirmed ROLLBACK and a readback of the same backend
154
+ identity. After that the connection can be reused.
155
+ The broken `Query.cancel()` is not used on this path. For unfinished user JS without
156
+ SQL a 5-second wait limit is kept; an explicit cancellation signal also interrupts that wait.
157
+
158
+ A long query inside the callback can be cancelled from outside:
159
+
160
+ ```ts
161
+ await db.transactionScope(async (tx) => {
162
+ await tx.databaseTime();
163
+ await db.database.querySqlRaw("SELECT pg_sleep({0})", 30);
164
+ }, { signal: AbortSignal.timeout(1_000) });
165
+ ```
166
+
167
+ An already aborted signal rejects the call before BEGIN. When an active scope is
168
+ cancelled, new and deferred operations are blocked. Server cancellation rolls back the
169
+ whole physical transaction, including the outer one when a nested scope is cancelled;
170
+ a caught error does not allow its COMMIT. After the callback and its operations
171
+ finish, control passes to the provider: its operation timeout applies until the COMMIT
172
+ response. The signal is passed to `reserve({ signal })`; a connection handed out late
173
+ is closed without BEGIN. `options.timeoutMs` bounds waiting for a connection, BEGIN,
174
+ the callback, SQL and COMMIT; the default is the provider's `operationTimeoutMs`
175
+ (30 seconds). Confirming a cancellation has a separate `cancellationTimeoutMs`
176
+ budget (5 seconds), and releasing the resource one more such budget. This is not a
177
+ promise to finish the whole call within `timeoutMs`. User afterCommit/afterRollback
178
+ have their own execution time; a late cancellation does not change a confirmed
179
+ COMMIT. Arbitrary JS is not stopped, but its late calls into the ORM are forbidden.
180
+
181
+ If the SQL completion and the rollback on the same backend are not confirmed, the ORM
182
+ returns `ORM_TRANSACTION_OUTCOME_UNKNOWN` with `phase: "cancellation"`. The user
183
+ rollback callback is not called. All contexts included in the scope block new SQL
184
+ and saves; reconcile the result through a new context. A lost COMMIT response keeps
185
+ `phase: "commit"`. There is no automatic retry.
186
+
187
+ With an explicit `cancellationMode: "close"` the former policy of closing and
188
+ checking that the backend is gone is kept. In this mode on Bun 1.4.0 **fast
189
+ cancellation over TLS is not confirmed**: the connection-close Promise settles, but
190
+ SQL on the server may stay active. In a check of a 10-second query the backend stayed
191
+ active after five seconds; the ORM returned an unknown outcome within its budget. With
192
+ an explicitly configured server `statementTimeoutMs: 600` a separate check ended with
193
+ a confirmed rollback in 641 ms. The server limit counts from the start of the SQL, so
194
+ it does not guarantee such a delay from any later abort.
195
+
196
+ `postgres({ operationTimeoutMs, cancellationTimeoutMs, cancellationMode, maxPendingOperations,
197
+ serverTimeouts, onOperation })` configures the provider policy.
198
+ `cancellationMode` takes `server` (the default) or `close`. The server mode uses a
199
+ lazy service pool max=1 in addition to the working pool, with the same credentials
200
+ and TLS. Both pools close together with the provider. Borrowed advisory locks are
201
+ released explicitly after a confirmed rollback, before the connection is returned.
202
+ After a forced close the pool checks later reservations with SELECT 1 before user
203
+ work. A native connection timeout on admission allows one retry within the shared
204
+ deadline; business SQL, the callback and COMMIT are not retried. The check adds one
205
+ round trip after such a failure until the provider is recreated; a regular confirmed
206
+ server cancellation does not enable it.
207
+
208
+ The SQL check of PID/backend_start/query_start is not atomic against the system
209
+ reusing the PID; this API does not give the PID+secret guarantee of the protocol.
210
+ `serverTimeouts` supports `statementTimeoutMs`, `lockTimeoutMs`,
211
+ `idleInTransactionTimeoutMs`, `transactionTimeoutMs` (the last one is PostgreSQL 17+).
212
+ The settings are applied with SET LOCAL and checked at BEGIN; by default the server
213
+ limits do not change. Root query/execute and ping have a client deadline, but the
214
+ SET LOCAL profile applies only inside transactions. Unfinished native operations hold
215
+ a slot until they actually finish; the default limit is 256, with a bounded reserve
216
+ for cleanup. `statistics()` and `onOperation` show the number of such operations,
217
+ durations and unknown outcomes without SQL or parameters.
218
+
219
+ The ORM connector passes the pool, connection and TLS settings and the listed limits.
220
+ Units, validation and a connection example are in the
221
+ [core/orm passport](../../core/orm/MODULE.md).
222
+
223
+ Results of the current server mode, real AbortSignal TCP/TLS scenarios and binary
224
+ qualification are in the [integration report](https://github.com/asus97178/osnova/blob/33a4513a56abb43a1694e7a6e56373187b928a70/docs/audits/orm-server-cancel-integration-2026-09-14.md).
225
+ Earlier physical checks of the close mode confirmed cancellation in 395–402 ms,
226
+ rollback, key restoration, advisory lock release, an unaffected neighboring active
227
+ query in the same pool and further saves. This is a measurement of a local run, not a
228
+ deadline for any environment. [Fix and evidence](https://github.com/asus97178/osnova/blob/33a4513a56abb43a1694e7a6e56373187b928a70/docs/audits/orm-2026-09-14-cancellation-fix.md),
229
+ [cancellation contract](MODULE.md). A direct `Bun.SQL Query.cancel()` call stays a
230
+ separate failed gate from the [earlier qualification](https://github.com/asus97178/osnova/blob/33a4513a56abb43a1694e7a6e56373187b928a70/docs/audits/orm-2026-09-14-qualification.md).
231
+ New time limits, network failures, TLS and binary execution are described in the
232
+ [hardening report](https://github.com/asus97178/osnova/blob/33a4513a56abb43a1694e7a6e56373187b928a70/docs/audits/orm-bun-sql-hardening-2026-09-14.md).
233
+
234
+ `findForUpdate()` refreshes only a clean tracked entity. Unsaved regular assignments,
235
+ JSON/Date changes and an explicit `update()` cause a rejection before the values are
236
+ overwritten. Models with only a generated key are saved with separate
237
+ `INSERT DEFAULT VALUES` inside the shared transaction.
238
+
239
+ ## Physical types and SQL names
240
+
241
+ A PostgreSQL FK to a native UUID key gets the physical `uuid` type; the logical
242
+ `PropertyModel.type` and converters are kept. This applies to explicit FKs,
243
+ navigations and dynamic models, including composite relations and PK/FK chains.
244
+ Incompatible types are rejected before DDL. Existing columns are not converted
245
+ automatically: a mismatch needs a separate migration. Exact admission rejects
246
+ `GENERATED ALWAYS` if the model declares `BY DEFAULT`.
247
+
248
+ `PostgresDialect.quoteId()` quotes **one** name:
249
+ `quoteId("external.name")` returns `"external.name"`. For a table with a schema use
250
+ `qualifyTable(model)` or join a separately quoted schema and name. The old
251
+ `tableName` format of dynamic models is kept; the ORM uses the original schema and
252
+ table components without splitting on dots. A manually passed
253
+ `ForeignKeyConstraint.referencedTable` keeps the existing `schema.table` format.
254
+
255
+ `include()` uses the `KeyTuple` semantics shared with the identity map for references
256
+ and collections, including `bigint`, `Date` and converter-backed binary keys.