passalong 1.4.0 → 1.6.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/src/update.js CHANGED
@@ -20,8 +20,15 @@
20
20
  // command started it, and config.json is read, patched and written whole: a refresh that read it
21
21
  // just before `logout` or `use` wrote it, and wrote it back after, put the old accounts and the old
22
22
  // default back. This file has one writer, so there is nothing to lose.
23
- import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
24
- import { join } from "node:path";
23
+ import {
24
+ existsSync,
25
+ mkdirSync,
26
+ readFileSync,
27
+ realpathSync,
28
+ renameSync,
29
+ writeFileSync,
30
+ } from "node:fs";
31
+ import { delimiter, dirname, join } from "node:path";
25
32
  import { HOME } from "./store.js";
26
33
 
27
34
  const FILE = join(HOME, "update.json");
@@ -138,3 +145,41 @@ export async function refresh({ now = Date.now(), fetchImpl = fetch, save = writ
138
145
  }
139
146
  return latest;
140
147
  }
148
+
149
+ /**
150
+ * Other copies of passalong on PATH, besides the one at `cli`: their path and version, and whether
151
+ * one of them comes first, so `passalong` typed in a shell runs it rather than this. npm and pnpm
152
+ * each keep their own global copy, and updating one left the old one running from the other
153
+ * (2026-11-06). Each version is read from the package.json beside the bin's real file.
154
+ */
155
+ export function otherCopies(cli, { path = process.env.PATH || "" } = {}) {
156
+ const real = (p) => {
157
+ try {
158
+ return realpathSync(p);
159
+ } catch {
160
+ return "";
161
+ }
162
+ };
163
+ const versionAt = (file) => {
164
+ try {
165
+ return (
166
+ JSON.parse(readFileSync(join(dirname(file), "..", "package.json"), "utf8")).version || ""
167
+ );
168
+ } catch {
169
+ return "";
170
+ }
171
+ };
172
+ const mine = real(cli);
173
+ const seen = new Set();
174
+ const found = [];
175
+ for (const dir of path.split(delimiter).filter(Boolean)) {
176
+ const bin = join(dir, process.platform === "win32" ? "passalong.cmd" : "passalong");
177
+ if (!existsSync(bin)) continue;
178
+ const file = real(bin);
179
+ if (!file || seen.has(file)) continue;
180
+ seen.add(file);
181
+ found.push({ path: bin, version: versionAt(file), mine: file === mine });
182
+ }
183
+ const others = found.filter((f) => !f.mine);
184
+ return { others, shadowed: found.length > 0 && !found[0].mine };
185
+ }