@iola_adm/iola-cli 0.1.91 → 0.1.93

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.
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from "node:child_process";
3
+ import { fileURLToPath } from "node:url";
4
+ import { dirname, resolve } from "node:path";
5
+
6
+ const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
7
+ const cliPath = resolve(rootDir, "bin", "iola.js");
8
+ const node = process.execPath;
9
+ const frames = ["|", "/", "-", "\\"];
10
+
11
+ const steps = [
12
+ {
13
+ title: "Подготовка локальной БД",
14
+ args: [cliPath, "db", "init", "--silent"],
15
+ },
16
+ {
17
+ title: "Проверка браузерного runtime",
18
+ args: [cliPath, "browser", "install"],
19
+ },
20
+ {
21
+ title: "Проверка локальной модели IOLA",
22
+ args: [cliPath, "ai", "setup", "iola", "--yes", "--quiet", "--optional"],
23
+ },
24
+ ];
25
+
26
+ const canAnimate = process.stdout.isTTY && process.env.CI !== "true";
27
+
28
+ console.log("");
29
+ console.log("IOLA CLI: настройка после установки");
30
+
31
+ for (let index = 0; index < steps.length; index += 1) {
32
+ const step = steps[index];
33
+ await runStep(step, index + 1, steps.length);
34
+ }
35
+
36
+ console.log("IOLA CLI готова. Запуск: iola");
37
+
38
+ async function runStep(step, current, total) {
39
+ const started = Date.now();
40
+ let frame = 0;
41
+ let lastOutput = "";
42
+ const prefix = `[${current}/${total}] ${step.title}`;
43
+ const render = () => {
44
+ if (!canAnimate) return;
45
+ const seconds = Math.max(1, Math.round((Date.now() - started) / 1000));
46
+ process.stdout.write(`\r${frames[frame]} ${prefix}... ${seconds}s`);
47
+ frame = (frame + 1) % frames.length;
48
+ };
49
+
50
+ if (!canAnimate) {
51
+ console.log(`... ${prefix}`);
52
+ }
53
+ render();
54
+ const timer = setInterval(render, 120);
55
+ const result = await run(node, ["--no-warnings", ...step.args], (chunk) => {
56
+ lastOutput = chunk.trim() || lastOutput;
57
+ });
58
+ clearInterval(timer);
59
+
60
+ if (result.code !== 0) {
61
+ if (canAnimate) process.stdout.write(`\r`);
62
+ if (lastOutput) console.error(lastOutput);
63
+ console.error(`× ${prefix}: ошибка установки`);
64
+ process.exit(result.code || 1);
65
+ }
66
+
67
+ if (canAnimate) {
68
+ process.stdout.write(`\r✓ ${prefix} готово за ${formatDuration(Date.now() - started)}\n`);
69
+ } else {
70
+ console.log(`✓ ${prefix} готово за ${formatDuration(Date.now() - started)}`);
71
+ }
72
+ }
73
+
74
+ function run(command, args, onOutput) {
75
+ return new Promise((resolvePromise) => {
76
+ const child = spawn(command, args, {
77
+ cwd: rootDir,
78
+ windowsHide: true,
79
+ stdio: ["ignore", "pipe", "pipe"],
80
+ });
81
+
82
+ child.stdout.on("data", (chunk) => onOutput(String(chunk)));
83
+ child.stderr.on("data", (chunk) => onOutput(String(chunk)));
84
+ child.on("close", (code) => resolvePromise({ code }));
85
+ child.on("error", (error) => {
86
+ onOutput(error.message);
87
+ resolvePromise({ code: 1 });
88
+ });
89
+ });
90
+ }
91
+
92
+ function formatDuration(ms) {
93
+ const seconds = Math.max(1, Math.round(ms / 1000));
94
+ if (seconds < 60) return `${seconds}s`;
95
+ const minutes = Math.floor(seconds / 60);
96
+ const rest = seconds % 60;
97
+ return `${minutes}m ${rest}s`;
98
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iola_adm/iola-cli",
3
- "version": "0.1.91",
3
+ "version": "0.1.93",
4
4
  "description": "CLI и AI-агент городского округа Йошкар-Ола.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/adm-iola/iola-cli#readme",
@@ -16,9 +16,9 @@
16
16
  "iola": "bin/iola.js"
17
17
  },
