@zintrust/core 0.1.1 → 0.1.3

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 (487) hide show
  1. package/README.md +3 -3
  2. package/bin/zintrust.d.ts.map +1 -1
  3. package/bin/zintrust.js +18 -1
  4. package/package.json +15 -1
  5. package/src/boot/Application.d.ts.map +1 -1
  6. package/src/boot/Application.js +46 -3
  7. package/src/boot/Server.d.ts.map +1 -1
  8. package/src/boot/Server.js +3 -4
  9. package/src/boot/bootstrap.js +77 -6
  10. package/src/builder/BundleOptimizer.d.ts.map +1 -1
  11. package/src/builder/BundleOptimizer.js +6 -4
  12. package/src/cache/drivers/KVDriver.d.ts.map +1 -1
  13. package/src/cache/drivers/KVDriver.js +6 -6
  14. package/src/cache/drivers/RedisDriver.js +1 -1
  15. package/src/cli/BaseCommand.d.ts +2 -2
  16. package/src/cli/BaseCommand.d.ts.map +1 -1
  17. package/src/cli/BaseCommand.js +2 -1
  18. package/src/cli/CLI.d.ts.map +1 -1
  19. package/src/cli/CLI.js +11 -4
  20. package/src/cli/commands/AddCommand.js +1 -1
  21. package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
  22. package/src/cli/commands/ConfigCommand.js +34 -4
  23. package/src/cli/commands/D1MigrateCommand.d.ts +4 -0
  24. package/src/cli/commands/D1MigrateCommand.d.ts.map +1 -1
  25. package/src/cli/commands/D1MigrateCommand.js +4 -3
  26. package/src/cli/commands/FixCommand.d.ts.map +1 -1
  27. package/src/cli/commands/FixCommand.js +3 -16
  28. package/src/cli/commands/LogsCleanupCommand.d.ts +6 -0
  29. package/src/cli/commands/LogsCleanupCommand.d.ts.map +1 -0
  30. package/src/cli/commands/LogsCleanupCommand.js +20 -0
  31. package/src/cli/commands/LogsCommand.d.ts.map +1 -1
  32. package/src/cli/commands/LogsCommand.js +1 -1
  33. package/src/cli/commands/MakeMailTemplateCommand.d.ts +10 -0
  34. package/src/cli/commands/MakeMailTemplateCommand.d.ts.map +1 -0
  35. package/src/cli/commands/MakeMailTemplateCommand.js +74 -0
  36. package/src/cli/commands/MakeNotificationTemplateCommand.d.ts +10 -0
  37. package/src/cli/commands/MakeNotificationTemplateCommand.d.ts.map +1 -0
  38. package/src/cli/commands/MakeNotificationTemplateCommand.js +113 -0
  39. package/src/cli/commands/NewCommand.d.ts +4 -0
  40. package/src/cli/commands/NewCommand.d.ts.map +1 -1
  41. package/src/cli/commands/NewCommand.js +33 -20
  42. package/src/cli/commands/PluginCommand.d.ts.map +1 -1
  43. package/src/cli/commands/PluginCommand.js +8 -4
  44. package/src/cli/commands/PrepareCommand.d.ts.map +1 -1
  45. package/src/cli/commands/PrepareCommand.js +1 -1
  46. package/src/cli/commands/QACommand.d.ts.map +1 -1
  47. package/src/cli/commands/QACommand.js +11 -20
  48. package/src/cli/commands/SecretsCommand.d.ts +16 -0
  49. package/src/cli/commands/SecretsCommand.d.ts.map +1 -0
  50. package/src/cli/commands/SecretsCommand.js +91 -0
  51. package/src/cli/commands/StartCommand.d.ts.map +1 -1
  52. package/src/cli/commands/StartCommand.js +2 -2
  53. package/src/cli/commands/TemplatesCommand.d.ts +3 -0
  54. package/src/cli/commands/TemplatesCommand.d.ts.map +1 -0
  55. package/src/cli/commands/TemplatesCommand.js +65 -0
  56. package/src/cli/commands/index.d.ts +5 -0
  57. package/src/cli/commands/index.d.ts.map +1 -1
  58. package/src/cli/commands/index.js +5 -0
  59. package/src/cli/config/ConfigManager.js +1 -1
  60. package/src/cli/index.d.ts +2 -1
  61. package/src/cli/index.d.ts.map +1 -1
  62. package/src/cli/index.js +2 -1
  63. package/src/cli/scaffolding/ControllerGenerator.js +1 -1
  64. package/src/cli/scaffolding/FeatureScaffolder.js +4 -4
  65. package/src/cli/scaffolding/FileGenerator.js +1 -1
  66. package/src/cli/scaffolding/ModelGenerator.js +1 -1
  67. package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
  68. package/src/cli/scaffolding/ProjectScaffolder.js +61 -11
  69. package/src/cli/scaffolding/ResponseFactoryGenerator.d.ts.map +1 -1
  70. package/src/cli/scaffolding/ResponseFactoryGenerator.js +3 -2
  71. package/src/cli/scaffolding/RouteGenerator.js +1 -1
  72. package/src/cli/scaffolding/ServiceIntegrationTestGenerator.js +1 -1
  73. package/src/cli/scaffolding/ServiceScaffolder.js +2 -2
  74. package/src/cli/scaffolding/TemplateGenerator.d.ts +40 -0
  75. package/src/cli/scaffolding/TemplateGenerator.d.ts.map +1 -0
  76. package/src/cli/scaffolding/TemplateGenerator.js +172 -0
  77. package/src/cli/scaffolding/index.d.ts +1 -0
  78. package/src/cli/scaffolding/index.d.ts.map +1 -1
  79. package/src/cli/scaffolding/index.js +1 -0
  80. package/src/cli/utils/spawn.js +1 -1
  81. package/src/common/AwsSigV4.d.ts +41 -0
  82. package/src/common/AwsSigV4.d.ts.map +1 -0
  83. package/src/common/AwsSigV4.js +69 -0
  84. package/src/common/index.d.ts +39 -0
  85. package/src/common/index.d.ts.map +1 -1
  86. package/src/common/index.js +101 -8
  87. package/src/common/uuid.d.ts +3 -0
  88. package/src/common/uuid.d.ts.map +1 -0
  89. package/src/common/uuid.js +30 -0
  90. package/src/config/FileLogWriter.d.ts +22 -0
  91. package/src/config/FileLogWriter.d.ts.map +1 -0
  92. package/src/config/FileLogWriter.js +192 -0
  93. package/src/config/SecretsManager.d.ts.map +1 -1
  94. package/src/config/SecretsManager.js +37 -11
  95. package/src/config/StartupConfigValidator.d.ts +15 -0
  96. package/src/config/StartupConfigValidator.d.ts.map +1 -0
  97. package/src/config/StartupConfigValidator.js +86 -0
  98. package/src/config/app.d.ts +2 -1
  99. package/src/config/app.d.ts.map +1 -1
  100. package/src/config/app.js +65 -15
  101. package/src/config/broadcast.d.ts +47 -0
  102. package/src/config/broadcast.d.ts.map +1 -0
  103. package/src/config/broadcast.js +54 -0
  104. package/src/config/cache.d.ts +13 -17
  105. package/src/config/cache.d.ts.map +1 -1
  106. package/src/config/cache.js +9 -11
  107. package/src/config/cloudflare.d.ts +26 -0
  108. package/src/config/cloudflare.d.ts.map +1 -0
  109. package/src/config/cloudflare.js +38 -0
  110. package/src/config/env.d.ts +6 -0
  111. package/src/config/env.d.ts.map +1 -1
  112. package/src/config/env.js +6 -0
  113. package/src/config/index.d.ts +52 -28
  114. package/src/config/index.d.ts.map +1 -1
  115. package/src/config/index.js +3 -0
  116. package/src/config/logger.d.ts +2 -0
  117. package/src/config/logger.d.ts.map +1 -1
  118. package/src/config/logger.js +270 -11
  119. package/src/config/logging/HttpLogger.d.ts +23 -0
  120. package/src/config/logging/HttpLogger.d.ts.map +1 -0
  121. package/src/config/logging/HttpLogger.js +93 -0
  122. package/src/config/logging/KvLogger.d.ts +22 -0
  123. package/src/config/logging/KvLogger.d.ts.map +1 -0
  124. package/src/config/logging/KvLogger.js +143 -0
  125. package/src/config/logging/SlackLogger.d.ts +23 -0
  126. package/src/config/logging/SlackLogger.d.ts.map +1 -0
  127. package/src/config/logging/SlackLogger.js +119 -0
  128. package/src/config/mail.d.ts +81 -0
  129. package/src/config/mail.d.ts.map +1 -0
  130. package/src/config/mail.js +73 -0
  131. package/src/config/middleware.d.ts +8 -0
  132. package/src/config/middleware.d.ts.map +1 -0
  133. package/src/config/middleware.js +18 -0
  134. package/src/config/notification.d.ts +62 -0
  135. package/src/config/notification.d.ts.map +1 -0
  136. package/src/config/notification.js +43 -0
  137. package/src/config/security.d.ts.map +1 -1
  138. package/src/config/security.js +2 -2
  139. package/src/config/startup.d.ts +23 -0
  140. package/src/config/startup.d.ts.map +1 -0
  141. package/src/config/startup.js +15 -0
  142. package/src/config/storage.d.ts +21 -35
  143. package/src/config/storage.d.ts.map +1 -1
  144. package/src/config/storage.js +57 -37
  145. package/src/database/migrations/index.d.ts +1 -1
  146. package/src/database/migrations/index.d.ts.map +1 -1
  147. package/src/database/migrations/index.js +2 -1
  148. package/src/features/Queue.js +1 -25
  149. package/src/health/RuntimeHealthProbes.d.ts +13 -0
  150. package/src/health/RuntimeHealthProbes.d.ts.map +1 -0
  151. package/src/health/RuntimeHealthProbes.js +62 -0
  152. package/src/health/StartupHealthChecks.d.ts +26 -0
  153. package/src/health/StartupHealthChecks.d.ts.map +1 -0
  154. package/src/health/StartupHealthChecks.js +124 -0
  155. package/src/http/ErrorResponse.d.ts +28 -0
  156. package/src/http/ErrorResponse.d.ts.map +1 -0
  157. package/src/http/ErrorResponse.js +42 -0
  158. package/src/http/Kernel.d.ts +5 -0
  159. package/src/http/Kernel.d.ts.map +1 -1
  160. package/src/http/Kernel.js +96 -30
  161. package/src/http/RequestContext.d.ts +20 -0
  162. package/src/http/RequestContext.d.ts.map +1 -0
  163. package/src/http/RequestContext.js +77 -0
  164. package/src/index.d.ts +9 -1
  165. package/src/index.d.ts.map +1 -1
  166. package/src/index.js +8 -2
  167. package/src/microservices/MicroserviceManager.d.ts.map +1 -1
  168. package/src/microservices/MicroserviceManager.js +9 -6
  169. package/src/microservices/PostgresAdapter.d.ts.map +1 -1
  170. package/src/microservices/PostgresAdapter.js +3 -1
  171. package/src/microservices/ServiceBundler.d.ts.map +1 -1
  172. package/src/microservices/ServiceBundler.js +6 -4
  173. package/src/microservices/ServiceHealthMonitor.js +2 -2
  174. package/src/middleware/CsrfMiddleware.d.ts.map +1 -1
  175. package/src/middleware/CsrfMiddleware.js +2 -19
  176. package/src/middleware/ErrorHandlerMiddleware.d.ts +6 -0
  177. package/src/middleware/ErrorHandlerMiddleware.d.ts.map +1 -0
  178. package/src/middleware/ErrorHandlerMiddleware.js +33 -0
  179. package/src/middleware/LoggingMiddleware.d.ts +9 -0
  180. package/src/middleware/LoggingMiddleware.d.ts.map +1 -0
  181. package/src/middleware/LoggingMiddleware.js +36 -0
  182. package/src/middleware/index.d.ts +2 -0
  183. package/src/middleware/index.d.ts.map +1 -1
  184. package/src/middleware/index.js +2 -0
  185. package/src/node-singletons/async_hooks.d.ts +9 -0
  186. package/src/node-singletons/async_hooks.d.ts.map +1 -0
  187. package/src/node-singletons/async_hooks.js +8 -0
  188. package/src/node-singletons/fs.d.ts +2 -2
  189. package/src/node-singletons/fs.d.ts.map +1 -1
  190. package/src/node-singletons/fs.js +2 -2
  191. package/src/node-singletons/http.d.ts +1 -1
  192. package/src/node-singletons/http.d.ts.map +1 -1
  193. package/src/node-singletons/http.js +1 -1
  194. package/src/node-singletons/index.d.ts +4 -0
  195. package/src/node-singletons/index.d.ts.map +1 -1
  196. package/src/node-singletons/index.js +4 -0
  197. package/src/node-singletons/net.d.ts +9 -0
  198. package/src/node-singletons/net.d.ts.map +1 -0
  199. package/src/node-singletons/net.js +8 -0
  200. package/src/node-singletons/os.d.ts +3 -3
  201. package/src/node-singletons/os.d.ts.map +1 -1
  202. package/src/node-singletons/os.js +3 -4
  203. package/src/node-singletons/path.d.ts +3 -1
  204. package/src/node-singletons/path.d.ts.map +1 -1
  205. package/src/node-singletons/path.js +3 -1
  206. package/src/node-singletons/perf-hooks.d.ts +3 -1
  207. package/src/node-singletons/perf-hooks.d.ts.map +1 -1
  208. package/src/node-singletons/perf-hooks.js +3 -1
  209. package/src/node-singletons/process.d.ts +23 -0
  210. package/src/node-singletons/process.d.ts.map +1 -0
  211. package/src/node-singletons/process.js +8 -0
  212. package/src/node-singletons/readline.d.ts +3 -3
  213. package/src/node-singletons/readline.d.ts.map +1 -1
  214. package/src/node-singletons/readline.js +3 -4
  215. package/src/node-singletons/tls.d.ts +9 -0
  216. package/src/node-singletons/tls.d.ts.map +1 -0
  217. package/src/node-singletons/tls.js +8 -0
  218. package/src/node-singletons/url.d.ts +3 -1
  219. package/src/node-singletons/url.d.ts.map +1 -1
  220. package/src/node-singletons/url.js +3 -1
  221. package/src/orm/ConnectionManager.d.ts +6 -1
  222. package/src/orm/ConnectionManager.d.ts.map +1 -1
  223. package/src/orm/ConnectionManager.js +14 -0
  224. package/src/orm/DatabaseAdapter.d.ts +6 -0
  225. package/src/orm/DatabaseAdapter.d.ts.map +1 -1
  226. package/src/orm/QueryBuilder.d.ts +8 -1
  227. package/src/orm/QueryBuilder.d.ts.map +1 -1
  228. package/src/orm/QueryBuilder.js +188 -28
  229. package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
  230. package/src/orm/adapters/D1Adapter.js +18 -12
  231. package/src/orm/adapters/MySQLAdapter.d.ts.map +1 -1
  232. package/src/orm/adapters/MySQLAdapter.js +4 -0
  233. package/src/orm/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  234. package/src/orm/adapters/PostgreSQLAdapter.js +4 -0
  235. package/src/orm/adapters/SQLServerAdapter.d.ts.map +1 -1
  236. package/src/orm/adapters/SQLServerAdapter.js +4 -0
  237. package/src/orm/adapters/SQLiteAdapter.d.ts.map +1 -1
  238. package/src/orm/adapters/SQLiteAdapter.js +4 -0
  239. package/src/performance/CodeGenerationBenchmark.js +3 -3
  240. package/src/performance/Optimizer.d.ts +1 -1
  241. package/src/performance/Optimizer.d.ts.map +1 -1
  242. package/src/performance/Optimizer.js +150 -75
  243. package/src/performance/establish-baseline.js +3 -3
  244. package/src/runtime/PluginManager.d.ts +3 -1
  245. package/src/runtime/PluginManager.d.ts.map +1 -1
  246. package/src/runtime/PluginManager.js +124 -28
  247. package/src/runtime/RuntimeDetector.d.ts.map +1 -1
  248. package/src/runtime/RuntimeDetector.js +47 -6
  249. package/src/runtime/adapters/CloudflareAdapter.js +2 -2
  250. package/src/runtime/adapters/FargateAdapter.d.ts.map +1 -1
  251. package/src/runtime/adapters/FargateAdapter.js +2 -1
  252. package/src/runtime/adapters/LambdaAdapter.d.ts.map +1 -1
  253. package/src/runtime/adapters/LambdaAdapter.js +4 -2
  254. package/src/runtime/adapters/NodeServerAdapter.d.ts.map +1 -1
  255. package/src/runtime/adapters/NodeServerAdapter.js +2 -1
  256. package/src/scheduler/ScheduleRunner.d.ts +18 -0
  257. package/src/scheduler/ScheduleRunner.d.ts.map +1 -0
  258. package/src/scheduler/ScheduleRunner.js +155 -0
  259. package/src/scheduler/index.d.ts +3 -0
  260. package/src/scheduler/index.d.ts.map +1 -0
  261. package/src/scheduler/index.js +1 -0
  262. package/src/scheduler/types.d.ts +16 -0
  263. package/src/scheduler/types.d.ts.map +1 -0
  264. package/src/scheduler/types.js +4 -0
  265. package/src/schedules/index.d.ts +2 -0
  266. package/src/schedules/index.d.ts.map +1 -0
  267. package/src/schedules/index.js +1 -0
  268. package/src/schedules/log-cleanup.d.ts +4 -0
  269. package/src/schedules/log-cleanup.d.ts.map +1 -0
  270. package/src/schedules/log-cleanup.js +18 -0
  271. package/src/scripts/GenerateEnvArtifacts.d.ts +13 -0
  272. package/src/scripts/GenerateEnvArtifacts.d.ts.map +1 -0
  273. package/src/scripts/GenerateEnvArtifacts.js +171 -0
  274. package/src/scripts/TemplateSync.js +109 -70
  275. package/src/security/CsrfTokenManager.js +1 -1
  276. package/src/security/Encryptor.js +1 -1
  277. package/src/security/Hash.d.ts +14 -0
  278. package/src/security/Hash.d.ts.map +1 -0
  279. package/src/security/Hash.js +81 -0
  280. package/src/security/StartupSecretValidation.d.ts +20 -0
  281. package/src/security/StartupSecretValidation.d.ts.map +1 -0
  282. package/src/security/StartupSecretValidation.js +61 -0
  283. package/src/security/UrlValidator.d.ts +0 -1
  284. package/src/security/UrlValidator.d.ts.map +1 -1
  285. package/src/security/UrlValidator.js +1 -2
  286. package/src/security/Xss.d.ts +14 -0
  287. package/src/security/Xss.d.ts.map +1 -0
  288. package/src/security/Xss.js +57 -0
  289. package/src/security/XssProtection.d.ts.map +1 -1
  290. package/src/security/XssProtection.js +155 -17
  291. package/src/templates/adapters/MySQLAdapter.ts.tpl +5 -0
  292. package/src/templates/adapters/PostgreSQLAdapter.ts.tpl +5 -0
  293. package/src/templates/adapters/SQLServerAdapter.ts.tpl +5 -0
  294. package/src/templates/adapters/SQLiteAdapter.ts.tpl +5 -0
  295. package/src/templates/features/Queue.ts.tpl +1 -29
  296. package/src/templates/project/basic/.env.example.tpl +48 -0
  297. package/src/templates/project/basic/.env.tpl +89 -94
  298. package/src/templates/project/basic/app/Toolkit/Broadcast/sendBroadcast.ts.tpl +7 -0
  299. package/src/templates/project/basic/app/Toolkit/Mail/sendWelcomeEmail.ts.tpl +30 -0
  300. package/src/templates/project/basic/app/Toolkit/Notification/sendSlackNotification.ts.tpl +10 -0
  301. package/src/templates/project/basic/app/Toolkit/Notification/sendSms.ts.tpl +13 -0
  302. package/src/templates/project/basic/config/FileLogWriter.ts.tpl +240 -0
  303. package/src/templates/project/basic/config/SecretsManager.ts.tpl +44 -21
  304. package/src/templates/project/basic/config/StartupConfigValidator.ts.tpl +151 -0
  305. package/src/templates/project/basic/config/app.ts.tpl +84 -15
  306. package/src/templates/project/basic/config/broadcast.ts.tpl +97 -0
  307. package/src/templates/project/basic/config/cache.ts.tpl +19 -23
  308. package/src/templates/project/basic/config/cloudflare.ts.tpl +57 -0
  309. package/src/templates/project/basic/config/env.ts.tpl +7 -1
  310. package/src/templates/project/basic/config/index.ts.tpl +3 -0
  311. package/src/templates/project/basic/config/logger.ts.tpl +301 -11
  312. package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +121 -0
  313. package/src/templates/project/basic/config/logging/KvLogger.ts.tpl +181 -0
  314. package/src/templates/project/basic/config/logging/SlackLogger.ts.tpl +156 -0
  315. package/src/templates/project/basic/config/mail.ts.tpl +141 -0
  316. package/src/templates/project/basic/config/middleware.ts.tpl +27 -0
  317. package/src/templates/project/basic/config/notification.ts.tpl +86 -0
  318. package/src/templates/project/basic/config/security.ts.tpl +4 -5
  319. package/src/templates/project/basic/config/startup.ts.tpl +27 -0
  320. package/src/templates/project/basic/config/storage.ts.tpl +77 -42
  321. package/src/templates/project/basic/database/migrations/index.ts.tpl +1 -1
  322. package/src/templates/project/basic/package.json.tpl +1 -1
  323. package/src/templates/project/basic/routes/api.ts.tpl +11 -37
  324. package/src/templates/project/basic/routes/broadcast.ts.tpl +32 -0
  325. package/src/templates/project/basic/routes/health.ts.tpl +134 -0
  326. package/src/templates/project/basic/routes/storage.ts.tpl +42 -0
  327. package/src/templates/project/basic/src/index.ts.tpl +38 -11
  328. package/src/templates/project/basic/template.json +3 -0
  329. package/src/toolkit/Secrets/EnvFile.d.ts +15 -0
  330. package/src/toolkit/Secrets/EnvFile.d.ts.map +1 -0
  331. package/src/toolkit/Secrets/EnvFile.js +63 -0
  332. package/src/toolkit/Secrets/Manifest.d.ts +24 -0
  333. package/src/toolkit/Secrets/Manifest.d.ts.map +1 -0
  334. package/src/toolkit/Secrets/Manifest.js +71 -0
  335. package/src/toolkit/Secrets/index.d.ts +42 -0
  336. package/src/toolkit/Secrets/index.d.ts.map +1 -0
  337. package/src/toolkit/Secrets/index.js +119 -0
  338. package/src/toolkit/Secrets/providers/AwsSecretsManager.d.ts +14 -0
  339. package/src/toolkit/Secrets/providers/AwsSecretsManager.d.ts.map +1 -0
  340. package/src/toolkit/Secrets/providers/AwsSecretsManager.js +131 -0
  341. package/src/toolkit/Secrets/providers/CloudflareKv.d.ts +9 -0
  342. package/src/toolkit/Secrets/providers/CloudflareKv.d.ts.map +1 -0
  343. package/src/toolkit/Secrets/providers/CloudflareKv.js +73 -0
  344. package/src/tools/broadcast/Broadcast.d.ts +7 -0
  345. package/src/tools/broadcast/Broadcast.d.ts.map +1 -0
  346. package/src/tools/broadcast/Broadcast.js +37 -0
  347. package/src/tools/broadcast/drivers/BaseDriver.d.ts +5 -0
  348. package/src/tools/broadcast/drivers/BaseDriver.d.ts.map +1 -0
  349. package/src/tools/broadcast/drivers/BaseDriver.js +8 -0
  350. package/src/tools/broadcast/drivers/InMemory.d.ts +18 -0
  351. package/src/tools/broadcast/drivers/InMemory.d.ts.map +1 -0
  352. package/src/tools/broadcast/drivers/InMemory.js +16 -0
  353. package/src/tools/broadcast/drivers/Pusher.d.ts +8 -0
  354. package/src/tools/broadcast/drivers/Pusher.d.ts.map +1 -0
  355. package/src/tools/broadcast/drivers/Pusher.js +75 -0
  356. package/src/tools/broadcast/drivers/Redis.d.ts +19 -0
  357. package/src/tools/broadcast/drivers/Redis.d.ts.map +1 -0
  358. package/src/tools/broadcast/drivers/Redis.js +73 -0
  359. package/src/tools/broadcast/drivers/RedisHttps.d.ts +14 -0
  360. package/src/tools/broadcast/drivers/RedisHttps.d.ts.map +1 -0
  361. package/src/tools/broadcast/drivers/RedisHttps.js +50 -0
  362. package/src/tools/broadcast/index.d.ts +7 -0
  363. package/src/tools/broadcast/index.d.ts.map +1 -0
  364. package/src/tools/broadcast/index.js +6 -0
  365. package/src/tools/http/Http.d.ts +49 -0
  366. package/src/tools/http/Http.d.ts.map +1 -0
  367. package/src/tools/http/Http.js +169 -0
  368. package/src/tools/http/HttpResponse.d.ts +32 -0
  369. package/src/tools/http/HttpResponse.d.ts.map +1 -0
  370. package/src/tools/http/HttpResponse.js +80 -0
  371. package/src/tools/http/index.d.ts +15 -0
  372. package/src/tools/http/index.d.ts.map +1 -0
  373. package/src/tools/http/index.js +9 -0
  374. package/src/tools/mail/Mail.d.ts +22 -0
  375. package/src/tools/mail/Mail.d.ts.map +1 -0
  376. package/src/tools/mail/Mail.js +105 -0
  377. package/src/tools/mail/attachments.d.ts +23 -0
  378. package/src/tools/mail/attachments.d.ts.map +1 -0
  379. package/src/tools/mail/attachments.js +26 -0
  380. package/src/tools/mail/drivers/BaseDriver.d.ts +5 -0
  381. package/src/tools/mail/drivers/BaseDriver.d.ts.map +1 -0
  382. package/src/tools/mail/drivers/BaseDriver.js +8 -0
  383. package/src/tools/mail/drivers/Mailgun.d.ts +31 -0
  384. package/src/tools/mail/drivers/Mailgun.d.ts.map +1 -0
  385. package/src/tools/mail/drivers/Mailgun.js +81 -0
  386. package/src/tools/mail/drivers/SendGrid.d.ts +29 -0
  387. package/src/tools/mail/drivers/SendGrid.d.ts.map +1 -0
  388. package/src/tools/mail/drivers/SendGrid.js +57 -0
  389. package/src/tools/mail/drivers/Ses.d.ts +24 -0
  390. package/src/tools/mail/drivers/Ses.d.ts.map +1 -0
  391. package/src/tools/mail/drivers/Ses.js +116 -0
  392. package/src/tools/mail/drivers/Smtp.d.ts +38 -0
  393. package/src/tools/mail/drivers/Smtp.d.ts.map +1 -0
  394. package/src/tools/mail/drivers/Smtp.js +327 -0
  395. package/src/tools/mail/templates/index.d.ts +27 -0
  396. package/src/tools/mail/templates/index.d.ts.map +1 -0
  397. package/src/tools/mail/templates/index.js +35 -0
  398. package/src/tools/mail/templates/markdown/index.d.ts +17 -0
  399. package/src/tools/mail/templates/markdown/index.d.ts.map +1 -0
  400. package/src/tools/mail/templates/markdown/index.js +49 -0
  401. package/src/tools/mail/templates/markdown/registry.d.ts +15 -0
  402. package/src/tools/mail/templates/markdown/registry.d.ts.map +1 -0
  403. package/src/tools/mail/templates/markdown/registry.js +34 -0
  404. package/src/tools/mail/templates/markdown/validator.d.ts +16 -0
  405. package/src/tools/mail/templates/markdown/validator.d.ts.map +1 -0
  406. package/src/tools/mail/templates/markdown/validator.js +24 -0
  407. package/src/tools/mail/testing.d.ts +41 -0
  408. package/src/tools/mail/testing.d.ts.map +1 -0
  409. package/src/tools/mail/testing.js +34 -0
  410. package/src/tools/notification/Driver.d.ts +11 -0
  411. package/src/tools/notification/Driver.d.ts.map +1 -0
  412. package/src/tools/notification/Driver.js +1 -0
  413. package/src/tools/notification/Notification.d.ts +11 -0
  414. package/src/tools/notification/Notification.d.ts.map +1 -0
  415. package/src/tools/notification/Notification.js +11 -0
  416. package/src/tools/notification/Registry.d.ts +10 -0
  417. package/src/tools/notification/Registry.d.ts.map +1 -0
  418. package/src/tools/notification/Registry.js +22 -0
  419. package/src/tools/notification/Service.d.ts +6 -0
  420. package/src/tools/notification/Service.d.ts.map +1 -0
  421. package/src/tools/notification/Service.js +18 -0
  422. package/src/tools/notification/config.d.ts +5 -0
  423. package/src/tools/notification/config.d.ts.map +1 -0
  424. package/src/tools/notification/config.js +5 -0
  425. package/src/tools/notification/drivers/BaseDriver.d.ts +5 -0
  426. package/src/tools/notification/drivers/BaseDriver.d.ts.map +1 -0
  427. package/src/tools/notification/drivers/BaseDriver.js +8 -0
  428. package/src/tools/notification/drivers/Console.d.ts +7 -0
  429. package/src/tools/notification/drivers/Console.d.ts.map +1 -0
  430. package/src/tools/notification/drivers/Console.js +13 -0
  431. package/src/tools/notification/drivers/Slack.d.ts +16 -0
  432. package/src/tools/notification/drivers/Slack.d.ts.map +1 -0
  433. package/src/tools/notification/drivers/Slack.js +24 -0
  434. package/src/tools/notification/drivers/Termii.d.ts +10 -0
  435. package/src/tools/notification/drivers/Termii.d.ts.map +1 -0
  436. package/src/tools/notification/drivers/Termii.js +47 -0
  437. package/src/tools/notification/drivers/Twilio.d.ts +21 -0
  438. package/src/tools/notification/drivers/Twilio.d.ts.map +1 -0
  439. package/src/tools/notification/drivers/Twilio.js +48 -0
  440. package/src/tools/notification/templates/markdown/index.d.ts +15 -0
  441. package/src/tools/notification/templates/markdown/index.d.ts.map +1 -0
  442. package/src/tools/notification/templates/markdown/index.js +38 -0
  443. package/src/tools/notification/templates/markdown/registry.d.ts +15 -0
  444. package/src/tools/notification/templates/markdown/registry.d.ts.map +1 -0
  445. package/src/tools/notification/templates/markdown/registry.js +36 -0
  446. package/src/tools/notification/testing.d.ts +19 -0
  447. package/src/tools/notification/testing.d.ts.map +1 -0
  448. package/src/tools/notification/testing.js +35 -0
  449. package/src/tools/notification/testingHelpers.d.ts +12 -0
  450. package/src/tools/notification/testingHelpers.d.ts.map +1 -0
  451. package/src/tools/notification/testingHelpers.js +32 -0
  452. package/src/tools/queue/Queue.d.ts +23 -0
  453. package/src/tools/queue/Queue.d.ts.map +1 -0
  454. package/src/tools/queue/Queue.js +38 -0
  455. package/src/tools/queue/drivers/InMemory.d.ts +10 -0
  456. package/src/tools/queue/drivers/InMemory.d.ts.map +1 -0
  457. package/src/tools/queue/drivers/InMemory.js +55 -0
  458. package/src/tools/queue/drivers/Redis.d.ts +10 -0
  459. package/src/tools/queue/drivers/Redis.d.ts.map +1 -0
  460. package/src/tools/queue/drivers/Redis.js +91 -0
  461. package/src/tools/storage/LocalSignedUrl.d.ts +12 -0
  462. package/src/tools/storage/LocalSignedUrl.d.ts.map +1 -0
  463. package/src/tools/storage/LocalSignedUrl.js +108 -0
  464. package/src/tools/storage/drivers/Gcs.d.ts +20 -0
  465. package/src/tools/storage/drivers/Gcs.d.ts.map +1 -0
  466. package/src/tools/storage/drivers/Gcs.js +152 -0
  467. package/src/tools/storage/drivers/Local.d.ts +18 -0
  468. package/src/tools/storage/drivers/Local.d.ts.map +1 -0
  469. package/src/tools/storage/drivers/Local.js +89 -0
  470. package/src/tools/storage/drivers/R2.d.ts +20 -0
  471. package/src/tools/storage/drivers/R2.d.ts.map +1 -0
  472. package/src/tools/storage/drivers/R2.js +73 -0
  473. package/src/tools/storage/drivers/S3.d.ts +26 -0
  474. package/src/tools/storage/drivers/S3.d.ts.map +1 -0
  475. package/src/tools/storage/drivers/S3.js +258 -0
  476. package/src/tools/storage/index.d.ts +24 -0
  477. package/src/tools/storage/index.d.ts.map +1 -0
  478. package/src/tools/storage/index.js +111 -0
  479. package/src/tools/storage/testing.d.ts +23 -0
  480. package/src/tools/storage/testing.d.ts.map +1 -0
  481. package/src/tools/storage/testing.js +52 -0
  482. package/src/tools/templates/MarkdownRenderer.d.ts +14 -0
  483. package/src/tools/templates/MarkdownRenderer.d.ts.map +1 -0
  484. package/src/tools/templates/MarkdownRenderer.js +300 -0
  485. package/src/tools/templates/index.d.ts +5 -0
  486. package/src/tools/templates/index.d.ts.map +1 -0
  487. package/src/tools/templates/index.js +4 -0
