@elnora-ai/cli 1.3.0 → 1.3.1

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.
Files changed (2) hide show
  1. package/dist/cli.js +139 -85
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -2020,10 +2020,9 @@ var CACHE_FILE = join2(CACHE_DIR, ".update-check");
2020
2020
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
2021
2021
  var FETCH_TIMEOUT_MS = 3e3;
2022
2022
  var SEMVER_RE = /^\d+\.\d+\.\d+(?:-[\w.]+)?(?:\+[\w.]+)?$/;
2023
- function shouldSkip() {
2023
+ function shouldSkipEntirely() {
2024
2024
  if (process.env.CI || process.env.GITHUB_ACTIONS) return true;
2025
2025
  if (process.env.ELNORA_NO_UPDATE_CHECK) return true;
2026
- if (!process.stderr.isTTY) return true;
2027
2026
  return false;
2028
2027
  }
2029
2028
  function readCache() {
@@ -2043,13 +2042,14 @@ function writeCache(entry) {
2043
2042
  }
2044
2043
  }
2045
2044
  function showUpdateNotice(latest) {
2045
+ if (!process.stderr.isTTY) return;
2046
2046
  const color2 = isColorEnabled();
2047
2047
  const msg = color2 ? `
2048
2048
  ${pc.yellow(`Update available: v${VERSION} \u2192 v${latest}`)}
2049
- Run: curl -fsSL https://cli.elnora.ai/install.sh | bash
2049
+ Run: elnora update
2050
2050
  ` : `
2051
2051
  Update available: v${VERSION} \u2192 v${latest}
2052
- Run: curl -fsSL https://cli.elnora.ai/install.sh | bash
2052
+ Run: elnora update
2053
2053
  `;
2054
2054
  process.stderr.write(msg);
2055
2055
  }
@@ -2065,7 +2065,7 @@ function isNewerVersion(a, b) {
2065
2065
  return false;
2066
2066
  }
2067
2067
  function registerUpdateCheck() {
2068
- if (shouldSkip()) return;
2068
+ if (shouldSkipEntirely()) return;
2069
2069
  const cached = readCache();
2070
2070
  if (cached) {
2071
2071
  const elapsed = Date.now() - new Date(cached.checkedAt).getTime();
@@ -2078,7 +2078,9 @@ function registerUpdateCheck() {
2078
2078
  return;
2079
2079
  }
2080
2080
  }
2081
- setTimeout(async () => {
2081
+ const keepAlive = setInterval(() => {
2082
+ }, 6e4);
2083
+ (async () => {
2082
2084
  try {
2083
2085
  const response = await fetch(NPM_REGISTRY_URL, {
2084
2086
  signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
@@ -2092,8 +2094,10 @@ function registerUpdateCheck() {
2092
2094
  showUpdateNotice(latest);
2093
2095
  }
2094
2096
  } catch {
2097
+ } finally {
2098
+ clearInterval(keepAlive);
2095
2099
  }
2096
- }, 0);
2100
+ })();
2097
2101
  }
2098
2102
 
2099
2103
  // src/commands/doctor.ts
@@ -4873,6 +4877,30 @@ import { join as join6 } from "node:path";
4873
4877
  import { Readable } from "node:stream";
4874
4878
  import { pipeline } from "node:stream/promises";
4875
4879
  import pc5 from "picocolors";
4880
+
4881
+ // src/lib/install-method.ts
4882
+ function detectInstallMethod() {
4883
+ const execPath = process.argv[1] ?? "";
4884
+ if (execPath.includes("node_modules")) {
4885
+ return "npm";
4886
+ }
4887
+ if (execPath.includes("/Cellar/") || execPath.includes("/homebrew/")) {
4888
+ return "homebrew";
4889
+ }
4890
+ return "binary";
4891
+ }
4892
+ function getUpdateInstruction(method) {
4893
+ switch (method) {
4894
+ case "npm":
4895
+ return "npm update -g @elnora-ai/cli";
4896
+ case "homebrew":
4897
+ return "brew upgrade elnora";
4898
+ case "binary":
4899
+ return "elnora update --install";
4900
+ }
4901
+ }
4902
+
4903
+ // src/commands/update.ts
4876
4904
  var NPM_REGISTRY_URL2 = "https://registry.npmjs.org/@elnora-ai/cli/latest";
4877
4905
  var GITHUB_REPO = "Elnora-AI/elnora-cli";
4878
4906
  function getPlatformTarget() {
@@ -4888,8 +4916,11 @@ function getPlatformTarget() {
4888
4916
  return null;
4889
4917
  }
4890
4918
  }
4891
- function getManualHint() {
4892
- return process.platform === "win32" ? " irm https://cli.elnora.ai/install.ps1 | iex" : " curl -fsSL https://cli.elnora.ai/install.sh | bash";
4919
+ async function fetchLatestVersion() {
4920
+ const res = await fetch(NPM_REGISTRY_URL2, { signal: AbortSignal.timeout(5e3) });
4921
+ if (!res.ok) throw new Error(`Registry returned HTTP ${res.status}`);
4922
+ const data = await res.json();
4923
+ return data.version ?? "unknown";
4893
4924
  }
4894
4925
  async function downloadToFile(url, dest) {
4895
4926
  const res = await fetch(url, { signal: AbortSignal.timeout(12e4), redirect: "follow" });
@@ -4897,98 +4928,121 @@ async function downloadToFile(url, dest) {
4897
4928
  const nodeStream = Readable.fromWeb(res.body);
4898
4929
  await pipeline(nodeStream, createWriteStream(dest));
4899
4930
  }
4931
+ async function installBinaryUpdate(latest) {
4932
+ const color2 = isColorEnabled();
4933
+ const platformInfo = getPlatformTarget();
4934
+ if (!platformInfo) {
4935
+ console.error(`Unsupported platform: ${process.platform}.`);
4936
+ console.error("Try: npm update -g @elnora-ai/cli");
4937
+ process.exitCode = 1;
4938
+ return;
4939
+ }
4940
+ const { target, ext } = platformInfo;
4941
+ const binaryUrl = `https://github.com/${GITHUB_REPO}/releases/download/v${latest}/${target}.${ext}`;
4942
+ const checksumUrl = `https://github.com/${GITHUB_REPO}/releases/download/v${latest}/${target}.sha256`;
4943
+ const tmp = join6(tmpdir(), `elnora-update-${Date.now()}`);
4944
+ mkdirSync4(tmp, { recursive: true });
4945
+ const archivePath = join6(tmp, `${target}.${ext}`);
4946
+ try {
4947
+ console.error("Downloading...");
4948
+ await downloadToFile(binaryUrl, archivePath);
4949
+ let checksumVerified = false;
4950
+ try {
4951
+ const checksumRes = await fetch(checksumUrl, { signal: AbortSignal.timeout(15e3) });
4952
+ if (checksumRes.ok) {
4953
+ const checksumText = await checksumRes.text();
4954
+ const expected = checksumText.split(/\s/)[0].trim();
4955
+ if (expected.length === 64) {
4956
+ const actual = createHash("sha256").update(readFileSync6(archivePath)).digest("hex");
4957
+ if (actual.toLowerCase() !== expected.toLowerCase()) {
4958
+ console.error("Checksum verification failed. The download may be corrupted.");
4959
+ process.exitCode = 1;
4960
+ return;
4961
+ }
4962
+ checksumVerified = true;
4963
+ }
4964
+ }
4965
+ } catch {
4966
+ }
4967
+ if (!checksumVerified) {
4968
+ console.error("Warning: Could not verify download checksum. Proceeding anyway.");
4969
+ }
4970
+ if (process.platform === "win32") {
4971
+ const extractDir = join6(tmp, "extracted");
4972
+ execFileSync("powershell", [
4973
+ "-NoProfile",
4974
+ "-Command",
4975
+ `Expand-Archive -Path '${archivePath}' -DestinationPath '${extractDir}' -Force`
4976
+ ]);
4977
+ const installDir = join6(process.env.USERPROFILE ?? process.env.HOME ?? "", ".elnora", "bin");
4978
+ mkdirSync4(installDir, { recursive: true });
4979
+ copyFileSync(join6(extractDir, target), join6(installDir, "elnora.exe"));
4980
+ } else {
4981
+ execFileSync("tar", ["-xzf", archivePath, "-C", tmp]);
4982
+ const installDir = process.env.ELNORA_INSTALL_DIR ?? join6(process.env.HOME ?? "", ".local", "bin");
4983
+ mkdirSync4(installDir, { recursive: true });
4984
+ const dest = join6(installDir, "elnora");
4985
+ copyFileSync(join6(tmp, target), dest);
4986
+ chmodSync2(dest, 493);
4987
+ }
4988
+ const done = color2 ? `${pc5.green("\u2713")} Updated to v${latest}` : `\u2713 Updated to v${latest}`;
4989
+ console.error(done);
4990
+ } finally {
4991
+ try {
4992
+ rmSync(tmp, { recursive: true, force: true });
4993
+ } catch {
4994
+ }
4995
+ }
4996
+ }
4900
4997
  function addUpdateCommand(program2) {
4901
- program2.command("update").description("Update Elnora CLI to the latest version").action(async () => {
4998
+ program2.command("update").description("Check for updates (use --install to apply)").option("--install", "Download and install the update").action(async (opts) => {
4902
4999
  const color2 = isColorEnabled();
4903
- const hint = getManualHint();
5000
+ const method = detectInstallMethod();
4904
5001
  let latest;
4905
5002
  try {
4906
- const res = await fetch(NPM_REGISTRY_URL2, { signal: AbortSignal.timeout(5e3) });
4907
- if (!res.ok) {
4908
- console.error("Failed to check for updates. Try manually:");
4909
- console.error(hint);
4910
- process.exit(1);
4911
- }
4912
- const data = await res.json();
4913
- latest = data.version ?? "unknown";
5003
+ latest = await fetchLatestVersion();
4914
5004
  } catch {
4915
- console.error("Failed to reach registry. Try manually:");
4916
- console.error(hint);
4917
- process.exit(1);
5005
+ console.error("Failed to check for updates.");
5006
+ process.exitCode = 1;
5007
+ return;
5008
+ }
5009
+ if (latest === "unknown") {
5010
+ console.error("Could not determine latest version.");
5011
+ process.exitCode = 1;
5012
+ return;
4918
5013
  }
4919
5014
  if (latest === VERSION || !isNewerVersion(latest, VERSION)) {
4920
5015
  const msg2 = color2 ? `${pc5.green("\u2713")} Already on the latest version (v${VERSION})` : `\u2713 Already on the latest version (v${VERSION})`;
4921
5016
  console.error(msg2);
4922
5017
  return;
4923
5018
  }
5019
+ const instruction = getUpdateInstruction(method);
5020
+ if (!opts.install) {
5021
+ const msg2 = color2 ? `${pc5.yellow("Update available:")} v${VERSION} \u2192 v${latest}` : `Update available: v${VERSION} \u2192 v${latest}`;
5022
+ console.error(msg2);
5023
+ console.error(`Run: ${instruction}`);
5024
+ return;
5025
+ }
4924
5026
  const msg = color2 ? `Updating Elnora CLI ${pc5.dim(`v${VERSION}`)} \u2192 ${pc5.green(`v${latest}`)}...` : `Updating Elnora CLI v${VERSION} \u2192 v${latest}...`;
4925
5027
  console.error(msg);
4926
- const platformInfo = getPlatformTarget();
4927
- if (!platformInfo) {
4928
- console.error(`
4929
- Unsupported platform: ${process.platform}. Try manually:`);
4930
- console.error(" npm update -g @elnora-ai/cli");
4931
- process.exit(1);
5028
+ if (method === "npm") {
5029
+ console.error("Installed via npm. Run:");
5030
+ console.error(` npm update -g @elnora-ai/cli`);
5031
+ return;
5032
+ }
5033
+ if (method === "homebrew") {
5034
+ console.error("Installed via Homebrew. Run:");
5035
+ console.error(` brew upgrade elnora`);
5036
+ return;
4932
5037
  }
4933
- const { target, ext } = platformInfo;
4934
- const binaryUrl = `https://github.com/${GITHUB_REPO}/releases/download/v${latest}/${target}.${ext}`;
4935
- const checksumUrl = `https://github.com/${GITHUB_REPO}/releases/download/v${latest}/${target}.sha256`;
4936
- const tmp = join6(tmpdir(), `elnora-update-${Date.now()}`);
4937
- mkdirSync4(tmp, { recursive: true });
4938
- const archivePath = join6(tmp, `${target}.${ext}`);
4939
5038
  try {
4940
- await downloadToFile(binaryUrl, archivePath);
4941
- let checksumVerified = false;
4942
- try {
4943
- const checksumRes = await fetch(checksumUrl, { signal: AbortSignal.timeout(15e3) });
4944
- if (checksumRes.ok) {
4945
- const checksumText = await checksumRes.text();
4946
- const expected = checksumText.split(/\s/)[0].trim();
4947
- if (expected.length === 64) {
4948
- const actual = createHash("sha256").update(readFileSync6(archivePath)).digest("hex");
4949
- if (actual.toLowerCase() !== expected.toLowerCase()) {
4950
- console.error("\nChecksum verification failed. The download may be corrupted.");
4951
- console.error("Try again, or install manually:");
4952
- console.error(hint);
4953
- process.exit(1);
4954
- }
4955
- checksumVerified = true;
4956
- }
4957
- }
4958
- } catch {
4959
- }
4960
- if (!checksumVerified) {
4961
- console.error("Warning: Could not verify download checksum. Proceeding anyway.");
4962
- }
4963
- if (process.platform === "win32") {
4964
- const extractDir = join6(tmp, "extracted");
4965
- execFileSync("powershell", [
4966
- "-NoProfile",
4967
- "-Command",
4968
- `Expand-Archive -Path '${archivePath}' -DestinationPath '${extractDir}' -Force`
4969
- ]);
4970
- const installDir = join6(process.env.USERPROFILE ?? process.env.HOME ?? "", ".elnora", "bin");
4971
- mkdirSync4(installDir, { recursive: true });
4972
- copyFileSync(join6(extractDir, target), join6(installDir, "elnora.exe"));
4973
- } else {
4974
- execFileSync("tar", ["-xzf", archivePath, "-C", tmp]);
4975
- const installDir = process.env.ELNORA_INSTALL_DIR ?? join6(process.env.HOME ?? "", ".local", "bin");
4976
- mkdirSync4(installDir, { recursive: true });
4977
- const dest = join6(installDir, "elnora");
4978
- copyFileSync(join6(tmp, target), dest);
4979
- chmodSync2(dest, 493);
4980
- }
4981
- const done = color2 ? `${pc5.green("\u2713")} Updated to v${latest}` : `\u2713 Updated to v${latest}`;
4982
- console.error(done);
5039
+ await installBinaryUpdate(latest);
4983
5040
  } catch {
4984
- console.error("\nUpdate failed. Try manually:");
4985
- console.error(hint);
4986
- process.exit(1);
4987
- } finally {
4988
- try {
4989
- rmSync(tmp, { recursive: true, force: true });
4990
- } catch {
4991
- }
5041
+ console.error("Update failed. Try manually:");
5042
+ console.error(
5043
+ process.platform === "win32" ? " irm https://cli.elnora.ai/install.ps1 | iex" : " curl -fsSL https://cli.elnora.ai/install.sh | bash"
5044
+ );
5045
+ process.exitCode = 1;
4992
5046
  }
4993
5047
  });
4994
5048
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elnora-ai/cli",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Elnora AI Platform CLI",
5
5
  "type": "module",
6
6
  "bin": {