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,684 @@
1
+ # Repository: specification
2
+
3
+ Repository (`IRepository<T>` / `Repository<T>`) is a **thin wrapper over the ORM** for working with **one entity**.
4
+ It writes no SQL and does not duplicate ORM logic: everything is delegated to `DbSet<T>` and `DbContext`.
5
+
6
+ ---
7
+
8
+ ## In plain words
9
+
10
+ Picture three layers:
11
+
12
+ ```
13
+ Service (UserService)
14
+ ↓
15
+ Repository<User> ← "work only with users"
16
+ ↓
17
+ DbSet<User> + DbContext ← the whole ORM (queries, tracking, SaveChanges)
18
+ ↓
19
+ Database
20
+ ```
21
+
22
+ **Repository** is the "door" into the ORM for a concrete table/entity.
23
+ Instead of writing `ctx.users.where(...)` in every service or carrying the whole `DbContext` around, the service gets a ready `IRepository<User>` object through DI.
24
+
25
+ ---
26
+
27
+ ## Why use it
28
+
29
+ | Without Repository | With Repository |
30
+ | --- | --- |
31
+ | The service depends on the whole `AppDbContext` | The service depends only on `IRepository<User>` |
32
+ | Easy to touch other tables by accident | One entity is visible, so fewer mistakes |
33
+ | Harder to test (needs the full context) | `IRepository<User>` can be replaced with a mock |
34
+ | Data access style is scattered across the project | One pattern: `query()` / `add()` / `saveChanges()` |
35
+
36
+ **Repository does not replace the ORM**: it **organizes** access to it in application code (services, controllers, background tasks).
37
+
38
+ ### When Repository fits
39
+
40
+ - CRUD and LINQ-like queries over one entity
41
+ - The application service layer with DI
42
+ - Several repositories in one request (they all share one scoped `DbContext`)
43
+
44
+ ### When to use `DbContext` directly
45
+
46
+ - A complex transaction over several unrelated entities with manual orchestration
47
+ - Scripts/migrations that need no DI (`DbContextFactory`)
48
+ - Raw SQL through `database.executeSqlRaw` that is not tied to one entity
49
+
50
+ ---
51
+
52
+ ## Module files
53
+
54
+ | File | Purpose |
55
+ | --- | --- |
56
+ | `IRepository.ts` | The interface + the `IRepository` and `repositoryFor()` DI tokens |
57
+ | `Repository.ts` | The scoped implementation (delegates to the ORM) |
58
+ | `registerRepositories.ts` | Registers repositories in the DI container |
59
+
60
+ Exports: `bazis/core/orm` (`IRepository`, `repositoryFor`, `registerRepositories`); the `Repository` class itself is in `bazis/library/orm`.
61
+
62
+ ---
63
+
64
+ ## Lifecycle and DI
65
+
66
+ - **Lifetime:** `scoped`: one `Repository<T>` instance per scope (usually one HTTP request)
67
+ - **DbContext** is scoped too → repositories registered for one context type in one scope **share its ChangeTracker**. Repositories of different contexts are independent
68
+ - `saveChanges()` on any repository saves **all** pending changes of the context (not only "its own" table)
69
+ - For a new application operation, make the write boundary explicit: inject your
70
+ `DbContext`, work with its DbSet and call `db.saveChanges()`. The repository
71
+ method stays a compatible shortcut for the same operation, not a separate commit.
72
+
73
+ Registration is automatic with `ormModule({ ... })`:
74
+
75
+ ```ts
76
+ const DataModule = ormModule({
77
+ context: AppDbContext,
78
+ entities: [User, Post],
79
+ provider: postgres({ url: Bun.env.BAZIS_PG_URL! }),
80
+ registerRepositories: true, // true by default
81
+ });
82
+ ```
83
+
84
+ `ormModule` exports the `IRepository` family token so importing modules can inject `repositoryFor(User)`.
85
+
86
+ Turning repositories off:
87
+
88
+ ```ts
89
+ ormModule({ ..., registerRepositories: false })
90
+ ```
91
+
92
+ ---
93
+
94
+ ## API: `IRepository<T>`
95
+
96
+ Below are all the interface members. `Repository<T>` behaves **identically** (it only delegates).
97
+
98
+ ### Queries
99
+
100
+ #### `query(): DbSet<T>`
101
+
102
+ The entry point to the ORM's LINQ-like queries. Returns the same object as `dbSet`.
103
+
104
+ ```ts
105
+ const adults = await users
106
+ .query()
107
+ .where((u) => u.age.gte(18))
108
+ .orderBy((u) => u.name)
109
+ .take(20)
110
+ .toList();
111
+ ```
112
+
113
+ #### `readonly dbSet: DbSet<T>`
114
+
115
+ Direct access to the `DbSet` is an escape hatch for advanced scenarios.
116
+ `query()` and `dbSet` are the same thing; pick whichever reads better in the code.
117
+
118
+ **What `DbSet` / the chain after `query()` can do** (the full ORM list):
119
+
120
+ | Method | What it does |
121
+ | --- | --- |
122
+ | `where(predicate)` | Filter (several `where` = AND) |
123
+ | `orderBy(selector)` | Ascending sort |
124
+ | `orderByDescending(selector)` | Descending sort |
125
+ | `take(n)` | LIMIT |
126
+ | `skip(n)` | OFFSET |
127
+ | `asNoTracking()` | Do not track the result (faster for read-only) |
128
+ | `ignoreQueryFilters()` | Turn off `@QueryFilter` and the soft-delete filter |
129
+ | `select(u => ({ ... }))` | Projection into a plain object |
130
+ | `include(u => u.nav)` | Eager loading of a navigation |
131
+ | `thenInclude(...)` | Nested loading after `include` |
132
+ | `toList()` | Run the query, return an array |
133
+ | `first(predicate?)` | The first element or an error |
134
+ | `firstOrDefault(predicate?)` | The first element or `null` |
135
+ | `count(predicate?)` | Number of rows |
136
+ | `any(predicate?)` | Whether there is at least one row |
137
+
138
+ **Predicates** (a Proxy DSL, not strings in SQL):
139
+
140
+ `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `like`, `startsWith`, `endsWith`, `contains`, `in`, `isNull`, `isNotNull`, the combinators `.and()`, `.or()`, `.not()`.
141
+
142
+ > Important: in predicates use `.and()` / `.or()`, not JavaScript `&&` / `||`.
143
+
144
+ ---
145
+
146
+ ### Reading by key
147
+
148
+ #### `find(key: unknown): Promise<T | null>`
149
+
150
+ A primary key lookup runs SQL with the access filters and soft delete applied.
151
+ If the found entity is already tracked, the same object is returned (identity map).
152
+ Having the object in the tracker does not by itself allow skipping the query.
153
+
154
+ ```ts
155
+ const user = await users.find(42);
156
+ if (user === null) {
157
+ // not found
158
+ }
159
+ ```
160
+
161
+ ---
162
+
163
+ ### Changes (change tracking)
164
+
165
+ Changes **do not reach the database right away**: they pile up in the `ChangeTracker` until `saveChanges()` is called.
166
+
167
+ #### `add(entity: T): T`
168
+
169
+ Marks the entity for **INSERT**. Returns the same reference.
170
+
171
+ ```ts
172
+ const user = users.add(Object.assign(new User(), { name: "Ann" }));
173
+ await users.saveChanges(); // INSERT, the id is generated
174
+ ```
175
+
176
+ #### `addRange(entities: readonly T[]): void`
177
+
178
+ Batch insert (several `Added` in one call).
179
+
180
+ #### `update(entity: T): T`
181
+
182
+ Marks a **full UPDATE** of all non-key columns.
183
+
184
+ #### `remove(entity: T): T`
185
+
186
+ Marks for deletion. For `@SoftDelete` it sets a timestamp instead of DELETE.
187
+
188
+ #### `attach(entity: T): T`
189
+
190
+ Attaches an existing object as `Unchanged` (with a snapshot for change tracking).
191
+
192
+ #### `stateOf(entity: T): EntityState`
193
+
194
+ The current state in the tracker:
195
+
196
+ | `EntityState` | Meaning |
197
+ | --- | --- |
198
+ | `Detached` | Not tracked |
199
+ | `Unchanged` | Loaded, no changes |
200
+ | `Added` | Will be INSERTed |
201
+ | `Modified` | Will be UPDATEd |
202
+ | `Deleted` | Will be DELETEd (or soft-deleted) |
203
+
204
+ ---
205
+
206
+ ### Saving (Unit of Work)
207
+
208
+ #### `saveChanges(): Promise<number>`
209
+
210
+ Applies **all** changes of the current `DbContext` in **one transaction**.
211
+ Returns the number of processed entities; `0` if there is nothing to save.
212
+
213
+ Before saving, the ORM runs:
214
+
215
+ 1. `DetectChanges` (comparison with the snapshot)
216
+ 2. Validation (`@Validator`, if `validateOnSave: true`)
217
+ 3. INSERT / UPDATE / DELETE with parameterized SQL
218
+ 4. `AcceptChanges` on success
219
+
220
+ On an error the transaction is rolled back and the tracker state is kept: you can fix the data and call `saveChanges()` again.
221
+
222
+ ```ts
223
+ users.add(newUser);
224
+ posts.add(newPost);
225
+ await users.saveChanges(); // saves both User and Post: one context
226
+ ```
227
+
228
+ ---
229
+
230
+ ### Infrastructure (read-only)
231
+
232
+ #### `readonly changeTracker: ChangeTracker`
233
+
234
+ Direct access to the context's tracker (rarely needed in services; for debugging and advanced cases).
235
+
236
+ #### `readonly database: DatabaseFacade`
237
+
238
+ The database facade of the same context:
239
+
240
+ - `ensureCreated()` / `migrate()` / `migrateVersioned()`
241
+ - `executeSqlRaw()` / `querySqlRaw()`
242
+ - `transaction(work)`
243
+ - `canConnect()`
244
+
245
+ ```ts
246
+ await users.database.executeSqlRaw(
247
+ 'UPDATE "Users" SET "active" = {0} WHERE "id" = {1}',
248
+ false,
249
+ userId,
250
+ );
251
+ ```
252
+
253
+ ---
254
+
255
+ ## DI: tokens and injection
256
+
257
+ ### `repositoryFor(User)`: the recommended way
258
+
259
+ A typed token for a concrete entity:
260
+
261
+ ```ts
262
+ import { repositoryFor, type IRepository } from "@/core/orm";
263
+
264
+ class UserService {
265
+ constructor(private readonly users: IRepository<User>) {}
266
+ }
267
+ ```
268
+
269
+ Registration in a module (if you do not use `ormModule`):
270
+
271
+ ```ts
272
+ import { Module } from "@/core/di";
273
+ import { registerRepositories } from "@/core/orm";
274
+
275
+ @Module({
276
+ configure: (di) => registerRepositories(di, AppDbContext, [User, Post]),
277
+ exports: [IRepository],
278
+ })
279
+ class MyModule {}
280
+ ```
281
+
282
+ ### Explicit dependencies in a provider
283
+
284
+ ```ts
285
+ import { scoped, DI } from "@/core/di";
286
+ import { repositoryFor } from "@/core/orm";
287
+
288
+ providers: [
289
+ scoped(
290
+ DI.classProvider(UserService, UserService, [repositoryFor(User)] as const),
291
+ ),
292
+ ],
293
+ ```
294
+
295
+ ### `IRepository` — open generic family
296
+
297
+ A low-level token for DI extensions:
298
+
299
+ ```ts
300
+ IRepository.of(User) // the same as repositoryFor(User), but without the richer typing
301
+ ```
302
+
303
+ ---
304
+
305
+ ## Full example
306
+
307
+ ### 1. Entity and context
308
+
309
+ ```ts
310
+ import { Column, DbContext, Entity, Key, ormModule } from "bazis/core/orm";
311
+ import { postgres } from "bazis/library/orm";
312
+
313
+ @Entity()
314
+ class User {
315
+ @Key() id = 0;
316
+ @Column({ type: "text" }) name = "";
317
+ @Column({ type: "integer" }) age = 0;
318
+ }
319
+
320
+ class AppDbContext extends DbContext {
321
+ readonly users = this.set(User);
322
+ }
323
+ ```
324
+
325
+ ### 2. Data module
326
+
327
+ ```ts
328
+ export const DataModule = ormModule({
329
+ context: AppDbContext,
330
+ entities: [User],
331
+ provider: postgres({ url: Bun.env.BAZIS_PG_URL! }),
332
+ migrateOnStart: true,
333
+ });
334
+ ```
335
+
336
+ ### 3. Service
337
+
338
+ ```ts
339
+ import { repositoryFor, type IRepository } from "bazis/core/orm";
340
+
341
+ export class UserService {
342
+ constructor(private readonly users: IRepository<User>) {}
343
+
344
+ listAdults(limit: number) {
345
+ return this.users
346
+ .query()
347
+ .where((u) => u.age.gte(18))
348
+ .orderBy((u) => u.name)
349
+ .take(limit)
350
+ .toList();
351
+ }
352
+
353
+ async findById(id: number) {
354
+ return this.users.find(id);
355
+ }
356
+
357
+ async create(name: string, age: number) {
358
+ const user = this.users.add(Object.assign(new User(), { name, age }));
359
+ await this.users.saveChanges();
360
+ return user; // the id is filled in after saveChanges
361
+ }
362
+
363
+ async rename(id: number, name: string) {
364
+ const user = await this.users.find(id);
365
+ if (user === null) return false;
366
+ user.name = name; // snapshot tracking picks up the change
367
+ await this.users.saveChanges();
368
+ return true;
369
+ }
370
+
371
+ async removeById(id: number) {
372
+ const user = await this.users.find(id);
373
+ if (user === null) return false;
374
+ this.users.remove(user);
375
+ await this.users.saveChanges();
376
+ return true;
377
+ }
378
+ }
379
+ ```
380
+
381
+ ### 4. Application module
382
+
383
+ ```ts
384
+ import { Module, scoped } from "@/core/di";
385
+ import { repositoryFor } from "@/core/orm";
386
+
387
+ @Module({
388
+ imports: [DataModule],
389
+ providers: [
390
+ scoped(UserService, UserService, [repositoryFor(User)] as const),
391
+ ],
392
+ exports: [UserService],
393
+ })
394
+ class UsersModule {}
395
+ ```
396
+
397
+ ---
398
+
399
+ ## Query examples
400
+
401
+ ### Filter and paging
402
+
403
+ ```ts
404
+ const page = await users
405
+ .query()
406
+ .where((u) => u.age.gte(18).and(u.name.startsWith("A")))
407
+ .orderByDescending((u) => u.age)
408
+ .skip(20)
409
+ .take(10)
410
+ .toList();
411
+ ```
412
+
413
+ ### Projection (only the needed fields)
414
+
415
+ ```ts
416
+ const labels = await users
417
+ .query()
418
+ .select((u) => ({ id: u.id, name: u.name }))
419
+ .where((u) => u.age.gt(21))
420
+ .toList();
421
+ // [{ id: 1, name: "Ann" }, ...]
422
+ ```
423
+
424
+ ### Eager loading of relations
425
+
426
+ ```ts
427
+ const authors = await authorsRepo
428
+ .query()
429
+ .include((a) => a.books)
430
+ .thenInclude((b) => b.reviews)
431
+ .toList();
432
+ ```
433
+
434
+ ### Global filter and soft delete
435
+
436
+ ```ts
437
+ // @QueryFilter on the entity goes into WHERE automatically
438
+ await docs.query().toList();
439
+
440
+ // See the "hidden" rows:
441
+ await docs.query().ignoreQueryFilters().toList();
442
+
443
+ // @SoftDelete: remove() sets deletedAt instead of DELETE
444
+ docs.remove(doc);
445
+ await docs.saveChanges();
446
+ ```
447
+
448
+ ### Read-only without tracking
449
+
450
+ ```ts
451
+ const rows = await users.query().asNoTracking().toList();
452
+ // the objects are not in the changeTracker, which is faster for reports and lists
453
+ ```
454
+
455
+ ---
456
+
457
+ ## Several repositories in one service
458
+
459
+ ```ts
460
+ class OrderService {
461
+ constructor(
462
+ private readonly orders: IRepository<Order>,
463
+ private readonly products: IRepository<Product>,
464
+ ) {}
465
+
466
+ async placeOrder(productId: number, qty: number) {
467
+ const product = await this.products.find(productId);
468
+ if (product === null) throw new Error("product not found");
469
+
470
+ this.orders.add(Object.assign(new Order(), { productId, qty }));
471
+ product.stock -= qty;
472
+
473
+ await this.orders.saveChanges(); // saves both Order and Product
474
+ }
475
+ }
476
+ ```
477
+
478
+ Both repositories use **one** scoped `DbContext` → one transaction per `saveChanges()`.
479
+
480
+ ---
481
+
482
+ ## What Repository does **not** do
483
+
484
+ - It does not create a separate Unit of Work: that is `DbContext.saveChanges()`
485
+ - It does not generate SQL: that is `SqlTranslator` / `SaveExecutor`
486
+ - It does not validate on its own: the ORM validates on `saveChanges()`
487
+ - It does not isolate transactions across scopes: each scope has its own context
488
+ - It does not register entities: only those passed to `ormModule({ entities: [...] })`
489
+
490
+ ---
491
+
492
+ ## Common mistakes
493
+
494
+ ### 1. Forgot `saveChanges()`
495
+
496
+ ```ts
497
+ users.add(user);
498
+ // the data is not in the database yet!
499
+ await users.saveChanges();
500
+ ```
501
+
502
+ ### 2. `add()` of the wrong entity
503
+
504
+ ```ts
505
+ // ❌ a book added through authorsRepo: the ORM treats it as an Author
506
+ authors.add(book);
507
+
508
+ // ✅ its own repository
509
+ books.add(book);
510
+ ```
511
+
512
+ ### 3. Dependencies of `IRepository<User>` without codegen
513
+
514
+ `di:generate` wires a constructor parameter typed `IRepository<User>` automatically. Explicit deps are needed only when the class is registered without codegen (for example in a hand-built test container):
515
+
516
+ ```ts
517
+ scoped(UserService, UserService, [repositoryFor(User)] as const)
518
+ ```
519
+
520
+ ### 4. `ensureCreated` in tests without starting the application
521
+
522
+ `ensureCreated: true` in `ormModule` runs in `OrmLifecycle.start()` (at application start).
523
+ In tests call it by hand:
524
+
525
+ ```ts
526
+ await scope.resolve(AppDbContext).database.ensureCreated();
527
+ ```
528
+
529
+ ### 5. Different scopes have different data in the tracker
530
+
531
+ ```ts
532
+ const scopeA = container.createScope();
533
+ const scopeB = container.createScope();
534
+ // resolve in scopeA and scopeB gives different DbContext and Repository instances
535
+ ```
536
+
537
+ ---
538
+
539
+ ## Relation to `DbContext.setOf()`
540
+
541
+ Inside, Repository calls:
542
+
543
+ ```ts
544
+ context.setOf(EntityClass) // → DbSet<T>
545
+ ```
546
+
547
+ The `setOf` method was added to `DbContext` exactly for generic access without declaring a `readonly users = this.set(User)` field in the subclass.
548
+ In application code prefer **Repository** over a direct `setOf`.
549
+
550
+ ---
551
+
552
+ ## Mocks and testing without a database
553
+
554
+ Repository is easy to replace in unit tests: the service is tested without PostgreSQL and without a `DbContext`.
555
+
556
+ ### Level 1: a mock `IRepository<User>`
557
+
558
+ Testing `UserService` without a database: pass an object with the needed methods:
559
+
560
+ ```ts
561
+ import { describe, expect, test } from "bun:test";
562
+ import type { IRepository } from "@/core/orm";
563
+ import { UserService } from "./UserService";
564
+ import { User } from "./User";
565
+
566
+ test("add calls repository add and saveChanges", async () => {
567
+ let saved = false;
568
+ const users: IRepository<User> = {
569
+ get dbSet() { throw new Error("not needed"); },
570
+ query() { throw new Error("not needed"); },
571
+ find: async () => null,
572
+ add: (entity) => entity,
573
+ addRange: () => {},
574
+ update: (entity) => entity,
575
+ remove: (entity) => entity,
576
+ attach: (entity) => entity,
577
+ stateOf: () => "Unchanged" as const,
578
+ saveChanges: async () => { saved = true; return 1; },
579
+ get changeTracker() { throw new Error("not needed"); },
580
+ get database() { throw new Error("not needed"); },
581
+ };
582
+
583
+ const service = new UserService(users);
584
+ await service.add("Ann");
585
+ expect(saved).toBe(true);
586
+ });
587
+ ```
588
+
589
+ A mock usually needs only the methods the service calls.
590
+
591
+ ### Level 2: an in-memory store (without Repository)
592
+
593
+ For **controller** tests it is enough to replace the store contract the controller depends on (here a hypothetical `IUserStore`):
594
+
595
+ ```ts
596
+ import { Module, createContainer, DI } from "bazis/core/di";
597
+ import { InMemoryUserStore } from "./InMemoryUserStore";
598
+ import { IUserStore } from "./IUserStore";
599
+ import { UsersController } from "./UsersController";
600
+
601
+ @Module({
602
+ controllers: [UsersController],
603
+ providers: [
604
+ DI.scoped(DI.valueProvider(IUserStore, new InMemoryUserStore())),
605
+ ],
606
+ })
607
+ class TestUsersModule {}
608
+
609
+ const container = createContainer(TestUsersModule);
610
+ const scope = container.createScope();
611
+ const controller = scope.resolve(UsersController);
612
+ // call the controller methods or run HTTP e2e over the module
613
+ ```
614
+
615
+ The controller and the HTTP layer do not touch the ORM, only the `IUserStore` contract.
616
+
617
+ ### Level 3: an integration test with a real Repository
618
+
619
+ As in [orm.repository.test.ts](../../../core/orm/test/orm.repository.test.ts):
620
+
621
+ ```ts
622
+ const DataModule = ormModule({
623
+ context: UsersDbContext,
624
+ entities: [User],
625
+ provider: postgres({ url: Bun.env.BAZIS_PG_URL! }),
626
+ healthCheck: false,
627
+ });
628
+
629
+ const container = createContainer(DataModule);
630
+ const scope = container.createScope();
631
+ await scope.resolve(UsersDbContext).database.ensureCreated();
632
+
633
+ const service = new UserService(scope.resolve(repositoryFor(User)));
634
+ await service.add("Integration");
635
+ expect(await service.list(10)).toHaveLength(1);
636
+ ```
637
+
638
+ ### What to mock in which tests
639
+
640
+ | You test | Mock | Database needed? |
641
+ | --- | --- | --- |
642
+ | `UserService` (domain rules) | `IRepository<User>` | No |
643
+ | `UsersController` (HTTP, @Catch) | the store contract / an in-memory store | No |
644
+ | Repository + ORM (queries, tracking) | — | Yes (PostgreSQL) |
645
+ | Full HTTP e2e | — | Yes (or a test module with an in-memory store) |
646
+
647
+ ### Tips
648
+
649
+ 1. **Do not mock `query()`** if you test SQL/filters: use PostgreSQL qualification.
650
+ 2. **Mock `saveChanges()`** to check that the service saves data at all.
651
+ 3. **One scope per test**: `scope.dispose()` in `afterEach`, otherwise scoped services leak.
652
+ 4. In hand-built DI test containers (without codegen) with `validateOnBuild: true`, give Repository deps explicitly: `[repositoryFor(User)]`.
653
+
654
+ ---
655
+
656
+ ## Tests
657
+
658
+ Live examples and scenarios:
659
+
660
+ - ORM Repository: [orm.repository.test.ts](../../../core/orm/test/orm.repository.test.ts)
661
+
662
+ Covered: CRUD, queries, include, `@QueryFilter`, `@SoftDelete`, scoped DI, module encapsulation.
663
+
664
+ ---
665
+
666
+ ## Cheat sheet
667
+
668
+ ```ts
669
+ // DI
670
+ constructor(private readonly users: IRepository<User>) {}
671
+
672
+ // Read
673
+ await users.find(id);
674
+ await users.query().where(...).toList();
675
+
676
+ // Write
677
+ users.add(entity);
678
+ users.update(entity);
679
+ users.remove(entity);
680
+ await users.saveChanges();
681
+
682
+ // DI token
683
+ repositoryFor(User)
684
+ ```