@zintrust/core 0.1.18 → 0.1.20
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 +16 -10
- package/bin/zintrust-main.d.ts.map +1 -1
- package/bin/zintrust-main.js +9 -0
- package/package.json +11 -2
- package/public/error-pages/404.html +145 -0
- package/public/error-pages/500.html +266 -0
- package/public/error-pages/error.css +628 -0
- package/public/error-pages/error.js +428 -0
- package/public/index.html +1 -1
- package/public/zintrust.svg +30 -0
- package/routes/api.d.ts +7 -0
- package/routes/api.d.ts.map +1 -0
- package/routes/api.js +115 -0
- package/routes/broadcast.d.ts +9 -0
- package/routes/broadcast.d.ts.map +1 -0
- package/routes/broadcast.js +27 -0
- package/routes/health.d.ts +7 -0
- package/routes/health.d.ts.map +1 -0
- package/routes/health.js +127 -0
- package/routes/metrics.d.ts +9 -0
- package/routes/metrics.d.ts.map +1 -0
- package/routes/metrics.js +20 -0
- package/routes/openapi.d.ts +9 -0
- package/routes/openapi.d.ts.map +1 -0
- package/routes/openapi.js +76 -0
- package/routes/storage.d.ts +4 -0
- package/routes/storage.d.ts.map +1 -0
- package/routes/storage.js +35 -0
- package/src/boot/Application.d.ts +2 -2
- package/src/boot/Application.d.ts.map +1 -1
- package/src/boot/Application.js +18 -3
- package/src/boot/Server.d.ts +3 -2
- package/src/boot/Server.d.ts.map +1 -1
- package/src/boot/Server.js +39 -165
- package/src/boot/bootstrap.js +1 -1
- package/src/cache/Cache.d.ts +1 -1
- package/src/cache/Cache.d.ts.map +1 -1
- package/src/cache/CacheDriver.d.ts +4 -0
- package/src/cache/CacheDriver.d.ts.map +1 -1
- package/src/cache/drivers/KVDriver.d.ts +1 -1
- package/src/cache/drivers/KVDriver.d.ts.map +1 -1
- package/src/cache/drivers/MemoryDriver.d.ts +1 -1
- package/src/cache/drivers/MemoryDriver.d.ts.map +1 -1
- package/src/cache/drivers/MemoryDriver.js +16 -0
- package/src/cache/drivers/MongoDriver.d.ts +1 -1
- package/src/cache/drivers/MongoDriver.d.ts.map +1 -1
- package/src/cache/drivers/RedisDriver.d.ts +1 -1
- package/src/cache/drivers/RedisDriver.d.ts.map +1 -1
- package/src/cli/CLI.d.ts.map +1 -1
- package/src/cli/CLI.js +12 -4
- package/src/cli/PromptHelper.d.ts.map +1 -1
- package/src/cli/PromptHelper.js +4 -3
- package/src/cli/commands/AddCommand.d.ts +2 -2
- package/src/cli/commands/AddCommand.d.ts.map +1 -1
- package/src/cli/commands/AddCommand.js +135 -58
- package/src/cli/commands/ConfigCommand.d.ts +1 -1
- package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
- package/src/cli/commands/CreateCommand.d.ts +15 -0
- package/src/cli/commands/CreateCommand.d.ts.map +1 -0
- package/src/cli/commands/CreateCommand.js +143 -0
- package/src/cli/commands/D1MigrateCommand.d.ts +1 -1
- package/src/cli/commands/D1MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/D1MigrateCommand.js +16 -20
- package/src/cli/commands/DbSeedCommand.d.ts +9 -0
- package/src/cli/commands/DbSeedCommand.d.ts.map +1 -0
- package/src/cli/commands/DbSeedCommand.js +171 -0
- package/src/cli/commands/DebugCommand.d.ts +1 -1
- package/src/cli/commands/DebugCommand.d.ts.map +1 -1
- package/src/cli/commands/FixCommand.d.ts +1 -1
- package/src/cli/commands/FixCommand.d.ts.map +1 -1
- package/src/cli/commands/JwtDevCommand.d.ts +8 -0
- package/src/cli/commands/JwtDevCommand.d.ts.map +1 -0
- package/src/cli/commands/JwtDevCommand.js +114 -0
- package/src/cli/commands/KeyGenerateCommand.d.ts +1 -1
- package/src/cli/commands/KeyGenerateCommand.d.ts.map +1 -1
- package/src/cli/commands/LogsCommand.d.ts +2 -2
- package/src/cli/commands/LogsCommand.d.ts.map +1 -1
- package/src/cli/commands/LogsCommand.js +36 -2
- package/src/cli/commands/MakeMailTemplateCommand.d.ts +1 -1
- package/src/cli/commands/MakeMailTemplateCommand.d.ts.map +1 -1
- package/src/cli/commands/MakeNotificationTemplateCommand.d.ts +1 -1
- package/src/cli/commands/MakeNotificationTemplateCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateCommand.d.ts +1 -1
- package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateCommand.js +291 -35
- package/src/cli/commands/NewCommand.d.ts +2 -2
- package/src/cli/commands/NewCommand.d.ts.map +1 -1
- package/src/cli/commands/NewCommand.js +38 -13
- package/src/cli/commands/PluginCommand.d.ts +1 -1
- package/src/cli/commands/PluginCommand.d.ts.map +1 -1
- package/src/cli/commands/PrepareCommand.d.ts +1 -1
- package/src/cli/commands/PrepareCommand.d.ts.map +1 -1
- package/src/cli/commands/QACommand.d.ts +2 -2
- package/src/cli/commands/QACommand.d.ts.map +1 -1
- package/src/cli/commands/RoutesCommand.d.ts +10 -0
- package/src/cli/commands/RoutesCommand.d.ts.map +1 -0
- package/src/cli/commands/RoutesCommand.js +242 -0
- package/src/cli/commands/SimulateCommand.d.ts +1 -1
- package/src/cli/commands/SimulateCommand.d.ts.map +1 -1
- package/src/cli/commands/SimulateCommand.js +1 -1
- package/src/cli/commands/StartCommand.d.ts.map +1 -1
- package/src/cli/commands/StartCommand.js +90 -3
- package/src/cli/commands/UpgradeCommand.d.ts +16 -0
- package/src/cli/commands/UpgradeCommand.d.ts.map +1 -0
- package/src/cli/commands/UpgradeCommand.js +107 -0
- package/src/cli/commands/index.d.ts +3 -0
- package/src/cli/commands/index.d.ts.map +1 -1
- package/src/cli/commands/index.js +3 -0
- package/src/cli/commands/runner/index.d.ts +3 -0
- package/src/cli/commands/runner/index.d.ts.map +1 -0
- package/src/cli/commands/runner/index.js +139 -0
- package/src/cli/config/ConfigManager.d.ts +1 -1
- package/src/cli/config/ConfigManager.d.ts.map +1 -1
- package/src/cli/config/ConfigValidator.d.ts +1 -1
- package/src/cli/config/ConfigValidator.d.ts.map +1 -1
- package/src/cli/config/ConfigValidator.js +1 -1
- package/src/cli/d1/D1SqlMigrations.d.ts +20 -0
- package/src/cli/d1/D1SqlMigrations.d.ts.map +1 -0
- package/src/cli/d1/D1SqlMigrations.js +224 -0
- package/src/cli/d1/WranglerConfig.d.ts +4 -0
- package/src/cli/d1/WranglerConfig.d.ts.map +1 -0
- package/src/cli/d1/WranglerConfig.js +122 -0
- package/src/cli/d1/WranglerD1.d.ts +11 -0
- package/src/cli/d1/WranglerD1.d.ts.map +1 -0
- package/src/cli/d1/WranglerD1.js +16 -0
- package/src/cli/env/EnvFileBackfill.d.ts +10 -0
- package/src/cli/env/EnvFileBackfill.d.ts.map +1 -0
- package/src/cli/env/EnvFileBackfill.js +64 -0
- package/src/cli/scaffolding/ControllerGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/ControllerGenerator.js +72 -22
- package/src/cli/scaffolding/FactoryGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/FactoryGenerator.js +3 -1
- package/src/cli/scaffolding/GovernanceScaffolder.d.ts +23 -0
- package/src/cli/scaffolding/GovernanceScaffolder.d.ts.map +1 -0
- package/src/cli/scaffolding/GovernanceScaffolder.js +327 -0
- package/src/cli/scaffolding/MigrationGenerator.d.ts +10 -0
- package/src/cli/scaffolding/MigrationGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/MigrationGenerator.js +137 -51
- package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ProjectScaffolder.js +54 -59
- package/src/cli/scaffolding/RouteGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/RouteGenerator.js +79 -43
- package/src/cli/scaffolding/SeederGenerator.d.ts +5 -0
- package/src/cli/scaffolding/SeederGenerator.d.ts.map +1 -1
- package/src/cli/scaffolding/SeederGenerator.js +63 -15
- package/src/cli/scaffolding/ServiceScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ServiceScaffolder.js +24 -3
- package/src/cli/scaffolding/index.d.ts +2 -0
- package/src/cli/scaffolding/index.d.ts.map +1 -1
- package/src/cli/scaffolding/index.js +1 -0
- package/src/cli/utils/DistPackager.d.ts.map +1 -1
- package/src/cli/utils/DistPackager.js +8 -0
- package/src/common/index.d.ts +8 -0
- package/src/common/index.d.ts.map +1 -1
- package/src/common/index.js +28 -0
- package/src/common/utility.d.ts +38 -0
- package/src/common/utility.d.ts.map +1 -0
- package/src/common/utility.js +101 -0
- package/src/config/FileLogWriter.d.ts +2 -1
- package/src/config/FileLogWriter.d.ts.map +1 -1
- package/src/config/FileLogWriter.js +83 -2
- package/src/config/app.d.ts.map +1 -1
- package/src/config/app.js +3 -1
- package/src/config/broadcast.d.ts +1 -1
- package/src/config/broadcast.d.ts.map +1 -1
- package/src/config/broadcast.js +1 -1
- package/src/config/cache.d.ts +1 -1
- package/src/config/cache.d.ts.map +1 -1
- package/src/config/cloudflare.d.ts +1 -1
- package/src/config/cloudflare.d.ts.map +1 -1
- package/src/config/database.d.ts +7 -1
- package/src/config/database.d.ts.map +1 -1
- package/src/config/database.js +99 -7
- package/src/config/env.d.ts +6 -0
- package/src/config/env.d.ts.map +1 -1
- package/src/config/env.js +7 -0
- package/src/config/index.d.ts +8 -2
- package/src/config/index.d.ts.map +1 -1
- package/src/config/logging/KvLogger.js +1 -1
- package/src/config/logging/SlackLogger.js +2 -2
- package/src/config/middleware.d.ts +22 -2
- package/src/config/middleware.d.ts.map +1 -1
- package/src/config/middleware.js +179 -11
- package/src/config/notification.js +1 -1
- package/src/config/security.d.ts +1 -1
- package/src/config/security.js +1 -1
- package/src/config/storage.js +1 -1
- package/src/config/type.d.ts +8 -2
- package/src/config/type.d.ts.map +1 -1
- package/src/events/EventDispatcher.d.ts.map +1 -1
- package/src/events/EventDispatcher.js +6 -4
- package/src/exceptions/ZintrustError.d.ts +7 -0
- package/src/exceptions/ZintrustError.d.ts.map +1 -1
- package/src/exceptions/ZintrustError.js +56 -0
- package/src/features/Auth.d.ts +1 -1
- package/src/features/Auth.d.ts.map +1 -1
- package/src/features/Auth.js +3 -3
- package/src/features/Queue.js +1 -1
- package/src/functions/cloudflare.d.ts.map +1 -1
- package/src/functions/cloudflare.js +3 -14
- package/src/functions/deno.d.ts.map +1 -1
- package/src/functions/deno.js +3 -14
- package/src/functions/lambda.d.ts.map +1 -1
- package/src/functions/lambda.js +3 -14
- package/src/health/StartupHealthChecks.js +1 -1
- package/src/http/Controller.d.ts +2 -2
- package/src/http/Controller.d.ts.map +1 -1
- package/src/http/FileUpload.d.ts +68 -0
- package/src/http/FileUpload.d.ts.map +1 -0
- package/src/http/FileUpload.js +120 -0
- package/src/http/Kernel.d.ts +5 -5
- package/src/http/Kernel.d.ts.map +1 -1
- package/src/http/Kernel.js +139 -23
- package/src/http/Request.d.ts +20 -1
- package/src/http/Request.d.ts.map +1 -1
- package/src/http/Request.js +23 -0
- package/src/http/RequestContext.d.ts +6 -0
- package/src/http/RequestContext.d.ts.map +1 -1
- package/src/http/RequestContext.js +77 -1
- package/src/http/Response.d.ts +1 -1
- package/src/http/Response.d.ts.map +1 -1
- package/src/http/ValidationHelper.d.ts +78 -0
- package/src/http/ValidationHelper.d.ts.map +1 -0
- package/src/http/ValidationHelper.js +121 -0
- package/src/http/error-pages/ErrorPageRenderer.d.ts +17 -0
- package/src/http/error-pages/ErrorPageRenderer.d.ts.map +1 -0
- package/src/http/error-pages/ErrorPageRenderer.js +88 -0
- package/src/http/middleware/BodyParsingMiddleware.d.ts +12 -0
- package/src/http/middleware/BodyParsingMiddleware.d.ts.map +1 -0
- package/src/http/middleware/BodyParsingMiddleware.js +251 -0
- package/src/http/middleware/FileUploadMiddleware.d.ts +12 -0
- package/src/http/middleware/FileUploadMiddleware.d.ts.map +1 -0
- package/src/http/middleware/FileUploadMiddleware.js +74 -0
- package/src/http/parsers/BodyParsers.d.ts +32 -0
- package/src/http/parsers/BodyParsers.d.ts.map +1 -0
- package/src/http/parsers/BodyParsers.js +159 -0
- package/src/http/parsers/MultipartParser.d.ts +33 -0
- package/src/http/parsers/MultipartParser.d.ts.map +1 -0
- package/src/http/parsers/MultipartParser.js +129 -0
- package/src/http/parsers/MultipartParserRegistry.d.ts +34 -0
- package/src/http/parsers/MultipartParserRegistry.d.ts.map +1 -0
- package/src/http/parsers/MultipartParserRegistry.js +20 -0
- package/src/http/validated.d.ts +12 -0
- package/src/http/validated.d.ts.map +1 -0
- package/src/http/validated.js +41 -0
- package/src/index.d.ts +65 -7
- package/src/index.d.ts.map +1 -1
- package/src/index.js +59 -5
- package/src/microservices/RequestTracingMiddleware.d.ts +2 -2
- package/src/microservices/RequestTracingMiddleware.d.ts.map +1 -1
- package/src/microservices/RequestTracingMiddleware.js +3 -0
- package/src/microservices/ServiceAuthMiddleware.d.ts +2 -2
- package/src/microservices/ServiceAuthMiddleware.d.ts.map +1 -1
- package/src/middleware/AuthMiddleware.d.ts +10 -0
- package/src/middleware/AuthMiddleware.d.ts.map +1 -0
- package/src/middleware/AuthMiddleware.js +16 -0
- package/src/middleware/CsrfMiddleware.d.ts +11 -1
- package/src/middleware/CsrfMiddleware.d.ts.map +1 -1
- package/src/middleware/CsrfMiddleware.js +33 -0
- package/src/middleware/JwtAuthMiddleware.d.ts +11 -0
- package/src/middleware/JwtAuthMiddleware.d.ts.map +1 -0
- package/src/middleware/JwtAuthMiddleware.js +73 -0
- package/src/middleware/LoggingMiddleware.d.ts.map +1 -1
- package/src/middleware/LoggingMiddleware.js +8 -3
- package/src/middleware/MiddlewareStack.d.ts +2 -2
- package/src/middleware/MiddlewareStack.d.ts.map +1 -1
- package/src/middleware/RateLimiter.d.ts +2 -2
- package/src/middleware/RateLimiter.d.ts.map +1 -1
- package/src/middleware/RateLimiter.js +26 -1
- package/src/middleware/SanitizeBodyMiddleware.d.ts +12 -0
- package/src/middleware/SanitizeBodyMiddleware.d.ts.map +1 -0
- package/src/middleware/SanitizeBodyMiddleware.js +31 -0
- package/src/middleware/SecurityMiddleware.d.ts +1 -1
- package/src/middleware/SecurityMiddleware.d.ts.map +1 -1
- package/src/middleware/SessionMiddleware.d.ts +1 -1
- package/src/middleware/SessionMiddleware.d.ts.map +1 -1
- package/src/middleware/ValidationMiddleware.d.ts +25 -0
- package/src/middleware/ValidationMiddleware.d.ts.map +1 -0
- package/src/middleware/ValidationMiddleware.js +251 -0
- package/src/migrations/MigrationDiscovery.d.ts +5 -0
- package/src/migrations/MigrationDiscovery.d.ts.map +1 -0
- package/src/migrations/MigrationDiscovery.js +16 -0
- package/src/migrations/MigrationLoader.d.ts +5 -0
- package/src/migrations/MigrationLoader.d.ts.map +1 -0
- package/src/migrations/MigrationLoader.js +43 -0
- package/src/migrations/MigrationLock.d.ts +4 -0
- package/src/migrations/MigrationLock.d.ts.map +1 -0
- package/src/migrations/MigrationLock.js +33 -0
- package/src/migrations/Migrator.d.ts +23 -0
- package/src/migrations/Migrator.d.ts.map +1 -0
- package/src/migrations/Migrator.js +4 -0
- package/src/migrations/MigratorFactory.d.ts +25 -0
- package/src/migrations/MigratorFactory.d.ts.map +1 -0
- package/src/migrations/MigratorFactory.js +323 -0
- package/src/migrations/schema/Blueprint.d.ts +5 -0
- package/src/migrations/schema/Blueprint.d.ts.map +1 -0
- package/src/migrations/schema/Blueprint.js +189 -0
- package/src/migrations/schema/Schema.d.ts +8 -0
- package/src/migrations/schema/Schema.d.ts.map +1 -0
- package/src/migrations/schema/Schema.js +141 -0
- package/src/migrations/schema/SchemaCompiler.d.ts +20 -0
- package/src/migrations/schema/SchemaCompiler.d.ts.map +1 -0
- package/src/migrations/schema/SchemaCompiler.js +262 -0
- package/src/migrations/schema/index.d.ts +5 -0
- package/src/migrations/schema/index.d.ts.map +1 -0
- package/src/migrations/schema/index.js +3 -0
- package/src/migrations/schema/types.d.ts +86 -0
- package/src/migrations/schema/types.d.ts.map +1 -0
- package/src/migrations/schema/types.js +1 -0
- package/src/migrations/types.d.ts +45 -0
- package/src/migrations/types.d.ts.map +1 -0
- package/src/migrations/types.js +1 -0
- package/src/node-singletons/crypto.d.ts +1 -1
- package/src/node-singletons/crypto.d.ts.map +1 -1
- package/src/node-singletons/crypto.js +1 -1
- 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 +1 -1
- package/src/node-singletons/util.d.ts +6 -0
- package/src/node-singletons/util.d.ts.map +1 -0
- package/src/node-singletons/util.js +5 -0
- package/src/node.d.ts +2 -0
- package/src/node.d.ts.map +1 -1
- package/src/node.js +7 -0
- package/src/observability/OpenTelemetry.d.ts +62 -0
- package/src/observability/OpenTelemetry.d.ts.map +1 -0
- package/src/observability/OpenTelemetry.js +167 -0
- package/src/observability/PrometheusMetrics.d.ts +25 -0
- package/src/observability/PrometheusMetrics.d.ts.map +1 -0
- package/src/observability/PrometheusMetrics.js +114 -0
- package/src/openapi/OpenApiGenerator.d.ts +68 -0
- package/src/openapi/OpenApiGenerator.d.ts.map +1 -0
- package/src/openapi/OpenApiGenerator.js +287 -0
- package/src/orm/Database.d.ts +4 -2
- package/src/orm/Database.d.ts.map +1 -1
- package/src/orm/Database.js +142 -29
- package/src/orm/DatabaseAdapter.d.ts +13 -0
- package/src/orm/DatabaseAdapter.d.ts.map +1 -1
- package/src/orm/DatabaseAdapterRegistry.d.ts.map +1 -1
- package/src/orm/DatabaseAdapterRegistry.js +3 -1
- package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -1
- package/src/orm/DatabaseRuntimeRegistration.js +4 -0
- package/src/orm/Model.d.ts +30 -2
- package/src/orm/Model.d.ts.map +1 -1
- package/src/orm/Model.js +255 -62
- package/src/orm/QueryBuilder.d.ts +22 -1
- package/src/orm/QueryBuilder.d.ts.map +1 -1
- package/src/orm/QueryBuilder.js +405 -95
- package/src/orm/Relationships.d.ts +7 -1
- package/src/orm/Relationships.d.ts.map +1 -1
- package/src/orm/Relationships.js +18 -0
- package/src/orm/SchemaCompiler.d.ts +9 -0
- package/src/orm/SchemaCompiler.d.ts.map +1 -0
- package/src/orm/SchemaCompiler.js +145 -0
- package/src/orm/adapters/D1Adapter.d.ts +1 -1
- package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
- package/src/orm/adapters/MySQLAdapter.d.ts +1 -1
- package/src/orm/adapters/MySQLAdapter.d.ts.map +1 -1
- package/src/orm/adapters/MySQLAdapter.js +88 -69
- package/src/orm/adapters/PostgreSQLAdapter.d.ts +1 -1
- package/src/orm/adapters/PostgreSQLAdapter.d.ts.map +1 -1
- package/src/orm/adapters/PostgreSQLAdapter.js +88 -69
- package/src/orm/adapters/SQLServerAdapter.d.ts +1 -1
- package/src/orm/adapters/SQLServerAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SQLiteAdapter.d.ts +1 -1
- package/src/orm/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SQLiteAdapter.js +63 -3
- package/src/orm/maintenance/SqliteMaintenance.d.ts +5 -0
- package/src/orm/maintenance/SqliteMaintenance.d.ts.map +1 -0
- package/src/orm/maintenance/SqliteMaintenance.js +14 -0
- package/src/orm/migrations/MigrationStore.d.ts +38 -0
- package/src/orm/migrations/MigrationStore.d.ts.map +1 -0
- package/src/orm/migrations/MigrationStore.js +157 -0
- package/src/performance/CodeGenerationBenchmark.d.ts.map +1 -1
- package/src/performance/Optimizer.d.ts +1 -0
- package/src/performance/Optimizer.d.ts.map +1 -1
- package/src/performance/Optimizer.js +37 -3
- package/src/profiling/MemoryProfiler.d.ts +1 -1
- package/src/profiling/MemoryProfiler.d.ts.map +1 -1
- package/src/profiling/N1Detector.d.ts +1 -1
- package/src/profiling/N1Detector.d.ts.map +1 -1
- package/src/profiling/QueryLogger.d.ts +1 -1
- package/src/profiling/QueryLogger.d.ts.map +1 -1
- package/src/profiling/RequestProfiler.d.ts +3 -3
- package/src/profiling/RequestProfiler.d.ts.map +1 -1
- package/src/routes/api.d.ts +2 -0
- package/src/routes/api.d.ts.map +1 -0
- package/src/routes/api.js +1 -0
- package/src/routes/broadcast.d.ts +2 -0
- package/src/routes/broadcast.d.ts.map +1 -0
- package/src/routes/broadcast.js +1 -0
- package/src/routes/health.d.ts +2 -0
- package/src/routes/health.d.ts.map +1 -0
- package/src/routes/health.js +1 -0
- package/src/routes/metrics.d.ts +2 -0
- package/src/routes/metrics.d.ts.map +1 -0
- package/src/routes/metrics.js +1 -0
- package/src/routes/storage.d.ts +2 -0
- package/src/routes/storage.d.ts.map +1 -0
- package/src/routes/storage.js +1 -0
- package/src/routing/CoreRoutes.d.ts +12 -0
- package/src/routing/CoreRoutes.d.ts.map +1 -0
- package/src/routing/CoreRoutes.js +151 -0
- package/src/routing/RouteRegistry.d.ts +39 -0
- package/src/routing/RouteRegistry.d.ts.map +1 -0
- package/src/routing/RouteRegistry.js +44 -0
- package/src/routing/Router.d.ts +26 -9
- package/src/routing/Router.d.ts.map +1 -1
- package/src/routing/Router.js +79 -35
- package/src/routing/common.d.ts +15 -0
- package/src/routing/common.d.ts.map +1 -0
- package/src/routing/common.js +47 -0
- package/src/routing/doc.d.ts +28 -0
- package/src/routing/doc.d.ts.map +1 -0
- package/src/routing/doc.js +95 -0
- package/src/routing/error.d.ts +21 -0
- package/src/routing/error.d.ts.map +1 -0
- package/src/routing/error.js +126 -0
- package/src/routing/errorPages.d.ts +14 -0
- package/src/routing/errorPages.d.ts.map +1 -0
- package/src/routing/errorPages.js +103 -0
- package/src/routing/publicRoot.d.ts +18 -0
- package/src/routing/publicRoot.d.ts.map +1 -0
- package/src/routing/publicRoot.js +49 -0
- package/src/runtime/PluginAutoImports.d.ts +21 -0
- package/src/runtime/PluginAutoImports.d.ts.map +1 -0
- package/src/runtime/PluginAutoImports.js +59 -0
- package/src/runtime/PluginManager.d.ts +1 -5
- package/src/runtime/PluginManager.d.ts.map +1 -1
- package/src/runtime/PluginManager.js +25 -18
- package/src/runtime/RuntimeAdapter.d.ts.map +1 -1
- package/src/runtime/RuntimeAdapter.js +20 -1
- package/src/runtime/RuntimeDetector.d.ts +1 -1
- package/src/runtime/RuntimeDetector.d.ts.map +1 -1
- package/src/runtime/adapters/CloudflareAdapter.d.ts +1 -1
- package/src/runtime/adapters/CloudflareAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/CloudflareAdapter.js +1 -1
- package/src/runtime/adapters/DenoAdapter.d.ts +1 -1
- package/src/runtime/adapters/DenoAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/DenoAdapter.js +3 -3
- package/src/runtime/adapters/LambdaAdapter.d.ts +1 -1
- package/src/runtime/adapters/LambdaAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/LambdaAdapter.js +1 -1
- package/src/runtime/adapters/NodeServerAdapter.d.ts +1 -1
- package/src/runtime/adapters/NodeServerAdapter.d.ts.map +1 -1
- package/src/runtime/getKernel.d.ts +9 -0
- package/src/runtime/getKernel.d.ts.map +1 -0
- package/src/runtime/getKernel.js +27 -0
- package/src/scripts/TemplateImportsCheck.js +47 -7
- package/src/scripts/TemplateSync.js +92 -20
- package/src/security/Encryptor.d.ts.map +1 -1
- package/src/security/Encryptor.js +64 -7
- package/src/security/JwtManager.d.ts +1 -0
- package/src/security/JwtManager.d.ts.map +1 -1
- package/src/security/JwtManager.js +33 -0
- package/src/security/Sanitizer.d.ts +76 -0
- package/src/security/Sanitizer.d.ts.map +1 -0
- package/src/security/Sanitizer.js +412 -0
- package/src/security/TokenRevocation.d.ts +7 -0
- package/src/security/TokenRevocation.d.ts.map +1 -0
- package/src/security/TokenRevocation.js +57 -0
- package/src/seeders/SeederDiscovery.d.ts +5 -0
- package/src/seeders/SeederDiscovery.d.ts.map +1 -0
- package/src/seeders/SeederDiscovery.js +21 -0
- package/src/seeders/SeederLoader.d.ts +5 -0
- package/src/seeders/SeederLoader.d.ts.map +1 -0
- package/src/seeders/SeederLoader.js +60 -0
- package/src/seeders/types.d.ts +18 -0
- package/src/seeders/types.d.ts.map +1 -0
- package/src/seeders/types.js +1 -0
- package/src/session/SessionManager.js +1 -1
- package/src/start.d.ts +21 -0
- package/src/start.d.ts.map +1 -0
- package/src/start.js +60 -0
- package/src/templates/adapters/MySQLAdapter.ts.tpl +109 -85
- package/src/templates/adapters/PostgreSQLAdapter.ts.tpl +129 -88
- package/src/templates/adapters/SQLServerAdapter.ts.tpl +5 -9
- package/src/templates/adapters/SQLiteAdapter.ts.tpl +78 -11
- package/src/templates/features/Queue.ts.tpl +2 -2
- package/src/templates/project/basic/app/Controllers/AuthController.ts.tpl +217 -0
- package/src/templates/project/basic/app/Controllers/UserController.ts.tpl +3 -16
- package/src/templates/project/basic/app/Middleware/ProfilerMiddleware.ts.tpl +1 -3
- package/src/templates/project/basic/app/Middleware/index.ts.tpl +3 -8
- package/src/templates/project/basic/app/Models/Post.ts.tpl +2 -3
- package/src/templates/project/basic/app/Models/User.ts.tpl +1 -1
- package/src/templates/project/basic/app/Types/controller.ts.tpl +46 -0
- package/src/templates/project/basic/config/FileLogWriter.ts.tpl +5 -236
- package/src/templates/project/basic/config/SecretsManager.ts.tpl +13 -450
- package/src/templates/project/basic/config/StartupConfigValidator.ts.tpl +9 -268
- package/src/templates/project/basic/config/app.ts.tpl +13 -153
- package/src/templates/project/basic/config/broadcast.ts.tpl +15 -129
- package/src/templates/project/basic/config/cache.ts.tpl +15 -92
- package/src/templates/project/basic/config/cloudflare.ts.tpl +4 -39
- package/src/templates/project/basic/config/constants.ts.tpl +9 -65
- package/src/templates/project/basic/config/database.ts.tpl +29 -116
- package/src/templates/project/basic/config/env.ts.tpl +5 -169
- package/src/templates/project/basic/config/features.ts.tpl +6 -54
- package/src/templates/project/basic/config/index.ts.tpl +27 -24
- package/src/templates/project/basic/config/logger.ts.tpl +5 -381
- package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +1 -1
- package/src/templates/project/basic/config/logging/KvLogger.ts.tpl +2 -2
- package/src/templates/project/basic/config/logging/SlackLogger.ts.tpl +1 -1
- package/src/templates/project/basic/config/mail.ts.tpl +15 -115
- package/src/templates/project/basic/config/microservices.ts.tpl +11 -97
- package/src/templates/project/basic/config/middleware.ts.tpl +27 -18
- package/src/templates/project/basic/config/notification.ts.tpl +14 -127
- package/src/templates/project/basic/config/queue.ts.tpl +16 -79
- package/src/templates/project/basic/config/security.ts.tpl +11 -163
- package/src/templates/project/basic/config/startup.ts.tpl +10 -21
- package/src/templates/project/basic/config/storage.ts.tpl +15 -133
- package/src/templates/project/basic/config/type.ts.tpl +33 -441
- package/src/templates/project/basic/database/factories/UserFactory.ts.tpl +80 -0
- package/src/templates/project/basic/database/migrations/create_tasks_table.ts.tpl +28 -0
- package/src/templates/project/basic/database/migrations/create_users_table.ts.tpl +29 -0
- package/src/templates/project/basic/database/seeders/DatabaseSeeder.ts.tpl +19 -0
- package/src/templates/project/basic/database/seeders/UserSeeder.ts.tpl +18 -0
- package/src/templates/project/basic/database/seeders/index.ts.tpl +2 -0
- package/src/templates/project/basic/package.json.tpl +1 -1
- package/src/templates/project/basic/routes/api.ts.tpl +74 -36
- package/src/templates/project/basic/routes/health.ts.tpl +1 -6
- package/src/templates/project/basic/routes/metrics.ts.tpl +22 -0
- package/src/templates/project/basic/src/index.ts.tpl +7 -80
- package/src/templates/project/basic/tsconfig.json.tpl +12 -13
- package/src/testing/TestEnvironment.d.ts +40 -0
- package/src/testing/TestEnvironment.d.ts.map +1 -0
- package/src/testing/TestEnvironment.js +141 -0
- package/src/testing/TestHttp.d.ts +29 -0
- package/src/testing/TestHttp.d.ts.map +1 -0
- package/src/testing/TestHttp.js +96 -0
- package/src/testing/index.d.ts +5 -0
- package/src/testing/index.d.ts.map +1 -0
- package/src/testing/index.js +2 -0
- package/src/time/DateTime.d.ts +181 -0
- package/src/time/DateTime.d.ts.map +1 -0
- package/src/time/DateTime.js +300 -0
- package/src/time/index.d.ts +7 -0
- package/src/time/index.d.ts.map +1 -0
- package/src/time/index.js +5 -0
- package/src/tools/http/Http.d.ts.map +1 -1
- package/src/tools/http/Http.js +4 -0
- package/src/tools/mail/drivers/Smtp.js +1 -1
- package/src/tools/queue/drivers/InMemory.d.ts +1 -1
- package/src/tools/queue/drivers/InMemory.d.ts.map +1 -1
- package/src/tools/queue/drivers/InMemory.js +1 -1
- package/src/tools/queue/drivers/Redis.d.ts +1 -1
- package/src/tools/queue/drivers/Redis.d.ts.map +1 -1
- package/src/tools/queue/drivers/Redis.js +1 -1
- package/src/validation/ValidationError.d.ts.map +1 -1
- package/src/validation/ValidationError.js +4 -2
- package/src/validation/Validator.d.ts +49 -16
- package/src/validation/Validator.d.ts.map +1 -1
- package/src/validation/Validator.js +307 -5
- package/src/common/uuid.d.ts +0 -3
- package/src/common/uuid.d.ts.map +0 -1
- package/src/common/uuid.js +0 -30
- package/src/templates/project/basic/.env.example.tpl +0 -74
- package/src/templates/project/basic/.env.tpl +0 -166
- package/src/templates/project/basic/database/migrations/index.ts.tpl +0 -2
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create Command
|
|
3
|
+
* Shortcuts for common scaffolding tasks.
|
|
4
|
+
*/
|
|
5
|
+
import { BaseCommand } from '../BaseCommand.js';
|
|
6
|
+
import { FileGenerator } from '../scaffolding/FileGenerator.js';
|
|
7
|
+
import { MigrationGenerator } from '../scaffolding/MigrationGenerator.js';
|
|
8
|
+
import { CommonUtils } from '../../common/index.js';
|
|
9
|
+
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
10
|
+
import * as path from '../../node-singletons/path.js';
|
|
11
|
+
const pluralize = (snake) => (snake.endsWith('s') ? snake : `${snake}s`);
|
|
12
|
+
const buildCreateTableMigrationName = (model) => {
|
|
13
|
+
const modelSnake = CommonUtils.toSnakeCase(model).replaceAll(/[^a-z0-9_]+/g, '_');
|
|
14
|
+
const tablePlural = pluralize(modelSnake);
|
|
15
|
+
return `create_${tablePlural}_table`;
|
|
16
|
+
};
|
|
17
|
+
const buildAddColumnMigrationName = (column, model) => {
|
|
18
|
+
const colSnake = CommonUtils.toSnakeCase(column).replaceAll(/[^a-z0-9_]+/g, '_');
|
|
19
|
+
const modelSnake = CommonUtils.toSnakeCase(model).replaceAll(/[^a-z0-9_]+/g, '_');
|
|
20
|
+
const tablePlural = pluralize(modelSnake);
|
|
21
|
+
return `add_${colSnake}_${tablePlural}_table`;
|
|
22
|
+
};
|
|
23
|
+
const findMigrationBySuffix = (migrationsPath, suffix) => {
|
|
24
|
+
const files = FileGenerator.listFiles(migrationsPath, false);
|
|
25
|
+
for (const file of files) {
|
|
26
|
+
if (path.basename(file).endsWith(suffix))
|
|
27
|
+
return file;
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
};
|
|
31
|
+
const addOptions = (command) => {
|
|
32
|
+
command
|
|
33
|
+
.argument('<type>', 'What to create (currently: migration)')
|
|
34
|
+
.argument('<name>', 'Name (for migration: model name like "user")');
|
|
35
|
+
// Accepted for consistency with other CLI commands.
|
|
36
|
+
command.option('--no-interactive', 'Skip interactive prompts');
|
|
37
|
+
};
|
|
38
|
+
const executeCreate = async (cmd, options) => {
|
|
39
|
+
const args = Array.isArray(options.args) ? options.args : [];
|
|
40
|
+
const type = args[0];
|
|
41
|
+
const name = args[1];
|
|
42
|
+
if (type !== 'migration') {
|
|
43
|
+
throw ErrorFactory.createCliError('Usage: zin create migration <model>');
|
|
44
|
+
}
|
|
45
|
+
if (typeof name !== 'string' || name.trim() === '') {
|
|
46
|
+
throw ErrorFactory.createValidationError('Model name is required');
|
|
47
|
+
}
|
|
48
|
+
const projectRoot = process.cwd();
|
|
49
|
+
const migrationsPath = path.join(projectRoot, 'database', 'migrations');
|
|
50
|
+
const migrationName = buildCreateTableMigrationName(name);
|
|
51
|
+
const tableName = pluralize(CommonUtils.toSnakeCase(name).replaceAll(/[^a-z0-9_]+/g, '_'));
|
|
52
|
+
cmd.info(`Creating migration: ${migrationName}...`);
|
|
53
|
+
const result = await MigrationGenerator.generateMigration({
|
|
54
|
+
name: migrationName,
|
|
55
|
+
migrationsPath,
|
|
56
|
+
type: 'create',
|
|
57
|
+
table: tableName,
|
|
58
|
+
});
|
|
59
|
+
if (result.success === false)
|
|
60
|
+
throw ErrorFactory.createCliError(result.message);
|
|
61
|
+
cmd.success('Migration created successfully!');
|
|
62
|
+
cmd.info(`File: ${path.basename(result.filePath)}`);
|
|
63
|
+
};
|
|
64
|
+
const executeCm = async (cmd, options) => {
|
|
65
|
+
const args = Array.isArray(options.args) ? options.args : [];
|
|
66
|
+
const model = args[0];
|
|
67
|
+
if (typeof model !== 'string' || model.trim() === '') {
|
|
68
|
+
throw ErrorFactory.createCliError('Usage: zin cm <model>');
|
|
69
|
+
}
|
|
70
|
+
await executeCreate(cmd, { ...options, args: ['migration', model] });
|
|
71
|
+
};
|
|
72
|
+
const executeAm = async (cmd, options) => {
|
|
73
|
+
const args = Array.isArray(options.args) ? options.args : [];
|
|
74
|
+
const column = args[0];
|
|
75
|
+
const model = args[1];
|
|
76
|
+
if (typeof column !== 'string' ||
|
|
77
|
+
column.trim() === '' ||
|
|
78
|
+
typeof model !== 'string' ||
|
|
79
|
+
model.trim() === '') {
|
|
80
|
+
throw ErrorFactory.createCliError('Usage: zin am <column> <model>');
|
|
81
|
+
}
|
|
82
|
+
const projectRoot = process.cwd();
|
|
83
|
+
const migrationsPath = path.join(projectRoot, 'database', 'migrations');
|
|
84
|
+
const tableName = pluralize(CommonUtils.toSnakeCase(model).replaceAll(/[^a-z0-9_]+/g, '_'));
|
|
85
|
+
const createName = buildCreateTableMigrationName(model);
|
|
86
|
+
const existingCreate = findMigrationBySuffix(migrationsPath, `_${createName}.ts`);
|
|
87
|
+
if (existingCreate === undefined) {
|
|
88
|
+
throw ErrorFactory.createCliError(`Missing required create migration for model '${model}'. Create it first: zin cm ${model}`);
|
|
89
|
+
}
|
|
90
|
+
const migrationName = buildAddColumnMigrationName(column, model);
|
|
91
|
+
cmd.info(`Creating migration: ${migrationName}...`);
|
|
92
|
+
const result = await MigrationGenerator.generateMigration({
|
|
93
|
+
name: migrationName,
|
|
94
|
+
migrationsPath,
|
|
95
|
+
// Let generator infer type from name (add_* => alter)
|
|
96
|
+
table: tableName,
|
|
97
|
+
column: CommonUtils.toSnakeCase(column).replaceAll(/[^a-z0-9_]+/g, '_'),
|
|
98
|
+
});
|
|
99
|
+
if (result.success === false)
|
|
100
|
+
throw ErrorFactory.createCliError(result.message);
|
|
101
|
+
cmd.success('Migration created successfully!');
|
|
102
|
+
cmd.info(`File: ${path.basename(result.filePath)}`);
|
|
103
|
+
};
|
|
104
|
+
export const CreateCommand = Object.freeze({
|
|
105
|
+
create() {
|
|
106
|
+
const cmd = BaseCommand.create({
|
|
107
|
+
name: 'create',
|
|
108
|
+
description: 'Create resources (e.g. migrations) with opinionated naming',
|
|
109
|
+
addOptions,
|
|
110
|
+
execute: async (options) => executeCreate(cmd, options),
|
|
111
|
+
});
|
|
112
|
+
return cmd;
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
export const CreateMigrationCommand = Object.freeze({
|
|
116
|
+
create() {
|
|
117
|
+
const cmd = BaseCommand.create({
|
|
118
|
+
name: 'cm',
|
|
119
|
+
description: 'Shortcut: create migration for a model (create_<models>_table)',
|
|
120
|
+
addOptions: (command) => {
|
|
121
|
+
command.argument('<model>', 'Model name (e.g. user)');
|
|
122
|
+
command.option('--no-interactive', 'Skip interactive prompts');
|
|
123
|
+
},
|
|
124
|
+
execute: async (options) => executeCm(cmd, options),
|
|
125
|
+
});
|
|
126
|
+
return cmd;
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
export const AddMigrationCommand = Object.freeze({
|
|
130
|
+
create() {
|
|
131
|
+
const cmd = BaseCommand.create({
|
|
132
|
+
name: 'am',
|
|
133
|
+
description: 'Shortcut: add column migration for a model (add_<col>_<models>_table)',
|
|
134
|
+
addOptions: (command) => {
|
|
135
|
+
command.argument('<column>', 'Column name (e.g. bio)');
|
|
136
|
+
command.argument('<model>', 'Model name (e.g. user)');
|
|
137
|
+
command.option('--no-interactive', 'Skip interactive prompts');
|
|
138
|
+
},
|
|
139
|
+
execute: async (options) => executeAm(cmd, options),
|
|
140
|
+
});
|
|
141
|
+
return cmd;
|
|
142
|
+
},
|
|
143
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"D1MigrateCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/D1MigrateCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"D1MigrateCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/D1MigrateCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAyDrE;;;GAGG;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB;IAC3B;;OAEG;cACO,YAAY;EAwBtB,CAAC"}
|
|
@@ -1,31 +1,27 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* D1 Migrate Command
|
|
3
|
-
* Run Cloudflare D1 migrations using Wrangler
|
|
4
|
-
*/
|
|
5
1
|
import { BaseCommand } from '../BaseCommand.js';
|
|
2
|
+
import { WranglerD1 } from '../d1/WranglerD1.js';
|
|
6
3
|
import { resolveNpmPath } from '../../common/index.js';
|
|
7
4
|
import { appConfig } from '../../config/app.js';
|
|
8
5
|
import { Logger } from '../../config/logger.js';
|
|
9
6
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
10
|
-
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
7
|
+
const RESOLVED_VOID = Promise.resolve();
|
|
12
8
|
const runWrangler = async (cmd, args) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
});
|
|
20
|
-
return result;
|
|
9
|
+
// Back-compat entrypoint for tests; we only use this for D1 migrations apply.
|
|
10
|
+
const dbName = args[3];
|
|
11
|
+
const mode = args[4];
|
|
12
|
+
const isLocal = mode === '--local';
|
|
13
|
+
await RESOLVED_VOID;
|
|
14
|
+
return WranglerD1.applyMigrations({ cmd, dbName, isLocal });
|
|
21
15
|
};
|
|
22
16
|
const executeD1Migrate = async (cmd, options) => {
|
|
23
17
|
const isLocal = options['local'] === true || options['remote'] !== true;
|
|
24
|
-
const dbName = typeof options['database'] === 'string'
|
|
25
|
-
|
|
18
|
+
const dbName = typeof options['database'] === 'string' && options['database'].trim() !== ''
|
|
19
|
+
? options['database']
|
|
20
|
+
: 'zintrust_db';
|
|
26
21
|
cmd.info(`Running D1 migrations for ${dbName} (${isLocal ? 'local' : 'remote'})...`);
|
|
22
|
+
await RESOLVED_VOID;
|
|
27
23
|
try {
|
|
28
|
-
const output =
|
|
24
|
+
const output = WranglerD1.applyMigrations({ cmd, dbName, isLocal });
|
|
29
25
|
if (output !== '')
|
|
30
26
|
cmd.info(output);
|
|
31
27
|
cmd.info('✓ D1 migrations completed successfully');
|
|
@@ -57,9 +53,9 @@ export const D1MigrateCommand = Object.freeze({
|
|
|
57
53
|
create() {
|
|
58
54
|
const addOptions = (command) => {
|
|
59
55
|
command
|
|
60
|
-
.option('--local', 'Run
|
|
61
|
-
.option('--remote', 'Run
|
|
62
|
-
.option('--database <name>', 'D1 database name
|
|
56
|
+
.option('--local', 'Run against local D1 database (via wrangler dev)')
|
|
57
|
+
.option('--remote', 'Run against remote D1 database (production)')
|
|
58
|
+
.option('--database <name>', 'Wrangler D1 database binding name (from wrangler.toml). Defaults to "zintrust_db"');
|
|
63
59
|
};
|
|
64
60
|
const cmd = BaseCommand.create({
|
|
65
61
|
name: 'd1:migrate',
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DbSeedCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/DbSeedCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA6MrE,eAAO,MAAM,aAAa;cACd,YAAY;EAUtB,CAAC"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Db Seed Command
|
|
3
|
+
* Run database seeders from database/seeders
|
|
4
|
+
*/
|
|
5
|
+
import { SeederDiscovery } from '../../seeders/SeederDiscovery.js';
|
|
6
|
+
import { SeederLoader } from '../../seeders/SeederLoader.js';
|
|
7
|
+
import { BaseCommand } from '../BaseCommand.js';
|
|
8
|
+
import { PromptHelper } from '../PromptHelper.js';
|
|
9
|
+
import { databaseConfig } from '../../config/database.js';
|
|
10
|
+
import { Env } from '../../config/env.js';
|
|
11
|
+
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
12
|
+
import { resetDatabase, useDatabase } from '../../orm/Database.js';
|
|
13
|
+
const addSeedOptions = (command) => {
|
|
14
|
+
command
|
|
15
|
+
.option('--dir <path>', 'Seeders directory (relative to project root)', databaseConfig.seeders.directory)
|
|
16
|
+
.option('--service <domain/name>', 'Run global + service-local seeders')
|
|
17
|
+
.option('--only-service <domain/name>', 'Run only service-local seeders')
|
|
18
|
+
.option('--no-interactive', 'Skip interactive prompts');
|
|
19
|
+
};
|
|
20
|
+
const getInteractive = (options) => options['interactive'] !== false && process.env['CI'] !== 'true';
|
|
21
|
+
const ensureNonD1Driver = (driver) => {
|
|
22
|
+
if (driver === 'd1' || driver === 'd1-remote') {
|
|
23
|
+
throw ErrorFactory.createCliError('This project is configured for D1. Seeding via `zin db:seed` is not supported yet.');
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const mapConnectionToOrmConfig = (conn) => {
|
|
27
|
+
switch (conn.driver) {
|
|
28
|
+
case 'sqlite':
|
|
29
|
+
return { driver: 'sqlite', database: conn.database };
|
|
30
|
+
case 'postgresql':
|
|
31
|
+
return {
|
|
32
|
+
driver: 'postgresql',
|
|
33
|
+
host: conn.host,
|
|
34
|
+
port: conn.port,
|
|
35
|
+
database: conn.database,
|
|
36
|
+
username: conn.username,
|
|
37
|
+
password: conn.password,
|
|
38
|
+
};
|
|
39
|
+
case 'mysql':
|
|
40
|
+
return {
|
|
41
|
+
driver: 'mysql',
|
|
42
|
+
host: conn.host,
|
|
43
|
+
port: conn.port,
|
|
44
|
+
database: conn.database,
|
|
45
|
+
username: conn.username,
|
|
46
|
+
password: conn.password,
|
|
47
|
+
};
|
|
48
|
+
default:
|
|
49
|
+
return { driver: 'sqlite', database: ':memory:' };
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const confirmProductionRun = async (cmd, interactive) => {
|
|
53
|
+
if (Env.NODE_ENV !== 'production')
|
|
54
|
+
return true;
|
|
55
|
+
const confirmed = await PromptHelper.confirm('NODE_ENV=production. Continue running seeders?', false, interactive);
|
|
56
|
+
if (!confirmed) {
|
|
57
|
+
cmd.warn('Cancelled.');
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
};
|
|
62
|
+
const getServiceArgs = (options) => {
|
|
63
|
+
let serviceArg;
|
|
64
|
+
if (typeof options['onlyService'] === 'string') {
|
|
65
|
+
serviceArg = String(options['onlyService']);
|
|
66
|
+
}
|
|
67
|
+
else if (typeof options['service'] === 'string') {
|
|
68
|
+
serviceArg = String(options['service']);
|
|
69
|
+
}
|
|
70
|
+
const includeGlobal = typeof options['onlyService'] !== 'string';
|
|
71
|
+
return { service: serviceArg, includeGlobal };
|
|
72
|
+
};
|
|
73
|
+
const parseServiceRef = (raw) => {
|
|
74
|
+
const trimmed = raw.trim();
|
|
75
|
+
const parts = trimmed.split('/').filter((p) => p.trim().length > 0);
|
|
76
|
+
if (parts.length !== 2) {
|
|
77
|
+
throw ErrorFactory.createCliError(`Invalid service reference: '${raw}'. Expected format: <domain>/<name>`);
|
|
78
|
+
}
|
|
79
|
+
return { domain: parts[0], name: parts[1] };
|
|
80
|
+
};
|
|
81
|
+
const normalizeSeederNameArg = (raw) => {
|
|
82
|
+
const trimmed = raw.trim();
|
|
83
|
+
if (trimmed.endsWith('.ts'))
|
|
84
|
+
return trimmed.slice(0, -3);
|
|
85
|
+
if (trimmed.endsWith('.js'))
|
|
86
|
+
return trimmed.slice(0, -3);
|
|
87
|
+
return trimmed;
|
|
88
|
+
};
|
|
89
|
+
const selectSeederFiles = (files, seederName) => {
|
|
90
|
+
if (seederName !== undefined) {
|
|
91
|
+
return files.filter((filePath) => {
|
|
92
|
+
const base = filePath.split('/').pop() ?? '';
|
|
93
|
+
const withoutExt = base.replace(/\.(ts|js)$/u, '');
|
|
94
|
+
return withoutExt === seederName;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
const databaseSeeder = files.find((filePath) => {
|
|
98
|
+
const base = filePath.split('/').pop() ?? '';
|
|
99
|
+
const withoutExt = base.replace(/\.(ts|js)$/u, '');
|
|
100
|
+
return withoutExt === 'DatabaseSeeder';
|
|
101
|
+
});
|
|
102
|
+
if (databaseSeeder !== undefined)
|
|
103
|
+
return [databaseSeeder];
|
|
104
|
+
return files;
|
|
105
|
+
};
|
|
106
|
+
const executeSeed = async (options, cmd) => {
|
|
107
|
+
const interactive = getInteractive(options);
|
|
108
|
+
const okToProceed = await confirmProductionRun(cmd, interactive);
|
|
109
|
+
if (!okToProceed)
|
|
110
|
+
return;
|
|
111
|
+
const conn = databaseConfig.getConnection();
|
|
112
|
+
ensureNonD1Driver(conn.driver);
|
|
113
|
+
const ormConfig = mapConnectionToOrmConfig(conn);
|
|
114
|
+
const db = useDatabase(ormConfig, 'default');
|
|
115
|
+
const dirOpt = typeof options['dir'] === 'string' ? options['dir'] : databaseConfig.seeders.directory;
|
|
116
|
+
const { service, includeGlobal } = getServiceArgs(options);
|
|
117
|
+
const projectRoot = process.cwd();
|
|
118
|
+
const globalDir = SeederDiscovery.resolveDir(projectRoot, dirOpt);
|
|
119
|
+
const globalFiles = includeGlobal ? SeederDiscovery.listSeederFiles(globalDir) : [];
|
|
120
|
+
let serviceFiles = [];
|
|
121
|
+
if (service !== undefined) {
|
|
122
|
+
const { domain, name } = parseServiceRef(service);
|
|
123
|
+
const serviceRoot = `${projectRoot}/services/${domain}/${name}`;
|
|
124
|
+
const serviceDir = SeederDiscovery.resolveDir(serviceRoot, dirOpt);
|
|
125
|
+
serviceFiles = SeederDiscovery.listSeederFiles(serviceDir);
|
|
126
|
+
}
|
|
127
|
+
const seederArgRaw = Array.isArray(options.args) ? options.args[0] : undefined;
|
|
128
|
+
const seederName = typeof seederArgRaw === 'string' && seederArgRaw.trim() !== ''
|
|
129
|
+
? normalizeSeederNameArg(seederArgRaw)
|
|
130
|
+
: undefined;
|
|
131
|
+
const selectedGlobal = selectSeederFiles(globalFiles, seederName);
|
|
132
|
+
const selectedService = selectSeederFiles(serviceFiles, seederName);
|
|
133
|
+
const selected = [...selectedGlobal, ...selectedService];
|
|
134
|
+
if (seederName !== undefined) {
|
|
135
|
+
if (selected.length === 0) {
|
|
136
|
+
throw ErrorFactory.createCliError(`Seeder not found: ${seederName} (dir=${dirOpt}, global=${globalFiles.length}, service=${serviceFiles.length})`);
|
|
137
|
+
}
|
|
138
|
+
if (selected.length > 1) {
|
|
139
|
+
throw ErrorFactory.createCliError(`Seeder name is ambiguous: ${seederName} (matches=${selected.length}). Use --only-service or adjust name.`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (selected.length === 0) {
|
|
143
|
+
cmd.info('No seeders found.');
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
cmd.info(`Running ${selected.length} seeder(s)...`);
|
|
147
|
+
await db.connect();
|
|
148
|
+
try {
|
|
149
|
+
await selected.reduce(async (previous, filePath) => {
|
|
150
|
+
await previous;
|
|
151
|
+
const loaded = await SeederLoader.load(filePath);
|
|
152
|
+
cmd.info(`→ ${loaded.name}`);
|
|
153
|
+
await loaded.run(db);
|
|
154
|
+
cmd.success(`✓ Seeded: ${loaded.name}`);
|
|
155
|
+
}, Promise.resolve());
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
await resetDatabase();
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
export const DbSeedCommand = Object.freeze({
|
|
162
|
+
create() {
|
|
163
|
+
const cmd = BaseCommand.create({
|
|
164
|
+
name: 'db:seed',
|
|
165
|
+
description: 'Run database seeders',
|
|
166
|
+
addOptions: addSeedOptions,
|
|
167
|
+
execute: async (options) => executeSeed(options, cmd),
|
|
168
|
+
});
|
|
169
|
+
return cmd;
|
|
170
|
+
},
|
|
171
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DebugCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/DebugCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"DebugCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/DebugCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAyDrE;;GAEG;AACH,eAAO,MAAM,YAAY;IACvB;;OAEG;kBApBc,YAAY;EAsB7B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FixCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/FixCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"FixCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/FixCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAoDrE;;GAEG;AACH,eAAO,MAAM,UAAU;IACrB;;OAEG;cACO,YAAY;EAkBtB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT Dev Command
|
|
3
|
+
* Mint a local development JWT for quick manual API testing.
|
|
4
|
+
*/
|
|
5
|
+
import { type IBaseCommand } from '../BaseCommand';
|
|
6
|
+
export declare const JwtDevCommand: IBaseCommand;
|
|
7
|
+
export default JwtDevCommand;
|
|
8
|
+
//# sourceMappingURL=JwtDevCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JwtDevCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/JwtDevCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA6FvF,eAAO,MAAM,aAAa,EAAE,YAqD3B,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT Dev Command
|
|
3
|
+
* Mint a local development JWT for quick manual API testing.
|
|
4
|
+
*/
|
|
5
|
+
import { BaseCommand } from '../BaseCommand.js';
|
|
6
|
+
import { appConfig } from '../../config/app.js';
|
|
7
|
+
import { securityConfig } from '../../config/security.js';
|
|
8
|
+
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
9
|
+
import { JwtManager } from '../../security/JwtManager.js';
|
|
10
|
+
const parseExpiresToSeconds = (value) => {
|
|
11
|
+
const raw = typeof value === 'string' ? value.trim() : '';
|
|
12
|
+
if (raw === '')
|
|
13
|
+
return 60 * 60;
|
|
14
|
+
// Allow raw seconds
|
|
15
|
+
if (/^\d+$/.test(raw)) {
|
|
16
|
+
const seconds = Number.parseInt(raw, 10);
|
|
17
|
+
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
18
|
+
throw ErrorFactory.createCliError(`Invalid --expires '${raw}'. Must be > 0 seconds.`);
|
|
19
|
+
}
|
|
20
|
+
return seconds;
|
|
21
|
+
}
|
|
22
|
+
const match = /^(\d+)([smhd])$/i.exec(raw);
|
|
23
|
+
if (!match) {
|
|
24
|
+
throw ErrorFactory.createCliError(`Invalid --expires '${raw}'. Use seconds (e.g. 3600) or a duration like 30m, 1h, 7d.`);
|
|
25
|
+
}
|
|
26
|
+
const amount = Number.parseInt(match[1] ?? '', 10);
|
|
27
|
+
const unit = (match[2] ?? '').toLowerCase();
|
|
28
|
+
if (!Number.isFinite(amount) || amount <= 0) {
|
|
29
|
+
throw ErrorFactory.createCliError(`Invalid --expires '${raw}'. Must be > 0.`);
|
|
30
|
+
}
|
|
31
|
+
const multipliers = {
|
|
32
|
+
s: 1,
|
|
33
|
+
m: 60,
|
|
34
|
+
h: 60 * 60,
|
|
35
|
+
d: 24 * 60 * 60,
|
|
36
|
+
};
|
|
37
|
+
const multiplier = multipliers[unit];
|
|
38
|
+
if (multiplier === undefined) {
|
|
39
|
+
throw ErrorFactory.createCliError(`Invalid --expires '${raw}'. Supported units: s, m, h, d (e.g. 30m, 1h).`);
|
|
40
|
+
}
|
|
41
|
+
return amount * multiplier;
|
|
42
|
+
};
|
|
43
|
+
const assertNotProduction = (allowProduction) => {
|
|
44
|
+
if (!appConfig.isProduction())
|
|
45
|
+
return;
|
|
46
|
+
if (allowProduction === true)
|
|
47
|
+
return;
|
|
48
|
+
throw ErrorFactory.createCliError("Refusing to mint a dev JWT in production. Use --allow-production only if you know what you're doing.");
|
|
49
|
+
};
|
|
50
|
+
const createJwt = (payload, expiresInSeconds) => {
|
|
51
|
+
const algorithm = securityConfig.jwt.algorithm;
|
|
52
|
+
const secret = securityConfig.jwt.secret;
|
|
53
|
+
const jwt = JwtManager.create();
|
|
54
|
+
if (algorithm === 'HS256' || algorithm === 'HS512') {
|
|
55
|
+
jwt.setHmacSecret(secret);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
throw ErrorFactory.createCliError(`JWT algorithm '${algorithm}' is not supported by zin jwt:dev (HS256/HS512 only).`);
|
|
59
|
+
}
|
|
60
|
+
return jwt.sign(payload, {
|
|
61
|
+
algorithm,
|
|
62
|
+
expiresIn: expiresInSeconds,
|
|
63
|
+
issuer: securityConfig.jwt.issuer,
|
|
64
|
+
audience: securityConfig.jwt.audience,
|
|
65
|
+
subject: typeof payload.sub === 'string' ? payload.sub : undefined,
|
|
66
|
+
jwtId: jwt.generateJwtId(),
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
export const JwtDevCommand = Object.freeze(BaseCommand.create({
|
|
70
|
+
name: 'jwt:dev',
|
|
71
|
+
description: 'Mint a local development JWT (for manual API testing)',
|
|
72
|
+
aliases: ['jwt:token', 'jwt:mint'],
|
|
73
|
+
addOptions: (command) => {
|
|
74
|
+
command
|
|
75
|
+
.option('--sub <sub>', 'JWT subject claim (default: 1)', '1')
|
|
76
|
+
.option('--email <email>', 'Email claim')
|
|
77
|
+
.option('--role <role>', 'Role claim')
|
|
78
|
+
.option('--expires <duration>', "Expiry: seconds or 30m/1h/7d (default: '1h')", '1h')
|
|
79
|
+
.option('--json', 'Output machine-readable JSON')
|
|
80
|
+
.option('--allow-production', 'Allow running in production (dangerous)');
|
|
81
|
+
},
|
|
82
|
+
execute: (options) => {
|
|
83
|
+
assertNotProduction(options.allowProduction);
|
|
84
|
+
const expiresInSeconds = parseExpiresToSeconds(options.expires);
|
|
85
|
+
const payload = {
|
|
86
|
+
...(typeof options.sub === 'string' && options.sub.trim() !== ''
|
|
87
|
+
? { sub: options.sub.trim() }
|
|
88
|
+
: {}),
|
|
89
|
+
...(typeof options.email === 'string' && options.email.trim() !== ''
|
|
90
|
+
? { email: options.email.trim() }
|
|
91
|
+
: {}),
|
|
92
|
+
...(typeof options.role === 'string' && options.role.trim() !== ''
|
|
93
|
+
? { role: options.role.trim() }
|
|
94
|
+
: {}),
|
|
95
|
+
};
|
|
96
|
+
const token = createJwt(payload, expiresInSeconds);
|
|
97
|
+
/* eslint-disable no-console */
|
|
98
|
+
if (options.json === true) {
|
|
99
|
+
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
100
|
+
console.log(JSON.stringify({
|
|
101
|
+
token,
|
|
102
|
+
algorithm: securityConfig.jwt.algorithm,
|
|
103
|
+
expiresIn: expiresInSeconds,
|
|
104
|
+
issuedAt: nowSeconds,
|
|
105
|
+
expiresAt: nowSeconds + expiresInSeconds,
|
|
106
|
+
payload,
|
|
107
|
+
}));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
console.log(token);
|
|
111
|
+
/* eslint-enable no-console */
|
|
112
|
+
},
|
|
113
|
+
}));
|
|
114
|
+
export default JwtDevCommand;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeyGenerateCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/KeyGenerateCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"KeyGenerateCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/KeyGenerateCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAQrE,eAAO,MAAM,kBAAkB;cACnB,YAAY;EAmEtB,CAAC"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* LogsCommand - CLI command for viewing and managing logs
|
|
3
3
|
* Commands: zin logs, zin logs --follow, zin logs --level error, zin logs --clear
|
|
4
4
|
*/
|
|
5
|
-
import { IBaseCommand } from '../BaseCommand';
|
|
6
|
-
import { Command } from 'commander';
|
|
5
|
+
import type { IBaseCommand } from '../BaseCommand';
|
|
6
|
+
import type { Command } from 'commander';
|
|
7
7
|
export declare const LogsCommand: Readonly<{
|
|
8
8
|
/**
|
|
9
9
|
* Create a new logs command instance
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LogsCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/LogsCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"LogsCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/LogsCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AASrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+MzC,eAAO,MAAM,WAAW;IACtB;;OAEG;cACO,YAAY;IAwBtB;;;OAGG;sBACe,OAAO,GAAG,IAAI;EAchC,CAAC;AAEH,eAAe,WAAW,CAAC"}
|
|
@@ -95,23 +95,57 @@ const followLogs = (category) => {
|
|
|
95
95
|
Logger.info(chalk.blue(`👀 Following logs: ${logFile}\n`));
|
|
96
96
|
Logger.info(chalk.gray('Press Ctrl+C to stop...\n'));
|
|
97
97
|
let lastSize = 0;
|
|
98
|
+
let currentStream = null;
|
|
99
|
+
const safeDestroy = (stream) => {
|
|
100
|
+
try {
|
|
101
|
+
const anyStream = stream;
|
|
102
|
+
if (typeof anyStream.destroy === 'function')
|
|
103
|
+
anyStream.destroy();
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// best-effort
|
|
107
|
+
}
|
|
108
|
+
};
|
|
98
109
|
const interval = setInterval(() => {
|
|
99
110
|
if (!fs.existsSync(logFile))
|
|
100
111
|
return;
|
|
101
112
|
const stats = fs.statSync(logFile);
|
|
102
113
|
if (stats.size <= lastSize)
|
|
103
114
|
return;
|
|
104
|
-
|
|
115
|
+
// Close previous stream if it exists
|
|
116
|
+
if (currentStream !== null) {
|
|
117
|
+
safeDestroy(currentStream);
|
|
118
|
+
}
|
|
119
|
+
currentStream = fs.createReadStream(logFile, {
|
|
105
120
|
start: lastSize,
|
|
106
121
|
encoding: 'utf-8',
|
|
107
122
|
});
|
|
108
|
-
|
|
123
|
+
currentStream.on('data', (chunk) => {
|
|
109
124
|
processLogChunk(chunk, loggerInstance);
|
|
110
125
|
});
|
|
126
|
+
currentStream.on('end', () => {
|
|
127
|
+
// Clean up stream reference when done
|
|
128
|
+
if (currentStream !== null) {
|
|
129
|
+
safeDestroy(currentStream);
|
|
130
|
+
currentStream = null;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
currentStream.on('error', (error) => {
|
|
134
|
+
Logger.error('Stream error', { error });
|
|
135
|
+
if (currentStream !== null) {
|
|
136
|
+
safeDestroy(currentStream);
|
|
137
|
+
currentStream = null;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
111
140
|
lastSize = stats.size;
|
|
112
141
|
}, 1000);
|
|
113
142
|
process.on('SIGINT', () => {
|
|
114
143
|
clearInterval(interval);
|
|
144
|
+
// Clean up stream on exit
|
|
145
|
+
if (currentStream !== null) {
|
|
146
|
+
safeDestroy(currentStream);
|
|
147
|
+
currentStream = null;
|
|
148
|
+
}
|
|
115
149
|
Logger.info(chalk.yellow('\n\nLog following stopped'));
|
|
116
150
|
process.exit(0);
|
|
117
151
|
});
|