@linxiraos/main 1.1.26 → 1.1.28

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/bin/zeta.js +101 -12
  2. package/package.json +3 -3
package/bin/zeta.js CHANGED
@@ -1,7 +1,14 @@
1
1
  #!/usr/bin/env node
2
- // zeta launcher — resolves the workspace binary from optionalDependencies
3
- // leaves (same pattern as the zeta-ide / zeta-editor launchers). Node-only,
4
- // no Bun needed.
2
+ // zeta launcher — unified binary discovery, npm-form face:
3
+ // ① explicit env — ZETA_BIN_DIR (delimiter-separated dirs, probed first)
4
+ // ② PATH — a *native* zetawork/zeta binary (distro pacman install
5
+ // or a real .exe); PATH hits are used as-is, with no
6
+ // cross-component version validation
7
+ // ③ npm vendored — the platform-leaf binary shipped as
8
+ // @linxiraos/main-<platform>-<arch> (same pattern as the
9
+ // zeta-ide / zeta-editor launchers), then the repo
10
+ // target/release location for source checkouts
11
+ // Node-only, no Bun needed.
5
12
 
6
13
  const fs = require("node:fs");
7
14
  const path = require("node:path");
@@ -11,25 +18,107 @@ const { spawn } = require("node:child_process");
11
18
  const PKG_PLATFORM = process.platform === "win32" ? "windows" : process.platform;
12
19
  const PKG_PREFIX = "@linxiraos/main-";
13
20
  const EXE = process.platform === "win32" ? "zeta.exe" : "zeta-linux-x64";
21
+ const NATIVE_BINS = ["zetawork", "zeta", "zeta-work"];
14
22
 
15
23
  function die(msg) {
16
24
  process.stderr.write(`zeta: ${msg}\n`);
17
25
  process.exit(1);
18
26
  }
19
27
 
20
- let bin = null;
21
- try {
22
- bin = require.resolve(`${PKG_PREFIX}${PKG_PLATFORM}-${process.arch}/bin/${EXE}`);
23
- } catch {
24
- // Fall back to a repo-layout location (dev / source checkout):
25
- // <repo>/main/target/release/<exe> next to this package.
26
- const local = path.join(__dirname, "..", "..", "..", "target", "release", EXE);
27
- if (fs.existsSync(local)) bin = local;
28
+ /** Native-executable test so PATH probes never pick up another JS shim
29
+ * (npm's .cmd/.ps1/sh launchers for this very package live on PATH —
30
+ * re-executing them would recurse into this script). POSIX also demands
31
+ * the exec bit: a non-executable ELF (broken extract, cache artifact)
32
+ * would only die later with a raw spawn EACCES. */
33
+ function isNativeBinary(candidate) {
34
+ let stat;
35
+ try {
36
+ stat = fs.statSync(candidate);
37
+ } catch {
38
+ return false;
39
+ }
40
+ if (!stat.isFile()) return false;
41
+ if (process.platform === "win32") {
42
+ return candidate.toLowerCase().endsWith(".exe");
43
+ }
44
+ if (!isExecutable(candidate)) return false;
45
+ let head;
46
+ try {
47
+ const fd = fs.openSync(candidate, "r");
48
+ const buf = Buffer.alloc(4);
49
+ const read = fs.readSync(fd, buf, 0, 4, 0);
50
+ fs.closeSync(fd);
51
+ head = read === 4 ? buf : null;
52
+ } catch {
53
+ return false;
54
+ }
55
+ return head !== null && head.equals(Buffer.from([0x7f, 0x45, 0x4c, 0x46])); // \x7fELF
56
+ }
57
+
58
+ /** POSIX exec-bit probe; Windows access(X_OK) always succeeds, which is
59
+ * fine there — a named .exe is the platform's native form. */
60
+ function isExecutable(candidate) {
61
+ try {
62
+ fs.accessSync(candidate, fs.constants.X_OK);
63
+ return true;
64
+ } catch {
65
+ return false;
66
+ }
67
+ }
68
+
69
+ /** Native executable candidates for one bin name per directory entry:
70
+ * `name.exe` on Windows, the bare ELF name elsewhere. */
71
+ function nativeCandidates(dir, name) {
72
+ return process.platform === "win32" ? [path.join(dir, `${name}.exe`)] : [path.join(dir, name)];
73
+ }
74
+
75
+ /** First native hit for the workbench bins inside `dirs`, or null. */
76
+ function findNativeIn(dirs) {
77
+ for (const dir of dirs) {
78
+ if (!dir) continue;
79
+ for (const name of NATIVE_BINS) {
80
+ for (const candidate of nativeCandidates(dir, name)) {
81
+ if (isNativeBinary(candidate)) return candidate;
82
+ }
83
+ }
84
+ }
85
+ return null;
86
+ }
87
+
88
+ function explicitDirs() {
89
+ const raw = process.env.ZETA_BIN_DIR;
90
+ if (!raw) return [];
91
+ return raw.split(path.delimiter).map((dir) => dir.trim()).filter((dir) => dir.length > 0);
92
+ }
93
+
94
+ /** Windows env blocks carry `Path`, POSIX `PATH` — accept either spelling. */
95
+ function pathDirs() {
96
+ const raw = process.env.PATH ?? process.env.Path;
97
+ return (raw || "").split(path.delimiter);
98
+ }
99
+
100
+ // ① explicit env → ② PATH (native binaries only)
101
+ const fromNative = findNativeIn([...explicitDirs(), ...pathDirs()]);
102
+
103
+ let bin = fromNative;
104
+ if (!bin) {
105
+ // ③ npm vendored platform leaf. A resolved but non-executable leaf
106
+ // (broken extract, cache artifact) must fall through to the install
107
+ // hint instead of dying later with a raw spawn EACCES.
108
+ try {
109
+ const leaf = require.resolve(`${PKG_PREFIX}${PKG_PLATFORM}-${process.arch}/bin/${EXE}`);
110
+ if (process.platform === "win32" || isExecutable(leaf)) bin = leaf;
111
+ } catch {
112
+ // Fall back to a repo-layout location (dev / source checkout):
113
+ // <repo>/main/target/release/<exe> next to this package.
114
+ const local = path.join(__dirname, "..", "..", "..", "target", "release", EXE);
115
+ if (fs.existsSync(local) && (process.platform === "win32" || isExecutable(local))) bin = local;
116
+ }
28
117
  }
29
118
 
30
119
  if (!bin) {
31
120
  die(
32
- `no binary for ${process.platform}-${process.arch}; ` +
121
+ `no native zetawork/zeta on PATH and no binary for ${process.platform}-${process.arch}; ` +
33
122
  `install @linxiraos/main (supported: windows-x64, linux-x64) ` +
34
123
  `or build from source with \`cargo build --release\` in the main/ workspace`,
35
124
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linxiraos/main",
3
- "version": "1.1.26",
3
+ "version": "1.1.28",
4
4
  "description": "zeta — the Zeta workspace: a nested-terminal workbench with tabs, panes, and the Zeta tool suite",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -22,8 +22,8 @@
22
22
  "README.md"
23
23
  ],
24
24
  "optionalDependencies": {
25
- "@linxiraos/main-windows-x64": "1.1.26",
26
- "@linxiraos/main-linux-x64": "1.1.26"
25
+ "@linxiraos/main-windows-x64": "1.1.28",
26
+ "@linxiraos/main-linux-x64": "1.1.28"
27
27
  },
28
28
  "engines": {
29
29
  "node": ">=18"