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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alexander Alenin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # bazis
2
+
3
+ A modular backend framework for [Bun](https://bun.com), written in TypeScript:
4
+ constructor dependency injection wired by code generation, HTTP controllers
5
+ with validated request models, an ORM for PostgreSQL, configuration with
6
+ per-environment defaults, JWT, WebSocket, gRPC, background services, AI agents
7
+ and a CLI that scaffolds, runs, tests and compiles your app into a single
8
+ executable.
9
+
10
+ The package ships TypeScript sources and runs on Bun only (≥ 1.4.0). There is
11
+ no build step and no separate type package.
12
+
13
+ ## Quick start
14
+
15
+ ```sh
16
+ bunx bazis new MyApp
17
+ cd my-app
18
+ bun install
19
+ bunx bazis dev # GET http://127.0.0.1:3000/health
20
+ ```
21
+
22
+ `bazis new` creates a project with `src/index.ts`, a root `AppModule`,
23
+ `bazis.config.json`, scripts, a `/health` test and an `.env.example`.
24
+
25
+ ## CLI
26
+
27
+ | Command | What it does |
28
+ | --- | --- |
29
+ | `bazis new <Name>` | Create a project in `./<name>` |
30
+ | `bazis g module <Name> --empty\|--minimal\|--full` | Add a module: empty; CRUD with ORM, validation and paging; or the same with auth guards |
31
+ | `bazis g pack <Name> --parts a,b` | Add a composite module made of several atomic ones |
32
+ | `bazis codegen` | Regenerate dependency wiring into `src/generated/bazis` |
33
+ | `bazis dev [--watch]` | Codegen, then run the app from source with `BAZIS_ENV=development` (unless set); `--watch` restarts on changes in `src/` |
34
+ | `bazis test [args]` | Codegen, then `bun test` |
35
+ | `bazis build` | Codegen and typecheck |
36
+ | `bazis build --bin` | Also compile `bin/<name>`, a standalone executable |
37
+
38
+ `dev`, `test` and `build` run codegen themselves. If you start the app some
39
+ other way after changing code, it warns at startup that the generated code is
40
+ out of date. A compiled binary carries everything it needs and skips that
41
+ check.
42
+
43
+ ## A module
44
+
45
+ ```ts
46
+ // src/app/modules/greeting/Greeting.module.ts
47
+ import { Module, scoped } from "bazis/core/di";
48
+ import { Controller, Get } from "bazis/core/http";
49
+
50
+ export class GreetingService {
51
+ hello(name: string) {
52
+ return { message: `Hello, ${name}` };
53
+ }
54
+ }
55
+
56
+ @Controller("greetings")
57
+ export class GreetingController {
58
+ // No registration code: `bazis codegen` reads the constructor.
59
+ constructor(private readonly greetings: GreetingService) {}
60
+
61
+ @Get(":name")
62
+ get(name: string) {
63
+ return this.greetings.hello(name);
64
+ }
65
+ }
66
+
67
+ @Module({
68
+ controllers: [GreetingController],
69
+ providers: [scoped(GreetingService)],
70
+ exports: [GreetingService],
71
+ })
72
+ export class GreetingModule {}
73
+ ```
74
+
75
+ `bunx bazis g module Greeting --empty` creates this file with an empty module
76
+ and adds `GreetingModule` to the `imports` of `AppModule`. With the code above,
77
+ `GET /greetings/world` answers `{"message":"Hello, world"}`. Another module
78
+ that imports `GreetingModule` can take `GreetingService` in its own
79
+ constructor.
80
+
81
+ ## Database
82
+
83
+ ```ts
84
+ // src/app/infra/App.infra.ts
85
+ import { Infra } from "bazis/core/infra";
86
+ import { ormBazisConnect } from "bazis/core/orm";
87
+ import { dbConfig } from "../config/db.config"; // defineConfig("db", { default: { host, port, ... } })
88
+
89
+ @Infra({ db: ormBazisConnect(dbConfig) })
90
+ export class AppInfra {}
91
+
92
+ // src/index.ts
93
+ await runApp(AppModule, { infra: AppInfra, http: { port: 3000, health: true } });
94
+ ```
95
+
96
+ A feature module attaches its own `DbContext` and entities with
97
+ `ormBazis: { context, entities }`; its services take that context in their
98
+ constructors. `bunx bazis g module Task --minimal` generates such a module.
99
+ Configuration values can be overridden from the environment
100
+ (`BAZIS_DB__HOST`, `BAZIS_DB__PASSWORD`, ...). Invalid configuration or a
101
+ missing production secret stops startup with an error that names the key.
102
+
103
+ A unique index violation in `saveChanges()` rejects with
104
+ `UniqueViolationError` (with `constraint` and `table`); catch it to answer 409.
105
+ Request-body fields declared as `string`, `number` or `boolean` are checked
106
+ against the JSON type automatically (400 on mismatch); other rules come from
107
+ `@Validator`.
108
+
109
+ ## Example
110
+
111
+ The source repository contains `examples/todo`: three modules (projects,
112
+ tasks and a report), PostgreSQL, cross-module injection, validation, JSON:API
113
+ lists, an end-to-end test and a binary build.
114
+
115
+ ## Entry points
116
+
117
+ Import from the subpaths listed in `exports` of `package.json`:
118
+ `bazis/core/app`, `bazis/core/di`, `bazis/core/http`, `bazis/core/orm`,
119
+ `bazis/core/infra`, `bazis/core/kernel`, `bazis/library/validation`,
120
+ `bazis/library/jsonapi` and others. Anything not listed there is internal.
121
+
122
+ ## Language of built-in texts
123
+
124
+ Built-in texts are English. Russian sets ship with the package; apply them
125
+ once at startup:
126
+
127
+ ```ts
128
+ import { MessageRegistry, RU_VALIDATION_MESSAGES } from "bazis/library/validation";
129
+ import { CodexError, RU_CODEX_MESSAGES } from "bazis/core/infra";
130
+ import { RU_UI_LABELS } from "bazis/core/app";
131
+
132
+ MessageRegistry.setDefaults(RU_VALIDATION_MESSAGES); // validation errors
133
+ CodexError.useMessages(RU_CODEX_MESSAGES); // Codex connector errors
134
+ await runApp(AppModule, { ui: { labels: RU_UI_LABELS, surfaces: [/* ... */] } }); // generated UI texts
135
+ ```
136
+
137
+ Either call also accepts your own texts for some codes.
138
+
139
+ ## Status
140
+
141
+ Pre-1.0: a minor version (0.x) can contain breaking changes; a patch version
142
+ does not.
143
+
144
+ ## License
145
+
146
+ MIT
package/cli/build.ts ADDED
@@ -0,0 +1,147 @@
1
+ import { existsSync, mkdtempSync, rmSync, watch } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import path from "node:path";
4
+ import { resolveBun } from "./codegen";
5
+
6
+ type Codegen = (cwd: string, target?: string) => Promise<number>;
7
+
8
+ export interface BuildOptions {
9
+ /** Also compile the entrypoint into a standalone executable. */
10
+ readonly bin: boolean;
11
+ /** Executable path relative to the project; default `bin/<package name>`. */
12
+ readonly outfile?: string;
13
+ }
14
+
15
+ /**
16
+ * `bazis dev`: codegen, then run the default target's entrypoint from source.
17
+ * With `watch`, a change under src/ (except src/generated) stops the app,
18
+ * reruns codegen and starts it again; a failed codegen waits for the next change.
19
+ * The app runs as `development` unless BAZIS_ENV is set in the shell.
20
+ */
21
+ /** `bazis dev` means development; an BAZIS_ENV from the shell still wins. */
22
+ export function devEnvironment(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
23
+ return { ...env, BAZIS_ENV: env.BAZIS_ENV || "development" };
24
+ }
25
+
26
+ export async function runDev(cwd: string, codegen: Codegen, log: (message: string) => void, options: { readonly watch?: boolean } = {}): Promise<number> {
27
+ const bun = await resolveBun(cwd);
28
+ const entry = await projectEntry(cwd);
29
+ const env = devEnvironment(process.env);
30
+ if (!options.watch) {
31
+ const generated = await codegen(cwd);
32
+ if (generated !== 0) return generated;
33
+ const child = Bun.spawn([bun, "run", entry], { cwd, env, stdin: "inherit", stdout: "inherit", stderr: "inherit" });
34
+ // The app owns graceful shutdown; forward the signal instead of dying first.
35
+ const forward = (signal: NodeJS.Signals) => () => child.kill(signal);
36
+ const onInterrupt = forward("SIGINT"), onTerminate = forward("SIGTERM");
37
+ process.on("SIGINT", onInterrupt);
38
+ process.on("SIGTERM", onTerminate);
39
+ try {
40
+ return await child.exited;
41
+ } finally {
42
+ process.off("SIGINT", onInterrupt);
43
+ process.off("SIGTERM", onTerminate);
44
+ }
45
+ }
46
+
47
+ let child: ReturnType<typeof Bun.spawn> | undefined;
48
+ let queue = Promise.resolve();
49
+ let timer: ReturnType<typeof setTimeout> | undefined;
50
+ const stop = async () => {
51
+ if (!child) return;
52
+ const running = child;
53
+ child = undefined;
54
+ running.kill("SIGTERM");
55
+ await running.exited;
56
+ };
57
+ const start = async () => {
58
+ if (await codegen(cwd) !== 0) { log("[bazis] codegen failed; waiting for changes..."); return; }
59
+ child = Bun.spawn([bun, "run", entry], { cwd, env, stdin: "inherit", stdout: "inherit", stderr: "inherit" });
60
+ };
61
+ const watcher = watch(path.join(cwd, "src"), { recursive: true }, (_event, file) => {
62
+ // codegen writes src/generated: watching it would restart forever.
63
+ if (!file || /^generated([\\/]|$)/.test(String(file))) return;
64
+ clearTimeout(timer);
65
+ timer = setTimeout(() => {
66
+ queue = queue.then(async () => { log(`[bazis] ${file} changed, restarting...`); await stop(); await start(); });
67
+ }, 150);
68
+ });
69
+ const finished = Promise.withResolvers<number>();
70
+ const shutdown = () => {
71
+ watcher.close();
72
+ clearTimeout(timer);
73
+ queue = queue.then(stop).then(() => finished.resolve(0), () => finished.resolve(1));
74
+ };
75
+ process.once("SIGINT", shutdown);
76
+ process.once("SIGTERM", shutdown);
77
+ log("[bazis] watching src/ for changes (Ctrl+C to stop)");
78
+ queue = queue.then(start);
79
+ try {
80
+ return await finished.promise;
81
+ } finally {
82
+ process.off("SIGINT", shutdown);
83
+ process.off("SIGTERM", shutdown);
84
+ }
85
+ }
86
+
87
+ /** `bazis test [args]`: codegen, then `bun test` with the given arguments. */
88
+ export async function runTest(cwd: string, args: readonly string[], codegen: Codegen): Promise<number> {
89
+ const generated = await codegen(cwd);
90
+ if (generated !== 0) return generated;
91
+ return await Bun.spawn([await resolveBun(cwd), "test", ...args], { cwd, stdin: "inherit", stdout: "inherit", stderr: "inherit" }).exited;
92
+ }
93
+
94
+ /** `bazis build [--bin]`: codegen and typecheck; with `bin`, also compile. */
95
+ export async function runBuild(cwd: string, options: BuildOptions, codegen: Codegen, log: (message: string) => void): Promise<number> {
96
+ const generated = await codegen(cwd);
97
+ if (generated !== 0) return generated;
98
+ const bun = await resolveBun(cwd);
99
+ const tsc = path.join(cwd, "node_modules/typescript/bin/tsc");
100
+ if (!existsSync(tsc)) throw new Error("TypeScript is not installed in this project. Run: bun add -d typescript");
101
+ log("[bazis] typecheck...");
102
+ const typecheck = await Bun.spawn([bun, tsc, "--noEmit"], { cwd, stdout: "inherit", stderr: "inherit" }).exited;
103
+ if (typecheck !== 0 || !options.bin) return typecheck;
104
+ const outfile = path.resolve(cwd, options.outfile ?? path.join("bin", await binaryName(cwd)));
105
+ log(`[bazis] compile ${path.relative(cwd, outfile)}...`);
106
+ return compileBinary(bun, await projectEntry(cwd), outfile);
107
+ }
108
+
109
+ /**
110
+ * `bun build --compile` clones the running Bun executable into a temporary
111
+ * `.<hash>.bun-build` file in its working directory and cannot remove it when
112
+ * that executable is read-only or carries `uchg` (scripts/bazis-bun). Compile
113
+ * from a private directory and remove it afterwards.
114
+ */
115
+ export function compileBinary(bun: string, entry: string, outfile: string): number {
116
+ const workDir = mkdtempSync(path.join(tmpdir(), "bazis-compile-"));
117
+ try {
118
+ const result = Bun.spawnSync([bun, "build", "--compile", path.resolve(entry), "--outfile", path.resolve(outfile)],
119
+ { cwd: workDir, stdout: "inherit", stderr: "inherit" });
120
+ return result.exitCode ?? 1;
121
+ } finally {
122
+ if (existsSync("/usr/bin/chflags")) Bun.spawnSync(["/usr/bin/chflags", "-R", "nouchg", workDir]);
123
+ try {
124
+ rmSync(workDir, { recursive: true, force: true });
125
+ } catch (error) {
126
+ // The binary itself is complete; report the leftover without failing the build.
127
+ console.error(`[bazis] temporary directory was not removed: ${workDir}`, error);
128
+ }
129
+ }
130
+ }
131
+
132
+ async function projectEntry(cwd: string): Promise<string> {
133
+ const configFile = Bun.file(path.join(cwd, "bazis.config.json"));
134
+ if (!await configFile.exists()) throw new Error("bazis.config.json not found in the current directory.");
135
+ const config = await configFile.json() as { defaultTarget?: string; targets?: Record<string, { entrypoints?: unknown }> };
136
+ const entry = (config.targets?.[config.defaultTarget ?? ""]?.entrypoints as unknown[] | undefined)?.[0];
137
+ if (typeof entry !== "string" || !entry) throw new Error("bazis.config.json has no entrypoint for its default target.");
138
+ return path.resolve(cwd, entry);
139
+ }
140
+
141
+ async function binaryName(cwd: string): Promise<string> {
142
+ const manifest = Bun.file(path.join(cwd, "package.json"));
143
+ const name = await manifest.exists() ? (await manifest.json() as { name?: unknown }).name : undefined;
144
+ const base = typeof name === "string" ? name.replace(/^@[^/]+\//, "").replace(/[^a-z0-9._-]+/gi, "-") : "";
145
+ if (!base) throw new Error("package.json needs a name for the default binary path; pass --outfile.");
146
+ return base;
147
+ }
package/cli/codegen.ts ADDED
@@ -0,0 +1,40 @@
1
+ import { existsSync } from "node:fs";
2
+ import path from "node:path";
3
+
4
+ const GENERATOR = "core/scripts/di-generate.ts";
5
+
6
+ /** Run the framework generator for the project in `cwd`; returns its exit code. */
7
+ export async function runCodegen(cwd: string, target?: string): Promise<number> {
8
+ if (target !== undefined) {
9
+ const configFile = Bun.file(path.join(cwd, "bazis.config.json"));
10
+ if (!await configFile.exists()) throw new Error("--target requires bazis.config.json in the current directory.");
11
+ const config = await configFile.json();
12
+ if (target !== "all" && !Object.hasOwn(config.targets ?? {}, target)) throw new Error(`Unknown codegen target: ${target}`);
13
+ }
14
+ const args = [await resolveBun(cwd), resolveGenerator(cwd), ...(target === undefined ? [] : ["--target", target])];
15
+ return await Bun.spawn(args, { cwd, stdout: "inherit", stderr: "inherit" }).exited;
16
+ }
17
+
18
+ /**
19
+ * The generator of the framework this project uses: the installed package,
20
+ * the framework source checkout, or the package this CLI runs from.
21
+ */
22
+ export function resolveGenerator(cwd: string): string {
23
+ const candidates = [
24
+ path.join(cwd, "node_modules/bazis", GENERATOR),
25
+ path.join(cwd, "src/bazis", GENERATOR),
26
+ path.resolve(import.meta.dir, "..", GENERATOR),
27
+ ];
28
+ const generator = candidates.find((candidate) => existsSync(candidate));
29
+ if (!generator) throw new Error("bazis code generator not found. Install the framework in this project: bun add bazis");
30
+ return generator;
31
+ }
32
+
33
+ /** Bun for child processes: the project's qualified launcher when present. */
34
+ export async function resolveBun(cwd: string): Promise<string> {
35
+ const wrapper = path.join(cwd, "scripts/bazis-bun");
36
+ // process.execPath can be the compiled CLI itself. Never invoke it as Bun.
37
+ const executable = await Bun.file(wrapper).exists() ? wrapper : (process.env.BAZIS_BUN_BIN || Bun.which("bun"));
38
+ if (!executable) throw new Error("Bun was not found. Set BAZIS_BUN_BIN or put Bun on PATH.");
39
+ return executable;
40
+ }
@@ -0,0 +1,187 @@
1
+ import path from "node:path";
2
+ import { randomUUID } from "node:crypto";
3
+ import { lstat, mkdir, readFile, realpath, rename, rm, rmdir, writeFile } from "node:fs/promises";
4
+ import { buildModuleTemplates, type ModuleTemplateFiles, type ModuleTemplateProfile } from "./templates/module";
5
+ import { buildPackTemplates } from "./templates/pack";
6
+ import { parseModuleName, type ModuleNaming } from "./naming";
7
+ import { moduleImportPath, registerModuleInSource } from "./moduleRegistration";
8
+
9
+ export interface GenerateModuleOptions {
10
+ /** User, users, order-item. */
11
+ readonly name: string;
12
+ /** Default: src/app/modules, relative to cwd. */
13
+ readonly modulesRoot?: string;
14
+ /** Default: {modulesRoot}/App.module.ts, relative to cwd. */
15
+ readonly appModulePath?: string;
16
+ readonly register?: boolean;
17
+ readonly force?: boolean;
18
+ readonly profile?: ModuleTemplateProfile;
19
+ /** Validate and return the plan without writing files. */
20
+ readonly dryRun?: boolean;
21
+ }
22
+
23
+ export interface GenerateModulePackOptions extends Omit<GenerateModuleOptions, "profile"> {
24
+ readonly parts: readonly string[];
25
+ }
26
+
27
+ export interface GenerateModuleResult {
28
+ readonly moduleDir: string;
29
+ readonly files: readonly string[];
30
+ /** In dry-run, whether the resulting plan connects the module. */
31
+ readonly registered: boolean;
32
+ readonly dryRun: boolean;
33
+ readonly changes: readonly { readonly path: string; readonly action: "create" | "update" }[];
34
+ readonly warnings: readonly string[];
35
+ }
36
+
37
+ interface PlannedWrite {
38
+ readonly absolute: string;
39
+ readonly content: string;
40
+ readonly original: string | undefined;
41
+ }
42
+
43
+ export async function generateModule(options: GenerateModuleOptions): Promise<GenerateModuleResult> {
44
+ const naming = parseModuleName(options.name);
45
+ const profile = options.profile ?? "minimal";
46
+ if (!["empty", "minimal", "full"].includes(profile)) throw new Error(`Unknown profile: ${profile}`);
47
+ const modulesRoot = await canonicalDirectory(path.resolve(options.modulesRoot ?? "src/app/modules"));
48
+ let authImportPath: string | null | undefined;
49
+ if (profile === "full") {
50
+ // The host's auth helpers are optional: without them the controller is
51
+ // generated without @Authorize and the command says so.
52
+ const authDir = path.resolve("src/app/modules/auth");
53
+ const helpers = await Promise.all(["tokenKinds.ts", "jwtAuth.ts"].map(async (helper) => (await fileInfo(path.join(authDir, helper)))?.isFile() === true));
54
+ authImportPath = helpers.every(Boolean)
55
+ ? moduleImportPath(path.join(modulesRoot, naming.folder, "http", `${naming.module}.controller.ts`), await canonicalDirectory(authDir))
56
+ : null;
57
+ }
58
+ const result = await generateFiles(options, naming, naming.folder, buildModuleTemplates(naming, profile, authImportPath));
59
+ return authImportPath === null
60
+ ? { ...result, warnings: [...result.warnings, "No auth helpers in src/app/modules/auth: the full profile controller has no @Authorize. Protect its routes before exposing them."] }
61
+ : result;
62
+ }
63
+
64
+ export async function generateModulePack(options: GenerateModulePackOptions): Promise<GenerateModuleResult> {
65
+ const naming = parseModuleName(options.name);
66
+ return generateFiles(options, naming, `${naming.folder}_modules`, buildPackTemplates(naming, options.parts));
67
+ }
68
+
69
+ async function generateFiles(options: GenerateModuleOptions, naming: ModuleNaming, folder: string, templates: readonly ModuleTemplateFiles[]): Promise<GenerateModuleResult> {
70
+ const modulesRoot = await canonicalDirectory(path.resolve(options.modulesRoot ?? "src/app/modules"));
71
+ const moduleDir = path.join(modulesRoot, folder);
72
+ const requestedAppPath = path.resolve(options.appModulePath ?? path.join(modulesRoot, "App.module.ts"));
73
+ const appModulePath = path.join(await canonicalDirectory(path.dirname(requestedAppPath)), path.basename(requestedAppPath));
74
+ const moduleInfo = await fileInfo(moduleDir);
75
+ if (moduleInfo && !options.force) throw new Error(`Module folder already exists: ${moduleDir}. Use --force to overwrite.`);
76
+ if (moduleInfo && !moduleInfo.isDirectory()) throw new Error(`Module path is not a directory: ${moduleDir}.`);
77
+
78
+ const featureWrites: PlannedWrite[] = [];
79
+ for (const file of templates) {
80
+ const absolute = path.join(moduleDir, file.relativePath);
81
+ const info = await fileInfo(absolute);
82
+ if (info && !options.force) throw new Error(`File already exists: ${absolute}. Use --force to overwrite.`);
83
+ if (info && !info.isFile()) throw new Error(`Refusing to overwrite a non-regular file: ${absolute}`);
84
+ featureWrites.push({ absolute, content: file.content, original: info ? await readFile(absolute, "utf8") : undefined });
85
+ }
86
+
87
+ // Complete host preflight before the first write, including on --force.
88
+ const writes = [...featureWrites];
89
+ const warnings: string[] = [];
90
+ let registered = false;
91
+ if (options.register !== false) {
92
+ const appInfo = await fileInfo(appModulePath);
93
+ if (!appInfo) {
94
+ warnings.push(`App module not found, skipped registration: ${appModulePath}`);
95
+ } else {
96
+ if (!appInfo.isFile()) throw new Error(`App module must be a regular file: ${appModulePath}`);
97
+ const original = await readFile(appModulePath, "utf8");
98
+ const content = registerModuleInSource(original, appModulePath, path.join(moduleDir, `${naming.module}.module.ts`), naming.moduleClass);
99
+ if (content !== original) writes.push({ absolute: appModulePath, content, original });
100
+ registered = true;
101
+ }
102
+ }
103
+ const changed = writes.filter((write) => write.content !== write.original);
104
+ if (!options.dryRun) await commitWrites(changed);
105
+ return {
106
+ moduleDir,
107
+ files: featureWrites.map((write) => path.relative(process.cwd(), write.absolute)),
108
+ registered, dryRun: options.dryRun === true, warnings,
109
+ changes: changed.map((write) => ({ path: path.relative(process.cwd(), write.absolute), action: write.original === undefined ? "create" : "update" })),
110
+ };
111
+ }
112
+
113
+ async function fileInfo(absolute: string) {
114
+ try {
115
+ return await lstat(absolute);
116
+ } catch (error) {
117
+ const code = (error as NodeJS.ErrnoException).code;
118
+ if (code === "ENOENT" || code === "ENOTDIR") return undefined;
119
+ throw error;
120
+ }
121
+ }
122
+
123
+ /** Relative imports must survive runtime realpath resolution (e.g. /var -> /private/var). */
124
+ async function canonicalDirectory(directory: string): Promise<string> {
125
+ try {
126
+ return await realpath(directory);
127
+ } catch (error) {
128
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
129
+ const parent = path.dirname(directory);
130
+ if (parent === directory) throw error;
131
+ return path.join(await canonicalDirectory(parent), path.basename(directory));
132
+ }
133
+ }
134
+
135
+ async function commitWrites(writes: readonly PlannedWrite[]): Promise<void> {
136
+ const completed: PlannedWrite[] = [];
137
+ const createdDirectories = new Set<string>();
138
+ try {
139
+ for (const write of writes) {
140
+ const current = await fileInfo(write.absolute);
141
+ if ((current ? await readFile(write.absolute, "utf8") : undefined) !== write.original) {
142
+ throw new Error(`File changed after generation was planned: ${write.absolute}`);
143
+ }
144
+ await writeAtomically(write.absolute, write.content, createdDirectories);
145
+ completed.push(write);
146
+ }
147
+ } catch (error) {
148
+ const rollbackErrors: unknown[] = [];
149
+ for (const write of completed.reverse()) {
150
+ try {
151
+ if (write.original === undefined) await rm(write.absolute, { force: true });
152
+ else await writeAtomically(write.absolute, write.original, createdDirectories);
153
+ } catch (rollbackError) {
154
+ rollbackErrors.push(rollbackError);
155
+ }
156
+ }
157
+ for (const directory of [...createdDirectories].sort((a, b) => b.length - a.length)) {
158
+ try {
159
+ await rmdir(directory);
160
+ } catch (cleanupError) {
161
+ const code = (cleanupError as NodeJS.ErrnoException).code;
162
+ // Preserve files another writer may have added to a new directory.
163
+ if (code !== "ENOTEMPTY" && code !== "ENOENT") rollbackErrors.push(cleanupError);
164
+ }
165
+ }
166
+ if (rollbackErrors.length) throw new AggregateError([error, ...rollbackErrors], "Module generation failed and rollback was incomplete.");
167
+ throw error;
168
+ }
169
+ }
170
+
171
+ async function writeAtomically(absolute: string, content: string, createdDirectories: Set<string>): Promise<void> {
172
+ const parent = path.dirname(absolute);
173
+ const firstCreated = await mkdir(parent, { recursive: true });
174
+ if (firstCreated) {
175
+ for (let directory = parent; ; directory = path.dirname(directory)) {
176
+ createdDirectories.add(directory);
177
+ if (directory === firstCreated) break;
178
+ }
179
+ }
180
+ const temporary = path.join(parent, `.${path.basename(absolute)}.bazis-${randomUUID()}.tmp`);
181
+ try {
182
+ await writeFile(temporary, content, { encoding: "utf8", flag: "wx" });
183
+ await rename(temporary, absolute);
184
+ } finally {
185
+ await rm(temporary, { force: true });
186
+ }
187
+ }