@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
@@ -0,0 +1,412 @@
1
+ /**
2
+ * Input Sanitizer (Character Whitelisting)
3
+ *
4
+ * Provides small utilities to remove unwanted characters from user input.
5
+ *
6
+ * Important:
7
+ * - This is NOT a complete SQL injection defense.
8
+ * - Always use parameterized queries / the ORM / QueryBuilder.
9
+ *
10
+ * Use this for:
11
+ * - Normalizing identifiers (username, slug-ish strings)
12
+ * - Cleaning phone numbers / numeric strings
13
+ * - Reducing unexpected characters before storage/logging
14
+ *
15
+ * Bulletproof Mode:
16
+ * - Enabled by default (`bulletproof=true`) for security-critical methods
17
+ * - Throws SanitizerError instead of returning empty/invalid values
18
+ * - Validates numeric ranges, leading zeros, type coercion attacks
19
+ * - ~5-15% performance overhead; disable for performance-critical paths
20
+ */
21
+ import { ErrorFactory } from '../exceptions/ZintrustError.js';
22
+ const MAX_NUMERIC_INPUT_LEN = 64;
23
+ const MAX_EMAIL_LEN = 254;
24
+ const MAX_NAME_LEN = 200;
25
+ const MAX_PASSWORD_LEN = 256;
26
+ const assertMaxLen = (method, label, value, maxLen) => {
27
+ if (value.length <= maxLen)
28
+ return;
29
+ throw ErrorFactory.createSanitizerError(method, `${label} too long`, value);
30
+ };
31
+ const isEmpty = (value) => {
32
+ // Preserve legacy semantics: treat 0 and "0" as empty.
33
+ return (value === null ||
34
+ value === undefined ||
35
+ value === false ||
36
+ value === 0 ||
37
+ value === '' ||
38
+ value === '0');
39
+ };
40
+ const toStr = (value) => {
41
+ return String(value ?? '');
42
+ };
43
+ const stripSpaces = (value) => {
44
+ return toStr(value).replaceAll(' ', '');
45
+ };
46
+ const sanitize = (value, pattern, stripSpace = false) => {
47
+ const input = stripSpace ? stripSpaces(value) : toStr(value);
48
+ return input.replace(pattern, '');
49
+ };
50
+ const isNumericString = (value) => {
51
+ const trimmed = value.trim();
52
+ if (trimmed.length === 0)
53
+ return false;
54
+ const n = Number(trimmed);
55
+ return Number.isFinite(n);
56
+ };
57
+ const parseAmount = (value, bulletproof = true) => {
58
+ if (isEmpty(value))
59
+ return 0;
60
+ const cleaned = sanitize(value, /[^0-9.-]/g, true);
61
+ const num = Number(cleaned);
62
+ if (bulletproof) {
63
+ // Handle string edge cases - check original value
64
+ const str = String(value);
65
+ const trimmed = str.trim();
66
+ assertMaxLen('parseAmount', 'Input', trimmed, MAX_NUMERIC_INPUT_LEN);
67
+ // Reject explicit plus sign prefixes (type confusion)
68
+ if (trimmed.startsWith('+')) {
69
+ throw ErrorFactory.createSanitizerError('parseAmount', 'Plus sign not allowed', value);
70
+ }
71
+ // Reject "Infinity", "-Infinity", "NaN" explicitly
72
+ if (/^[+-]?infinity$/i.test(trimmed) || /^nan$/i.test(trimmed)) {
73
+ throw ErrorFactory.createSanitizerError('parseAmount', 'Non-finite number', value);
74
+ }
75
+ // Reject scientific notation (e.g., "1e308", "2.5e10")
76
+ if (/[eE]/.test(trimmed)) {
77
+ throw ErrorFactory.createSanitizerError('parseAmount', 'Scientific notation not allowed', value);
78
+ }
79
+ assertMaxLen('parseAmount', 'Sanitized numeric', cleaned, MAX_NUMERIC_INPUT_LEN);
80
+ // Require a strict numeric shape after sanitization (prevents "1-2" -> NaN etc.)
81
+ if (!/^-?\d+(?:\.\d+)?$/.test(cleaned)) {
82
+ throw ErrorFactory.createSanitizerError('parseAmount', 'Invalid numeric format', value);
83
+ }
84
+ // Reject Infinity, NaN, and overflow attacks
85
+ if (!Number.isFinite(num)) {
86
+ throw ErrorFactory.createSanitizerError('parseAmount', 'Non-finite number', value);
87
+ }
88
+ if (Math.abs(num) > Number.MAX_SAFE_INTEGER) {
89
+ throw ErrorFactory.createSanitizerError('parseAmount', 'Number exceeds safe integer range', value);
90
+ }
91
+ }
92
+ return Number.isFinite(num) ? num : 0;
93
+ };
94
+ const alphanumeric = (value) => {
95
+ if (isEmpty(value))
96
+ return '';
97
+ return sanitize(value, /[^A-Za-z0-9]/g, true);
98
+ };
99
+ const alphanumericDotDash = (value) => {
100
+ if (isEmpty(value))
101
+ return '';
102
+ return sanitize(value, /[^A-Za-z0-9\-.]/g, true);
103
+ };
104
+ const validateNonNegativeNumericStringPreSanitization = (trimmed, value) => {
105
+ assertMaxLen('nonNegativeNumericStringOrNull', 'Input', trimmed, MAX_NUMERIC_INPUT_LEN);
106
+ // Reject explicit plus sign prefixes (type confusion)
107
+ if (trimmed.startsWith('+')) {
108
+ throw ErrorFactory.createSanitizerError('nonNegativeNumericStringOrNull', 'Plus sign not allowed', value);
109
+ }
110
+ // Reject scientific notation before sanitization can mask it
111
+ if (/[eE]/.test(trimmed)) {
112
+ throw ErrorFactory.createSanitizerError('nonNegativeNumericStringOrNull', 'Scientific notation not allowed', value);
113
+ }
114
+ };
115
+ const validateNonNegativeNumericStringPostSanitization = (da, value) => {
116
+ assertMaxLen('nonNegativeNumericStringOrNull', 'Sanitized numeric', da, MAX_NUMERIC_INPUT_LEN);
117
+ // Strict shape: allow optional leading '-' and optional fractional part.
118
+ if (!/^-?\d+(?:\.\d+)?$/.test(da)) {
119
+ throw ErrorFactory.createSanitizerError('nonNegativeNumericStringOrNull', 'Invalid numeric format', value);
120
+ }
121
+ // For integers (no decimal point), validate leading zeros
122
+ if (da.includes('.')) {
123
+ // For decimals, only check overflow
124
+ const num = Number(da);
125
+ if (Math.abs(num) > Number.MAX_SAFE_INTEGER) {
126
+ throw ErrorFactory.createSanitizerError('nonNegativeNumericStringOrNull', 'Number exceeds safe integer range', value);
127
+ }
128
+ }
129
+ else {
130
+ const numericId = Number.parseInt(da, 10);
131
+ if (!Number.isFinite(numericId) ||
132
+ numericId < 0 ||
133
+ numericId > Number.MAX_SAFE_INTEGER ||
134
+ numericId.toString() !== da) {
135
+ throw ErrorFactory.createSanitizerError('nonNegativeNumericStringOrNull', 'Invalid numeric format (leading zeros, overflow, or type mismatch)', value);
136
+ }
137
+ }
138
+ };
139
+ const nonNegativeNumericStringOrNull = (value, bulletproof = true) => {
140
+ if (isEmpty(value))
141
+ return 0;
142
+ const raw = stripSpaces(value);
143
+ if (bulletproof) {
144
+ const trimmed = raw.trim();
145
+ validateNonNegativeNumericStringPreSanitization(trimmed, value);
146
+ }
147
+ const da = raw.replaceAll(/[^0-9\-.]/g, '');
148
+ const numeric = isNumericString(da);
149
+ if (numeric && Number(da) < 0)
150
+ return 0;
151
+ if (!numeric) {
152
+ return null;
153
+ }
154
+ if (bulletproof) {
155
+ validateNonNegativeNumericStringPostSanitization(da, value);
156
+ }
157
+ return da;
158
+ };
159
+ const digitsOnly = (value, bulletproof = true) => {
160
+ // Special handling for '0' string
161
+ if (value === '0') {
162
+ if (bulletproof) {
163
+ throw ErrorFactory.createSanitizerError('digitsOnly', 'Invalid numeric ID (zero, negative, overflow, or leading zeros)', value);
164
+ }
165
+ return '0';
166
+ }
167
+ if (isEmpty(value))
168
+ return '';
169
+ const da = sanitize(value, /\D/g);
170
+ if (bulletproof) {
171
+ assertMaxLen('digitsOnly', 'Sanitized numeric', da, 16);
172
+ // After removing non-digits, check if result is empty
173
+ if (da.length === 0) {
174
+ throw ErrorFactory.createSanitizerError('digitsOnly', 'Empty result after removing non-digits', value);
175
+ }
176
+ // Check for special characters that get stripped (like +)
177
+ const str = String(value);
178
+ if (/^[+-]/.test(str.trim())) {
179
+ throw ErrorFactory.createSanitizerError('digitsOnly', 'Invalid numeric ID (starts with +/- sign)', value);
180
+ }
181
+ const numericId = Number.parseInt(da, 10);
182
+ if (!Number.isFinite(numericId) ||
183
+ numericId <= 0 ||
184
+ numericId > Number.MAX_SAFE_INTEGER ||
185
+ numericId.toString() !== da) {
186
+ throw ErrorFactory.createSanitizerError('digitsOnly', 'Invalid numeric ID (zero, negative, overflow, or leading zeros)', value);
187
+ }
188
+ }
189
+ return da.replaceAll(' ', '');
190
+ };
191
+ const validateDecimalStringPreSanitization = (trimmed, value) => {
192
+ assertMaxLen('decimalString', 'Input', trimmed, MAX_NUMERIC_INPUT_LEN);
193
+ // Reject explicit plus/minus prefixes and scientific notation (type confusion)
194
+ if (/^[+-]/.test(trimmed)) {
195
+ throw ErrorFactory.createSanitizerError('decimalString', 'Signed values not allowed', value);
196
+ }
197
+ if (/[eE]/.test(trimmed)) {
198
+ throw ErrorFactory.createSanitizerError('decimalString', 'Scientific notation not allowed', value);
199
+ }
200
+ };
201
+ const validateDecimalStringPostSanitization = (result, cleaned, value) => {
202
+ assertMaxLen('decimalString', 'Sanitized numeric', cleaned, MAX_NUMERIC_INPUT_LEN);
203
+ if (result.length === 0) {
204
+ throw ErrorFactory.createSanitizerError('decimalString', 'Empty result after sanitization', value);
205
+ }
206
+ if (!/^\d+(?:\.\d+)?$/.test(result)) {
207
+ throw ErrorFactory.createSanitizerError('decimalString', 'Invalid decimal format', value);
208
+ }
209
+ const num = Number(result);
210
+ if (!Number.isFinite(num)) {
211
+ throw ErrorFactory.createSanitizerError('decimalString', 'Non-numeric decimal value', value);
212
+ }
213
+ if (Math.abs(num) > Number.MAX_SAFE_INTEGER) {
214
+ throw ErrorFactory.createSanitizerError('decimalString', 'Decimal value exceeds safe range', value);
215
+ }
216
+ };
217
+ const decimalString = (value, bulletproof = true) => {
218
+ if (isEmpty(value))
219
+ return '';
220
+ if (bulletproof) {
221
+ const trimmed = String(value).trim();
222
+ validateDecimalStringPreSanitization(trimmed, value);
223
+ }
224
+ // Allow only valid decimal format: digits and at most one decimal point
225
+ const cleaned = sanitize(value, /[^0-9.]/g);
226
+ const parts = cleaned.split('.');
227
+ // Bulletproof mode: reject multiple decimal points rather than merging.
228
+ // Legacy/unsafe mode: normalize by keeping the first decimal point.
229
+ let result;
230
+ if (parts.length > 2) {
231
+ result = bulletproof ? '' : `${parts[0]}.${parts.slice(1).join('')}`;
232
+ }
233
+ else {
234
+ result = cleaned;
235
+ }
236
+ if (bulletproof) {
237
+ validateDecimalStringPostSanitization(result, cleaned, value);
238
+ }
239
+ return result;
240
+ };
241
+ const numericDotOnly = (value) => {
242
+ if (isEmpty(value))
243
+ return '';
244
+ return sanitize(value, /[^0-9.]/g);
245
+ };
246
+ const createBasicSanitizers = () => {
247
+ return {
248
+ parseAmount,
249
+ alphanumeric,
250
+ alphanumericDotDash,
251
+ nonNegativeNumericStringOrNull,
252
+ digitsOnly,
253
+ decimalString,
254
+ numericDotOnly,
255
+ };
256
+ };
257
+ const addressTextSanitizer = (value) => {
258
+ if (isEmpty(value))
259
+ return '';
260
+ return sanitize(value, /[^A-Za-z0-9\-.@+, _]/g);
261
+ };
262
+ const emailLikeSanitizer = (value) => {
263
+ if (isEmpty(value))
264
+ return '';
265
+ return sanitize(value, /[^A-Za-z0-9\-.@+_]/g);
266
+ };
267
+ const emailSanitizer = (value, bulletproof = true) => {
268
+ if (isEmpty(value))
269
+ return '';
270
+ const result = sanitize(value, /[^A-Za-z0-9\-.@_]/g);
271
+ if (bulletproof) {
272
+ const trimmed = result.trim();
273
+ assertMaxLen('email', 'Email', trimmed, MAX_EMAIL_LEN);
274
+ if (trimmed.length === 0) {
275
+ throw ErrorFactory.createSanitizerError('email', 'Empty result after sanitization', value);
276
+ }
277
+ if (!trimmed.includes('@')) {
278
+ throw ErrorFactory.createSanitizerError('email', 'Missing @ symbol in email', value);
279
+ }
280
+ // Basic validation: something@something
281
+ const parts = trimmed.split('@');
282
+ if (parts.length !== 2 || parts[0].length === 0 || parts[1].length === 0) {
283
+ throw ErrorFactory.createSanitizerError('email', 'Invalid email format', value);
284
+ }
285
+ }
286
+ return result;
287
+ };
288
+ const messageTextSanitizer = (value) => {
289
+ if (isEmpty(value))
290
+ return '';
291
+ return sanitize(value, /[^A-Za-z0-9\-.@+_&$%!,()? ]/g);
292
+ };
293
+ const nameTextSanitizer = (value, bulletproof = true) => {
294
+ if (isEmpty(value))
295
+ return '';
296
+ const result = sanitize(value, /[^A-Za-z0-9 .]/g);
297
+ if (bulletproof) {
298
+ const trimmed = result.trim();
299
+ assertMaxLen('nameText', 'Name', trimmed, MAX_NAME_LEN);
300
+ if (trimmed.length === 0) {
301
+ throw ErrorFactory.createSanitizerError('nameText', 'Empty or whitespace-only result', value);
302
+ }
303
+ // Names should have at least one letter
304
+ if (!/[A-Za-z]/.test(trimmed)) {
305
+ throw ErrorFactory.createSanitizerError('nameText', 'Name must contain at least one letter', value);
306
+ }
307
+ }
308
+ return result;
309
+ };
310
+ const wordCharsAndSpacesSanitizer = (value) => {
311
+ if (isEmpty(value))
312
+ return '';
313
+ return sanitize(value, /[^A-Za-z0-9_\s]/g);
314
+ };
315
+ const safePasswordCharsSanitizer = (value, bulletproof = true) => {
316
+ if (isEmpty(value))
317
+ return '';
318
+ const result = sanitize(value, /[^!@#$%&*/\sA-Za-z0-9_]/g);
319
+ if (bulletproof) {
320
+ const trimmed = result.trim();
321
+ assertMaxLen('safePasswordChars', 'Password', trimmed, MAX_PASSWORD_LEN);
322
+ if (trimmed.length === 0) {
323
+ throw ErrorFactory.createSanitizerError('safePasswordChars', 'Empty result after sanitization', value);
324
+ }
325
+ }
326
+ return result;
327
+ };
328
+ const createTextSanitizers = () => {
329
+ return {
330
+ addressText: addressTextSanitizer,
331
+ emailLike: emailLikeSanitizer,
332
+ email: emailSanitizer,
333
+ messageText: messageTextSanitizer,
334
+ nameText: nameTextSanitizer,
335
+ wordCharsAndSpaces: wordCharsAndSpacesSanitizer,
336
+ safePasswordChars: safePasswordCharsSanitizer,
337
+ };
338
+ };
339
+ const createSpecializedSanitizers = () => {
340
+ const ipAddressText = (value) => {
341
+ if (isEmpty(value))
342
+ return '';
343
+ return sanitize(value, /[^A-Za-z0-9:.]/g);
344
+ };
345
+ const alphaNumericColonDash = (value) => {
346
+ if (isEmpty(value))
347
+ return '';
348
+ return sanitize(value, /[^A-Za-z0-9:-]/g);
349
+ };
350
+ const dateSlash = (value) => {
351
+ if (isEmpty(value))
352
+ return '';
353
+ return sanitize(value, /[^0-9/]/g);
354
+ };
355
+ const lowercaseAlphanumeric = (value) => {
356
+ if (isEmpty(value))
357
+ return '';
358
+ return sanitize(value, /[^A-Za-z0-9]/g).toLowerCase();
359
+ };
360
+ const uppercaseAlphanumeric = (value) => {
361
+ if (isEmpty(value))
362
+ return '';
363
+ return sanitize(value, /[^A-Za-z0-9]/g).toUpperCase();
364
+ };
365
+ const alphanumericNoSpaces = (value) => {
366
+ if (isEmpty(value))
367
+ return '';
368
+ return sanitize(value, /[^A-Za-z0-9 ]/g, true);
369
+ };
370
+ const dateSlashNoSpaces = (value) => {
371
+ if (isEmpty(value))
372
+ return '';
373
+ return sanitize(value, /[^0-9/]/g, true);
374
+ };
375
+ // Legacy naming was misleading; this is closer to a "uuid/token safe" whitelist.
376
+ const uuidTokenSafe = (value) => {
377
+ if (isEmpty(value))
378
+ return '';
379
+ return sanitize(value, /[^A-Za-z0-9\-=]/g, true);
380
+ };
381
+ // Base64url-like (plus "=") token whitelisting.
382
+ const tokenSafe = (value) => {
383
+ if (isEmpty(value))
384
+ return '';
385
+ return sanitize(value, /[^A-Za-z0-9\-=_]/g, true);
386
+ };
387
+ const keyLike = (value) => {
388
+ if (isEmpty(value))
389
+ return '';
390
+ return sanitize(value, /[^A-Za-z0-9\-:. ]/g, true);
391
+ };
392
+ return {
393
+ ipAddressText,
394
+ alphaNumericColonDash,
395
+ dateSlash,
396
+ lowercaseAlphanumeric,
397
+ uppercaseAlphanumeric,
398
+ alphanumericNoSpaces,
399
+ dateSlashNoSpaces,
400
+ uuidTokenSafe,
401
+ tokenSafe,
402
+ keyLike,
403
+ };
404
+ };
405
+ export const createSanitizer = () => {
406
+ return Object.freeze({
407
+ ...createBasicSanitizers(),
408
+ ...createTextSanitizers(),
409
+ ...createSpecializedSanitizers(),
410
+ });
411
+ };
412
+ export const Sanitizer = createSanitizer();
@@ -0,0 +1,7 @@
1
+ type AuthorizationHeader = string | string[] | undefined;
2
+ export declare const TokenRevocation: Readonly<{
3
+ revoke(header: AuthorizationHeader): string | null;
4
+ isRevoked(token: string): boolean;
5
+ }>;
6
+ export default TokenRevocation;
7
+ //# sourceMappingURL=TokenRevocation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenRevocation.d.ts","sourceRoot":"","sources":["../../../src/security/TokenRevocation.ts"],"names":[],"mappings":"AAGA,KAAK,mBAAmB,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;AAsCzD,eAAO,MAAM,eAAe;mBACX,mBAAmB,GAAG,MAAM,GAAG,IAAI;qBASjC,MAAM,GAAG,OAAO;EAUjC,CAAC;AAEH,eAAe,eAAe,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { securityConfig } from '../config/security.js';
2
+ import { JwtManager } from './JwtManager.js';
3
+ const revokedTokens = new Map();
4
+ const defaultTtlMs = Math.max(securityConfig.jwt.expiresIn * 1000, 60_000);
5
+ const getBearerToken = (header) => {
6
+ const value = Array.isArray(header) ? header[0] : header;
7
+ if (typeof value !== 'string')
8
+ return null;
9
+ const [scheme, token] = value.trim().split(' ');
10
+ if (scheme.toLowerCase() !== 'bearer')
11
+ return null;
12
+ if (typeof token !== 'string' || token.trim() === '')
13
+ return null;
14
+ return token;
15
+ };
16
+ const cleanupExpired = () => {
17
+ const now = Date.now();
18
+ for (const [token, expiresAt] of revokedTokens.entries()) {
19
+ if (expiresAt <= now) {
20
+ revokedTokens.delete(token);
21
+ }
22
+ }
23
+ };
24
+ const resolveExpiryMs = (token) => {
25
+ try {
26
+ const payload = JwtManager.create().decode(token);
27
+ if (typeof payload.exp === 'number' && Number.isFinite(payload.exp)) {
28
+ return payload.exp * 1000;
29
+ }
30
+ }
31
+ catch {
32
+ // ignore decode errors; fallback to default TTL
33
+ }
34
+ return Date.now() + defaultTtlMs;
35
+ };
36
+ export const TokenRevocation = Object.freeze({
37
+ revoke(header) {
38
+ const token = getBearerToken(header);
39
+ if (token === null)
40
+ return null;
41
+ cleanupExpired();
42
+ revokedTokens.set(token, resolveExpiryMs(token));
43
+ return token;
44
+ },
45
+ isRevoked(token) {
46
+ cleanupExpired();
47
+ const expiresAt = revokedTokens.get(token);
48
+ if (expiresAt === undefined)
49
+ return false;
50
+ if (expiresAt <= Date.now()) {
51
+ revokedTokens.delete(token);
52
+ return false;
53
+ }
54
+ return true;
55
+ },
56
+ });
57
+ export default TokenRevocation;
@@ -1 +1 @@
1
- {"version":3,"file":"XssProtection.d.ts","sourceRoot":"","sources":["../../../src/security/XssProtection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA6SH;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,OAAO,KAAG,MAGzC,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC;CAClC;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,cAO1B,CAAC"}
1
+ {"version":3,"file":"XssProtection.d.ts","sourceRoot":"","sources":["../../../src/security/XssProtection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA0WH;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,OAAO,KAAG,MAGzC,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC;CAClC;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,cAO1B,CAAC"}
@@ -27,30 +27,51 @@ const escapeHtml = (text) => {
27
27
  /**
28
28
  * Sanitize HTML by removing dangerous tags and attributes
29
29
  */
30
- const sanitizeHtml = (html) => {
31
- if (typeof html !== 'string') {
32
- return '';
33
- }
30
+ const MAX_SANITIZE_LOOPS = 50;
31
+ function removeScripts(input) {
34
32
  // Remove script tags and content (loop until stable to avoid incomplete multi-character sanitization)
35
- let sanitized = html;
36
- let prevScriptSanitized;
33
+ let sanitized = input;
34
+ let prevSanitized;
35
+ let loopCount = 0;
37
36
  do {
38
- prevScriptSanitized = sanitized;
37
+ prevSanitized = sanitized;
39
38
  sanitized = sanitized.replaceAll(/<script\b[\s\S]*?<\/script[^<]*?>/gi, '');
40
- } while (sanitized !== prevScriptSanitized);
39
+ loopCount++;
40
+ } while (sanitized !== prevSanitized && loopCount < MAX_SANITIZE_LOOPS);
41
+ if (loopCount >= MAX_SANITIZE_LOOPS) {
42
+ Logger.warn('[XSS] Sanitization loop limit reached (script removal)');
43
+ return ''; // Fail safe: return empty string if attack detected
44
+ }
45
+ return sanitized;
46
+ }
47
+ function removeDangerousTags(input) {
41
48
  // Remove iframe, object, embed, and base tags
49
+ let sanitized = input;
42
50
  sanitized = sanitized.replaceAll(/<(?:iframe|object|embed|base)\b[\s\S]*?>/gi, '');
43
51
  sanitized = sanitized.replaceAll(/<\/(?:iframe|object|embed|base)>/gi, '');
52
+ return sanitized;
53
+ }
54
+ function removeEventHandlers(input) {
44
55
  // Remove event handlers (on*). Re-apply until stable to avoid incomplete multi-character sanitization.
45
- let previousSanitized;
56
+ let sanitized = input;
57
+ let prevSanitized;
58
+ let loopCount = 0;
46
59
  do {
47
- previousSanitized = sanitized;
60
+ prevSanitized = sanitized;
48
61
  sanitized = sanitized.replaceAll(/\bon\w+\s*=\s*(?:'[^']*'|"[^"]*"|`[^`]*`|[^\s>]*)/gi, '');
49
- } while (sanitized !== previousSanitized);
62
+ loopCount++;
63
+ } while (sanitized !== prevSanitized && loopCount < MAX_SANITIZE_LOOPS);
64
+ if (loopCount >= MAX_SANITIZE_LOOPS) {
65
+ Logger.warn('[XSS] Sanitization loop limit reached (event handler removal)');
66
+ return '';
67
+ }
68
+ return sanitized;
69
+ }
70
+ function stripDangerousUrlAttributes(input) {
50
71
  // Remove dangerous protocols in URL-bearing attributes.
51
72
  // This uses the same protocol normalization logic as encodeHref to prevent obfuscations like:
52
73
  // href="jav&#x61;script:..." or href="java\nscript:..." or href="%6a%61..."
53
- sanitized = sanitized.replaceAll(/(\s)(href|src|action|formaction|xlink:href)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi, (match, _leadingWhitespace, _attributeName, doubleQuotedValue, singleQuotedValue, unquotedValue) => {
74
+ return input.replaceAll(/(\s)(href|src|action|formaction|xlink:href)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi, (match, _leadingWhitespace, _attributeName, doubleQuotedValue, singleQuotedValue, unquotedValue) => {
54
75
  const rawValue = doubleQuotedValue ?? singleQuotedValue ?? unquotedValue ?? '';
55
76
  const protocolCheck = normalizeHrefForProtocolCheck(rawValue);
56
77
  // Allow relative URLs and fragments.
@@ -92,19 +113,46 @@ const sanitizeHtml = (html) => {
92
113
  // Otherwise, keep the attribute (e.g. relative-like values without a scheme).
93
114
  return match;
94
115
  });
116
+ }
117
+ function removeStyles(input) {
95
118
  // Remove style tags and style attributes with potentially dangerous content
119
+ let sanitized = input;
96
120
  let prevSanitized;
121
+ let loopCount = 0;
97
122
  do {
98
123
  prevSanitized = sanitized;
99
124
  sanitized = sanitized.replaceAll(/<style\b[\s\S]*?<\/style>/gi, '');
100
- } while (sanitized !== prevSanitized);
125
+ loopCount++;
126
+ } while (sanitized !== prevSanitized && loopCount < MAX_SANITIZE_LOOPS);
127
+ if (loopCount >= MAX_SANITIZE_LOOPS) {
128
+ Logger.warn('[XSS] Sanitization loop limit reached (style removal)');
129
+ return '';
130
+ }
101
131
  sanitized = sanitized.replaceAll(/\bstyle\s*=\s*(?:'[^']*'|"[^"]*"|[^\s>]*)/gi, '');
132
+ return sanitized;
133
+ }
134
+ function sanitizeHtml(html) {
135
+ if (typeof html !== 'string') {
136
+ return '';
137
+ }
138
+ let sanitized = html;
139
+ sanitized = removeScripts(sanitized);
140
+ if (!sanitized)
141
+ return '';
142
+ sanitized = removeDangerousTags(sanitized);
143
+ sanitized = removeEventHandlers(sanitized);
144
+ if (!sanitized)
145
+ return '';
146
+ sanitized = stripDangerousUrlAttributes(sanitized);
147
+ sanitized = removeStyles(sanitized);
148
+ if (!sanitized)
149
+ return '';
102
150
  // Remove form elements
103
151
  sanitized = sanitized.replaceAll(/<form\b[\s\S]*?<\/form>/gi, '');
104
152
  // Remove object and embed tags
105
153
  sanitized = sanitized.replaceAll(/<(?:object|embed|applet|meta|link|base)\b[\s\S]*?>/gi, '');
106
154
  return sanitized.trim();
107
- };
155
+ }
108
156
  /**
109
157
  * Encode URI component to prevent injection in URLs
110
158
  */
@@ -0,0 +1,5 @@
1
+ export declare const SeederDiscovery: Readonly<{
2
+ resolveDir(projectRoot: string, dir: string): string;
3
+ listSeederFiles(dir: string): string[];
4
+ }>;
5
+ //# sourceMappingURL=SeederDiscovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SeederDiscovery.d.ts","sourceRoot":"","sources":["../../../src/seeders/SeederDiscovery.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,eAAe;4BACF,MAAM,OAAO,MAAM,GAAG,MAAM;yBAI/B,MAAM,GAAG,MAAM,EAAE;EAQtC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import fs from '../node-singletons/fs.js';
2
+ import * as path from '../node-singletons/path.js';
3
+ const isSeederFile = (file) => {
4
+ if (file.endsWith('.d.ts'))
5
+ return false;
6
+ return file.endsWith('.ts') || file.endsWith('.js');
7
+ };
8
+ export const SeederDiscovery = Object.freeze({
9
+ resolveDir(projectRoot, dir) {
10
+ return path.resolve(projectRoot, dir);
11
+ },
12
+ listSeederFiles(dir) {
13
+ if (!fs.existsSync(dir))
14
+ return [];
15
+ const files = fs.readdirSync(dir);
16
+ return files
17
+ .filter(isSeederFile)
18
+ .sort((a, b) => a.localeCompare(b))
19
+ .map((f) => path.join(dir, f));
20
+ },
21
+ });
@@ -0,0 +1,5 @@
1
+ import type { LoadedSeeder } from '../seeders/types';
2
+ export declare const SeederLoader: Readonly<{
3
+ load(filePath: string): Promise<LoadedSeeder>;
4
+ }>;
5
+ //# sourceMappingURL=SeederLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SeederLoader.d.ts","sourceRoot":"","sources":["../../../src/seeders/SeederLoader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,iBAAiB,CAAC;AAwDnE,eAAO,MAAM,YAAY;mBACF,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;EA0BnD,CAAC"}