@tankpkg/cli 0.16.4 → 0.16.5

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/bin/tank.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as VERSION, i as USER_AGENT, l as setConfig, n as flushLogs, o as getConfig, s as getConfigDir, t as authFlowLog } from "../debug-logger-Dna3btSz.js";
2
+ import { a as VERSION, i as USER_AGENT, l as setConfig, n as flushLogs, o as getConfig, s as getConfigDir, t as authFlowLog } from "../debug-logger-BpF5Gl-T.js";
3
3
  import { t as logger } from "../logger-BhULz3Uz.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { Command } from "commander";
@@ -21,6 +21,7 @@ import { pipeline } from "node:stream/promises";
21
21
  import open from "open";
22
22
  import ignore from "ignore";
23
23
  import { fileURLToPath } from "node:url";
24
+ import { inspect } from "node:util";
24
25
  //#region \0rolldown/runtime.js
25
26
  var __defProp$1 = Object.defineProperty;
26
27
  var __exportAll = (all, no_symbols) => {
@@ -9067,18 +9068,31 @@ function writeLockfileWithResolvedGraph(lock, nodes, downloaded, onProgress) {
9067
9068
  lock.skills = sortedSkills;
9068
9069
  return lock;
9069
9070
  }
9070
- function mkdirSafeNoSymlinks(targetDir) {
9071
- const resolved = path.resolve(targetDir);
9072
- const segments = resolved.split(path.sep).filter(Boolean);
9073
- let current = resolved.startsWith("/") ? "/" : "";
9074
- for (const seg of segments) {
9075
- current = path.join(current, seg);
9076
- if (fs.existsSync(current)) {
9077
- const stat = fs.lstatSync(current);
9078
- if (stat.isSymbolicLink()) throw new TankIntegrityError(`Symlink in install path: ${current}`);
9079
- if (!stat.isDirectory()) throw new TankIntegrityError(`Non-directory in install path: ${current}`);
9080
- } else fs.mkdirSync(current);
9071
+ /**
9072
+ * Plan the ordered list of ancestor directories to create for `targetDir`,
9073
+ * from just below the filesystem root down to the leaf (the root itself is
9074
+ * never returned — it always exists and must not be `mkdir`'d).
9075
+ *
9076
+ * The path module is injectable so Windows drive/UNC root handling can be
9077
+ * verified on any host via `path.win32` without a real Windows machine.
9078
+ */
9079
+ function planMkdirSegments(targetDir, pathMod = path) {
9080
+ const resolved = pathMod.resolve(targetDir);
9081
+ const { root } = pathMod.parse(resolved);
9082
+ const dirs = [];
9083
+ let current = root;
9084
+ for (const seg of resolved.slice(root.length).split(pathMod.sep).filter(Boolean)) {
9085
+ current = pathMod.join(current, seg);
9086
+ dirs.push(current);
9081
9087
  }
9088
+ return dirs;
9089
+ }
9090
+ function mkdirSafeNoSymlinks(targetDir) {
9091
+ for (const current of planMkdirSegments(targetDir)) if (fs.existsSync(current)) {
9092
+ const stat = fs.lstatSync(current);
9093
+ if (stat.isSymbolicLink()) throw new TankIntegrityError(`Symlink in install path: ${current}`);
9094
+ if (!stat.isDirectory()) throw new TankIntegrityError(`Non-directory in install path: ${current}`);
9095
+ } else fs.mkdirSync(current);
9082
9096
  }
9083
9097
  function isDirNonEmpty(dir) {
9084
9098
  try {
@@ -12084,6 +12098,37 @@ function printUserInfo(user) {
12084
12098
  logger.info(`Email: ${user.email ?? "unknown"}`);
12085
12099
  }
12086
12100
  //#endregion
12101
+ //#region src/lib/describe-error.ts
12102
+ /** Format a real Error, surfacing Node errno fields (code/syscall/path) when present. */
12103
+ function describeErrorObject(err) {
12104
+ const e = err;
12105
+ const base = err.message?.trim() || err.name || "Error";
12106
+ const tags = [
12107
+ e.code != null ? `code=${String(e.code)}` : null,
12108
+ e.syscall != null ? `syscall=${String(e.syscall)}` : null,
12109
+ e.path != null ? `path=${String(e.path)}` : null
12110
+ ].filter((tag) => tag !== null);
12111
+ return tags.length > 0 ? `${base} (${tags.join(", ")})` : base;
12112
+ }
12113
+ /**
12114
+ * Render an unknown thrown value as a non-empty, actionable string.
12115
+ *
12116
+ * Guarantees a useful message for every input: errno errors surface their
12117
+ * `code`/`syscall`/`path`, non-Error objects are inspected, and the result
12118
+ * never collapses to an empty string or a bare placeholder like `<none>`
12119
+ * (the symptom Windows users hit during `tank install`).
12120
+ */
12121
+ function describeError(err) {
12122
+ if (err instanceof Error) return describeErrorObject(err);
12123
+ if (err === null || err === void 0) return `${String(err)} (non-error thrown)`;
12124
+ if (typeof err === "object") try {
12125
+ return `${err.constructor?.name ?? "object"}: ${inspect(err, { depth: 2 })}`;
12126
+ } catch {
12127
+ return Object.prototype.toString.call(err);
12128
+ }
12129
+ return `${typeof err} ${String(err)}`;
12130
+ }
12131
+ //#endregion
12087
12132
  //#region src/lib/install-suggestions.ts
12088
12133
  /**
12089
12134
  * Best-effort fuzzy lookup of similar skill names. Hits the public /api/v1/search
@@ -12304,7 +12349,7 @@ program.command("install").alias("i").description("Install one or more skills fr
12304
12349
  ...proxyOpt
12305
12350
  });
12306
12351
  } catch (err) {
12307
- const msg = err instanceof Error ? err.message : String(err);
12352
+ const msg = describeError(err);
12308
12353
  console.error(`Install failed: ${msg}`);
12309
12354
  process.exit(1);
12310
12355
  }
@@ -12327,7 +12372,7 @@ program.command("install").alias("i").description("Install one or more skills fr
12327
12372
  ...proxyOpt
12328
12373
  });
12329
12374
  } catch (err) {
12330
- const msg = err instanceof Error ? err.message : String(err);
12375
+ const msg = describeError(err);
12331
12376
  failures.push({
12332
12377
  target,
12333
12378
  error: msg,