@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.
- package/README.md +214 -0
- package/bin/zintrust.d.ts.map +1 -1
- package/bin/zintrust.js +18 -1
- package/package.json +4 -34
- package/public/index.html +535 -0
- package/src/boot/Application.d.ts.map +1 -1
- package/src/boot/Application.js +46 -3
- package/src/boot/Server.d.ts.map +1 -1
- package/src/boot/Server.js +3 -4
- package/src/boot/bootstrap.js +77 -6
- package/src/builder/BundleOptimizer.d.ts.map +1 -1
- package/src/builder/BundleOptimizer.js +25 -29
- package/src/cache/Cache.d.ts.map +1 -1
- package/src/cache/Cache.js +4 -2
- package/src/cache/drivers/KVDriver.d.ts.map +1 -1
- package/src/cache/drivers/KVDriver.js +8 -7
- package/src/cache/drivers/MemoryDriver.d.ts.map +1 -1
- package/src/cache/drivers/MemoryDriver.js +5 -0
- package/src/cache/drivers/RedisDriver.js +1 -1
- package/src/cli/BaseCommand.d.ts +2 -2
- package/src/cli/BaseCommand.d.ts.map +1 -1
- package/src/cli/BaseCommand.js +2 -1
- package/src/cli/CLI.d.ts.map +1 -1
- package/src/cli/CLI.js +22 -18
- package/src/cli/ErrorHandler.d.ts.map +1 -1
- package/src/cli/ErrorHandler.js +2 -4
- package/src/cli/commands/AddCommand.d.ts +81 -0
- package/src/cli/commands/AddCommand.d.ts.map +1 -1
- package/src/cli/commands/AddCommand.js +24 -5
- package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
- package/src/cli/commands/ConfigCommand.js +59 -25
- package/src/cli/commands/D1MigrateCommand.d.ts +4 -0
- package/src/cli/commands/D1MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/D1MigrateCommand.js +6 -4
- package/src/cli/commands/FixCommand.d.ts.map +1 -1
- package/src/cli/commands/FixCommand.js +3 -15
- package/src/cli/commands/LogsCleanupCommand.d.ts +6 -0
- package/src/cli/commands/LogsCleanupCommand.d.ts.map +1 -0
- package/src/cli/commands/LogsCleanupCommand.js +20 -0
- package/src/cli/commands/LogsCommand.d.ts.map +1 -1
- package/src/cli/commands/LogsCommand.js +4 -6
- package/src/cli/commands/MakeMailTemplateCommand.d.ts +10 -0
- package/src/cli/commands/MakeMailTemplateCommand.d.ts.map +1 -0
- package/src/cli/commands/MakeMailTemplateCommand.js +74 -0
- package/src/cli/commands/MakeNotificationTemplateCommand.d.ts +10 -0
- package/src/cli/commands/MakeNotificationTemplateCommand.d.ts.map +1 -0
- package/src/cli/commands/MakeNotificationTemplateCommand.js +113 -0
- package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateCommand.js +3 -3
- package/src/cli/commands/NewCommand.d.ts +4 -0
- package/src/cli/commands/NewCommand.d.ts.map +1 -1
- package/src/cli/commands/NewCommand.js +34 -19
- package/src/cli/commands/PluginCommand.d.ts.map +1 -1
- package/src/cli/commands/PluginCommand.js +8 -4
- package/src/cli/commands/PrepareCommand.d.ts.map +1 -1
- package/src/cli/commands/PrepareCommand.js +1 -1
- package/src/cli/commands/QACommand.d.ts.map +1 -1
- package/src/cli/commands/QACommand.js +16 -26
- package/src/cli/commands/SecretsCommand.d.ts +16 -0
- package/src/cli/commands/SecretsCommand.d.ts.map +1 -0
- package/src/cli/commands/SecretsCommand.js +91 -0
- package/src/cli/commands/StartCommand.d.ts.map +1 -1
- package/src/cli/commands/StartCommand.js +2 -2
- package/src/cli/commands/TemplatesCommand.d.ts +3 -0
- package/src/cli/commands/TemplatesCommand.d.ts.map +1 -0
- package/src/cli/commands/TemplatesCommand.js +65 -0
- package/src/cli/commands/index.d.ts +5 -0
- package/src/cli/commands/index.d.ts.map +1 -1
- package/src/cli/commands/index.js +5 -0
- package/src/cli/config/ConfigManager.js +1 -1
- package/src/cli/index.d.ts +2 -1
- package/src/cli/index.d.ts.map +1 -1
- package/src/cli/index.js +2 -1
- package/src/cli/scaffolding/ControllerGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/ControllerGenerator.js +11 -10
- package/src/cli/scaffolding/FeatureScaffolder.js +4 -4
- package/src/cli/scaffolding/FileGenerator.js +1 -1
- package/src/cli/scaffolding/MigrationGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/MigrationGenerator.js +10 -9
- package/src/cli/scaffolding/ModelGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/ModelGenerator.js +11 -10
- package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ProjectScaffolder.js +61 -11
- package/src/cli/scaffolding/ResponseFactoryGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/ResponseFactoryGenerator.js +2 -1
- package/src/cli/scaffolding/RouteGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/RouteGenerator.js +15 -14
- package/src/cli/scaffolding/SeederGenerator.js +1 -1
- package/src/cli/scaffolding/ServiceIntegrationTestGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/ServiceIntegrationTestGenerator.js +7 -6
- package/src/cli/scaffolding/ServiceRequestFactoryGenerator.d.ts +1 -1
- package/src/cli/scaffolding/ServiceRequestFactoryGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/ServiceRequestFactoryGenerator.js +2 -2
- package/src/cli/scaffolding/ServiceScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ServiceScaffolder.js +13 -12
- package/src/cli/scaffolding/TemplateEngine.d.ts +10 -3
- package/src/cli/scaffolding/TemplateEngine.d.ts.map +1 -1
- package/src/cli/scaffolding/TemplateEngine.js +15 -285
- package/src/cli/scaffolding/TemplateGenerator.d.ts +40 -0
- package/src/cli/scaffolding/TemplateGenerator.d.ts.map +1 -0
- package/src/cli/scaffolding/TemplateGenerator.js +172 -0
- package/src/cli/scaffolding/index.d.ts +1 -0
- package/src/cli/scaffolding/index.d.ts.map +1 -1
- package/src/cli/scaffolding/index.js +1 -0
- package/src/cli/utils/spawn.js +1 -1
- package/src/common/AwsSigV4.d.ts +41 -0
- package/src/common/AwsSigV4.d.ts.map +1 -0
- package/src/common/AwsSigV4.js +69 -0
- package/src/common/index.d.ts +39 -0
- package/src/common/index.d.ts.map +1 -1
- package/src/common/index.js +101 -8
- package/src/common/uuid.d.ts +3 -0
- package/src/common/uuid.d.ts.map +1 -0
- package/src/common/uuid.js +30 -0
- package/src/config/FileLogWriter.d.ts +22 -0
- package/src/config/FileLogWriter.d.ts.map +1 -0
- package/src/config/FileLogWriter.js +192 -0
- package/src/config/SecretsManager.d.ts.map +1 -1
- package/src/config/SecretsManager.js +26 -0
- package/src/config/StartupConfigValidator.d.ts +15 -0
- package/src/config/StartupConfigValidator.d.ts.map +1 -0
- package/src/config/StartupConfigValidator.js +86 -0
- package/src/config/app.d.ts +2 -1
- package/src/config/app.d.ts.map +1 -1
- package/src/config/app.js +65 -15
- package/src/config/broadcast.d.ts +47 -0
- package/src/config/broadcast.d.ts.map +1 -0
- package/src/config/broadcast.js +54 -0
- package/src/config/cache.d.ts +13 -17
- package/src/config/cache.d.ts.map +1 -1
- package/src/config/cache.js +9 -11
- package/src/config/cloudflare.d.ts +26 -0
- package/src/config/cloudflare.d.ts.map +1 -0
- package/src/config/cloudflare.js +38 -0
- package/src/config/env.d.ts +6 -0
- package/src/config/env.d.ts.map +1 -1
- package/src/config/env.js +6 -0
- package/src/config/index.d.ts +52 -28
- package/src/config/index.d.ts.map +1 -1
- package/src/config/index.js +3 -0
- package/src/config/logger.d.ts +2 -0
- package/src/config/logger.d.ts.map +1 -1
- package/src/config/logger.js +270 -11
- package/src/config/logging/HttpLogger.d.ts +23 -0
- package/src/config/logging/HttpLogger.d.ts.map +1 -0
- package/src/config/logging/HttpLogger.js +93 -0
- package/src/config/logging/KvLogger.d.ts +22 -0
- package/src/config/logging/KvLogger.d.ts.map +1 -0
- package/src/config/logging/KvLogger.js +143 -0
- package/src/config/logging/SlackLogger.d.ts +23 -0
- package/src/config/logging/SlackLogger.d.ts.map +1 -0
- package/src/config/logging/SlackLogger.js +119 -0
- package/src/config/mail.d.ts +81 -0
- package/src/config/mail.d.ts.map +1 -0
- package/src/config/mail.js +73 -0
- package/src/config/middleware.d.ts +8 -0
- package/src/config/middleware.d.ts.map +1 -0
- package/src/config/middleware.js +18 -0
- package/src/config/notification.d.ts +62 -0
- package/src/config/notification.d.ts.map +1 -0
- package/src/config/notification.js +43 -0
- package/src/config/security.d.ts.map +1 -1
- package/src/config/security.js +2 -2
- package/src/config/startup.d.ts +23 -0
- package/src/config/startup.d.ts.map +1 -0
- package/src/config/startup.js +15 -0
- package/src/config/storage.d.ts +21 -35
- package/src/config/storage.d.ts.map +1 -1
- package/src/config/storage.js +57 -37
- package/src/database/migrations/index.d.ts +1 -1
- package/src/database/migrations/index.d.ts.map +1 -1
- package/src/database/migrations/index.js +2 -1
- package/src/features/Queue.js +1 -25
- package/src/functions/lambda.d.ts.map +1 -1
- package/src/functions/lambda.js +6 -1
- package/src/health/RuntimeHealthProbes.d.ts +13 -0
- package/src/health/RuntimeHealthProbes.d.ts.map +1 -0
- package/src/health/RuntimeHealthProbes.js +62 -0
- package/src/health/StartupHealthChecks.d.ts +26 -0
- package/src/health/StartupHealthChecks.d.ts.map +1 -0
- package/src/health/StartupHealthChecks.js +124 -0
- package/src/http/ErrorResponse.d.ts +28 -0
- package/src/http/ErrorResponse.d.ts.map +1 -0
- package/src/http/ErrorResponse.js +42 -0
- package/src/http/Kernel.d.ts +5 -0
- package/src/http/Kernel.d.ts.map +1 -1
- package/src/http/Kernel.js +96 -30
- package/src/http/Request.d.ts +1 -1
- package/src/http/Request.d.ts.map +1 -1
- package/src/http/RequestContext.d.ts +20 -0
- package/src/http/RequestContext.d.ts.map +1 -0
- package/src/http/RequestContext.js +77 -0
- package/src/index.d.ts +9 -1
- package/src/index.d.ts.map +1 -1
- package/src/index.js +8 -2
- package/src/microservices/MicroserviceBootstrap.d.ts.map +1 -1
- package/src/microservices/MicroserviceBootstrap.js +6 -5
- package/src/microservices/MicroserviceManager.d.ts.map +1 -1
- package/src/microservices/MicroserviceManager.js +7 -5
- package/src/microservices/PostgresAdapter.d.ts.map +1 -1
- package/src/microservices/PostgresAdapter.js +7 -4
- package/src/microservices/ServiceBundler.d.ts.map +1 -1
- package/src/microservices/ServiceBundler.js +3 -1
- package/src/microservices/ServiceHealthMonitor.d.ts.map +1 -1
- package/src/microservices/ServiceHealthMonitor.js +7 -3
- package/src/middleware/CsrfMiddleware.d.ts.map +1 -1
- package/src/middleware/CsrfMiddleware.js +2 -19
- package/src/middleware/ErrorHandlerMiddleware.d.ts +6 -0
- package/src/middleware/ErrorHandlerMiddleware.d.ts.map +1 -0
- package/src/middleware/ErrorHandlerMiddleware.js +33 -0
- package/src/middleware/LoggingMiddleware.d.ts +9 -0
- package/src/middleware/LoggingMiddleware.d.ts.map +1 -0
- package/src/middleware/LoggingMiddleware.js +36 -0
- package/src/middleware/index.d.ts +2 -0
- package/src/middleware/index.d.ts.map +1 -1
- package/src/middleware/index.js +2 -0
- package/src/node-singletons/async_hooks.d.ts +9 -0
- package/src/node-singletons/async_hooks.d.ts.map +1 -0
- package/src/node-singletons/async_hooks.js +8 -0
- package/src/node-singletons/fs.d.ts +2 -2
- package/src/node-singletons/fs.d.ts.map +1 -1
- package/src/node-singletons/fs.js +2 -2
- package/src/node-singletons/http.d.ts +1 -1
- package/src/node-singletons/http.d.ts.map +1 -1
- package/src/node-singletons/http.js +1 -1
- package/src/node-singletons/index.d.ts +4 -0
- package/src/node-singletons/index.d.ts.map +1 -1
- package/src/node-singletons/index.js +4 -0
- package/src/node-singletons/net.d.ts +9 -0
- package/src/node-singletons/net.d.ts.map +1 -0
- package/src/node-singletons/net.js +8 -0
- package/src/node-singletons/os.d.ts +3 -3
- package/src/node-singletons/os.d.ts.map +1 -1
- package/src/node-singletons/os.js +3 -4
- package/src/node-singletons/path.d.ts +3 -1
- package/src/node-singletons/path.d.ts.map +1 -1
- package/src/node-singletons/path.js +3 -1
- package/src/node-singletons/perf-hooks.d.ts +3 -1
- package/src/node-singletons/perf-hooks.d.ts.map +1 -1
- package/src/node-singletons/perf-hooks.js +3 -1
- package/src/node-singletons/process.d.ts +23 -0
- package/src/node-singletons/process.d.ts.map +1 -0
- package/src/node-singletons/process.js +8 -0
- package/src/node-singletons/readline.d.ts +3 -3
- package/src/node-singletons/readline.d.ts.map +1 -1
- package/src/node-singletons/readline.js +3 -4
- package/src/node-singletons/tls.d.ts +9 -0
- package/src/node-singletons/tls.d.ts.map +1 -0
- package/src/node-singletons/tls.js +8 -0
- package/src/node-singletons/url.d.ts +3 -1
- package/src/node-singletons/url.d.ts.map +1 -1
- package/src/node-singletons/url.js +3 -1
- package/src/orm/ConnectionManager.d.ts +6 -1
- package/src/orm/ConnectionManager.d.ts.map +1 -1
- package/src/orm/ConnectionManager.js +14 -0
- package/src/orm/DatabaseAdapter.d.ts +6 -0
- package/src/orm/DatabaseAdapter.d.ts.map +1 -1
- package/src/orm/QueryBuilder.d.ts +8 -1
- package/src/orm/QueryBuilder.d.ts.map +1 -1
- package/src/orm/QueryBuilder.js +188 -28
- package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
- package/src/orm/adapters/D1Adapter.js +18 -12
- package/src/orm/adapters/MySQLAdapter.d.ts.map +1 -1
- package/src/orm/adapters/MySQLAdapter.js +4 -0
- package/src/orm/adapters/PostgreSQLAdapter.d.ts.map +1 -1
- package/src/orm/adapters/PostgreSQLAdapter.js +4 -0
- package/src/orm/adapters/SQLServerAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SQLServerAdapter.js +4 -0
- package/src/orm/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SQLiteAdapter.js +4 -0
- package/src/performance/Benchmark.d.ts.map +1 -1
- package/src/performance/Benchmark.js +3 -0
- package/src/performance/CodeGenerationBenchmark.js +3 -3
- package/src/performance/Optimizer.d.ts +1 -1
- package/src/performance/Optimizer.d.ts.map +1 -1
- package/src/performance/Optimizer.js +157 -80
- package/src/performance/establish-baseline.js +3 -3
- package/src/runtime/PluginManager.d.ts +3 -1
- package/src/runtime/PluginManager.d.ts.map +1 -1
- package/src/runtime/PluginManager.js +124 -28
- package/src/runtime/RuntimeDetector.d.ts.map +1 -1
- package/src/runtime/RuntimeDetector.js +47 -5
- package/src/runtime/adapters/CloudflareAdapter.js +2 -2
- package/src/runtime/adapters/DenoAdapter.js +9 -7
- package/src/runtime/adapters/FargateAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/FargateAdapter.js +4 -3
- package/src/runtime/adapters/LambdaAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/LambdaAdapter.js +4 -2
- package/src/runtime/adapters/NodeServerAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/NodeServerAdapter.js +7 -6
- package/src/scheduler/ScheduleRunner.d.ts +18 -0
- package/src/scheduler/ScheduleRunner.d.ts.map +1 -0
- package/src/scheduler/ScheduleRunner.js +155 -0
- package/src/scheduler/index.d.ts +3 -0
- package/src/scheduler/index.d.ts.map +1 -0
- package/src/scheduler/index.js +1 -0
- package/src/scheduler/types.d.ts +16 -0
- package/src/scheduler/types.d.ts.map +1 -0
- package/src/scheduler/types.js +4 -0
- package/src/schedules/index.d.ts +2 -0
- package/src/schedules/index.d.ts.map +1 -0
- package/src/schedules/index.js +1 -0
- package/src/schedules/log-cleanup.d.ts +4 -0
- package/src/schedules/log-cleanup.d.ts.map +1 -0
- package/src/schedules/log-cleanup.js +18 -0
- package/src/scripts/GenerateEnvArtifacts.d.ts +13 -0
- package/src/scripts/GenerateEnvArtifacts.d.ts.map +1 -0
- package/src/scripts/GenerateEnvArtifacts.js +171 -0
- package/src/scripts/TemplateSync.js +109 -70
- package/src/security/CsrfTokenManager.js +1 -1
- package/src/security/Encryptor.js +1 -1
- package/src/security/Hash.d.ts +14 -0
- package/src/security/Hash.d.ts.map +1 -0
- package/src/security/Hash.js +81 -0
- package/src/security/StartupSecretValidation.d.ts +20 -0
- package/src/security/StartupSecretValidation.d.ts.map +1 -0
- package/src/security/StartupSecretValidation.js +61 -0
- package/src/security/UrlValidator.d.ts +0 -1
- package/src/security/UrlValidator.d.ts.map +1 -1
- package/src/security/UrlValidator.js +1 -2
- package/src/security/Xss.d.ts +14 -0
- package/src/security/Xss.d.ts.map +1 -0
- package/src/security/Xss.js +57 -0
- package/src/security/XssProtection.d.ts.map +1 -1
- package/src/security/XssProtection.js +150 -16
- package/src/templates/adapters/MySQLAdapter.ts.tpl +5 -0
- package/src/templates/adapters/PostgreSQLAdapter.ts.tpl +5 -0
- package/src/templates/adapters/SQLServerAdapter.ts.tpl +5 -0
- package/src/templates/adapters/SQLiteAdapter.ts.tpl +5 -0
- package/src/templates/features/Queue.ts.tpl +1 -29
- package/src/templates/project/basic/.env.example.tpl +48 -0
- package/src/templates/project/basic/.env.tpl +89 -94
- package/src/templates/project/basic/app/Toolkit/Broadcast/sendBroadcast.ts.tpl +7 -0
- package/src/templates/project/basic/app/Toolkit/Mail/sendWelcomeEmail.ts.tpl +30 -0
- package/src/templates/project/basic/app/Toolkit/Notification/sendSlackNotification.ts.tpl +10 -0
- package/src/templates/project/basic/app/Toolkit/Notification/sendSms.ts.tpl +13 -0
- package/src/templates/project/basic/config/FileLogWriter.ts.tpl +240 -0
- package/src/templates/project/basic/config/SecretsManager.ts.tpl +32 -1
- package/src/templates/project/basic/config/StartupConfigValidator.ts.tpl +151 -0
- package/src/templates/project/basic/config/app.ts.tpl +84 -15
- package/src/templates/project/basic/config/broadcast.ts.tpl +97 -0
- package/src/templates/project/basic/config/cache.ts.tpl +19 -23
- package/src/templates/project/basic/config/cloudflare.ts.tpl +57 -0
- package/src/templates/project/basic/config/env.ts.tpl +7 -1
- package/src/templates/project/basic/config/index.ts.tpl +3 -0
- package/src/templates/project/basic/config/logger.ts.tpl +301 -11
- package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +121 -0
- package/src/templates/project/basic/config/logging/KvLogger.ts.tpl +181 -0
- package/src/templates/project/basic/config/logging/SlackLogger.ts.tpl +156 -0
- package/src/templates/project/basic/config/mail.ts.tpl +141 -0
- package/src/templates/project/basic/config/middleware.ts.tpl +27 -0
- package/src/templates/project/basic/config/notification.ts.tpl +86 -0
- package/src/templates/project/basic/config/security.ts.tpl +4 -5
- package/src/templates/project/basic/config/startup.ts.tpl +27 -0
- package/src/templates/project/basic/config/storage.ts.tpl +77 -42
- package/src/templates/project/basic/database/migrations/index.ts.tpl +1 -1
- package/src/templates/project/basic/package.json.tpl +1 -1
- package/src/templates/project/basic/routes/api.ts.tpl +9 -37
- package/src/templates/project/basic/routes/broadcast.ts.tpl +32 -0
- package/src/templates/project/basic/routes/health.ts.tpl +134 -0
- package/src/templates/project/basic/src/index.ts.tpl +38 -11
- package/src/templates/project/basic/template.json +3 -0
- package/src/toolkit/Secrets/EnvFile.d.ts +15 -0
- package/src/toolkit/Secrets/EnvFile.d.ts.map +1 -0
- package/src/toolkit/Secrets/EnvFile.js +63 -0
- package/src/toolkit/Secrets/Manifest.d.ts +24 -0
- package/src/toolkit/Secrets/Manifest.d.ts.map +1 -0
- package/src/toolkit/Secrets/Manifest.js +71 -0
- package/src/toolkit/Secrets/index.d.ts +42 -0
- package/src/toolkit/Secrets/index.d.ts.map +1 -0
- package/src/toolkit/Secrets/index.js +119 -0
- package/src/toolkit/Secrets/providers/AwsSecretsManager.d.ts +14 -0
- package/src/toolkit/Secrets/providers/AwsSecretsManager.d.ts.map +1 -0
- package/src/toolkit/Secrets/providers/AwsSecretsManager.js +131 -0
- package/src/toolkit/Secrets/providers/CloudflareKv.d.ts +9 -0
- package/src/toolkit/Secrets/providers/CloudflareKv.d.ts.map +1 -0
- package/src/toolkit/Secrets/providers/CloudflareKv.js +73 -0
- package/src/tools/broadcast/Broadcast.d.ts +7 -0
- package/src/tools/broadcast/Broadcast.d.ts.map +1 -0
- package/src/tools/broadcast/Broadcast.js +37 -0
- package/src/tools/broadcast/drivers/BaseDriver.d.ts +5 -0
- package/src/tools/broadcast/drivers/BaseDriver.d.ts.map +1 -0
- package/src/tools/broadcast/drivers/BaseDriver.js +8 -0
- package/src/tools/broadcast/drivers/InMemory.d.ts +18 -0
- package/src/tools/broadcast/drivers/InMemory.d.ts.map +1 -0
- package/src/tools/broadcast/drivers/InMemory.js +16 -0
- package/src/tools/broadcast/drivers/Pusher.d.ts +8 -0
- package/src/tools/broadcast/drivers/Pusher.d.ts.map +1 -0
- package/src/tools/broadcast/drivers/Pusher.js +75 -0
- package/src/tools/broadcast/drivers/Redis.d.ts +19 -0
- package/src/tools/broadcast/drivers/Redis.d.ts.map +1 -0
- package/src/tools/broadcast/drivers/Redis.js +73 -0
- package/src/tools/broadcast/drivers/RedisHttps.d.ts +14 -0
- package/src/tools/broadcast/drivers/RedisHttps.d.ts.map +1 -0
- package/src/tools/broadcast/drivers/RedisHttps.js +50 -0
- package/src/tools/broadcast/index.d.ts +7 -0
- package/src/tools/broadcast/index.d.ts.map +1 -0
- package/src/tools/broadcast/index.js +6 -0
- package/src/tools/http/Http.d.ts +51 -0
- package/src/tools/http/Http.d.ts.map +1 -0
- package/src/tools/http/Http.js +171 -0
- package/src/tools/http/HttpResponse.d.ts +32 -0
- package/src/tools/http/HttpResponse.d.ts.map +1 -0
- package/src/tools/http/HttpResponse.js +80 -0
- package/src/tools/http/index.d.ts +15 -0
- package/src/tools/http/index.d.ts.map +1 -0
- package/src/tools/http/index.js +9 -0
- package/src/tools/mail/Mail.d.ts +22 -0
- package/src/tools/mail/Mail.d.ts.map +1 -0
- package/src/tools/mail/Mail.js +105 -0
- package/src/tools/mail/attachments.d.ts +23 -0
- package/src/tools/mail/attachments.d.ts.map +1 -0
- package/src/tools/mail/attachments.js +26 -0
- package/src/tools/mail/drivers/BaseDriver.d.ts +5 -0
- package/src/tools/mail/drivers/BaseDriver.d.ts.map +1 -0
- package/src/tools/mail/drivers/BaseDriver.js +8 -0
- package/src/tools/mail/drivers/Mailgun.d.ts +31 -0
- package/src/tools/mail/drivers/Mailgun.d.ts.map +1 -0
- package/src/tools/mail/drivers/Mailgun.js +81 -0
- package/src/tools/mail/drivers/SendGrid.d.ts +29 -0
- package/src/tools/mail/drivers/SendGrid.d.ts.map +1 -0
- package/src/tools/mail/drivers/SendGrid.js +57 -0
- package/src/tools/mail/drivers/Ses.d.ts +24 -0
- package/src/tools/mail/drivers/Ses.d.ts.map +1 -0
- package/src/tools/mail/drivers/Ses.js +116 -0
- package/src/tools/mail/drivers/Smtp.d.ts +38 -0
- package/src/tools/mail/drivers/Smtp.d.ts.map +1 -0
- package/src/tools/mail/drivers/Smtp.js +327 -0
- package/src/tools/mail/templates/index.d.ts +27 -0
- package/src/tools/mail/templates/index.d.ts.map +1 -0
- package/src/tools/mail/templates/index.js +35 -0
- package/src/tools/mail/templates/markdown/index.d.ts +17 -0
- package/src/tools/mail/templates/markdown/index.d.ts.map +1 -0
- package/src/tools/mail/templates/markdown/index.js +49 -0
- package/src/tools/mail/templates/markdown/registry.d.ts +15 -0
- package/src/tools/mail/templates/markdown/registry.d.ts.map +1 -0
- package/src/tools/mail/templates/markdown/registry.js +34 -0
- package/src/tools/mail/templates/markdown/validator.d.ts +16 -0
- package/src/tools/mail/templates/markdown/validator.d.ts.map +1 -0
- package/src/tools/mail/templates/markdown/validator.js +24 -0
- package/src/tools/mail/testing.d.ts +41 -0
- package/src/tools/mail/testing.d.ts.map +1 -0
- package/src/tools/mail/testing.js +34 -0
- package/src/tools/notification/Driver.d.ts +11 -0
- package/src/tools/notification/Driver.d.ts.map +1 -0
- package/src/tools/notification/Driver.js +1 -0
- package/src/tools/notification/Notification.d.ts +11 -0
- package/src/tools/notification/Notification.d.ts.map +1 -0
- package/src/tools/notification/Notification.js +11 -0
- package/src/tools/notification/Registry.d.ts +10 -0
- package/src/tools/notification/Registry.d.ts.map +1 -0
- package/src/tools/notification/Registry.js +22 -0
- package/src/tools/notification/Service.d.ts +6 -0
- package/src/tools/notification/Service.d.ts.map +1 -0
- package/src/tools/notification/Service.js +18 -0
- package/src/tools/notification/config.d.ts +5 -0
- package/src/tools/notification/config.d.ts.map +1 -0
- package/src/tools/notification/config.js +5 -0
- package/src/tools/notification/drivers/BaseDriver.d.ts +5 -0
- package/src/tools/notification/drivers/BaseDriver.d.ts.map +1 -0
- package/src/tools/notification/drivers/BaseDriver.js +8 -0
- package/src/tools/notification/drivers/Console.d.ts +7 -0
- package/src/tools/notification/drivers/Console.d.ts.map +1 -0
- package/src/tools/notification/drivers/Console.js +13 -0
- package/src/tools/notification/drivers/Slack.d.ts +16 -0
- package/src/tools/notification/drivers/Slack.d.ts.map +1 -0
- package/src/tools/notification/drivers/Slack.js +24 -0
- package/src/tools/notification/drivers/Termii.d.ts +10 -0
- package/src/tools/notification/drivers/Termii.d.ts.map +1 -0
- package/src/tools/notification/drivers/Termii.js +47 -0
- package/src/tools/notification/drivers/Twilio.d.ts +21 -0
- package/src/tools/notification/drivers/Twilio.d.ts.map +1 -0
- package/src/tools/notification/drivers/Twilio.js +48 -0
- package/src/tools/notification/templates/markdown/index.d.ts +15 -0
- package/src/tools/notification/templates/markdown/index.d.ts.map +1 -0
- package/src/tools/notification/templates/markdown/index.js +38 -0
- package/src/tools/notification/templates/markdown/registry.d.ts +15 -0
- package/src/tools/notification/templates/markdown/registry.d.ts.map +1 -0
- package/src/tools/notification/templates/markdown/registry.js +36 -0
- package/src/tools/notification/testing.d.ts +19 -0
- package/src/tools/notification/testing.d.ts.map +1 -0
- package/src/tools/notification/testing.js +35 -0
- package/src/tools/notification/testingHelpers.d.ts +12 -0
- package/src/tools/notification/testingHelpers.d.ts.map +1 -0
- package/src/tools/notification/testingHelpers.js +32 -0
- package/src/tools/queue/Queue.d.ts +23 -0
- package/src/tools/queue/Queue.d.ts.map +1 -0
- package/src/tools/queue/Queue.js +38 -0
- package/src/tools/queue/drivers/InMemory.d.ts +10 -0
- package/src/tools/queue/drivers/InMemory.d.ts.map +1 -0
- package/src/tools/queue/drivers/InMemory.js +55 -0
- package/src/tools/queue/drivers/Redis.d.ts +10 -0
- package/src/tools/queue/drivers/Redis.d.ts.map +1 -0
- package/src/tools/queue/drivers/Redis.js +91 -0
- package/src/tools/storage/drivers/Gcs.d.ts +20 -0
- package/src/tools/storage/drivers/Gcs.d.ts.map +1 -0
- package/src/tools/storage/drivers/Gcs.js +152 -0
- package/src/tools/storage/drivers/Local.d.ts +17 -0
- package/src/tools/storage/drivers/Local.d.ts.map +1 -0
- package/src/tools/storage/drivers/Local.js +63 -0
- package/src/tools/storage/drivers/R2.d.ts +20 -0
- package/src/tools/storage/drivers/R2.d.ts.map +1 -0
- package/src/tools/storage/drivers/R2.js +73 -0
- package/src/tools/storage/drivers/S3.d.ts +26 -0
- package/src/tools/storage/drivers/S3.d.ts.map +1 -0
- package/src/tools/storage/drivers/S3.js +258 -0
- package/src/tools/storage/index.d.ts +24 -0
- package/src/tools/storage/index.d.ts.map +1 -0
- package/src/tools/storage/index.js +112 -0
- package/src/tools/storage/testing.d.ts +23 -0
- package/src/tools/storage/testing.d.ts.map +1 -0
- package/src/tools/storage/testing.js +52 -0
- package/src/tools/templates/MarkdownRenderer.d.ts +14 -0
- package/src/tools/templates/MarkdownRenderer.d.ts.map +1 -0
- package/src/tools/templates/MarkdownRenderer.js +300 -0
- package/src/tools/templates/index.d.ts +5 -0
- package/src/tools/templates/index.d.ts.map +1 -0
- 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 '@
|
|
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:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
98
|
+
environment: normalizeMode(),
|
|
39
99
|
|
|
40
100
|
/**
|
|
41
101
|
* Application port
|
|
42
102
|
*/
|
|
43
|
-
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:
|
|
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:
|
|
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:
|
|
148
|
+
timezone: readEnvString('APP_TIMEZONE', 'UTC'),
|
|
80
149
|
|
|
81
150
|
/**
|
|
82
151
|
* Request timeout (milliseconds)
|
|
83
152
|
*/
|
|
84
|
-
requestTimeout:
|
|
153
|
+
requestTimeout: readEnvInt('REQUEST_TIMEOUT', 30000),
|
|
85
154
|
|
|
86
155
|
/**
|
|
87
156
|
* Max request body size
|
|
88
157
|
*/
|
|
89
|
-
maxBodySize:
|
|
158
|
+
maxBodySize: readEnvString('MAX_BODY_SIZE', '10mb'),
|
|
90
159
|
|
|
91
160
|
getSafeEnv,
|
|
92
161
|
} as const;
|