@zintrust/core 0.1.19 → 0.1.21

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 (528) hide show
  1. package/README.md +10 -10
  2. package/bin/zintrust-main.d.ts.map +1 -1
  3. package/bin/zintrust-main.js +9 -0
  4. package/package.json +3 -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/zintrust.svg +30 -0
  10. package/routes/api.d.ts.map +1 -1
  11. package/routes/api.js +41 -17
  12. package/routes/metrics.d.ts +9 -0
  13. package/routes/metrics.d.ts.map +1 -0
  14. package/routes/metrics.js +20 -0
  15. package/routes/openapi.d.ts +9 -0
  16. package/routes/openapi.d.ts.map +1 -0
  17. package/routes/openapi.js +76 -0
  18. package/src/boot/Application.d.ts +2 -2
  19. package/src/boot/Application.d.ts.map +1 -1
  20. package/src/boot/Application.js +66 -13
  21. package/src/boot/Server.d.ts +3 -2
  22. package/src/boot/Server.d.ts.map +1 -1
  23. package/src/boot/Server.js +39 -165
  24. package/src/boot/bootstrap.js +2 -0
  25. package/src/cache/Cache.d.ts +1 -1
  26. package/src/cache/Cache.d.ts.map +1 -1
  27. package/src/cache/CacheDriver.d.ts +4 -0
  28. package/src/cache/CacheDriver.d.ts.map +1 -1
  29. package/src/cache/drivers/KVDriver.d.ts +1 -1
  30. package/src/cache/drivers/KVDriver.d.ts.map +1 -1
  31. package/src/cache/drivers/MemoryDriver.d.ts +1 -1
  32. package/src/cache/drivers/MemoryDriver.d.ts.map +1 -1
  33. package/src/cache/drivers/MemoryDriver.js +16 -0
  34. package/src/cache/drivers/MongoDriver.d.ts +1 -1
  35. package/src/cache/drivers/MongoDriver.d.ts.map +1 -1
  36. package/src/cache/drivers/RedisDriver.d.ts +1 -1
  37. package/src/cache/drivers/RedisDriver.d.ts.map +1 -1
  38. package/src/cli/CLI.d.ts.map +1 -1
  39. package/src/cli/CLI.js +10 -4
  40. package/src/cli/commands/AddCommand.d.ts +2 -2
  41. package/src/cli/commands/AddCommand.d.ts.map +1 -1
  42. package/src/cli/commands/AddCommand.js +135 -58
  43. package/src/cli/commands/ConfigCommand.d.ts +1 -1
  44. package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
  45. package/src/cli/commands/CreateCommand.d.ts +15 -0
  46. package/src/cli/commands/CreateCommand.d.ts.map +1 -0
  47. package/src/cli/commands/CreateCommand.js +143 -0
  48. package/src/cli/commands/D1MigrateCommand.d.ts +1 -1
  49. package/src/cli/commands/D1MigrateCommand.d.ts.map +1 -1
  50. package/src/cli/commands/D1MigrateCommand.js +16 -20
  51. package/src/cli/commands/DbSeedCommand.d.ts +9 -0
  52. package/src/cli/commands/DbSeedCommand.d.ts.map +1 -0
  53. package/src/cli/commands/DbSeedCommand.js +171 -0
  54. package/src/cli/commands/DebugCommand.d.ts +1 -1
  55. package/src/cli/commands/DebugCommand.d.ts.map +1 -1
  56. package/src/cli/commands/FixCommand.d.ts +1 -1
  57. package/src/cli/commands/FixCommand.d.ts.map +1 -1
  58. package/src/cli/commands/JwtDevCommand.d.ts +8 -0
  59. package/src/cli/commands/JwtDevCommand.d.ts.map +1 -0
  60. package/src/cli/commands/JwtDevCommand.js +114 -0
  61. package/src/cli/commands/KeyGenerateCommand.d.ts +1 -1
  62. package/src/cli/commands/KeyGenerateCommand.d.ts.map +1 -1
  63. package/src/cli/commands/LogsCommand.d.ts +2 -2
  64. package/src/cli/commands/LogsCommand.d.ts.map +1 -1
  65. package/src/cli/commands/LogsCommand.js +36 -2
  66. package/src/cli/commands/MakeMailTemplateCommand.d.ts +1 -1
  67. package/src/cli/commands/MakeMailTemplateCommand.d.ts.map +1 -1
  68. package/src/cli/commands/MakeNotificationTemplateCommand.d.ts +1 -1
  69. package/src/cli/commands/MakeNotificationTemplateCommand.d.ts.map +1 -1
  70. package/src/cli/commands/MigrateCommand.d.ts +1 -1
  71. package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
  72. package/src/cli/commands/MigrateCommand.js +324 -35
  73. package/src/cli/commands/NewCommand.d.ts +1 -1
  74. package/src/cli/commands/NewCommand.d.ts.map +1 -1
  75. package/src/cli/commands/NewCommand.js +12 -4
  76. package/src/cli/commands/PluginCommand.d.ts +1 -1
  77. package/src/cli/commands/PluginCommand.d.ts.map +1 -1
  78. package/src/cli/commands/PrepareCommand.d.ts +1 -1
  79. package/src/cli/commands/PrepareCommand.d.ts.map +1 -1
  80. package/src/cli/commands/QACommand.d.ts +2 -2
  81. package/src/cli/commands/QACommand.d.ts.map +1 -1
  82. package/src/cli/commands/RoutesCommand.d.ts +10 -0
  83. package/src/cli/commands/RoutesCommand.d.ts.map +1 -0
  84. package/src/cli/commands/RoutesCommand.js +242 -0
  85. package/src/cli/commands/SimulateCommand.d.ts +1 -1
  86. package/src/cli/commands/SimulateCommand.d.ts.map +1 -1
  87. package/src/cli/commands/index.d.ts +3 -0
  88. package/src/cli/commands/index.d.ts.map +1 -1
  89. package/src/cli/commands/index.js +3 -0
  90. package/src/cli/config/ConfigManager.d.ts +1 -1
  91. package/src/cli/config/ConfigManager.d.ts.map +1 -1
  92. package/src/cli/config/ConfigValidator.d.ts +1 -1
  93. package/src/cli/config/ConfigValidator.d.ts.map +1 -1
  94. package/src/cli/config/ConfigValidator.js +1 -1
  95. package/src/cli/d1/D1SqlMigrations.d.ts +20 -0
  96. package/src/cli/d1/D1SqlMigrations.d.ts.map +1 -0
  97. package/src/cli/d1/D1SqlMigrations.js +229 -0
  98. package/src/cli/d1/WranglerConfig.d.ts +4 -0
  99. package/src/cli/d1/WranglerConfig.d.ts.map +1 -0
  100. package/src/cli/d1/WranglerConfig.js +122 -0
  101. package/src/cli/d1/WranglerD1.d.ts +11 -0
  102. package/src/cli/d1/WranglerD1.d.ts.map +1 -0
  103. package/src/cli/d1/WranglerD1.js +16 -0
  104. package/src/cli/scaffolding/ControllerGenerator.d.ts.map +1 -1
  105. package/src/cli/scaffolding/ControllerGenerator.js +76 -26
  106. package/src/cli/scaffolding/FactoryGenerator.d.ts.map +1 -1
  107. package/src/cli/scaffolding/FactoryGenerator.js +3 -1
  108. package/src/cli/scaffolding/GovernanceScaffolder.d.ts +23 -0
  109. package/src/cli/scaffolding/GovernanceScaffolder.d.ts.map +1 -0
  110. package/src/cli/scaffolding/GovernanceScaffolder.js +327 -0
  111. package/src/cli/scaffolding/MigrationGenerator.d.ts +10 -0
  112. package/src/cli/scaffolding/MigrationGenerator.d.ts.map +1 -1
  113. package/src/cli/scaffolding/MigrationGenerator.js +137 -51
  114. package/src/cli/scaffolding/ModelGenerator.js +1 -1
  115. package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
  116. package/src/cli/scaffolding/ProjectScaffolder.js +36 -4
  117. package/src/cli/scaffolding/RouteGenerator.d.ts.map +1 -1
  118. package/src/cli/scaffolding/RouteGenerator.js +79 -43
  119. package/src/cli/scaffolding/SeederGenerator.d.ts +5 -0
  120. package/src/cli/scaffolding/SeederGenerator.d.ts.map +1 -1
  121. package/src/cli/scaffolding/SeederGenerator.js +63 -15
  122. package/src/cli/scaffolding/ServiceScaffolder.d.ts.map +1 -1
  123. package/src/cli/scaffolding/ServiceScaffolder.js +28 -7
  124. package/src/cli/scaffolding/index.d.ts +2 -0
  125. package/src/cli/scaffolding/index.d.ts.map +1 -1
  126. package/src/cli/scaffolding/index.js +1 -0
  127. package/src/common/index.d.ts +8 -0
  128. package/src/common/index.d.ts.map +1 -1
  129. package/src/common/index.js +28 -0
  130. package/src/common/utility.d.ts +38 -0
  131. package/src/common/utility.d.ts.map +1 -0
  132. package/src/common/utility.js +101 -0
  133. package/src/config/FileLogWriter.d.ts +2 -1
  134. package/src/config/FileLogWriter.d.ts.map +1 -1
  135. package/src/config/FileLogWriter.js +83 -2
  136. package/src/config/app.d.ts.map +1 -1
  137. package/src/config/app.js +3 -1
  138. package/src/config/broadcast.d.ts +14 -28
  139. package/src/config/broadcast.d.ts.map +1 -1
  140. package/src/config/broadcast.js +69 -35
  141. package/src/config/cache.d.ts +13 -45
  142. package/src/config/cache.d.ts.map +1 -1
  143. package/src/config/cache.js +69 -25
  144. package/src/config/cloudflare.d.ts +1 -1
  145. package/src/config/cloudflare.d.ts.map +1 -1
  146. package/src/config/database.d.ts +22 -64
  147. package/src/config/database.d.ts.map +1 -1
  148. package/src/config/database.js +191 -37
  149. package/src/config/env.d.ts +12 -0
  150. package/src/config/env.d.ts.map +1 -1
  151. package/src/config/env.js +14 -0
  152. package/src/config/index.d.ts +33 -137
  153. package/src/config/index.d.ts.map +1 -1
  154. package/src/config/logging/KvLogger.js +1 -1
  155. package/src/config/logging/SlackLogger.js +2 -2
  156. package/src/config/mail.d.ts +19 -55
  157. package/src/config/mail.d.ts.map +1 -1
  158. package/src/config/mail.js +63 -21
  159. package/src/config/middleware.d.ts +44 -1
  160. package/src/config/middleware.d.ts.map +1 -1
  161. package/src/config/middleware.js +157 -5
  162. package/src/config/notification.d.ts +14 -27
  163. package/src/config/notification.d.ts.map +1 -1
  164. package/src/config/notification.js +82 -36
  165. package/src/config/queue.d.ts +21 -51
  166. package/src/config/queue.d.ts.map +1 -1
  167. package/src/config/queue.js +72 -27
  168. package/src/config/security.d.ts +1 -1
  169. package/src/config/security.js +1 -1
  170. package/src/config/storage.d.ts +27 -34
  171. package/src/config/storage.d.ts.map +1 -1
  172. package/src/config/storage.js +97 -56
  173. package/src/config/type.d.ts +13 -2
  174. package/src/config/type.d.ts.map +1 -1
  175. package/src/events/EventDispatcher.d.ts.map +1 -1
  176. package/src/events/EventDispatcher.js +6 -4
  177. package/src/exceptions/ZintrustError.d.ts +7 -0
  178. package/src/exceptions/ZintrustError.d.ts.map +1 -1
  179. package/src/exceptions/ZintrustError.js +56 -0
  180. package/src/features/Auth.d.ts +1 -1
  181. package/src/features/Auth.d.ts.map +1 -1
  182. package/src/features/Auth.js +3 -3
  183. package/src/features/Queue.js +1 -1
  184. package/src/functions/cloudflare.d.ts.map +1 -1
  185. package/src/functions/cloudflare.js +3 -14
  186. package/src/functions/deno.d.ts.map +1 -1
  187. package/src/functions/deno.js +3 -14
  188. package/src/functions/lambda.d.ts.map +1 -1
  189. package/src/functions/lambda.js +3 -14
  190. package/src/health/StartupHealthChecks.js +1 -1
  191. package/src/http/Controller.d.ts +2 -2
  192. package/src/http/Controller.d.ts.map +1 -1
  193. package/src/http/FileUpload.d.ts +68 -0
  194. package/src/http/FileUpload.d.ts.map +1 -0
  195. package/src/http/FileUpload.js +120 -0
  196. package/src/http/Kernel.d.ts +5 -5
  197. package/src/http/Kernel.d.ts.map +1 -1
  198. package/src/http/Kernel.js +139 -23
  199. package/src/http/Request.d.ts +20 -1
  200. package/src/http/Request.d.ts.map +1 -1
  201. package/src/http/Request.js +23 -0
  202. package/src/http/RequestContext.d.ts +6 -0
  203. package/src/http/RequestContext.d.ts.map +1 -1
  204. package/src/http/RequestContext.js +77 -1
  205. package/src/http/Response.d.ts +1 -1
  206. package/src/http/Response.d.ts.map +1 -1
  207. package/src/http/ValidationHelper.d.ts +78 -0
  208. package/src/http/ValidationHelper.d.ts.map +1 -0
  209. package/src/http/ValidationHelper.js +121 -0
  210. package/src/http/error-pages/ErrorPageRenderer.d.ts +17 -0
  211. package/src/http/error-pages/ErrorPageRenderer.d.ts.map +1 -0
  212. package/src/http/error-pages/ErrorPageRenderer.js +88 -0
  213. package/src/http/middleware/BodyParsingMiddleware.d.ts +12 -0
  214. package/src/http/middleware/BodyParsingMiddleware.d.ts.map +1 -0
  215. package/src/http/middleware/BodyParsingMiddleware.js +251 -0
  216. package/src/http/middleware/FileUploadMiddleware.d.ts +12 -0
  217. package/src/http/middleware/FileUploadMiddleware.d.ts.map +1 -0
  218. package/src/http/middleware/FileUploadMiddleware.js +74 -0
  219. package/src/http/parsers/BodyParsers.d.ts +32 -0
  220. package/src/http/parsers/BodyParsers.d.ts.map +1 -0
  221. package/src/http/parsers/BodyParsers.js +159 -0
  222. package/src/http/parsers/MultipartParser.d.ts +33 -0
  223. package/src/http/parsers/MultipartParser.d.ts.map +1 -0
  224. package/src/http/parsers/MultipartParser.js +156 -0
  225. package/src/http/parsers/MultipartParserRegistry.d.ts +34 -0
  226. package/src/http/parsers/MultipartParserRegistry.d.ts.map +1 -0
  227. package/src/http/parsers/MultipartParserRegistry.js +20 -0
  228. package/src/http/validated.d.ts +12 -0
  229. package/src/http/validated.d.ts.map +1 -0
  230. package/src/http/validated.js +41 -0
  231. package/src/index.d.ts +73 -12
  232. package/src/index.d.ts.map +1 -1
  233. package/src/index.js +60 -5
  234. package/src/microservices/PostgresAdapter.d.ts.map +1 -1
  235. package/src/microservices/PostgresAdapter.js +0 -1
  236. package/src/microservices/RequestTracingMiddleware.d.ts +2 -2
  237. package/src/microservices/RequestTracingMiddleware.d.ts.map +1 -1
  238. package/src/microservices/RequestTracingMiddleware.js +3 -0
  239. package/src/microservices/ServiceAuthMiddleware.d.ts +2 -2
  240. package/src/microservices/ServiceAuthMiddleware.d.ts.map +1 -1
  241. package/src/middleware/AuthMiddleware.d.ts +10 -0
  242. package/src/middleware/AuthMiddleware.d.ts.map +1 -0
  243. package/src/middleware/AuthMiddleware.js +16 -0
  244. package/src/middleware/CsrfMiddleware.d.ts +11 -1
  245. package/src/middleware/CsrfMiddleware.d.ts.map +1 -1
  246. package/src/middleware/CsrfMiddleware.js +33 -0
  247. package/src/middleware/JwtAuthMiddleware.d.ts +11 -0
  248. package/src/middleware/JwtAuthMiddleware.d.ts.map +1 -0
  249. package/src/middleware/JwtAuthMiddleware.js +73 -0
  250. package/src/middleware/LoggingMiddleware.d.ts.map +1 -1
  251. package/src/middleware/LoggingMiddleware.js +8 -3
  252. package/src/middleware/MiddlewareStack.d.ts +2 -2
  253. package/src/middleware/MiddlewareStack.d.ts.map +1 -1
  254. package/src/middleware/RateLimiter.d.ts +2 -2
  255. package/src/middleware/RateLimiter.d.ts.map +1 -1
  256. package/src/middleware/SanitizeBodyMiddleware.d.ts +12 -0
  257. package/src/middleware/SanitizeBodyMiddleware.d.ts.map +1 -0
  258. package/src/middleware/SanitizeBodyMiddleware.js +31 -0
  259. package/src/middleware/SecurityMiddleware.d.ts +1 -1
  260. package/src/middleware/SecurityMiddleware.d.ts.map +1 -1
  261. package/src/middleware/SessionMiddleware.d.ts +1 -1
  262. package/src/middleware/SessionMiddleware.d.ts.map +1 -1
  263. package/src/middleware/ValidationMiddleware.d.ts +25 -0
  264. package/src/middleware/ValidationMiddleware.d.ts.map +1 -0
  265. package/src/middleware/ValidationMiddleware.js +251 -0
  266. package/src/migrations/MigrationDiscovery.d.ts +5 -0
  267. package/src/migrations/MigrationDiscovery.d.ts.map +1 -0
  268. package/src/migrations/MigrationDiscovery.js +16 -0
  269. package/src/migrations/MigrationLoader.d.ts +5 -0
  270. package/src/migrations/MigrationLoader.d.ts.map +1 -0
  271. package/src/migrations/MigrationLoader.js +43 -0
  272. package/src/migrations/MigrationLock.d.ts +4 -0
  273. package/src/migrations/MigrationLock.d.ts.map +1 -0
  274. package/src/migrations/MigrationLock.js +33 -0
  275. package/src/migrations/Migrator.d.ts +23 -0
  276. package/src/migrations/Migrator.d.ts.map +1 -0
  277. package/src/migrations/Migrator.js +4 -0
  278. package/src/migrations/MigratorFactory.d.ts +25 -0
  279. package/src/migrations/MigratorFactory.d.ts.map +1 -0
  280. package/src/migrations/MigratorFactory.js +339 -0
  281. package/src/migrations/schema/Blueprint.d.ts +5 -0
  282. package/src/migrations/schema/Blueprint.d.ts.map +1 -0
  283. package/src/migrations/schema/Blueprint.js +189 -0
  284. package/src/migrations/schema/Schema.d.ts +8 -0
  285. package/src/migrations/schema/Schema.d.ts.map +1 -0
  286. package/src/migrations/schema/Schema.js +141 -0
  287. package/src/migrations/schema/SchemaCompiler.d.ts +20 -0
  288. package/src/migrations/schema/SchemaCompiler.d.ts.map +1 -0
  289. package/src/migrations/schema/SchemaCompiler.js +262 -0
  290. package/src/migrations/schema/index.d.ts +5 -0
  291. package/src/migrations/schema/index.d.ts.map +1 -0
  292. package/src/migrations/schema/index.js +3 -0
  293. package/src/migrations/schema/types.d.ts +86 -0
  294. package/src/migrations/schema/types.d.ts.map +1 -0
  295. package/src/migrations/schema/types.js +1 -0
  296. package/src/migrations/types.d.ts +45 -0
  297. package/src/migrations/types.d.ts.map +1 -0
  298. package/src/migrations/types.js +1 -0
  299. package/src/node-singletons/crypto.d.ts +1 -1
  300. package/src/node-singletons/crypto.d.ts.map +1 -1
  301. package/src/node-singletons/crypto.js +1 -1
  302. package/src/node-singletons/fs.d.ts +2 -2
  303. package/src/node-singletons/fs.d.ts.map +1 -1
  304. package/src/node-singletons/fs.js +1 -1
  305. package/src/node-singletons/util.d.ts +6 -0
  306. package/src/node-singletons/util.d.ts.map +1 -0
  307. package/src/node-singletons/util.js +5 -0
  308. package/src/node.d.ts +3 -1
  309. package/src/node.d.ts.map +1 -1
  310. package/src/node.js +6 -2
  311. package/src/observability/OpenTelemetry.d.ts +62 -0
  312. package/src/observability/OpenTelemetry.d.ts.map +1 -0
  313. package/src/observability/OpenTelemetry.js +167 -0
  314. package/src/observability/PrometheusMetrics.d.ts +25 -0
  315. package/src/observability/PrometheusMetrics.d.ts.map +1 -0
  316. package/src/observability/PrometheusMetrics.js +114 -0
  317. package/src/openapi/OpenApiGenerator.d.ts +68 -0
  318. package/src/openapi/OpenApiGenerator.d.ts.map +1 -0
  319. package/src/openapi/OpenApiGenerator.js +287 -0
  320. package/src/orm/Database.d.ts +5 -2
  321. package/src/orm/Database.d.ts.map +1 -1
  322. package/src/orm/Database.js +219 -63
  323. package/src/orm/DatabaseAdapter.d.ts +14 -0
  324. package/src/orm/DatabaseAdapter.d.ts.map +1 -1
  325. package/src/orm/DatabaseAdapterRegistry.d.ts.map +1 -1
  326. package/src/orm/DatabaseAdapterRegistry.js +3 -1
  327. package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -1
  328. package/src/orm/DatabaseRuntimeRegistration.js +12 -0
  329. package/src/orm/Model.d.ts +30 -2
  330. package/src/orm/Model.d.ts.map +1 -1
  331. package/src/orm/Model.js +255 -62
  332. package/src/orm/QueryBuilder.d.ts +22 -1
  333. package/src/orm/QueryBuilder.d.ts.map +1 -1
  334. package/src/orm/QueryBuilder.js +406 -99
  335. package/src/orm/Relationships.d.ts +7 -1
  336. package/src/orm/Relationships.d.ts.map +1 -1
  337. package/src/orm/Relationships.js +18 -0
  338. package/src/orm/SchemaCompiler.d.ts +9 -0
  339. package/src/orm/SchemaCompiler.d.ts.map +1 -0
  340. package/src/orm/SchemaCompiler.js +145 -0
  341. package/src/orm/adapters/D1Adapter.d.ts +1 -1
  342. package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
  343. package/src/orm/adapters/MySQLAdapter.d.ts +1 -1
  344. package/src/orm/adapters/MySQLAdapter.d.ts.map +1 -1
  345. package/src/orm/adapters/MySQLAdapter.js +88 -69
  346. package/src/orm/adapters/PostgreSQLAdapter.d.ts +1 -1
  347. package/src/orm/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  348. package/src/orm/adapters/PostgreSQLAdapter.js +88 -69
  349. package/src/orm/adapters/SQLServerAdapter.d.ts +1 -1
  350. package/src/orm/adapters/SQLServerAdapter.d.ts.map +1 -1
  351. package/src/orm/adapters/SQLiteAdapter.d.ts +1 -1
  352. package/src/orm/adapters/SQLiteAdapter.d.ts.map +1 -1
  353. package/src/orm/adapters/SQLiteAdapter.js +59 -3
  354. package/src/orm/maintenance/SqliteMaintenance.d.ts +5 -0
  355. package/src/orm/maintenance/SqliteMaintenance.d.ts.map +1 -0
  356. package/src/orm/maintenance/SqliteMaintenance.js +14 -0
  357. package/src/orm/migrations/MigrationStore.d.ts +38 -0
  358. package/src/orm/migrations/MigrationStore.d.ts.map +1 -0
  359. package/src/orm/migrations/MigrationStore.js +157 -0
  360. package/src/performance/CodeGenerationBenchmark.d.ts.map +1 -1
  361. package/src/performance/Optimizer.d.ts +7 -6
  362. package/src/performance/Optimizer.d.ts.map +1 -1
  363. package/src/performance/Optimizer.js +170 -55
  364. package/src/profiling/MemoryProfiler.d.ts +1 -1
  365. package/src/profiling/MemoryProfiler.d.ts.map +1 -1
  366. package/src/profiling/N1Detector.d.ts +1 -1
  367. package/src/profiling/N1Detector.d.ts.map +1 -1
  368. package/src/profiling/QueryLogger.d.ts +1 -1
  369. package/src/profiling/QueryLogger.d.ts.map +1 -1
  370. package/src/profiling/RequestProfiler.d.ts +3 -3
  371. package/src/profiling/RequestProfiler.d.ts.map +1 -1
  372. package/src/routes/metrics.d.ts +2 -0
  373. package/src/routes/metrics.d.ts.map +1 -0
  374. package/src/routes/metrics.js +1 -0
  375. package/src/routing/CoreRoutes.d.ts +12 -0
  376. package/src/routing/CoreRoutes.d.ts.map +1 -0
  377. package/src/routing/CoreRoutes.js +151 -0
  378. package/src/routing/RouteRegistry.d.ts +39 -0
  379. package/src/routing/RouteRegistry.d.ts.map +1 -0
  380. package/src/routing/RouteRegistry.js +44 -0
  381. package/src/routing/Router.d.ts +26 -9
  382. package/src/routing/Router.d.ts.map +1 -1
  383. package/src/routing/Router.js +79 -35
  384. package/src/routing/common.d.ts +15 -0
  385. package/src/routing/common.d.ts.map +1 -0
  386. package/src/routing/common.js +47 -0
  387. package/src/routing/doc.d.ts +27 -0
  388. package/src/routing/doc.d.ts.map +1 -0
  389. package/src/routing/doc.js +110 -0
  390. package/src/routing/error.d.ts +21 -0
  391. package/src/routing/error.d.ts.map +1 -0
  392. package/src/routing/error.js +126 -0
  393. package/src/routing/errorPages.d.ts +14 -0
  394. package/src/routing/errorPages.d.ts.map +1 -0
  395. package/src/routing/errorPages.js +103 -0
  396. package/src/routing/publicRoot.d.ts +27 -0
  397. package/src/routing/publicRoot.d.ts.map +1 -0
  398. package/src/routing/publicRoot.js +110 -0
  399. package/src/runtime/PluginAutoImports.d.ts +21 -0
  400. package/src/runtime/PluginAutoImports.d.ts.map +1 -0
  401. package/src/runtime/PluginAutoImports.js +59 -0
  402. package/src/runtime/PluginManager.d.ts +1 -5
  403. package/src/runtime/PluginManager.d.ts.map +1 -1
  404. package/src/runtime/PluginManager.js +25 -18
  405. package/src/runtime/RuntimeDetector.d.ts +1 -1
  406. package/src/runtime/RuntimeDetector.d.ts.map +1 -1
  407. package/src/runtime/StartupConfigFileRegistry.d.ts +20 -0
  408. package/src/runtime/StartupConfigFileRegistry.d.ts.map +1 -0
  409. package/src/runtime/StartupConfigFileRegistry.js +44 -0
  410. package/src/runtime/adapters/CloudflareAdapter.d.ts +1 -1
  411. package/src/runtime/adapters/CloudflareAdapter.d.ts.map +1 -1
  412. package/src/runtime/adapters/CloudflareAdapter.js +1 -1
  413. package/src/runtime/adapters/DenoAdapter.d.ts +1 -1
  414. package/src/runtime/adapters/DenoAdapter.d.ts.map +1 -1
  415. package/src/runtime/adapters/DenoAdapter.js +1 -1
  416. package/src/runtime/adapters/LambdaAdapter.d.ts +1 -1
  417. package/src/runtime/adapters/LambdaAdapter.d.ts.map +1 -1
  418. package/src/runtime/adapters/LambdaAdapter.js +1 -1
  419. package/src/runtime/adapters/NodeServerAdapter.d.ts +1 -1
  420. package/src/runtime/adapters/NodeServerAdapter.d.ts.map +1 -1
  421. package/src/runtime/getKernel.d.ts +9 -0
  422. package/src/runtime/getKernel.d.ts.map +1 -0
  423. package/src/runtime/getKernel.js +27 -0
  424. package/src/runtime/useFileLoader.d.ts +26 -0
  425. package/src/runtime/useFileLoader.d.ts.map +1 -0
  426. package/src/runtime/useFileLoader.js +188 -0
  427. package/src/scripts/TemplateImportsCheck.js +40 -0
  428. package/src/scripts/TemplateSync.js +90 -24
  429. package/src/security/Encryptor.d.ts.map +1 -1
  430. package/src/security/Encryptor.js +64 -7
  431. package/src/security/JwtManager.d.ts +1 -0
  432. package/src/security/JwtManager.d.ts.map +1 -1
  433. package/src/security/JwtManager.js +33 -0
  434. package/src/security/Sanitizer.d.ts +76 -0
  435. package/src/security/Sanitizer.d.ts.map +1 -0
  436. package/src/security/Sanitizer.js +412 -0
  437. package/src/security/TokenRevocation.d.ts +7 -0
  438. package/src/security/TokenRevocation.d.ts.map +1 -0
  439. package/src/security/TokenRevocation.js +57 -0
  440. package/src/security/XssProtection.d.ts.map +1 -1
  441. package/src/security/XssProtection.js +62 -14
  442. package/src/seeders/SeederDiscovery.d.ts +5 -0
  443. package/src/seeders/SeederDiscovery.d.ts.map +1 -0
  444. package/src/seeders/SeederDiscovery.js +21 -0
  445. package/src/seeders/SeederLoader.d.ts +5 -0
  446. package/src/seeders/SeederLoader.d.ts.map +1 -0
  447. package/src/seeders/SeederLoader.js +60 -0
  448. package/src/seeders/types.d.ts +18 -0
  449. package/src/seeders/types.d.ts.map +1 -0
  450. package/src/seeders/types.js +1 -0
  451. package/src/session/SessionManager.js +1 -1
  452. package/src/templates/adapters/MySQLAdapter.ts.tpl +109 -85
  453. package/src/templates/adapters/PostgreSQLAdapter.ts.tpl +129 -88
  454. package/src/templates/adapters/SQLServerAdapter.ts.tpl +5 -9
  455. package/src/templates/adapters/SQLiteAdapter.ts.tpl +78 -11
  456. package/src/templates/features/Queue.ts.tpl +3 -2
  457. package/src/templates/project/basic/app/Controllers/AuthController.ts.tpl +217 -0
  458. package/src/templates/project/basic/app/Controllers/UserController.ts.tpl +1 -12
  459. package/src/templates/project/basic/app/Types/controller.ts.tpl +46 -0
  460. package/src/templates/project/basic/config/FileLogWriter.ts.tpl +5 -236
  461. package/src/templates/project/basic/config/SecretsManager.ts.tpl +10 -447
  462. package/src/templates/project/basic/config/StartupConfigValidator.ts.tpl +9 -268
  463. package/src/templates/project/basic/config/app.ts.tpl +13 -153
  464. package/src/templates/project/basic/config/broadcast.ts.tpl +29 -126
  465. package/src/templates/project/basic/config/cache.ts.tpl +12 -70
  466. package/src/templates/project/basic/config/cloudflare.ts.tpl +4 -39
  467. package/src/templates/project/basic/config/constants.ts.tpl +9 -65
  468. package/src/templates/project/basic/config/database.ts.tpl +66 -123
  469. package/src/templates/project/basic/config/env.ts.tpl +5 -169
  470. package/src/templates/project/basic/config/features.ts.tpl +6 -54
  471. package/src/templates/project/basic/config/index.ts.tpl +8 -23
  472. package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +7 -114
  473. package/src/templates/project/basic/config/mail.ts.tpl +9 -62
  474. package/src/templates/project/basic/config/microservices.ts.tpl +11 -97
  475. package/src/templates/project/basic/config/middleware.ts.tpl +25 -43
  476. package/src/templates/project/basic/config/notification.ts.tpl +13 -114
  477. package/src/templates/project/basic/config/queue.ts.tpl +9 -40
  478. package/src/templates/project/basic/config/security.ts.tpl +11 -163
  479. package/src/templates/project/basic/config/startup.ts.tpl +10 -21
  480. package/src/templates/project/basic/config/storage.ts.tpl +57 -137
  481. package/src/templates/project/basic/config/type.ts.tpl +32 -451
  482. package/src/templates/project/basic/database/factories/UserFactory.ts.tpl +80 -0
  483. package/src/templates/project/basic/database/migrations/create_tasks_table.ts.tpl +28 -0
  484. package/src/templates/project/basic/database/migrations/create_users_table.ts.tpl +29 -0
  485. package/src/templates/project/basic/database/seeders/DatabaseSeeder.ts.tpl +19 -0
  486. package/src/templates/project/basic/database/seeders/UserSeeder.ts.tpl +18 -0
  487. package/src/templates/project/basic/database/seeders/index.ts.tpl +2 -0
  488. package/src/templates/project/basic/routes/api.ts.tpl +71 -33
  489. package/src/templates/project/basic/routes/metrics.ts.tpl +22 -0
  490. package/src/templates/project/basic/src/index.ts.tpl +3 -0
  491. package/src/templates/project/basic/tsconfig.json.tpl +12 -11
  492. package/src/testing/TestEnvironment.d.ts +40 -0
  493. package/src/testing/TestEnvironment.d.ts.map +1 -0
  494. package/src/testing/TestEnvironment.js +141 -0
  495. package/src/testing/TestHttp.d.ts +29 -0
  496. package/src/testing/TestHttp.d.ts.map +1 -0
  497. package/src/testing/TestHttp.js +96 -0
  498. package/src/testing/index.d.ts +5 -0
  499. package/src/testing/index.d.ts.map +1 -0
  500. package/src/testing/index.js +2 -0
  501. package/src/time/DateTime.d.ts +181 -0
  502. package/src/time/DateTime.d.ts.map +1 -0
  503. package/src/time/DateTime.js +300 -0
  504. package/src/time/index.d.ts +7 -0
  505. package/src/time/index.d.ts.map +1 -0
  506. package/src/time/index.js +5 -0
  507. package/src/tools/http/Http.d.ts.map +1 -1
  508. package/src/tools/http/Http.js +4 -0
  509. package/src/tools/mail/drivers/Smtp.js +1 -1
  510. package/src/tools/queue/drivers/InMemory.d.ts +1 -1
  511. package/src/tools/queue/drivers/InMemory.d.ts.map +1 -1
  512. package/src/tools/queue/drivers/InMemory.js +1 -1
  513. package/src/tools/queue/drivers/Redis.d.ts +1 -1
  514. package/src/tools/queue/drivers/Redis.d.ts.map +1 -1
  515. package/src/tools/queue/drivers/Redis.js +1 -1
  516. package/src/validation/ValidationError.d.ts.map +1 -1
  517. package/src/validation/ValidationError.js +4 -2
  518. package/src/validation/Validator.d.ts +49 -16
  519. package/src/validation/Validator.d.ts.map +1 -1
  520. package/src/validation/Validator.js +307 -5
  521. package/src/common/uuid.d.ts +0 -3
  522. package/src/common/uuid.d.ts.map +0 -1
  523. package/src/common/uuid.js +0 -30
  524. package/src/templates/project/basic/.env.example.tpl +0 -74
  525. package/src/templates/project/basic/.env.tpl +0 -166
  526. package/src/templates/project/basic/config/logging/KvLogger.ts.tpl +0 -181
  527. package/src/templates/project/basic/config/logging/SlackLogger.ts.tpl +0 -156
  528. package/src/templates/project/basic/database/migrations/index.ts.tpl +0 -2
