@command-center/command-center 0.7.2 → 0.7.3-rc1

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/README.md CHANGED
@@ -9,6 +9,7 @@ Binary distribution of UpToSpeed Command Center, a desktop-friendly interface fo
9
9
  - Linux arm64
10
10
  - Linux x64
11
11
  - Windows x64
12
+ - Windows arm64
12
13
 
13
14
  If your platform is missing, please open an issue so we can add another target.
14
15
 
@@ -25,6 +26,7 @@ This command places a `command-center` executable on your `$PATH`. During instal
25
26
  - `@command-center/command-center-linux-arm64`
26
27
  - `@command-center/command-center-linux-x64`
27
28
  - `@command-center/command-center-win-x64`
29
+ - `@command-center/command-center-win-arm64`
28
30
 
29
31
  Each optional package ships exactly one prebuilt binary. The wrapper resolves the right package at runtime and forwards all CLI arguments to its binary.
30
32
 
@@ -69,3 +71,4 @@ directly from the printed path.
69
71
  - **“Unsupported platform”** – The wrapper could not map your `process.platform`/`process.arch` combination. Please file an issue with your OS and architecture.
70
72
  - **“Expected binary … was not found”** – Reinstall the package. If you are developing locally, run `npm run prepare:dist` from the repository root to refresh the optional binary packages.
71
73
  - **Permission errors** – On POSIX systems, ensure the binaries remain executable (`chmod +x node_modules/@command-center/command-center-*/dist/command-center-*`).
74
+ - **AVX crash on Windows** – If the Windows x64 binary crashes immediately (e.g. in Parallels or on older CPUs without AVX), the wrapper automatically installs and runs `@command-center/command-center-win-x64-baseline`, a build without AVX instructions.
@@ -1,16 +1,41 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { spawn } from "node:child_process";
3
+ // Thin Node.js wrapper around the precompiled Command Center binary.
4
+ //
5
+ // This script resolves the correct platform-specific binary from npm optional
6
+ // dependencies and spawns it, forwarding all CLI arguments and stdio.
7
+ //
8
+ // COMMENT_AVX_Fallback (Windows x64 only), 2026.03.04
9
+ // --------------------------------
10
+ // Parallels Desktop x86_64 emulation on Apple Silicon does not support AVX.
11
+ // When run: will exit with STATUS_ILLEGAL_INSTRUCTION.
12
+ // Solution: Have another binary that is compiled without AVX instructions (baseline),
13
+ // download it on demand.
14
+
15
+ // #######################################
16
+ // Imports
17
+ // #######################################
18
+
19
+ import { execSync, spawn } from "node:child_process";
4
20
  import { existsSync } from "node:fs";
5
21
  import { createRequire } from "node:module";
6
22
  import path from "node:path";
7
23
 
24
+ // #######################################
25
+ // Constants
26
+ // #######################################
27
+
8
28
  const require = createRequire(import.meta.url);
9
29
  const packageMetadata = require("../package.json");
10
30
 
11
31
  const PACKAGE_VERSION = packageMetadata.version ?? "0.0.0";
12
32
  const PLATFORM_KEY = `${process.platform}:${process.arch}`;
13
33
 
34
+ // STATUS_ILLEGAL_INSTRUCTION (0xC000001D) as an unsigned 32-bit integer.
35
+ // Windows returns this when a process hits an unsupported CPU instruction
36
+ // (e.g. AVX on a system without AVX support, such as Parallels x86_64 emulation).
37
+ const STATUS_ILLEGAL_INSTRUCTION = 3_221_225_501;
38
+
14
39
  // TAG_PLATFORM_MATRIX 2025.10.14: Keep entries in sync with scripts/build-all.ts outputs.
