@zintrust/core 0.1.19 → 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 +10 -10
- package/bin/zintrust-main.d.ts.map +1 -1
- package/bin/zintrust-main.js +9 -0
- package/package.json +2 -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/zintrust.svg +30 -0
- package/routes/api.d.ts.map +1 -1
- package/routes/api.js +41 -17
- 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/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/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 +10 -4
- 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 +1 -1
- package/src/cli/commands/NewCommand.d.ts.map +1 -1
- package/src/cli/commands/NewCommand.js +12 -4
- 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/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/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/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 +36 -4
- 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/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/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 +1 -1
- package/src/config/database.d.ts.map +1 -1
- package/src/config/database.js +92 -6
- 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 +1 -1
- package/src/config/logging/KvLogger.js +1 -1
- package/src/config/logging/SlackLogger.js +2 -2
- package/src/config/middleware.d.ts +20 -1
- package/src/config/middleware.d.ts.map +1 -1
- package/src/config/middleware.js +135 -3
- package/src/config/security.d.ts +1 -1
- package/src/config/security.js +1 -1
- package/src/config/type.d.ts +1 -1
- 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 +64 -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/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 +3 -1
- package/src/node.d.ts.map +1 -1
- package/src/node.js +6 -2
- 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/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 -99
- 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 +58 -2
- 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/metrics.d.ts +2 -0
- package/src/routes/metrics.d.ts.map +1 -0
- package/src/routes/metrics.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/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 +1 -1
- 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 +40 -0
- package/src/scripts/TemplateSync.js +86 -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/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 +3 -2
- package/src/templates/project/basic/app/Controllers/AuthController.ts.tpl +217 -0
- package/src/templates/project/basic/app/Controllers/UserController.ts.tpl +1 -12
- 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 +10 -447
- 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 -128
- package/src/templates/project/basic/config/cache.ts.tpl +15 -91
- 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 -122
- 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 +8 -23
- package/src/templates/project/basic/config/mail.ts.tpl +15 -114
- package/src/templates/project/basic/config/microservices.ts.tpl +11 -97
- package/src/templates/project/basic/config/middleware.ts.tpl +25 -43
- package/src/templates/project/basic/config/notification.ts.tpl +14 -126
- 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 -132
- package/src/templates/project/basic/config/type.ts.tpl +33 -451
- 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/routes/api.ts.tpl +71 -33
- package/src/templates/project/basic/routes/metrics.ts.tpl +22 -0
- package/src/templates/project/basic/tsconfig.json.tpl +12 -11
- 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,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Controller
|
|
3
|
+
* Minimal, real auth endpoints backing the example API routes.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
getString,
|
|
8
|
+
Auth,
|
|
9
|
+
Logger,
|
|
10
|
+
getValidatedBody,
|
|
11
|
+
useDatabase,
|
|
12
|
+
QueryBuilder,
|
|
13
|
+
JwtManager,
|
|
14
|
+
TokenRevocation
|
|
15
|
+
} from '@zintrust/core';
|
|
16
|
+
import type { AuthControllerApi, JsonRecord, UserRow } from '@app/Types/controller';
|
|
17
|
+
import type { IRequest, IResponse } from '@zintrust/core';
|
|
18
|
+
import User from '@app/Models/User';
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
const pickPublicUser = (row: UserRow): { id: unknown; name: string; email: string } => {
|
|
22
|
+
return {
|
|
23
|
+
id: row.id,
|
|
24
|
+
name: getString(row.name),
|
|
25
|
+
email: getString(row.email),
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Authenticates a user by email and password.
|
|
31
|
+
* Validates credentials against the database and returns a JWT access token on success.
|
|
32
|
+
* Logs all authentication attempts for security auditing.
|
|
33
|
+
* @param req - HTTP request containing email and password
|
|
34
|
+
* @param res - HTTP response to send authentication result
|
|
35
|
+
* @returns Promise that resolves after sending the response
|
|
36
|
+
*/
|
|
37
|
+
async function login(req: IRequest, res: IResponse): Promise<void> {
|
|
38
|
+
const body = getValidatedBody<JsonRecord>(req);
|
|
39
|
+
if (!body) {
|
|
40
|
+
Logger.error('AuthController.login: validation middleware did not populate req.validated.body');
|
|
41
|
+
return res.setStatus(500).json({ error: 'Internal server error' });
|
|
42
|
+
}
|
|
43
|
+
const email = getString(body['email']);
|
|
44
|
+
const password = getString(body['password']);
|
|
45
|
+
const ipAddress = req.getRaw().socket.remoteAddress ?? 'unknown';
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
const existing = await User.where('email', '=', email).limit(1).first<UserRow>();
|
|
49
|
+
|
|
50
|
+
if (existing === null) {
|
|
51
|
+
Logger.warn('AuthController.login: failed login attempt', {
|
|
52
|
+
email,
|
|
53
|
+
ip: ipAddress,
|
|
54
|
+
reason: 'user_not_found',
|
|
55
|
+
timestamp: new Date().toISOString(),
|
|
56
|
+
});
|
|
57
|
+
res.setStatus(401).json({ error: 'Invalid credentials' });
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const passwordHash = getString(existing.password);
|
|
62
|
+
const ok = await Auth.compare(password, passwordHash);
|
|
63
|
+
if (!ok) {
|
|
64
|
+
Logger.warn('AuthController.login: failed login attempt', {
|
|
65
|
+
email,
|
|
66
|
+
ip: ipAddress,
|
|
67
|
+
reason: 'invalid_password',
|
|
68
|
+
timestamp: new Date().toISOString(),
|
|
69
|
+
});
|
|
70
|
+
res.setStatus(401).json({ error: 'Invalid credentials' });
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const user = pickPublicUser(existing);
|
|
75
|
+
|
|
76
|
+
const subject = ((): string | undefined => {
|
|
77
|
+
const id = user.id;
|
|
78
|
+
if (typeof id === 'string' && id.length > 0) return id;
|
|
79
|
+
if (typeof id === 'number' && Number.isFinite(id)) return String(id);
|
|
80
|
+
return undefined;
|
|
81
|
+
})();
|
|
82
|
+
|
|
83
|
+
const token = JwtManager.signAccessToken({
|
|
84
|
+
sub: subject,
|
|
85
|
+
email,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
Logger.info('AuthController.login: successful login', {
|
|
89
|
+
userId: subject,
|
|
90
|
+
email,
|
|
91
|
+
ip: ipAddress,
|
|
92
|
+
timestamp: new Date().toISOString(),
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
res.json({
|
|
96
|
+
token,
|
|
97
|
+
token_type: 'Bearer',
|
|
98
|
+
user,
|
|
99
|
+
});
|
|
100
|
+
} catch (error) {
|
|
101
|
+
Logger.error('AuthController.login: unexpected error', {
|
|
102
|
+
email,
|
|
103
|
+
ip: ipAddress,
|
|
104
|
+
error: error instanceof Error ? error.message : String(error),
|
|
105
|
+
timestamp: new Date().toISOString(),
|
|
106
|
+
});
|
|
107
|
+
res.setStatus(500).json({ error: 'Login failed' });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Registers a new user with name, email, and password.
|
|
113
|
+
* Validates email uniqueness, hashes password, and stores user in database.
|
|
114
|
+
* Returns 201 on success, 409 if email already exists.
|
|
115
|
+
* @param req - HTTP request containing name, email, and password
|
|
116
|
+
* @param res - HTTP response to send registration result
|
|
117
|
+
* @returns Promise that resolves after sending the response
|
|
118
|
+
*/
|
|
119
|
+
async function register(req: IRequest, res: IResponse): Promise<void> {
|
|
120
|
+
const body = getValidatedBody<JsonRecord>(req);
|
|
121
|
+
if (!body) {
|
|
122
|
+
Logger.error(
|
|
123
|
+
'AuthController.register: validation middleware did not populate req.validated.body'
|
|
124
|
+
);
|
|
125
|
+
res.setStatus(500).json({ error: 'Internal server error' });
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const name = getString(body['name']);
|
|
129
|
+
const email = getString(body['email']);
|
|
130
|
+
const password = getString(body['password']);
|
|
131
|
+
const ipAddress = req.getRaw().socket.remoteAddress ?? 'unknown';
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const db = useDatabase();
|
|
135
|
+
|
|
136
|
+
const existing = await QueryBuilder.create('users', db)
|
|
137
|
+
.where('email', '=', email)
|
|
138
|
+
.limit(1)
|
|
139
|
+
.first<UserRow>();
|
|
140
|
+
|
|
141
|
+
if (existing !== null) {
|
|
142
|
+
Logger.warn('AuthController.register: duplicate email attempt', {
|
|
143
|
+
email,
|
|
144
|
+
ip: ipAddress,
|
|
145
|
+
timestamp: new Date().toISOString(),
|
|
146
|
+
});
|
|
147
|
+
res.setStatus(409).json({ error: 'Email already registered' });
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const passwordHash = await Auth.hash(password);
|
|
152
|
+
|
|
153
|
+
await QueryBuilder.create('users', db).insert({
|
|
154
|
+
name,
|
|
155
|
+
email,
|
|
156
|
+
password: passwordHash,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
Logger.info('AuthController.register: successful registration', {
|
|
160
|
+
email,
|
|
161
|
+
ip: ipAddress,
|
|
162
|
+
timestamp: new Date().toISOString(),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
res.setStatus(201).json({ message: 'Registered' });
|
|
166
|
+
} catch (error) {
|
|
167
|
+
Logger.error('AuthController.register failed', error);
|
|
168
|
+
res.setStatus(500).json({ error: 'Registration failed' });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Logs out the current user by revoking their JWT token.
|
|
174
|
+
* Extracts authorization header and marks token as revoked.
|
|
175
|
+
* Requires persistent token revocation store for stateless JWT validation.
|
|
176
|
+
* @param req - HTTP request containing authorization header with JWT token
|
|
177
|
+
* @param res - HTTP response to send logout confirmation
|
|
178
|
+
* @returns Promise that resolves after sending the response
|
|
179
|
+
*/
|
|
180
|
+
async function logout(req: IRequest, res: IResponse): Promise<void> {
|
|
181
|
+
const authHeader =
|
|
182
|
+
typeof req.getHeader === 'function' ? req.getHeader('authorization') : undefined;
|
|
183
|
+
TokenRevocation.revoke(authHeader);
|
|
184
|
+
res.json({ message: 'Logged out' });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Refreshes the user's JWT access token.
|
|
189
|
+
* Generates a new token with the same claims as the current user.
|
|
190
|
+
* Returns 401 if user is not authenticated.
|
|
191
|
+
* @param req - HTTP request with user populated by authentication middleware
|
|
192
|
+
* @param res - HTTP response to send refreshed token
|
|
193
|
+
* @returns Promise that resolves after sending the response
|
|
194
|
+
*/
|
|
195
|
+
async function refresh(req: IRequest, res: IResponse): Promise<void> {
|
|
196
|
+
const user = req.user;
|
|
197
|
+
if (user === undefined) {
|
|
198
|
+
res.setStatus(401).json({ error: 'Unauthorized' });
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const token = JwtManager.signAccessToken(user);
|
|
203
|
+
res.json({ token, token_type: 'Bearer' });
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export const AuthController = Object.freeze({
|
|
207
|
+
create(): AuthControllerApi {
|
|
208
|
+
return {
|
|
209
|
+
login,
|
|
210
|
+
register,
|
|
211
|
+
logout,
|
|
212
|
+
refresh,
|
|
213
|
+
};
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
export default AuthController;
|
|
@@ -5,19 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
import { User } from '@app/Models/User';
|
|
7
7
|
import { IRequest, Logger, IResponse } from '@zintrust/core';
|
|
8
|
+
import { IUserController } from '@app/Types/controller';
|
|
8
9
|
|
|
9
|
-
/**
|
|
10
|
-
* User Controller Interface
|
|
11
|
-
*/
|
|
12
|
-
export interface IUserController {
|
|
13
|
-
index(req: IRequest, res: IResponse): Promise<void>;
|
|
14
|
-
show(req: IRequest, res: IResponse): Promise<void>;
|
|
15
|
-
create(req: IRequest, res: IResponse): Promise<void>;
|
|
16
|
-
store(req: IRequest, res: IResponse): Promise<void>;
|
|
17
|
-
edit(req: IRequest, res: IResponse): Promise<void>;
|
|
18
|
-
update(req: IRequest, res: IResponse): Promise<void>;
|
|
19
|
-
destroy(req: IRequest, res: IResponse): Promise<void>;
|
|
20
|
-
}
|
|
21
10
|
|
|
22
11
|
/**
|
|
23
12
|
* User Controller Methods
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { IRequest, IResponse } from '@zintrust/core';
|
|
2
|
+
|
|
3
|
+
export type JsonRecord = Record<string, unknown>;
|
|
4
|
+
|
|
5
|
+
export type LoginBody = {
|
|
6
|
+
email: string;
|
|
7
|
+
password: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type RegisterBody = {
|
|
11
|
+
name: string;
|
|
12
|
+
email: string;
|
|
13
|
+
password: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type UserRow = {
|
|
17
|
+
id?: unknown;
|
|
18
|
+
name?: unknown;
|
|
19
|
+
email?: unknown;
|
|
20
|
+
password?: unknown;
|
|
21
|
+
};
|
|
22
|
+
export type AuthControllerApi = {
|
|
23
|
+
login(req: IRequest, res: IResponse): Promise<void>;
|
|
24
|
+
register(req: IRequest, res: IResponse): Promise<void>;
|
|
25
|
+
logout(req: IRequest, res: IResponse): Promise<void>;
|
|
26
|
+
refresh(req: IRequest, res: IResponse): Promise<void>;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type ValidationErrorLike = {
|
|
30
|
+
name?: unknown;
|
|
31
|
+
toObject?: () => Record<string, string[]>;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* User Controller Interface
|
|
36
|
+
*/
|
|
37
|
+
export interface IUserController {
|
|
38
|
+
index(req: IRequest, res: IResponse): Promise<void>;
|
|
39
|
+
show(req: IRequest, res: IResponse): Promise<void>;
|
|
40
|
+
create(req: IRequest, res: IResponse): Promise<void>;
|
|
41
|
+
store(req: IRequest, res: IResponse): Promise<void>;
|
|
42
|
+
fill(req: IRequest, res: IResponse): Promise<void>;
|
|
43
|
+
edit(req: IRequest, res: IResponse): Promise<void>;
|
|
44
|
+
update(req: IRequest, res: IResponse): Promise<void>;
|
|
45
|
+
destroy(req: IRequest, res: IResponse): Promise<void>;
|
|
46
|
+
}
|
|
@@ -1,240 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* FileLogWriter (
|
|
2
|
+
* FileLogWriter (template)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Keep this file declarative:
|
|
5
|
+
* - Core owns Node-specific file logging implementation.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import * as fs from 'node:fs';
|
|
11
|
-
import * as path from 'node:path';
|
|
12
|
-
|
|
13
|
-
const getCwdSafe = (): string => {
|
|
14
|
-
try {
|
|
15
|
-
if (typeof process === 'undefined' || typeof process.cwd !== 'function') return '';
|
|
16
|
-
return process.cwd();
|
|
17
|
-
} catch {
|
|
18
|
-
return '';
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const getDateStr = (d: Date): string => d.toISOString().slice(0, 10);
|
|
23
|
-
|
|
24
|
-
const isAppLogFile = (fileName: string): boolean =>
|
|
25
|
-
fileName.startsWith('app-') && fileName.endsWith('.log');
|
|
26
|
-
|
|
27
|
-
const parseDateFromLogFilename = (fileName: string): number | null => {
|
|
28
|
-
const match = /^app-(\d{4}-\d{2}-\d{2})(?:-\d+)?\.log$/.exec(fileName);
|
|
29
|
-
if (match?.[1] === undefined) return null;
|
|
30
|
-
|
|
31
|
-
const parsed = Date.parse(`${match[1]}T00:00:00.000Z`);
|
|
32
|
-
return Number.isNaN(parsed) ? null : parsed;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const isOlderThanCutoffByMtime = (fullPath: string, cutoff: number): boolean => {
|
|
36
|
-
try {
|
|
37
|
-
const stat = fs.statSync(fullPath);
|
|
38
|
-
return stat.mtime.getTime() < cutoff;
|
|
39
|
-
} catch {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const safeUnlink = (fullPath: string): void => {
|
|
45
|
-
try {
|
|
46
|
-
fs.unlinkSync(fullPath);
|
|
47
|
-
} catch {
|
|
48
|
-
// best-effort
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const readDirSafe = (dirPath: string): string[] => {
|
|
53
|
-
try {
|
|
54
|
-
return fs.readdirSync(dirPath);
|
|
55
|
-
} catch {
|
|
56
|
-
return [];
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const shouldDeleteLogFile = (fileName: string, fullPath: string, cutoff: number): boolean => {
|
|
61
|
-
const parsed = parseDateFromLogFilename(fileName);
|
|
62
|
-
if (parsed !== null) return parsed < cutoff;
|
|
63
|
-
|
|
64
|
-
return isOlderThanCutoffByMtime(fullPath, cutoff);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const cleanupOldLogs = (logsDir: string, keepDays: number): void => {
|
|
68
|
-
if (keepDays <= 0) return;
|
|
69
|
-
|
|
70
|
-
const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1000;
|
|
71
|
-
const files = readDirSafe(logsDir);
|
|
72
|
-
if (files.length === 0) return;
|
|
73
|
-
|
|
74
|
-
for (const fileName of files) {
|
|
75
|
-
if (!isAppLogFile(fileName)) continue;
|
|
76
|
-
|
|
77
|
-
const fullPath = path.join(logsDir, fileName);
|
|
78
|
-
if (!shouldDeleteLogFile(fileName, fullPath, cutoff)) continue;
|
|
79
|
-
|
|
80
|
-
safeUnlink(fullPath);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
type CleanOnceOptions = {
|
|
85
|
-
logsDir?: string;
|
|
86
|
-
keepDays?: number;
|
|
87
|
-
maxTotalSize?: number;
|
|
88
|
-
keepFiles?: number;
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const listAppLogFiles = (
|
|
92
|
-
logsDir: string,
|
|
93
|
-
order: 'newest-first' | 'oldest-first'
|
|
94
|
-
): Array<{ name: string; path: string }> => {
|
|
95
|
-
const files = readDirSafe(logsDir)
|
|
96
|
-
.filter((f) => isAppLogFile(f))
|
|
97
|
-
.map((f) => ({ name: f, path: path.join(logsDir, f) }));
|
|
98
|
-
|
|
99
|
-
return files.sort((a, b) => {
|
|
100
|
-
if (a.name === b.name) return 0;
|
|
101
|
-
const newerFirst = a.name < b.name ? 1 : -1;
|
|
102
|
-
return order === 'newest-first' ? newerFirst : -newerFirst;
|
|
103
|
-
});
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const enforceKeepFilesPolicy = (
|
|
107
|
-
filesNewestFirst: Array<{ name: string; path: string }>,
|
|
108
|
-
keepFiles: number | undefined,
|
|
109
|
-
deleted: string[]
|
|
110
|
-
): void => {
|
|
111
|
-
if (typeof keepFiles !== 'number' || keepFiles < 0) return;
|
|
112
|
-
if (filesNewestFirst.length <= keepFiles) return;
|
|
113
|
-
|
|
114
|
-
const toDelete = filesNewestFirst.slice(keepFiles);
|
|
115
|
-
for (const f of toDelete) {
|
|
116
|
-
safeUnlink(f.path);
|
|
117
|
-
deleted.push(f.path);
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
const getFileSizesTotal = (
|
|
122
|
-
filesOldestFirst: Array<{ name: string; path: string }>
|
|
123
|
-
): { total: number; sizes: Array<{ path: string; size: number }> } => {
|
|
124
|
-
let total = 0;
|
|
125
|
-
const sizes: Array<{ path: string; size: number }> = [];
|
|
126
|
-
|
|
127
|
-
for (const file of filesOldestFirst) {
|
|
128
|
-
try {
|
|
129
|
-
const stat = fs.statSync(file.path);
|
|
130
|
-
sizes.push({ path: file.path, size: stat.size });
|
|
131
|
-
total += stat.size;
|
|
132
|
-
} catch {
|
|
133
|
-
// ignore
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return { total, sizes };
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const deleteOldestUntilWithinLimit = (
|
|
141
|
-
sizesOldestFirst: Array<{ path: string; size: number }>,
|
|
142
|
-
maxTotalSize: number,
|
|
143
|
-
deleted: string[],
|
|
144
|
-
initialTotal: number
|
|
145
|
-
): void => {
|
|
146
|
-
let total = initialTotal;
|
|
147
|
-
|
|
148
|
-
let idx = 0;
|
|
149
|
-
while (total > maxTotalSize && idx < sizesOldestFirst.length) {
|
|
150
|
-
const del = sizesOldestFirst[idx];
|
|
151
|
-
safeUnlink(del.path);
|
|
152
|
-
deleted.push(del.path);
|
|
153
|
-
total -= del.size;
|
|
154
|
-
idx++;
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
const enforceMaxTotalSizePolicy = (
|
|
159
|
-
logsDir: string,
|
|
160
|
-
maxTotalSize: number | undefined,
|
|
161
|
-
deleted: string[]
|
|
162
|
-
): void => {
|
|
163
|
-
if (typeof maxTotalSize !== 'number' || maxTotalSize <= 0) return;
|
|
164
|
-
|
|
165
|
-
const remainingOldestFirst = listAppLogFiles(logsDir, 'oldest-first');
|
|
166
|
-
const { total, sizes } = getFileSizesTotal(remainingOldestFirst);
|
|
167
|
-
deleteOldestUntilWithinLimit(sizes, maxTotalSize, deleted, total);
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Clean log files with additional retention policies.
|
|
172
|
-
* Returns an array of deleted file paths for auditing/tests.
|
|
173
|
-
*/
|
|
174
|
-
export const cleanOnce = (options?: CleanOnceOptions): string[] => {
|
|
175
|
-
const cwd = getCwdSafe();
|
|
176
|
-
if (cwd === '') return [];
|
|
177
|
-
|
|
178
|
-
const logsDir = options?.logsDir ?? path.join(cwd, 'logs');
|
|
179
|
-
const keepDays = options?.keepDays ?? Env.LOG_ROTATION_DAYS;
|
|
180
|
-
const maxTotalSize = options?.maxTotalSize ?? Env.getInt('LOG_MAX_TOTAL_SIZE', 0);
|
|
181
|
-
const keepFiles = options?.keepFiles ?? Env.getInt('LOG_KEEP_FILES', 0);
|
|
182
|
-
|
|
183
|
-
// Step 1: delete by age
|
|
184
|
-
cleanupOldLogs(logsDir, keepDays);
|
|
185
|
-
|
|
186
|
-
const deleted: string[] = [];
|
|
187
|
-
|
|
188
|
-
// Step 2: enforce keepFiles (keep newest N files)
|
|
189
|
-
const filesNewestFirst = listAppLogFiles(logsDir, 'newest-first');
|
|
190
|
-
enforceKeepFilesPolicy(filesNewestFirst, keepFiles, deleted);
|
|
191
|
-
|
|
192
|
-
// Step 3: enforce max total size
|
|
193
|
-
enforceMaxTotalSizePolicy(logsDir, maxTotalSize, deleted);
|
|
194
|
-
|
|
195
|
-
return deleted;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
const rotateIfNeeded = (logFile: string, maxSizeBytes: number): void => {
|
|
199
|
-
if (maxSizeBytes <= 0) return;
|
|
200
|
-
|
|
201
|
-
try {
|
|
202
|
-
if (!fs.existsSync(logFile)) return;
|
|
203
|
-
|
|
204
|
-
const stat = fs.statSync(logFile);
|
|
205
|
-
if (stat.size <= maxSizeBytes) return;
|
|
206
|
-
|
|
207
|
-
const ext = '.log';
|
|
208
|
-
const base = logFile.endsWith(ext) ? logFile.slice(0, -ext.length) : logFile;
|
|
209
|
-
const rotated = `${base}-${Date.now()}${ext}`;
|
|
210
|
-
fs.renameSync(logFile, rotated);
|
|
211
|
-
} catch {
|
|
212
|
-
// best-effort
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
export const FileLogWriter = Object.freeze({
|
|
217
|
-
write(line: string): void {
|
|
218
|
-
const cwd = getCwdSafe();
|
|
219
|
-
if (cwd === '') return;
|
|
220
|
-
|
|
221
|
-
const logsDir = path.join(cwd, 'logs');
|
|
222
|
-
ensureDirSafe(logsDir);
|
|
223
|
-
|
|
224
|
-
const dateStr = getDateStr(new Date());
|
|
225
|
-
const logFile = path.join(logsDir, `app-${dateStr}.log`);
|
|
226
|
-
|
|
227
|
-
rotateIfNeeded(logFile, Env.LOG_ROTATION_SIZE);
|
|
228
|
-
|
|
229
|
-
try {
|
|
230
|
-
fs.appendFileSync(logFile, `${line}\n`);
|
|
231
|
-
} catch {
|
|
232
|
-
// best-effort
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
cleanupOldLogs(logsDir, Env.LOG_ROTATION_DAYS);
|
|
237
|
-
},
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
export default FileLogWriter;
|
|
8
|
+
export { cleanOnce, FileLogWriter } from '@zintrust/core/node';
|
|
9
|
+
export { FileLogWriter as default } from '@zintrust/core/node';
|