@@ -0,0 +1,13 @@
1
+ import { sendSms } from '@notification/drivers/Twilio';
2
+
3
+ export async function sendSmsNotification(
4
+ accountSid: string,
5
+ authToken: string,
6
+ from: string,
7
+ to: string,
8
+ body: string
9
+ ): Promise<void> {
10
+ await sendSms({ accountSid, authToken, from }, { to, body });
11
+ }
12
+
13
+ export default Object.freeze({ sendSmsNotification });
@@ -0,0 +1,240 @@
1
+ /**
2
+ * FileLogWriter (Node.js only)
3
+ *
4
+ * Provides best-effort file logging with daily + size-based rotation.
5
+ * This module imports Node built-ins and should be loaded only in Node environments.
6
+ */
7
+
8
+ import { ensureDirSafe } from '@common/index';
9
+ import { Env } from '@config/env';
10
+ import * as fs from '@node-singletons/fs';
11
+ import * as path from '@node-singletons/path';
12
+
13
+ const getCwdSafe = (): string => {
14
+ try {
15
+ if (typeof process === 'undefined' || typeof process.cwd !== 'function') return '';
16
+ return process.cwd();
17
+ } catch {
18
+ return '';
19
+ }
20
+ };
21
+
22
+ const getDateStr = (d: Date): string => d.toISOString().slice(0, 10);
23
+
24
+ const isAppLogFile = (fileName: string): boolean =>
25
+ fileName.startsWith('app-') && fileName.endsWith('.log');
26
+
27
+ const parseDateFromLogFilename = (fileName: string): number | null => {
28
+ const match = /^app-(\d{4}-\d{2}-\d{2})(?:-\d+)?\.log$/.exec(fileName);
29
+ if (match?.[1] === undefined) return null;
30
+
31
+ const parsed = Date.parse(`${match[1]}T00:00:00.000Z`);
32
+ return Number.isNaN(parsed) ? null : parsed;
33
+ };
34
+
35
+ const isOlderThanCutoffByMtime = (fullPath: string, cutoff: number): boolean => {
36
+ try {
37
+ const stat = fs.statSync(fullPath);
38
+ return stat.mtime.getTime() < cutoff;
39
+ } catch {
40
+ return false;
41
+ }
42
+ };
43
+
44
+ const safeUnlink = (fullPath: string): void => {
45
+ try {
46
+ fs.unlinkSync(fullPath);
47
+ } catch {
48
+ // best-effort
49
+ }
50
+ };
51
+
52
+ const readDirSafe = (dirPath: string): string[] => {
53
+ try {
54
+ return fs.readdirSync(dirPath);
55
+ } catch {
56
+ return [];
57
+ }
58
+ };
59
+
60
+ const shouldDeleteLogFile = (fileName: string, fullPath: string, cutoff: number): boolean => {
61
+ const parsed = parseDateFromLogFilename(fileName);
62
+ if (parsed !== null) return parsed < cutoff;
63
+
64
+ return isOlderThanCutoffByMtime(fullPath, cutoff);
65
+ };
66
+
67
+ const cleanupOldLogs = (logsDir: string, keepDays: number): void => {
68
+ if (keepDays <= 0) return;
69
+
70
+ const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1000;
71
+ const files = readDirSafe(logsDir);
72
+ if (files.length === 0) return;
73
+
74
+ for (const fileName of files) {
75
+ if (!isAppLogFile(fileName)) continue;
76
+
77
+ const fullPath = path.join(logsDir, fileName);
78
+ if (!shouldDeleteLogFile(fileName, fullPath, cutoff)) continue;
79
+
80
+ safeUnlink(fullPath);
81
+ }
82
+ };
83
+
84
+ type CleanOnceOptions = {
85
+ logsDir?: string;
86
+ keepDays?: number;
87
+ maxTotalSize?: number;
88
+ keepFiles?: number;
89
+ };
90
+
91
+ const listAppLogFiles = (
92
+ logsDir: string,
93
+ order: 'newest-first' | 'oldest-first'
94
+ ): Array<{ name: string; path: string }> => {
95
+ const files = readDirSafe(logsDir)
96
+ .filter((f) => isAppLogFile(f))
97
+ .map((f) => ({ name: f, path: path.join(logsDir, f) }));
98
+
99
+ return files.sort((a, b) => {
100
+ if (a.name === b.name) return 0;
101
+ const newerFirst = a.name < b.name ? 1 : -1;
102
+ return order === 'newest-first' ? newerFirst : -newerFirst;
103
+ });
104
+ };
105
+
106
+ const enforceKeepFilesPolicy = (
107
+ filesNewestFirst: Array<{ name: string; path: string }>,
108
+ keepFiles: number | undefined,
109
+ deleted: string[]
110
+ ): void => {
111
+ if (typeof keepFiles !== 'number' || keepFiles < 0) return;
112
+ if (filesNewestFirst.length <= keepFiles) return;
113
+
114
+ const toDelete = filesNewestFirst.slice(keepFiles);
115
+ for (const f of toDelete) {
116
+ safeUnlink(f.path);
117
+ deleted.push(f.path);
118
+ }
119
+ };
120
+
121
+ const getFileSizesTotal = (
122
+ filesOldestFirst: Array<{ name: string; path: string }>
123
+ ): { total: number; sizes: Array<{ path: string; size: number }> } => {
124
+ let total = 0;
125
+ const sizes: Array<{ path: string; size: number }> = [];
126
+
127
+ for (const file of filesOldestFirst) {
128
+ try {
129
+ const stat = fs.statSync(file.path);
130
+ sizes.push({ path: file.path, size: stat.size });
131
+ total += stat.size;
132
+ } catch {
133
+ // ignore
134
+ }
135
+ }
136
+
137
+ return { total, sizes };
138
+ };
139
+
140
+ const deleteOldestUntilWithinLimit = (
141
+ sizesOldestFirst: Array<{ path: string; size: number }>,
142
+ maxTotalSize: number,
143
+ deleted: string[],
144
+ initialTotal: number
145
+ ): void => {
146
+ let total = initialTotal;
147
+
148
+ let idx = 0;
149
+ while (total > maxTotalSize && idx < sizesOldestFirst.length) {
150
+ const del = sizesOldestFirst[idx];
151
+ safeUnlink(del.path);
152
+ deleted.push(del.path);
153
+ total -= del.size;
154
+ idx++;
155
+ }
156
+ };
157
+
158
+ const enforceMaxTotalSizePolicy = (
159
+ logsDir: string,
160
+ maxTotalSize: number | undefined,
161
+ deleted: string[]
162
+ ): void => {
163
+ if (typeof maxTotalSize !== 'number' || maxTotalSize <= 0) return;
164
+
165
+ const remainingOldestFirst = listAppLogFiles(logsDir, 'oldest-first');
166
+ const { total, sizes } = getFileSizesTotal(remainingOldestFirst);
167
+ deleteOldestUntilWithinLimit(sizes, maxTotalSize, deleted, total);
168
+ };
169
+
170
+ /**
171
+ * Clean log files with additional retention policies.
172
+ * Returns an array of deleted file paths for auditing/tests.
173
+ */
174
+ export const cleanOnce = (options?: CleanOnceOptions): string[] => {
175
+ const cwd = getCwdSafe();
176
+ if (cwd === '') return [];
177
+
178
+ const logsDir = options?.logsDir ?? path.join(cwd, 'logs');
179
+ const keepDays = options?.keepDays ?? Env.LOG_ROTATION_DAYS;
180
+ const maxTotalSize = options?.maxTotalSize ?? Env.getInt('LOG_MAX_TOTAL_SIZE', 0);
181
+ const keepFiles = options?.keepFiles ?? Env.getInt('LOG_KEEP_FILES', 0);
182
+
183
+ // Step 1: delete by age
184
+ cleanupOldLogs(logsDir, keepDays);
185
+
186
+ const deleted: string[] = [];
187
+
188
+ // Step 2: enforce keepFiles (keep newest N files)
189
+ const filesNewestFirst = listAppLogFiles(logsDir, 'newest-first');
190
+ enforceKeepFilesPolicy(filesNewestFirst, keepFiles, deleted);
191
+
192
+ // Step 3: enforce max total size
193
+ enforceMaxTotalSizePolicy(logsDir, maxTotalSize, deleted);
194
+
195
+ return deleted;
196
+ };
197
+
198
+ const rotateIfNeeded = (logFile: string, maxSizeBytes: number): void => {
199
+ if (maxSizeBytes <= 0) return;
200
+
201
+ try {
202
+ if (!fs.existsSync(logFile)) return;
203
+
204
+ const stat = fs.statSync(logFile);
205
+ if (stat.size <= maxSizeBytes) return;
206
+
207
+ const ext = '.log';
208
+ const base = logFile.endsWith(ext) ? logFile.slice(0, -ext.length) : logFile;
209
+ const rotated = `${base}-${Date.now()}${ext}`;
210
+ fs.renameSync(logFile, rotated);
211
+ } catch {
212
+ // best-effort
213
+ }
214
+ };
215
+
216
+ export const FileLogWriter = Object.freeze({
217
+ write(line: string): void {
218
+ const cwd = getCwdSafe();
219
+ if (cwd === '') return;
220
+
221
+ const logsDir = path.join(cwd, 'logs');
222
+ ensureDirSafe(logsDir);
223
+
224
+ const dateStr = getDateStr(new Date());
225
+ const logFile = path.join(logsDir, `app-${dateStr}.log`);
226
+
227
+ rotateIfNeeded(logFile, Env.LOG_ROTATION_SIZE);
228
+
229
+ try {
230
+ fs.appendFileSync(logFile, `${line}\n`);
231
+ } catch {
232
+ // best-effort
233
+ return;
234
+ }
235
+
236
+ cleanupOldLogs(logsDir, Env.LOG_ROTATION_DAYS);
237
+ },
238
+ });
239
+
240
+ export default FileLogWriter;
@@ -38,6 +38,25 @@ interface SecretsManagerInstance {
38
38
  clearCache(key?: string): void;
39
39
  }
