@paniolo/cli 0.5.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/README.md +19 -0
- package/bin/paniolo.js +86 -0
- package/package.json +23 -0
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @paniolo/cli
|
|
2
|
+
|
|
3
|
+
Internal distribution of the unified native `paniolo` CLI.
|
|
4
|
+
|
|
5
|
+
The wrapper selects one optional per-platform package and launches its bundled
|
|
6
|
+
binary. Commands include `paniolo scan`, `paniolo qmd`, `paniolo wiki`,
|
|
7
|
+
`paniolo evolve`, and `paniolo mcp`.
|
|
8
|
+
|
|
9
|
+
## Local release workflow
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
node npm/scripts/gen-packages.mjs --tool cli
|
|
13
|
+
node npm/scripts/stage-binaries.mjs --tool cli
|
|
14
|
+
node npm/scripts/pack-smoke.mjs --tool cli
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Ranch Hand releases are validated locally. `paniolo-internal` is not included
|
|
18
|
+
in this package family; harness maintenance scripts invoke it from the sibling
|
|
19
|
+
Ranch Hand source checkout.
|
package/bin/paniolo.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// Thin launcher for the native paniolo CLI. The binary itself ships in a
|
|
5
|
+
// per-platform optional dependency (@paniolo/cli-<platform>-<arch>); npm only
|
|
6
|
+
// installs the one matching the host's os/cpu. We resolve that package here and
|
|
7
|
+
// exec its binary. No network access, no postinstall — see
|
|
8
|
+
// docs/cross-building.md for how the binaries are produced and published.
|
|
9
|
+
|
|
10
|
+
const fs = require("fs");
|
|
11
|
+
const path = require("path");
|
|
12
|
+
const { spawn } = require("child_process");
|
|
13
|
+
|
|
14
|
+
// npm tarballs packed on Windows lose the Unix executable bit, so a binary
|
|
15
|
+
// published from a Windows machine arrives mode 0644 and fails to spawn with
|
|
16
|
+
// EACCES on Linux/macOS. Restore the bit at runtime (only when missing, and
|
|
17
|
+
// best-effort so a read-only install still surfaces the real spawn error).
|
|
18
|
+
function ensureExecutable(binary) {
|
|
19
|
+
if (process.platform === "win32") {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const { mode } = fs.statSync(binary);
|
|
24
|
+
if ((mode & 0o111) === 0) {
|
|
25
|
+
fs.chmodSync(binary, 0o755);
|
|
26
|
+
}
|
|
27
|
+
} catch {
|
|
28
|
+
// ignore; the spawn below will report a meaningful error if truly broken
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// The supported platform/arch keys, the platform-package scope, and the binary
|
|
33
|
+
// name are derived from this wrapper's own package.json — its
|
|
34
|
+
// optionalDependencies are the per-platform packages, generated from the single
|
|
35
|
+
// target list in npm/scripts/tools.mjs. So nothing about the target set is
|
|
36
|
+
// duplicated here; adding a platform there flows through on the next generate.
|
|
37
|
+
const wrapperPkg = require("../package.json");
|
|
38
|
+
const PKG_PREFIX = `${wrapperPkg.name}-`; // e.g. "@paniolo/cli-"
|
|
39
|
+
const BIN_NAME = Object.keys(wrapperPkg.bin)[0]; // "paniolo"
|
|
40
|
+
const SUPPORTED = new Set(
|
|
41
|
+
Object.keys(wrapperPkg.optionalDependencies || {}).map((dep) => dep.slice(PKG_PREFIX.length))
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
function resolveBinary() {
|
|
45
|
+
const key = `${process.platform}-${process.arch}`;
|
|
46
|
+
if (!SUPPORTED.has(key)) {
|
|
47
|
+
return { error: `unsupported platform/arch: ${key}` };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const pkg = `${PKG_PREFIX}${key}`;
|
|
51
|
+
const exe = process.platform === "win32" ? `${BIN_NAME}.exe` : BIN_NAME;
|
|
52
|
+
try {
|
|
53
|
+
// Resolve via the platform package's manifest so this works regardless of
|
|
54
|
+
// how the binary file is named in `exports`.
|
|
55
|
+
const manifest = require.resolve(`${pkg}/package.json`);
|
|
56
|
+
return { binary: path.join(path.dirname(manifest), exe) };
|
|
57
|
+
} catch {
|
|
58
|
+
return {
|
|
59
|
+
error:
|
|
60
|
+
`the platform package ${pkg} is not installed.\n` +
|
|
61
|
+
`Reinstall ${wrapperPkg.name} with optional dependencies enabled ` +
|
|
62
|
+
`(npm install --include=optional, or remove --no-optional / --omit=optional).`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const resolved = resolveBinary();
|
|
68
|
+
if (resolved.error) {
|
|
69
|
+
process.stderr.write(`${BIN_NAME}: ${resolved.error}\n`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
ensureExecutable(resolved.binary);
|
|
74
|
+
|
|
75
|
+
const child = spawn(resolved.binary, process.argv.slice(2), { stdio: "inherit" });
|
|
76
|
+
child.on("error", (error) => {
|
|
77
|
+
process.stderr.write(`${BIN_NAME}: failed to run ${resolved.binary}: ${error.message}\n`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
});
|
|
80
|
+
child.on("exit", (code, signal) => {
|
|
81
|
+
if (signal !== null) {
|
|
82
|
+
process.kill(process.pid, signal);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
process.exit(code ?? 0);
|
|
86
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@paniolo/cli",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Unified native Paniolo CLI, distributed as per-platform npm packages.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"bin": {
|
|
7
|
+
"paniolo": "bin/paniolo.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=18"
|
|
14
|
+
},
|
|
15
|
+
"optionalDependencies": {
|
|
16
|
+
"@paniolo/cli-linux-x64": "0.5.0",
|
|
17
|
+
"@paniolo/cli-linux-arm64": "0.5.0",
|
|
18
|
+
"@paniolo/cli-win32-x64": "0.5.0",
|
|
19
|
+
"@paniolo/cli-win32-arm64": "0.5.0",
|
|
20
|
+
"@paniolo/cli-darwin-x64": "0.5.0",
|
|
21
|
+
"@paniolo/cli-darwin-arm64": "0.5.0"
|
|
22
|
+
}
|
|
23
|
+
}
|