18
18
  "scripts": {
19
- "postinstall": "node --no-warnings bin/iola.js db init --silent && node --no-warnings bin/iola.js browser install && node --no-warnings bin/iola.js ai setup iola --yes --quiet --optional",
19
+ "postinstall": "node --no-warnings bin/postinstall.js",
20
20
  "start": "node --no-warnings bin/iola.js",
21
- "test": "node --no-warnings --check bin/iola.js && node --no-warnings --check src/cli.js && node --no-warnings test/smoke-test.js"
21
+ "test": "node --no-warnings --check bin/iola.js && node --no-warnings --check bin/postinstall.js && node --no-warnings --check src/cli.js && node --no-warnings test/smoke-test.js"
22
22
  },
23
23
  "files": [
24
24
  "bin",
package/src/cli.js CHANGED
@@ -2138,6 +2138,7 @@ async function handleUninstall(args = []) {
2138
2138
  description: "локальная папка .iola текущего проекта",
2139
2139
  });
2140
2140
  }
2141
+ const npmPackage = "@iola_adm/iola-cli";
2141
2142
 
2142
2143
  const safeTargets = targets.map((target) => ({
2143
2144
  ...target,
@@ -2160,7 +2161,8 @@ async function handleUninstall(args = []) {
2160
2161
  exists: existsSync(target.path),
2161
2162
  description: target.description,
2162
2163
  })),
2163
- willKeep: ["Codex CLI", "Codex auth/config", "npm package files"],
2164
+ willRemovePackage: npmPackage,
2165
+ willKeep: ["Codex CLI", "Codex auth/config"],
2164
2166
  reinstall: "npm install -g @iola_adm/iola-cli@latest",
2165
2167
  };
2166
2168
  if (options.json) printJson(payload);
@@ -2175,8 +2177,9 @@ async function handleUninstall(args = []) {
2175
2177
  console.log(` ${target.description}`);
2176
2178
  }
2177
2179
  console.log("");
2180
+ console.log(`Будет удален npm-пакет: ${npmPackage}`);
2178
2181
  console.log("Codex CLI и его настройки не удаляются.");
2179
- const confirmed = await confirm("Удалить локальные данные iola-cli? [y/N] ");
2182
+ const confirmed = await confirm("Полностью удалить iola-cli? [y/N] ");
2180
2183
  if (!confirmed) {
2181
2184
  console.log("Удаление отменено.");
2182
2185
  return { deleted: false };
@@ -2188,9 +2191,11 @@ async function handleUninstall(args = []) {
2188
2191
  }
2189
2192
 
2190
2193
  console.log("Локальные данные iola-cli удалены.");
2194
+ console.log(`Удаляю npm-пакет ${npmPackage}...`);
2195
+ await runCommand(getNpmCommand(), ["remove", "-g", npmPackage], { inherit: true });
2196
+ console.log("npm-пакет iola-cli удален.");
2191
2197
  console.log("Codex CLI не тронут.");
2192
- console.log("Для полной переустановки npm-пакета:");
2193
- console.log(" npm remove -g @iola_adm/iola-cli");
2198
+ console.log("Для повторной установки:");
2194
2199
  console.log(" npm install -g @iola_adm/iola-cli@latest");
2195
2200
  return { deleted: true };
2196
2201
  }
@@ -9986,6 +9991,10 @@ function runCommand(command, args, options = {}) {
9986
9991
  });
9987
9992
  }
9988
9993
 
9994
+ function getNpmCommand() {
9995
+ return process.platform === "win32" ? "npm.cmd" : "npm";
9996
+ }
9997
+
9989
9998
  function debugLog(message) {
9990
9999
  if (!process.env.IOLA_DEBUG_FILE) return;
9991
10000
  appendFile(process.env.IOLA_DEBUG_FILE, `[${new Date().toISOString()}] ${message}\n`, "utf8").catch(() => {});
@@ -64,8 +64,11 @@ assertIncludes(skills, "reports", "skills list");
64
64
  assertNotIncludes(skills, "gosuslugi", "skills list");
65
65
 
66
66
  const deletePlan = JSON.parse(await runCli(["delete", "--dry-run", "--json"]));
67
- if (!Array.isArray(deletePlan.willDelete) || !deletePlan.willKeep.includes("Codex CLI")) {
68
- throw new Error("delete dry-run should list delete targets and keep Codex CLI");
67
+ if (!Array.isArray(deletePlan.willDelete) || deletePlan.willRemovePackage !== "@iola_adm/iola-cli" || !deletePlan.willKeep.includes("Codex CLI")) {
68
+ throw new Error("delete dry-run should list delete targets, npm package, and keep Codex CLI");
69
+ }
70
+ if (deletePlan.willKeep.includes("npm package files")) {
71
+ throw new Error("delete dry-run should not keep npm package files");
69
72
  }
70
73
 
71
74
  console.log("smoke tests passed");