40
40
 
41
+ function pruneCache(
42
+ cache: Map<string, { value: string; expiresAt: number }>,
43
+ maxEntries: number
44
+ ): void {
45
+ if (cache.size <= maxEntries) return;
46
+
47
+ const now = Date.now();
48
+ for (const [key, entry] of cache.entries()) {
49
+ if (entry.expiresAt <= now) cache.delete(key);
50
+ }
51
+
52
+ // If still large, drop oldest entries (Map preserves insertion order)
53
+ while (cache.size > maxEntries) {
54
+ const next = cache.keys().next();
55
+ if (next.done === true) break;
56
+ cache.delete(next.value);
57
+ }
58
+ }
59
+
41
60
  /**
42
61
  * Get secret value from appropriate backend
43
62
  */
@@ -53,6 +72,9 @@ async function runGetSecret(
53
72
  return cached.value;
54
73
  }
55
74
 
75
+ // Opportunistic cleanup if cache has grown
76
+ pruneCache(cache, 500);
77
+
56
78
  let value: string;
57
79
 
58
80
  switch (config.platform) {
@@ -77,6 +99,8 @@ async function runGetSecret(
77
99
  expiresAt: Date.now() + ttl,
78
100
  });
79
101
 
102
+ pruneCache(cache, 500);
103
+
80
104
  return value;