@@ -3,14 +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
10
- .split('.')
11
- .map((part) => `"${part.replaceAll('"', '""')}"`)
12
- .join('.');
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
+ };
13
36
  const SAFE_IDENTIFIER_PATH = /^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/;
37
+ const SAFE_IDENTIFIER = /^[A-Za-z_]\w*$/;
14
38
  const assertSafeIdentifierPath = (id, label) => {
15
39
  const trimmed = id.trim();
16
40
  if (trimmed.length === 0) {
@@ -20,6 +44,15 @@ const assertSafeIdentifierPath = (id, label) => {
20
44
  throw ErrorFactory.createDatabaseError(`Unsafe SQL identifier for ${label}`);
21
45
  }
22
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
+ };
23
56
  const normalizeOrderDirection = (direction) => {
24
57
  if (direction === undefined || direction === null)
25
58
  return 'ASC';
@@ -69,27 +102,98 @@ const isNumericLiteral = (value) => {
69
102
  // Disallows: 1e3, 1;DROP, 1 as ok
70
103
  return /^(?:0|[1-9]\d*)(?:\.\d+)?$/.test(value);
71
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
+ };
72
161
  /**
73
162
  * Build SELECT clause
74
163
  */
75
- const buildSelectClause = (columns) => columns
76
- .map((c) => {
77
- if (c === '*')
78
- return c;
79
- if (isNumericLiteral(c))
80
- return c;
81
- assertSafeIdentifierPath(c, 'select column');
82
- return escapeIdentifier(c);
83
- })
84
- .join(', ');
85
- 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) => {
86
190
  if (conditions.length === 0)
87
191
  return { sql: '', parameters: [] };
88
192
  const parameters = [];
89
193
  const clauses = conditions.map((clause) => {
90
194
  assertSafeIdentifierPath(clause.column, 'where column');
91
195
  const operator = assertSafeOperator(clause.operator);
92
- const columnSql = escapeIdentifier(clause.column);
196
+ const columnSql = escapeIdentifier(clause.column, dialect);
93
197
  if (operator === 'IN' || operator === 'NOT IN') {
94
198
  if (!Array.isArray(clause.value) || clause.value.length === 0) {
95
199
  throw ErrorFactory.createDatabaseError('IN operator requires a non-empty array');
@@ -142,17 +246,20 @@ const getEffectiveWhereConditions = (state) => {
142
246
  /**
143
247
  * Build ORDER BY clause
144
248
  */
145
- const buildOrderByClause = (orderBy) => {
146
- if (!orderBy)
249
+ const buildOrderByClause = (orderByClauses, dialect) => {
250
+ if (orderByClauses.length === 0)
147
251
  return '';
148
- const col = orderBy.column.trim();
149
- let columnSql = col;
150
- if (!isNumericLiteral(col)) {
151
- assertSafeIdentifierPath(col, 'order by column');
152
- columnSql = escapeIdentifier(col);
153
- }
154
- const dir = normalizeOrderDirection(orderBy.direction);
155
- return ` ORDER BY ${columnSql} ${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(', ')}`;
156
263
  };
157
264
  /**
158
265
  * Build LIMIT and OFFSET clause
@@ -173,10 +280,10 @@ const buildSelectQuery = (state) => {
173
280
  if (state.tableName.length > 0) {
174
281
  assertSafeIdentifierPath(state.tableName, 'table name');
175
282
  }
176
- const columns = buildSelectClause(state.selectColumns);
177
- const fromClause = state.tableName.length > 0 ? ` FROM ${escapeIdentifier(state.tableName)}` : '';
178
- const where = compileWhere(getEffectiveWhereConditions(state));
179
- 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)}`;
180
287
  return { sql, parameters: where.parameters };
181
288
  };
182
289
  const applyWhereCondition = (state, column, operator, value) => {
@@ -204,7 +311,7 @@ const applyOrderByClause = (state, column, direction) => {
204
311
  assertSafeIdentifierPath(col, 'order by column');
205
312
  }
206
313
  const dir = normalizeOrderDirection(direction);
207
- state.orderByClause = { column: col, direction: dir };
314
+ state.orderByClauses.push({ column: col, direction: dir });
208
315
  };
209
316
  const applyLimit = (state, count) => {
210
317
  assertSafeLimitOffset(count, 'LIMIT');
@@ -224,6 +331,64 @@ async function executeFirst(builder, db) {
224
331
  const results = (await db.query(builder.toSQL(), builder.getParameters(), builder.isReadOperation()));
225
332
  return results[0] ?? null;
226
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
+ };
227
392
  /**
228
393
  * Execute query and return all results
229
394
  */
@@ -235,75 +400,214 @@ async function executeGet(builder, db) {
235
400
  /**
236
401
  * Create the builder object
237
402
  */
238
- function createBuilder(state, db) {
239
- const builder = {
240
- select: (...columns) => {
241
- state.selectColumns = columns.length > 0 ? columns : ['*'];
242
- return builder;
243
- },
244
- where: (column, operator, value) => {
245
- applyWhereCondition(state, column, operator, value);
246
- return builder;
247
- },
248
- andWhere: (column, operator, value) => builder.where(column, operator, value),
249
- orWhere: (column, operator, value) => builder.where(column, operator, value),
250
- withTrashed: () => {
251
- if (state.softDelete === undefined) {
252
- state.softDelete = { column: 'deleted_at', mode: 'include' };
253
- }
254
- else {
255
- state.softDelete.mode = 'include';
256
- }
257
- return builder;
258
- },
259
- onlyTrashed: () => {
260
- if (state.softDelete === undefined) {
261
- state.softDelete = { column: 'deleted_at', mode: 'only' };
262
- }
263
- else {
264
- state.softDelete.mode = 'only';
265
- }
266
- return builder;
267
- },
268
- withoutTrashed: () => {
269
- if (state.softDelete === undefined) {
270
- 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);
271
552
  }
272
553
  else {
273
- state.softDelete.mode = 'exclude';
554
+ const found = relatedResults.find((r) => r.getAttribute(foreignKey) === modelId);
555
+ model.setRelation(relation, found ?? null);
274
556
  }
275
- return builder;
276
- },
277
- join: (tableJoin, on) => {
278
- state.joins.push({ table: tableJoin, on });
279
- return builder;
280
- },
281
- leftJoin: (tableJoin, on) => builder.join(tableJoin, on),
282
- orderBy: (column, direction = 'ASC') => {
283
- applyOrderByClause(state, column, direction);
284
- return builder;
285
- },
286
- limit: (count) => {
287
- applyLimit(state, count);
288
- return builder;
289
- },
290
- offset: (count) => {
291
- applyOffset(state, count);
292
- return builder;
293
- },
294
- getWhereClauses: () => state.whereConditions,
295
- getSelectColumns: () => state.selectColumns,
296
- getTable: () => state.tableName,
297
- getLimit: () => state.limitValue,
298
- getOffset: () => state.offsetValue,
299
- getOrderBy: () => state.orderByClause,
300
- getJoins: () => state.joins,
301
- isReadOperation: () => true,
302
- toSQL: () => buildSelectQuery(state).sql,
303
- getParameters: () => buildSelectQuery(state).parameters,
304
- first: async () => executeFirst(builder, db),
305
- get: async () => executeGet(builder, db),
557
+ }
306
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
+ const result = await currentDb.execute(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: result.lastInsertId ??
579
+ (items.length === 1 ? (items[0]?.['id'] ?? null) : null),
580
+ affectedRows: result.rowCount,
581
+ insertedRecords: items,
582
+ };
583
+ };
584
+ builder.update = async (values) => {
585
+ const currentDb = ensureDb();
586
+ const tableName = state.tableName.trim();
587
+ if (tableName.length === 0)
588
+ throw ErrorFactory.createDatabaseError('UPDATE requires a table name');
589
+ const compiled = compileUpdate(tableName, values, state.whereConditions, state.dialect);
590
+ await currentDb.query(compiled.sql, compiled.parameters, false);
591
+ };
592
+ builder.delete = async () => {
593
+ const currentDb = ensureDb();
594
+ const tableName = state.tableName.trim();
595
+ if (tableName.length === 0)
596
+ throw ErrorFactory.createDatabaseError('DELETE requires a table name');
597
+ const compiled = compileDelete(tableName, state.whereConditions, state.dialect);
598
+ await currentDb.query(compiled.sql, compiled.parameters, false);
599
+ };
600
+ }
601
+ function createBuilder(state, db) {
602
+ const builder = {};
603
+ attachSelectMethods(builder, state);
604
+ attachWhereMethods(builder, state);
605
+ attachSoftDeleteMethods(builder, state);
606
+ attachJoinOrderPagingMethods(builder, state);
607
+ attachIntrospectionMethods(builder, state);
608
+ attachReadExecutionMethods(builder, db);
609
+ attachRelationshipMethods(builder, state);
610
+ attachWriteMethods(builder, state, db);
307
611
  return builder;
308
612
  }
309
613
  /**
@@ -327,7 +631,10 @@ export const QueryBuilder = Object.freeze({
327
631
  tableName,
328
632
  whereConditions: [],
329
633
  selectColumns: ['*'],
634
+ orderByClauses: [],
330
635
  joins: [],
636
+ eagerLoads: [],
637
+ dialect: typeof database?.getType === 'function' ? database.getType() : undefined,
331
638
  };
332
639
  if (options.softDeleteColumn !== undefined && options.softDeleteColumn.trim().length > 0) {
333
640
  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"}