15
40
  const PLATFORM_PACKAGES = new Map([
16
41
  [
@@ -46,15 +71,51 @@ const PLATFORM_PACKAGES = new Map([
46
71
  {
47
72
  packageName: "@command-center/command-center-win-x64",
48
73
  binaryName: "command-center-win-x64.exe",
74
+ // On-demand fallback: only downloaded if the primary binary crashes with
75
+ // STATUS_ILLEGAL_INSTRUCTION (no AVX support). See file header for details.
76
+ fallbackPackageName: "@command-center/command-center-win-x64-baseline",
77
+ fallbackBinaryName: "command-center-win-x64-baseline.exe",
78
+ },
79
+ ],
80
+ [
81
+ "win32:arm64",
82
+ {
83
+ packageName: "@command-center/command-center-win-arm64",
84
+ binaryName: "command-center-win-arm64.exe",
49
85
  },
50
86
  ],
51
87
  ]);
52
88
 
89
+ // #######################################
90
+ // Utility Functions
91
+ // #######################################
92
+
53
93
  function fail(message) {
54
94
  console.error(`command-center (wrapper): ${message}`);
55
95
  process.exit(1);
56
96
  }
57
97
 
98
+ // #######################################
99
+ // Binary Resolution
100
+ // #######################################
101
+
102
+ function resolvePackageRoot(packageName) {
103
+ const packageJsonPath = require.resolve(`${packageName}/package.json`);
104
+ return path.dirname(packageJsonPath);
105
+ }
106
+
107
+ function resolveBinaryInPackage(packageName, binaryName) {
108
+ let packageRoot;
109
+ try {
110
+ packageRoot = resolvePackageRoot(packageName);
111
+ } catch {
112
+ return null;
113
+ }
114
+
115
+ const binaryPath = path.join(packageRoot, "dist", binaryName);
116
+ return existsSync(binaryPath) ? binaryPath : null;
117
+ }
118
+
58
119
  function resolveBinary() {
59
120
  const entry = PLATFORM_PACKAGES.get(PLATFORM_KEY);
60
121
  if (!entry) {
@@ -65,61 +126,161 @@ function resolveBinary() {
65
126
  );
66
127
  }
67
128
 
68
- let packageRoot = "";
69
- try {
70
- const packageJsonPath = require.resolve(
71
- `${entry.packageName}/package.json`,
72
- );
73
- packageRoot = path.dirname(packageJsonPath);
74
- } catch (error) {
129
+ const binaryPath = resolveBinaryInPackage(
130
+ entry.packageName,
131
+ entry.binaryName,
132
+ );
133
+ if (!binaryPath) {
75
134
  fail(
76
135
  `missing optional dependency '${entry.packageName}'.` +
77
136
  "\n • npm should install it automatically on supported platforms." +
78
- "\n • Try reinstalling the CLI or running 'npm install @command-center/command-center' again." +
79
- `\n • Underlying error: ${error instanceof Error ? error.message : String(error)}`,
137
+ "\n • Try reinstalling the CLI or running 'npm install @command-center/command-center' again.",
80
138
  );
81
139
  }
82
140
 
83
- const binaryPath = path.join(packageRoot, "dist", entry.binaryName);
84
- if (!existsSync(binaryPath)) {
85
- fail(
86
- `expected binary '${entry.binaryName}' was not found in ${entry.packageName}.` +
87
- "\n • Ensure the optional dependency was published with binaries (run 'bun run build:binary' before publishing)." +
88
- "\n • If you are developing locally, run 'npm run prepare:dist' to refresh optional packages.",
141
+ return { binaryPath, entry };
142
+ }
143
+
144
+ // #######################################
145
+ // Process Spawning
146
+ // #######################################
147
+
148
+ function spawnBinary(binaryPath, argv) {
149
+ return new Promise((resolve) => {
150
+ const child = spawn(binaryPath, argv, { stdio: "inherit" });
151
+
152
+ child.on("error", (error) => {
153
+ resolve({ code: null, signal: null, error });
154
+ });
155
+
156
+ child.on("exit", (code, signal) => {
157
+ resolve({ code, signal, error: null });
158
+ });
159
+ });
160
+ }
161
+
162
+ // #######################################
163
+ // AVX Fallback
164
+ // #######################################
165
+
166
+ // Downloads the baseline binary package on demand via `npm install -g`.
167
+ // This only runs once per machine — after installation, subsequent launches
168
+ // find the package locally and skip this step.
169
+ function installFallbackPackage(packageName) {
170
+ console.error(
171
+ `command-center (wrapper): installing fallback package ${packageName}@${PACKAGE_VERSION}...`,
172
+ );
173
+ try {
174
+ execSync(`npm install -g ${packageName}@${PACKAGE_VERSION}`, {
175
+ stdio: "inherit",
176
+ });
177
+ return true;
178
+ } catch {
179
+ console.error(
180
+ `command-center (wrapper): failed to install ${packageName}. You can install it manually:` +
181
+ `\n npm install -g ${packageName}@${PACKAGE_VERSION}`,
89
182
  );
183
+ return false;
90
184
  }
91
-
92
- return binaryPath;
93
185
  }
94
186
 
187
+ // #######################################
188
+ // Main
189
+ // #######################################
190
+
95
191
  const argv = process.argv.slice(2);
96
192
 
97
193
  const printVersionBanner = () => {
98
194
  console.log(`command-center ${PACKAGE_VERSION}`);
99
195
  };
100
196
 
197
+ // ##############################
198
+ // Handle --version flag
199
+ // ##############################
200
+
101
201
  if (argv.some((arg) => arg === "--version" || arg === "-v")) {
102
202
  printVersionBanner();
103
203
  process.exit(0);
104
204
  }
105
205
 
106
- const binaryPath = resolveBinary();
206
+ // ##############################
207
+ // Resolve and spawn primary binary
208
+ // ##############################
209
+
210
+ const { binaryPath, entry } = resolveBinary();
107
211
  printVersionBanner();
108
212
 
109
- const child = spawn(binaryPath, argv, {
110
- stdio: "inherit",
111
- });
213
+ const result = await spawnBinary(binaryPath, argv);
214
+
215
+ if (result.error) {
216
+ fail(`failed to launch bundled binary (${result.error.message}).`);
217
+ }
218
+
219
+ // ##############################
220
+ // AVX fallback for Windows
221
+ // ##############################
222
+
223
+ // The AVX binary crashes immediately on CPUs/emulators without AVX support.
224
+ // Node's `spawn` reports the Windows NTSTATUS code as an unsigned 32-bit exit
225
+ // code (3221225501), not the signed representation (-1073741795).
226
+ // When we see this specific exit code AND the platform entry has a fallback
227
+ // configured, we install (if needed) and launch the baseline binary instead.
228
+ if (result.code === STATUS_ILLEGAL_INSTRUCTION && entry.fallbackPackageName) {
229
+ console.error(
230
+ "command-center (wrapper): binary crashed (CPU does not support AVX instructions).",
231
+ );
232
+
233
+ // ####################
234
+ // Resolve or install fallback binary
235
+ // ####################
112
236
 
113
- child.on("error", (error) => {
114
- fail(`failed to launch bundled binary (${error.message}).`);
115
- });
237
+ let fallbackPath = resolveBinaryInPackage(
238
+ entry.fallbackPackageName,
239
+ entry.fallbackBinaryName,
240
+ );
116
241
 
117
- child.on("exit", (code, signal) => {
118
- if (signal) {
242
+ if (!fallbackPath) {
243
+ const installed = installFallbackPackage(entry.fallbackPackageName);
244
+ if (installed) {
245
+ fallbackPath = resolveBinaryInPackage(
246
+ entry.fallbackPackageName,
247
+ entry.fallbackBinaryName,
248
+ );
249
+ }
250
+ }
251
+
252
+ if (!fallbackPath) {
253
+ fail("failed to resolve fallback binary after installation.");
254
+ }
255
+
256
+ // ####################
257
+ // Spawn fallback binary
258
+ // ####################
259
+
260
+ console.error("command-center (wrapper): retrying with baseline binary...");
261
+ const fallbackResult = await spawnBinary(fallbackPath, argv);
262
+
263
+ if (fallbackResult.error) {
264
+ fail(`failed to launch fallback binary (${fallbackResult.error.message}).`);
265
+ }
266
+ if (fallbackResult.signal) {
119
267
  console.error(
120
- `command-center (wrapper): process terminated with signal ${signal}.`,
268
+ `command-center (wrapper): process terminated with signal ${fallbackResult.signal}.`,
121
269
  );
122
270
  process.exit(1);
123
271
  }
124
- process.exit(code === null ? 1 : code);
125
- });
272
+ process.exit(fallbackResult.code === null ? 1 : fallbackResult.code);
273
+ }
274
+
275
+ // ##############################
276
+ // Exit with primary binary result
277
+ // ##############################
278
+
279
+ if (result.signal) {
280
+ console.error(
281
+ `command-center (wrapper): process terminated with signal ${result.signal}.`,
282
+ );
283
+ process.exit(1);
284
+ }
285
+
286
+ process.exit(result.code === null ? 1 : result.code);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@command-center/command-center",
3
- "version": "0.7.2",
3
+ "version": "0.7.3-rc1",
4
4
  "type": "module",
5
5
  "description": "Binary distribution of UpToSpeed Command Center",
6
6
  "bin": {
@@ -23,11 +23,12 @@
23
23
  "access": "public"
24
24
  },
25
25
  "optionalDependencies": {
26
- "@command-center/command-center-linux-arm64": "0.7.2",
27
- "@command-center/command-center-linux-x64": "0.7.2",
28
- "@command-center/command-center-macos-arm64": "0.7.2",
29
- "@command-center/command-center-macos-x64": "0.7.2",
30
- "@command-center/command-center-win-x64": "0.7.2"
26
+ "@command-center/command-center-linux-arm64": "0.7.3-rc1",
27
+ "@command-center/command-center-linux-x64": "0.7.3-rc1",
28
+ "@command-center/command-center-macos-arm64": "0.7.3-rc1",
29
+ "@command-center/command-center-macos-x64": "0.7.3-rc1",
30
+ "@command-center/command-center-win-arm64": "0.7.3-rc1",
31
+ "@command-center/command-center-win-x64": "0.7.3-rc1"
31
32
  },
32
33
  "scripts": {}
33
34
  }