@zintrust/core 0.1.18 → 0.1.20

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 (558) hide show
  1. package/README.md +16 -10
  2. package/bin/zintrust-main.d.ts.map +1 -1
  3. package/bin/zintrust-main.js +9 -0
  4. package/package.json +11 -2
  5. package/public/error-pages/404.html +145 -0
  6. package/public/error-pages/500.html +266 -0
  7. package/public/error-pages/error.css +628 -0
  8. package/public/error-pages/error.js +428 -0
  9. package/public/index.html +1 -1
  10. package/public/zintrust.svg +30 -0
  11. package/routes/api.d.ts +7 -0
  12. package/routes/api.d.ts.map +1 -0
  13. package/routes/api.js +115 -0
  14. package/routes/broadcast.d.ts +9 -0
  15. package/routes/broadcast.d.ts.map +1 -0
  16. package/routes/broadcast.js +27 -0
  17. package/routes/health.d.ts +7 -0
  18. package/routes/health.d.ts.map +1 -0
  19. package/routes/health.js +127 -0
  20. package/routes/metrics.d.ts +9 -0
  21. package/routes/metrics.d.ts.map +1 -0
  22. package/routes/metrics.js +20 -0
  23. package/routes/openapi.d.ts +9 -0
  24. package/routes/openapi.d.ts.map +1 -0
  25. package/routes/openapi.js +76 -0
  26. package/routes/storage.d.ts +4 -0
  27. package/routes/storage.d.ts.map +1 -0
  28. package/routes/storage.js +35 -0
  29. package/src/boot/Application.d.ts +2 -2
  30. package/src/boot/Application.d.ts.map +1 -1
  31. package/src/boot/Application.js +18 -3
  32. package/src/boot/Server.d.ts +3 -2
  33. package/src/boot/Server.d.ts.map +1 -1
  34. package/src/boot/Server.js +39 -165
  35. package/src/boot/bootstrap.js +1 -1
  36. package/src/cache/Cache.d.ts +1 -1
  37. package/src/cache/Cache.d.ts.map +1 -1
  38. package/src/cache/CacheDriver.d.ts +4 -0
  39. package/src/cache/CacheDriver.d.ts.map +1 -1
  40. package/src/cache/drivers/KVDriver.d.ts +1 -1
  41. package/src/cache/drivers/KVDriver.d.ts.map +1 -1
  42. package/src/cache/drivers/MemoryDriver.d.ts +1 -1
  43. package/src/cache/drivers/MemoryDriver.d.ts.map +1 -1
  44. package/src/cache/drivers/MemoryDriver.js +16 -0
  45. package/src/cache/drivers/MongoDriver.d.ts +1 -1
  46. package/src/cache/drivers/MongoDriver.d.ts.map +1 -1
  47. package/src/cache/drivers/RedisDriver.d.ts +1 -1
  48. package/src/cache/drivers/RedisDriver.d.ts.map +1 -1
  49. package/src/cli/CLI.d.ts.map +1 -1
  50. package/src/cli/CLI.js +12 -4
  51. package/src/cli/PromptHelper.d.ts.map +1 -1
  52. package/src/cli/PromptHelper.js +4 -3
  53. package/src/cli/commands/AddCommand.d.ts +2 -2
  54. package/src/cli/commands/AddCommand.d.ts.map +1 -1
  55. package/src/cli/commands/AddCommand.js +135 -58
  56. package/src/cli/commands/ConfigCommand.d.ts +1 -1
  57. package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
  58. package/src/cli/commands/CreateCommand.d.ts +15 -0
  59. package/src/cli/commands/CreateCommand.d.ts.map +1 -0
  60. package/src/cli/commands/CreateCommand.js +143 -0
  61. package/src/cli/commands/D1MigrateCommand.d.ts +1 -1
  62. package/src/cli/commands/D1MigrateCommand.d.ts.map +1 -1
  63. package/src/cli/commands/D1MigrateCommand.js +16 -20
  64. package/src/cli/commands/DbSeedCommand.d.ts +9 -0
  65. package/src/cli/commands/DbSeedCommand.d.ts.map +1 -0
  66. package/src/cli/commands/DbSeedCommand.js +171 -0
  67. package/src/cli/commands/DebugCommand.d.ts +1 -1
  68. package/src/cli/commands/DebugCommand.d.ts.map +1 -1
  69. package/src/cli/commands/FixCommand.d.ts +1 -1
  70. package/src/cli/commands/FixCommand.d.ts.map +1 -1
  71. package/src/cli/commands/JwtDevCommand.d.ts +8 -0
  72. package/src/cli/commands/JwtDevCommand.d.ts.map +1 -0
  73. package/src/cli/commands/JwtDevCommand.js +114 -0
  74. package/src/cli/commands/KeyGenerateCommand.d.ts +1 -1
  75. package/src/cli/commands/KeyGenerateCommand.d.ts.map +1 -1
  76. package/src/cli/commands/LogsCommand.d.ts +2 -2
  77. package/src/cli/commands/LogsCommand.d.ts.map +1 -1
  78. package/src/cli/commands/LogsCommand.js +36 -2
  79. package/src/cli/commands/MakeMailTemplateCommand.d.ts +1 -1
  80. package/src/cli/commands/MakeMailTemplateCommand.d.ts.map +1 -1
  81. package/src/cli/commands/MakeNotificationTemplateCommand.d.ts +1 -1
  82. package/src/cli/commands/MakeNotificationTemplateCommand.d.ts.map +1 -1
  83. package/src/cli/commands/MigrateCommand.d.ts +1 -1
  84. package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
  85. package/src/cli/commands/MigrateCommand.js +291 -35
  86. package/src/cli/commands/NewCommand.d.ts +2 -2
  87. package/src/cli/commands/NewCommand.d.ts.map +1 -1
  88. package/src/cli/commands/NewCommand.js +38 -13
  89. package/src/cli/commands/PluginCommand.d.ts +1 -1
  90. package/src/cli/commands/PluginCommand.d.ts.map +1 -1
  91. package/src/cli/commands/PrepareCommand.d.ts +1 -1
  92. package/src/cli/commands/PrepareCommand.d.ts.map +1 -1
  93. package/src/cli/commands/QACommand.d.ts +2 -2
  94. package/src/cli/commands/QACommand.d.ts.map +1 -1
  95. package/src/cli/commands/RoutesCommand.d.ts +10 -0
  96. package/src/cli/commands/RoutesCommand.d.ts.map +1 -0
  97. package/src/cli/commands/RoutesCommand.js +242 -0
  98. package/src/cli/commands/SimulateCommand.d.ts +1 -1
  99. package/src/cli/commands/SimulateCommand.d.ts.map +1 -1
  100. package/src/cli/commands/SimulateCommand.js +1 -1
  101. package/src/cli/commands/StartCommand.d.ts.map +1 -1
  102. package/src/cli/commands/StartCommand.js +90 -3
  103. package/src/cli/commands/UpgradeCommand.d.ts +16 -0
  104. package/src/cli/commands/UpgradeCommand.d.ts.map +1 -0
  105. package/src/cli/commands/UpgradeCommand.js +107 -0
  106. package/src/cli/commands/index.d.ts +3 -0
  107. package/src/cli/commands/index.d.ts.map +1 -1
  108. package/src/cli/commands/index.js +3 -0
  109. package/src/cli/commands/runner/index.d.ts +3 -0
  110. package/src/cli/commands/runner/index.d.ts.map +1 -0
  111. package/src/cli/commands/runner/index.js +139 -0
  112. package/src/cli/config/ConfigManager.d.ts +1 -1
  113. package/src/cli/config/ConfigManager.d.ts.map +1 -1
  114. package/src/cli/config/ConfigValidator.d.ts +1 -1
  115. package/src/cli/config/ConfigValidator.d.ts.map +1 -1
  116. package/src/cli/config/ConfigValidator.js +1 -1
  117. package/src/cli/d1/D1SqlMigrations.d.ts +20 -0
  118. package/src/cli/d1/D1SqlMigrations.d.ts.map +1 -0
  119. package/src/cli/d1/D1SqlMigrations.js +224 -0
  120. package/src/cli/d1/WranglerConfig.d.ts +4 -0
  121. package/src/cli/d1/WranglerConfig.d.ts.map +1 -0
  122. package/src/cli/d1/WranglerConfig.js +122 -0
  123. package/src/cli/d1/WranglerD1.d.ts +11 -0
  124. package/src/cli/d1/WranglerD1.d.ts.map +1 -0
  125. package/src/cli/d1/WranglerD1.js +16 -0
  126. package/src/cli/env/EnvFileBackfill.d.ts +10 -0
  127. package/src/cli/env/EnvFileBackfill.d.ts.map +1 -0
  128. package/src/cli/env/EnvFileBackfill.js +64 -0
  129. package/src/cli/scaffolding/ControllerGenerator.d.ts.map +1 -1
  130. package/src/cli/scaffolding/ControllerGenerator.js +72 -22
  131. package/src/cli/scaffolding/FactoryGenerator.d.ts.map +1 -1
  132. package/src/cli/scaffolding/FactoryGenerator.js +3 -1
  133. package/src/cli/scaffolding/GovernanceScaffolder.d.ts +23 -0
  134. package/src/cli/scaffolding/GovernanceScaffolder.d.ts.map +1 -0
  135. package/src/cli/scaffolding/GovernanceScaffolder.js +327 -0
  136. package/src/cli/scaffolding/MigrationGenerator.d.ts +10 -0
  137. package/src/cli/scaffolding/MigrationGenerator.d.ts.map +1 -1
  138. package/src/cli/scaffolding/MigrationGenerator.js +137 -51
  139. package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
  140. package/src/cli/scaffolding/ProjectScaffolder.js +54 -59
  141. package/src/cli/scaffolding/RouteGenerator.d.ts.map +1 -1
  142. package/src/cli/scaffolding/RouteGenerator.js +79 -43
  143. package/src/cli/scaffolding/SeederGenerator.d.ts +5 -0
  144. package/src/cli/scaffolding/SeederGenerator.d.ts.map +1 -1
  145. package/src/cli/scaffolding/SeederGenerator.js +63 -15
  146. package/src/cli/scaffolding/ServiceScaffolder.d.ts.map +1 -1
  147. package/src/cli/scaffolding/ServiceScaffolder.js +24 -3
  148. package/src/cli/scaffolding/index.d.ts +2 -0
  149. package/src/cli/scaffolding/index.d.ts.map +1 -1
  150. package/src/cli/scaffolding/index.js +1 -0
  151. package/src/cli/utils/DistPackager.d.ts.map +1 -1
  152. package/src/cli/utils/DistPackager.js +8 -0
  153. package/src/common/index.d.ts +8 -0
  154. package/src/common/index.d.ts.map +1 -1
  155. package/src/common/index.js +28 -0
  156. package/src/common/utility.d.ts +38 -0
  157. package/src/common/utility.d.ts.map +1 -0
  158. package/src/common/utility.js +101 -0
  159. package/src/config/FileLogWriter.d.ts +2 -1
  160. package/src/config/FileLogWriter.d.ts.map +1 -1
  161. package/src/config/FileLogWriter.js +83 -2
  162. package/src/config/app.d.ts.map +1 -1
  163. package/src/config/app.js +3 -1
  164. package/src/config/broadcast.d.ts +1 -1
  165. package/src/config/broadcast.d.ts.map +1 -1
  166. package/src/config/broadcast.js +1 -1
  167. package/src/config/cache.d.ts +1 -1
  168. package/src/config/cache.d.ts.map +1 -1
  169. package/src/config/cloudflare.d.ts +1 -1
  170. package/src/config/cloudflare.d.ts.map +1 -1
  171. package/src/config/database.d.ts +7 -1
  172. package/src/config/database.d.ts.map +1 -1
  173. package/src/config/database.js +99 -7
  174. package/src/config/env.d.ts +6 -0
  175. package/src/config/env.d.ts.map +1 -1
  176. package/src/config/env.js +7 -0
  177. package/src/config/index.d.ts +8 -2
  178. package/src/config/index.d.ts.map +1 -1
  179. package/src/config/logging/KvLogger.js +1 -1
  180. package/src/config/logging/SlackLogger.js +2 -2
  181. package/src/config/middleware.d.ts +22 -2
  182. package/src/config/middleware.d.ts.map +1 -1
  183. package/src/config/middleware.js +179 -11
  184. package/src/config/notification.js +1 -1
  185. package/src/config/security.d.ts +1 -1
  186. package/src/config/security.js +1 -1
  187. package/src/config/storage.js +1 -1
  188. package/src/config/type.d.ts +8 -2
  189. package/src/config/type.d.ts.map +1 -1
  190. package/src/events/EventDispatcher.d.ts.map +1 -1
  191. package/src/events/EventDispatcher.js +6 -4
  192. package/src/exceptions/ZintrustError.d.ts +7 -0
  193. package/src/exceptions/ZintrustError.d.ts.map +1 -1
  194. package/src/exceptions/ZintrustError.js +56 -0
  195. package/src/features/Auth.d.ts +1 -1
  196. package/src/features/Auth.d.ts.map +1 -1
  197. package/src/features/Auth.js +3 -3
  198. package/src/features/Queue.js +1 -1
  199. package/src/functions/cloudflare.d.ts.map +1 -1
  200. package/src/functions/cloudflare.js +3 -14
  201. package/src/functions/deno.d.ts.map +1 -1
  202. package/src/functions/deno.js +3 -14
  203. package/src/functions/lambda.d.ts.map +1 -1
  204. package/src/functions/lambda.js +3 -14
  205. package/src/health/StartupHealthChecks.js +1 -1
  206. package/src/http/Controller.d.ts +2 -2
  207. package/src/http/Controller.d.ts.map +1 -1
  208. package/src/http/FileUpload.d.ts +68 -0
  209. package/src/http/FileUpload.d.ts.map +1 -0
  210. package/src/http/FileUpload.js +120 -0
  211. package/src/http/Kernel.d.ts +5 -5
  212. package/src/http/Kernel.d.ts.map +1 -1
  213. package/src/http/Kernel.js +139 -23
  214. package/src/http/Request.d.ts +20 -1
  215. package/src/http/Request.d.ts.map +1 -1
  216. package/src/http/Request.js +23 -0
  217. package/src/http/RequestContext.d.ts +6 -0
  218. package/src/http/RequestContext.d.ts.map +1 -1
  219. package/src/http/RequestContext.js +77 -1
  220. package/src/http/Response.d.ts +1 -1
  221. package/src/http/Response.d.ts.map +1 -1
  222. package/src/http/ValidationHelper.d.ts +78 -0
  223. package/src/http/ValidationHelper.d.ts.map +1 -0
  224. package/src/http/ValidationHelper.js +121 -0
  225. package/src/http/error-pages/ErrorPageRenderer.d.ts +17 -0
  226. package/src/http/error-pages/ErrorPageRenderer.d.ts.map +1 -0
  227. package/src/http/error-pages/ErrorPageRenderer.js +88 -0
  228. package/src/http/middleware/BodyParsingMiddleware.d.ts +12 -0
  229. package/src/http/middleware/BodyParsingMiddleware.d.ts.map +1 -0
  230. package/src/http/middleware/BodyParsingMiddleware.js +251 -0
  231. package/src/http/middleware/FileUploadMiddleware.d.ts +12 -0
  232. package/src/http/middleware/FileUploadMiddleware.d.ts.map +1 -0
  233. package/src/http/middleware/FileUploadMiddleware.js +74 -0
  234. package/src/http/parsers/BodyParsers.d.ts +32 -0
  235. package/src/http/parsers/BodyParsers.d.ts.map +1 -0
  236. package/src/http/parsers/BodyParsers.js +159 -0
  237. package/src/http/parsers/MultipartParser.d.ts +33 -0
  238. package/src/http/parsers/MultipartParser.d.ts.map +1 -0
  239. package/src/http/parsers/MultipartParser.js +129 -0
  240. package/src/http/parsers/MultipartParserRegistry.d.ts +34 -0
  241. package/src/http/parsers/MultipartParserRegistry.d.ts.map +1 -0
  242. package/src/http/parsers/MultipartParserRegistry.js +20 -0
  243. package/src/http/validated.d.ts +12 -0
  244. package/src/http/validated.d.ts.map +1 -0
  245. package/src/http/validated.js +41 -0
  246. package/src/index.d.ts +65 -7
  247. package/src/index.d.ts.map +1 -1
  248. package/src/index.js +59 -5
  249. package/src/microservices/RequestTracingMiddleware.d.ts +2 -2
  250. package/src/microservices/RequestTracingMiddleware.d.ts.map +1 -1
  251. package/src/microservices/RequestTracingMiddleware.js +3 -0
  252. package/src/microservices/ServiceAuthMiddleware.d.ts +2 -2
  253. package/src/microservices/ServiceAuthMiddleware.d.ts.map +1 -1
  254. package/src/middleware/AuthMiddleware.d.ts +10 -0
  255. package/src/middleware/AuthMiddleware.d.ts.map +1 -0
  256. package/src/middleware/AuthMiddleware.js +16 -0
  257. package/src/middleware/CsrfMiddleware.d.ts +11 -1
  258. package/src/middleware/CsrfMiddleware.d.ts.map +1 -1
  259. package/src/middleware/CsrfMiddleware.js +33 -0
  260. package/src/middleware/JwtAuthMiddleware.d.ts +11 -0
  261. package/src/middleware/JwtAuthMiddleware.d.ts.map +1 -0
  262. package/src/middleware/JwtAuthMiddleware.js +73 -0
  263. package/src/middleware/LoggingMiddleware.d.ts.map +1 -1
  264. package/src/middleware/LoggingMiddleware.js +8 -3
  265. package/src/middleware/MiddlewareStack.d.ts +2 -2
  266. package/src/middleware/MiddlewareStack.d.ts.map +1 -1
  267. package/src/middleware/RateLimiter.d.ts +2 -2
  268. package/src/middleware/RateLimiter.d.ts.map +1 -1
  269. package/src/middleware/RateLimiter.js +26 -1
  270. package/src/middleware/SanitizeBodyMiddleware.d.ts +12 -0
  271. package/src/middleware/SanitizeBodyMiddleware.d.ts.map +1 -0
  272. package/src/middleware/SanitizeBodyMiddleware.js +31 -0
  273. package/src/middleware/SecurityMiddleware.d.ts +1 -1
  274. package/src/middleware/SecurityMiddleware.d.ts.map +1 -1
  275. package/src/middleware/SessionMiddleware.d.ts +1 -1
  276. package/src/middleware/SessionMiddleware.d.ts.map +1 -1
  277. package/src/middleware/ValidationMiddleware.d.ts +25 -0
  278. package/src/middleware/ValidationMiddleware.d.ts.map +1 -0
  279. package/src/middleware/ValidationMiddleware.js +251 -0
  280. package/src/migrations/MigrationDiscovery.d.ts +5 -0
  281. package/src/migrations/MigrationDiscovery.d.ts.map +1 -0
  282. package/src/migrations/MigrationDiscovery.js +16 -0
  283. package/src/migrations/MigrationLoader.d.ts +5 -0
  284. package/src/migrations/MigrationLoader.d.ts.map +1 -0
  285. package/src/migrations/MigrationLoader.js +43 -0
  286. package/src/migrations/MigrationLock.d.ts +4 -0
  287. package/src/migrations/MigrationLock.d.ts.map +1 -0
  288. package/src/migrations/MigrationLock.js +33 -0
  289. package/src/migrations/Migrator.d.ts +23 -0
  290. package/src/migrations/Migrator.d.ts.map +1 -0
  291. package/src/migrations/Migrator.js +4 -0
  292. package/src/migrations/MigratorFactory.d.ts +25 -0
  293. package/src/migrations/MigratorFactory.d.ts.map +1 -0
  294. package/src/migrations/MigratorFactory.js +323 -0
  295. package/src/migrations/schema/Blueprint.d.ts +5 -0
  296. package/src/migrations/schema/Blueprint.d.ts.map +1 -0
  297. package/src/migrations/schema/Blueprint.js +189 -0
  298. package/src/migrations/schema/Schema.d.ts +8 -0
  299. package/src/migrations/schema/Schema.d.ts.map +1 -0
  300. package/src/migrations/schema/Schema.js +141 -0
  301. package/src/migrations/schema/SchemaCompiler.d.ts +20 -0
  302. package/src/migrations/schema/SchemaCompiler.d.ts.map +1 -0
  303. package/src/migrations/schema/SchemaCompiler.js +262 -0
  304. package/src/migrations/schema/index.d.ts +5 -0
  305. package/src/migrations/schema/index.d.ts.map +1 -0
  306. package/src/migrations/schema/index.js +3 -0
  307. package/src/migrations/schema/types.d.ts +86 -0
  308. package/src/migrations/schema/types.d.ts.map +1 -0
  309. package/src/migrations/schema/types.js +1 -0
  310. package/src/migrations/types.d.ts +45 -0
  311. package/src/migrations/types.d.ts.map +1 -0
  312. package/src/migrations/types.js +1 -0
  313. package/src/node-singletons/crypto.d.ts +1 -1
  314. package/src/node-singletons/crypto.d.ts.map +1 -1
  315. package/src/node-singletons/crypto.js +1 -1
  316. package/src/node-singletons/fs.d.ts +2 -2
  317. package/src/node-singletons/fs.d.ts.map +1 -1
  318. package/src/node-singletons/fs.js +1 -1
  319. package/src/node-singletons/util.d.ts +6 -0
  320. package/src/node-singletons/util.d.ts.map +1 -0
  321. package/src/node-singletons/util.js +5 -0
  322. package/src/node.d.ts +2 -0
  323. package/src/node.d.ts.map +1 -1
  324. package/src/node.js +7 -0
  325. package/src/observability/OpenTelemetry.d.ts +62 -0
  326. package/src/observability/OpenTelemetry.d.ts.map +1 -0
  327. package/src/observability/OpenTelemetry.js +167 -0
  328. package/src/observability/PrometheusMetrics.d.ts +25 -0
  329. package/src/observability/PrometheusMetrics.d.ts.map +1 -0
  330. package/src/observability/PrometheusMetrics.js +114 -0
  331. package/src/openapi/OpenApiGenerator.d.ts +68 -0
  332. package/src/openapi/OpenApiGenerator.d.ts.map +1 -0
  333. package/src/openapi/OpenApiGenerator.js +287 -0
  334. package/src/orm/Database.d.ts +4 -2
  335. package/src/orm/Database.d.ts.map +1 -1
  336. package/src/orm/Database.js +142 -29
  337. package/src/orm/DatabaseAdapter.d.ts +13 -0
  338. package/src/orm/DatabaseAdapter.d.ts.map +1 -1
  339. package/src/orm/DatabaseAdapterRegistry.d.ts.map +1 -1
  340. package/src/orm/DatabaseAdapterRegistry.js +3 -1
  341. package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -1
  342. package/src/orm/DatabaseRuntimeRegistration.js +4 -0
  343. package/src/orm/Model.d.ts +30 -2
  344. package/src/orm/Model.d.ts.map +1 -1
  345. package/src/orm/Model.js +255 -62
  346. package/src/orm/QueryBuilder.d.ts +22 -1
  347. package/src/orm/QueryBuilder.d.ts.map +1 -1
  348. package/src/orm/QueryBuilder.js +405 -95
  349. package/src/orm/Relationships.d.ts +7 -1
  350. package/src/orm/Relationships.d.ts.map +1 -1
  351. package/src/orm/Relationships.js +18 -0
  352. package/src/orm/SchemaCompiler.d.ts +9 -0
  353. package/src/orm/SchemaCompiler.d.ts.map +1 -0
  354. package/src/orm/SchemaCompiler.js +145 -0
  355. package/src/orm/adapters/D1Adapter.d.ts +1 -1
  356. package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
  357. package/src/orm/adapters/MySQLAdapter.d.ts +1 -1
  358. package/src/orm/adapters/MySQLAdapter.d.ts.map +1 -1
  359. package/src/orm/adapters/MySQLAdapter.js +88 -69
  360. package/src/orm/adapters/PostgreSQLAdapter.d.ts +1 -1
  361. package/src/orm/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  362. package/src/orm/adapters/PostgreSQLAdapter.js +88 -69
  363. package/src/orm/adapters/SQLServerAdapter.d.ts +1 -1
  364. package/src/orm/adapters/SQLServerAdapter.d.ts.map +1 -1
  365. package/src/orm/adapters/SQLiteAdapter.d.ts +1 -1
  366. package/src/orm/adapters/SQLiteAdapter.d.ts.map +1 -1
  367. package/src/orm/adapters/SQLiteAdapter.js +63 -3
  368. package/src/orm/maintenance/SqliteMaintenance.d.ts +5 -0
  369. package/src/orm/maintenance/SqliteMaintenance.d.ts.map +1 -0
  370. package/src/orm/maintenance/SqliteMaintenance.js +14 -0
  371. package/src/orm/migrations/MigrationStore.d.ts +38 -0
  372. package/src/orm/migrations/MigrationStore.d.ts.map +1 -0
  373. package/src/orm/migrations/MigrationStore.js +157 -0
  374. package/src/performance/CodeGenerationBenchmark.d.ts.map +1 -1
  375. package/src/performance/Optimizer.d.ts +1 -0
  376. package/src/performance/Optimizer.d.ts.map +1 -1
  377. package/src/performance/Optimizer.js +37 -3
  378. package/src/profiling/MemoryProfiler.d.ts +1 -1
  379. package/src/profiling/MemoryProfiler.d.ts.map +1 -1
  380. package/src/profiling/N1Detector.d.ts +1 -1
  381. package/src/profiling/N1Detector.d.ts.map +1 -1
  382. package/src/profiling/QueryLogger.d.ts +1 -1
  383. package/src/profiling/QueryLogger.d.ts.map +1 -1
  384. package/src/profiling/RequestProfiler.d.ts +3 -3
  385. package/src/profiling/RequestProfiler.d.ts.map +1 -1
  386. package/src/routes/api.d.ts +2 -0
  387. package/src/routes/api.d.ts.map +1 -0
  388. package/src/routes/api.js +1 -0
  389. package/src/routes/broadcast.d.ts +2 -0
  390. package/src/routes/broadcast.d.ts.map +1 -0
  391. package/src/routes/broadcast.js +1 -0
  392. package/src/routes/health.d.ts +2 -0
  393. package/src/routes/health.d.ts.map +1 -0
  394. package/src/routes/health.js +1 -0
  395. package/src/routes/metrics.d.ts +2 -0
  396. package/src/routes/metrics.d.ts.map +1 -0
  397. package/src/routes/metrics.js +1 -0
  398. package/src/routes/storage.d.ts +2 -0
  399. package/src/routes/storage.d.ts.map +1 -0
  400. package/src/routes/storage.js +1 -0
  401. package/src/routing/CoreRoutes.d.ts +12 -0
  402. package/src/routing/CoreRoutes.d.ts.map +1 -0
  403. package/src/routing/CoreRoutes.js +151 -0
  404. package/src/routing/RouteRegistry.d.ts +39 -0
  405. package/src/routing/RouteRegistry.d.ts.map +1 -0
  406. package/src/routing/RouteRegistry.js +44 -0
  407. package/src/routing/Router.d.ts +26 -9
  408. package/src/routing/Router.d.ts.map +1 -1
  409. package/src/routing/Router.js +79 -35
  410. package/src/routing/common.d.ts +15 -0
  411. package/src/routing/common.d.ts.map +1 -0
  412. package/src/routing/common.js +47 -0
  413. package/src/routing/doc.d.ts +28 -0
  414. package/src/routing/doc.d.ts.map +1 -0
  415. package/src/routing/doc.js +95 -0
  416. package/src/routing/error.d.ts +21 -0
  417. package/src/routing/error.d.ts.map +1 -0
  418. package/src/routing/error.js +126 -0
  419. package/src/routing/errorPages.d.ts +14 -0
  420. package/src/routing/errorPages.d.ts.map +1 -0
  421. package/src/routing/errorPages.js +103 -0
  422. package/src/routing/publicRoot.d.ts +18 -0
  423. package/src/routing/publicRoot.d.ts.map +1 -0
  424. package/src/routing/publicRoot.js +49 -0
  425. package/src/runtime/PluginAutoImports.d.ts +21 -0
  426. package/src/runtime/PluginAutoImports.d.ts.map +1 -0
  427. package/src/runtime/PluginAutoImports.js +59 -0
  428. package/src/runtime/PluginManager.d.ts +1 -5
  429. package/src/runtime/PluginManager.d.ts.map +1 -1
  430. package/src/runtime/PluginManager.js +25 -18
  431. package/src/runtime/RuntimeAdapter.d.ts.map +1 -1
  432. package/src/runtime/RuntimeAdapter.js +20 -1
  433. package/src/runtime/RuntimeDetector.d.ts +1 -1
  434. package/src/runtime/RuntimeDetector.d.ts.map +1 -1
  435. package/src/runtime/adapters/CloudflareAdapter.d.ts +1 -1
  436. package/src/runtime/adapters/CloudflareAdapter.d.ts.map +1 -1
  437. package/src/runtime/adapters/CloudflareAdapter.js +1 -1
  438. package/src/runtime/adapters/DenoAdapter.d.ts +1 -1
  439. package/src/runtime/adapters/DenoAdapter.d.ts.map +1 -1
  440. package/src/runtime/adapters/DenoAdapter.js +3 -3
  441. package/src/runtime/adapters/LambdaAdapter.d.ts +1 -1
  442. package/src/runtime/adapters/LambdaAdapter.d.ts.map +1 -1
  443. package/src/runtime/adapters/LambdaAdapter.js +1 -1
  444. package/src/runtime/adapters/NodeServerAdapter.d.ts +1 -1
  445. package/src/runtime/adapters/NodeServerAdapter.d.ts.map +1 -1
  446. package/src/runtime/getKernel.d.ts +9 -0
  447. package/src/runtime/getKernel.d.ts.map +1 -0
  448. package/src/runtime/getKernel.js +27 -0
  449. package/src/scripts/TemplateImportsCheck.js +47 -7
  450. package/src/scripts/TemplateSync.js +92 -20
  451. package/src/security/Encryptor.d.ts.map +1 -1
  452. package/src/security/Encryptor.js +64 -7
  453. package/src/security/JwtManager.d.ts +1 -0
  454. package/src/security/JwtManager.d.ts.map +1 -1
  455. package/src/security/JwtManager.js +33 -0
  456. package/src/security/Sanitizer.d.ts +76 -0
  457. package/src/security/Sanitizer.d.ts.map +1 -0
  458. package/src/security/Sanitizer.js +412 -0
  459. package/src/security/TokenRevocation.d.ts +7 -0
  460. package/src/security/TokenRevocation.d.ts.map +1 -0
  461. package/src/security/TokenRevocation.js +57 -0
  462. package/src/seeders/SeederDiscovery.d.ts +5 -0
  463. package/src/seeders/SeederDiscovery.d.ts.map +1 -0
  464. package/src/seeders/SeederDiscovery.js +21 -0
  465. package/src/seeders/SeederLoader.d.ts +5 -0
  466. package/src/seeders/SeederLoader.d.ts.map +1 -0
  467. package/src/seeders/SeederLoader.js +60 -0
  468. package/src/seeders/types.d.ts +18 -0
  469. package/src/seeders/types.d.ts.map +1 -0
  470. package/src/seeders/types.js +1 -0
  471. package/src/session/SessionManager.js +1 -1
  472. package/src/start.d.ts +21 -0
  473. package/src/start.d.ts.map +1 -0
  474. package/src/start.js +60 -0
  475. package/src/templates/adapters/MySQLAdapter.ts.tpl +109 -85
  476. package/src/templates/adapters/PostgreSQLAdapter.ts.tpl +129 -88
  477. package/src/templates/adapters/SQLServerAdapter.ts.tpl +5 -9
  478. package/src/templates/adapters/SQLiteAdapter.ts.tpl +78 -11
  479. package/src/templates/features/Queue.ts.tpl +2 -2
  480. package/src/templates/project/basic/app/Controllers/AuthController.ts.tpl +217 -0
  481. package/src/templates/project/basic/app/Controllers/UserController.ts.tpl +3 -16
  482. package/src/templates/project/basic/app/Middleware/ProfilerMiddleware.ts.tpl +1 -3
  483. package/src/templates/project/basic/app/Middleware/index.ts.tpl +3 -8
  484. package/src/templates/project/basic/app/Models/Post.ts.tpl +2 -3
  485. package/src/templates/project/basic/app/Models/User.ts.tpl +1 -1
  486. package/src/templates/project/basic/app/Types/controller.ts.tpl +46 -0
  487. package/src/templates/project/basic/config/FileLogWriter.ts.tpl +5 -236
  488. package/src/templates/project/basic/config/SecretsManager.ts.tpl +13 -450
  489. package/src/templates/project/basic/config/StartupConfigValidator.ts.tpl +9 -268
  490. package/src/templates/project/basic/config/app.ts.tpl +13 -153
  491. package/src/templates/project/basic/config/broadcast.ts.tpl +15 -129
  492. package/src/templates/project/basic/config/cache.ts.tpl +15 -92
  493. package/src/templates/project/basic/config/cloudflare.ts.tpl +4 -39
  494. package/src/templates/project/basic/config/constants.ts.tpl +9 -65
  495. package/src/templates/project/basic/config/database.ts.tpl +29 -116
  496. package/src/templates/project/basic/config/env.ts.tpl +5 -169
  497. package/src/templates/project/basic/config/features.ts.tpl +6 -54
  498. package/src/templates/project/basic/config/index.ts.tpl +27 -24
  499. package/src/templates/project/basic/config/logger.ts.tpl +5 -381
  500. package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +1 -1
  501. package/src/templates/project/basic/config/logging/KvLogger.ts.tpl +2 -2
  502. package/src/templates/project/basic/config/logging/SlackLogger.ts.tpl +1 -1
  503. package/src/templates/project/basic/config/mail.ts.tpl +15 -115
  504. package/src/templates/project/basic/config/microservices.ts.tpl +11 -97
  505. package/src/templates/project/basic/config/middleware.ts.tpl +27 -18
  506. package/src/templates/project/basic/config/notification.ts.tpl +14 -127
  507. package/src/templates/project/basic/config/queue.ts.tpl +16 -79
  508. package/src/templates/project/basic/config/security.ts.tpl +11 -163
  509. package/src/templates/project/basic/config/startup.ts.tpl +10 -21
  510. package/src/templates/project/basic/config/storage.ts.tpl +15 -133
  511. package/src/templates/project/basic/config/type.ts.tpl +33 -441
  512. package/src/templates/project/basic/database/factories/UserFactory.ts.tpl +80 -0
  513. package/src/templates/project/basic/database/migrations/create_tasks_table.ts.tpl +28 -0
  514. package/src/templates/project/basic/database/migrations/create_users_table.ts.tpl +29 -0
  515. package/src/templates/project/basic/database/seeders/DatabaseSeeder.ts.tpl +19 -0
  516. package/src/templates/project/basic/database/seeders/UserSeeder.ts.tpl +18 -0
  517. package/src/templates/project/basic/database/seeders/index.ts.tpl +2 -0
  518. package/src/templates/project/basic/package.json.tpl +1 -1
  519. package/src/templates/project/basic/routes/api.ts.tpl +74 -36
  520. package/src/templates/project/basic/routes/health.ts.tpl +1 -6
  521. package/src/templates/project/basic/routes/metrics.ts.tpl +22 -0
  522. package/src/templates/project/basic/src/index.ts.tpl +7 -80
  523. package/src/templates/project/basic/tsconfig.json.tpl +12 -13
  524. package/src/testing/TestEnvironment.d.ts +40 -0
  525. package/src/testing/TestEnvironment.d.ts.map +1 -0
  526. package/src/testing/TestEnvironment.js +141 -0
  527. package/src/testing/TestHttp.d.ts +29 -0
  528. package/src/testing/TestHttp.d.ts.map +1 -0
  529. package/src/testing/TestHttp.js +96 -0
  530. package/src/testing/index.d.ts +5 -0
  531. package/src/testing/index.d.ts.map +1 -0
  532. package/src/testing/index.js +2 -0
  533. package/src/time/DateTime.d.ts +181 -0
  534. package/src/time/DateTime.d.ts.map +1 -0
  535. package/src/time/DateTime.js +300 -0
  536. package/src/time/index.d.ts +7 -0
  537. package/src/time/index.d.ts.map +1 -0
  538. package/src/time/index.js +5 -0
  539. package/src/tools/http/Http.d.ts.map +1 -1
  540. package/src/tools/http/Http.js +4 -0
  541. package/src/tools/mail/drivers/Smtp.js +1 -1
  542. package/src/tools/queue/drivers/InMemory.d.ts +1 -1
  543. package/src/tools/queue/drivers/InMemory.d.ts.map +1 -1
  544. package/src/tools/queue/drivers/InMemory.js +1 -1
  545. package/src/tools/queue/drivers/Redis.d.ts +1 -1
  546. package/src/tools/queue/drivers/Redis.d.ts.map +1 -1
  547. package/src/tools/queue/drivers/Redis.js +1 -1
  548. package/src/validation/ValidationError.d.ts.map +1 -1
  549. package/src/validation/ValidationError.js +4 -2
  550. package/src/validation/Validator.d.ts +49 -16
  551. package/src/validation/Validator.d.ts.map +1 -1
  552. package/src/validation/Validator.js +307 -5
  553. package/src/common/uuid.d.ts +0 -3
  554. package/src/common/uuid.d.ts.map +0 -1
  555. package/src/common/uuid.js +0 -30
  556. package/src/templates/project/basic/.env.example.tpl +0 -74
  557. package/src/templates/project/basic/.env.tpl +0 -166
  558. package/src/templates/project/basic/database/migrations/index.ts.tpl +0 -2
