@everywheredev/cli 0.0.1-5.1
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 +135 -0
- package/bin/pocketdev.js +19 -0
- package/dist/index.js +388 -0
- package/package.json +68 -0
- package/scripts/build.mjs +68 -0
- package/scripts/ensure-node-pty.mjs +52 -0
- package/scripts/smoke.mjs +52 -0
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@everywheredev/cli",
|
|
3
|
+
"version": "0.0.1-5.1",
|
|
4
|
+
"description": "PocketDev CLI — a Claude-Code-style TypeScript thin client for the PocketDev host (FULL-REMOTE Hydra OAuth2).",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"bin": {
|
|
8
|
+
"pocketdev": "bin/pocketdev.js"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/vectorkub/pocketdev.git",
|
|
13
|
+
"directory": "cli"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/vectorkub/pocketdev/tree/main/cli#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/vectorkub/pocketdev/issues"
|
|
18
|
+
},
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"bin/",
|
|
24
|
+
"dist/",
|
|
25
|
+
"scripts/",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=20"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc -p tsconfig.json --noEmit && node scripts/build.mjs",
|
|
33
|
+
"build:watch": "tsc -p tsconfig.json --watch",
|
|
34
|
+
"dev": "node --import tsx ./src/index.ts",
|
|
35
|
+
"test": "vitest run --passWithNoTests",
|
|
36
|
+
"test:watch": "vitest",
|
|
37
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
38
|
+
"smoke": "node scripts/smoke.mjs",
|
|
39
|
+
"prepare": "npm run build",
|
|
40
|
+
"postinstall": "node scripts/ensure-node-pty.mjs"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"chalk": "^5.3.0",
|
|
44
|
+
"chokidar": "^4.0.3",
|
|
45
|
+
"gradient-string": "^2.0.2",
|
|
46
|
+
"ignore": "^5.3.2",
|
|
47
|
+
"ink": "^5.0.1",
|
|
48
|
+
"jose": "^5.9.6",
|
|
49
|
+
"keytar": "^7.9.0",
|
|
50
|
+
"node-pty": "^1.0.0",
|
|
51
|
+
"puppeteer-core": "^23.11.1",
|
|
52
|
+
"react": "^18.3.1",
|
|
53
|
+
"reflect-metadata": "^0.2.2",
|
|
54
|
+
"tsyringe": "^4.8.0",
|
|
55
|
+
"ws": "^8.18.0",
|
|
56
|
+
"zod": "^3.23.8"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/gradient-string": "^1.1.6",
|
|
60
|
+
"@types/node": "^20.14.0",
|
|
61
|
+
"@types/react": "^18.3.3",
|
|
62
|
+
"@types/ws": "^8.5.12",
|
|
63
|
+
"esbuild": "^0.24.0",
|
|
64
|
+
"tsx": "^4.16.0",
|
|
65
|
+
"typescript": "^5.5.0",
|
|
66
|
+
"vitest": "^2.0.0"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Bundles the CLI into a single minified dist/index.js so the published package
|
|
2
|
+
// is not trivially readable (the source repo stays private; only this bundle ships).
|
|
3
|
+
//
|
|
4
|
+
// Why esbuild-direct-from-src is safe: src/ uses no decorators and DI is wired with
|
|
5
|
+
// manual factories (src/di/container.ts), so esbuild not emitting decorator metadata
|
|
6
|
+
// is irrelevant. Type-checking is enforced separately via `tsc --noEmit` (see the
|
|
7
|
+
// "build" script in package.json).
|
|
8
|
+
|
|
9
|
+
import { rm } from "node:fs/promises";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
import { dirname, resolve } from "node:path";
|
|
12
|
+
import { build } from "esbuild";
|
|
13
|
+
|
|
14
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
15
|
+
|
|
16
|
+
// Clear stale per-file tsc output so only the single bundle ships.
|
|
17
|
+
await rm(resolve(root, "dist"), { recursive: true, force: true });
|
|
18
|
+
|
|
19
|
+
await build({
|
|
20
|
+
absWorkingDir: root,
|
|
21
|
+
entryPoints: ["src/index.ts"],
|
|
22
|
+
outfile: "dist/index.js", // keep this path: bin/pocketdev.js and scripts/smoke.mjs import ../dist/index.js
|
|
23
|
+
bundle: true,
|
|
24
|
+
minify: true,
|
|
25
|
+
platform: "node",
|
|
26
|
+
format: "esm", // package is "type":"module"; preserves import.meta.url for createRequire
|
|
27
|
+
target: "node20",
|
|
28
|
+
legalComments: "none",
|
|
29
|
+
// ESM output has no `require`/__dirname/__filename globals, but bundled CJS deps (e.g. ws calling
|
|
30
|
+
// require("events")) and node-pty's createRequire path rely on them. Define them at the top of the
|
|
31
|
+
// bundle from import.meta.url so those calls resolve against the real Node module system.
|
|
32
|
+
banner: {
|
|
33
|
+
js: [
|
|
34
|
+
"import { createRequire as __everywhere_createRequire } from 'node:module';",
|
|
35
|
+
"import { fileURLToPath as __everywhere_fileURLToPath } from 'node:url';",
|
|
36
|
+
"import { dirname as __everywhere_dirname } from 'node:path';",
|
|
37
|
+
"const require = __everywhere_createRequire(import.meta.url);",
|
|
38
|
+
"const __filename = __everywhere_fileURLToPath(import.meta.url);",
|
|
39
|
+
"const __dirname = __everywhere_dirname(__filename);",
|
|
40
|
+
].join("\n"),
|
|
41
|
+
},
|
|
42
|
+
// Native addons + dynamic-import natives stay external (resolved from node_modules at runtime).
|
|
43
|
+
// node-pty/puppeteer-core/ignore load via createRequire (not followed by the bundler), but we
|
|
44
|
+
// list them for clarity; keytar loads via dynamic import() which esbuild WOULD bundle otherwise.
|
|
45
|
+
// These are real `dependencies` installed in the user's node_modules; keep them external so the
|
|
46
|
+
// native/dynamic loaders (createRequire / dynamic import()) resolve them at runtime.
|
|
47
|
+
external: ["node-pty", "keytar", "puppeteer-core", "ignore"],
|
|
48
|
+
plugins: [
|
|
49
|
+
// ink statically imports react-devtools-core (only used when ink's DEV devtools are enabled).
|
|
50
|
+
// It isn't a dependency, so we can't externalize it (an external ESM import resolves eagerly at
|
|
51
|
+
// load and would crash). Stub it to an empty module — the devtools code path never runs for users.
|
|
52
|
+
{
|
|
53
|
+
name: "stub-react-devtools",
|
|
54
|
+
setup(b) {
|
|
55
|
+
b.onResolve({ filter: /^react-devtools-core$/ }, () => ({
|
|
56
|
+
path: "react-devtools-core",
|
|
57
|
+
namespace: "stub-react-devtools",
|
|
58
|
+
}));
|
|
59
|
+
b.onLoad({ filter: /.*/, namespace: "stub-react-devtools" }, () => ({
|
|
60
|
+
contents: "export default {};",
|
|
61
|
+
loader: "js",
|
|
62
|
+
}));
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
process.stdout.write("built dist/index.js\n");
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Postinstall guard for node-pty's native binaries.
|
|
2
|
+
//
|
|
3
|
+
// node-pty execs a bundled `spawn-helper` to allocate the PTY on macOS/Linux. npm frequently extracts it
|
|
4
|
+
// WITHOUT the executable bit, which makes every PTY spawn fail with "posix_spawnp failed" → the device
|
|
5
|
+
// terminal exits 1 instantly. This runs after install to (1) confirm the prebuild for this platform/arch
|
|
6
|
+
// exists and (2) restore +x on the helper. It is best-effort and NEVER fails the install (exit 0 always),
|
|
7
|
+
// since the runtime also self-heals (src/transport/device-terminal.ts:ensureSpawnHelperExecutable).
|
|
8
|
+
|
|
9
|
+
import { chmodSync, existsSync, readdirSync } from "node:fs";
|
|
10
|
+
import { createRequire } from "node:module";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
const root = dirname(require.resolve("node-pty/package.json"));
|
|
16
|
+
const tag = `${process.platform}-${process.arch}`; // e.g. darwin-arm64, linux-x64
|
|
17
|
+
|
|
18
|
+
let fixed = 0;
|
|
19
|
+
const helpers = [
|
|
20
|
+
join(root, "build", "Release", "spawn-helper"), // built-from-source layout
|
|
21
|
+
];
|
|
22
|
+
const prebuilds = join(root, "prebuilds");
|
|
23
|
+
if (existsSync(prebuilds)) {
|
|
24
|
+
for (const d of readdirSync(prebuilds)) {
|
|
25
|
+
helpers.push(join(prebuilds, d, "spawn-helper"));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
for (const h of helpers) {
|
|
29
|
+
if (existsSync(h)) {
|
|
30
|
+
try {
|
|
31
|
+
chmodSync(h, 0o755);
|
|
32
|
+
fixed++;
|
|
33
|
+
} catch {
|
|
34
|
+
/* not our file / read-only fs */
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Warn (don't fail) if there's no prebuild for this platform — node-pty would need a build toolchain.
|
|
40
|
+
const ptyNode = join(prebuilds, tag, "pty.node");
|
|
41
|
+
const builtNode = join(root, "build", "Release", "pty.node");
|
|
42
|
+
if (!existsSync(ptyNode) && !existsSync(builtNode)) {
|
|
43
|
+
console.warn(
|
|
44
|
+
`[pocketdev] node-pty has no prebuilt binary for ${tag}; dashboard terminal sharing may be off. ` +
|
|
45
|
+
`Install a build toolchain (python3 + a C++ compiler) and run \`npm rebuild node-pty\`.`,
|
|
46
|
+
);
|
|
47
|
+
} else if (fixed > 0) {
|
|
48
|
+
console.log(`[pocketdev] node-pty ready (${tag}); ensured spawn-helper is executable.`);
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
// node-pty not installed yet / layout differs — the runtime self-heal covers it.
|
|
52
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Cross-OS smoke test for the published CLI shape.
|
|
2
|
+
//
|
|
3
|
+
// The CLI has no offline `--help`/`--version` — every invocation routes to the `session` command,
|
|
4
|
+
// which needs auth + a running host. So we can't prove "this OS is supported" by running the binary.
|
|
5
|
+
// Instead we directly load the two NATIVE addons (the real per-OS/arch risk) and the compiled entry:
|
|
6
|
+
// - require("node-pty") / require("keytar") loads the native binary for this platform/arch. `require`
|
|
7
|
+
// does NOT touch the OS secret service or spawn a PTY, so it is safe headless/CI.
|
|
8
|
+
// - import("../dist/index.js") proves the built JS + its full dependency graph resolve here.
|
|
9
|
+
//
|
|
10
|
+
// Ships in `files` (scripts/), so it runs identically from a source checkout and from an installed
|
|
11
|
+
// tarball: `node scripts/smoke.mjs` (cwd = package root) or
|
|
12
|
+
// `node node_modules/@pocketdev/cli/scripts/smoke.mjs` (from a consumer install).
|
|
13
|
+
|
|
14
|
+
import { createRequire } from "node:module";
|
|
15
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
16
|
+
import { dirname, join } from "node:path";
|
|
17
|
+
|
|
18
|
+
const require = createRequire(import.meta.url);
|
|
19
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
|
|
21
|
+
let failed = false;
|
|
22
|
+
const ok = (m) => console.log(`ok: ${m}`);
|
|
23
|
+
const fail = (m, e) => {
|
|
24
|
+
failed = true;
|
|
25
|
+
console.error(`FAIL: ${m}: ${e?.stack ?? e}`);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
console.log(`[smoke] ${process.platform}-${process.arch} node ${process.version}`);
|
|
29
|
+
|
|
30
|
+
for (const mod of ["node-pty", "keytar"]) {
|
|
31
|
+
try {
|
|
32
|
+
require(mod);
|
|
33
|
+
ok(`native addon "${mod}" loaded`);
|
|
34
|
+
} catch (e) {
|
|
35
|
+
fail(`native addon "${mod}"`, e);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
// scripts/ -> ../dist/index.js (pathToFileURL handles Windows drive paths correctly)
|
|
41
|
+
await import(pathToFileURL(join(here, "..", "dist", "index.js")).href);
|
|
42
|
+
ok("dist/index.js loaded");
|
|
43
|
+
} catch (e) {
|
|
44
|
+
fail("dist/index.js", e);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (failed) {
|
|
48
|
+
console.error("[smoke] FAILED");
|
|
49
|
+
process.exitCode = 1;
|
|
50
|
+
} else {
|
|
51
|
+
console.log("[smoke] OK — all native addons + compiled entry load on this platform");
|
|
52
|
+
}
|