@zintrust/core 0.1.0 → 0.1.2

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 (518) hide show
  1. package/README.md +214 -0
  2. package/bin/zintrust.d.ts.map +1 -1
  3. package/bin/zintrust.js +18 -1
  4. package/package.json +4 -34
  5. package/public/index.html +535 -0
  6. package/src/boot/Application.d.ts.map +1 -1
  7. package/src/boot/Application.js +46 -3
  8. package/src/boot/Server.d.ts.map +1 -1
  9. package/src/boot/Server.js +3 -4
  10. package/src/boot/bootstrap.js +77 -6
  11. package/src/builder/BundleOptimizer.d.ts.map +1 -1
  12. package/src/builder/BundleOptimizer.js +25 -29
  13. package/src/cache/Cache.d.ts.map +1 -1
  14. package/src/cache/Cache.js +4 -2
  15. package/src/cache/drivers/KVDriver.d.ts.map +1 -1
  16. package/src/cache/drivers/KVDriver.js +8 -7
  17. package/src/cache/drivers/MemoryDriver.d.ts.map +1 -1
  18. package/src/cache/drivers/MemoryDriver.js +5 -0
  19. package/src/cache/drivers/RedisDriver.js +1 -1
  20. package/src/cli/BaseCommand.d.ts +2 -2
  21. package/src/cli/BaseCommand.d.ts.map +1 -1
  22. package/src/cli/BaseCommand.js +2 -1
  23. package/src/cli/CLI.d.ts.map +1 -1
  24. package/src/cli/CLI.js +22 -18
  25. package/src/cli/ErrorHandler.d.ts.map +1 -1
  26. package/src/cli/ErrorHandler.js +2 -4
  27. package/src/cli/commands/AddCommand.d.ts +81 -0
  28. package/src/cli/commands/AddCommand.d.ts.map +1 -1
  29. package/src/cli/commands/AddCommand.js +24 -5
  30. package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
  31. package/src/cli/commands/ConfigCommand.js +59 -25
  32. package/src/cli/commands/D1MigrateCommand.d.ts +4 -0
  33. package/src/cli/commands/D1MigrateCommand.d.ts.map +1 -1
  34. package/src/cli/commands/D1MigrateCommand.js +6 -4
  35. package/src/cli/commands/FixCommand.d.ts.map +1 -1
  36. package/src/cli/commands/FixCommand.js +3 -15
  37. package/src/cli/commands/LogsCleanupCommand.d.ts +6 -0
  38. package/src/cli/commands/LogsCleanupCommand.d.ts.map +1 -0
  39. package/src/cli/commands/LogsCleanupCommand.js +20 -0
  40. package/src/cli/commands/LogsCommand.d.ts.map +1 -1
  41. package/src/cli/commands/LogsCommand.js +4 -6
  42. package/src/cli/commands/MakeMailTemplateCommand.d.ts +10 -0
  43. package/src/cli/commands/MakeMailTemplateCommand.d.ts.map +1 -0
  44. package/src/cli/commands/MakeMailTemplateCommand.js +74 -0
  45. package/src/cli/commands/MakeNotificationTemplateCommand.d.ts +10 -0
  46. package/src/cli/commands/MakeNotificationTemplateCommand.d.ts.map +1 -0
  47. package/src/cli/commands/MakeNotificationTemplateCommand.js +113 -0
  48. package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
  49. package/src/cli/commands/MigrateCommand.js +3 -3
  50. package/src/cli/commands/NewCommand.d.ts +4 -0
  51. package/src/cli/commands/NewCommand.d.ts.map +1 -1
  52. package/src/cli/commands/NewCommand.js +34 -19
  53. package/src/cli/commands/PluginCommand.d.ts.map +1 -1
  54. package/src/cli/commands/PluginCommand.js +8 -4
  55. package/src/cli/commands/PrepareCommand.d.ts.map +1 -1
  56. package/src/cli/commands/PrepareCommand.js +1 -1
  57. package/src/cli/commands/QACommand.d.ts.map +1 -1
  58. package/src/cli/commands/QACommand.js +16 -26
  59. package/src/cli/commands/SecretsCommand.d.ts +16 -0
  60. package/src/cli/commands/SecretsCommand.d.ts.map +1 -0
  61. package/src/cli/commands/SecretsCommand.js +91 -0
  62. package/src/cli/commands/StartCommand.d.ts.map +1 -1
  63. package/src/cli/commands/StartCommand.js +2 -2
  64. package/src/cli/commands/TemplatesCommand.d.ts +3 -0
  65. package/src/cli/commands/TemplatesCommand.d.ts.map +1 -0
  66. package/src/cli/commands/TemplatesCommand.js +65 -0
  67. package/src/cli/commands/index.d.ts +5 -0
  68. package/src/cli/commands/index.d.ts.map +1 -1
  69. package/src/cli/commands/index.js +5 -0
  70. package/src/cli/config/ConfigManager.js +1 -1
  71. package/src/cli/index.d.ts +2 -1
  72. package/src/cli/index.d.ts.map +1 -1
  73. package/src/cli/index.js +2 -1
  74. package/src/cli/scaffolding/ControllerGenerator.d.ts.map +1 -1
  75. package/src/cli/scaffolding/ControllerGenerator.js +11 -10
  76. package/src/cli/scaffolding/FeatureScaffolder.js +4 -4
  77. package/src/cli/scaffolding/FileGenerator.js +1 -1
  78. package/src/cli/scaffolding/MigrationGenerator.d.ts.map +1 -1
  79. package/src/cli/scaffolding/MigrationGenerator.js +10 -9
  80. package/src/cli/scaffolding/ModelGenerator.d.ts.map +1 -1
  81. package/src/cli/scaffolding/ModelGenerator.js +11 -10
  82. package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
  83. package/src/cli/scaffolding/ProjectScaffolder.js +61 -11
  84. package/src/cli/scaffolding/ResponseFactoryGenerator.d.ts.map +1 -1
  85. package/src/cli/scaffolding/ResponseFactoryGenerator.js +2 -1
  86. package/src/cli/scaffolding/RouteGenerator.d.ts.map +1 -1
  87. package/src/cli/scaffolding/RouteGenerator.js +15 -14
  88. package/src/cli/scaffolding/SeederGenerator.js +1 -1
  89. package/src/cli/scaffolding/ServiceIntegrationTestGenerator.d.ts.map +1 -1
  90. package/src/cli/scaffolding/ServiceIntegrationTestGenerator.js +7 -6
  91. package/src/cli/scaffolding/ServiceRequestFactoryGenerator.d.ts +1 -1
  92. package/src/cli/scaffolding/ServiceRequestFactoryGenerator.d.ts.map +1 -1
  93. package/src/cli/scaffolding/ServiceRequestFactoryGenerator.js +2 -2
  94. package/src/cli/scaffolding/ServiceScaffolder.d.ts.map +1 -1
  95. package/src/cli/scaffolding/ServiceScaffolder.js +13 -12
  96. package/src/cli/scaffolding/TemplateEngine.d.ts +10 -3
  97. package/src/cli/scaffolding/TemplateEngine.d.ts.map +1 -1
  98. package/src/cli/scaffolding/TemplateEngine.js +15 -285
  99. package/src/cli/scaffolding/TemplateGenerator.d.ts +40 -0
  100. package/src/cli/scaffolding/TemplateGenerator.d.ts.map +1 -0
  101. package/src/cli/scaffolding/TemplateGenerator.js +172 -0
  102. package/src/cli/scaffolding/index.d.ts +1 -0
  103. package/src/cli/scaffolding/index.d.ts.map +1 -1
  104. package/src/cli/scaffolding/index.js +1 -0
  105. package/src/cli/utils/spawn.js +1 -1
  106. package/src/common/AwsSigV4.d.ts +41 -0
  107. package/src/common/AwsSigV4.d.ts.map +1 -0
  108. package/src/common/AwsSigV4.js +69 -0
  109. package/src/common/index.d.ts +39 -0
  110. package/src/common/index.d.ts.map +1 -1
  111. package/src/common/index.js +101 -8
  112. package/src/common/uuid.d.ts +3 -0
  113. package/src/common/uuid.d.ts.map +1 -0
  114. package/src/common/uuid.js +30 -0
  115. package/src/config/FileLogWriter.d.ts +22 -0
  116. package/src/config/FileLogWriter.d.ts.map +1 -0
  117. package/src/config/FileLogWriter.js +192 -0
  118. package/src/config/SecretsManager.d.ts.map +1 -1
  119. package/src/config/SecretsManager.js +26 -0
  120. package/src/config/StartupConfigValidator.d.ts +15 -0
  121. package/src/config/StartupConfigValidator.d.ts.map +1 -0
  122. package/src/config/StartupConfigValidator.js +86 -0
  123. package/src/config/app.d.ts +2 -1
  124. package/src/config/app.d.ts.map +1 -1
  125. package/src/config/app.js +65 -15
  126. package/src/config/broadcast.d.ts +47 -0
  127. package/src/config/broadcast.d.ts.map +1 -0
  128. package/src/config/broadcast.js +54 -0
  129. package/src/config/cache.d.ts +13 -17
  130. package/src/config/cache.d.ts.map +1 -1
  131. package/src/config/cache.js +9 -11
  132. package/src/config/cloudflare.d.ts +26 -0
  133. package/src/config/cloudflare.d.ts.map +1 -0
  134. package/src/config/cloudflare.js +38 -0
  135. package/src/config/env.d.ts +6 -0
  136. package/src/config/env.d.ts.map +1 -1
  137. package/src/config/env.js +6 -0
  138. package/src/config/index.d.ts +52 -28
  139. package/src/config/index.d.ts.map +1 -1
  140. package/src/config/index.js +3 -0
  141. package/src/config/logger.d.ts +2 -0
  142. package/src/config/logger.d.ts.map +1 -1
  143. package/src/config/logger.js +270 -11
  144. package/src/config/logging/HttpLogger.d.ts +23 -0
  145. package/src/config/logging/HttpLogger.d.ts.map +1 -0
  146. package/src/config/logging/HttpLogger.js +93 -0
  147. package/src/config/logging/KvLogger.d.ts +22 -0
  148. package/src/config/logging/KvLogger.d.ts.map +1 -0
  149. package/src/config/logging/KvLogger.js +143 -0
  150. package/src/config/logging/SlackLogger.d.ts +23 -0
  151. package/src/config/logging/SlackLogger.d.ts.map +1 -0
  152. package/src/config/logging/SlackLogger.js +119 -0
  153. package/src/config/mail.d.ts +81 -0
  154. package/src/config/mail.d.ts.map +1 -0
  155. package/src/config/mail.js +73 -0
  156. package/src/config/middleware.d.ts +8 -0
  157. package/src/config/middleware.d.ts.map +1 -0
  158. package/src/config/middleware.js +18 -0
  159. package/src/config/notification.d.ts +62 -0
  160. package/src/config/notification.d.ts.map +1 -0
  161. package/src/config/notification.js +43 -0
  162. package/src/config/security.d.ts.map +1 -1
  163. package/src/config/security.js +2 -2
  164. package/src/config/startup.d.ts +23 -0
  165. package/src/config/startup.d.ts.map +1 -0
  166. package/src/config/startup.js +15 -0
  167. package/src/config/storage.d.ts +21 -35
  168. package/src/config/storage.d.ts.map +1 -1
  169. package/src/config/storage.js +57 -37
  170. package/src/database/migrations/index.d.ts +1 -1
  171. package/src/database/migrations/index.d.ts.map +1 -1
  172. package/src/database/migrations/index.js +2 -1
  173. package/src/features/Queue.js +1 -25
  174. package/src/functions/lambda.d.ts.map +1 -1
  175. package/src/functions/lambda.js +6 -1
  176. package/src/health/RuntimeHealthProbes.d.ts +13 -0
  177. package/src/health/RuntimeHealthProbes.d.ts.map +1 -0
  178. package/src/health/RuntimeHealthProbes.js +62 -0
  179. package/src/health/StartupHealthChecks.d.ts +26 -0
  180. package/src/health/StartupHealthChecks.d.ts.map +1 -0
  181. package/src/health/StartupHealthChecks.js +124 -0
  182. package/src/http/ErrorResponse.d.ts +28 -0
  183. package/src/http/ErrorResponse.d.ts.map +1 -0
  184. package/src/http/ErrorResponse.js +42 -0
  185. package/src/http/Kernel.d.ts +5 -0
  186. package/src/http/Kernel.d.ts.map +1 -1
  187. package/src/http/Kernel.js +96 -30
  188. package/src/http/Request.d.ts +1 -1
  189. package/src/http/Request.d.ts.map +1 -1
  190. package/src/http/RequestContext.d.ts +20 -0
  191. package/src/http/RequestContext.d.ts.map +1 -0
  192. package/src/http/RequestContext.js +77 -0
  193. package/src/index.d.ts +9 -1
  194. package/src/index.d.ts.map +1 -1
  195. package/src/index.js +8 -2
  196. package/src/microservices/MicroserviceBootstrap.d.ts.map +1 -1
  197. package/src/microservices/MicroserviceBootstrap.js +6 -5
  198. package/src/microservices/MicroserviceManager.d.ts.map +1 -1
  199. package/src/microservices/MicroserviceManager.js +7 -5
  200. package/src/microservices/PostgresAdapter.d.ts.map +1 -1
  201. package/src/microservices/PostgresAdapter.js +7 -4
  202. package/src/microservices/ServiceBundler.d.ts.map +1 -1
  203. package/src/microservices/ServiceBundler.js +3 -1
  204. package/src/microservices/ServiceHealthMonitor.d.ts.map +1 -1
  205. package/src/microservices/ServiceHealthMonitor.js +7 -3
  206. package/src/middleware/CsrfMiddleware.d.ts.map +1 -1
  207. package/src/middleware/CsrfMiddleware.js +2 -19
  208. package/src/middleware/ErrorHandlerMiddleware.d.ts +6 -0
  209. package/src/middleware/ErrorHandlerMiddleware.d.ts.map +1 -0
  210. package/src/middleware/ErrorHandlerMiddleware.js +33 -0
  211. package/src/middleware/LoggingMiddleware.d.ts +9 -0
  212. package/src/middleware/LoggingMiddleware.d.ts.map +1 -0
  213. package/src/middleware/LoggingMiddleware.js +36 -0
  214. package/src/middleware/index.d.ts +2 -0
  215. package/src/middleware/index.d.ts.map +1 -1
  216. package/src/middleware/index.js +2 -0
  217. package/src/node-singletons/async_hooks.d.ts +9 -0
  218. package/src/node-singletons/async_hooks.d.ts.map +1 -0
  219. package/src/node-singletons/async_hooks.js +8 -0
  220. package/src/node-singletons/fs.d.ts +2 -2
  221. package/src/node-singletons/fs.d.ts.map +1 -1
  222. package/src/node-singletons/fs.js +2 -2
  223. package/src/node-singletons/http.d.ts +1 -1
  224. package/src/node-singletons/http.d.ts.map +1 -1
  225. package/src/node-singletons/http.js +1 -1
  226. package/src/node-singletons/index.d.ts +4 -0
  227. package/src/node-singletons/index.d.ts.map +1 -1
  228. package/src/node-singletons/index.js +4 -0
  229. package/src/node-singletons/net.d.ts +9 -0
  230. package/src/node-singletons/net.d.ts.map +1 -0
  231. package/src/node-singletons/net.js +8 -0
  232. package/src/node-singletons/os.d.ts +3 -3
  233. package/src/node-singletons/os.d.ts.map +1 -1
  234. package/src/node-singletons/os.js +3 -4
  235. package/src/node-singletons/path.d.ts +3 -1
  236. package/src/node-singletons/path.d.ts.map +1 -1
  237. package/src/node-singletons/path.js +3 -1
  238. package/src/node-singletons/perf-hooks.d.ts +3 -1
  239. package/src/node-singletons/perf-hooks.d.ts.map +1 -1
  240. package/src/node-singletons/perf-hooks.js +3 -1
  241. package/src/node-singletons/process.d.ts +23 -0
  242. package/src/node-singletons/process.d.ts.map +1 -0
  243. package/src/node-singletons/process.js +8 -0
  244. package/src/node-singletons/readline.d.ts +3 -3
  245. package/src/node-singletons/readline.d.ts.map +1 -1
  246. package/src/node-singletons/readline.js +3 -4
  247. package/src/node-singletons/tls.d.ts +9 -0
  248. package/src/node-singletons/tls.d.ts.map +1 -0
  249. package/src/node-singletons/tls.js +8 -0
  250. package/src/node-singletons/url.d.ts +3 -1
  251. package/src/node-singletons/url.d.ts.map +1 -1
  252. package/src/node-singletons/url.js +3 -1
  253. package/src/orm/ConnectionManager.d.ts +6 -1
  254. package/src/orm/ConnectionManager.d.ts.map +1 -1
  255. package/src/orm/ConnectionManager.js +14 -0
  256. package/src/orm/DatabaseAdapter.d.ts +6 -0
  257. package/src/orm/DatabaseAdapter.d.ts.map +1 -1
  258. package/src/orm/QueryBuilder.d.ts +8 -1
  259. package/src/orm/QueryBuilder.d.ts.map +1 -1
  260. package/src/orm/QueryBuilder.js +188 -28
  261. package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
  262. package/src/orm/adapters/D1Adapter.js +18 -12
  263. package/src/orm/adapters/MySQLAdapter.d.ts.map +1 -1
  264. package/src/orm/adapters/MySQLAdapter.js +4 -0
  265. package/src/orm/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  266. package/src/orm/adapters/PostgreSQLAdapter.js +4 -0
  267. package/src/orm/adapters/SQLServerAdapter.d.ts.map +1 -1
  268. package/src/orm/adapters/SQLServerAdapter.js +4 -0
  269. package/src/orm/adapters/SQLiteAdapter.d.ts.map +1 -1
  270. package/src/orm/adapters/SQLiteAdapter.js +4 -0
  271. package/src/performance/Benchmark.d.ts.map +1 -1
  272. package/src/performance/Benchmark.js +3 -0
  273. package/src/performance/CodeGenerationBenchmark.js +3 -3
  274. package/src/performance/Optimizer.d.ts +1 -1
  275. package/src/performance/Optimizer.d.ts.map +1 -1
  276. package/src/performance/Optimizer.js +157 -80
  277. package/src/performance/establish-baseline.js +3 -3
  278. package/src/runtime/PluginManager.d.ts +3 -1
  279. package/src/runtime/PluginManager.d.ts.map +1 -1
  280. package/src/runtime/PluginManager.js +124 -28
  281. package/src/runtime/RuntimeDetector.d.ts.map +1 -1
  282. package/src/runtime/RuntimeDetector.js +47 -5
  283. package/src/runtime/adapters/CloudflareAdapter.js +2 -2
  284. package/src/runtime/adapters/DenoAdapter.js +9 -7
  285. package/src/runtime/adapters/FargateAdapter.d.ts.map +1 -1
  286. package/src/runtime/adapters/FargateAdapter.js +4 -3
  287. package/src/runtime/adapters/LambdaAdapter.d.ts.map +1 -1
  288. package/src/runtime/adapters/LambdaAdapter.js +4 -2
  289. package/src/runtime/adapters/NodeServerAdapter.d.ts.map +1 -1
  290. package/src/runtime/adapters/NodeServerAdapter.js +7 -6
  291. package/src/scheduler/ScheduleRunner.d.ts +18 -0
  292. package/src/scheduler/ScheduleRunner.d.ts.map +1 -0
  293. package/src/scheduler/ScheduleRunner.js +155 -0
  294. package/src/scheduler/index.d.ts +3 -0
  295. package/src/scheduler/index.d.ts.map +1 -0
  296. package/src/scheduler/index.js +1 -0
  297. package/src/scheduler/types.d.ts +16 -0
  298. package/src/scheduler/types.d.ts.map +1 -0
  299. package/src/scheduler/types.js +4 -0
  300. package/src/schedules/index.d.ts +2 -0
  301. package/src/schedules/index.d.ts.map +1 -0
  302. package/src/schedules/index.js +1 -0
  303. package/src/schedules/log-cleanup.d.ts +4 -0
  304. package/src/schedules/log-cleanup.d.ts.map +1 -0
  305. package/src/schedules/log-cleanup.js +18 -0
  306. package/src/scripts/GenerateEnvArtifacts.d.ts +13 -0
  307. package/src/scripts/GenerateEnvArtifacts.d.ts.map +1 -0
  308. package/src/scripts/GenerateEnvArtifacts.js +171 -0
  309. package/src/scripts/TemplateSync.js +109 -70
  310. package/src/security/CsrfTokenManager.js +1 -1
  311. package/src/security/Encryptor.js +1 -1
  312. package/src/security/Hash.d.ts +14 -0
  313. package/src/security/Hash.d.ts.map +1 -0
  314. package/src/security/Hash.js +81 -0
  315. package/src/security/StartupSecretValidation.d.ts +20 -0
  316. package/src/security/StartupSecretValidation.d.ts.map +1 -0
  317. package/src/security/StartupSecretValidation.js +61 -0
  318. package/src/security/UrlValidator.d.ts +0 -1
  319. package/src/security/UrlValidator.d.ts.map +1 -1
  320. package/src/security/UrlValidator.js +1 -2
  321. package/src/security/Xss.d.ts +14 -0
  322. package/src/security/Xss.d.ts.map +1 -0
  323. package/src/security/Xss.js +57 -0
  324. package/src/security/XssProtection.d.ts.map +1 -1
  325. package/src/security/XssProtection.js +150 -16
  326. package/src/templates/adapters/MySQLAdapter.ts.tpl +5 -0
  327. package/src/templates/adapters/PostgreSQLAdapter.ts.tpl +5 -0
  328. package/src/templates/adapters/SQLServerAdapter.ts.tpl +5 -0
  329. package/src/templates/adapters/SQLiteAdapter.ts.tpl +5 -0
  330. package/src/templates/features/Queue.ts.tpl +1 -29
  331. package/src/templates/project/basic/.env.example.tpl +48 -0
  332. package/src/templates/project/basic/.env.tpl +89 -94
  333. package/src/templates/project/basic/app/Toolkit/Broadcast/sendBroadcast.ts.tpl +7 -0
  334. package/src/templates/project/basic/app/Toolkit/Mail/sendWelcomeEmail.ts.tpl +30 -0
  335. package/src/templates/project/basic/app/Toolkit/Notification/sendSlackNotification.ts.tpl +10 -0
  336. package/src/templates/project/basic/app/Toolkit/Notification/sendSms.ts.tpl +13 -0
  337. package/src/templates/project/basic/config/FileLogWriter.ts.tpl +240 -0
  338. package/src/templates/project/basic/config/SecretsManager.ts.tpl +32 -1
  339. package/src/templates/project/basic/config/StartupConfigValidator.ts.tpl +151 -0
  340. package/src/templates/project/basic/config/app.ts.tpl +84 -15
  341. package/src/templates/project/basic/config/broadcast.ts.tpl +97 -0
  342. package/src/templates/project/basic/config/cache.ts.tpl +19 -23
  343. package/src/templates/project/basic/config/cloudflare.ts.tpl +57 -0
  344. package/src/templates/project/basic/config/env.ts.tpl +7 -1
  345. package/src/templates/project/basic/config/index.ts.tpl +3 -0
  346. package/src/templates/project/basic/config/logger.ts.tpl +301 -11
  347. package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +121 -0
  348. package/src/templates/project/basic/config/logging/KvLogger.ts.tpl +181 -0
  349. package/src/templates/project/basic/config/logging/SlackLogger.ts.tpl +156 -0
  350. package/src/templates/project/basic/config/mail.ts.tpl +141 -0
  351. package/src/templates/project/basic/config/middleware.ts.tpl +27 -0
  352. package/src/templates/project/basic/config/notification.ts.tpl +86 -0
  353. package/src/templates/project/basic/config/security.ts.tpl +4 -5
  354. package/src/templates/project/basic/config/startup.ts.tpl +27 -0
  355. package/src/templates/project/basic/config/storage.ts.tpl +77 -42
  356. package/src/templates/project/basic/database/migrations/index.ts.tpl +1 -1
  357. package/src/templates/project/basic/package.json.tpl +1 -1
  358. package/src/templates/project/basic/routes/api.ts.tpl +9 -37
  359. package/src/templates/project/basic/routes/broadcast.ts.tpl +32 -0
  360. package/src/templates/project/basic/routes/health.ts.tpl +134 -0
  361. package/src/templates/project/basic/src/index.ts.tpl +38 -11
  362. package/src/templates/project/basic/template.json +3 -0
  363. package/src/toolkit/Secrets/EnvFile.d.ts +15 -0
  364. package/src/toolkit/Secrets/EnvFile.d.ts.map +1 -0
  365. package/src/toolkit/Secrets/EnvFile.js +63 -0
  366. package/src/toolkit/Secrets/Manifest.d.ts +24 -0
  367. package/src/toolkit/Secrets/Manifest.d.ts.map +1 -0
  368. package/src/toolkit/Secrets/Manifest.js +71 -0
  369. package/src/toolkit/Secrets/index.d.ts +42 -0
  370. package/src/toolkit/Secrets/index.d.ts.map +1 -0
  371. package/src/toolkit/Secrets/index.js +119 -0
  372. package/src/toolkit/Secrets/providers/AwsSecretsManager.d.ts +14 -0
  373. package/src/toolkit/Secrets/providers/AwsSecretsManager.d.ts.map +1 -0
  374. package/src/toolkit/Secrets/providers/AwsSecretsManager.js +131 -0
  375. package/src/toolkit/Secrets/providers/CloudflareKv.d.ts +9 -0
  376. package/src/toolkit/Secrets/providers/CloudflareKv.d.ts.map +1 -0
  377. package/src/toolkit/Secrets/providers/CloudflareKv.js +73 -0
  378. package/src/tools/broadcast/Broadcast.d.ts +7 -0
  379. package/src/tools/broadcast/Broadcast.d.ts.map +1 -0
  380. package/src/tools/broadcast/Broadcast.js +37 -0
  381. package/src/tools/broadcast/drivers/BaseDriver.d.ts +5 -0
  382. package/src/tools/broadcast/drivers/BaseDriver.d.ts.map +1 -0
  383. package/src/tools/broadcast/drivers/BaseDriver.js +8 -0
  384. package/src/tools/broadcast/drivers/InMemory.d.ts +18 -0
  385. package/src/tools/broadcast/drivers/InMemory.d.ts.map +1 -0
  386. package/src/tools/broadcast/drivers/InMemory.js +16 -0
  387. package/src/tools/broadcast/drivers/Pusher.d.ts +8 -0
  388. package/src/tools/broadcast/drivers/Pusher.d.ts.map +1 -0
  389. package/src/tools/broadcast/drivers/Pusher.js +75 -0
  390. package/src/tools/broadcast/drivers/Redis.d.ts +19 -0
  391. package/src/tools/broadcast/drivers/Redis.d.ts.map +1 -0
  392. package/src/tools/broadcast/drivers/Redis.js +73 -0
  393. package/src/tools/broadcast/drivers/RedisHttps.d.ts +14 -0
  394. package/src/tools/broadcast/drivers/RedisHttps.d.ts.map +1 -0
  395. package/src/tools/broadcast/drivers/RedisHttps.js +50 -0
  396. package/src/tools/broadcast/index.d.ts +7 -0
  397. package/src/tools/broadcast/index.d.ts.map +1 -0
  398. package/src/tools/broadcast/index.js +6 -0
  399. package/src/tools/http/Http.d.ts +51 -0
  400. package/src/tools/http/Http.d.ts.map +1 -0
  401. package/src/tools/http/Http.js +171 -0
  402. package/src/tools/http/HttpResponse.d.ts +32 -0
  403. package/src/tools/http/HttpResponse.d.ts.map +1 -0
  404. package/src/tools/http/HttpResponse.js +80 -0
  405. package/src/tools/http/index.d.ts +15 -0
  406. package/src/tools/http/index.d.ts.map +1 -0
  407. package/src/tools/http/index.js +9 -0
  408. package/src/tools/mail/Mail.d.ts +22 -0
  409. package/src/tools/mail/Mail.d.ts.map +1 -0
  410. package/src/tools/mail/Mail.js +105 -0
  411. package/src/tools/mail/attachments.d.ts +23 -0
  412. package/src/tools/mail/attachments.d.ts.map +1 -0
  413. package/src/tools/mail/attachments.js +26 -0
  414. package/src/tools/mail/drivers/BaseDriver.d.ts +5 -0
  415. package/src/tools/mail/drivers/BaseDriver.d.ts.map +1 -0
  416. package/src/tools/mail/drivers/BaseDriver.js +8 -0
  417. package/src/tools/mail/drivers/Mailgun.d.ts +31 -0
  418. package/src/tools/mail/drivers/Mailgun.d.ts.map +1 -0
  419. package/src/tools/mail/drivers/Mailgun.js +81 -0
  420. package/src/tools/mail/drivers/SendGrid.d.ts +29 -0
  421. package/src/tools/mail/drivers/SendGrid.d.ts.map +1 -0
  422. package/src/tools/mail/drivers/SendGrid.js +57 -0
  423. package/src/tools/mail/drivers/Ses.d.ts +24 -0
  424. package/src/tools/mail/drivers/Ses.d.ts.map +1 -0
  425. package/src/tools/mail/drivers/Ses.js +116 -0
  426. package/src/tools/mail/drivers/Smtp.d.ts +38 -0
  427. package/src/tools/mail/drivers/Smtp.d.ts.map +1 -0
  428. package/src/tools/mail/drivers/Smtp.js +327 -0
  429. package/src/tools/mail/templates/index.d.ts +27 -0
  430. package/src/tools/mail/templates/index.d.ts.map +1 -0
  431. package/src/tools/mail/templates/index.js +35 -0
  432. package/src/tools/mail/templates/markdown/index.d.ts +17 -0
  433. package/src/tools/mail/templates/markdown/index.d.ts.map +1 -0
  434. package/src/tools/mail/templates/markdown/index.js +49 -0
  435. package/src/tools/mail/templates/markdown/registry.d.ts +15 -0
  436. package/src/tools/mail/templates/markdown/registry.d.ts.map +1 -0
  437. package/src/tools/mail/templates/markdown/registry.js +34 -0
  438. package/src/tools/mail/templates/markdown/validator.d.ts +16 -0
  439. package/src/tools/mail/templates/markdown/validator.d.ts.map +1 -0
  440. package/src/tools/mail/templates/markdown/validator.js +24 -0
  441. package/src/tools/mail/testing.d.ts +41 -0
  442. package/src/tools/mail/testing.d.ts.map +1 -0
  443. package/src/tools/mail/testing.js +34 -0
  444. package/src/tools/notification/Driver.d.ts +11 -0
  445. package/src/tools/notification/Driver.d.ts.map +1 -0
  446. package/src/tools/notification/Driver.js +1 -0
  447. package/src/tools/notification/Notification.d.ts +11 -0
  448. package/src/tools/notification/Notification.d.ts.map +1 -0
  449. package/src/tools/notification/Notification.js +11 -0
  450. package/src/tools/notification/Registry.d.ts +10 -0
  451. package/src/tools/notification/Registry.d.ts.map +1 -0
  452. package/src/tools/notification/Registry.js +22 -0
  453. package/src/tools/notification/Service.d.ts +6 -0
  454. package/src/tools/notification/Service.d.ts.map +1 -0
  455. package/src/tools/notification/Service.js +18 -0
  456. package/src/tools/notification/config.d.ts +5 -0
  457. package/src/tools/notification/config.d.ts.map +1 -0
  458. package/src/tools/notification/config.js +5 -0
  459. package/src/tools/notification/drivers/BaseDriver.d.ts +5 -0
  460. package/src/tools/notification/drivers/BaseDriver.d.ts.map +1 -0
  461. package/src/tools/notification/drivers/BaseDriver.js +8 -0
  462. package/src/tools/notification/drivers/Console.d.ts +7 -0
  463. package/src/tools/notification/drivers/Console.d.ts.map +1 -0
  464. package/src/tools/notification/drivers/Console.js +13 -0
  465. package/src/tools/notification/drivers/Slack.d.ts +16 -0
  466. package/src/tools/notification/drivers/Slack.d.ts.map +1 -0
  467. package/src/tools/notification/drivers/Slack.js +24 -0
  468. package/src/tools/notification/drivers/Termii.d.ts +10 -0
  469. package/src/tools/notification/drivers/Termii.d.ts.map +1 -0
  470. package/src/tools/notification/drivers/Termii.js +47 -0
  471. package/src/tools/notification/drivers/Twilio.d.ts +21 -0
  472. package/src/tools/notification/drivers/Twilio.d.ts.map +1 -0
  473. package/src/tools/notification/drivers/Twilio.js +48 -0
  474. package/src/tools/notification/templates/markdown/index.d.ts +15 -0
  475. package/src/tools/notification/templates/markdown/index.d.ts.map +1 -0
  476. package/src/tools/notification/templates/markdown/index.js +38 -0
  477. package/src/tools/notification/templates/markdown/registry.d.ts +15 -0
  478. package/src/tools/notification/templates/markdown/registry.d.ts.map +1 -0
  479. package/src/tools/notification/templates/markdown/registry.js +36 -0
  480. package/src/tools/notification/testing.d.ts +19 -0
  481. package/src/tools/notification/testing.d.ts.map +1 -0
  482. package/src/tools/notification/testing.js +35 -0
  483. package/src/tools/notification/testingHelpers.d.ts +12 -0
  484. package/src/tools/notification/testingHelpers.d.ts.map +1 -0
  485. package/src/tools/notification/testingHelpers.js +32 -0
  486. package/src/tools/queue/Queue.d.ts +23 -0
  487. package/src/tools/queue/Queue.d.ts.map +1 -0
  488. package/src/tools/queue/Queue.js +38 -0
  489. package/src/tools/queue/drivers/InMemory.d.ts +10 -0
  490. package/src/tools/queue/drivers/InMemory.d.ts.map +1 -0
  491. package/src/tools/queue/drivers/InMemory.js +55 -0
  492. package/src/tools/queue/drivers/Redis.d.ts +10 -0
  493. package/src/tools/queue/drivers/Redis.d.ts.map +1 -0
  494. package/src/tools/queue/drivers/Redis.js +91 -0
  495. package/src/tools/storage/drivers/Gcs.d.ts +20 -0
  496. package/src/tools/storage/drivers/Gcs.d.ts.map +1 -0
  497. package/src/tools/storage/drivers/Gcs.js +152 -0
  498. package/src/tools/storage/drivers/Local.d.ts +17 -0
  499. package/src/tools/storage/drivers/Local.d.ts.map +1 -0
  500. package/src/tools/storage/drivers/Local.js +63 -0
  501. package/src/tools/storage/drivers/R2.d.ts +20 -0
  502. package/src/tools/storage/drivers/R2.d.ts.map +1 -0
  503. package/src/tools/storage/drivers/R2.js +73 -0
  504. package/src/tools/storage/drivers/S3.d.ts +26 -0
  505. package/src/tools/storage/drivers/S3.d.ts.map +1 -0
  506. package/src/tools/storage/drivers/S3.js +258 -0
  507. package/src/tools/storage/index.d.ts +24 -0
  508. package/src/tools/storage/index.d.ts.map +1 -0
  509. package/src/tools/storage/index.js +112 -0
  510. package/src/tools/storage/testing.d.ts +23 -0
  511. package/src/tools/storage/testing.d.ts.map +1 -0
  512. package/src/tools/storage/testing.js +52 -0
  513. package/src/tools/templates/MarkdownRenderer.d.ts +14 -0
  514. package/src/tools/templates/MarkdownRenderer.d.ts.map +1 -0
  515. package/src/tools/templates/MarkdownRenderer.js +300 -0
  516. package/src/tools/templates/index.d.ts +5 -0
  517. package/src/tools/templates/index.d.ts.map +1 -0
  518. 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;
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { Logger } from '@config/logger';
8
- import { ErrorFactory } from '@zintrust/core';
8
+ import { ErrorFactory } from '@exceptions/ZintrustError';
9
9
 
