@zintrust/core 0.1.1 → 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 +3 -3
- package/bin/zintrust.d.ts.map +1 -1
- package/bin/zintrust.js +18 -1
- package/package.json +1 -1
- 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 +6 -4
- package/src/cache/drivers/KVDriver.d.ts.map +1 -1
- package/src/cache/drivers/KVDriver.js +6 -6
- 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 +11 -4
- package/src/cli/commands/AddCommand.js +1 -1
- package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
- package/src/cli/commands/ConfigCommand.js +34 -4
- 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 +4 -3
- package/src/cli/commands/FixCommand.d.ts.map +1 -1
- package/src/cli/commands/FixCommand.js +3 -16
- 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 +1 -1
- 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/NewCommand.d.ts +4 -0
- package/src/cli/commands/NewCommand.d.ts.map +1 -1
- package/src/cli/commands/NewCommand.js +33 -20
- 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 +11 -20
- 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.js +1 -1
- package/src/cli/scaffolding/FeatureScaffolder.js +4 -4
- package/src/cli/scaffolding/FileGenerator.js +1 -1
- package/src/cli/scaffolding/ModelGenerator.js +1 -1
- 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 +3 -2
- package/src/cli/scaffolding/RouteGenerator.js +1 -1
- package/src/cli/scaffolding/ServiceIntegrationTestGenerator.js +1 -1
- package/src/cli/scaffolding/ServiceScaffolder.js +2 -2
- 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 +37 -11
- 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/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/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/MicroserviceManager.d.ts.map +1 -1
- package/src/microservices/MicroserviceManager.js +9 -6
- package/src/microservices/PostgresAdapter.d.ts.map +1 -1
- package/src/microservices/PostgresAdapter.js +3 -1
- package/src/microservices/ServiceBundler.d.ts.map +1 -1
- package/src/microservices/ServiceBundler.js +6 -4
- package/src/microservices/ServiceHealthMonitor.js +2 -2
- 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/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 +150 -75
- 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 -6
- package/src/runtime/adapters/CloudflareAdapter.js +2 -2
- package/src/runtime/adapters/FargateAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/FargateAdapter.js +2 -1
- 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 +2 -1
- 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 +44 -21
- 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
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
import { UserController } from '@app/Controllers/UserController';
|
|
7
7
|
import { Env } from '@config/env';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { registerBroadcastRoutes } from '@routes/broadcast';
|
|
9
|
+
import { registerHealthRoutes } from '@routes/health';
|
|
10
|
+
import { type IRouter, Router } from '@routing/Router';
|
|
10
11
|
|
|
11
12
|
export function registerRoutes(router: IRouter): void {
|
|
12
13
|
const userController = UserController.create();
|
|
@@ -19,6 +20,12 @@ export function registerRoutes(router: IRouter): void {
|
|
|
19
20
|
* Register public routes
|
|
20
21
|
*/
|
|
21
22
|
function registerPublicRoutes(router: IRouter): void {
|
|
23
|
+
registerRootRoute(router);
|
|
24
|
+
registerHealthRoutes(router);
|
|
25
|
+
registerBroadcastRoutes(router);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function registerRootRoute(router: IRouter): void {
|
|
22
29
|
Router.get(router, '/', async (_req, res) => {
|
|
23
30
|
res.json({
|
|
24
31
|
framework: 'Zintrust Framework',
|
|
@@ -28,41 +35,6 @@ function registerPublicRoutes(router: IRouter): void {
|
|
|
28
35
|
database: Env.DB_CONNECTION ?? 'sqlite',
|
|
29
36
|
});
|
|
30
37
|
});
|
|
31
|
-
|
|
32
|
-
Router.get(router, '/health', async (_req, res) => {
|
|
33
|
-
try {
|
|
34
|
-
const db = useDatabase();
|
|
35
|
-
await db.query('SELECT 1');
|
|
36
|
-
|
|
37
|
-
const uptime =
|
|
38
|
-
typeof process !== 'undefined' && typeof process.uptime === 'function'
|
|
39
|
-
? process.uptime()
|
|
40
|
-
: 0;
|
|
41
|
-
|
|
42
|
-
res.json({
|
|
43
|
-
status: 'healthy',
|
|
44
|
-
timestamp: new Date().toISOString(),
|
|
45
|
-
uptime,
|
|
46
|
-
database: 'connected',
|
|
47
|
-
environment: Env.NODE_ENV ?? 'development',
|
|
48
|
-
});
|
|
49
|
-
} catch (error) {
|
|
50
|
-
Logger.error('Health check failed:', error);
|
|
51
|
-
|
|
52
|
-
const isProd =
|
|
53
|
-
typeof process !== 'undefined' &&
|
|
54
|
-
typeof process.env === 'object' &&
|
|
55
|
-
process.env !== null &&
|
|
56
|
-
process.env['NODE_ENV'] === 'production';
|
|
57
|
-
|
|
58
|
-
res.setStatus(503).json({
|
|
59
|
-
status: 'unhealthy',
|
|
60
|
-
timestamp: new Date().toISOString(),
|
|
61
|
-
database: 'disconnected',
|
|
62
|
-
error: isProd ? 'Service unavailable' : (error as Error).message,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
38
|
}
|
|
67
39
|
|
|
68
40
|
/**
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Broadcast Routes
|
|
3
|
+
*
|
|
4
|
+
* Runtime-only endpoints for broadcast.
|
|
5
|
+
* Provider setup and secret provisioning remain CLI-only.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { type IRouter, Router } from '@routing/Router';
|
|
9
|
+
|
|
10
|
+
export function registerBroadcastRoutes(router: IRouter): void {
|
|
11
|
+
Router.get(router, '/broadcast/health', async (_req, res) => {
|
|
12
|
+
res.json({ ok: true });
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
Router.post(router, '/broadcast/send', async (req: { body?: unknown }, res) => {
|
|
16
|
+
const body = (req.body ?? {}) as Record<string, unknown>;
|
|
17
|
+
const channel = typeof body['channel'] === 'string' ? body['channel'] : '';
|
|
18
|
+
const event = typeof body['event'] === 'string' ? body['event'] : '';
|
|
19
|
+
const data = body['data'];
|
|
20
|
+
|
|
21
|
+
if (!channel || !event) {
|
|
22
|
+
res
|
|
23
|
+
.setStatus(400)
|
|
24
|
+
.json({ ok: false, error: 'Invalid payload: channel and event are required' });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const { Broadcast } = await import('@broadcast/Broadcast');
|
|
29
|
+
const result = await Broadcast.send(channel, event, data);
|
|
30
|
+
res.json({ ok: true, result });
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health Routes
|
|
3
|
+
* Provides health, liveness, and readiness endpoints.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { appConfig } from '@/config';
|
|
7
|
+
import { RuntimeHealthProbes } from '@/health/RuntimeHealthProbes';
|
|
8
|
+
import { Env } from '@config/env';
|
|
9
|
+
import { Logger } from '@config/logger';
|
|
10
|
+
import { useDatabase } from '@orm/Database';
|
|
11
|
+
import { QueryBuilder } from '@orm/QueryBuilder';
|
|
12
|
+
import { type IRouter, Router } from '@routing/Router';
|
|
13
|
+
|
|
14
|
+
export function registerHealthRoutes(router: IRouter): void {
|
|
15
|
+
registerHealthRoute(router);
|
|
16
|
+
registerHealthLiveRoute(router);
|
|
17
|
+
registerHealthReadyRoute(router);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function registerHealthRoute(router: IRouter): void {
|
|
21
|
+
Router.get(router, '/health', async (_req, res) => {
|
|
22
|
+
const environment = Env.NODE_ENV ?? 'development';
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const db = useDatabase();
|
|
26
|
+
await QueryBuilder.ping(db);
|
|
27
|
+
|
|
28
|
+
const uptime =
|
|
29
|
+
typeof process !== 'undefined' && typeof process.uptime === 'function'
|
|
30
|
+
? process.uptime()
|
|
31
|
+
: 0;
|
|
32
|
+
|
|
33
|
+
res.json({
|
|
34
|
+
status: 'healthy',
|
|
35
|
+
timestamp: new Date().toISOString(),
|
|
36
|
+
uptime,
|
|
37
|
+
database: 'connected',
|
|
38
|
+
environment,
|
|
39
|
+
});
|
|
40
|
+
} catch (error) {
|
|
41
|
+
Logger.error('Health check failed:', error);
|
|
42
|
+
|
|
43
|
+
const isProd = environment === 'production' || environment === 'prod';
|
|
44
|
+
|
|
45
|
+
res.setStatus(503).json({
|
|
46
|
+
status: 'unhealthy',
|
|
47
|
+
timestamp: new Date().toISOString(),
|
|
48
|
+
database: 'disconnected',
|
|
49
|
+
error: isProd ? 'Service unavailable' : (error as Error).message,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function registerHealthLiveRoute(router: IRouter): void {
|
|
56
|
+
Router.get(router, '/health/live', async (_req, res) => {
|
|
57
|
+
const uptime =
|
|
58
|
+
typeof process !== 'undefined' && typeof process.uptime === 'function' ? process.uptime() : 0;
|
|
59
|
+
|
|
60
|
+
res.json({
|
|
61
|
+
status: 'alive',
|
|
62
|
+
timestamp: new Date().toISOString(),
|
|
63
|
+
uptime,
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function registerHealthReadyRoute(router: IRouter): void {
|
|
69
|
+
Router.get(router, '/health/ready', async (_req, res) => {
|
|
70
|
+
const startTime = Date.now();
|
|
71
|
+
const environment = appConfig.environment;
|
|
72
|
+
|
|
73
|
+
let databaseResponseTime: number | null = null;
|
|
74
|
+
let cacheResponseTime: number | null = null;
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const db = useDatabase();
|
|
78
|
+
await QueryBuilder.ping(db);
|
|
79
|
+
|
|
80
|
+
databaseResponseTime = Date.now() - startTime;
|
|
81
|
+
|
|
82
|
+
// Only probe KV at runtime when explicitly configured.
|
|
83
|
+
cacheResponseTime = await RuntimeHealthProbes.pingKvCache(2000);
|
|
84
|
+
|
|
85
|
+
res.json({
|
|
86
|
+
status: 'ready',
|
|
87
|
+
timestamp: new Date().toISOString(),
|
|
88
|
+
environment,
|
|
89
|
+
dependencies: {
|
|
90
|
+
database: {
|
|
91
|
+
status: 'ready',
|
|
92
|
+
responseTime: databaseResponseTime,
|
|
93
|
+
},
|
|
94
|
+
...(cacheResponseTime === null
|
|
95
|
+
? {}
|
|
96
|
+
: {
|
|
97
|
+
cache: {
|
|
98
|
+
status: 'ready',
|
|
99
|
+
responseTime: cacheResponseTime,
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
} catch (error) {
|
|
105
|
+
Logger.error('Readiness check failed:', error);
|
|
106
|
+
|
|
107
|
+
const isProd = environment === 'production';
|
|
108
|
+
|
|
109
|
+
const responseTime = Date.now() - startTime;
|
|
110
|
+
|
|
111
|
+
const dependencies: Record<string, unknown> = {
|
|
112
|
+
database: {
|
|
113
|
+
status: databaseResponseTime === null ? 'unavailable' : 'ready',
|
|
114
|
+
responseTime: databaseResponseTime ?? responseTime,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
if (RuntimeHealthProbes.getCacheDriverName() === 'kv') {
|
|
119
|
+
dependencies['cache'] = {
|
|
120
|
+
status: 'unavailable',
|
|
121
|
+
responseTime: cacheResponseTime ?? responseTime,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
res.setStatus(503).json({
|
|
126
|
+
status: 'not_ready',
|
|
127
|
+
timestamp: new Date().toISOString(),
|
|
128
|
+
environment,
|
|
129
|
+
dependencies,
|
|
130
|
+
error: isProd ? 'Service unavailable' : (error as Error).message,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
@@ -28,22 +28,49 @@ async function start() {
|
|
|
28
28
|
await server.listen();
|
|
29
29
|
|
|
30
30
|
Logger.info(`Server running at http://${host}:${port}`);
|
|
31
|
+
|
|
32
|
+
const shutdown = async (signal: string): Promise<void> => {
|
|
33
|
+
Logger.info(`${signal} received, shutting down gracefully...`);
|
|
34
|
+
|
|
35
|
+
const timeoutMs = Env.getInt('SHUTDOWN_TIMEOUT', 10000);
|
|
36
|
+
const withTimeout = async <T>(promise: Promise<T>, ms: number): Promise<T> => {
|
|
37
|
+
if (ms <= 0) return promise;
|
|
38
|
+
return new Promise<T>((resolve, reject) => {
|
|
39
|
+
const timer = setTimeout(() => reject(new globalThis.Error('Shutdown timed out')), ms);
|
|
40
|
+
promise
|
|
41
|
+
.then((value) => {
|
|
42
|
+
clearTimeout(timer);
|
|
43
|
+
resolve(value);
|
|
44
|
+
})
|
|
45
|
+
.catch((err) => {
|
|
46
|
+
clearTimeout(timer);
|
|
47
|
+
reject(err);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
await withTimeout(
|
|
54
|
+
(async () => {
|
|
55
|
+
await server.close();
|
|
56
|
+
await app.shutdown();
|
|
57
|
+
})(),
|
|
58
|
+
timeoutMs
|
|
59
|
+
);
|
|
60
|
+
process.exit(0);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
Logger.error('Graceful shutdown failed:', error);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
process.on('SIGTERM', () => void shutdown('SIGTERM'));
|
|
68
|
+
process.on('SIGINT', () => void shutdown('SIGINT'));
|
|
31
69
|
} catch (error) {
|
|
32
70
|
Logger.error('Failed to start application:', error);
|
|
33
71
|
process.exit(1);
|
|
34
72
|
}
|
|
35
73
|
}
|
|
36
74
|
|
|
37
|
-
// Handle graceful shutdown
|
|
38
|
-
process.on('SIGTERM', () => {
|
|
39
|
-
Logger.info('SIGTERM received, shutting down gracefully...');
|
|
40
|
-
process.exit(0);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
process.on('SIGINT', () => {
|
|
44
|
-
Logger.info('SIGINT received, shutting down gracefully...');
|
|
45
|
-
process.exit(0);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
75
|
// Run start
|
|
49
76
|
await start();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type EnvFileWriteMode = 'overwrite';
|
|
2
|
+
export declare const EnvFile: Readonly<{
|
|
3
|
+
read(params: {
|
|
4
|
+
cwd: string;
|
|
5
|
+
path: string;
|
|
6
|
+
}): Promise<Record<string, string>>;
|
|
7
|
+
write(params: {
|
|
8
|
+
cwd: string;
|
|
9
|
+
path: string;
|
|
10
|
+
values: Record<string, string>;
|
|
11
|
+
mode: EnvFileWriteMode;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
}>;
|
|
14
|
+
export default EnvFile;
|
|
15
|
+
//# sourceMappingURL=EnvFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvFile.d.ts","sourceRoot":"","sources":["../../../../src/toolkit/Secrets/EnvFile.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAmC3C,eAAO,MAAM,OAAO;iBACC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;kBAgB9D;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,IAAI,EAAE,gBAAgB,CAAC;KACxB,GAAG,OAAO,CAAC,IAAI,CAAC;EAgBjB,CAAC;AAEH,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ErrorFactory } from '../../exceptions/ZintrustError';
|
|
2
|
+
import { fsPromises as fs } from '../../node-singletons/fs';
|
|
3
|
+
import * as path from '../../node-singletons/path';
|
|
4
|
+
const isValidKey = (key) => /^[A-Z0-9_]+$/.test(key);
|
|
5
|
+
const parseEnvLine = (line) => {
|
|
6
|
+
const trimmed = line.trim();
|
|
7
|
+
if (trimmed === '' || trimmed.startsWith('#'))
|
|
8
|
+
return null;
|
|
9
|
+
const eq = trimmed.indexOf('=');
|
|
10
|
+
if (eq <= 0)
|
|
11
|
+
return null;
|
|
12
|
+
const key = trimmed.slice(0, eq).trim();
|
|
13
|
+
const raw = trimmed.slice(eq + 1);
|
|
14
|
+
if (!isValidKey(key))
|
|
15
|
+
return null;
|
|
16
|
+
// Preserve value verbatim (except strip surrounding quotes if present)
|
|
17
|
+
let value = raw;
|
|
18
|
+
const v = raw.trim();
|
|
19
|
+
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) {
|
|
20
|
+
value = v.slice(1, -1);
|
|
21
|
+
}
|
|
22
|
+
return { key, value };
|
|
23
|
+
};
|
|
24
|
+
const serializeEnv = (values) => {
|
|
25
|
+
const keys = Object.keys(values).sort((a, b) => a.localeCompare(b));
|
|
26
|
+
const lines = keys.map((key) => {
|
|
27
|
+
const value = values[key] ?? '';
|
|
28
|
+
// Write as JSON string to safely quote newlines, #, etc.
|
|
29
|
+
return `${key}=${JSON.stringify(value)}`;
|
|
30
|
+
});
|
|
31
|
+
return `${lines.join('\n')}\n`;
|
|
32
|
+
};
|
|
33
|
+
export const EnvFile = Object.freeze({
|
|
34
|
+
async read(params) {
|
|
35
|
+
const filePath = path.resolve(params.cwd, params.path);
|
|
36
|
+
try {
|
|
37
|
+
const raw = await fs.readFile(filePath, 'utf-8');
|
|
38
|
+
const result = {};
|
|
39
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
40
|
+
const parsed = parseEnvLine(line);
|
|
41
|
+
if (parsed)
|
|
42
|
+
result[parsed.key] = parsed.value;
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
async write(params) {
|
|
51
|
+
const filePath = path.resolve(params.cwd, params.path);
|
|
52
|
+
for (const key of Object.keys(params.values)) {
|
|
53
|
+
if (!isValidKey(key)) {
|
|
54
|
+
throw ErrorFactory.createCliError(`Invalid env key: ${key}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const content = serializeEnv(params.values);
|
|
58
|
+
// Ensure parent dir exists for cases like ./.zintrust/.env.pull
|
|
59
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
60
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
export default EnvFile;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type SecretsProviderName = 'aws' | 'cloudflare';
|
|
2
|
+
export type ManifestKeySpec = {
|
|
3
|
+
aws?: {
|
|
4
|
+
secretId: string;
|
|
5
|
+
jsonKey?: string;
|
|
6
|
+
};
|
|
7
|
+
cloudflare?: {
|
|
8
|
+
key: string;
|
|
9
|
+
namespaceId?: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export type SecretsManifest = {
|
|
13
|
+
provider: SecretsProviderName;
|
|
14
|
+
keys: Record<string, ManifestKeySpec>;
|
|
15
|
+
};
|
|
16
|
+
export declare const Manifest: Readonly<{
|
|
17
|
+
load(params: {
|
|
18
|
+
cwd: string;
|
|
19
|
+
path: string;
|
|
20
|
+
provider: SecretsProviderName;
|
|
21
|
+
}): Promise<SecretsManifest>;
|
|
22
|
+
}>;
|
|
23
|
+
export default Manifest;
|
|
24
|
+
//# sourceMappingURL=Manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Manifest.d.ts","sourceRoot":"","sources":["../../../../src/toolkit/Secrets/Manifest.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,mBAAmB,GAAG,KAAK,GAAG,YAAY,CAAC;AAEvD,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,CAAC,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,UAAU,CAAC,EAAE;QACX,GAAG,EAAE,MAAM,CAAC;QACZ,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CACvC,CAAC;AA+DF,eAAO,MAAM,QAAQ;iBACA;QACjB,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,mBAAmB,CAAC;KAC/B,GAAG,OAAO,CAAC,eAAe,CAAC;EA4B5B,CAAC;AAEH,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ErrorFactory } from '../../exceptions/ZintrustError';
|
|
2
|
+
import { fsPromises as fs } from '../../node-singletons/fs';
|
|
3
|
+
import * as path from '../../node-singletons/path';
|
|
4
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
|
+
const assertString = (value, name) => {
|
|
6
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
7
|
+
throw ErrorFactory.createCliError(`Manifest: missing/invalid ${name}`);
|
|
8
|
+
}
|
|
9
|
+
return value;
|
|
10
|
+
};
|
|
11
|
+
const validateKeyName = (key) => {
|
|
12
|
+
if (!/^[A-Z0-9_]+$/.test(key)) {
|
|
13
|
+
throw ErrorFactory.createCliError(`Manifest: invalid env key: ${key}`);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const parseProvider = (parsed, fallback) => {
|
|
17
|
+
const provider = 'provider' in parsed && typeof parsed['provider'] === 'string'
|
|
18
|
+
? parsed['provider']
|
|
19
|
+
: fallback;
|
|
20
|
+
if (provider !== 'aws' && provider !== 'cloudflare') {
|
|
21
|
+
throw ErrorFactory.createCliError('Manifest: provider must be aws|cloudflare');
|
|
22
|
+
}
|
|
23
|
+
return provider;
|
|
24
|
+
};
|
|
25
|
+
const parseKeySpec = (envKey, specUnknown) => {
|
|
26
|
+
const spec = {};
|
|
27
|
+
const awsUnknown = specUnknown['aws'];
|
|
28
|
+
if (isRecord(awsUnknown)) {
|
|
29
|
+
spec.aws = {
|
|
30
|
+
secretId: assertString(awsUnknown['secretId'], `keys.${envKey}.aws.secretId`),
|
|
31
|
+
jsonKey: typeof awsUnknown['jsonKey'] === 'string' && awsUnknown['jsonKey'].trim() !== ''
|
|
32
|
+
? awsUnknown['jsonKey']
|
|
33
|
+
: undefined,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const cloudflareUnknown = specUnknown['cloudflare'];
|
|
37
|
+
if (isRecord(cloudflareUnknown)) {
|
|
38
|
+
spec.cloudflare = {
|
|
39
|
+
key: assertString(cloudflareUnknown['key'], `keys.${envKey}.cloudflare.key`),
|
|
40
|
+
namespaceId: typeof cloudflareUnknown['namespaceId'] === 'string' &&
|
|
41
|
+
cloudflareUnknown['namespaceId'].trim() !== ''
|
|
42
|
+
? cloudflareUnknown['namespaceId']
|
|
43
|
+
: undefined,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return spec;
|
|
47
|
+
};
|
|
48
|
+
export const Manifest = Object.freeze({
|
|
49
|
+
async load(params) {
|
|
50
|
+
const filePath = path.resolve(params.cwd, params.path);
|
|
51
|
+
const raw = await fs.readFile(filePath, 'utf-8');
|
|
52
|
+
const parsedUnknown = JSON.parse(raw);
|
|
53
|
+
if (!isRecord(parsedUnknown)) {
|
|
54
|
+
throw ErrorFactory.createCliError('Manifest: expected JSON object');
|
|
55
|
+
}
|
|
56
|
+
const provider = parseProvider(parsedUnknown, params.provider);
|
|
57
|
+
const keysUnknown = parsedUnknown['keys'];
|
|
58
|
+
if (!isRecord(keysUnknown)) {
|
|
59
|
+
throw ErrorFactory.createCliError('Manifest: keys must be an object');
|
|
60
|
+
}
|
|
61
|
+
const keys = {};
|
|
62
|
+
for (const [envKey, specUnknown] of Object.entries(keysUnknown)) {
|
|
63
|
+
validateKeyName(envKey);
|
|
64
|
+
if (!isRecord(specUnknown))
|
|
65
|
+
throw ErrorFactory.createCliError(`Manifest: key ${envKey} must be an object`);
|
|
66
|
+
keys[envKey] = parseKeySpec(envKey, specUnknown);
|
|
67
|
+
}
|
|
68
|
+
return { provider, keys };
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
export default Manifest;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets Toolkit (Core)
|
|
3
|
+
*
|
|
4
|
+
* Internal framework module intended for CLI usage.
|
|
5
|
+
* It may use Node APIs (via node-singletons) and should not be used by runtime apps.
|
|
6
|
+
*/
|
|
7
|
+
import { type SecretsProviderName } from '../Secrets/Manifest';
|
|
8
|
+
export type { SecretsProviderName } from '../Secrets/Manifest';
|
|
9
|
+
export type PullOptions = {
|
|
10
|
+
cwd: string;
|
|
11
|
+
provider?: SecretsProviderName;
|
|
12
|
+
manifestPath?: string;
|
|
13
|
+
outFile?: string;
|
|
14
|
+
dryRun?: boolean;
|
|
15
|
+
};
|
|
16
|
+
export type PushOptions = {
|
|
17
|
+
cwd: string;
|
|
18
|
+
provider?: SecretsProviderName;
|
|
19
|
+
manifestPath?: string;
|
|
20
|
+
inFile?: string;
|
|
21
|
+
dryRun?: boolean;
|
|
22
|
+
};
|
|
23
|
+
export type DoctorOptions = {
|
|
24
|
+
provider?: SecretsProviderName;
|
|
25
|
+
};
|
|
26
|
+
export declare const SecretsToolkit: Readonly<{
|
|
27
|
+
pull(options: PullOptions): Promise<{
|
|
28
|
+
outFile: string;
|
|
29
|
+
keys: string[];
|
|
30
|
+
}>;
|
|
31
|
+
push(options: PushOptions): Promise<{
|
|
32
|
+
inFile: string;
|
|
33
|
+
keys: string[];
|
|
34
|
+
}>;
|
|
35
|
+
doctor(options: DoctorOptions): {
|
|
36
|
+
provider: SecretsProviderName;
|
|
37
|
+
ok: boolean;
|
|
38
|
+
missing: string[];
|
|
39
|
+
};
|
|
40
|
+
}>;
|
|
41
|
+
export default SecretsToolkit;
|
|
42
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/toolkit/Secrets/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAY,KAAK,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAI/E,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,EAAE,mBAAmB,CAAC;CAChC,CAAC;AA0GF,eAAO,MAAM,cAAc;kBACL,WAAW,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;kBAkB1D,WAAW,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;oBAoB7D,aAAa,GAAG;QAC9B,QAAQ,EAAE,mBAAmB,CAAC;QAC9B,EAAE,EAAE,OAAO,CAAC;QACZ,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB;EASD,CAAC;AAEH,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets Toolkit (Core)
|
|
3
|
+
*
|
|
4
|
+
* Internal framework module intended for CLI usage.
|
|
5
|
+
* It may use Node APIs (via node-singletons) and should not be used by runtime apps.
|
|
6
|
+
*/
|
|
7
|
+
import { ErrorFactory } from '../../exceptions/ZintrustError';
|
|
8
|
+
import { EnvFile } from '../Secrets/EnvFile';
|
|
9
|
+
import { Manifest } from '../Secrets/Manifest';
|
|
10
|
+
import { AwsSecretsManager } from '../Secrets/providers/AwsSecretsManager';
|
|
11
|
+
import { CloudflareKv } from '../Secrets/providers/CloudflareKv';
|
|
12
|
+
const resolveProvider = (provider) => {
|
|
13
|
+
if (provider === 'aws' || provider === 'cloudflare')
|
|
14
|
+
return provider;
|
|
15
|
+
throw ErrorFactory.createCliError('Missing/invalid provider. Use --provider aws|cloudflare or set ZINTRUST_SECRETS_PROVIDER.');
|
|
16
|
+
};
|
|
17
|
+
const resolveOutFile = (outFile) => outFile ?? process.env['ZINTRUST_ENV_FILE'] ?? '.env.pull';
|
|
18
|
+
const resolveManifestPath = (manifestPath) => manifestPath ?? process.env['ZINTRUST_SECRETS_MANIFEST'] ?? 'secrets.manifest.json';
|
|
19
|
+
const resolveInFile = (inFile) => inFile ?? process.env['ZINTRUST_ENV_IN_FILE'] ?? '.env';
|
|
20
|
+
const pullAws = async (manifest) => {
|
|
21
|
+
const client = AwsSecretsManager.createFromEnv();
|
|
22
|
+
const entries = Object.entries(manifest.keys).filter(([, spec]) => spec.aws !== undefined);
|
|
23
|
+
const pairs = await Promise.all(entries.map(async ([envKey, spec]) => {
|
|
24
|
+
const aws = spec.aws;
|
|
25
|
+
if (aws === undefined)
|
|
26
|
+
return null;
|
|
27
|
+
const value = await client.getValue(aws.secretId, aws.jsonKey);
|
|
28
|
+
return value === null ? null : [envKey, value];
|
|
29
|
+
}));
|
|
30
|
+
const resolved = {};
|
|
31
|
+
for (const pair of pairs) {
|
|
32
|
+
if (pair)
|
|
33
|
+
resolved[pair[0]] = pair[1];
|
|
34
|
+
}
|
|
35
|
+
return resolved;
|
|
36
|
+
};
|
|
37
|
+
const pullCloudflare = async (manifest) => {
|
|
38
|
+
const client = CloudflareKv.createFromEnv();
|
|
39
|
+
const entries = Object.entries(manifest.keys).filter(([, spec]) => spec.cloudflare !== undefined);
|
|
40
|
+
const pairs = await Promise.all(entries.map(async ([envKey, spec]) => {
|
|
41
|
+
const cf = spec.cloudflare;
|
|
42
|
+
if (cf === undefined)
|
|
43
|
+
return null;
|
|
44
|
+
const value = await client.getValue(cf.key, cf.namespaceId);
|
|
45
|
+
return value === null ? null : [envKey, value];
|
|
46
|
+
}));
|
|
47
|
+
const resolved = {};
|
|
48
|
+
for (const pair of pairs) {
|
|
49
|
+
if (pair)
|
|
50
|
+
resolved[pair[0]] = pair[1];
|
|
51
|
+
}
|
|
52
|
+
return resolved;
|
|
53
|
+
};
|
|
54
|
+
const pushAws = async (manifest, env, dryRun) => {
|
|
55
|
+
const client = AwsSecretsManager.createFromEnv();
|
|
56
|
+
const entries = Object.entries(manifest.keys).filter(([, spec]) => spec.aws !== undefined);
|
|
57
|
+
const pushed = await Promise.all(entries.map(async ([envKey, spec]) => {
|
|
58
|
+
const aws = spec.aws;
|
|
59
|
+
if (aws === undefined)
|
|
60
|
+
return null;
|
|
61
|
+
const value = env[envKey];
|
|
62
|
+
if (typeof value !== 'string')
|
|
63
|
+
return null;
|
|
64
|
+
if (!dryRun)
|
|
65
|
+
await client.putValue(aws.secretId, value);
|
|
66
|
+
return envKey;
|
|
67
|
+
}));
|
|
68
|
+
return pushed.filter((k) => typeof k === 'string');
|
|
69
|
+
};
|
|
70
|
+
const pushCloudflare = async (manifest, env, dryRun) => {
|
|
71
|
+
const client = CloudflareKv.createFromEnv();
|
|
72
|
+
const entries = Object.entries(manifest.keys).filter(([, spec]) => spec.cloudflare !== undefined);
|
|
73
|
+
const pushed = await Promise.all(entries.map(async ([envKey, spec]) => {
|
|
74
|
+
const cf = spec.cloudflare;
|
|
75
|
+
if (cf === undefined)
|
|
76
|
+
return null;
|
|
77
|
+
const value = env[envKey];
|
|
78
|
+
if (typeof value !== 'string')
|
|
79
|
+
return null;
|
|
80
|
+
if (!dryRun)
|
|
81
|
+
await client.putValue(cf.key, value, cf.namespaceId);
|
|
82
|
+
return envKey;
|
|
83
|
+
}));
|
|
84
|
+
return pushed.filter((k) => typeof k === 'string');
|
|
85
|
+
};
|
|
86
|
+
export const SecretsToolkit = Object.freeze({
|
|
87
|
+
async pull(options) {
|
|
88
|
+
const provider = resolveProvider(options.provider ??
|
|
89
|
+
process.env['ZINTRUST_SECRETS_PROVIDER']);
|
|
90
|
+
const outFile = resolveOutFile(options.outFile);
|
|
91
|
+
const manifestPath = resolveManifestPath(options.manifestPath);
|
|
92
|
+
const manifest = await Manifest.load({ cwd: options.cwd, path: manifestPath, provider });
|
|
93
|
+
const resolved = provider === 'aws' ? await pullAws(manifest) : await pullCloudflare(manifest);
|
|
94
|
+
if (options.dryRun === true)
|
|
95
|
+
return { outFile, keys: Object.keys(resolved) };
|
|
96
|
+
await EnvFile.write({ cwd: options.cwd, path: outFile, values: resolved, mode: 'overwrite' });
|
|
97
|
+
return { outFile, keys: Object.keys(resolved) };
|
|
98
|
+
},
|
|
99
|
+
async push(options) {
|
|
100
|
+
const provider = resolveProvider(options.provider ??
|
|
101
|
+
process.env['ZINTRUST_SECRETS_PROVIDER']);
|
|
102
|
+
const inFile = resolveInFile(options.inFile);
|
|
103
|
+
const manifestPath = resolveManifestPath(options.manifestPath);
|
|
104
|
+
const manifest = await Manifest.load({ cwd: options.cwd, path: manifestPath, provider });
|
|
105
|
+
const env = await EnvFile.read({ cwd: options.cwd, path: inFile });
|
|
106
|
+
const dryRun = options.dryRun === true;
|
|
107
|
+
const keys = provider === 'aws'
|
|
108
|
+
? await pushAws(manifest, env, dryRun)
|
|
109
|
+
: await pushCloudflare(manifest, env, dryRun);
|
|
110
|
+
return { inFile, keys };
|
|
111
|
+
},
|
|
112
|
+
doctor(options) {
|
|
113
|
+
const provider = resolveProvider(options.provider ??
|
|
114
|
+
process.env['ZINTRUST_SECRETS_PROVIDER']);
|
|
115
|
+
const missing = provider === 'aws' ? AwsSecretsManager.doctorEnv() : CloudflareKv.doctorEnv();
|
|
116
|
+
return { provider, ok: missing.length === 0, missing };
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
export default SecretsToolkit;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type AwsCredentials = {
|
|
2
|
+
accessKeyId: string;
|
|
3
|
+
secretAccessKey: string;
|
|
4
|
+
sessionToken?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const AwsSecretsManager: Readonly<{
|
|
7
|
+
createFromEnv(): {
|
|
8
|
+
getValue: (secretId: string, jsonKey?: string) => Promise<string | null>;
|
|
9
|
+
putValue: (secretId: string, value: string) => Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
doctorEnv(): string[];
|
|
12
|
+
}>;
|
|
13
|
+
export default AwsSecretsManager;
|
|
14
|
+
//# sourceMappingURL=AwsSecretsManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AwsSecretsManager.d.ts","sourceRoot":"","sources":["../../../../../src/toolkit/Secrets/providers/AwsSecretsManager.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GAAG;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AA0GF,eAAO,MAAM,iBAAiB;qBACX;QACf,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACzE,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC9D;iBAsDY,MAAM,EAAE;EAcrB,CAAC;AAEH,eAAe,iBAAiB,CAAC"}
|