@nmakarov/cli-toolkit 0.25.0 → 0.29.0
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/dist/cli-runner.cjs +118 -36
- package/dist/cli-runner.cjs.map +1 -1
- package/dist/cli-runner.js +118 -36
- package/dist/cli-runner.js.map +1 -1
- package/dist/index.cjs +114 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +114 -36
- package/dist/index.js.map +1 -1
- package/dist/init.cjs +94 -31
- package/dist/init.cjs.map +1 -1
- package/dist/init.js +94 -31
- package/dist/init.js.map +1 -1
- package/dist/params.cjs +69 -28
- package/dist/params.cjs.map +1 -1
- package/dist/params.js +69 -28
- package/dist/params.js.map +1 -1
- package/dist/s3.cjs +1 -0
- package/dist/s3.cjs.map +1 -1
- package/dist/s3.js +1 -0
- package/dist/s3.js.map +1 -1
- package/dist/tasks.cjs +25 -7
- package/dist/tasks.cjs.map +1 -1
- package/dist/tasks.js +25 -7
- package/dist/tasks.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1810,46 +1810,87 @@ var Params = class _Params {
|
|
|
1810
1810
|
paramGetters = [];
|
|
1811
1811
|
trackedParams = [];
|
|
1812
1812
|
_currentModule = "script";
|
|
1813
|
-
/**
|
|
1814
|
-
|
|
1813
|
+
/**
|
|
1814
|
+
* Resolved early in constructor so cleanup does not read params lazily.
|
|
1815
|
+
* One of: false (off) | "end" (print at exit) | "top" (print after init,
|
|
1816
|
+
* via context.showUsedParamsIfNeeded()) | "stop" (print after init, then
|
|
1817
|
+
* exit the process — also via context.showUsedParamsIfNeeded()).
|
|
1818
|
+
*/
|
|
1819
|
+
_showUsedParamsMode = false;
|
|
1820
|
+
/** Guard so the dump prints at most once (top OR end, never both). */
|
|
1821
|
+
_usedParamsPrinted = false;
|
|
1815
1822
|
constructor(context, options = {}) {
|
|
1816
1823
|
this.context = context;
|
|
1817
1824
|
this.args = context.args;
|
|
1818
1825
|
if (Object.keys(options).length > 0) {
|
|
1819
1826
|
this.configure(options);
|
|
1820
1827
|
}
|
|
1821
|
-
this.
|
|
1828
|
+
this._resolveShowUsedParams();
|
|
1822
1829
|
if (context && typeof context.registerCleanup === "function") {
|
|
1823
1830
|
context.registerCleanup((ctx) => {
|
|
1824
|
-
if (!ctx.params.
|
|
1825
|
-
|
|
1826
|
-
const modules = Object.keys(byModule).sort();
|
|
1827
|
-
if (modules.length === 0) return;
|
|
1828
|
-
const logger = ctx.logger;
|
|
1829
|
-
logger.debug("[Params]: list of used params:");
|
|
1830
|
-
if (typeof logger.highlight !== "function") {
|
|
1831
|
-
for (const mod of modules) {
|
|
1832
|
-
logger.debug(` [${mod}]`);
|
|
1833
|
-
for (const [key, entry] of Object.entries(byModule[mod])) {
|
|
1834
|
-
logger.debug(` ${key}: ${JSON.stringify(entry.value)} (${entry.source})`);
|
|
1835
|
-
}
|
|
1836
|
-
}
|
|
1837
|
-
return;
|
|
1838
|
-
}
|
|
1839
|
-
for (const mod of modules) {
|
|
1840
|
-
logger.debug(` [${mod}]`);
|
|
1841
|
-
for (const [key, entry] of Object.entries(byModule[mod])) {
|
|
1842
|
-
const valueStr = JSON.stringify(entry.value);
|
|
1843
|
-
const display = entry.source === "default" ? valueStr : logger.highlight(valueStr);
|
|
1844
|
-
logger.debug(` ${key}: ${display} (${entry.source})`);
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1831
|
+
if (!ctx.params.getShowUsedParamsMode()) return;
|
|
1832
|
+
ctx.params.printUsedParams(ctx.logger);
|
|
1847
1833
|
});
|
|
1848
1834
|
}
|
|
1849
1835
|
}
|
|
1850
|
-
/**
|
|
1836
|
+
/**
|
|
1837
|
+
* Resolve the --showUsedParams mode. The flag is intentionally dual-typed:
|
|
1838
|
+
* (absent) / --no-showUsedParams / =false -> false (off)
|
|
1839
|
+
* --showUsedParams / =true -> "end" (print at exit)
|
|
1840
|
+
* --showUsedParams=top -> "top" (print after init)
|
|
1841
|
+
* --showUsedParams=stop -> "stop" (print after init, then exit)
|
|
1842
|
+
* Read raw (uncoerced) from args so the string "top"/"stop" isn't forced to
|
|
1843
|
+
* a boolean, then track it under the "script" module for the dump itself.
|
|
1844
|
+
*/
|
|
1845
|
+
_resolveShowUsedParams() {
|
|
1846
|
+
const raw = this.args.get("showUsedParams");
|
|
1847
|
+
const source = this.args.getSource?.("showUsedParams") ?? "default";
|
|
1848
|
+
let mode = false;
|
|
1849
|
+
if (raw === void 0 || raw === null) {
|
|
1850
|
+
mode = false;
|
|
1851
|
+
} else if (typeof raw === "string" && raw.trim().toLowerCase() === "top") {
|
|
1852
|
+
mode = "top";
|
|
1853
|
+
} else if (typeof raw === "string" && raw.trim().toLowerCase() === "stop") {
|
|
1854
|
+
mode = "stop";
|
|
1855
|
+
} else {
|
|
1856
|
+
const s = typeof raw === "string" ? raw.trim().toLowerCase() : raw;
|
|
1857
|
+
const falsey = s === false || s === "false" || s === "0" || s === "no" || s === "off";
|
|
1858
|
+
mode = falsey ? false : "end";
|
|
1859
|
+
}
|
|
1860
|
+
this._showUsedParamsMode = mode;
|
|
1861
|
+
this.trackParam("showUsedParams", "string", mode, raw === void 0 ? "default" : source, "script");
|
|
1862
|
+
return mode;
|
|
1863
|
+
}
|
|
1864
|
+
/** Whether --showUsedParams was requested in any mode (truthy = on). */
|
|
1851
1865
|
getShowUsedParams() {
|
|
1852
|
-
return this.
|
|
1866
|
+
return this._showUsedParamsMode !== false;
|
|
1867
|
+
}
|
|
1868
|
+
/** Resolved mode: false | "end" | "top" | "stop". */
|
|
1869
|
+
getShowUsedParamsMode() {
|
|
1870
|
+
return this._showUsedParamsMode;
|
|
1871
|
+
}
|
|
1872
|
+
/**
|
|
1873
|
+
* Print the module-grouped list of figured params (the --showUsedParams
|
|
1874
|
+
* dump). Idempotent: only the first call prints, so callers can invoke it
|
|
1875
|
+
* at the top (long-running services) without double-printing at exit.
|
|
1876
|
+
*/
|
|
1877
|
+
printUsedParams(logger) {
|
|
1878
|
+
if (this._usedParamsPrinted) return;
|
|
1879
|
+
const byModule = this.getFiguredByModule();
|
|
1880
|
+
const modules = Object.keys(byModule).sort();
|
|
1881
|
+
if (modules.length === 0) return;
|
|
1882
|
+
this._usedParamsPrinted = true;
|
|
1883
|
+
logger = logger ?? this.context?.logger ?? console;
|
|
1884
|
+
const hasHighlight = typeof logger.highlight === "function";
|
|
1885
|
+
logger.debug("[Params]: list of used params:");
|
|
1886
|
+
for (const mod of modules) {
|
|
1887
|
+
logger.debug(` [${mod}]`);
|
|
1888
|
+
for (const [key, entry] of Object.entries(byModule[mod])) {
|
|
1889
|
+
const valueStr = JSON.stringify(entry.value);
|
|
1890
|
+
const display = hasHighlight && entry.source !== "default" ? logger.highlight(valueStr) : valueStr;
|
|
1891
|
+
logger.debug(` ${key}: ${display} (${entry.source})`);
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1853
1894
|
}
|
|
1854
1895
|
/**
|
|
1855
1896
|
* Configure parameters
|
|
@@ -3859,6 +3900,7 @@ var S3 = class _S3 {
|
|
|
3859
3900
|
secretAccessKey: config2.secretAccessKey
|
|
3860
3901
|
};
|
|
3861
3902
|
}
|
|
3903
|
+
process.env.AWS_SDK_JS_NODE_VERSION_SUPPORT_WARNING_DISABLED ??= "true";
|
|
3862
3904
|
this.client = new import_client_s3.S3Client(clientConfig);
|
|
3863
3905
|
}
|
|
3864
3906
|
// ── info ────────────────────────────────────────────────────────────────
|
|
@@ -4385,7 +4427,25 @@ function setup(opts = {}) {
|
|
|
4385
4427
|
emitter: partialContext.emitter,
|
|
4386
4428
|
isStop: partialContext.isStop,
|
|
4387
4429
|
cleanupFunctions: partialContext.cleanupFunctions,
|
|
4388
|
-
registerCleanup: partialContext.registerCleanup
|
|
4430
|
+
registerCleanup: partialContext.registerCleanup,
|
|
4431
|
+
// For long-running scripts (servers): with --showUsedParams=top, print
|
|
4432
|
+
// the used-params list now (after the script has initialized all its
|
|
4433
|
+
// own components), instead of at exit. No-op for the default mode,
|
|
4434
|
+
// which prints at exit via the cleanup registered by Params.
|
|
4435
|
+
//
|
|
4436
|
+
// --showUsedParams=stop behaves like "top" but then exits immediately —
|
|
4437
|
+
// a quick "show me the figured params and quit" that skips the flow's
|
|
4438
|
+
// actual work. Like --stopAfter=init, this is a hard exit(0) (registered
|
|
4439
|
+
// cleanups are skipped); call it once components/params are resolved.
|
|
4440
|
+
showUsedParamsIfNeeded: () => {
|
|
4441
|
+
const mode = params.getShowUsedParamsMode?.();
|
|
4442
|
+
if (mode !== "top" && mode !== "stop") return;
|
|
4443
|
+
params.printUsedParams(logger);
|
|
4444
|
+
if (mode === "stop") {
|
|
4445
|
+
logger.debug?.("[showUsedParams=stop] params printed \u2014 exiting");
|
|
4446
|
+
process.exit(0);
|
|
4447
|
+
}
|
|
4448
|
+
}
|
|
4389
4449
|
};
|
|
4390
4450
|
logger.debug("[setup] completed successfully");
|
|
4391
4451
|
return context;
|
|
@@ -4507,7 +4567,7 @@ function defineTasksTable(t, db, tableNameForIndex) {
|
|
|
4507
4567
|
t.timestamp("past_due").defaultTo(null);
|
|
4508
4568
|
t.text("name").notNullable();
|
|
4509
4569
|
t.text("opid");
|
|
4510
|
-
t.
|
|
4570
|
+
t.jsonb("params");
|
|
4511
4571
|
t.text("service_group");
|
|
4512
4572
|
t.integer("instance_number");
|
|
4513
4573
|
t.text("service_name");
|
|
@@ -4516,7 +4576,7 @@ function defineTasksTable(t, db, tableNameForIndex) {
|
|
|
4516
4576
|
t.timestamp("status_changed_at").defaultTo(null);
|
|
4517
4577
|
t.text("progress");
|
|
4518
4578
|
t.boolean("success");
|
|
4519
|
-
t.
|
|
4579
|
+
t.jsonb("results");
|
|
4520
4580
|
t.index(["service_group", "status", "priority", "created_at"], `${tableNameForIndex}_claim_idx`);
|
|
4521
4581
|
t.index(["service_group", "name"], `${tableNameForIndex}_group_name_idx`);
|
|
4522
4582
|
}
|
|
@@ -4531,11 +4591,29 @@ function taskHistoryInsertFromQueueRow(row, overrides) {
|
|
|
4531
4591
|
async function ensureTaskTables(context, options = {}) {
|
|
4532
4592
|
const queueName = options.queueName ?? "tasks";
|
|
4533
4593
|
const recreate = options.recreate ?? false;
|
|
4594
|
+
const dryRun = options.dryRun ?? false;
|
|
4534
4595
|
const db = getDb(context);
|
|
4596
|
+
const log = context.logger ?? console;
|
|
4535
4597
|
const { tasksTable, historyTable, registryTable } = queueToTableNames(queueName);
|
|
4536
4598
|
const needsTasks = recreate ? true : !await db.tableExists(tasksTable);
|
|
4537
4599
|
const needsHistory = recreate ? true : !await db.tableExists(historyTable);
|
|
4538
4600
|
const needsRegistry = recreate ? true : !await db.tableExists(registryTable);
|
|
4601
|
+
if (dryRun) {
|
|
4602
|
+
const plan = [];
|
|
4603
|
+
if (recreate) {
|
|
4604
|
+
plan.push(`DROP TABLE IF EXISTS ${historyTable}, ${tasksTable}, ${registryTable}`);
|
|
4605
|
+
}
|
|
4606
|
+
if (needsTasks) plan.push(`CREATE TABLE ${tasksTable} (tasks queue)`);
|
|
4607
|
+
if (needsHistory) plan.push(`CREATE TABLE ${historyTable} (history mirror)`);
|
|
4608
|
+
if (needsRegistry) plan.push(`CREATE TABLE ${registryTable} (services registry)`);
|
|
4609
|
+
if (plan.length === 0) {
|
|
4610
|
+
log.info?.(`[tasks-schema] dryRun \u2014 queue "${queueName}" already up to date; no DDL`);
|
|
4611
|
+
} else {
|
|
4612
|
+
log.info?.(`[tasks-schema] dryRun \u2014 would run ${plan.length} statement(s) for queue "${queueName}":`);
|
|
4613
|
+
for (const s of plan) log.info?.(` - ${s}`);
|
|
4614
|
+
}
|
|
4615
|
+
return;
|
|
4616
|
+
}
|
|
4539
4617
|
if (recreate) {
|
|
4540
4618
|
await db.schema.dropTableIfExists(historyTable);
|
|
4541
4619
|
await db.schema.dropTableIfExists(tasksTable);
|
|
@@ -5978,8 +6056,7 @@ function forwardChildLogToParent(context, prefix, message) {
|
|
|
5978
6056
|
}
|
|
5979
6057
|
function buildNodeArgs(scriptPath, cliArgs) {
|
|
5980
6058
|
const inheritedExecArgs = Array.isArray(process.execArgv) ? [...process.execArgv] : [];
|
|
5981
|
-
|
|
5982
|
-
return hasTsRuntimeInParent ? [...inheritedExecArgs, scriptPath, ...cliArgs] : ["--import", "tsx", scriptPath, ...cliArgs];
|
|
6059
|
+
return [...inheritedExecArgs, scriptPath, ...cliArgs];
|
|
5983
6060
|
}
|
|
5984
6061
|
function resolveTasksTableName(context) {
|
|
5985
6062
|
return context.tasksQueueName || context.params?.get?.("table") || "tasks";
|
|
@@ -6219,9 +6296,8 @@ async function executeClaimedTask(context, tasksTable, historyTable, row, regist
|
|
|
6219
6296
|
const dbName = String(context?.params?.get?.("dbName") || "local");
|
|
6220
6297
|
const tableName = String(context?.params?.get?.("table") || "tasks");
|
|
6221
6298
|
const fallbackRecoverCommand = [
|
|
6222
|
-
"
|
|
6223
|
-
"
|
|
6224
|
-
"examples/tasks/recover-task.ts",
|
|
6299
|
+
"node",
|
|
6300
|
+
"examples/tasks/recover-task.js",
|
|
6225
6301
|
`--dbName='${dbName.replace(/'/g, `'\\''`)}'`,
|
|
6226
6302
|
`--table='${tableName.replace(/'/g, `'\\''`)}'`,
|
|
6227
6303
|
`--id='${String(row.id).replace(/'/g, `'\\''`)}'`
|
|
@@ -6287,6 +6363,8 @@ async function claimNextRunnableTask(context, tasksTable, serviceGroup, registry
|
|
|
6287
6363
|
const db = getDb3(context);
|
|
6288
6364
|
let query = db(tasksTable).where({ status: "idle" }).where(function() {
|
|
6289
6365
|
this.whereNull("service_group").orWhere({ service_group: serviceGroup });
|
|
6366
|
+
}).where(function() {
|
|
6367
|
+
this.whereNull("next_run_at").orWhere("next_run_at", "<=", db.fn.now());
|
|
6290
6368
|
}).orderByRaw("CASE WHEN past_due IS NULL THEN 1 ELSE 0 END ASC").orderBy([{ column: "priority", order: "asc" }]).orderByRaw("CASE WHEN completed_at IS NULL THEN 0 ELSE 1 END ASC").orderBy([{ column: "completed_at", order: "asc" }, { column: "created_at", order: "asc" }]).limit(scanLimit);
|
|
6291
6369
|
if (taskNames && taskNames.length > 0) {
|
|
6292
6370
|
query = query.whereIn("name", taskNames);
|