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,497 @@
1
+ import { ModelBuildError } from "../errors";
2
+ import type {
3
+ CheckModel,
4
+ EntityModel,
5
+ ForeignKeyModel,
6
+ IndexModel,
7
+ KeyGeneration,
8
+ PropertyConvention,
9
+ PropertyModel,
10
+ RelationKind,
11
+ RelationModel,
12
+ StorageColumnType,
13
+ } from "./types";
14
+ import { compileCheck, validateCheckAst, type CheckPredicate } from "../Schema/CheckExpression";
15
+ import { registerDynamicTableIdentity } from "../Schema/tableKey";
16
+
17
+ type EntityClass = new () => object;
18
+
19
+ /**
20
+ * Logical field type of a dynamic table: what a user picks when designing the
21
+ * table. It maps to a physical `StorageColumnType` plus (for semantic fields)
22
+ * a `PropertyConvention`.
23
+ */
24
+ export type ScalarLogicalFieldType =
25
+ | "string"
26
+ | "int"
27
+ | "bigint"
28
+ | "decimal"
29
+ | "bool"
30
+ | "datetime"
31
+ | "uuid"
32
+ | "json";
33
+
34
+ export type LogicalFieldType = ScalarLogicalFieldType | "foreignKey";
35
+
36
+ /** Definition of one dynamic table field. */
37
+ export interface DynamicFieldDefinition {
38
+ /** Property name in the entity (and the column name, if `columnName` is not set). */
39
+ readonly name: string;
40
+ /** Physical column name (defaults to `name`). */
41
+ readonly columnName?: string;
42
+ /** Logical type. */
43
+ readonly type: LogicalFieldType;
44
+ /** Single-field primary key (at most one field). For a composite key use the table's `primaryKey` instead. */
45
+ readonly isKey?: boolean;
46
+ /** NOT NULL. The key and semantic timestamp fields are always required. */
47
+ readonly required?: boolean;
48
+ /** Create a unique index on the column. */
49
+ readonly unique?: boolean;
50
+ /** Create a regular index on the column. */
51
+ readonly indexed?: boolean;
52
+ /** Automatic behavior on save (`uuid`/`createdAt`/`updatedAt`). */
53
+ readonly convention?: PropertyConvention;
54
+ /** UUID version for a `uuid` field/key (default v4). */
55
+ readonly uuidVersion?: "v4" | "v7";
56
+ /** Target dynamic table; required only for `foreignKey`. */
57
+ readonly target?: string;
58
+ /** Reference navigation of this table; required only for `foreignKey`. */
59
+ readonly navigationName?: string;
60
+ /** Optional collection navigation on the target table; compiled by the target's definition. */
61
+ readonly inverseNavigationName?: string;
62
+ /** Snapshot of the target key's logical type; defines the physical type of the FK column. */
63
+ readonly targetKeyType?: ScalarLogicalFieldType;
64
+ }
65
+
66
+ /** Explicit composite index of a dynamic table. */
67
+ export interface DynamicIndexDefinition {
68
+ readonly name?: string;
69
+ /** Physical column names, not logical property names. */
70
+ readonly columns: readonly string[];
71
+ readonly unique?: boolean;
72
+ }
73
+
74
+ /**
75
+ * Compiled navigation between dynamic tables. Reference navigations and
76
+ * physical constraints are derived from `foreignKey` fields; this contract
77
+ * remains for server-derived inverse collections.
78
+ *
79
+ * - `reference`: `foreignKey` is a property of THIS table and points to the `target` key;
80
+ * - `collection`: `foreignKey` is a property of the `target` table and points to this table's key.
81
+ */
82
+ export interface DynamicRelationDefinition {
83
+ readonly navigationName: string;
84
+ readonly kind: RelationKind;
85
+ /** Name of the target table/model. */
86
+ readonly target: string;
87
+ /** Name of the foreign key property (on the dependent side). */
88
+ readonly foreignKey: string | readonly string[];
89
+ }
90
+ export interface DynamicPrimaryKeyDefinition { readonly properties: readonly [string, ...string[]]; readonly name?: string }
91
+ export interface DynamicForeignKeyDefinition { readonly properties: readonly [string, ...string[]]; readonly target: string; readonly name?: string; readonly onDelete?: "noAction" | "restrict" | "cascade" | "setNull"; readonly onUpdate?: "noAction" | "restrict" | "cascade" | "setNull" }
92
+ export interface DynamicCheckDefinition { readonly name: string; readonly predicate: CheckPredicate<Record<string, unknown>> }
93
+
94
+ /** Dynamic table definition (from an application's metadata catalog). */
95
+ export interface DynamicTableDefinition {
96
+ /** Entity/model name (used as the registry key and the `ctor` name). */
97
+ readonly name: string;
98
+ /** Physical database schema (for example `data`). Becomes part of `tableName`. */
99
+ readonly schema?: string;
100
+ /** Physical table name (defaults to `name`). */
101
+ readonly tableName?: string;
102
+ readonly fields: readonly DynamicFieldDefinition[];
103
+ readonly primaryKey?: DynamicPrimaryKeyDefinition;
104
+ readonly indexes?: readonly DynamicIndexDefinition[];
105
+ readonly foreignKeys?: readonly DynamicForeignKeyDefinition[];
106
+ readonly checks?: readonly DynamicCheckDefinition[];
107
+ readonly relations?: readonly DynamicRelationDefinition[];
108
+ /** Soft-delete property name (NULL = not deleted). */
109
+ readonly softDeleteProperty?: string;
110
+ }
111
+ /** Strict schema contracts use the same dynamic entity shape; no second runtime exists. */
112
+ export type DynamicEntityDefinition = DynamicTableDefinition;
113
+
114
+ /** Resolver of the target table's ctor by name (lazy, for relations). */
115
+ export type DynamicTargetResolver = (name: string) => EntityClass;
116
+
117
+ const LOGICAL_TO_STORAGE: Record<ScalarLogicalFieldType, StorageColumnType> = {
118
+ string: "text",
119
+ int: "integer",
120
+ bigint: "integer",
121
+ decimal: "real",
122
+ bool: "boolean",
123
+ datetime: "datetime",
124
+ uuid: "text",
125
+ json: "json",
126
+ };
127
+
128
+ /**
129
+ * Builds an `EntityModel` from a catalog table definition, without decorators
130
+ * or reflection. Creates a named anonymous `ctor` (its instances are plain row
131
+ * objects); the model then works both for `DbSet`/`ChangeTracker` and for DDL
132
+ * generation by the dialect (`createTableSql` and so on).
133
+ *
134
+ * Mirrors the `ModelBuilder` rules: one primary key, an integer key is identity
135
+ * by default, key/timestamp fields are always NOT NULL.
136
+ */
137
+ export function buildDynamicModel(def: DynamicTableDefinition, resolveTarget?: DynamicTargetResolver): EntityModel {
138
+ return buildDynamicModelWithCtor(def, { [def.name]: class {} }[def.name]! as EntityClass, resolveTarget);
139
+ }
140
+
141
+ /**
142
+ * Compiles a strict dynamic schema as one closed graph. This is deliberately
143
+ * package-local (not re-exported from the public ORM barrel): the legacy
144
+ * single-table entry point retains its resolver-based behaviour.
145
+ */
146
+ export function compileDynamicModelGraph(definitions: readonly DynamicEntityDefinition[]): readonly EntityModel[] {
147
+ const definitionsByName = new Map<string, DynamicEntityDefinition>();
148
+ const identities = new Set<string>();
149
+ const ctors = new Map<string, EntityClass>();
150
+ for (const definition of definitions) {
151
+ if (definitionsByName.has(definition.name)) {
152
+ throw new ModelBuildError(`Dynamic schema contains duplicate entity name "${definition.name}".`);
153
+ }
154
+ const identity = `${definition.schema ?? ""}\0${definition.tableName ?? definition.name}`;
155
+ if (identities.has(identity)) {
156
+ throw new ModelBuildError(`Dynamic schema contains duplicate table identity "${definition.schema ?? ""}.${definition.tableName ?? definition.name}".`);
157
+ }
158
+ definitionsByName.set(definition.name, definition);
159
+ identities.add(identity);
160
+ ctors.set(definition.name, { [definition.name]: class {} }[definition.name]! as EntityClass);
161
+ }
162
+
163
+ const target = (source: string): DynamicTargetResolver => (name) => {
164
+ const ctor = ctors.get(name);
165
+ if (!ctor) throw new ModelBuildError(`Dynamic table "${source}" references unknown target "${name}" in this schema contract.`);
166
+ return ctor;
167
+ };
168
+ const models = definitions.map((definition) => buildDynamicModelWithCtor(definition, ctors.get(definition.name)!, target(definition.name)));
169
+ const modelByCtor = new Map(models.map((model) => [model.ctor, model]));
170
+ return models.map((model) => validateGraphForeignKeys(model, modelByCtor));
171
+ }
172
+
173
+ function buildDynamicModelWithCtor(
174
+ def: DynamicTableDefinition,
175
+ ctor: EntityClass,
176
+ resolveTarget?: DynamicTargetResolver,
177
+ ): EntityModel {
178
+ if (def.fields.length === 0) {
179
+ throw new ModelBuildError(`Dynamic table "${def.name}" has no fields.`);
180
+ }
181
+
182
+ const properties = def.fields.map((field) => buildProperty(def.name, field));
183
+
184
+ const keys = properties.filter((property) => property.isKey);
185
+ if (def.primaryKey && keys.length > 0) throw new ModelBuildError(`Dynamic table "${def.name}" cannot combine primaryKey with legacy isKey.`);
186
+ if (keys.length === 0 && !def.primaryKey) {
187
+ throw new ModelBuildError(`Dynamic table "${def.name}" has no primary key. Mark one field with isKey.`);
188
+ }
189
+ if (keys.length > 1) {
190
+ throw new ModelBuildError(
191
+ `Dynamic table "${def.name}" declares multiple keys ("${keys
192
+ .map((key) => key.propertyName)
193
+ .join('", "')}"). Composite keys are not supported.`,
194
+ );
195
+ }
196
+ const key = keys[0];
197
+
198
+ const byName = new Map<string, PropertyModel>();
199
+ for (const property of properties) {
200
+ if (byName.has(property.propertyName)) {
201
+ throw new ModelBuildError(`Dynamic table "${def.name}": duplicate field "${property.propertyName}".`);
202
+ }
203
+ byName.set(property.propertyName, property);
204
+ }
205
+
206
+ const primaryKey = def.primaryKey ? def.primaryKey.properties.map((name) => {
207
+ const property = byName.get(name); if (!property) throw new ModelBuildError(`Dynamic table "${def.name}": primary key references unknown field "${name}".`); return { ...property, isKey: true, required: true, generation: "none" as const };
208
+ }) : [key!];
209
+ if (new Set(primaryKey.map((property) => property.propertyName)).size !== primaryKey.length) throw new ModelBuildError(`Dynamic table "${def.name}": duplicate primary key property.`);
210
+ for (const primary of primaryKey) { const index = properties.findIndex((property) => property.propertyName === primary.propertyName); properties[index] = primary; byName.set(primary.propertyName, primary); }
211
+ const physicalName = def.tableName ?? def.name;
212
+ const tableName = def.schema ? `${def.schema}.${physicalName}` : physicalName;
213
+ registerDynamicTableIdentity(ctor, { schema: def.schema || undefined, table: physicalName });
214
+
215
+ assertExternalTargetsResolvable(def, resolveTarget);
216
+ const targetCtor = targetResolver(def.name, ctor, resolveTarget);
217
+ const relations = buildRelations(def, byName, targetCtor);
218
+ const relationByName = new Map(relations.map((relation) => [relation.navigationName, relation]));
219
+ const foreignKeys: ForeignKeyModel[] = def.fields
220
+ .filter((field) => field.type === "foreignKey")
221
+ .map((field) => ({ property: field.name, properties: [field.name], target: () => targetCtor(field.target!), onDelete: "noAction" as const, onUpdate: "noAction" as const }));
222
+
223
+ for (const fk of def.foreignKeys ?? []) {
224
+ if (fk.properties.length === 0 || new Set(fk.properties).size !== fk.properties.length) throw new ModelBuildError(`Dynamic table "${def.name}": invalid composite foreign key.`);
225
+ for (const name of fk.properties) if (!byName.has(name)) throw new ModelBuildError(`Dynamic table "${def.name}": foreign key references unknown field "${name}".`);
226
+ foreignKeys.push({ property: fk.properties[0]!, properties: [...fk.properties], name: fk.name ?? `fk_${physicalName}_${fk.properties.join("_")}`, target: () => targetCtor(fk.target), onDelete: fk.onDelete ?? "noAction", onUpdate: fk.onUpdate ?? "noAction" });
227
+ }
228
+ const checks: CheckModel[] = (def.checks ?? []).map((check) => ({ name: check.name, expression: compileCheck(check.predicate) }));
229
+ for (const check of checks) validateCheckAst(check.expression, properties);
230
+ return {
231
+ ctor,
232
+ name: def.name,
233
+ tableName,
234
+ properties,
235
+ key: primaryKey as [PropertyModel, ...PropertyModel[]],
236
+ keyName: def.primaryKey?.name,
237
+ indexes: buildIndexes(def, physicalName, byName),
238
+ checks,
239
+ relations,
240
+ foreignKeys,
241
+ queryFilters: [],
242
+ softDeleteProperty: def.softDeleteProperty,
243
+ propertyByName: (name: string) => byName.get(name),
244
+ relationByName: (name: string) => relationByName.get(name),
245
+ };
246
+ }
247
+
248
+ function validateGraphForeignKeys(model: EntityModel, modelByCtor: ReadonlyMap<EntityClass, EntityModel>): EntityModel {
249
+ const checks = [...model.checks];
250
+ const names = new Set(checks.map((check) => check.name));
251
+ if (names.size !== checks.length) throw new ModelBuildError(`Dynamic table "${model.name}" has duplicate CHECK names.`);
252
+ for (const relation of model.relations) {
253
+ if (!modelByCtor.has(relation.target())) {
254
+ throw new ModelBuildError(`Dynamic table "${model.name}" relation target is outside its schema contract.`);
255
+ }
256
+ }
257
+ const shapes = new Set<string>();
258
+ const foreignKeys: ForeignKeyModel[] = [];
259
+
260
+ for (const foreignKey of model.foreignKeys) {
261
+ const target = modelByCtor.get(foreignKey.target());
262
+ if (!target) throw new ModelBuildError(`Dynamic table "${model.name}" has a foreign key target outside its schema contract.`);
263
+ const locals = foreignKey.properties.map((property) => model.propertyByName(property));
264
+ if (locals.some((property) => !property)) throw new ModelBuildError(`Dynamic table "${model.name}" foreign key references an unknown field.`);
265
+ if (locals.length !== target.key.length) {
266
+ throw new ModelBuildError(`Dynamic table "${model.name}" foreign key must target the complete primary key of "${target.name}".`);
267
+ }
268
+ for (let index = 0; index < locals.length; index += 1) {
269
+ if (locals[index]!.type !== target.key[index]!.type) {
270
+ throw new ModelBuildError(`Dynamic table "${model.name}" foreign key component types/order do not match target primary key "${target.name}".`);
271
+ }
272
+ }
273
+ const nullable = locals.map((property) => !property!.required);
274
+ if (nullable.some(Boolean) && !nullable.every(Boolean)) {
275
+ throw new ModelBuildError(`Dynamic table "${model.name}" nullable composite foreign key must be all nullable or all required.`);
276
+ }
277
+ if ((foreignKey.onDelete === "setNull" || foreignKey.onUpdate === "setNull") && !nullable.every(Boolean)) {
278
+ throw new ModelBuildError(`Dynamic table "${model.name}" setNull requires nullable foreign key components.`);
279
+ }
280
+ const name = foreignKey.name ?? `fk_${model.tableName}_${foreignKey.properties.join("_")}`;
281
+ const shape = `${foreignKey.properties.join("\0")}\0${target.name}`;
282
+ if (names.has(name) || shapes.has(shape)) {
283
+ throw new ModelBuildError(`Dynamic table "${model.name}" has duplicate or conflicting foreign key "${name}".`);
284
+ }
285
+ names.add(name);
286
+ shapes.add(shape);
287
+ foreignKeys.push({ ...foreignKey, name });
288
+ if (nullable.every(Boolean) && locals.length > 1) {
289
+ const companionName = `ck_${model.tableName}_${foreignKey.properties.join("_")}_tuple`;
290
+ if (names.has(companionName)) throw new ModelBuildError(`Dynamic table "${model.name}" has conflicting CHECK name "${companionName}".`);
291
+ names.add(companionName);
292
+ checks.push(nullableTupleCheck(companionName, locals as PropertyModel[]));
293
+ }
294
+ }
295
+ return { ...model, foreignKeys, checks };
296
+ }
297
+
298
+ function nullableTupleCheck(name: string, properties: readonly PropertyModel[]): CheckModel {
299
+ let allNull: CheckModel["expression"] = { kind: "null", left: properties[0]!.propertyName, not: false };
300
+ let allPresent: CheckModel["expression"] = { kind: "null", left: properties[0]!.propertyName, not: true };
301
+ for (const property of properties.slice(1)) {
302
+ allNull = { kind: "and", left: allNull, right: { kind: "null", left: property.propertyName, not: false } };
303
+ allPresent = { kind: "and", left: allPresent, right: { kind: "null", left: property.propertyName, not: true } };
304
+ }
305
+ return { name, expression: { kind: "or", left: allNull, right: allPresent } };
306
+ }
307
+
308
+ function buildRelations(
309
+ def: DynamicTableDefinition,
310
+ byName: Map<string, PropertyModel>,
311
+ resolveTarget: DynamicTargetResolver,
312
+ ): RelationModel[] {
313
+ const fieldReferences: DynamicRelationDefinition[] = def.fields
314
+ .filter((field) => field.type === "foreignKey")
315
+ .map((field) => ({
316
+ navigationName: field.navigationName!,
317
+ kind: "reference",
318
+ target: field.target!,
319
+ foreignKey: field.name,
320
+ }));
321
+ const definitions = [...fieldReferences, ...(def.relations ?? [])];
322
+ if (definitions.length === 0) {
323
+ return [];
324
+ }
325
+
326
+ const seen = new Set<string>();
327
+ const relations: RelationModel[] = [];
328
+ for (const relation of definitions) {
329
+ if (seen.has(relation.navigationName)) {
330
+ throw new ModelBuildError(`Dynamic table "${def.name}": duplicate navigation "${relation.navigationName}".`);
331
+ }
332
+ seen.add(relation.navigationName);
333
+ if (byName.has(relation.navigationName)) {
334
+ throw new ModelBuildError(
335
+ `Dynamic table "${def.name}": navigation "${relation.navigationName}" collides with a field.`,
336
+ );
337
+ }
338
+ // For reference the foreign key is a property of this table; for collection it is on the target.
339
+ const relationKeys = typeof relation.foreignKey === "string" ? [relation.foreignKey] : relation.foreignKey;
340
+ if (relation.kind === "reference" && relationKeys.some((key) => !byName.has(key))) {
341
+ throw new ModelBuildError(
342
+ `Dynamic table "${def.name}": relation "${relation.navigationName}" references unknown foreign key "${relation.foreignKey}".`,
343
+ );
344
+ }
345
+ const targetName = relation.target;
346
+ relations.push({
347
+ navigationName: relation.navigationName,
348
+ kind: relation.kind,
349
+ foreignKey: relation.foreignKey,
350
+ target: () => resolveTarget(targetName),
351
+ });
352
+ }
353
+ return relations;
354
+ }
355
+
356
+ function buildProperty(tableName: string, field: DynamicFieldDefinition): PropertyModel {
357
+ if (field.type === "foreignKey") {
358
+ return buildForeignKeyProperty(tableName, field);
359
+ }
360
+ const isKey = field.isKey === true;
361
+ const storageType = LOGICAL_TO_STORAGE[field.type];
362
+ if (!storageType) {
363
+ throw new ModelBuildError(`Dynamic table "${tableName}": unknown field type "${field.type}" for "${field.name}".`);
364
+ }
365
+
366
+ // An integer key is auto-increment (identity) by default.
367
+ const generation: KeyGeneration =
368
+ isKey && storageType === "integer" ? "identity"
369
+ : isKey && field.type === "uuid" ? (field.uuidVersion === "v7" ? "uuidV7" : "uuid")
370
+ : "none";
371
+ const convention: PropertyConvention | undefined =
372
+ field.convention ?? (field.type === "uuid" && !isKey ? "uuid" : undefined);
373
+ const required = isKey || field.required === true || convention === "createdAt" || convention === "updatedAt";
374
+
375
+ return {
376
+ propertyName: field.name,
377
+ columnName: field.columnName ?? field.name,
378
+ type: storageType,
379
+ isKey,
380
+ generation,
381
+ required,
382
+ convention,
383
+ uuidVersion: field.uuidVersion,
384
+ databaseDefault: generation === "uuid" ? { kind: "uuidV4" } : { kind: "none" },
385
+ };
386
+ }
387
+
388
+ function buildForeignKeyProperty(tableName: string, field: DynamicFieldDefinition): PropertyModel {
389
+ if (!field.target) {
390
+ throw new ModelBuildError(`Dynamic table "${tableName}": foreign key field "${field.name}" has no target.`);
391
+ }
392
+ if (!field.navigationName) {
393
+ throw new ModelBuildError(`Dynamic table "${tableName}": foreign key field "${field.name}" has no navigationName.`);
394
+ }
395
+ if (!field.targetKeyType) {
396
+ throw new ModelBuildError(`Dynamic table "${tableName}": foreign key field "${field.name}" has no targetKeyType.`);
397
+ }
398
+ if (field.isKey === true) {
399
+ throw new ModelBuildError(`Dynamic table "${tableName}": foreign key field "${field.name}" cannot be a primary key.`);
400
+ }
401
+ if (field.convention !== undefined || field.uuidVersion !== undefined) {
402
+ throw new ModelBuildError(
403
+ `Dynamic table "${tableName}": foreign key field "${field.name}" cannot declare convention or uuidVersion.`,
404
+ );
405
+ }
406
+
407
+ const storageType = LOGICAL_TO_STORAGE[field.targetKeyType];
408
+ if (!storageType) {
409
+ throw new ModelBuildError(
410
+ `Dynamic table "${tableName}": foreign key field "${field.name}" has unknown targetKeyType "${field.targetKeyType}".`,
411
+ );
412
+ }
413
+
414
+ return {
415
+ propertyName: field.name,
416
+ columnName: field.columnName ?? field.name,
417
+ type: storageType,
418
+ isKey: false,
419
+ generation: "none",
420
+ required: field.required === true,
421
+ databaseDefault: { kind: "none" },
422
+ };
423
+ }
424
+
425
+ function assertExternalTargetsResolvable(
426
+ def: DynamicTableDefinition,
427
+ resolveTarget?: DynamicTargetResolver,
428
+ ): void {
429
+ if (resolveTarget) return;
430
+ const externalTarget = [
431
+ ...def.fields.filter((field) => field.type === "foreignKey").map((field) => field.target),
432
+ ...(def.relations ?? []).map((relation) => relation.target),
433
+ ].find((target) => target !== undefined && target !== def.name);
434
+ if (externalTarget) {
435
+ throw new ModelBuildError(
436
+ `Dynamic table "${def.name}" references target "${externalTarget}" but no target resolver was provided.`,
437
+ );
438
+ }
439
+ }
440
+
441
+ function targetResolver(
442
+ sourceName: string,
443
+ sourceCtor: EntityClass,
444
+ resolveTarget?: DynamicTargetResolver,
445
+ ): DynamicTargetResolver {
446
+ return (targetName) => {
447
+ if (targetName === sourceName) return sourceCtor;
448
+ if (!resolveTarget) {
449
+ throw new ModelBuildError(
450
+ `Dynamic table "${sourceName}" references target "${targetName}" but no target resolver was provided.`,
451
+ );
452
+ }
453
+ return resolveTarget(targetName);
454
+ };
455
+ }
456
+
457
+ function buildIndexes(
458
+ def: DynamicTableDefinition,
459
+ physicalName: string,
460
+ byName: Map<string, PropertyModel>,
461
+ ): IndexModel[] {
462
+ const indexes: IndexModel[] = [];
463
+ const base = physicalName.toLowerCase();
464
+
465
+ // Indexes from field flags (unique/indexed).
466
+ for (const field of def.fields) {
467
+ if (!field.unique && !field.indexed) {
468
+ continue;
469
+ }
470
+ const column = field.columnName ?? field.name;
471
+ indexes.push({ name: `ix_${base}_${column}`, columns: [column], unique: field.unique === true });
472
+ }
473
+
474
+ // Explicit composite indexes.
475
+ for (const index of def.indexes ?? []) {
476
+ for (const column of index.columns) {
477
+ if (![...byName.values()].some((property) => property.columnName === column)) {
478
+ throw new ModelBuildError(`Dynamic table "${def.name}": index references unknown column "${column}".`);
479
+ }
480
+ }
481
+ indexes.push({
482
+ name: index.name ?? `ix_${base}_${index.columns.join("_")}`,
483
+ columns: index.columns,
484
+ unique: index.unique === true,
485
+ });
486
+ }
487
+
488
+ const names = new Set<string>();
489
+ for (const index of indexes) {
490
+ if (!index.columns.length || new Set(index.columns).size !== index.columns.length) {
491
+ throw new ModelBuildError(`Dynamic table "${def.name}": index must contain distinct columns.`);
492
+ }
493
+ if (names.has(index.name)) throw new ModelBuildError(`Dynamic table "${def.name}": duplicate index name "${index.name}".`);
494
+ names.add(index.name);
495
+ }
496
+ return indexes;
497
+ }
@@ -0,0 +1,36 @@
1
+ import type { EntityModel, PropertyModel } from "./types";
2
+ import { OrmError } from "../errors";
3
+
4
+ /** Structural, typed primary-key identity; never joins component strings. */
5
+ export class KeyTuple {
6
+ private constructor(readonly values: readonly unknown[], private readonly signature: string) {}
7
+ static fromEntity(model: EntityModel, entity: Record<string, unknown>): KeyTuple | undefined {
8
+ const values = model.key.map((property) => entity[property.propertyName]);
9
+ return values.some((value) => value === null || value === undefined) ? undefined : KeyTuple.fromValues(model.key, values);
10
+ }
11
+ static fromInput(model: EntityModel, input: unknown): KeyTuple {
12
+ const properties = model.key;
13
+ const values = properties.length === 1 && (typeof input !== "object" || input === null || input instanceof Date || input instanceof Uint8Array)
14
+ ? [input]
15
+ : readObject(properties, input);
16
+ if (values.some((value) => value === null || value === undefined)) throw new OrmError(`Primary key for "${model.name}" is incomplete.`);
17
+ return KeyTuple.fromValues(properties, values);
18
+ }
19
+ private static fromValues(properties: readonly PropertyModel[], values: readonly unknown[]): KeyTuple {
20
+ return new KeyTuple([...values], JSON.stringify(values.map((value, index) => [properties[index]!.type, stable(value)])));
21
+ }
22
+ equals(other: KeyTuple): boolean { return this.signature === other.signature; }
23
+ toString(): string { return this.signature; }
24
+ }
25
+ function readObject(properties: readonly PropertyModel[], input: unknown): unknown[] {
26
+ if (!input || typeof input !== "object" || Array.isArray(input)) throw new OrmError("Composite primary key requires an object with every key component.");
27
+ const record = input as Record<string, unknown>; const expected = new Set(properties.map((property) => property.propertyName));
28
+ for (const name of Object.keys(record)) if (!expected.has(name)) throw new OrmError(`Primary key has unexpected component "${name}".`);
29
+ return properties.map((property) => { if (!(property.propertyName in record)) throw new OrmError(`Primary key is missing component "${property.propertyName}".`); return record[property.propertyName]; });
30
+ }
31
+ function stable(value: unknown): unknown {
32
+ if (value instanceof Date) return ["date", value.toISOString()];
33
+ if (value instanceof Uint8Array) return ["bytes", [...value]];
34
+ if (typeof value === "bigint") return ["bigint", value.toString()];
35
+ return [typeof value, value];
36
+ }