81
105
  }
82
106
 
@@ -169,14 +193,13 @@ const SecretsManagerImpl = {
169
193
  /**
170
194
  * Rotate secret (trigger new secret generation)
171
195
  */
196
+ // eslint-disable-next-line @typescript-eslint/require-await
172
197
  async rotateSecret(_key: string): Promise<void> {
173
198
  if (config.platform === 'aws') {
174
199
  // AWS Secrets Manager supports automatic rotation
175
- return Promise.reject(ErrorFactory.createConfigError('Secret rotation not implemented'));
200
+ throw ErrorFactory.createConfigError('Secret rotation not implemented');
176
201
  }
177
- return Promise.reject(
178
- ErrorFactory.createConfigError('Secret rotation not supported on this platform')
179
- );
202
+ throw ErrorFactory.createConfigError('Secret rotation not supported on this platform');
180
203
  },
181
204
 
182
205
  /**
@@ -191,7 +214,7 @@ const SecretsManagerImpl = {
191
214
  case 'deno':
192
215
  case 'local':
193
216
  default:
194
- return Promise.resolve([]);
217
+ return [];
195
218
  }
196
219
  },
197
220
 
@@ -212,41 +235,39 @@ const SecretsManagerImpl = {
212
235
  /**
213
236
  * AWS Secrets Manager integration
214
237
  */
238
+ // eslint-disable-next-line @typescript-eslint/require-await
215
239
  async function getFromAWSSecretsManager(key: string): Promise<string> {
216
240
  try {
217
241
  Logger.debug(`[AWS] Getting secret: ${key}`);
218
242
  throw ErrorFactory.createConfigError('AWS SDK not available in core - use wrapper module');
219
243
  } catch (error) {
220
- return Promise.reject(
221
- ErrorFactory.createTryCatchError(
222
- `Failed to retrieve secret from AWS: ${(error as Error).message}`,
223
- error
224
- )
244
+ throw ErrorFactory.createTryCatchError(
245
+ `Failed to retrieve secret from AWS: ${(error as Error).message}`,
246
+ error
225
247
  );
226
248
  }
227
249
  }
228
250
 
251
+ // eslint-disable-next-line @typescript-eslint/require-await
229
252
  async function setInAWSSecretsManager(
230
253
  key: string,
231
254
  _value: string,
232
255
  _options?: SetSecretOptions
233
256
  ): Promise<void> {
234
257
  Logger.info(`[AWS] Setting secret: ${key}`);
235
- return Promise.reject(
236
- ErrorFactory.createConfigError('AWS SDK not available in core - use wrapper module')
237
- );
258
+ throw ErrorFactory.createConfigError('AWS SDK not available in core - use wrapper module');
238
259
  }
239
260
 
261
+ // eslint-disable-next-line @typescript-eslint/require-await
240
262
  async function deleteFromAWSSecretsManager(key: string): Promise<void> {
241
263
  Logger.info(`[AWS] Deleting secret: ${key}`);
242
- return Promise.reject(
243
- ErrorFactory.createConfigError('AWS SDK not available in core - use wrapper module')
244
- );
264
+ throw ErrorFactory.createConfigError('AWS SDK not available in core - use wrapper module');
245
265
  }
246
266
 
267
+ // eslint-disable-next-line @typescript-eslint/require-await
247
268
  async function listFromAWSSecretsManager(pattern?: string): Promise<string[]> {
248
269
  Logger.info(`[AWS] Listing secrets with pattern: ${pattern ?? '*'}`);
249
- return Promise.resolve([]);
270
+ return [];
250
271
  }
251
272
 
252
273
  /**
@@ -294,25 +315,27 @@ async function listFromCloudflareKV(config: SecretConfig, pattern?: string): Pro
294
315
  /**
295
316
  * Deno environment integration
296
317
  */
318
+ // eslint-disable-next-line @typescript-eslint/require-await
297
319
  async function getFromDenoEnv(key: string): Promise<string> {
298
320
  const value = (
299
321
  globalThis as unknown as Record<string, { env?: { get?: (key: string) => string } }>
300
322
  )['Deno']?.env?.get?.(key);
301
323
  if (value === undefined || value === null || value === '') {
302
- return Promise.reject(ErrorFactory.createNotFoundError(`Secret not found: ${key}`, { key }));
324
+ throw ErrorFactory.createNotFoundError(`Secret not found: ${key}`, { key });
303
325
  }
304
- return Promise.resolve(value);
326
+ return value;
305
327
  }
306
328
 
307
329
  /**
308
330
  * Local environment variables (Node.js)
309
331
  */
332
+ // eslint-disable-next-line @typescript-eslint/require-await
310
333
  async function getFromEnv(key: string): Promise<string> {
311
334
  const value = process.env[key];
312
335
  if (value === undefined || value === null || value === '') {
313
- return Promise.reject(ErrorFactory.createNotFoundError(`Secret not found: ${key}`, { key }));
336
+ throw ErrorFactory.createNotFoundError(`Secret not found: ${key}`, { key });
314
337
  }
315
- return Promise.resolve(value);
338
+ return value;
316
339
  }
317
340
 
318
341
  /**
@@ -0,0 +1,151 @@
1
+ import { appConfig } from '@config/app';
2
+ import { ErrorFactory } from '@exceptions/ZintrustError';
3
+
4
+ export type StartupConfigValidationError = {
5
+ key: string;
6
+ value: unknown;
7
+ message: string;
8
+ };
9
+
10
+ export type StartupConfigValidationResult = {
11
+ valid: boolean;
12
+ errors: StartupConfigValidationError[];
13
+ };
14
+
15
+ const isSensitiveKey = (key: string): boolean => {
16
+ const normalized = key.toLowerCase();
17
+ return (
18
+ normalized.includes('password') ||
19
+ normalized.includes('secret') ||
20
+ normalized.includes('token') ||
21
+ normalized.includes('key') ||
22
+ normalized.includes('authorization')
23
+ );
24
+ };
25
+
26
+ const redactValue = (key: string, value: unknown): unknown => {
27
+ return isSensitiveKey(key) ? '<redacted>' : value;
28
+ };
29
+
30
+ const pushError = (
31
+ errors: StartupConfigValidationError[],
32
+ key: string,
33
+ value: unknown,
34
+ message: string
35
+ ): void => {
36
+ errors.push({ key, value: redactValue(key, value), message });
37
+ };
38
+
39
+ const validateEnum = (
40
+ errors: StartupConfigValidationError[],
41
+ key: string,
42
+ value: string,
43
+ allowed: readonly string[]
44
+ ): void => {
45
+ if (!allowed.includes(value)) {
46
+ pushError(errors, key, value, `${key} must be one of: ${allowed.join(', ')}`);
47
+ }
48
+ };
49
+
50
+ const validateIntRange = (
51
+ errors: StartupConfigValidationError[],
52
+ key: string,
53
+ value: number,
54
+ min: number,
55
+ max: number
56
+ ): void => {
57
+ if (Number.isNaN(value)) {
58
+ pushError(errors, key, value, `${key} must be a valid integer`);
59
+ return;
60
+ }
61
+
62
+ if (value < min || value > max) {
63
+ pushError(errors, key, value, `${key} must be between ${min} and ${max}`);
64
+ }
65
+ };
66
+
67
+ const validatePositiveInt = (
68
+ errors: StartupConfigValidationError[],
69
+ key: string,
70
+ value: number
71
+ ): void => {
72
+ if (Number.isNaN(value)) {
73
+ pushError(errors, key, value, `${key} must be a valid integer`);
74
+ return;
75
+ }
76
+
77
+ if (value <= 0) {
78
+ pushError(errors, key, value, `${key} must be greater than 0`);
79
+ }
80
+ };
81
+
82
+ type ProcessLike = {
83
+ env?: Record<string, string | undefined>;
84
+ };
85
+
86
+ const getProcessLike = (): ProcessLike | undefined => {
87
+ return typeof process === 'undefined' ? undefined : (process as unknown as ProcessLike);
88
+ };
89
+
90
+ const getEnvString = (key: string, defaultValue: string): string => {
91
+ const proc = getProcessLike();
92
+ const env = proc?.env ?? {};
93
+ return env[key] ?? defaultValue;
94
+ };
95
+
96
+ const getEnvInt = (key: string, defaultValue: number): number => {
97
+ const raw = getEnvString(key, String(defaultValue));
98
+ return Number.parseInt(raw, 10);
99
+ };
100
+
101
+ export const StartupConfigValidator = Object.freeze({
102
+ validate(): StartupConfigValidationResult {
103
+ const errors: StartupConfigValidationError[] = [];
104
+
105
+ const nodeEnv = getEnvString('NODE_ENV', 'development');
106
+ validateEnum(errors, 'NODE_ENV', nodeEnv, ['development', 'production', 'testing', 'test']);
107
+
108
+ const appPort = getEnvInt('APP_PORT', 3000);
109
+ validateIntRange(errors, 'APP_PORT', appPort, 1, 65535);
110
+
111
+ const logFormat = getEnvString('LOG_FORMAT', 'text');
112
+ validateEnum(errors, 'LOG_FORMAT', logFormat, ['text', 'json']);
113
+
114
+ const logLevel = getEnvString('LOG_LEVEL', 'debug');
115
+ validateEnum(errors, 'LOG_LEVEL', logLevel, ['debug', 'info', 'warn', 'error']);
116
+
117
+ const logRotationSize = getEnvInt('LOG_ROTATION_SIZE', 10485760);
118
+ validatePositiveInt(errors, 'LOG_ROTATION_SIZE', logRotationSize);
119
+
120
+ const logRotationDays = getEnvInt('LOG_ROTATION_DAYS', 7);
121
+ validatePositiveInt(errors, 'LOG_ROTATION_DAYS', logRotationDays);
122
+
123
+ const startupHealthTimeoutMs = getEnvInt('STARTUP_HEALTH_TIMEOUT_MS', 2500);
124
+ validatePositiveInt(errors, 'STARTUP_HEALTH_TIMEOUT_MS', startupHealthTimeoutMs);
125
+
126
+ if (appConfig.isProduction()) {
127
+ const appKey = getEnvString('APP_KEY', '');
128
+ if (appKey.trim().length < 16) {
129
+ pushError(
130
+ errors,
131
+ 'APP_KEY',
132
+ appKey,
133
+ 'APP_KEY must be set and at least 16 characters in production'
134
+ );
135
+ }
136
+ }
137
+
138
+ return { valid: errors.length === 0, errors };
139
+ },
140
+
141
+ assertValid(): void {
142
+ const result = StartupConfigValidator.validate();
143
+ if (result.valid) return;
144
+
145
+ throw ErrorFactory.createConfigError('Invalid startup configuration', {
146
+ errors: result.errors,
147
+ });
148
+ },
149
+ });
150
+
151
+ export default StartupConfigValidator;