@@ -3,11 +3,38 @@
3
3
  * Build queries without raw SQL
4
4
  */
5
5
  import { ErrorFactory } from '../exceptions/ZintrustError.js';
6
- /**
7
- * Escape SQL identifier
8
- */
9
- const escapeIdentifier = (id) => `"${id.replaceAll('"', '""')}"`;
6
+ const getIdentifierQuote = (dialect) => {
7
+ const d = (dialect ?? '').toLowerCase();
8
+ if (d === 'mysql') {
9
+ return {
10
+ open: '`',
11
+ close: '`',
12
+ escape: (raw) => raw.replaceAll('`', '``'),
13
+ };
14
+ }
15
+ if (d === 'sqlserver') {
16
+ return {
17
+ open: '[',
18
+ close: ']',
19
+ escape: (raw) => raw.replaceAll(']', ']]'),
20
+ };
21
+ }
22
+ // sqlite/postgresql/d1/d1-remote: standard SQL double-quote identifiers.
23
+ return {
24
+ open: '"',
25
+ close: '"',
26
+ escape: (raw) => raw.replaceAll('"', '""'),
27
+ };
28
+ };
29
+ const escapeIdentifier = (id, dialect) => {
30
+ const q = getIdentifierQuote(dialect);
31
+ return id
32
+ .split('.')
33
+ .map((part) => `${q.open}${q.escape(part)}${q.close}`)
34
+ .join('.');
35
+ };
10
36
  const SAFE_IDENTIFIER_PATH = /^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/;
