@nmakarov/cli-toolkit 0.59.0 → 0.63.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 +51 -4
- package/dist/cli-runner.cjs.map +1 -1
- package/dist/cli-runner.js +51 -4
- package/dist/cli-runner.js.map +1 -1
- package/dist/db.cjs +16 -3
- package/dist/db.cjs.map +1 -1
- package/dist/db.js +16 -3
- package/dist/db.js.map +1 -1
- package/dist/deploy.cjs +57 -16
- package/dist/deploy.cjs.map +1 -1
- package/dist/deploy.js +57 -16
- package/dist/deploy.js.map +1 -1
- package/dist/index.cjs +110 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +109 -20
- package/dist/index.js.map +1 -1
- package/dist/init.cjs +5 -0
- package/dist/init.cjs.map +1 -1
- package/dist/init.js +5 -0
- package/dist/init.js.map +1 -1
- package/dist/logger.cjs +5 -0
- package/dist/logger.cjs.map +1 -1
- package/dist/logger.js +5 -0
- package/dist/logger.js.map +1 -1
- package/dist/tasks.cjs +32 -1
- package/dist/tasks.cjs.map +1 -1
- package/dist/tasks.js +31 -1
- package/dist/tasks.js.map +1 -1
- package/package.json +1 -1
- package/scripts/deploy/cli.js +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1125,6 +1125,7 @@ __export(src_exports, {
|
|
|
1125
1125
|
controlLaneTaskNames: () => controlLaneTaskNames,
|
|
1126
1126
|
convertPattern: () => convertPattern,
|
|
1127
1127
|
createRelease: () => createRelease,
|
|
1128
|
+
createTaskProgressReporter: () => createTaskProgressReporter,
|
|
1128
1129
|
defaultFileSynopsisFunction: () => defaultFileSynopsisFunction,
|
|
1129
1130
|
defaultTasksRegistry: () => defaultTasksRegistry,
|
|
1130
1131
|
defaultVersionSynopsisFunction: () => defaultVersionSynopsisFunction,
|
|
@@ -3693,13 +3694,15 @@ var CONNECTION_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
|
3693
3694
|
"57P02",
|
|
3694
3695
|
"57P03"
|
|
3695
3696
|
]);
|
|
3696
|
-
var CONNECTION_ERROR_MESSAGE_RE = /connection (terminated|ended|closed|destroyed|reset|refused|not open)|Connection terminated unexpectedly|Client has encountered a connection error|server closed the connection|Cannot use a pool after calling end|This socket has been ended|connect ECONNRESET
|
|
3697
|
+
var CONNECTION_ERROR_MESSAGE_RE = /connection (terminated|ended|closed|destroyed|reset|refused|not open)|Connection terminated unexpectedly|Client has encountered a connection error|server closed the connection|Cannot use a pool after calling end|This socket has been ended|connect ECONNRESET/i;
|
|
3697
3698
|
var Db = class _Db {
|
|
3698
3699
|
static async init(context, options = {}) {
|
|
3699
3700
|
const buildConfig = async () => {
|
|
3700
3701
|
const defs = {
|
|
3701
3702
|
dbName: "string",
|
|
3702
|
-
dbProfile: "boolean default false"
|
|
3703
|
+
dbProfile: "boolean default false",
|
|
3704
|
+
/** Cap knex pool size (default 10). Size ≈ expected concurrency + headroom. */
|
|
3705
|
+
dbPoolMax: "number"
|
|
3703
3706
|
};
|
|
3704
3707
|
const discovered = context?.params?.getAllForModule?.("db", defs) ?? {};
|
|
3705
3708
|
const merged = { ...discovered, ...options };
|
|
@@ -3758,12 +3761,23 @@ var Db = class _Db {
|
|
|
3758
3761
|
context?.args?.env,
|
|
3759
3762
|
merged.name
|
|
3760
3763
|
);
|
|
3764
|
+
const poolMaxRaw = merged.dbPoolMax ?? merged.pool?.max;
|
|
3765
|
+
const poolMax = Number(poolMaxRaw);
|
|
3766
|
+
const pool = {
|
|
3767
|
+
...KNEX_DEFAULTS.pool,
|
|
3768
|
+
...merged.pool && typeof merged.pool === "object" ? merged.pool : {}
|
|
3769
|
+
};
|
|
3770
|
+
if (Number.isFinite(poolMax) && poolMax >= 1) {
|
|
3771
|
+
pool.max = Math.floor(poolMax);
|
|
3772
|
+
}
|
|
3761
3773
|
return {
|
|
3762
3774
|
...KNEX_DEFAULTS,
|
|
3763
3775
|
connectionString: dbConnectionString,
|
|
3764
3776
|
name: displayName,
|
|
3765
3777
|
profile: !!dbProfile,
|
|
3766
|
-
logger: context.logger
|
|
3778
|
+
logger: context.logger,
|
|
3779
|
+
pool,
|
|
3780
|
+
...merged.acquireConnectionTimeout != null ? { acquireConnectionTimeout: merged.acquireConnectionTimeout } : {}
|
|
3767
3781
|
};
|
|
3768
3782
|
};
|
|
3769
3783
|
const config2 = context?.params?.runWithModuleAsync ? await context.params.runWithModuleAsync("db", buildConfig) : await buildConfig();
|
|
@@ -5190,6 +5204,9 @@ var Logger = class _Logger {
|
|
|
5190
5204
|
const message = this.inspectChunks([operation, ...chunks]);
|
|
5191
5205
|
this.out({ level: "response", message });
|
|
5192
5206
|
}
|
|
5207
|
+
/**
|
|
5208
|
+
* @returns {boolean} true when the progress line was emitted (not throttled)
|
|
5209
|
+
*/
|
|
5193
5210
|
progress(message, opts) {
|
|
5194
5211
|
const { prefix, count, total } = opts;
|
|
5195
5212
|
const paddedTotal = String(total).length;
|
|
@@ -5223,7 +5240,9 @@ var Logger = class _Logger {
|
|
|
5223
5240
|
if (this.options.progressThrottle && prefix) {
|
|
5224
5241
|
this.lastProgressTimes[prefix] = Date.now();
|
|
5225
5242
|
}
|
|
5243
|
+
return true;
|
|
5226
5244
|
}
|
|
5245
|
+
return false;
|
|
5227
5246
|
}
|
|
5228
5247
|
shouldOutputProgress(prefix, count, total) {
|
|
5229
5248
|
if (!this.options.progressThrottle) {
|
|
@@ -5819,10 +5838,47 @@ function isFreshOnline(proc, oldPid) {
|
|
|
5819
5838
|
}
|
|
5820
5839
|
return true;
|
|
5821
5840
|
}
|
|
5841
|
+
async function deletePm2App(appName, options = {}) {
|
|
5842
|
+
const { dryRun = false, logger = console, waitTimeoutMs = 65e3, oldPid = null } = options;
|
|
5843
|
+
if (dryRun) {
|
|
5844
|
+
logger.info(`[dryRun] would pm2 delete ${appName}`);
|
|
5845
|
+
return;
|
|
5846
|
+
}
|
|
5847
|
+
const before = await getPm2Process(appName, { logger });
|
|
5848
|
+
if (!before) {
|
|
5849
|
+
logger.info(`pm2 ${appName}: not present (skip delete)`);
|
|
5850
|
+
return;
|
|
5851
|
+
}
|
|
5852
|
+
await runShell(`pm2 delete "${appName}"`, { logger });
|
|
5853
|
+
await waitPm2(
|
|
5854
|
+
appName,
|
|
5855
|
+
(proc) => {
|
|
5856
|
+
if (proc) return false;
|
|
5857
|
+
if (oldPid != null && isPidAlive(oldPid)) return false;
|
|
5858
|
+
return true;
|
|
5859
|
+
},
|
|
5860
|
+
{ timeoutMs: waitTimeoutMs, logger, label: "deleted (process gone)" }
|
|
5861
|
+
);
|
|
5862
|
+
logger.info(`pm2 ${appName} deleted`);
|
|
5863
|
+
}
|
|
5864
|
+
async function startFromEcosystem(paths, options = {}) {
|
|
5865
|
+
const { dryRun = false, logger = console } = options;
|
|
5866
|
+
if (dryRun) {
|
|
5867
|
+
logger.info(`[dryRun] would pm2 start ${paths.ecosystem} --update-env`);
|
|
5868
|
+
return;
|
|
5869
|
+
}
|
|
5870
|
+
await runShell(
|
|
5871
|
+
`ENV=production NODE_ENV=production pm2 start "${paths.ecosystem}" --update-env`,
|
|
5872
|
+
{ logger }
|
|
5873
|
+
);
|
|
5874
|
+
logger.info("pm2 started from ecosystem");
|
|
5875
|
+
}
|
|
5822
5876
|
async function reloadPm2(paths, options = {}) {
|
|
5823
5877
|
const { dryRun = false, logger = console, appName = null, waitTimeoutMs = 65e3 } = options;
|
|
5824
5878
|
if (dryRun) {
|
|
5825
|
-
logger.info(
|
|
5879
|
+
logger.info(
|
|
5880
|
+
`[dryRun] would pm2 delete${appName ? ` ${appName}` : ""} + start ${paths.ecosystem} --update-env`
|
|
5881
|
+
);
|
|
5826
5882
|
return;
|
|
5827
5883
|
}
|
|
5828
5884
|
let oldPid = null;
|
|
@@ -5831,14 +5887,15 @@ async function reloadPm2(paths, options = {}) {
|
|
|
5831
5887
|
const n = Number(before?.pid);
|
|
5832
5888
|
if (Number.isFinite(n) && n > 0 && before?.pm2_env?.status === "online") {
|
|
5833
5889
|
oldPid = n;
|
|
5834
|
-
logger.info(`pm2 ${appName}:
|
|
5890
|
+
logger.info(`pm2 ${appName}: recreate (old pid=${oldPid})`);
|
|
5835
5891
|
}
|
|
5892
|
+
await deletePm2App(appName, { dryRun, logger, waitTimeoutMs, oldPid });
|
|
5893
|
+
} else {
|
|
5894
|
+
logger.warn?.(
|
|
5895
|
+
"reloadPm2: appName missing; starting ecosystem without delete (pass appName so script/env always recreate cleanly)"
|
|
5896
|
+
);
|
|
5836
5897
|
}
|
|
5837
|
-
await
|
|
5838
|
-
`ENV=production NODE_ENV=production pm2 startOrReload "${paths.ecosystem}" --update-env`,
|
|
5839
|
-
{ logger }
|
|
5840
|
-
);
|
|
5841
|
-
logger.info("pm2 reloaded");
|
|
5898
|
+
await startFromEcosystem(paths, { dryRun, logger });
|
|
5842
5899
|
if (appName) {
|
|
5843
5900
|
const proc = await waitPm2(
|
|
5844
5901
|
appName,
|
|
@@ -5846,7 +5903,7 @@ async function reloadPm2(paths, options = {}) {
|
|
|
5846
5903
|
{
|
|
5847
5904
|
timeoutMs: waitTimeoutMs,
|
|
5848
5905
|
logger,
|
|
5849
|
-
label: oldPid ? `online on new pid (old ${oldPid} gone)` : "online after
|
|
5906
|
+
label: oldPid ? `online on new pid (old ${oldPid} gone)` : "online after recreate"
|
|
5850
5907
|
}
|
|
5851
5908
|
);
|
|
5852
5909
|
logger.info(`pm2 ${appName} online pid=${proc?.pid ?? "?"}`);
|
|
@@ -5883,14 +5940,15 @@ async function stopPm2(appName, options = {}) {
|
|
|
5883
5940
|
async function startPm2(paths, options = {}) {
|
|
5884
5941
|
const { dryRun = false, logger = console, appName = null, waitTimeoutMs = 65e3 } = options;
|
|
5885
5942
|
if (dryRun) {
|
|
5886
|
-
logger.info(
|
|
5943
|
+
logger.info(
|
|
5944
|
+
`[dryRun] would pm2 delete${appName ? ` ${appName}` : ""} + start ${paths.ecosystem} --update-env`
|
|
5945
|
+
);
|
|
5887
5946
|
return;
|
|
5888
5947
|
}
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
);
|
|
5893
|
-
logger.info("pm2 started");
|
|
5948
|
+
if (appName) {
|
|
5949
|
+
await deletePm2App(appName, { dryRun, logger, waitTimeoutMs });
|
|
5950
|
+
}
|
|
5951
|
+
await startFromEcosystem(paths, { dryRun, logger });
|
|
5894
5952
|
if (appName) {
|
|
5895
5953
|
const proc = await waitPm2(
|
|
5896
5954
|
appName,
|
|
@@ -6145,7 +6203,7 @@ function buildEnsureEnvScript() {
|
|
|
6145
6203
|
return `/**
|
|
6146
6204
|
* Written by cli-toolkit deploy (init-structure). Do not hand-edit.
|
|
6147
6205
|
* Preloaded via pm2 node_args --require. Always set (do not only fill when unset):
|
|
6148
|
-
* \`pm2
|
|
6206
|
+
* \`pm2 start \u2026 --update-env\` can inject a non-production ENV from the
|
|
6149
6207
|
* deploy shell / prior dump, and a conditional assign would leave it in place.
|
|
6150
6208
|
*/
|
|
6151
6209
|
process.env.ENV = "production";
|
|
@@ -6511,7 +6569,9 @@ async function rollbackService(service, options = {}) {
|
|
|
6511
6569
|
logger.info(`rollback target: v${buildInfo.version} release=${buildInfo.release ?? rollbackTarget.name}`);
|
|
6512
6570
|
}
|
|
6513
6571
|
await activateRelease(rollbackTarget.path, paths, { dryRun, logger });
|
|
6514
|
-
|
|
6572
|
+
const appName = service.pm2?.appName ?? null;
|
|
6573
|
+
const waitTimeoutMs = 65e3;
|
|
6574
|
+
await reloadPm2(paths, { dryRun, logger, appName, waitTimeoutMs });
|
|
6515
6575
|
const summary = `rollback ${activeName} \u2192 ${rollbackTarget.name} dryRun=${dryRun}`;
|
|
6516
6576
|
if (!dryRun) await appendDeployLog(paths.deployLog, summary);
|
|
6517
6577
|
return { from: activeName, to: rollbackTarget.name, path: rollbackTarget.path };
|
|
@@ -7022,6 +7082,34 @@ async function updateTaskProgress(context, tasksTable, taskId, progress) {
|
|
|
7022
7082
|
progress: typeof progress === "string" ? progress : JSON.stringify(progress)
|
|
7023
7083
|
});
|
|
7024
7084
|
}
|
|
7085
|
+
function createTaskProgressReporter(context, tasksTable, taskId) {
|
|
7086
|
+
let pump = null;
|
|
7087
|
+
let pending = void 0;
|
|
7088
|
+
let hasPending = false;
|
|
7089
|
+
return (progress) => {
|
|
7090
|
+
pending = progress;
|
|
7091
|
+
hasPending = true;
|
|
7092
|
+
if (pump) return pump;
|
|
7093
|
+
pump = (async () => {
|
|
7094
|
+
try {
|
|
7095
|
+
while (hasPending) {
|
|
7096
|
+
hasPending = false;
|
|
7097
|
+
const value = pending;
|
|
7098
|
+
try {
|
|
7099
|
+
await updateTaskProgress(context, tasksTable, taskId, value);
|
|
7100
|
+
} catch (err) {
|
|
7101
|
+
context.logger?.warn?.(
|
|
7102
|
+
`[tasks] progress update failed for ${taskId}: ${err?.message ?? err}`
|
|
7103
|
+
);
|
|
7104
|
+
}
|
|
7105
|
+
}
|
|
7106
|
+
} finally {
|
|
7107
|
+
pump = null;
|
|
7108
|
+
}
|
|
7109
|
+
})();
|
|
7110
|
+
return pump;
|
|
7111
|
+
};
|
|
7112
|
+
}
|
|
7025
7113
|
|
|
7026
7114
|
// src/tasks/servicesRegistry.js
|
|
7027
7115
|
function getDb2(context) {
|
|
@@ -8873,7 +8961,8 @@ async function executeClaimedTask(context, tasksTable, historyTable, row, regist
|
|
|
8873
8961
|
try {
|
|
8874
8962
|
taskInstance = new TaskClass(context, row);
|
|
8875
8963
|
runningTaskInstances.set(row.id, taskInstance);
|
|
8876
|
-
const
|
|
8964
|
+
const reportProgress = createTaskProgressReporter(context, tasksTable, row.id);
|
|
8965
|
+
const runResult = await taskInstance.run(reportProgress);
|
|
8877
8966
|
success = !!runResult?.success;
|
|
8878
8967
|
results = runResult?.results ?? null;
|
|
8879
8968
|
} catch (error) {
|
|
@@ -9421,6 +9510,7 @@ var TasksManager = class _TasksManager {
|
|
|
9421
9510
|
controlLaneTaskNames,
|
|
9422
9511
|
convertPattern,
|
|
9423
9512
|
createRelease,
|
|
9513
|
+
createTaskProgressReporter,
|
|
9424
9514
|
defaultFileSynopsisFunction,
|
|
9425
9515
|
defaultTasksRegistry,
|
|
9426
9516
|
defaultVersionSynopsisFunction,
|