@zintrust/core 0.1.40 → 0.1.42
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/bin/zintrust-main.d.ts.map +1 -1
- package/bin/zintrust-main.js +22 -1
- package/package.json +24 -4
- package/public/error-pages/404.html +2 -2
- package/src/auth/Auth.js +1 -1
- package/src/boot/Application.d.ts +1 -16
- package/src/boot/Application.d.ts.map +1 -1
- package/src/boot/Application.js +2 -290
- package/src/boot/Server.d.ts +1 -1
- package/src/boot/Server.d.ts.map +1 -1
- package/src/boot/bootstrap.js +50 -16
- package/src/boot/registry/registerRoute.d.ts +6 -0
- package/src/boot/registry/registerRoute.d.ts.map +1 -0
- package/src/boot/registry/registerRoute.js +96 -0
- package/src/boot/registry/runtime.d.ts +15 -0
- package/src/boot/registry/runtime.d.ts.map +1 -0
- package/src/boot/registry/runtime.js +364 -0
- package/src/boot/registry/type.d.ts +25 -0
- package/src/boot/registry/type.d.ts.map +1 -0
- package/src/boot/registry/type.js +1 -0
- package/src/boot/registry/worker.d.ts +6 -0
- package/src/boot/registry/worker.d.ts.map +1 -0
- package/src/boot/registry/worker.js +35 -0
- package/src/cache/drivers/KVRemoteDriver.d.ts.map +1 -1
- package/src/cache/drivers/KVRemoteDriver.js +14 -1
- package/src/cli/CLI.d.ts.map +1 -1
- package/src/cli/CLI.js +94 -34
- package/src/cli/ErrorHandler.js +1 -1
- package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
- package/src/cli/commands/ConfigCommand.js +3 -5
- package/src/cli/commands/ContainerProxiesCommand.d.ts +5 -0
- package/src/cli/commands/ContainerProxiesCommand.d.ts.map +1 -0
- package/src/cli/commands/ContainerProxiesCommand.js +77 -0
- package/src/cli/commands/ContainerWorkersCommand.d.ts +5 -0
- package/src/cli/commands/ContainerWorkersCommand.d.ts.map +1 -0
- package/src/cli/commands/ContainerWorkersCommand.js +57 -0
- package/src/cli/commands/D1LearnCommand.d.ts +9 -0
- package/src/cli/commands/D1LearnCommand.d.ts.map +1 -0
- package/src/cli/commands/D1LearnCommand.js +143 -0
- package/src/cli/commands/D1MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/D1MigrateCommand.js +55 -16
- package/src/cli/commands/DeployCommand.d.ts +16 -0
- package/src/cli/commands/DeployCommand.d.ts.map +1 -0
- package/src/cli/commands/DeployCommand.js +110 -0
- package/src/cli/commands/DeployContainerProxiesCommand.d.ts +5 -0
- package/src/cli/commands/DeployContainerProxiesCommand.d.ts.map +1 -0
- package/src/cli/commands/DeployContainerProxiesCommand.js +27 -0
- package/src/cli/commands/DeployContainerWorkersCommand.d.ts +5 -0
- package/src/cli/commands/DeployContainerWorkersCommand.d.ts.map +1 -0
- package/src/cli/commands/DeployContainerWorkersCommand.js +27 -0
- package/src/cli/commands/DockerComposeCommandUtils.d.ts +3 -0
- package/src/cli/commands/DockerComposeCommandUtils.d.ts.map +1 -0
- package/src/cli/commands/DockerComposeCommandUtils.js +34 -0
- package/src/cli/commands/DoctorArchitectureCommand.d.ts +5 -0
- package/src/cli/commands/DoctorArchitectureCommand.d.ts.map +1 -0
- package/src/cli/commands/DoctorArchitectureCommand.js +54 -0
- package/src/cli/commands/InitContainerCommand.d.ts +5 -0
- package/src/cli/commands/InitContainerCommand.d.ts.map +1 -0
- package/src/cli/commands/InitContainerCommand.js +231 -0
- package/src/cli/commands/InitEcosystemCommand.d.ts +6 -0
- package/src/cli/commands/InitEcosystemCommand.d.ts.map +1 -0
- package/src/cli/commands/InitEcosystemCommand.js +51 -0
- package/src/cli/commands/InitProducerCommand.d.ts +5 -0
- package/src/cli/commands/InitProducerCommand.d.ts.map +1 -0
- package/src/cli/commands/InitProducerCommand.js +47 -0
- package/src/cli/commands/InitProxyCommand.d.ts +5 -0
- package/src/cli/commands/InitProxyCommand.d.ts.map +1 -0
- package/src/cli/commands/InitProxyCommand.js +442 -0
- package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateCommand.js +78 -36
- package/src/cli/commands/MigrateWorkerCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateWorkerCommand.js +36 -2
- package/src/cli/commands/MongoDBProxyCommand.d.ts +5 -0
- package/src/cli/commands/MongoDBProxyCommand.d.ts.map +1 -0
- package/src/cli/commands/MongoDBProxyCommand.js +98 -0
- package/src/cli/commands/MySqlProxyCommand.d.ts +6 -0
- package/src/cli/commands/MySqlProxyCommand.d.ts.map +1 -0
- package/src/cli/commands/MySqlProxyCommand.js +32 -0
- package/src/cli/commands/PostgresProxyCommand.d.ts +6 -0
- package/src/cli/commands/PostgresProxyCommand.d.ts.map +1 -0
- package/src/cli/commands/PostgresProxyCommand.js +32 -0
- package/src/cli/commands/ProxyCommand.d.ts +12 -0
- package/src/cli/commands/ProxyCommand.d.ts.map +1 -0
- package/src/cli/commands/ProxyCommand.js +80 -0
- package/src/cli/commands/ProxyCommandUtils.d.ts +6 -0
- package/src/cli/commands/ProxyCommandUtils.d.ts.map +1 -0
- package/src/cli/commands/ProxyCommandUtils.js +38 -0
- package/src/cli/commands/PutCommand.d.ts +6 -0
- package/src/cli/commands/PutCommand.d.ts.map +1 -0
- package/src/cli/commands/PutCommand.js +173 -0
- package/src/cli/commands/QueueRecoveryCommand.d.ts +6 -0
- package/src/cli/commands/QueueRecoveryCommand.d.ts.map +1 -0
- package/src/cli/commands/QueueRecoveryCommand.js +612 -0
- package/src/cli/commands/RedisProxyCommand.d.ts +6 -0
- package/src/cli/commands/RedisProxyCommand.d.ts.map +1 -0
- package/src/cli/commands/RedisProxyCommand.js +53 -0
- package/src/cli/commands/ScheduleListCommand.d.ts +6 -0
- package/src/cli/commands/ScheduleListCommand.d.ts.map +1 -0
- package/src/cli/commands/ScheduleListCommand.js +62 -0
- package/src/cli/commands/ScheduleRunCommand.d.ts +6 -0
- package/src/cli/commands/ScheduleRunCommand.d.ts.map +1 -0
- package/src/cli/commands/ScheduleRunCommand.js +32 -0
- package/src/cli/commands/ScheduleStartCommand.d.ts +6 -0
- package/src/cli/commands/ScheduleStartCommand.d.ts.map +1 -0
- package/src/cli/commands/ScheduleStartCommand.js +40 -0
- package/src/cli/commands/SecretsCommand.d.ts.map +1 -1
- package/src/cli/commands/SecretsCommand.js +2 -2
- package/src/cli/commands/SmtpProxyCommand.d.ts +6 -0
- package/src/cli/commands/SmtpProxyCommand.d.ts.map +1 -0
- package/src/cli/commands/SmtpProxyCommand.js +56 -0
- package/src/cli/commands/SqlProxyCommandUtils.d.ts +46 -0
- package/src/cli/commands/SqlProxyCommandUtils.d.ts.map +1 -0
- package/src/cli/commands/SqlProxyCommandUtils.js +48 -0
- package/src/cli/commands/SqlServerProxyCommand.d.ts +5 -0
- package/src/cli/commands/SqlServerProxyCommand.d.ts.map +1 -0
- package/src/cli/commands/SqlServerProxyCommand.js +85 -0
- package/src/cli/commands/StartCommand.d.ts.map +1 -1
- package/src/cli/commands/StartCommand.js +132 -17
- package/src/cli/commands/WorkerCommands.d.ts +1 -0
- package/src/cli/commands/WorkerCommands.d.ts.map +1 -1
- package/src/cli/commands/WorkerCommands.js +140 -6
- package/src/cli/commands/index.d.ts +2 -0
- package/src/cli/commands/index.d.ts.map +1 -1
- package/src/cli/commands/index.js +2 -0
- package/src/cli/commands/runner/index.d.ts +2 -2
- package/src/cli/commands/runner/index.d.ts.map +1 -1
- package/src/cli/commands/runner/index.js +15 -4
- package/src/cli/commands/schedule/ScheduleCliSupport.d.ts +6 -0
- package/src/cli/commands/schedule/ScheduleCliSupport.d.ts.map +1 -0
- package/src/cli/commands/schedule/ScheduleCliSupport.js +55 -0
- package/src/cli/config/ConfigManager.d.ts.map +1 -1
- package/src/cli/config/ConfigManager.js +8 -1
- package/src/cli/d1/D1SqlMigrations.d.ts.map +1 -1
- package/src/cli/d1/D1SqlMigrations.js +14 -1
- package/src/cli/d1/WranglerConfig.d.ts.map +1 -1
- package/src/cli/d1/WranglerConfig.js +34 -2
- package/src/cli/index.d.ts +4 -0
- package/src/cli/index.d.ts.map +1 -1
- package/src/cli/index.js +4 -0
- package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ProjectScaffolder.js +2 -0
- package/src/cli/scaffolding/ServiceScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ServiceScaffolder.js +1 -0
- package/src/cli/services/VersionChecker.d.ts.map +1 -1
- package/src/cli/services/VersionChecker.js +5 -1
- package/src/cli/utils/DatabaseCliUtils.d.ts.map +1 -1
- package/src/cli/utils/DatabaseCliUtils.js +6 -1
- package/src/cli/utils/EnvFileLoader.d.ts.map +1 -1
- package/src/cli/utils/EnvFileLoader.js +35 -15
- package/src/cli/workers/QueueWorkRunner.js +1 -1
- package/src/cli.d.ts +5 -0
- package/src/cli.d.ts.map +1 -0
- package/src/cli.js +4 -0
- package/src/collections/index.d.ts +2 -2
- package/src/collections/index.d.ts.map +1 -1
- package/src/collections/index.js +1 -1
- package/src/common/HealthRoutes.d.ts.map +1 -1
- package/src/common/HealthRoutes.js +50 -2
- package/src/common/RemoteSignedJson.d.ts +1 -0
- package/src/common/RemoteSignedJson.d.ts.map +1 -1
- package/src/common/RemoteSignedJson.js +81 -29
- package/src/common/index.d.ts +1 -0
- package/src/common/index.d.ts.map +1 -1
- package/src/common/index.js +12 -1
- package/src/common/utility.d.ts.map +1 -1
- package/src/common/utility.js +2 -6
- package/src/config/FileLogWriter.d.ts.map +1 -1
- package/src/config/FileLogWriter.js +21 -6
- package/src/config/app.d.ts +4 -0
- package/src/config/app.d.ts.map +1 -1
- package/src/config/app.js +4 -0
- package/src/config/cache.d.ts.map +1 -1
- package/src/config/cache.js +22 -2
- package/src/config/cloudflare.d.ts +5 -1
- package/src/config/cloudflare.d.ts.map +1 -1
- package/src/config/cloudflare.js +67 -8
- package/src/config/database.d.ts.map +1 -1
- package/src/config/database.js +48 -13
- package/src/config/env.d.ts +87 -2
- package/src/config/env.d.ts.map +1 -1
- package/src/config/env.js +158 -19
- package/src/config/index.d.ts +1 -0
- package/src/config/index.d.ts.map +1 -1
- package/src/config/mail.d.ts.map +1 -1
- package/src/config/mail.js +16 -10
- package/src/config/middleware.d.ts +5 -0
- package/src/config/middleware.d.ts.map +1 -1
- package/src/config/middleware.js +19 -1
- package/src/config/queue.d.ts.map +1 -1
- package/src/config/queue.js +70 -9
- package/src/config/redis.d.ts.map +1 -1
- package/src/config/redis.js +48 -13
- package/src/config/storage.d.ts.map +1 -1
- package/src/config/storage.js +1 -0
- package/src/config/type.d.ts +18 -0
- package/src/config/type.d.ts.map +1 -1
- package/src/config/workers.d.ts.map +1 -1
- package/src/config/workers.js +122 -16
- package/src/functions/cloudflare.d.ts.map +1 -1
- package/src/functions/cloudflare.js +55 -1
- package/src/health/StartupHealthChecks.js +1 -1
- package/src/helper/index.d.ts +225 -0
- package/src/helper/index.d.ts.map +1 -0
- package/src/helper/index.js +347 -0
- package/src/http/FileUpload.d.ts +3 -2
- package/src/http/FileUpload.d.ts.map +1 -1
- package/src/http/Kernel.d.ts.map +1 -1
- package/src/http/Kernel.js +2 -1
- package/src/http/error-pages/ErrorPageRenderer.d.ts +4 -0
- package/src/http/error-pages/ErrorPageRenderer.d.ts.map +1 -1
- package/src/http/error-pages/ErrorPageRenderer.js +141 -1
- package/src/http/middleware/BodyParsingMiddleware.d.ts.map +1 -1
- package/src/http/middleware/BodyParsingMiddleware.js +33 -6
- package/src/index.d.ts +26 -57
- package/src/index.d.ts.map +1 -1
- package/src/index.js +32 -18
- package/src/microservices/ServiceAuthMiddleware.d.ts.map +1 -1
- package/src/microservices/ServiceAuthMiddleware.js +12 -4
- package/src/middleware/CsrfMiddleware.d.ts.map +1 -1
- package/src/middleware/CsrfMiddleware.js +30 -16
- package/src/middleware/ErrorHandlerMiddleware.d.ts.map +1 -1
- package/src/middleware/ErrorHandlerMiddleware.js +2 -1
- package/src/migrations/MigrationDiscovery.d.ts.map +1 -1
- package/src/migrations/MigrationDiscovery.js +2 -1
- package/src/migrations/MigrationLoader.js +1 -1
- package/src/migrations/schema/SchemaCompiler.d.ts.map +1 -1
- package/src/migrations/schema/SchemaCompiler.js +6 -3
- 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 +1 -1
- package/src/node-singletons/fs.d.ts.map +1 -1
- package/src/node-singletons/path.d.ts +1 -1
- package/src/node-singletons/path.d.ts.map +1 -1
- package/src/node-singletons/path.js +1 -1
- package/src/node-singletons/stream.d.ts +11 -0
- package/src/node-singletons/stream.d.ts.map +1 -0
- package/src/node-singletons/stream.js +8 -0
- package/src/observability/OpenTelemetry.d.ts +7 -0
- package/src/observability/OpenTelemetry.d.ts.map +1 -1
- package/src/observability/OpenTelemetry.js +49 -2
- package/src/orm/Database.d.ts +4 -0
- package/src/orm/Database.d.ts.map +1 -1
- package/src/orm/Database.js +80 -9
- package/src/orm/DatabaseAdapter.d.ts +1 -0
- package/src/orm/DatabaseAdapter.d.ts.map +1 -1
- package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -1
- package/src/orm/DatabaseRuntimeRegistration.js +2 -0
- package/src/orm/QueryBuilder.d.ts +1 -0
- package/src/orm/QueryBuilder.d.ts.map +1 -1
- package/src/orm/QueryBuilder.js +33 -3
- package/src/orm/SchemaCompiler.d.ts.map +1 -1
- package/src/orm/SchemaCompiler.js +6 -3
- package/src/orm/SchemaStatemenWriter.d.ts +15 -0
- package/src/orm/SchemaStatemenWriter.d.ts.map +1 -0
- package/src/orm/SchemaStatemenWriter.js +78 -0
- package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
- package/src/orm/adapters/D1Adapter.js +52 -2
- package/src/orm/adapters/D1RemoteAdapter.d.ts.map +1 -1
- package/src/orm/adapters/D1RemoteAdapter.js +150 -89
- package/src/orm/adapters/MongoDBProxyAdapter.d.ts +3 -0
- package/src/orm/adapters/MongoDBProxyAdapter.d.ts.map +1 -0
- package/src/orm/adapters/MongoDBProxyAdapter.js +128 -0
- package/src/orm/adapters/MySQLProxyAdapter.d.ts +11 -0
- package/src/orm/adapters/MySQLProxyAdapter.d.ts.map +1 -0
- package/src/orm/adapters/MySQLProxyAdapter.js +162 -0
- package/src/orm/adapters/PostgreSQLProxyAdapter.d.ts +11 -0
- package/src/orm/adapters/PostgreSQLProxyAdapter.d.ts.map +1 -0
- package/src/orm/adapters/PostgreSQLProxyAdapter.js +163 -0
- package/src/orm/adapters/ProxyCache.d.ts +9 -0
- package/src/orm/adapters/ProxyCache.d.ts.map +1 -0
- package/src/orm/adapters/ProxyCache.js +24 -0
- package/src/orm/adapters/ProxySignedRequest.d.ts +11 -0
- package/src/orm/adapters/ProxySignedRequest.d.ts.map +1 -0
- package/src/orm/adapters/ProxySignedRequest.js +30 -0
- package/src/orm/adapters/ProxySigningPath.d.ts +3 -0
- package/src/orm/adapters/ProxySigningPath.d.ts.map +1 -0
- package/src/orm/adapters/ProxySigningPath.js +25 -0
- package/src/orm/adapters/SqlProxyAdapterUtils.d.ts +19 -0
- package/src/orm/adapters/SqlProxyAdapterUtils.d.ts.map +1 -0
- package/src/orm/adapters/SqlProxyAdapterUtils.js +36 -0
- package/src/orm/adapters/SqlProxyRegistryMode.d.ts +12 -0
- package/src/orm/adapters/SqlProxyRegistryMode.d.ts.map +1 -0
- package/src/orm/adapters/SqlProxyRegistryMode.js +24 -0
- package/src/orm/adapters/SqlServerProxyAdapter.d.ts +6 -0
- package/src/orm/adapters/SqlServerProxyAdapter.d.ts.map +1 -0
- package/src/orm/adapters/SqlServerProxyAdapter.js +154 -0
- package/src/orm/migrations/MigrationStore.js +1 -1
- package/src/performance/Optimizer.d.ts +1 -0
- package/src/performance/Optimizer.d.ts.map +1 -1
- package/src/performance/Optimizer.js +21 -8
- package/src/proxy/ErrorHandler.d.ts +11 -0
- package/src/proxy/ErrorHandler.d.ts.map +1 -0
- package/src/proxy/ErrorHandler.js +7 -0
- package/src/proxy/PoolManager.d.ts +8 -0
- package/src/proxy/PoolManager.d.ts.map +1 -0
- package/src/proxy/PoolManager.js +18 -0
- package/src/proxy/ProxyBackend.d.ts +18 -0
- package/src/proxy/ProxyBackend.d.ts.map +1 -0
- package/src/proxy/ProxyBackend.js +1 -0
- package/src/proxy/ProxyConfig.d.ts +12 -0
- package/src/proxy/ProxyConfig.d.ts.map +1 -0
- package/src/proxy/ProxyConfig.js +1 -0
- package/src/proxy/ProxyRegistry.d.ts +10 -0
- package/src/proxy/ProxyRegistry.d.ts.map +1 -0
- package/src/proxy/ProxyRegistry.js +11 -0
- package/src/proxy/ProxyRequestParsing.d.ts +9 -0
- package/src/proxy/ProxyRequestParsing.d.ts.map +1 -0
- package/src/proxy/ProxyRequestParsing.js +16 -0
- package/src/proxy/ProxyServer.d.ts +21 -0
- package/src/proxy/ProxyServer.d.ts.map +1 -0
- package/src/proxy/ProxyServer.js +84 -0
- package/src/proxy/ProxyServerUtils.d.ts +37 -0
- package/src/proxy/ProxyServerUtils.d.ts.map +1 -0
- package/src/proxy/ProxyServerUtils.js +42 -0
- package/src/proxy/ProxySigningConfigResolver.d.ts +22 -0
- package/src/proxy/ProxySigningConfigResolver.d.ts.map +1 -0
- package/src/proxy/ProxySigningConfigResolver.js +24 -0
- package/src/proxy/ProxySigningRequest.d.ts +12 -0
- package/src/proxy/ProxySigningRequest.d.ts.map +1 -0
- package/src/proxy/ProxySigningRequest.js +31 -0
- package/src/proxy/RequestValidator.d.ts +15 -0
- package/src/proxy/RequestValidator.d.ts.map +1 -0
- package/src/proxy/RequestValidator.js +26 -0
- package/src/proxy/SigningService.d.ts +39 -0
- package/src/proxy/SigningService.d.ts.map +1 -0
- package/src/proxy/SigningService.js +107 -0
- package/src/proxy/SqlPayloadValidator.d.ts +13 -0
- package/src/proxy/SqlPayloadValidator.d.ts.map +1 -0
- package/src/proxy/SqlPayloadValidator.js +14 -0
- package/src/proxy/SqlProxyDbOverrides.d.ts +17 -0
- package/src/proxy/SqlProxyDbOverrides.d.ts.map +1 -0
- package/src/proxy/SqlProxyDbOverrides.js +1 -0
- package/src/proxy/SqlProxyServerDeps.d.ts +12 -0
- package/src/proxy/SqlProxyServerDeps.d.ts.map +1 -0
- package/src/proxy/SqlProxyServerDeps.js +9 -0
- package/src/proxy/StatementPayloadValidator.d.ts +13 -0
- package/src/proxy/StatementPayloadValidator.d.ts.map +1 -0
- package/src/proxy/StatementPayloadValidator.js +18 -0
- package/src/proxy/StatementRegistryLoader.d.ts +2 -0
- package/src/proxy/StatementRegistryLoader.d.ts.map +1 -0
- package/src/proxy/StatementRegistryLoader.js +36 -0
- package/src/proxy/StatementRegistryResolver.d.ts +15 -0
- package/src/proxy/StatementRegistryResolver.d.ts.map +1 -0
- package/src/proxy/StatementRegistryResolver.js +34 -0
- package/src/proxy/d1/ZintrustD1Proxy.d.ts +3 -0
- package/src/proxy/d1/ZintrustD1Proxy.d.ts.map +1 -0
- package/src/proxy/d1/ZintrustD1Proxy.js +2 -0
- package/src/proxy/d1/register.d.ts +2 -0
- package/src/proxy/d1/register.d.ts.map +1 -0
- package/src/proxy/d1/register.js +5 -0
- package/src/proxy/isMutatingSql.d.ts +2 -0
- package/src/proxy/isMutatingSql.d.ts.map +1 -0
- package/src/proxy/isMutatingSql.js +12 -0
- package/src/proxy/kv/ZintrustKvProxy.d.ts +3 -0
- package/src/proxy/kv/ZintrustKvProxy.d.ts.map +1 -0
- package/src/proxy/kv/ZintrustKvProxy.js +2 -0
- package/src/proxy/kv/register.d.ts +2 -0
- package/src/proxy/kv/register.d.ts.map +1 -0
- package/src/proxy/kv/register.js +5 -0
- package/src/proxy/mongodb/MongoDBProxyServer.d.ts +33 -0
- package/src/proxy/mongodb/MongoDBProxyServer.d.ts.map +1 -0
- package/src/proxy/mongodb/MongoDBProxyServer.js +202 -0
- package/src/proxy/mongodb/register.d.ts +2 -0
- package/src/proxy/mongodb/register.d.ts.map +1 -0
- package/src/proxy/mongodb/register.js +5 -0
- package/src/proxy/mysql/MySqlProxyServer.d.ts +8 -0
- package/src/proxy/mysql/MySqlProxyServer.d.ts.map +1 -0
- package/src/proxy/mysql/MySqlProxyServer.js +202 -0
- package/src/proxy/mysql/register.d.ts +2 -0
- package/src/proxy/mysql/register.d.ts.map +1 -0
- package/src/proxy/mysql/register.js +5 -0
- package/src/proxy/postgres/PostgresProxyServer.d.ts +8 -0
- package/src/proxy/postgres/PostgresProxyServer.d.ts.map +1 -0
- package/src/proxy/postgres/PostgresProxyServer.js +178 -0
- package/src/proxy/postgres/register.d.ts +2 -0
- package/src/proxy/postgres/register.d.ts.map +1 -0
- package/src/proxy/postgres/register.js +5 -0
- package/src/proxy/redis/RedisProxyServer.d.ts +12 -0
- package/src/proxy/redis/RedisProxyServer.d.ts.map +1 -0
- package/src/proxy/redis/RedisProxyServer.js +192 -0
- package/src/proxy/redis/register.d.ts +2 -0
- package/src/proxy/redis/register.d.ts.map +1 -0
- package/src/proxy/redis/register.js +5 -0
- package/src/proxy/smtp/SmtpProxyServer.d.ts +19 -0
- package/src/proxy/smtp/SmtpProxyServer.d.ts.map +1 -0
- package/src/proxy/smtp/SmtpProxyServer.js +290 -0
- package/src/proxy/smtp/register.d.ts +2 -0
- package/src/proxy/smtp/register.d.ts.map +1 -0
- package/src/proxy/smtp/register.js +5 -0
- package/src/proxy/sqlserver/SqlServerProxyServer.d.ts +8 -0
- package/src/proxy/sqlserver/SqlServerProxyServer.d.ts.map +1 -0
- package/src/proxy/sqlserver/SqlServerProxyServer.js +203 -0
- package/src/proxy/sqlserver/register.d.ts +2 -0
- package/src/proxy/sqlserver/register.d.ts.map +1 -0
- package/src/proxy/sqlserver/register.js +5 -0
- package/src/proxy.d.ts +4 -0
- package/src/proxy.d.ts.map +1 -0
- package/src/proxy.js +3 -0
- package/src/routes/doc.d.ts.map +1 -1
- package/src/routes/doc.js +16 -2
- package/src/routes/error.d.ts +5 -4
- package/src/routes/error.d.ts.map +1 -1
- package/src/routes/error.js +15 -13
- package/src/routes/errorPages.d.ts +2 -0
- package/src/routes/errorPages.d.ts.map +1 -1
- package/src/routes/errorPages.js +144 -4
- package/src/runtime/PluginAutoImports.d.ts +1 -0
- package/src/runtime/PluginAutoImports.d.ts.map +1 -1
- package/src/runtime/PluginAutoImports.js +94 -9
- package/src/runtime/RuntimeAdapter.d.ts +8 -9
- package/src/runtime/RuntimeAdapter.d.ts.map +1 -1
- package/src/runtime/RuntimeAdapter.js +120 -34
- package/src/runtime/RuntimeServices.d.ts +47 -0
- package/src/runtime/RuntimeServices.d.ts.map +1 -0
- package/src/runtime/RuntimeServices.js +164 -0
- package/src/runtime/StartupConfigFileRegistry.d.ts +4 -4
- package/src/runtime/StartupConfigFileRegistry.d.ts.map +1 -1
- package/src/runtime/StartupConfigFileRegistry.js +12 -0
- package/src/runtime/WorkerAdapterImports.d.ts +5 -0
- package/src/runtime/WorkerAdapterImports.d.ts.map +1 -0
- package/src/runtime/WorkerAdapterImports.js +17 -0
- package/src/runtime/WorkersModule.d.ts +6 -0
- package/src/runtime/WorkersModule.d.ts.map +1 -0
- package/src/runtime/WorkersModule.js +278 -0
- package/src/runtime/adapters/CloudflareAdapter.d.ts.map +1 -1
- package/src/runtime/adapters/CloudflareAdapter.js +19 -2
- package/src/runtime/adapters/DenoAdapter.js +1 -0
- package/src/runtime/adapters/FargateAdapter.js +1 -1
- package/src/runtime/adapters/LambdaAdapter.js +1 -1
- package/src/runtime/adapters/NodeServerAdapter.js +1 -1
- package/src/runtime/detectRuntime.d.ts +10 -0
- package/src/runtime/detectRuntime.d.ts.map +1 -0
- package/src/runtime/detectRuntime.js +57 -0
- package/src/runtime/useFileLoader.d.ts.map +1 -1
- package/src/runtime/useFileLoader.js +16 -0
- package/src/scheduler/Schedule.d.ts +36 -0
- package/src/scheduler/Schedule.d.ts.map +1 -0
- package/src/scheduler/Schedule.js +197 -0
- package/src/scheduler/ScheduleHttpGateway.d.ts +8 -0
- package/src/scheduler/ScheduleHttpGateway.d.ts.map +1 -0
- package/src/scheduler/ScheduleHttpGateway.js +196 -0
- package/src/scheduler/ScheduleRunner.d.ts +6 -0
- package/src/scheduler/ScheduleRunner.d.ts.map +1 -1
- package/src/scheduler/ScheduleRunner.js +166 -29
- package/src/scheduler/SchedulerRuntime.d.ts +15 -0
- package/src/scheduler/SchedulerRuntime.d.ts.map +1 -0
- package/src/scheduler/SchedulerRuntime.js +79 -0
- package/src/scheduler/cron/Cron.d.ts +19 -0
- package/src/scheduler/cron/Cron.d.ts.map +1 -0
- package/src/scheduler/cron/Cron.js +200 -0
- package/src/scheduler/leader/SchedulerLeader.d.ts +14 -0
- package/src/scheduler/leader/SchedulerLeader.d.ts.map +1 -0
- package/src/scheduler/leader/SchedulerLeader.js +187 -0
- package/src/scheduler/state/ScheduleStateStore.d.ts +27 -0
- package/src/scheduler/state/ScheduleStateStore.d.ts.map +1 -0
- package/src/scheduler/state/ScheduleStateStore.js +27 -0
- package/src/scheduler/types.d.ts +10 -0
- package/src/scheduler/types.d.ts.map +1 -1
- package/src/schedules/index.d.ts +1 -0
- package/src/schedules/index.d.ts.map +1 -1
- package/src/schedules/index.js +1 -0
- package/src/schedules/job-tracking-cleanup.d.ts +4 -0
- package/src/schedules/job-tracking-cleanup.d.ts.map +1 -0
- package/src/schedules/job-tracking-cleanup.js +116 -0
- package/src/schedules/log-cleanup.d.ts +1 -2
- package/src/schedules/log-cleanup.d.ts.map +1 -1
- package/src/schedules/log-cleanup.js +12 -15
- package/src/scripts/TemplateImportsCheck.js +2 -2
- package/src/scripts/TemplateSync.js +3 -4
- package/src/security/CsrfTokenManager.d.ts.map +1 -1
- package/src/security/CsrfTokenManager.js +12 -0
- package/src/security/Hash.d.ts +1 -1
- package/src/security/Hash.d.ts.map +1 -1
- package/src/security/Hash.js +31 -36
- package/src/security/Sanitizer.d.ts.map +1 -1
- package/src/security/Sanitizer.js +1 -9
- package/src/security/SignedRequest.d.ts.map +1 -1
- package/src/security/SignedRequest.js +2 -2
- package/src/seeders/SeederLoader.js +1 -1
- package/src/session/SessionManager.d.ts +3 -0
- package/src/session/SessionManager.d.ts.map +1 -1
- package/src/session/SessionManager.js +49 -10
- package/src/sockets/CloudflareSocket.d.ts +24 -0
- package/src/sockets/CloudflareSocket.d.ts.map +1 -0
- package/src/sockets/CloudflareSocket.js +259 -0
- package/src/start.d.ts.map +1 -1
- package/src/start.js +1 -8
- package/src/templates/docker/docker-compose.ecosystem.yml.tpl +301 -0
- package/src/templates/docker/docker-compose.schedules.yml.tpl +84 -0
- package/src/templates/project/basic/app/Schedules/index.ts.tpl +0 -0
- package/src/templates/project/basic/config/database.ts.tpl +1 -1
- package/src/templates/project/basic/src/zintrust.plugins.wg.ts.tpl +8 -0
- package/src/toolkit/Secrets/Manifest.d.ts.map +1 -1
- package/src/toolkit/Secrets/Manifest.js +5 -7
- package/src/tools/mail/drivers/Smtp.d.ts.map +1 -1
- package/src/tools/mail/drivers/Smtp.js +229 -18
- package/src/tools/mail/index.d.ts.map +1 -1
- package/src/tools/mail/index.js +5 -4
- package/src/tools/mail/template-loader.d.ts.map +1 -1
- package/src/tools/mail/template-loader.js +197 -29
- package/src/tools/mail/templates/auth-password-reset.d.ts +3 -0
- package/src/tools/mail/templates/auth-password-reset.d.ts.map +1 -0
- package/src/tools/mail/templates/auth-password-reset.js +231 -0
- package/src/tools/mail/templates/auth-welcome.d.ts +3 -0
- package/src/tools/mail/templates/auth-welcome.d.ts.map +1 -0
- package/src/tools/mail/templates/auth-welcome.js +236 -0
- package/src/tools/mail/templates/general.d.ts +3 -0
- package/src/tools/mail/templates/general.d.ts.map +1 -0
- package/src/tools/mail/templates/general.js +109 -0
- package/src/tools/mail/templates/index.js +2 -2
- package/src/tools/mail/templates/job-completed.d.ts +3 -0
- package/src/tools/mail/templates/job-completed.d.ts.map +1 -0
- package/src/tools/mail/templates/job-completed.js +188 -0
- package/src/tools/mail/templates/notifications-new-comment.d.ts +3 -0
- package/src/tools/mail/templates/notifications-new-comment.d.ts.map +1 -0
- package/src/tools/mail/templates/notifications-new-comment.js +228 -0
- package/src/tools/mail/templates/password-reset.d.ts +3 -0
- package/src/tools/mail/templates/password-reset.d.ts.map +1 -0
- package/src/tools/mail/templates/password-reset.js +221 -0
- package/src/tools/mail/templates/performance-report.d.ts +3 -0
- package/src/tools/mail/templates/performance-report.d.ts.map +1 -0
- package/src/tools/mail/templates/performance-report.js +258 -0
- package/src/tools/mail/templates/welcome.d.ts +3 -0
- package/src/tools/mail/templates/welcome.d.ts.map +1 -0
- package/src/tools/mail/templates/welcome.js +187 -0
- package/src/tools/mail/templates/worker-alert.d.ts +3 -0
- package/src/tools/mail/templates/worker-alert.d.ts.map +1 -0
- package/src/tools/mail/templates/worker-alert.js +229 -0
- package/src/tools/notification/Notification.js +1 -1
- package/src/tools/notification/testingHelpers.js +6 -5
- package/src/tools/queue/AdvancedQueue.js +2 -6
- package/src/tools/queue/IdempotencyManager.d.ts +6 -0
- package/src/tools/queue/IdempotencyManager.d.ts.map +1 -0
- package/src/tools/queue/IdempotencyManager.js +36 -0
- package/src/tools/queue/JobHeartbeatStore.d.ts +16 -0
- package/src/tools/queue/JobHeartbeatStore.d.ts.map +1 -0
- package/src/tools/queue/JobHeartbeatStore.js +67 -0
- package/src/tools/queue/JobReconciliationRunner.d.ts +16 -0
- package/src/tools/queue/JobReconciliationRunner.d.ts.map +1 -0
- package/src/tools/queue/JobReconciliationRunner.js +56 -0
- package/src/tools/queue/JobRecoveryDaemon.d.ts +27 -0
- package/src/tools/queue/JobRecoveryDaemon.d.ts.map +1 -0
- package/src/tools/queue/JobRecoveryDaemon.js +303 -0
- package/src/tools/queue/JobStateTracker.d.ts +140 -0
- package/src/tools/queue/JobStateTracker.d.ts.map +1 -0
- package/src/tools/queue/JobStateTracker.js +409 -0
- package/src/tools/queue/JobStateTrackerDbPersistence.d.ts +12 -0
- package/src/tools/queue/JobStateTrackerDbPersistence.d.ts.map +1 -0
- package/src/tools/queue/JobStateTrackerDbPersistence.js +239 -0
- package/src/tools/queue/Queue.d.ts.map +1 -1
- package/src/tools/queue/Queue.js +160 -16
- package/src/tools/queue/QueueDataRedactor.d.ts +6 -0
- package/src/tools/queue/QueueDataRedactor.d.ts.map +1 -0
- package/src/tools/queue/QueueDataRedactor.js +45 -0
- package/src/tools/queue/QueueExtensions.d.ts.map +1 -1
- package/src/tools/queue/QueueExtensions.js +2 -1
- package/src/tools/queue/QueueReliabilityMetrics.d.ts +38 -0
- package/src/tools/queue/QueueReliabilityMetrics.d.ts.map +1 -0
- package/src/tools/queue/QueueReliabilityMetrics.js +131 -0
- package/src/tools/queue/QueueReliabilityOrchestrator.d.ts +7 -0
- package/src/tools/queue/QueueReliabilityOrchestrator.d.ts.map +1 -0
- package/src/tools/queue/QueueReliabilityOrchestrator.js +59 -0
- package/src/tools/queue/QueueRuntimeRegistration.d.ts +1 -9
- package/src/tools/queue/QueueRuntimeRegistration.d.ts.map +1 -1
- package/src/tools/queue/QueueRuntimeRegistration.js +75 -4
- package/src/tools/queue/QueueTracing.d.ts +32 -0
- package/src/tools/queue/QueueTracing.d.ts.map +1 -0
- package/src/tools/queue/QueueTracing.js +151 -0
- package/src/tools/queue/StalledJobMonitor.d.ts +5 -0
- package/src/tools/queue/StalledJobMonitor.d.ts.map +1 -0
- package/src/tools/queue/StalledJobMonitor.js +21 -0
- package/src/tools/queue/TimeoutManager.d.ts +14 -0
- package/src/tools/queue/TimeoutManager.d.ts.map +1 -0
- package/src/tools/queue/TimeoutManager.js +77 -0
- package/src/tools/queue/drivers/Redis.d.ts +1 -0
- package/src/tools/queue/drivers/Redis.d.ts.map +1 -1
- package/src/tools/queue/drivers/Redis.js +1 -0
- package/src/tools/queue/index.d.ts +10 -0
- package/src/tools/queue/index.d.ts.map +1 -1
- package/src/tools/queue/index.js +10 -0
- package/src/tools/storage/drivers/R2.d.ts +13 -0
- package/src/tools/storage/drivers/R2.d.ts.map +1 -1
- package/src/tools/storage/drivers/R2.js +29 -0
- package/src/zintrust.plugins.d.ts +9 -0
- package/src/zintrust.plugins.d.ts.map +1 -0
- package/src/zintrust.plugins.js +7 -0
- package/src/zintrust.plugins.wg.d.ts +9 -0
- package/src/zintrust.plugins.wg.d.ts.map +1 -0
- package/src/zintrust.plugins.wg.js +7 -0
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import { generateUuid } from '../../../common/utility.js';
|
|
2
|
+
import { RemoteSignedJson } from '../../../common/RemoteSignedJson.js';
|
|
3
|
+
import { Cloudflare } from '../../../config/cloudflare.js';
|
|
4
|
+
import { Env } from '../../../config/env.js';
|
|
5
|
+
import { Logger } from '../../../config/logger.js';
|
|
2
6
|
import { ErrorFactory } from '../../../exceptions/ZintrustError.js';
|
|
3
7
|
import * as net from '../../../node-singletons/net.js';
|
|
4
8
|
import * as tls from '../../../node-singletons/tls.js';
|
|
9
|
+
import { normalizeSigningCredentials } from '../../../proxy/SigningService.js';
|
|
10
|
+
const resolveSigningPrefix = (baseUrl) => {
|
|
11
|
+
try {
|
|
12
|
+
const parsed = new URL(baseUrl);
|
|
13
|
+
const path = parsed.pathname.endsWith('/') ? parsed.pathname.slice(0, -1) : parsed.pathname;
|
|
14
|
+
if (path === '' || path === '/')
|
|
15
|
+
return undefined;
|
|
16
|
+
return path;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
5
22
|
const normalizeRecipients = (to) => (Array.isArray(to) ? to : [to]);
|
|
6
23
|
const toBase64 = (value) => Buffer.from(value, 'utf8').toString('base64');
|
|
7
24
|
const isNodeRuntime = () => typeof process !== 'undefined' && typeof process.versions?.node === 'string';
|
|
25
|
+
const isWorkersRuntime = () => Cloudflare.getWorkersEnv() !== null;
|
|
8
26
|
const validateConfig = (config) => {
|
|
9
|
-
if (!isNodeRuntime()) {
|
|
10
|
-
throw ErrorFactory.createConfigError('SMTP driver requires Node.js runtime');
|
|
27
|
+
if (!isNodeRuntime() && !isWorkersRuntime()) {
|
|
28
|
+
throw ErrorFactory.createConfigError('SMTP driver requires Node.js or Workers runtime');
|
|
11
29
|
}
|
|
12
30
|
if (config.host.trim() === '') {
|
|
13
31
|
throw ErrorFactory.createConfigError('SMTP: missing MAIL_HOST');
|
|
@@ -16,7 +34,101 @@ const validateConfig = (config) => {
|
|
|
16
34
|
throw ErrorFactory.createConfigError('SMTP: invalid MAIL_PORT');
|
|
17
35
|
}
|
|
18
36
|
};
|
|
19
|
-
const
|
|
37
|
+
const resolveProxyBaseUrl = () => {
|
|
38
|
+
const explicit = Env.SMTP_PROXY_URL.trim();
|
|
39
|
+
if (explicit !== '')
|
|
40
|
+
return explicit;
|
|
41
|
+
const host = Env.SMTP_PROXY_HOST || '127.0.0.1';
|
|
42
|
+
const port = Env.SMTP_PROXY_PORT;
|
|
43
|
+
return `http://${host}:${port}`;
|
|
44
|
+
};
|
|
45
|
+
const buildProxySettings = () => {
|
|
46
|
+
const baseUrl = resolveProxyBaseUrl();
|
|
47
|
+
const keyId = Env.SMTP_PROXY_KEY_ID ?? '';
|
|
48
|
+
const secret = Env.SMTP_PROXY_SECRET ?? '';
|
|
49
|
+
const timeoutMs = Env.SMTP_PROXY_TIMEOUT_MS;
|
|
50
|
+
return { baseUrl, keyId, secret, timeoutMs };
|
|
51
|
+
};
|
|
52
|
+
const buildSignedSettings = (settings) => {
|
|
53
|
+
const creds = normalizeSigningCredentials({
|
|
54
|
+
keyId: settings.keyId ?? '',
|
|
55
|
+
secret: settings.secret ?? '',
|
|
56
|
+
});
|
|
57
|
+
return {
|
|
58
|
+
baseUrl: settings.baseUrl,
|
|
59
|
+
keyId: creds.keyId,
|
|
60
|
+
secret: creds.secret,
|
|
61
|
+
timeoutMs: settings.timeoutMs,
|
|
62
|
+
signaturePathPrefixToStrip: resolveSigningPrefix(settings.baseUrl),
|
|
63
|
+
missingUrlMessage: 'SMTP proxy URL is missing (SMTP_PROXY_URL)',
|
|
64
|
+
missingCredentialsMessage: 'SMTP proxy signing credentials are missing (SMTP_PROXY_KEY_ID / SMTP_PROXY_SECRET)',
|
|
65
|
+
messages: {
|
|
66
|
+
unauthorized: 'SMTP proxy unauthorized',
|
|
67
|
+
forbidden: 'SMTP proxy forbidden',
|
|
68
|
+
rateLimited: 'SMTP proxy rate limited',
|
|
69
|
+
rejected: 'SMTP proxy rejected request',
|
|
70
|
+
error: 'SMTP proxy error',
|
|
71
|
+
timedOut: 'SMTP proxy request timed out',
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
const ensureSignedSettings = (settings) => {
|
|
76
|
+
const signedSettings = buildSignedSettings(settings);
|
|
77
|
+
if (signedSettings.baseUrl.trim() === '') {
|
|
78
|
+
throw ErrorFactory.createConfigError('SMTP proxy URL is missing (SMTP_PROXY_URL)');
|
|
79
|
+
}
|
|
80
|
+
if (signedSettings.keyId.trim() === '' || signedSettings.secret.trim() === '') {
|
|
81
|
+
throw ErrorFactory.createConfigError('SMTP proxy signing credentials are missing (SMTP_PROXY_KEY_ID / SMTP_PROXY_SECRET)');
|
|
82
|
+
}
|
|
83
|
+
return signedSettings;
|
|
84
|
+
};
|
|
85
|
+
const shouldUseProxy = () => {
|
|
86
|
+
if (Env.USE_SMTP_PROXY === true)
|
|
87
|
+
return true;
|
|
88
|
+
// In Cloudflare Workers, SMTP requires TCP sockets; if sockets are disabled,
|
|
89
|
+
// we must use the HTTP SMTP proxy transport when a URL is configured.
|
|
90
|
+
if (isWorkersRuntime() && Cloudflare.isCloudflareSocketsEnabled() === false) {
|
|
91
|
+
return Env.SMTP_PROXY_URL.trim() !== '';
|
|
92
|
+
}
|
|
93
|
+
// Default: do not use proxy unless explicitly enabled.
|
|
94
|
+
return false;
|
|
95
|
+
};
|
|
96
|
+
const serializeMessage = (message) => {
|
|
97
|
+
const attachments = message.attachments?.map((attachment) => {
|
|
98
|
+
const raw = Buffer.isBuffer(attachment.content)
|
|
99
|
+
? attachment.content
|
|
100
|
+
: Buffer.from(attachment.content);
|
|
101
|
+
return {
|
|
102
|
+
filename: attachment.filename,
|
|
103
|
+
contentBase64: raw.toString('base64'),
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
to: message.to,
|
|
108
|
+
from: message.from,
|
|
109
|
+
subject: message.subject,
|
|
110
|
+
text: message.text,
|
|
111
|
+
html: message.html,
|
|
112
|
+
attachments: attachments && attachments.length > 0 ? attachments : undefined,
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
const sendViaProxy = async (message) => {
|
|
116
|
+
const settings = buildProxySettings();
|
|
117
|
+
const signedSettings = ensureSignedSettings(settings);
|
|
118
|
+
return RemoteSignedJson.request(signedSettings, '/zin/smtp/send', {
|
|
119
|
+
message: serializeMessage(message),
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
const loadCloudflareSocketFactory = async () => {
|
|
123
|
+
const mod = (await import('../../../sockets/CloudflareSocket.js'));
|
|
124
|
+
const record = mod;
|
|
125
|
+
const socketFactory = record.CloudflareSocket;
|
|
126
|
+
if (!socketFactory || typeof socketFactory.create !== 'function') {
|
|
127
|
+
throw ErrorFactory.createConnectionError('Cloudflare socket factory unavailable');
|
|
128
|
+
}
|
|
129
|
+
return socketFactory;
|
|
130
|
+
};
|
|
131
|
+
const createNodeSocket = async (config, implicitTls) => {
|
|
20
132
|
validateConfig(config);
|
|
21
133
|
return new Promise((resolve, reject) => {
|
|
22
134
|
const onError = (err) => {
|
|
@@ -34,6 +146,16 @@ const createSocket = async (config, implicitTls) => {
|
|
|
34
146
|
servername: config.host,
|
|
35
147
|
})
|
|
36
148
|
: net.connect({ host: config.host, port: config.port });
|
|
149
|
+
if (typeof socket.setTimeout === 'function') {
|
|
150
|
+
socket.setTimeout(10000);
|
|
151
|
+
}
|
|
152
|
+
socket.once('timeout', () => {
|
|
153
|
+
socket.destroy();
|
|
154
|
+
reject(ErrorFactory.createConnectionError('SMTP connection timed out', {
|
|
155
|
+
host: config.host,
|
|
156
|
+
port: config.port,
|
|
157
|
+
}));
|
|
158
|
+
});
|
|
37
159
|
if (implicitTls) {
|
|
38
160
|
socket.once('secureConnect', () => resolve(socket));
|
|
39
161
|
}
|
|
@@ -43,9 +165,67 @@ const createSocket = async (config, implicitTls) => {
|
|
|
43
165
|
socket.once('error', onError);
|
|
44
166
|
});
|
|
45
167
|
};
|
|
168
|
+
const createWorkersSocket = async (config, implicitTls) => {
|
|
169
|
+
validateConfig(config);
|
|
170
|
+
return new Promise((resolve, reject) => {
|
|
171
|
+
let cleanup = () => undefined;
|
|
172
|
+
const onError = (err) => {
|
|
173
|
+
cleanup();
|
|
174
|
+
reject(ErrorFactory.createConnectionError('SMTP connection failed', {
|
|
175
|
+
host: config.host,
|
|
176
|
+
port: config.port,
|
|
177
|
+
secure: implicitTls,
|
|
178
|
+
error: err,
|
|
179
|
+
}));
|
|
180
|
+
};
|
|
181
|
+
const socketFactoryPromise = loadCloudflareSocketFactory();
|
|
182
|
+
socketFactoryPromise
|
|
183
|
+
.then((socketFactory) => {
|
|
184
|
+
const socket = socketFactory.create(config.host, config.port, {
|
|
185
|
+
tls: implicitTls,
|
|
186
|
+
});
|
|
187
|
+
if (!socket) {
|
|
188
|
+
reject(ErrorFactory.createConnectionError('SMTP socket initialization failed'));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const onConnect = () => {
|
|
192
|
+
cleanup(socket);
|
|
193
|
+
resolve(socket);
|
|
194
|
+
};
|
|
195
|
+
cleanup = (target) => {
|
|
196
|
+
if (!target)
|
|
197
|
+
return;
|
|
198
|
+
if (typeof target.off === 'function') {
|
|
199
|
+
target.off('connect', onConnect);
|
|
200
|
+
target.off('error', onError);
|
|
201
|
+
}
|
|
202
|
+
else if (typeof target.removeListener === 'function') {
|
|
203
|
+
target.removeListener('connect', onConnect);
|
|
204
|
+
target.removeListener('error', onError);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
socket.once('connect', onConnect);
|
|
208
|
+
socket.once('error', onError);
|
|
209
|
+
})
|
|
210
|
+
.catch((err) => {
|
|
211
|
+
reject(ErrorFactory.createConnectionError('SMTP socket initialization failed', {
|
|
212
|
+
error: err,
|
|
213
|
+
}));
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
};
|
|
217
|
+
const createSocket = async (config, implicitTls) => {
|
|
218
|
+
if (isWorkersRuntime())
|
|
219
|
+
return createWorkersSocket(config, implicitTls);
|
|
220
|
+
return createNodeSocket(config, implicitTls);
|
|
221
|
+
};
|
|
46
222
|
const upgradeToStartTls = async (socket, host) => {
|
|
223
|
+
if (typeof socket.startTls === 'function') {
|
|
224
|
+
await socket.startTls();
|
|
225
|
+
return socket;
|
|
226
|
+
}
|
|
47
227
|
return new Promise((resolve, reject) => {
|
|
48
|
-
const tlsSocket = tls.connect({ socket, servername: host });
|
|
228
|
+
const tlsSocket = tls.connect({ socket: socket, servername: host });
|
|
49
229
|
tlsSocket.once('secureConnect', () => {
|
|
50
230
|
resolve(tlsSocket);
|
|
51
231
|
});
|
|
@@ -68,7 +248,8 @@ const createLineReader = (socket) => {
|
|
|
68
248
|
}
|
|
69
249
|
};
|
|
70
250
|
const onData = (data) => {
|
|
71
|
-
|
|
251
|
+
const chunk = data instanceof Uint8Array ? data : Buffer.from(String(data));
|
|
252
|
+
buffer += Buffer.from(chunk).toString('utf8');
|
|
72
253
|
wake();
|
|
73
254
|
};
|
|
74
255
|
socket.on('data', onData);
|
|
@@ -84,7 +265,19 @@ const createLineReader = (socket) => {
|
|
|
84
265
|
const immediate = tryReadLineFromBuffer();
|
|
85
266
|
if (typeof immediate === 'string')
|
|
86
267
|
return immediate;
|
|
87
|
-
await new Promise((resolve) =>
|
|
268
|
+
await new Promise((resolve, reject) => {
|
|
269
|
+
let fired = false;
|
|
270
|
+
const timer = globalThis.setTimeout(() => {
|
|
271
|
+
fired = true;
|
|
272
|
+
reject(ErrorFactory.createConnectionError('SMTP read timeout'));
|
|
273
|
+
}, 30000);
|
|
274
|
+
waiters.push(() => {
|
|
275
|
+
if (fired)
|
|
276
|
+
return;
|
|
277
|
+
clearTimeout(timer);
|
|
278
|
+
resolve();
|
|
279
|
+
});
|
|
280
|
+
});
|
|
88
281
|
return readLine();
|
|
89
282
|
};
|
|
90
283
|
const readMultiline = async (code, message) => {
|
|
@@ -112,20 +305,39 @@ const createLineReader = (socket) => {
|
|
|
112
305
|
return { code, message };
|
|
113
306
|
};
|
|
114
307
|
const close = () => {
|
|
115
|
-
socket.off
|
|
308
|
+
if (typeof socket.off === 'function') {
|
|
309
|
+
socket.off('data', onData);
|
|
310
|
+
}
|
|
116
311
|
};
|
|
117
312
|
return { readResponse, close };
|
|
118
313
|
};
|
|
119
|
-
const
|
|
314
|
+
const writeRaw = async (socket, data) => {
|
|
120
315
|
return new Promise((resolve, reject) => {
|
|
121
|
-
|
|
316
|
+
let settled = false;
|
|
317
|
+
const finish = (err) => {
|
|
318
|
+
if (settled)
|
|
319
|
+
return;
|
|
320
|
+
settled = true;
|
|
122
321
|
if (err)
|
|
123
322
|
reject(err);
|
|
124
323
|
else
|
|
125
324
|
resolve();
|
|
126
|
-
}
|
|
325
|
+
};
|
|
326
|
+
try {
|
|
327
|
+
const writer = socket;
|
|
328
|
+
writer.write(data, (err) => finish(err));
|
|
329
|
+
if (writer.write.length < 2) {
|
|
330
|
+
finish();
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
catch (err) {
|
|
334
|
+
finish(err);
|
|
335
|
+
}
|
|
127
336
|
});
|
|
128
337
|
};
|
|
338
|
+
const writeLine = async (socket, line) => {
|
|
339
|
+
return writeRaw(socket, `${line}\r\n`);
|
|
340
|
+
};
|
|
129
341
|
const assertCode = (res, expected, context) => {
|
|
130
342
|
const allowed = Array.isArray(expected) ? expected : [expected];
|
|
131
343
|
if (!allowed.includes(res.code)) {
|
|
@@ -213,14 +425,7 @@ const doData = async (socket, reader, message) => {
|
|
|
213
425
|
assertCode(dataRes, 354, 'DATA');
|
|
214
426
|
const raw = buildRfc2822Message(message);
|
|
215
427
|
const stuffed = dotStuff(raw);
|
|
216
|
-
await
|
|
217
|
-
socket.write(`${stuffed}\r\n.\r\n`, (err) => {
|
|
218
|
-
if (err)
|
|
219
|
-
reject(err);
|
|
220
|
-
else
|
|
221
|
-
resolve();
|
|
222
|
-
});
|
|
223
|
-
});
|
|
428
|
+
await writeRaw(socket, `${stuffed}\r\n.\r\n`);
|
|
224
429
|
const queued = await reader.readResponse();
|
|
225
430
|
assertCode(queued, 250, 'message body');
|
|
226
431
|
};
|
|
@@ -304,6 +509,12 @@ export const SmtpDriver = Object.freeze({
|
|
|
304
509
|
* - `secure='starttls'` performs STARTTLS after EHLO.
|
|
305
510
|
*/
|
|
306
511
|
async send(config, message) {
|
|
512
|
+
if (shouldUseProxy()) {
|
|
513
|
+
const proxyUrl = Env.SMTP_PROXY_URL;
|
|
514
|
+
Logger.debug('[SmtpDriver] Using SmtpProxy', { proxyUrl });
|
|
515
|
+
const result = await sendViaProxy(message);
|
|
516
|
+
return { ok: Boolean(result.ok), provider: 'smtp', messageId: result.messageId };
|
|
517
|
+
}
|
|
307
518
|
let mode = 'none';
|
|
308
519
|
if (config.secure === true)
|
|
309
520
|
mode = 'tls';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/tools/mail/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAI7E,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,YAAY,CAAC;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/tools/mail/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAI7E,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,YAAY,CAAC;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAgJF,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAsBD,eAAO,MAAM,IAAI;IACf;;OAEG;kBACiB,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAIrD,sBAAsB;gBACJ,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAGnD;;;;OAIG;iBACU,MAAM;cAnEb,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,cAAc,CAAC;;gBAuErC,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;EAGzD,CAAC;AAEH,eAAe,IAAI,CAAC"}
|
package/src/tools/mail/index.js
CHANGED
|
@@ -70,10 +70,7 @@ const sendWithDriver = async (driver, message) => {
|
|
|
70
70
|
throw ErrorFactory.createConfigError(`Mail driver not registered: ${driver.driver} (run \`zin add mail:${driver.driver}\` / \`npm i @zintrust/mail-${driver.driver}\`)`);
|
|
71
71
|
}
|
|
72
72
|
// Config exists for future drivers, but implementations are intentionally CLI/runtime-safe and added incrementally.
|
|
73
|
-
{
|
|
74
|
-
const err = ErrorFactory.createConfigError(`Mail driver not implemented: ${mailConfig.default}`);
|
|
75
|
-
throw err;
|
|
76
|
-
}
|
|
73
|
+
throw ErrorFactory.createConfigError(`Mail driver not registered: ${mailConfig.default}. Available drivers: ses, sendgrid, mailgun, smtp. Run \`zin add mail:${mailConfig.default}\` to install.`);
|
|
77
74
|
};
|
|
78
75
|
const createMailer = (name) => Object.freeze({
|
|
79
76
|
async send(input) {
|
|
@@ -95,10 +92,14 @@ const createMailer = (name) => Object.freeze({
|
|
|
95
92
|
});
|
|
96
93
|
},
|
|
97
94
|
});
|
|
95
|
+
const looksLikeHtml = (value) => /<\s*html\b|<!doctype\b|<\s*body\b/i.test(value);
|
|
98
96
|
async function renderTemplateToHtml(input) {
|
|
99
97
|
const { template, variables } = input;
|
|
100
98
|
// Import lazily to avoid circular deps
|
|
101
99
|
const { loadTemplate } = await import('./template-loader.js');
|
|
100
|
+
if (looksLikeHtml(template)) {
|
|
101
|
+
return loadTemplate(template, (variables ?? {}));
|
|
102
|
+
}
|
|
102
103
|
// template-loader expects full filename
|
|
103
104
|
const fileName = template.endsWith('.html') ? template : `${template}.html`;
|
|
104
105
|
return loadTemplate(fileName, (variables ?? {}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-loader.d.ts","sourceRoot":"","sources":["../../../../src/tools/mail/template-loader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"template-loader.d.ts","sourceRoot":"","sources":["../../../../src/tools/mail/template-loader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAoM9D;;GAEG;AACH,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,SAAS,GAAE,iBAAsB,GAChC,OAAO,CAAC,MAAM,CAAC,CAwBjB;AA2FD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAShD"}
|
|
@@ -1,37 +1,173 @@
|
|
|
1
1
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
2
2
|
import { readFile } from '../../node-singletons/fs.js';
|
|
3
3
|
import { dirname, join } from '../../node-singletons/path.js';
|
|
4
|
-
import { fileURLToPath } from '../../node-singletons/url.js';
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from '../../node-singletons/url.js';
|
|
5
5
|
import { Env } from '../../config/env.js';
|
|
6
6
|
import { interpolate } from './template-utils.js';
|
|
7
|
+
const looksLikeHtml = (value) => /<\s*html\b|<!doctype\b|<\s*body\b/i.test(value);
|
|
8
|
+
const builtinTemplateLoaders = Object.freeze({
|
|
9
|
+
'auth-password-reset': async () => import('./templates/auth-password-reset.js'),
|
|
10
|
+
'auth-welcome': async () => import('./templates/auth-welcome.js'),
|
|
11
|
+
general: async () => import('./templates/general.js'),
|
|
12
|
+
'job-completed': async () => import('./templates/job-completed.js'),
|
|
13
|
+
'notifications-new-comment': async () => import('./templates/notifications-new-comment.js'),
|
|
14
|
+
'password-reset': async () => import('./templates/password-reset.js'),
|
|
15
|
+
'performance-report': async () => import('./templates/performance-report.js'),
|
|
16
|
+
welcome: async () => import('./templates/welcome.js'),
|
|
17
|
+
'worker-alert': async () => import('./templates/worker-alert.js'),
|
|
18
|
+
});
|
|
19
|
+
const getSafeCwd = () => {
|
|
20
|
+
try {
|
|
21
|
+
if (typeof process !== 'undefined' && typeof process.cwd === 'function') {
|
|
22
|
+
const cwd = process.cwd();
|
|
23
|
+
if (typeof cwd === 'string' && cwd.trim() !== '')
|
|
24
|
+
return cwd;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return '';
|
|
29
|
+
}
|
|
30
|
+
return '';
|
|
31
|
+
};
|
|
7
32
|
/**
|
|
8
|
-
*
|
|
33
|
+
* Get the base directory for templates.
|
|
34
|
+
* In Cloudflare Workers, import.meta.url may be undefined, so we handle that case.
|
|
9
35
|
*/
|
|
10
|
-
|
|
36
|
+
function getBaseDir() {
|
|
11
37
|
try {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
38
|
+
// Check if import.meta.url is available (Node.js, Deno, modern bundlers)
|
|
39
|
+
if (typeof import.meta.url === 'string' && import.meta.url.trim() !== '') {
|
|
40
|
+
return dirname(fileURLToPath(import.meta.url));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Fallback for environments where fileURLToPath fails
|
|
45
|
+
}
|
|
46
|
+
// Fallback: use cwd if available
|
|
47
|
+
const cwd = getSafeCwd();
|
|
48
|
+
if (cwd.trim() !== '') {
|
|
49
|
+
return join(cwd, 'src', 'tools', 'mail');
|
|
50
|
+
}
|
|
51
|
+
// Last resort: return a relative path that might work
|
|
52
|
+
return './src/tools/mail';
|
|
53
|
+
}
|
|
54
|
+
function resolveTemplatePath(templateName) {
|
|
55
|
+
const baseDir = getBaseDir();
|
|
56
|
+
const isPath = templateName.includes('/') || templateName.endsWith('.html');
|
|
57
|
+
if (!isPath) {
|
|
58
|
+
return join(baseDir, 'templates', `${templateName}.html`);
|
|
59
|
+
}
|
|
60
|
+
if (templateName.startsWith('/')) {
|
|
61
|
+
return templateName;
|
|
62
|
+
}
|
|
63
|
+
const cwd = getSafeCwd();
|
|
64
|
+
return cwd.trim() === '' ? join(baseDir, templateName) : join(cwd, templateName);
|
|
65
|
+
}
|
|
66
|
+
function normalizeTemplateName(templateName) {
|
|
67
|
+
return {
|
|
68
|
+
normalizedTemplate: templateName.endsWith('.html') ? templateName : `${templateName}.html`,
|
|
69
|
+
normalizedModuleName: templateName.endsWith('.html') ? templateName.slice(0, -5) : templateName,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async function tryBuiltinLoader(normalizedModuleName) {
|
|
73
|
+
const builtinLoader = builtinTemplateLoaders[normalizedModuleName];
|
|
74
|
+
if (builtinLoader === undefined) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const imported = (await builtinLoader());
|
|
79
|
+
if (typeof imported.default === 'string' && imported.default.trim() !== '') {
|
|
80
|
+
return imported.default;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Fall through to filesystem/module path probes.
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
function getFileCandidates(templatePath, normalizedTemplate) {
|
|
89
|
+
const cwd = getSafeCwd();
|
|
90
|
+
const baseDir = getBaseDir();
|
|
91
|
+
return [
|
|
92
|
+
templatePath,
|
|
93
|
+
join(baseDir, 'templates', normalizedTemplate),
|
|
94
|
+
join(cwd, 'dist', 'src', 'tools', 'mail', 'templates', normalizedTemplate),
|
|
95
|
+
join(cwd, 'src', 'tools', 'mail', 'templates', normalizedTemplate),
|
|
96
|
+
].filter((path, index, arr) => path.trim() !== '' && arr.indexOf(path) === index);
|
|
97
|
+
}
|
|
98
|
+
function getModuleCandidates(normalizedModuleName) {
|
|
99
|
+
const cwd = getSafeCwd();
|
|
100
|
+
const baseDir = getBaseDir();
|
|
101
|
+
return [
|
|
102
|
+
join(cwd, 'dist', 'src', 'tools', 'mail', 'templates', `${normalizedModuleName}.js`),
|
|
103
|
+
join(cwd, 'src', 'tools', 'mail', 'templates', `${normalizedModuleName}.ts`),
|
|
104
|
+
join(baseDir, 'templates', `${normalizedModuleName}.js`),
|
|
105
|
+
join(baseDir, 'templates', `${normalizedModuleName}.ts`),
|
|
106
|
+
].filter((path, index, arr) => path.trim() !== '' && arr.indexOf(path) === index);
|
|
107
|
+
}
|
|
108
|
+
async function tryReadFromCandidates(candidates) {
|
|
109
|
+
let lastError;
|
|
110
|
+
for (const candidate of candidates) {
|
|
111
|
+
try {
|
|
112
|
+
// eslint-disable-next-line no-await-in-loop
|
|
113
|
+
const content = await readFile(candidate, 'utf-8');
|
|
114
|
+
return { content };
|
|
22
115
|
}
|
|
23
|
-
|
|
24
|
-
|
|
116
|
+
catch (error) {
|
|
117
|
+
lastError = error;
|
|
25
118
|
}
|
|
26
|
-
|
|
119
|
+
}
|
|
120
|
+
return { error: lastError };
|
|
121
|
+
}
|
|
122
|
+
async function tryImportFromCandidates(moduleCandidates) {
|
|
123
|
+
let lastError;
|
|
124
|
+
for (const modulePath of moduleCandidates) {
|
|
27
125
|
try {
|
|
28
|
-
|
|
126
|
+
// eslint-disable-next-line no-await-in-loop
|
|
127
|
+
const imported = (await import(pathToFileURL(modulePath).href));
|
|
128
|
+
if (typeof imported.default === 'string' && imported.default.trim() !== '') {
|
|
129
|
+
return { content: imported.default };
|
|
130
|
+
}
|
|
29
131
|
}
|
|
30
|
-
catch {
|
|
31
|
-
|
|
32
|
-
const fallbackPath = join(baseDir, 'templates', templateName.endsWith('.html') ? templateName : `${templateName}.html`);
|
|
33
|
-
template = await readFile(fallbackPath, 'utf-8');
|
|
132
|
+
catch (error) {
|
|
133
|
+
lastError = error;
|
|
34
134
|
}
|
|
135
|
+
}
|
|
136
|
+
return { error: lastError };
|
|
137
|
+
}
|
|
138
|
+
async function loadTemplateContent(templateName) {
|
|
139
|
+
const templatePath = resolveTemplatePath(templateName);
|
|
140
|
+
const { normalizedTemplate, normalizedModuleName } = normalizeTemplateName(templateName);
|
|
141
|
+
// Try builtin loader first
|
|
142
|
+
const builtinResult = await tryBuiltinLoader(normalizedModuleName);
|
|
143
|
+
if (builtinResult !== null && typeof builtinResult === 'string') {
|
|
144
|
+
return builtinResult;
|
|
145
|
+
}
|
|
146
|
+
// Try file system candidates
|
|
147
|
+
const fileCandidates = getFileCandidates(templatePath, normalizedTemplate);
|
|
148
|
+
const fileResult = await tryReadFromCandidates(fileCandidates);
|
|
149
|
+
if (fileResult.content !== undefined) {
|
|
150
|
+
return fileResult.content;
|
|
151
|
+
}
|
|
152
|
+
// Try module candidates
|
|
153
|
+
const moduleCandidates = getModuleCandidates(normalizedModuleName);
|
|
154
|
+
const moduleResult = await tryImportFromCandidates(moduleCandidates);
|
|
155
|
+
if (moduleResult.content !== undefined) {
|
|
156
|
+
return moduleResult.content;
|
|
157
|
+
}
|
|
158
|
+
// Extract last error from failed attempts
|
|
159
|
+
const lastError = fileResult.error ?? moduleResult.error;
|
|
160
|
+
throw ErrorFactory.createConfigError(`Failed to load template from known paths: ${[...fileCandidates, ...moduleCandidates].join(', ')}` +
|
|
161
|
+
(lastError === undefined ? '' : `. Last error: ${String(lastError)}`));
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Load and render email template with variable substitution
|
|
165
|
+
*/
|
|
166
|
+
export async function loadTemplate(templateName, variables = {}) {
|
|
167
|
+
try {
|
|
168
|
+
const template = looksLikeHtml(templateName)
|
|
169
|
+
? templateName
|
|
170
|
+
: await loadTemplateContent(templateName);
|
|
35
171
|
// Replace variables using shared interpolate util
|
|
36
172
|
const mergedVars = {
|
|
37
173
|
year: new Date().getFullYear().toString(),
|
|
@@ -53,21 +189,16 @@ export async function loadTemplate(templateName, variables = {}) {
|
|
|
53
189
|
* Render conditional blocks {{#if_condition}}...{{/if_condition}}
|
|
54
190
|
*/
|
|
55
191
|
function renderConditionals(template, variables) {
|
|
56
|
-
|
|
57
|
-
return template.replaceAll(conditionalRegex, (_fullMatch, condition, content) => {
|
|
192
|
+
return renderBlockTags(template, 'if', (condition, content) => {
|
|
58
193
|
const value = variables[condition];
|
|
59
|
-
|
|
60
|
-
return content;
|
|
61
|
-
}
|
|
62
|
-
return '';
|
|
194
|
+
return value === true || value === 'true' ? content : '';
|
|
63
195
|
});
|
|
64
196
|
}
|
|
65
197
|
/**
|
|
66
198
|
* Render loop blocks {{#each_array}}...{{/each_array}}
|
|
67
199
|
*/
|
|
68
200
|
function renderLoops(template, variables) {
|
|
69
|
-
|
|
70
|
-
return template.replaceAll(loopRegex, (_fullMatch, arrayName, content) => {
|
|
201
|
+
return renderBlockTags(template, 'each', (arrayName, content) => {
|
|
71
202
|
const array = variables[arrayName];
|
|
72
203
|
if (!Array.isArray(array)) {
|
|
73
204
|
return '';
|
|
@@ -86,6 +217,43 @@ function renderLoops(template, variables) {
|
|
|
86
217
|
.join('');
|
|
87
218
|
});
|
|
88
219
|
}
|
|
220
|
+
const isSafeBlockName = (value) => /^\w+$/.test(value);
|
|
221
|
+
const renderBlockTags = (template, tagPrefix, resolver) => {
|
|
222
|
+
const openPrefix = `{{#${tagPrefix}_`;
|
|
223
|
+
let cursor = 0;
|
|
224
|
+
let output = '';
|
|
225
|
+
while (cursor < template.length) {
|
|
226
|
+
const openIndex = template.indexOf(openPrefix, cursor);
|
|
227
|
+
if (openIndex < 0) {
|
|
228
|
+
output += template.slice(cursor);
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
output += template.slice(cursor, openIndex);
|
|
232
|
+
const nameStart = openIndex + openPrefix.length;
|
|
233
|
+
const openEnd = template.indexOf('}}', nameStart);
|
|
234
|
+
if (openEnd < 0) {
|
|
235
|
+
output += template.slice(openIndex);
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
const name = template.slice(nameStart, openEnd);
|
|
239
|
+
if (!isSafeBlockName(name)) {
|
|
240
|
+
output += template.slice(openIndex, openEnd + 2);
|
|
241
|
+
cursor = openEnd + 2;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
const closeToken = `{{/${tagPrefix}_${name}}}`;
|
|
245
|
+
const contentStart = openEnd + 2;
|
|
246
|
+
const closeIndex = template.indexOf(closeToken, contentStart);
|
|
247
|
+
if (closeIndex < 0) {
|
|
248
|
+
output += template.slice(openIndex);
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
const content = template.slice(contentStart, closeIndex);
|
|
252
|
+
output += resolver(name, content);
|
|
253
|
+
cursor = closeIndex + closeToken.length;
|
|
254
|
+
}
|
|
255
|
+
return output;
|
|
256
|
+
};
|
|
89
257
|
/**
|
|
90
258
|
* Get list of available templates
|
|
91
259
|
*/
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
declare const _default: "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n <title>Password Reset Request</title>\n <style>\n body {\n margin: 0;\n padding: 0;\n background-color: #0b1220;\n color: #e2e8f0;\n font-family:\n -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n }\n\n .email-container {\n max-width: 600px;\n margin: 40px auto;\n background-color: #0f172a;\n border: 1px solid #334155;\n border-radius: 12px;\n overflow: hidden;\n }\n\n .header {\n padding: 40px 40px 30px;\n text-align: center;\n background: linear-gradient(180deg, rgba(239, 68, 68, 0.15), rgba(220, 38, 38, 0.08));\n border-bottom: 1px solid #334155;\n }\n\n .icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 20px;\n border-radius: 12px;\n border: 1px solid rgba(239, 68, 68, 0.35);\n background: linear-gradient(180deg, rgba(239, 68, 68, 0.2), rgba(220, 38, 38, 0.1));\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n .title {\n margin: 0 0 8px;\n font-size: 28px;\n font-weight: 700;\n color: #e2e8f0;\n line-height: 1.2;\n }\n\n .subtitle {\n margin: 0;\n font-size: 16px;\n color: #e2e8f0;\n line-height: 1.5;\n }\n\n .content {\n padding: 40px;\n }\n\n .greeting {\n margin: 0 0 24px;\n font-size: 15px;\n color: #f1f5f9;\n line-height: 1.6;\n }\n\n .message {\n margin: 0 0 24px;\n font-size: 15px;\n color: #f1f5f9;\n line-height: 1.6;\n }\n\n .button-container {\n margin-bottom: 30px;\n text-align: center;\n }\n\n .reset-button {\n display: inline-block;\n padding: 14px 32px;\n background: linear-gradient(135deg, #ef4444, #dc2626);\n color: #ffffff;\n text-decoration: none;\n border-radius: 8px;\n font-weight: 600;\n font-size: 15px;\n border: 1px solid rgba(217, 82, 82, 0.8);\n }\n\n .security-notice {\n padding: 16px;\n background: rgba(251, 191, 36, 0.08);\n border-left: 3px solid #fbbf24;\n border-radius: 6px;\n margin-bottom: 30px;\n }\n\n .security-notice p {\n margin: 0;\n font-size: 14px;\n color: #e2e8f0;\n line-height: 1.6;\n }\n\n .security-notice strong {\n color: #fbbf24;\n }\n\n .expiry {\n margin: 0 0 16px;\n font-size: 14px;\n color: #e2e8f0;\n line-height: 1.6;\n }\n\n .expiry strong {\n color: #e2e8f0;\n }\n\n .alternative-link {\n margin: 0;\n font-size: 13px;\n color: #e2e8f0;\n line-height: 1.6;\n }\n\n .alternative-link a {\n color: #bae6fd;\n text-decoration: none;\n word-break: break-all;\n }\n\n .divider {\n margin: 30px 0;\n border-top: 1px solid #334155;\n }\n\n .support {\n margin: 0;\n font-size: 14px;\n color: #e2e8f0;\n line-height: 1.6;\n }\n\n .support a {\n color: #bae6fd;\n text-decoration: none;\n }\n\n .footer {\n padding: 30px 40px;\n background: rgba(15, 23, 42, 0.65);\n border-top: 1px solid #334155;\n text-align: center;\n }\n\n .footer p {\n margin: 0;\n font-size: 12px;\n color: #64748b;\n }\n </style>\n </head>\n <body>\n <div class=\"email-container\">\n <!-- Header -->\n <div class=\"header\">\n <div class=\"icon\">\n <span style=\"font-size: 24px\">\uD83D\uDD12</span>\n </div>\n <h1 class=\"title\">Password Reset Request</h1>\n <p class=\"subtitle\">We received a request to reset your password</p>\n </div>\n\n <!-- Main Content -->\n <div class=\"content\">\n <p class=\"greeting\">Hi <strong style=\"color: #e2e8f0\">{{name}}</strong>,</p>\n\n <p class=\"message\">\n Someone requested a password reset for your {{APP_NAME}} account (<strong\n style=\"color: #e2e8f0\"\n >{{email}}</strong\n >). If this was you, click the button below to reset your password:\n </p>\n\n <!-- CTA Button -->\n <div class=\"button-container\">\n <a href=\"{{reset_url}}\" class=\"reset-button\">Reset Password</a>\n </div>\n\n <!-- Security Notice -->\n <div class=\"security-notice\">\n <p>\n <strong>\u26A0 Security Notice</strong><br />\n If you didn't request this password reset, please ignore this email. Your password will\n remain unchanged.\n </p>\n </div>\n\n <p class=\"expiry\">\n For security reasons, this link will expire in <strong>{{expiryMinutes}} minutes</strong>.\n </p>\n\n <!-- Alternative Link -->\n <p class=\"alternative-link\">\n If the button above doesn't work, copy and paste this link into your browser:<br />\n <a href=\"{{reset_url}}\">{{reset_url}}</a>\n </p>\n\n <!-- Divider -->\n <div class=\"divider\"></div>\n\n <p class=\"support\">\n If you continue to have problems, please contact our\n <a href=\"{{support_url}}\">support team</a>.\n </p>\n </div>\n\n <!-- Footer -->\n <div class=\"footer\">\n <p>© {{year}} {{APP_NAME}}. All rights reserved.</p>\n </div>\n </div>\n </body>\n</html>";
|
|
2
|
+
export default _default;
|
|
3
|
+
//# sourceMappingURL=auth-password-reset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-password-reset.d.ts","sourceRoot":"","sources":["../../../../../src/tools/mail/templates/auth-password-reset.ts"],"names":[],"mappings":";AAAA,wBAsOS"}
|