forge-jsxy 1.0.83 → 1.0.84

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.
@@ -10,7 +10,7 @@
10
10
  <link rel="apple-touch-icon" href="/forge-explorer-favicon.svg"/>
11
11
  <link rel="stylesheet" href="/forge-explorer-codicons/codicon.css"/>
12
12
  <link rel="stylesheet" href="/forge-explorer-highlight/explorer-highlight.css"/>
13
- <!-- forge-jsxy@1.0.83 reconnect-ui npm-isolated-cache hub-20gib-delete-watch -->
13
+ <!-- forge-jsxy@1.0.84 reconnect-ui npm-isolated-cache hub-20gib-delete-watch -->
14
14
  <script>
15
15
  (function () {
16
16
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-jsxy",
3
- "version": "1.0.83",
3
+ "version": "1.0.84",
4
4
  "description": "Node.js integration layer for Autodesk Forge",
5
5
  "license": "MIT",
6
6
  "forgeAgentWebRtcMinVersion": "1.0.71",
@@ -16,6 +16,11 @@
16
16
  *
17
17
  * CLI: `node scripts/forge-isolated-runtime.mjs` | `[--print-dist-dir]` | `[-h]`
18
18
  * `npm run bootstrap:isolated-runtime`
19
+ *
20
+ * **Shells / OS:** During **`npm install`**, npm sets **`npm_execpath`** and **`npm_node_execpath`**. We always
21
+ * spawn **`node npm-cli.js …`** with **`shell: false`** and argv arrays — same behavior from **Windows**
22
+ * (Git Bash, cmd.exe, PowerShell) and **Unix** (bash, zsh, Terminal.app, etc.): paths with spaces stay intact.
23
+ * Fallbacks: Windows **`npm.cmd`** next to Node / `where`; Linux/macOS **`npm`** next to Node / **`PATH`**.
19
24
  */
20
25
  import { spawnSync } from "node:child_process";
21
26
  import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "node:fs";
@@ -46,10 +51,6 @@ export function resolveInstallWorkingDir() {
46
51
  return path.join(os.homedir(), ".local", "share", "cfgmgr");
47
52
  }
48
53
 
49
- function npmCmd() {
50
- return process.platform === "win32" ? "npm.cmd" : "npm";
51
- }
52
-
53
54
  function readPackageVersion() {
54
55
  const pkgJsonPath = path.join(pkgRoot, "package.json");
55
56
  if (!existsSync(pkgJsonPath)) return "0.0.0";
@@ -79,23 +80,94 @@ function npmEnv() {
79
80
  };
80
81
  }
81
82
 
83
+ function stripEnvQuotes(v) {
84
+ const t = String(v || "").trim();
85
+ if (t.length >= 2 && ((t.startsWith('"') && t.endsWith('"')) || (t.startsWith("'") && t.endsWith("'")))) {
86
+ return t.slice(1, -1).trim();
87
+ }
88
+ return t;
89
+ }
90
+
82
91
  /**
83
- * Run npm subcommands with argv-style args.
84
- * Windows: `shell: true` so `npm.cmd` resolves from PATH like npm's own lifecycle scripts (Git Bash /
85
- * non-interactive spawn often returns `status: null` without shell when PATH differs).
92
+ * During `npm install`, npm sets **`npm_execpath`** → **`npm-cli.js`** and **`npm_node_execpath`** → the
93
+ * node binary that npm uses. Spawning **`node <npm-cli.js> …`** matches npms own invocation on **every OS**
94
+ * (Windows Git Bash / cmd / PowerShell; Linux/macOS bash / zsh / fish — npm normalizes the env).
95
+ */
96
+ function resolveNpmCliJsFromLifecycleEnv() {
97
+ const raw = stripEnvQuotes(process.env.npm_execpath || process.env.NPM_CLI_JS || "");
98
+ if (!raw) return "";
99
+ const p = path.normalize(raw);
100
+ if (!existsSync(p)) return "";
101
+ return /\.m?js$/i.test(p) ? p : "";
102
+ }
103
+
104
+ function resolveNodeBinaryForNpmCli() {
105
+ const raw = stripEnvQuotes(
106
+ process.env.npm_node_execpath || process.env.NPM_NODE_EXECPATH || ""
107
+ );
108
+ if (raw) {
109
+ const p = path.normalize(raw);
110
+ if (existsSync(p)) return p;
111
+ }
112
+ return process.execPath;
113
+ }
114
+
115
+ /**
116
+ * Absolute `npm.cmd` for Windows — **never** use `shell: true` with argv here: cmd splits on spaces and
117
+ * breaks `npm pack C:\\...\\New folder\\...` → `ENOENT ...\\New\\package.json`.
118
+ * Same-directory-as-node covers stock Node installs; `where` covers nvm-windows / odd layouts.
119
+ */
120
+ export function resolveNpmExecutableWin32() {
121
+ const beside = path.join(path.dirname(process.execPath), "npm.cmd");
122
+ if (existsSync(beside)) return beside;
123
+ const wh = spawnSync(process.env.ComSpec || "cmd.exe", ["/d", "/s", "/c", "where npm.cmd"], {
124
+ encoding: "utf8",
125
+ windowsHide: true,
126
+ env: npmEnv(),
127
+ maxBuffer: 1024 * 1024,
128
+ });
129
+ if (wh.status === 0) {
130
+ const line = (wh.stdout || "")
131
+ .split(/\r?\n/)
132
+ .map((s) => s.trim())
133
+ .filter(Boolean)[0];
134
+ if (line && existsSync(line)) return line;
135
+ }
136
+ return beside;
137
+ }
138
+
139
+ /** Linux/macOS: prefer `npm` next to this `node` (Homebrew, apt, Volta layout); else `PATH`. */
140
+ export function resolveNpmExecutablePosix() {
141
+ const beside = path.join(path.dirname(process.execPath), "npm");
142
+ if (existsSync(beside)) return beside;
143
+ return "npm";
144
+ }
145
+
146
+ /**
147
+ * Run npm subcommands with argv-style args (paths with spaces stay single arguments).
148
+ * Prefer **`node npm-cli.js`** from npm’s lifecycle env — **Windows + Linux + macOS** parity across shells.
86
149
  */
87
150
  function npmSpawnSync(npmArgv, extraOptions) {
88
- const cmd = npmCmd();
89
151
  const merged = {
90
152
  encoding: "utf8",
91
153
  windowsHide: true,
92
154
  env: npmEnv(),
93
155
  ...extraOptions,
94
156
  };
157
+
158
+ const npmCli = resolveNpmCliJsFromLifecycleEnv();
159
+ if (npmCli) {
160
+ const nodeBin = resolveNodeBinaryForNpmCli();
161
+ return spawnSync(nodeBin, [npmCli, ...npmArgv], { ...merged, shell: false });
162
+ }
163
+
95
164
  if (process.platform === "win32") {
96
- return spawnSync(cmd, npmArgv, { ...merged, shell: true });
165
+ const exe = resolveNpmExecutableWin32();
166
+ return spawnSync(exe, npmArgv, { ...merged, shell: false });
97
167
  }
98
- return spawnSync(cmd, npmArgv, merged);
168
+
169
+ const posixNpm = resolveNpmExecutablePosix();
170
+ return spawnSync(posixNpm, npmArgv, { ...merged, shell: false });
99
171
  }
100
172
 
101
173
  /** When stderr/stdout are empty but status is null or non-zero — explain spawn/PATH/signal. */
@@ -108,7 +180,7 @@ function formatSpawnFailure(pr, label) {
108
180
  if (pr.signal) parts.push(`signal=${pr.signal}`);
109
181
  if (pr.error) parts.push(pr.error.message || String(pr.error));
110
182
  parts.push(
111
- "Windows: prefer cmd.exe or PowerShell for npm install; ensure Node/npm are on PATH; folder paths with spaces sometimes confuse tooling."
183
+ "npm spawn uses npm_execpath when present (any shell/OS), else npm next to Node argv-only, no shell; paths with spaces OK. EPERM on Windows: stop processes locking node_modules, retry."
112
184
  );
113
185
  return parts.join(" — ");
114
186
  }