37
+ const SAFE_IDENTIFIER = /^[A-Za-z_]\w*$/;
11
38
  const assertSafeIdentifierPath = (id, label) => {
12
39
  const trimmed = id.trim();
13
40
  if (trimmed.length === 0) {
@@ -17,6 +44,15 @@ const assertSafeIdentifierPath = (id, label) => {
17
44
  throw ErrorFactory.createDatabaseError(`Unsafe SQL identifier for ${label}`);
18
45
  }
19
46
  };
47
+ const assertSafeIdentifier = (id, label) => {
48
+ const trimmed = id.trim();
49
+ if (trimmed.length === 0) {
50
+ throw ErrorFactory.createDatabaseError(`Empty SQL identifier for ${label}`);
51
+ }
52
+ if (!SAFE_IDENTIFIER.test(trimmed)) {
53
+ throw ErrorFactory.createDatabaseError(`Unsafe SQL identifier for ${label}`);
54
+ }
55
+ };
20
56
  const normalizeOrderDirection = (direction) => {
21
57
  if (direction === undefined || direction === null)
22
58
  return 'ASC';
@@ -66,27 +102,98 @@ const isNumericLiteral = (value) => {
66
102
  // Disallows: 1e3, 1;DROP, 1 as ok
67
103
  return /^(?:0|[1-9]\d*)(?:\.\d+)?$/.test(value);
68
104
  };
105
+ const ALLOWED_AGGREGATES = new Set(['MAX', 'MIN', 'COUNT', 'SUM', 'AVG']);
106
+ const tryParseAggregateSelectExpr = (raw) => {
107
+ // Aggregate functions: MAX(col) [AS alias]
108
+ // Capture content greedily to avoid ReDoS from overlapping whitespace patterns (S5852)
109
+ const agg = /^(MAX|MIN|COUNT|SUM|AVG)\(([^)]+)\)(?: AS (\S+))?$/i.exec(raw);
110
+ if (agg === null)
111
+ return null;
112
+ const fn = agg[1]?.toUpperCase();
113
+ const arg = (agg[2] ?? '').trim();
114
+ const alias = (agg[3] ?? '').trim();
115
+ if (!ALLOWED_AGGREGATES.has(fn))
116
+ return null;
117
+ if (arg !== '*') {
118
+ assertSafeIdentifierPath(arg, 'aggregate argument');
119
+ }
120
+ if (alias.length > 0) {
121
+ assertSafeIdentifier(alias, 'aggregate alias');
122
+ }
123
+ return { kind: 'aggregate', fn, arg, alias: alias.length > 0 ? alias : undefined };
124
+ };
125
+ const tryParseColumnAliasSelectExpr = (raw) => {
126
+ // Column alias: col [AS alias]
127
+ // Avoid catastrophic backtracking by using a linear-time separator scan.
128
+ const upperRaw = raw.toUpperCase();
129
+ const asIndex = upperRaw.indexOf(' AS ');
130
+ if (asIndex === -1)
131
+ return null;
132
+ const asSeparator = { index: asIndex, 0: raw.slice(asIndex, asIndex + 4) };
133
+ const col = raw.slice(0, asSeparator.index).trim();
134
+ const alias = raw.slice(asSeparator.index + asSeparator[0].length).trim();
135
+ // Alias must be a single token (no whitespace).
136
+ if (col.length === 0 || alias.length === 0 || /\s/.test(alias))
137
+ return null;
138
+ assertSafeIdentifierPath(col, 'select column');
139
+ assertSafeIdentifier(alias, 'select alias');
140
+ return { kind: 'column', column: col, alias };
141
+ };
142
+ const tryParseSelectExpr = (expr) => {
143
+ const raw = expr.trim();
144
+ if (raw.length === 0) {
145
+ throw ErrorFactory.createDatabaseError('Empty SQL identifier for select column');
146
+ }
147
+ if (raw === '*')
148
+ return { kind: 'all' };
149
+ if (isNumericLiteral(raw))
150
+ return { kind: 'literal', value: raw };
151
+ const aggregate = tryParseAggregateSelectExpr(raw);
152
+ if (aggregate !== null)
153
+ return aggregate;
154
+ const aliased = tryParseColumnAliasSelectExpr(raw);
155
+ if (aliased !== null)
156
+ return aliased;
157
+ // Plain identifier path
158
+ assertSafeIdentifierPath(raw, 'select column');
159
+ return { kind: 'column', column: raw };
160
+ };
69
161
  /**
70
162
  * Build SELECT clause
71
163
  */
72
- const buildSelectClause = (columns) => columns
73
- .map((c) => {
74
- if (c === '*')
75
- return c;
76
- if (isNumericLiteral(c))
77
- return c;
78
- assertSafeIdentifierPath(c, 'select column');
79
- return escapeIdentifier(c);
80
- })
81
- .join(', ');
82
- const compileWhere = (conditions) => {
164
+ const formatSelectExpr = (parsed, dialect) => {
165
+ if (parsed.kind === 'all')
166
+ return '*';
167
+ if (parsed.kind === 'literal')
168
+ return parsed.value;
169
+ if (parsed.kind === 'aggregate') {
170
+ const argSql = parsed.arg === '*' ? '*' : escapeIdentifier(parsed.arg, dialect);
171
+ const base = `${parsed.fn}(${argSql})`;
172
+ const alias = typeof parsed.alias === 'string' && parsed.alias.length > 0 ? parsed.alias : null;
173
+ return alias === null ? base : `${base} AS ${escapeIdentifier(alias, dialect)}`;
174
+ }
175
+ const base = escapeIdentifier(parsed.column, dialect);
176
+ const alias = typeof parsed.alias === 'string' && parsed.alias.length > 0 ? parsed.alias : null;
177
+ return alias === null ? base : `${base} AS ${escapeIdentifier(alias, dialect)}`;
178
+ };
179
+ const buildSelectClause = (columns, dialect) => {
180
+ const out = [];
181
+ for (const c of columns) {
182
+ const parsed = tryParseSelectExpr(String(c));
183
+ if (parsed === null)
184
+ continue;
185
+ out.push(formatSelectExpr(parsed, dialect));
186
+ }
187
+ return out.join(', ');
188
+ };
189
+ const compileWhere = (conditions, dialect) => {
83
190
  if (conditions.length === 0)
84
191
  return { sql: '', parameters: [] };
85
192
  const parameters = [];
86
193
  const clauses = conditions.map((clause) => {
87
194
  assertSafeIdentifierPath(clause.column, 'where column');
88
195
  const operator = assertSafeOperator(clause.operator);
89
- const columnSql = escapeIdentifier(clause.column);
196
+ const columnSql = escapeIdentifier(clause.column, dialect);
90
197
  if (operator === 'IN' || operator === 'NOT IN') {
91
198
  if (!Array.isArray(clause.value) || clause.value.length === 0) {
92
199
  throw ErrorFactory.createDatabaseError('IN operator requires a non-empty array');
@@ -139,16 +246,20 @@ const getEffectiveWhereConditions = (state) => {
139
246
  /**
140
247
  * Build ORDER BY clause
141
248
  */
142
- const buildOrderByClause = (orderBy) => {
143
- if (!orderBy)
249
+ const buildOrderByClause = (orderByClauses, dialect) => {
250
+ if (orderByClauses.length === 0)
144
251
  return '';
145
- const col = orderBy.column.trim();
146
- if (!isNumericLiteral(col)) {
147
- assertSafeIdentifierPath(col, 'order by column');
148
- }
149
- const dir = normalizeOrderDirection(orderBy.direction);
150
- // Keep output unquoted for backwards compatibility; validation prevents injection.
151
- return ` ORDER BY ${col} ${dir}`;
252
+ const parts = orderByClauses.map((orderBy) => {
253
+ const col = orderBy.column.trim();
254
+ let columnSql = col;
255
+ if (!isNumericLiteral(col)) {
256
+ assertSafeIdentifierPath(col, 'order by column');
257
+ columnSql = escapeIdentifier(col, dialect);
258
+ }
259
+ const dir = normalizeOrderDirection(orderBy.direction);
260
+ return `${columnSql} ${dir}`;
261
+ });
262
+ return ` ORDER BY ${parts.join(', ')}`;
152
263
  };
153
264
  /**
154
265
  * Build LIMIT and OFFSET clause
@@ -169,10 +280,10 @@ const buildSelectQuery = (state) => {
169
280
  if (state.tableName.length > 0) {
170
281
  assertSafeIdentifierPath(state.tableName, 'table name');
171
282
  }
172
- const columns = buildSelectClause(state.selectColumns);
173
- const fromClause = state.tableName.length > 0 ? ` FROM ${escapeIdentifier(state.tableName)}` : '';
174
- const where = compileWhere(getEffectiveWhereConditions(state));
175
- const sql = `SELECT ${columns}${fromClause}${where.sql}${buildOrderByClause(state.orderByClause)}${buildLimitOffsetClause(state.limitValue, state.offsetValue)}`;
283
+ const columns = buildSelectClause(state.selectColumns, state.dialect);
284
+ const fromClause = state.tableName.length > 0 ? ` FROM ${escapeIdentifier(state.tableName, state.dialect)}` : '';
285
+ const where = compileWhere(getEffectiveWhereConditions(state), state.dialect);
286
+ const sql = `SELECT ${columns}${fromClause}${where.sql}${buildOrderByClause(state.orderByClauses, state.dialect)}${buildLimitOffsetClause(state.limitValue, state.offsetValue)}`;
176
287
  return { sql, parameters: where.parameters };
177
288
  };
178
289
  const applyWhereCondition = (state, column, operator, value) => {
@@ -200,7 +311,7 @@ const applyOrderByClause = (state, column, direction) => {
200
311
  assertSafeIdentifierPath(col, 'order by column');
201
312
  }
202
313
  const dir = normalizeOrderDirection(direction);
203
- state.orderByClause = { column: col, direction: dir };
314
+ state.orderByClauses.push({ column: col, direction: dir });
204
315
  };
205
316
  const applyLimit = (state, count) => {
206
317
  assertSafeLimitOffset(count, 'LIMIT');
@@ -220,6 +331,64 @@ async function executeFirst(builder, db) {
220
331
  const results = (await db.query(builder.toSQL(), builder.getParameters(), builder.isReadOperation()));
221
332
  return results[0] ?? null;
222
333
  }
334
+ async function executeFirstOrFail(builder, db, message) {
335
+ const result = await executeFirst(builder, db);
336
+ if (result === null)
337
+ throw ErrorFactory.createNotFoundError(message ?? 'Resource not found');
338
+ return result;
339
+ }
340
+ const compileInsert = (tableName, values, dialect) => {
341
+ const items = Array.isArray(values) ? values : [values];
342
+ if (items.length === 0) {
343
+ throw ErrorFactory.createDatabaseError('INSERT requires at least one column');
344
+ }
345
+ // Use keys from the first item
346
+ const keys = Object.keys(items[0] ?? {});
347
+ if (keys.length === 0) {
348
+ throw ErrorFactory.createDatabaseError('INSERT requires at least one column');
349
+ }
350
+ assertSafeIdentifierPath(tableName, 'table name');
351
+ for (const key of keys)
352
+ assertSafeIdentifier(key, 'insert column');
353
+ const colsSql = keys.map((k) => escapeIdentifier(k, dialect)).join(', ');
354
+ // Single row or multi-row placeholders
355
+ const rowPlaceholders = `(${keys.map(() => '?').join(', ')})`;
356
+ const placeholders = items.map(() => rowPlaceholders).join(', ');
357
+ const parameters = [];
358
+ for (const item of items) {
359
+ for (const key of keys) {
360
+ parameters.push(item[key]);
361
+ }
362
+ }
363
+ const sql = `INSERT INTO ${escapeIdentifier(tableName, dialect)} (${colsSql}) VALUES ${placeholders}`;
364
+ return { sql, parameters };
365
+ };
366
+ const compileUpdate = (tableName, values, conditions, dialect) => {
367
+ const keys = Object.keys(values);
368
+ if (keys.length === 0) {
369
+ throw ErrorFactory.createDatabaseError('UPDATE requires at least one column');
370
+ }
371
+ if (conditions.length === 0) {
372
+ throw ErrorFactory.createDatabaseError('UPDATE requires at least one WHERE clause');
373
+ }
374
+ assertSafeIdentifierPath(tableName, 'table name');
375
+ for (const key of keys)
376
+ assertSafeIdentifier(key, 'update column');
377
+ const setSql = keys.map((k) => `${escapeIdentifier(k, dialect)} = ?`).join(', ');
378
+ const setParams = keys.map((k) => values[k]);
379
+ const where = compileWhere(conditions, dialect);
380
+ const sql = `UPDATE ${escapeIdentifier(tableName, dialect)} SET ${setSql}${where.sql}`;
381
+ return { sql, parameters: [...setParams, ...where.parameters] };
382
+ };
383
+ const compileDelete = (tableName, conditions, dialect) => {
384
+ if (conditions.length === 0) {
385
+ throw ErrorFactory.createDatabaseError('DELETE requires at least one WHERE clause');
386
+ }
387
+ assertSafeIdentifierPath(tableName, 'table name');
388
+ const where = compileWhere(conditions, dialect);
389
+ const sql = `DELETE FROM ${escapeIdentifier(tableName, dialect)}${where.sql}`;
390
+ return { sql, parameters: where.parameters };
391
+ };
223
392
  /**
224
393
  * Execute query and return all results
225
394
  */
@@ -231,75 +400,213 @@ async function executeGet(builder, db) {
231
400
  /**
232
401
  * Create the builder object
233
402
  */
234
- function createBuilder(state, db) {
235
- const builder = {
236
- select: (...columns) => {
237
- state.selectColumns = columns.length > 0 ? columns : ['*'];
238
- return builder;
239
- },
240
- where: (column, operator, value) => {
241
- applyWhereCondition(state, column, operator, value);
242
- return builder;
243
- },
244
- andWhere: (column, operator, value) => builder.where(column, operator, value),
245
- orWhere: (column, operator, value) => builder.where(column, operator, value),
246
- withTrashed: () => {
247
- if (state.softDelete === undefined) {
248
- state.softDelete = { column: 'deleted_at', mode: 'include' };
249
- }
250
- else {
251
- state.softDelete.mode = 'include';
252
- }
253
- return builder;
254
- },
255
- onlyTrashed: () => {
256
- if (state.softDelete === undefined) {
257
- state.softDelete = { column: 'deleted_at', mode: 'only' };
258
- }
259
- else {
260
- state.softDelete.mode = 'only';
261
- }
262
- return builder;
263
- },
264
- withoutTrashed: () => {
265
- if (state.softDelete === undefined) {
266
- state.softDelete = { column: 'deleted_at', mode: 'exclude' };
403
+ function attachSelectMethods(builder, state) {
404
+ const clearDefaultStar = () => {
405
+ if (state.selectColumns.length === 1 && state.selectColumns[0] === '*')
406
+ state.selectColumns = [];
407
+ };
408
+ builder.select = (...columns) => {
409
+ state.selectColumns = columns.length > 0 ? columns : ['*'];
410
+ return builder;
411
+ };
412
+ builder.selectAs = (column, alias) => {
413
+ const col = String(column).trim();
414
+ const a = String(alias).trim();
415
+ assertSafeIdentifierPath(col, 'select column');
416
+ assertSafeIdentifier(a, 'select alias');
417
+ clearDefaultStar();
418
+ state.selectColumns.push(`${col} AS ${a}`);
419
+ return builder;
420
+ };
421
+ builder.max = (column, alias = 'max') => {
422
+ const col = String(column).trim();
423
+ const a = String(alias).trim();
424
+ assertSafeIdentifierPath(col, 'aggregate argument');
425
+ assertSafeIdentifier(a, 'aggregate alias');
426
+ clearDefaultStar();
427
+ state.selectColumns.push(`MAX(${col}) AS ${a}`);
428
+ return builder;
429
+ };
430
+ }
431
+ function attachWhereMethods(builder, state) {
432
+ builder.where = (column, operator, value) => {
433
+ applyWhereCondition(state, column, operator, value);
434
+ return builder;
435
+ };
436
+ builder.andWhere = (column, operator, value) => builder.where(column, operator, value);
437
+ builder.orWhere = (column, operator, value) => builder.where(column, operator, value);
438
+ builder.whereIn = (column, values) => {
439
+ builder.where(column, 'IN', values);
440
+ return builder;
441
+ };
442
+ builder.whereNotIn = (column, values) => {
443
+ builder.where(column, 'NOT IN', values);
444
+ return builder;
445
+ };
446
+ }
447
+ function attachSoftDeleteMethods(builder, state) {
448
+ builder.withTrashed = () => {
449
+ if (state.softDelete === undefined) {
450
+ state.softDelete = { column: 'deleted_at', mode: 'include' };
451
+ }
452
+ else {
453
+ state.softDelete.mode = 'include';
454
+ }
455
+ return builder;
456
+ };
457
+ builder.onlyTrashed = () => {
458
+ if (state.softDelete === undefined) {
459
+ state.softDelete = { column: 'deleted_at', mode: 'only' };
460
+ }
461
+ else {
462
+ state.softDelete.mode = 'only';
463
+ }
464
+ return builder;
465
+ };
466
+ builder.withoutTrashed = () => {
467
+ if (state.softDelete === undefined) {
468
+ state.softDelete = { column: 'deleted_at', mode: 'exclude' };
469
+ }
470
+ else {
471
+ state.softDelete.mode = 'exclude';
472
+ }
473
+ return builder;
474
+ };
475
+ }
476
+ function attachJoinOrderPagingMethods(builder, state) {
477
+ builder.join = (tableJoin, on) => {
478
+ state.joins.push({ table: tableJoin, on });
479
+ return builder;
480
+ };
481
+ builder.leftJoin = (tableJoin, on) => builder.join(tableJoin, on);
482
+ builder.orderBy = (column, direction = 'ASC') => {
483
+ applyOrderByClause(state, column, direction);
484
+ return builder;
485
+ };
486
+ builder.limit = (count) => {
487
+ applyLimit(state, count);
488
+ return builder;
489
+ };
490
+ builder.offset = (count) => {
491
+ applyOffset(state, count);
492
+ return builder;
493
+ };
494
+ }
495
+ function attachIntrospectionMethods(builder, state) {
496
+ builder.getWhereClauses = () => state.whereConditions;
497
+ builder.getSelectColumns = () => state.selectColumns;
498
+ builder.getTable = () => state.tableName;
499
+ builder.getLimit = () => state.limitValue;
500
+ builder.getOffset = () => state.offsetValue;
501
+ builder.getOrderBy = () => state.orderByClauses.at(-1);
502
+ builder.getJoins = () => state.joins;
503
+ builder.isReadOperation = () => true;
504
+ builder.toSQL = () => buildSelectQuery(state).sql;
505
+ builder.getParameters = () => buildSelectQuery(state).parameters;
506
+ // Internal method for eager loading distribution
507
+ builder.getEagerLoads = () => state.eagerLoads;
508
+ }
509
+ function attachReadExecutionMethods(builder, db) {
510
+ builder.first = async () => executeFirst(builder, db);
511
+ builder.firstOrFail = async (message) => executeFirstOrFail(builder, db, message);
512
+ builder.get = async () => executeGet(builder, db);
513
+ // raw just returns results without any hydration logic in callers
514
+ builder.raw = async () => executeGet(builder, db);
515
+ }
516
+ function attachRelationshipMethods(builder, state) {
517
+ builder.with = (relation) => {
518
+ state.eagerLoads.push(relation);
519
+ return builder;
520
+ };
521
+ builder.load = async (models, relation) => {
522
+ if (models.length === 0)
523
+ return;
524
+ // We assume the first model can give us the relationship definition
525
+ const firstModel = models[0];
526
+ if (typeof firstModel[relation] !== 'function')
527
+ return;
528
+ const rel = firstModel[relation]();
529
+ if (rel === null || rel === undefined)
530
+ return;
531
+ const related = rel.related;
532
+ if (related === null || related === undefined)
533
+ return;
534
+ const foreignKey = rel.foreignKey;
535
+ const localKey = rel.localKey;
536
+ const ids = models
537
+ .map((m) => m.getAttribute(localKey))
538
+ .filter((id) => id !== null && id !== undefined);
539
+ if (ids.length === 0)
540
+ return;
541
+ // Call query on the related model
542
+ const relatedModel = rel.related;
543
+ if (typeof relatedModel.query !== 'function')
544
+ return;
545
+ const relatedResults = await relatedModel.query().whereIn(foreignKey, ids).get();
546
+ // Map results back to models
547
+ for (const model of models) {
548
+ const modelId = model.getAttribute(localKey);
549
+ if (rel.type === 'hasMany' || rel.type === 'belongsToMany') {
550
+ const filtered = relatedResults.filter((r) => r.getAttribute(foreignKey) === modelId);
551
+ model.setRelation(relation, filtered);
267
552
  }
268
553
  else {
269
- state.softDelete.mode = 'exclude';
554
+ const found = relatedResults.find((r) => r.getAttribute(foreignKey) === modelId);
555
+ model.setRelation(relation, found ?? null);
270
556
  }
271
- return builder;
272
- },
273
- join: (tableJoin, on) => {
274
- state.joins.push({ table: tableJoin, on });
275
- return builder;
276
- },
277
- leftJoin: (tableJoin, on) => builder.join(tableJoin, on),
278
- orderBy: (column, direction = 'ASC') => {
279
- applyOrderByClause(state, column, direction);
280
- return builder;
281
- },
282
- limit: (count) => {
283
- applyLimit(state, count);
284
- return builder;
285
- },
286
- offset: (count) => {
287
- applyOffset(state, count);
288
- return builder;
289
- },
290
- getWhereClauses: () => state.whereConditions,
291
- getSelectColumns: () => state.selectColumns,
292
- getTable: () => state.tableName,
293
- getLimit: () => state.limitValue,
294
- getOffset: () => state.offsetValue,
295
- getOrderBy: () => state.orderByClause,
296
- getJoins: () => state.joins,
297
- isReadOperation: () => true,
298
- toSQL: () => buildSelectQuery(state).sql,
299
- getParameters: () => buildSelectQuery(state).parameters,
300
- first: async () => executeFirst(builder, db),
301
- get: async () => executeGet(builder, db),
557
+ }
302
558
  };
559
+ }
560
+ function attachWriteMethods(builder, state, db) {
561
+ const ensureDb = () => {
562
+ if (!db)
563
+ throw ErrorFactory.createDatabaseError('Database instance not provided to QueryBuilder');
564
+ return db;
565
+ };
566
+ builder.insert = async (values) => {
567
+ const currentDb = ensureDb();
568
+ const tableName = state.tableName.trim();
569
+ if (tableName.length === 0)
570
+ throw ErrorFactory.createDatabaseError('INSERT requires a table name');
571
+ const compiled = compileInsert(tableName, values, state.dialect);
572
+ const items = Array.isArray(values) ? values : [values];
573
+ await currentDb.query(compiled.sql, compiled.parameters, false);
574
+ // Return InsertResult with metadata
575
+ // Note: lastInsertId typically only available for single-row inserts in most databases
576
+ // For multi-row inserts, use the insertedRecords array
577
+ return {
578
+ id: items.length === 1 ? (items[0]?.['id'] ?? null) : null,
579
+ affectedRows: items.length,
580
+ insertedRecords: items,
581
+ };
582
+ };
583
+ builder.update = async (values) => {
584
+ const currentDb = ensureDb();
585
+ const tableName = state.tableName.trim();
586
+ if (tableName.length === 0)
587
+ throw ErrorFactory.createDatabaseError('UPDATE requires a table name');
588
+ const compiled = compileUpdate(tableName, values, state.whereConditions, state.dialect);
589
+ await currentDb.query(compiled.sql, compiled.parameters, false);
590
+ };
591
+ builder.delete = async () => {
592
+ const currentDb = ensureDb();
593
+ const tableName = state.tableName.trim();
594
+ if (tableName.length === 0)
595
+ throw ErrorFactory.createDatabaseError('DELETE requires a table name');
596
+ const compiled = compileDelete(tableName, state.whereConditions, state.dialect);
597
+ await currentDb.query(compiled.sql, compiled.parameters, false);
598
+ };
599
+ }
600
+ function createBuilder(state, db) {
601
+ const builder = {};
602
+ attachSelectMethods(builder, state);
603
+ attachWhereMethods(builder, state);
604
+ attachSoftDeleteMethods(builder, state);
605
+ attachJoinOrderPagingMethods(builder, state);
606
+ attachIntrospectionMethods(builder, state);
607
+ attachReadExecutionMethods(builder, db);
608
+ attachRelationshipMethods(builder, state);
609
+ attachWriteMethods(builder, state, db);
303
610
  return builder;
304
611
  }
305
612
  /**
@@ -323,7 +630,10 @@ export const QueryBuilder = Object.freeze({
323
630
  tableName,
324
631
  whereConditions: [],
325
632
  selectColumns: ['*'],
633
+ orderByClauses: [],
326
634
  joins: [],
635
+ eagerLoads: [],
636
+ dialect: typeof database?.getType === 'function' ? database.getType() : undefined,
327
637
  };
328
638
  if (options.softDeleteColumn !== undefined && options.softDeleteColumn.trim().length > 0) {
329
639
  state.softDelete = {
@@ -2,7 +2,7 @@
2
2
  * Relationship Types
3
3
  * Define how models relate to each other
4
4
  */
5
- import { IModel, Model, ModelStatic } from './Model';
5
+ import type { IModel, Model, ModelStatic } from './Model';
6
6
  export type RelationshipType = 'hasOne' | 'hasMany' | 'belongsTo' | 'belongsToMany';
7
7
  export interface Relation {
8
8
  type: RelationshipType;
@@ -13,6 +13,12 @@ export interface Relation {
13
13
  }
14
14
  export interface IRelationship {
15
15
  get(instance: IModel): Promise<unknown>;
16
+ type: RelationshipType;
17
+ related: ModelStatic;
18
+ foreignKey: string;
19
+ localKey: string;
20
+ throughTable?: string;
21
+ relatedKey?: string;
16
22
  }
17
23
  /**
18
24
  * HasOne Relationship
@@ -1 +1 @@
1
- {"version":3,"file":"Relationships.d.ts","sourceRoot":"","sources":["../../../src/orm/Relationships.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,eAAe,CAAC;AAEpF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,OAAO,KAAK,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACzC;AAUD;;;;;GAKG;AACH,eAAO,MAAM,MAAM;yBACI,WAAW,cAAc,MAAM,YAAY,MAAM,GAAG,aAAa;EAUtF,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,OAAO;yBACG,WAAW,cAAc,MAAM,YAAY,MAAM,GAAG,aAAa;EAUtF,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,SAAS;yBACC,WAAW,cAAc,MAAM,YAAY,MAAM,GAAG,aAAa;EAUtF,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,aAAa;yBAER,WAAW,gBACX,MAAM,cACR,MAAM,cACN,MAAM,GACjB,aAAa;EA8BhB,CAAC"}
1
+ {"version":3,"file":"Relationships.d.ts","sourceRoot":"","sources":["../../../src/orm/Relationships.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,eAAe,CAAC;AAEpF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,OAAO,KAAK,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAUD;;;;;GAKG;AACH,eAAO,MAAM,MAAM;yBACI,WAAW,cAAc,MAAM,YAAY,MAAM,GAAG,aAAa;EActF,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,OAAO;yBACG,WAAW,cAAc,MAAM,YAAY,MAAM,GAAG,aAAa;EActF,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,SAAS;yBACC,WAAW,cAAc,MAAM,YAAY,MAAM,GAAG,aAAa;EActF,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,aAAa;yBAER,WAAW,gBACX,MAAM,cACR,MAAM,cACN,MAAM,GACjB,aAAa;EAoChB,CAAC"}
@@ -18,6 +18,10 @@ const getRelatedTableName = (relatedModel) => {
18
18
  export const HasOne = Object.freeze({
19
19
  create(relatedModel, foreignKey, localKey) {
20
20
  return {
21
+ type: 'hasOne',
22
+ related: relatedModel,
23
+ foreignKey,
24
+ localKey,
21
25
  async get(instance) {
22
26
  const value = instance.getAttribute(localKey);
23
27
  if (value === undefined || value === null || value === '')
@@ -36,6 +40,10 @@ export const HasOne = Object.freeze({
36
40
  export const HasMany = Object.freeze({
37
41
  create(relatedModel, foreignKey, localKey) {
38
42
  return {
43
+ type: 'hasMany',
44
+ related: relatedModel,
45
+ foreignKey,
46
+ localKey,
39
47
  async get(instance) {
40
48
  const value = instance.getAttribute(localKey);
41
49
  if (value === undefined || value === null || value === '')
@@ -54,6 +62,10 @@ export const HasMany = Object.freeze({
54
62
  export const BelongsTo = Object.freeze({
55
63
  create(relatedModel, foreignKey, localKey) {
56
64
  return {
65
+ type: 'belongsTo',
66
+ related: relatedModel,
67
+ foreignKey,
68
+ localKey,
57
69
  async get(instance) {
58
70
  const value = instance.getAttribute(foreignKey);
59
71
  if (value === undefined || value === null || value === '')
@@ -81,6 +93,12 @@ export const BelongsToMany = Object.freeze({
81
93
  relatedKey !== '');
82
94
  };
83
95
  return {
96
+ type: 'belongsToMany',
97
+ related: relatedModel,
98
+ throughTable,
99
+ foreignKey,
100
+ relatedKey,
101
+ localKey: 'id',
84
102
  async get(instance) {
85
103
  if (!isValidInstance(instance)) {
86
104
  return [];
@@ -0,0 +1,9 @@
1
+ import type { IDatabase } from './Database';
2
+ import type { ISchema } from './Schema';
3
+ export declare const SchemaCompiler: Readonly<{
4
+ createTable(db: IDatabase, schema: ISchema, opts?: {
5
+ ifNotExists?: boolean;
6
+ }): Promise<void>;
7
+ dropTable(db: IDatabase, table: string): Promise<void>;
8
+ }>;
9
+ //# sourceMappingURL=SchemaCompiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaCompiler.d.ts","sourceRoot":"","sources":["../../../src/orm/SchemaCompiler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAoB,OAAO,EAAE,MAAM,aAAa,CAAC;AA4I7D,eAAO,MAAM,cAAc;oBAEnB,SAAS,UACL,OAAO,SACR;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,GAC/B,OAAO,CAAC,IAAI,CAAC;kBAMI,SAAS,SAAS,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;EAM5D,CAAC"}