10
10
  export interface CloudflareKV {
11
11
  get(key: string): Promise<string | null>;
@@ -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,6 +193,7 @@ 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
@@ -210,6 +235,7 @@ const SecretsManagerImpl = {
210
235
  /**
211
236
  * AWS Secrets Manager integration
212
237
  */
238
+ // eslint-disable-next-line @typescript-eslint/require-await
213
239
  async function getFromAWSSecretsManager(key: string): Promise<string> {
214
240
  try {
215
241
  Logger.debug(`[AWS] Getting secret: ${key}`);
@@ -222,6 +248,7 @@ async function getFromAWSSecretsManager(key: string): Promise<string> {
222
248
  }
223
249
  }
224
250
 
251
+ // eslint-disable-next-line @typescript-eslint/require-await
225
252
  async function setInAWSSecretsManager(
226
253
  key: string,
227
254
  _value: string,
@@ -231,11 +258,13 @@ async function setInAWSSecretsManager(
231
258
  throw ErrorFactory.createConfigError('AWS SDK not available in core - use wrapper module');
232
259
  }
233
260
 
261
+ // eslint-disable-next-line @typescript-eslint/require-await
234
262
  async function deleteFromAWSSecretsManager(key: string): Promise<void> {
235
263
  Logger.info(`[AWS] Deleting secret: ${key}`);
236
264
  throw ErrorFactory.createConfigError('AWS SDK not available in core - use wrapper module');
237
265
  }
238
266
 
267
+ // eslint-disable-next-line @typescript-eslint/require-await
239
268
  async function listFromAWSSecretsManager(pattern?: string): Promise<string[]> {
240
269
  Logger.info(`[AWS] Listing secrets with pattern: ${pattern ?? '*'}`);
241
270
  return [];
@@ -286,6 +315,7 @@ async function listFromCloudflareKV(config: SecretConfig, pattern?: string): Pro
286
315
  /**
287
316
  * Deno environment integration
288
317
  */
318
+ // eslint-disable-next-line @typescript-eslint/require-await
289
319
  async function getFromDenoEnv(key: string): Promise<string> {
290
320
  const value = (
291
321
  globalThis as unknown as Record<string, { env?: { get?: (key: string) => string } }>
@@ -299,6 +329,7 @@ async function getFromDenoEnv(key: string): Promise<string> {
299
329
  /**
300
330
  * Local environment variables (Node.js)
301
331
  */
332
+ // eslint-disable-next-line @typescript-eslint/require-await
302
333
  async function getFromEnv(key: string): Promise<string> {
303
334
  const value = process.env[key];
304
335
  if (value === undefined || value === null || value === '') {
@@ -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;
@@ -6,6 +6,47 @@
6
6
 
7
7
  import { Env } from '@config/env';
8
8
 
9
+ type ProcessLike = { env?: Record<string, string | undefined> };
10
+
11
+ type Environment = 'development' | 'dev' | 'production' | 'prod' | 'pro' | 'testing' | 'test';
12
+ type StartMode = 'development' | 'production' | 'testing';
13
+
14
+ const getProcessLike = (): ProcessLike | undefined => {
15
+ return typeof process === 'undefined' ? undefined : (process as unknown as ProcessLike);
16
+ };
17
+
18
+ const readEnvString = (key: string, defaultValue: string = ''): string => {
19
+ const anyEnv = Env as unknown as { get?: unknown };
20
+ if (typeof anyEnv.get === 'function') {
21
+ return (anyEnv.get as (k: string, d?: string) => string)(key, defaultValue);
22
+ }
23
+
24
+ const proc = getProcessLike();
25
+ const raw = proc?.env?.[key];
26
+ return raw ?? defaultValue;
27
+ };
28
+
29
+ const readEnvInt = (key: string, defaultValue: number): number => {
30
+ const anyEnv = Env as unknown as { getInt?: unknown };
31
+ if (typeof anyEnv.getInt === 'function') {
32
+ return (anyEnv.getInt as (k: string, d?: number) => number)(key, defaultValue);
33
+ }
34
+
35
+ const raw = readEnvString(key, String(defaultValue));
36
+ const parsed = Number.parseInt(raw, 10);
37
+ return Number.isNaN(parsed) ? defaultValue : parsed;
38
+ };
39
+
40
+ const readEnvBool = (key: string, defaultValue: boolean): boolean => {
41
+ const anyEnv = Env as unknown as { getBool?: unknown };
42
+ if (typeof anyEnv.getBool === 'function') {
43
+ return (anyEnv.getBool as (k: string, d?: boolean) => boolean)(key, defaultValue);
44
+ }
45
+
46
+ const raw = readEnvString(key, defaultValue ? 'true' : 'false');
47
+ return raw.toLowerCase() === 'true' || raw === '1';
48
+ };
49
+
9
50
  const getSafeEnv = (): NodeJS.ProcessEnv => {
10
51
  const baseEnv: Partial<NodeJS.ProcessEnv> = typeof process === 'undefined' ? {} : process.env;
11
52
 
@@ -13,39 +54,64 @@ const getSafeEnv = (): NodeJS.ProcessEnv => {
13
54
  ...(baseEnv as NodeJS.ProcessEnv),
14
55
 
15
56
  // Ensure required keys exist (env.d.ts augments ProcessEnv with required fields)
16
- NODE_ENV: baseEnv.NODE_ENV ?? (Env.NODE_ENV as NodeJS.ProcessEnv['NODE_ENV']),
17
- USE_RAW_QRY: baseEnv.USE_RAW_QRY ?? (Env.get('USE_RAW_QRY') || undefined),
18
- SERVICE_API_KEY: baseEnv.SERVICE_API_KEY ?? Env.get('SERVICE_API_KEY', ''),
19
- SERVICE_JWT_SECRET: baseEnv.SERVICE_JWT_SECRET ?? Env.get('SERVICE_JWT_SECRET', ''),
20
- BASE_URL: baseEnv.BASE_URL ?? Env.get('BASE_URL', ''),
21
- MODE: baseEnv.MODE ?? Env.get('MODE', ''),
57
+ NODE_ENV:
58
+ baseEnv.NODE_ENV ??
59
+ (readEnvString('NODE_ENV', 'development') as NodeJS.ProcessEnv['NODE_ENV']),
60
+ USE_RAW_QRY: baseEnv.USE_RAW_QRY ?? (readEnvString('USE_RAW_QRY', '') || undefined),
61
+ SERVICE_API_KEY: baseEnv.SERVICE_API_KEY ?? readEnvString('SERVICE_API_KEY', ''),
62
+ SERVICE_JWT_SECRET: baseEnv.SERVICE_JWT_SECRET ?? readEnvString('SERVICE_JWT_SECRET', ''),
63
+ BASE_URL: baseEnv['BASE_URL'] ?? readEnvString('BASE_URL', ''),
64
+ MODE: baseEnv['MODE'] ?? readEnvString('MODE', ''),
22
65
 
23
66
  // Hardening for child-process usage
24
- PATH: Env.SAFE_PATH,
67
+ PATH:
68
+ typeof (Env as unknown as { SAFE_PATH?: unknown }).SAFE_PATH === 'string'
69
+ ? (Env as unknown as { SAFE_PATH: string }).SAFE_PATH
70
+ : (baseEnv['PATH'] ?? ''),
25
71
  npm_config_scripts_prepend_node_path: 'true',
26
72
  };
27
73
  };
28
74
 
75
+ const normalizeMode = (): StartMode => {
76
+ const value = (
77
+ typeof (Env as unknown as { NODE_ENV?: unknown }).NODE_ENV === 'string'
78
+ ? (Env as unknown as { NODE_ENV: string }).NODE_ENV
79
+ : readEnvString('NODE_ENV', 'development')
80
+ ) as Environment;
81
+ if (value === 'production' || value === 'pro' || value === 'prod') return 'production';
82
+ if (value === 'testing' || value === 'test') return 'testing';
83
+ return 'development';
84
+ };
85
+
29
86
  const appConfigObj = {
30
87
  /**
31
88
  * Application name
32
89
  */
33
- name: Env.APP_NAME,
90
+ name:
91
+ typeof (Env as unknown as { APP_NAME?: unknown }).APP_NAME === 'string'
92
+ ? (Env as unknown as { APP_NAME: string }).APP_NAME
93
+ : readEnvString('APP_NAME', 'ZinTrust'),
34
94
 
35
95
  /**
36
96
  * Application environment
37
97
  */
38
- environment: Env.NODE_ENV as 'development' | 'production' | 'testing',
98
+ environment: normalizeMode(),
39
99
 
40
100
  /**
41
101
  * Application port
42
102
  */
43
- port: Env.PORT,
103
+ port:
104
+ typeof (Env as unknown as { PORT?: unknown }).PORT === 'number'
105
+ ? (Env as unknown as { PORT: number }).PORT
106
+ : readEnvInt('APP_PORT', 3000),
44
107
 
45
108
  /**
46
109
  * Application host
47
110
  */
48
- host: Env.HOST,
111
+ host:
112
+ typeof (Env as unknown as { HOST?: unknown }).HOST === 'string'
113
+ ? (Env as unknown as { HOST: string }).HOST
114
+ : readEnvString('HOST', 'localhost'),
49
115
 
50
116
  /**
51
117
  * Is development environment
@@ -71,22 +137,25 @@ const appConfigObj = {
71
137
  /**
72
138
  * Application debug mode
73
139
  */
74
- debug: Env.DEBUG,
140
+ debug:
141
+ typeof (Env as unknown as { DEBUG?: unknown }).DEBUG === 'boolean'
142
+ ? (Env as unknown as { DEBUG: boolean }).DEBUG
143
+ : readEnvBool('DEBUG', false),
75
144
 
76
145
  /**
77
146
  * Application timezone
78
147
  */
79
- timezone: Env.get('APP_TIMEZONE', 'UTC'),
148
+ timezone: readEnvString('APP_TIMEZONE', 'UTC'),
80
149
 
81
150
  /**
82
151
  * Request timeout (milliseconds)
83
152
  */
84
- requestTimeout: Env.getInt('REQUEST_TIMEOUT', 30000),
153
+ requestTimeout: readEnvInt('REQUEST_TIMEOUT', 30000),
85
154
 
86
155
  /**
87
156
  * Max request body size
88
157
  */
89
- maxBodySize: Env.get('MAX_BODY_SIZE', '10mb'),
158
+ maxBodySize: readEnvString('MAX_BODY_SIZE', '10mb'),
90
159
 
91
160
  getSafeEnv,
92
161
  } as const;