@zintrust/core 0.1.41 → 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/package.json +17 -1
- package/src/boot/bootstrap.js +27 -11
- package/src/boot/registry/runtime.d.ts.map +1 -1
- package/src/boot/registry/runtime.js +11 -0
- package/src/cli/CLI.d.ts.map +1 -1
- package/src/cli/CLI.js +12 -0
- package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
- package/src/cli/commands/ConfigCommand.js +3 -5
- 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/InitContainerCommand.d.ts.map +1 -1
- package/src/cli/commands/InitContainerCommand.js +21 -6
- 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/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/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.map +1 -1
- package/src/cli/commands/QueueRecoveryCommand.js +113 -14
- 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/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 +11 -1
- package/src/cli/d1/WranglerConfig.d.ts.map +1 -1
- package/src/cli/d1/WranglerConfig.js +34 -2
- 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 +33 -14
- 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/RemoteSignedJson.d.ts.map +1 -1
- package/src/common/RemoteSignedJson.js +49 -23
- package/src/common/utility.d.ts.map +1 -1
- package/src/common/utility.js +2 -6
- package/src/config/cloudflare.d.ts.map +1 -1
- package/src/config/cloudflare.js +19 -8
- package/src/config/env.js +2 -2
- 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/index.d.ts +3 -6
- package/src/index.d.ts.map +1 -1
- package/src/index.js +7 -9
- package/src/migrations/MigrationDiscovery.d.ts.map +1 -1
- package/src/migrations/MigrationDiscovery.js +2 -1
- package/src/orm/DatabaseAdapter.d.ts +1 -0
- package/src/orm/DatabaseAdapter.d.ts.map +1 -1
- 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 +137 -89
- package/src/orm/adapters/MySQLProxyAdapter.d.ts.map +1 -1
- package/src/orm/adapters/MySQLProxyAdapter.js +100 -81
- package/src/orm/adapters/PostgreSQLProxyAdapter.d.ts.map +1 -1
- package/src/orm/adapters/PostgreSQLProxyAdapter.js +26 -10
- package/src/orm/adapters/SqlProxyAdapterUtils.d.ts.map +1 -1
- package/src/orm/adapters/SqlProxyAdapterUtils.js +2 -1
- 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 +3 -0
- package/src/orm/adapters/SqlServerProxyAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SqlServerProxyAdapter.js +125 -117
- package/src/orm/migrations/MigrationStore.js +1 -1
- 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/RequestValidator.d.ts.map +1 -1
- package/src/proxy/RequestValidator.js +2 -1
- package/src/proxy/SigningService.js +2 -2
- 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 +2 -1
- package/src/proxy/d1/ZintrustD1Proxy.d.ts.map +1 -1
- package/src/proxy/d1/ZintrustD1Proxy.js +2 -1
- 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 +2 -1
- package/src/proxy/kv/ZintrustKvProxy.d.ts.map +1 -1
- package/src/proxy/kv/ZintrustKvProxy.js +2 -1
- package/src/proxy/mysql/MySqlProxyServer.d.ts +2 -8
- package/src/proxy/mysql/MySqlProxyServer.d.ts.map +1 -1
- package/src/proxy/mysql/MySqlProxyServer.js +84 -51
- package/src/proxy/postgres/PostgresProxyServer.d.ts +2 -8
- package/src/proxy/postgres/PostgresProxyServer.d.ts.map +1 -1
- package/src/proxy/postgres/PostgresProxyServer.js +86 -48
- package/src/proxy/smtp/SmtpProxyServer.d.ts.map +1 -1
- package/src/proxy/smtp/SmtpProxyServer.js +6 -5
- package/src/proxy/sqlserver/SqlServerProxyServer.d.ts +2 -8
- package/src/proxy/sqlserver/SqlServerProxyServer.d.ts.map +1 -1
- package/src/proxy/sqlserver/SqlServerProxyServer.js +84 -49
- package/src/proxy.d.ts +4 -0
- package/src/proxy.d.ts.map +1 -0
- package/src/proxy.js +3 -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/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/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/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 +7 -1
- package/src/tools/queue/JobReconciliationRunner.d.ts.map +1 -1
- package/src/tools/queue/JobReconciliationRunner.js +7 -39
- package/src/tools/queue/JobRecoveryDaemon.d.ts.map +1 -1
- package/src/tools/queue/JobRecoveryDaemon.js +116 -18
- package/src/tools/queue/JobStateTracker.d.ts +10 -1
- package/src/tools/queue/JobStateTracker.d.ts.map +1 -1
- package/src/tools/queue/JobStateTracker.js +24 -2
- package/src/tools/queue/JobStateTrackerDbPersistence.d.ts.map +1 -1
- package/src/tools/queue/JobStateTrackerDbPersistence.js +93 -2
|
@@ -8,6 +8,7 @@ import { WranglerConfig } from '../d1/WranglerConfig.js';
|
|
|
8
8
|
import { WranglerD1 } from '../d1/WranglerD1.js';
|
|
9
9
|
import { PromptHelper } from '../PromptHelper.js';
|
|
10
10
|
import { confirmProductionRun, mapConnectionToOrmConfig, parseRollbackSteps, } from '../utils/DatabaseCliUtils.js';
|
|
11
|
+
import { EnvFileLoader } from '../utils/EnvFileLoader.js';
|
|
11
12
|
import { readEnvString } from '../../common/ExternalServiceUtils.js';
|
|
12
13
|
import { databaseConfig } from '../../config/database.js';
|
|
13
14
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
@@ -52,7 +53,7 @@ const getServiceArgs = (options) => {
|
|
|
52
53
|
return { service: serviceArg, includeGlobal };
|
|
53
54
|
};
|
|
54
55
|
const isDestructiveAction = (options) => options['fresh'] === true || options['reset'] === true || options['rollback'] === true;
|
|
55
|
-
const
|
|
56
|
+
const isWranglerD1Driver = (driver) => driver === 'd1';
|
|
56
57
|
const describeTargetDatabase = (conn) => {
|
|
57
58
|
switch (conn.driver) {
|
|
58
59
|
case 'sqlite':
|
|
@@ -189,33 +190,47 @@ const runD1Actions = async (params) => {
|
|
|
189
190
|
cmd.info(output);
|
|
190
191
|
cmd.success('D1 migrations completed successfully');
|
|
191
192
|
};
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
if (isD1Driver(conn.driver)) {
|
|
193
|
+
const logOptionsForConn = (cmd, conn, options) => {
|
|
194
|
+
if (isWranglerD1Driver(conn.driver)) {
|
|
195
195
|
cmd.debug(`Migrate command executed with options: ${JSON.stringify(options)}`);
|
|
196
|
+
return;
|
|
196
197
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
198
|
+
const optionsForLog = { ...options };
|
|
199
|
+
delete optionsForLog['database'];
|
|
200
|
+
delete optionsForLog['local'];
|
|
201
|
+
delete optionsForLog['remote'];
|
|
202
|
+
cmd.debug(`Migrate command executed with options: ${JSON.stringify(optionsForLog)}`);
|
|
203
|
+
};
|
|
204
|
+
const warnIfAdapterMissing = (cmd, conn) => {
|
|
205
|
+
if (conn.driver === 'mysql' && DatabaseAdapterRegistry.get('mysql') === undefined) {
|
|
206
|
+
cmd.warn('MySQL adapter is not installed/registered; migrations may not hit a real MySQL DB.');
|
|
207
|
+
cmd.warn('Install via `zin plugin install adapter:mysql` (or `zin add db:mysql`).');
|
|
208
|
+
cmd.debug('[debug] Expected a side-effect import in src/zintrust.plugins.ts like: import "@zintrust/db-mysql/register";');
|
|
203
209
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
await runD1Actions({
|
|
208
|
-
options,
|
|
209
|
-
cmd,
|
|
210
|
-
projectRoot: process.cwd(),
|
|
211
|
-
globalDir,
|
|
212
|
-
extension,
|
|
213
|
-
separateTracking,
|
|
214
|
-
service,
|
|
215
|
-
includeGlobal,
|
|
216
|
-
});
|
|
217
|
-
return;
|
|
210
|
+
if (conn.driver === 'postgresql' && DatabaseAdapterRegistry.get('postgresql') === undefined) {
|
|
211
|
+
cmd.warn('PostgreSQL adapter is not installed/registered; migrations may not hit a real PostgreSQL DB.');
|
|
212
|
+
cmd.warn('Install via `zin plugin install adapter:postgres` (or `zin add db:postgres`).');
|
|
218
213
|
}
|
|
214
|
+
};
|
|
215
|
+
const withD1RemoteSqlMode = async (fn) => {
|
|
216
|
+
if (typeof process === 'undefined' || process.env === undefined)
|
|
217
|
+
return fn();
|
|
218
|
+
const prev = process.env['D1_REMOTE_MODE'];
|
|
219
|
+
process.env['D1_REMOTE_MODE'] = 'sql';
|
|
220
|
+
try {
|
|
221
|
+
return await fn();
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
if (prev === undefined) {
|
|
225
|
+
delete process.env['D1_REMOTE_MODE'];
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
process.env['D1_REMOTE_MODE'] = prev;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
const runOrmMigrationsForConn = async (params) => {
|
|
233
|
+
const { conn, options, cmd, interactive, globalDir, extension, separateTracking, service, includeGlobal, } = params;
|
|
219
234
|
const ormConfig = mapConnectionToOrmConfig(conn);
|
|
220
235
|
const destructive = isDestructiveAction(options);
|
|
221
236
|
const force = options['force'] === true;
|
|
@@ -231,18 +246,7 @@ const processConnection = async (conn, options, cmd, interactive) => {
|
|
|
231
246
|
cmd.info(`[i] Target database: ${describeTargetDatabase(conn)}`);
|
|
232
247
|
cmd.info('[i] Migration tracking table: migrations');
|
|
233
248
|
cmd.debug(`[debug] Registered database adapters: ${DatabaseAdapterRegistry.list().join(', ')}`);
|
|
234
|
-
|
|
235
|
-
// Adapters are registered via side-effect imports in src/zintrust.plugins.ts
|
|
236
|
-
// (generated by `zin plugin install`) and are loaded at CLI startup.
|
|
237
|
-
if (conn.driver === 'mysql' && DatabaseAdapterRegistry.get('mysql') === undefined) {
|
|
238
|
-
cmd.warn('MySQL adapter is not installed/registered; migrations may not hit a real MySQL DB.');
|
|
239
|
-
cmd.warn('Install via `zin plugin install adapter:mysql` (or `zin add db:mysql`).');
|
|
240
|
-
cmd.debug('[debug] Expected a side-effect import in src/zintrust.plugins.ts like: import "@zintrust/db-mysql/register";');
|
|
241
|
-
}
|
|
242
|
-
if (conn.driver === 'postgresql' && DatabaseAdapterRegistry.get('postgresql') === undefined) {
|
|
243
|
-
cmd.warn('PostgreSQL adapter is not installed/registered; migrations may not hit a real PostgreSQL DB.');
|
|
244
|
-
cmd.warn('Install via `zin plugin install adapter:postgres` (or `zin add db:postgres`).');
|
|
245
|
-
}
|
|
249
|
+
warnIfAdapterMissing(cmd, conn);
|
|
246
250
|
const db = Database.create(ormConfig);
|
|
247
251
|
await db.connect();
|
|
248
252
|
try {
|
|
@@ -261,7 +265,45 @@ const processConnection = async (conn, options, cmd, interactive) => {
|
|
|
261
265
|
await db.disconnect();
|
|
262
266
|
}
|
|
263
267
|
};
|
|
268
|
+
const processConnection = async (conn, options, cmd, interactive) => {
|
|
269
|
+
// Avoid confusion: `--database` is a D1-only option (Wrangler binding name), not DB_DATABASE.
|
|
270
|
+
logOptionsForConn(cmd, conn, options);
|
|
271
|
+
const { globalDir, extension, separateTracking } = getMigrationDirs();
|
|
272
|
+
const { service, includeGlobal } = getServiceArgs(options);
|
|
273
|
+
if (isWranglerD1Driver(conn.driver)) {
|
|
274
|
+
await runD1Actions({
|
|
275
|
+
options,
|
|
276
|
+
cmd,
|
|
277
|
+
projectRoot: process.cwd(),
|
|
278
|
+
globalDir,
|
|
279
|
+
extension,
|
|
280
|
+
separateTracking,
|
|
281
|
+
service,
|
|
282
|
+
includeGlobal,
|
|
283
|
+
});
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const run = async () => runOrmMigrationsForConn({
|
|
287
|
+
conn,
|
|
288
|
+
options,
|
|
289
|
+
cmd,
|
|
290
|
+
interactive,
|
|
291
|
+
globalDir,
|
|
292
|
+
extension,
|
|
293
|
+
separateTracking,
|
|
294
|
+
service,
|
|
295
|
+
includeGlobal,
|
|
296
|
+
});
|
|
297
|
+
if (conn.driver === 'd1-remote') {
|
|
298
|
+
cmd.info('[i] d1-remote migrations: using SQL mode automatically for this CLI run');
|
|
299
|
+
await withD1RemoteSqlMode(run);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
await run();
|
|
303
|
+
};
|
|
264
304
|
const executeMigrate = async (options, cmd) => {
|
|
305
|
+
// Ensure .env overlays are loaded for CLI runs (needed for d1-remote signing fallbacks).
|
|
306
|
+
EnvFileLoader.ensureLoaded();
|
|
265
307
|
const interactive = getInteractive(options);
|
|
266
308
|
const targets = [];
|
|
267
309
|
if (options['all'] === true) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MigrateWorkerCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/MigrateWorkerCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"MigrateWorkerCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/MigrateWorkerCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAiNrE,eAAO,MAAM,oBAAoB;cACrB,YAAY;EAUtB,CAAC"}
|
|
@@ -9,6 +9,19 @@ import { Migrator } from '../../migrations/Migrator.js';
|
|
|
9
9
|
import * as path from '../../node-singletons/path.js';
|
|
10
10
|
import { Database } from '../../orm/Database.js';
|
|
11
11
|
import { DatabaseAdapterRegistry } from '../../orm/DatabaseAdapterRegistry.js';
|
|
12
|
+
const isBuiltInDriver = (driver) => driver === 'sqlite' ||
|
|
13
|
+
driver === 'mysql' ||
|
|
14
|
+
driver === 'postgresql' ||
|
|
15
|
+
driver === 'sqlserver' ||
|
|
16
|
+
driver === 'd1' ||
|
|
17
|
+
driver === 'd1-remote';
|
|
18
|
+
const getWorkerPersistenceConnectionName = () => {
|
|
19
|
+
if (typeof process === 'undefined')
|
|
20
|
+
return 'default';
|
|
21
|
+
const raw = process.env?.['WORKER_PERSISTENCE_DB_CONNECTION'];
|
|
22
|
+
const value = typeof raw === 'string' ? raw.trim() : '';
|
|
23
|
+
return value.length > 0 ? value : 'default';
|
|
24
|
+
};
|
|
12
25
|
const addOptions = (command) => {
|
|
13
26
|
command
|
|
14
27
|
.option('--status', 'Display migration status (applied, pending, failed)')
|
|
@@ -80,10 +93,16 @@ const runForConnection = async (conn, options, cmd, interactive) => {
|
|
|
80
93
|
});
|
|
81
94
|
if (!proceed)
|
|
82
95
|
return;
|
|
83
|
-
if (!DatabaseAdapterRegistry.has(conn.driver)) {
|
|
96
|
+
if (!isBuiltInDriver(conn.driver) && !DatabaseAdapterRegistry.has(conn.driver)) {
|
|
84
97
|
cmd.warn(`Missing adapter for driver: ${conn.driver}`);
|
|
85
98
|
cmd.warn(`Install via 'zin plugin install adapter:${conn.driver}' (or 'zin add db:${conn.driver}').`);
|
|
86
99
|
}
|
|
100
|
+
const previousD1RemoteMode = typeof process === 'undefined' ? undefined : process.env['D1_REMOTE_MODE'];
|
|
101
|
+
if (conn.driver === 'd1-remote' && typeof process !== 'undefined') {
|
|
102
|
+
// Important: set BEFORE Database.create() so D1RemoteAdapter is constructed in SQL mode.
|
|
103
|
+
// Registry mode uses /zin/d1/statement, which is not appropriate for migrations.
|
|
104
|
+
process.env['D1_REMOTE_MODE'] = 'sql';
|
|
105
|
+
}
|
|
87
106
|
const ormConfig = mapConnectionToOrmConfig(conn);
|
|
88
107
|
const db = Database.create(ormConfig);
|
|
89
108
|
await db.connect();
|
|
@@ -98,6 +117,14 @@ const runForConnection = async (conn, options, cmd, interactive) => {
|
|
|
98
117
|
await runActions(migrator, options, cmd, conn.driver);
|
|
99
118
|
}
|
|
100
119
|
finally {
|
|
120
|
+
if (conn.driver === 'd1-remote' && typeof process !== 'undefined') {
|
|
121
|
+
if (previousD1RemoteMode === undefined) {
|
|
122
|
+
delete process.env['D1_REMOTE_MODE'];
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
process.env['D1_REMOTE_MODE'] = previousD1RemoteMode;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
101
128
|
await db.disconnect();
|
|
102
129
|
}
|
|
103
130
|
};
|
|
@@ -110,7 +137,14 @@ const executeMigrateWorker = async (options, cmd) => {
|
|
|
110
137
|
}
|
|
111
138
|
}
|
|
112
139
|
else {
|
|
113
|
-
|
|
140
|
+
const selected = getWorkerPersistenceConnectionName();
|
|
141
|
+
const hasSelected = selected.length > 0;
|
|
142
|
+
const connections = databaseConfig.connections;
|
|
143
|
+
const configured = hasSelected ? connections[selected] : undefined;
|
|
144
|
+
targets.push({
|
|
145
|
+
name: hasSelected ? selected : 'default',
|
|
146
|
+
config: configured ?? databaseConfig.getConnection(),
|
|
147
|
+
});
|
|
114
148
|
}
|
|
115
149
|
let sequence = Promise.resolve();
|
|
116
150
|
for (const { name, config } of targets) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PutCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/PutCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAmNvF,eAAO,MAAM,UAAU;cACX,YAAY;EAWtB,CAAC;AAEH,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { BaseCommand } from '../BaseCommand.js';
|
|
2
|
+
import { resolveNpmPath } from '../../common/index.js';
|
|
3
|
+
import { appConfig } from '../../config/app.js';
|
|
4
|
+
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
5
|
+
import { execFileSync } from '../../node-singletons/child-process.js';
|
|
6
|
+
import { existsSync, readFileSync } from '../../node-singletons/fs.js';
|
|
7
|
+
import * as path from '../../node-singletons/path.js';
|
|
8
|
+
import { EnvFile } from '../../toolkit/Secrets/EnvFile.js';
|
|
9
|
+
const toStringArray = (value) => {
|
|
10
|
+
if (typeof value === 'string')
|
|
11
|
+
return [value];
|
|
12
|
+
if (!Array.isArray(value))
|
|
13
|
+
return [];
|
|
14
|
+
return value.filter((v) => typeof v === 'string');
|
|
15
|
+
};
|
|
16
|
+
const uniq = (items) => {
|
|
17
|
+
const seen = new Set();
|
|
18
|
+
const out = [];
|
|
19
|
+
for (const item of items) {
|
|
20
|
+
const normalized = item.trim();
|
|
21
|
+
if (normalized === '' || seen.has(normalized))
|
|
22
|
+
continue;
|
|
23
|
+
seen.add(normalized);
|
|
24
|
+
out.push(normalized);
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
};
|
|
28
|
+
const readZintrustConfig = (cwd) => {
|
|
29
|
+
const filePath = path.join(cwd, '.zintrust.json');
|
|
30
|
+
if (!existsSync(filePath)) {
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const raw = readFileSync(filePath, 'utf8');
|
|
35
|
+
const parsed = JSON.parse(raw);
|
|
36
|
+
return typeof parsed === 'object' && parsed !== null ? parsed : {};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw ErrorFactory.createCliError('Failed to parse .zintrust.json', error);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const getConfigArray = (config, key) => {
|
|
43
|
+
const raw = config[key];
|
|
44
|
+
if (!Array.isArray(raw))
|
|
45
|
+
return [];
|
|
46
|
+
return uniq(raw.filter((item) => typeof item === 'string'));
|
|
47
|
+
};
|
|
48
|
+
const resolveConfigGroups = (options) => {
|
|
49
|
+
return uniq(toStringArray(options.var));
|
|
50
|
+
};
|
|
51
|
+
const resolveWranglerEnvs = (options) => {
|
|
52
|
+
const requested = uniq(toStringArray(options.wg));
|
|
53
|
+
if (requested.length === 0)
|
|
54
|
+
return ['worker'];
|
|
55
|
+
return requested;
|
|
56
|
+
};
|
|
57
|
+
const parseEnvPath = (options) => {
|
|
58
|
+
const direct = options['env_path'];
|
|
59
|
+
if (typeof direct === 'string' && direct.trim() !== '')
|
|
60
|
+
return direct;
|
|
61
|
+
return '.env';
|
|
62
|
+
};
|
|
63
|
+
const resolveValue = (key, envMap) => {
|
|
64
|
+
const fromFile = envMap[key];
|
|
65
|
+
const fromProcess = process.env[key];
|
|
66
|
+
return fromFile ?? fromProcess ?? '';
|
|
67
|
+
};
|
|
68
|
+
const getPutTimeoutMs = () => {
|
|
69
|
+
const raw = process.env['ZT_PUT_TIMEOUT_MS'];
|
|
70
|
+
if (typeof raw !== 'string')
|
|
71
|
+
return 120000;
|
|
72
|
+
const parsed = Number.parseInt(raw, 10);
|
|
73
|
+
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
74
|
+
return 120000;
|
|
75
|
+
return parsed;
|
|
76
|
+
};
|
|
77
|
+
const putSecret = (wranglerEnv, key, value) => {
|
|
78
|
+
const npmPath = resolveNpmPath();
|
|
79
|
+
execFileSync(npmPath, ['exec', '--yes', '--', 'wrangler', 'secret', 'put', key, '--env', wranglerEnv], {
|
|
80
|
+
stdio: ['pipe', 'inherit', 'inherit'],
|
|
81
|
+
input: value,
|
|
82
|
+
encoding: 'utf8',
|
|
83
|
+
timeout: getPutTimeoutMs(),
|
|
84
|
+
killSignal: 'SIGTERM',
|
|
85
|
+
env: appConfig.getSafeEnv(),
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
const addOptions = (command) => {
|
|
89
|
+
command
|
|
90
|
+
.argument('[provider]', 'Secret provider (cloudflare)', 'cloudflare')
|
|
91
|
+
.option('--wg <env...>', 'Wrangler environment target(s), e.g. d1-proxy kv-proxy')
|
|
92
|
+
.option('--var <configKey...>', 'Config array key(s) from .zintrust.json (e.g. d1_env kv_env)')
|
|
93
|
+
.option('--env_path <path>', 'Path to env file used as source values', '.env')
|
|
94
|
+
.option('--dry-run', 'Show what would be uploaded without calling wrangler');
|
|
95
|
+
};
|
|
96
|
+
const ensureCloudflareProvider = (providerRaw) => {
|
|
97
|
+
if (providerRaw.toLowerCase() === 'cloudflare')
|
|
98
|
+
return;
|
|
99
|
+
throw ErrorFactory.createCliError('Only cloudflare provider is supported for `zin put`');
|
|
100
|
+
};
|
|
101
|
+
const resolveSelectedKeys = (cmd, config, options) => {
|
|
102
|
+
const configGroups = resolveConfigGroups(options);
|
|
103
|
+
if (configGroups.length === 0) {
|
|
104
|
+
throw ErrorFactory.createCliError('No config groups selected. Use --var <group>.');
|
|
105
|
+
}
|
|
106
|
+
const selectedKeys = uniq(configGroups.flatMap((groupKey) => {
|
|
107
|
+
const keys = getConfigArray(config, groupKey);
|
|
108
|
+
if (keys.length === 0) {
|
|
109
|
+
cmd.warn(`Group \`${groupKey}\` is missing or empty in .zintrust.json`);
|
|
110
|
+
}
|
|
111
|
+
return keys;
|
|
112
|
+
}));
|
|
113
|
+
if (selectedKeys.length === 0) {
|
|
114
|
+
throw ErrorFactory.createCliError('No secret keys resolved from selected groups.');
|
|
115
|
+
}
|
|
116
|
+
return selectedKeys;
|
|
117
|
+
};
|
|
118
|
+
const getFailureReason = (error) => error instanceof Error ? error.message : String(error);
|
|
119
|
+
const reportResult = (cmd, pushed, failures) => {
|
|
120
|
+
cmd.success(`Cloudflare secrets report: pushed=${pushed}, failed=${failures.length}`);
|
|
121
|
+
for (const item of failures) {
|
|
122
|
+
cmd.warn(`${item.key} -> ${item.wranglerEnv}: ${item.reason}`);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const processPut = (cmd, wranglerEnvs, selectedKeys, envMap, dryRun) => {
|
|
126
|
+
let pushed = 0;
|
|
127
|
+
const failures = [];
|
|
128
|
+
for (const wranglerEnv of wranglerEnvs) {
|
|
129
|
+
for (const key of selectedKeys) {
|
|
130
|
+
const value = resolveValue(key, envMap);
|
|
131
|
+
if (value.trim() === '') {
|
|
132
|
+
failures.push({ wranglerEnv, key, reason: 'empty value' });
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
if (!dryRun) {
|
|
137
|
+
cmd.info(`putting ${key} -> ${wranglerEnv}...`);
|
|
138
|
+
putSecret(wranglerEnv, key, value);
|
|
139
|
+
}
|
|
140
|
+
pushed += 1;
|
|
141
|
+
cmd.info(`${dryRun ? '[dry-run] ' : ''}put ${key} -> ${wranglerEnv}`);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
failures.push({ wranglerEnv, key, reason: getFailureReason(error) });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return { pushed, failures };
|
|
149
|
+
};
|
|
150
|
+
const execute = async (cmd, options) => {
|
|
151
|
+
ensureCloudflareProvider(String(options.args?.[0] ?? 'cloudflare'));
|
|
152
|
+
const cwd = process.cwd();
|
|
153
|
+
const config = readZintrustConfig(cwd);
|
|
154
|
+
const selectedKeys = resolveSelectedKeys(cmd, config, options);
|
|
155
|
+
const envFilePath = parseEnvPath(options);
|
|
156
|
+
const envMap = await EnvFile.read({ cwd, path: envFilePath });
|
|
157
|
+
const wranglerEnvs = resolveWranglerEnvs(options);
|
|
158
|
+
const dryRun = options.dryRun === true;
|
|
159
|
+
const result = processPut(cmd, wranglerEnvs, selectedKeys, envMap, dryRun);
|
|
160
|
+
reportResult(cmd, result.pushed, result.failures);
|
|
161
|
+
};
|
|
162
|
+
export const PutCommand = Object.freeze({
|
|
163
|
+
create() {
|
|
164
|
+
const cmd = BaseCommand.create({
|
|
165
|
+
name: 'put',
|
|
166
|
+
description: 'Put secrets to Cloudflare with dynamic groups from .zintrust.json',
|
|
167
|
+
addOptions,
|
|
168
|
+
execute: async (options) => execute(cmd, options),
|
|
169
|
+
});
|
|
170
|
+
return cmd;
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
export default PutCommand;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueueRecoveryCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/QueueRecoveryCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"QueueRecoveryCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/QueueRecoveryCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAwvBrE,eAAO,MAAM,oBAAoB;cACrB,YAAY;EAsBtB,CAAC;AAEH,eAAe,oBAAoB,CAAC"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { BaseCommand } from '../BaseCommand.js';
|
|
2
|
+
import { databaseConfig } from '../../config/database.js';
|
|
2
3
|
import { Logger } from '../../config/logger.js';
|
|
3
4
|
import { queueConfig } from '../../config/queue.js';
|
|
4
5
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
5
|
-
import { useDatabase } from '../../orm/Database.js';
|
|
6
|
+
import { resetDatabase, useDatabase } from '../../orm/Database.js';
|
|
7
|
+
import { registerDatabasesFromRuntimeConfig } from '../../orm/DatabaseRuntimeRegistration.js';
|
|
6
8
|
import { JobRecoveryDaemon } from '../../tools/queue/JobRecoveryDaemon.js';
|
|
7
9
|
import { JobStateTracker } from '../../tools/queue/JobStateTracker.js';
|
|
8
10
|
import { Queue } from '../../tools/queue/Queue.js';
|
|
@@ -57,6 +59,7 @@ const normalizeStatus = (value) => {
|
|
|
57
59
|
const statuses = [
|
|
58
60
|
'pending',
|
|
59
61
|
'active',
|
|
62
|
+
'enqueued',
|
|
60
63
|
'completed',
|
|
61
64
|
'failed',
|
|
62
65
|
'stalled',
|
|
@@ -98,17 +101,13 @@ const toRecordFromPersisted = (row) => {
|
|
|
98
101
|
};
|
|
99
102
|
};
|
|
100
103
|
const getRecoverableStatuses = () => {
|
|
101
|
-
return new Set([
|
|
102
|
-
'pending_recovery',
|
|
103
|
-
'timeout',
|
|
104
|
-
'stalled',
|
|
105
|
-
'dead_letter',
|
|
106
|
-
]);
|
|
104
|
+
return new Set(['pending_recovery']);
|
|
107
105
|
};
|
|
108
106
|
const getAllStatuses = () => {
|
|
109
107
|
return new Set([
|
|
110
108
|
'pending',
|
|
111
109
|
'active',
|
|
110
|
+
'enqueued',
|
|
112
111
|
'completed',
|
|
113
112
|
'failed',
|
|
114
113
|
'stalled',
|
|
@@ -355,8 +354,35 @@ const runRecoveryOnce = async () => {
|
|
|
355
354
|
const result = await JobRecoveryDaemon.runOnce();
|
|
356
355
|
Logger.info('Queue recovery run completed', result);
|
|
357
356
|
};
|
|
357
|
+
const isDuplicateJobIdError = (error) => {
|
|
358
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
359
|
+
const normalized = message.toLowerCase();
|
|
360
|
+
return normalized.includes('jobid') && normalized.includes('already exists');
|
|
361
|
+
};
|
|
362
|
+
const validatePushable = (record) => {
|
|
363
|
+
if (record.status === 'enqueued') {
|
|
364
|
+
Logger.info('Job is already enqueued; nothing to push', {
|
|
365
|
+
jobId: record.jobId,
|
|
366
|
+
queueName: record.queueName,
|
|
367
|
+
});
|
|
368
|
+
return { ok: false };
|
|
369
|
+
}
|
|
370
|
+
if (record.status !== 'pending_recovery') {
|
|
371
|
+
Logger.error(`Refusing to push job in status ${record.status}. Only pending_recovery can be pushed.`);
|
|
372
|
+
if (typeof process !== 'undefined')
|
|
373
|
+
process.exitCode = 1;
|
|
374
|
+
return { ok: false };
|
|
375
|
+
}
|
|
376
|
+
return { ok: true };
|
|
377
|
+
};
|
|
358
378
|
const runPushForJob = async (record, options) => {
|
|
359
|
-
|
|
379
|
+
if (!validatePushable(record).ok)
|
|
380
|
+
return;
|
|
381
|
+
const basePayload = toSafeObject(record.payload);
|
|
382
|
+
const hasPayload = record.payload !== undefined &&
|
|
383
|
+
record.payload !== null &&
|
|
384
|
+
typeof record.payload === 'object' &&
|
|
385
|
+
Object.keys(basePayload).length > 0;
|
|
360
386
|
if (options.dryRun) {
|
|
361
387
|
Logger.info('Dry-run: skipping enqueue for target job', {
|
|
362
388
|
jobId: record.jobId,
|
|
@@ -365,12 +391,36 @@ const runPushForJob = async (record, options) => {
|
|
|
365
391
|
});
|
|
366
392
|
return;
|
|
367
393
|
}
|
|
368
|
-
|
|
369
|
-
|
|
394
|
+
if (!hasPayload) {
|
|
395
|
+
Logger.error(`Cannot push job because payload is missing in tracker/persistence store: ${record.jobId}. ` +
|
|
396
|
+
'Rehydrate payload_json first (or use policy recovery states) before pushing.');
|
|
397
|
+
if (typeof process !== 'undefined')
|
|
398
|
+
process.exitCode = 1;
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
const payload = {
|
|
402
|
+
...basePayload,
|
|
403
|
+
uniqueId: record.jobId,
|
|
404
|
+
attempts: typeof record.maxAttempts === 'number' ? record.maxAttempts : 3,
|
|
405
|
+
_currentAttempts: Math.max(0, Math.floor(record.attempts ?? 0)),
|
|
406
|
+
timestamp: Date.now(),
|
|
407
|
+
};
|
|
408
|
+
let replayJobId;
|
|
409
|
+
try {
|
|
410
|
+
replayJobId = await Queue.enqueue(record.queueName, payload, 'default');
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
if (isDuplicateJobIdError(error)) {
|
|
414
|
+
replayJobId = record.jobId;
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
throw error;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
await JobStateTracker.handedOffToQueue({
|
|
370
421
|
queueName: record.queueName,
|
|
371
422
|
jobId: record.jobId,
|
|
372
423
|
reason: `CLI pushed job as ${replayJobId}`,
|
|
373
|
-
retryAt: new Date().toISOString(),
|
|
374
424
|
});
|
|
375
425
|
Logger.info('Target job pushed to queue', {
|
|
376
426
|
originalJobId: record.jobId,
|
|
@@ -378,6 +428,21 @@ const runPushForJob = async (record, options) => {
|
|
|
378
428
|
queueName: record.queueName,
|
|
379
429
|
});
|
|
380
430
|
};
|
|
431
|
+
const isTestRuntime = () => (process.env['NODE_ENV'] ?? '').trim().toLowerCase() === 'test' || Boolean(process.env['VITEST']);
|
|
432
|
+
const cleanupOneOffCli = async () => {
|
|
433
|
+
try {
|
|
434
|
+
QueueReliabilityOrchestrator.stop();
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
// ignore
|
|
438
|
+
}
|
|
439
|
+
try {
|
|
440
|
+
await resetDatabase();
|
|
441
|
+
}
|
|
442
|
+
catch {
|
|
443
|
+
// ignore
|
|
444
|
+
}
|
|
445
|
+
};
|
|
381
446
|
const runRecoverOneForJob = async (record, options) => {
|
|
382
447
|
if (options.dryRun) {
|
|
383
448
|
Logger.info('Dry-run: skipping policy recovery for target job', {
|
|
@@ -456,10 +521,23 @@ const runTargetedRecovery = async (resolved) => {
|
|
|
456
521
|
return;
|
|
457
522
|
const record = await findRecord(resolved.jobId, resolved.queueName, resolved.allowDbLookup);
|
|
458
523
|
if (record === null) {
|
|
459
|
-
|
|
524
|
+
Logger.error(`Job not found in tracker${resolved.allowDbLookup ? ' or persistence store' : ''}: ${resolved.jobId}`);
|
|
525
|
+
if (typeof process !== 'undefined')
|
|
526
|
+
process.exitCode = 1;
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
if (record.status === 'enqueued' && !resolved.push) {
|
|
530
|
+
Logger.info('Job already enqueued; nothing to recover', {
|
|
531
|
+
jobId: record.jobId,
|
|
532
|
+
queueName: record.queueName,
|
|
533
|
+
});
|
|
534
|
+
return;
|
|
460
535
|
}
|
|
461
536
|
if (!resolved.push && !getRecoverableStatuses().has(record.status)) {
|
|
462
|
-
|
|
537
|
+
Logger.error(`Job status is not recoverable via policy runner: ${record.status}. Use --push to force requeue.`);
|
|
538
|
+
if (typeof process !== 'undefined')
|
|
539
|
+
process.exitCode = 1;
|
|
540
|
+
return;
|
|
463
541
|
}
|
|
464
542
|
if (resolved.push) {
|
|
465
543
|
await runPushForJob(record, { dryRun: resolved.dryRun });
|
|
@@ -480,11 +558,32 @@ const executeQueueRecovery = async (options) => {
|
|
|
480
558
|
const resolved = resolveExecutionOptions(options);
|
|
481
559
|
if (await maybeRunListMode(resolved))
|
|
482
560
|
return;
|
|
483
|
-
|
|
561
|
+
// Ensure DB connections exist for optional persistence lookups.
|
|
562
|
+
// (CLI commands don't run full app bootstrap.)
|
|
563
|
+
registerDatabasesFromRuntimeConfig(databaseConfig);
|
|
564
|
+
const envDefault = (process.env['QUEUE_DRIVER'] ?? '').toString().trim().toLowerCase();
|
|
565
|
+
const cliQueueConfig = {
|
|
566
|
+
...queueConfig,
|
|
567
|
+
default: (envDefault.length > 0
|
|
568
|
+
? envDefault
|
|
569
|
+
: queueConfig.default),
|
|
570
|
+
};
|
|
571
|
+
await registerQueuesFromRuntimeConfig(cliQueueConfig);
|
|
572
|
+
if (!resolved.start) {
|
|
573
|
+
// Queue registration may auto-start orchestrator when JOB_RELIABILITY_AUTOSTART=true.
|
|
574
|
+
// For one-off CLI runs, stop it to avoid noisy intervals.
|
|
575
|
+
QueueReliabilityOrchestrator.stop();
|
|
576
|
+
}
|
|
484
577
|
if (await maybeRunDefaultRecovery(resolved))
|
|
485
578
|
return;
|
|
486
579
|
await runTargetedRecovery(resolved);
|
|
487
580
|
await finalizeRecoveryExecution(resolved);
|
|
581
|
+
if (!resolved.start) {
|
|
582
|
+
await cleanupOneOffCli();
|
|
583
|
+
if (!isTestRuntime() && typeof process !== 'undefined') {
|
|
584
|
+
process.exit(process.exitCode ?? 0);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
488
587
|
};
|
|
489
588
|
export const QueueRecoveryCommand = Object.freeze({
|
|
490
589
|
create() {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScheduleListCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ScheduleListCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAsErE,eAAO,MAAM,mBAAmB;cACpB,YAAY;EAUtB,CAAC;AAEH,eAAe,mBAAmB,CAAC"}
|