@pizzapi/pizza 0.1.33 → 0.1.34-dev.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.
Files changed (2) hide show
  1. package/bin/pizza.mjs +103 -18
  2. package/package.json +6 -6
package/bin/pizza.mjs CHANGED
@@ -9,13 +9,14 @@
9
9
  * Pattern borrowed from esbuild, turbo, swc, etc.
10
10
  */
11
11
 
12
- import { execFileSync } from "node:child_process";
13
- import { existsSync } from "node:fs";
14
- import { join, dirname } from "node:path";
12
+ import { execFileSync, execSync } from "node:child_process";
13
+ import { existsSync, readFileSync } from "node:fs";
14
+ import { join, dirname, resolve } from "node:path";
15
15
  import { createRequire } from "node:module";
16
16
  import { fileURLToPath } from "node:url";
17
17
 
18
- const __dirname = dirname(fileURLToPath(import.meta.url));
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = dirname(__filename);
19
20
 
20
21
  // Map of `${process.platform}-${process.arch}` to npm package name
21
22
  const PLATFORM_PACKAGES = {
@@ -38,13 +39,24 @@ if (!pkgName) {
38
39
  process.exit(1);
39
40
  }
40
41
 
41
- // Try to find the binary
42
+ /** Read our own package.json version. */
43
+ function getOwnVersion() {
44
+ try {
45
+ const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
46
+ return pkg.version;
47
+ } catch {
48
+ return undefined;
49
+ }
50
+ }
51
+
52
+ /** Try to find the platform binary via multiple strategies. */
42
53
  function findBinary() {
43
- const require = createRequire(join(__dirname, ".."));
44
54
  const binName = process.platform === "win32" ? "pizza.exe" : "pizza";
55
+ const parts = pkgName.split("/");
45
56
 
46
57
  // Strategy 1: require.resolve the platform package
47
58
  try {
59
+ const require = createRequire(join(__dirname, "..", "package.json"));
48
60
  const pkgJson = require.resolve(`${pkgName}/package.json`);
49
61
  const pkgDir = dirname(pkgJson);
50
62
  const binPath = join(pkgDir, "bin", binName);
@@ -53,12 +65,8 @@ function findBinary() {
53
65
  // not found via require
54
66
  }
55
67
 
56
- const parts = pkgName.split("/");
57
-
58
68
  // Strategy 2: Sibling scoped package — both packages live under
59
69
  // node_modules/@pizzapi/, so the platform package is a sibling of ours.
60
- // __dirname = .../node_modules/@pizzapi/pizza/bin
61
- // sibling = .../node_modules/@pizzapi/cli-win32-x64/bin/pizza.exe
62
70
  {
63
71
  const siblingPath = join(__dirname, "..", "..", parts[1], "bin", binName);
64
72
  if (existsSync(siblingPath)) return siblingPath;
@@ -76,21 +84,98 @@ function findBinary() {
76
84
  if (existsSync(binPath)) return binPath;
77
85
  }
78
86
 
87
+ // Strategy 4: Walk up from __dirname looking for node_modules containing
88
+ // the platform package (covers deeply nested or unusual layouts)
89
+ {
90
+ let dir = resolve(__dirname);
91
+ for (let i = 0; i < 10; i++) {
92
+ const candidate = join(dir, "node_modules", parts[0], parts[1], "bin", binName);
93
+ if (existsSync(candidate)) return candidate;
94
+ const parent = dirname(dir);
95
+ if (parent === dir) break;
96
+ dir = parent;
97
+ }
98
+ }
99
+
100
+ // Strategy 5: Use npm root -g to find global node_modules
101
+ try {
102
+ const globalRoot = execSync("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
103
+ if (globalRoot) {
104
+ const binPath = join(globalRoot, parts[0], parts[1], "bin", binName);
105
+ if (existsSync(binPath)) return binPath;
106
+ }
107
+ } catch {
108
+ // npm not available or failed
109
+ }
110
+
79
111
  return null;
80
112
  }
81
113
 
82
- const binaryPath = findBinary();
114
+ /**
115
+ * Attempt to install the missing platform package alongside our package.
116
+ * Returns true if the install succeeded.
117
+ */
118
+ function tryAutoInstall(version) {
119
+ const versionSpec = version ? `${pkgName}@${version}` : pkgName;
120
+
121
+ // Determine whether we're in a global install by checking if our path
122
+ // is inside a global-looking node_modules (not inside a project).
123
+ const isGlobal = __dirname.includes("node_modules");
124
+
125
+ const globalFlag = isGlobal ? " -g" : "";
126
+ console.error(
127
+ `\nThe platform package "${pkgName}" was not installed automatically.\n` +
128
+ `Attempting to install it now...\n`,
129
+ );
130
+
131
+ try {
132
+ execSync(`npm install${globalFlag} ${versionSpec}`, {
133
+ stdio: "inherit",
134
+ env: process.env,
135
+ });
136
+ return true;
137
+ } catch {
138
+ return false;
139
+ }
140
+ }
141
+
142
+ // --- Main ---
143
+
144
+ let binaryPath = findBinary();
145
+
146
+ // If not found, try to auto-install the platform package and retry
147
+ if (!binaryPath) {
148
+ const version = getOwnVersion();
149
+ if (tryAutoInstall(version)) {
150
+ binaryPath = findBinary();
151
+ }
152
+ }
83
153
 
84
154
  if (!binaryPath) {
155
+ // Collect diagnostic info for troubleshooting
156
+ const parts = pkgName.split("/");
157
+ const diag = [
158
+ ` launcher: ${__filename}`,
159
+ ` __dirname: ${__dirname}`,
160
+ ` platform: ${platformKey}`,
161
+ ];
162
+ const siblingDir = join(__dirname, "..", "..", parts[1]);
163
+ diag.push(` sibling dir exists: ${existsSync(siblingDir)} (${siblingDir})`);
164
+ try {
165
+ const globalRoot = execSync("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
166
+ const globalPkg = join(globalRoot, parts[0], parts[1]);
167
+ diag.push(` global root: ${globalRoot}`);
168
+ diag.push(` global pkg exists: ${existsSync(globalPkg)} (${globalPkg})`);
169
+ } catch {}
170
+
85
171
  console.error(
86
172
  `Error: Could not find the PizzaPi binary for your platform (${platformKey}).\n\n` +
87
- `The platform-specific package "${pkgName}" should have been installed\n` +
88
- `automatically as an optional dependency.\n\n` +
89
- `Try reinstalling:\n` +
90
- ` npm install @pizzapi/pizza\n\n` +
91
- `If the problem persists, install the platform package directly:\n` +
92
- ` npm install ${pkgName}\n\n` +
93
- `Or build from source: https://github.com/Pizzaface/PizzaPi`,
173
+ `The platform-specific package "${pkgName}" could not be installed\n` +
174
+ `automatically.\n\n` +
175
+ `Try installing it manually:\n` +
176
+ ` npm install -g ${pkgName}@${getOwnVersion() || "latest"}\n\n` +
177
+ `Or build from source: https://github.com/Pizzaface/PizzaPi\n\n` +
178
+ `Diagnostics:\n${diag.join("\n")}`,
94
179
  );
95
180
  process.exit(1);
96
181
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pizzapi/pizza",
3
- "version": "0.1.33",
3
+ "version": "0.1.34-dev.1",
4
4
  "description": "PizzaPi — a self-hosted web interface and relay server for the pi coding agent. Stream live AI coding sessions to any browser.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -13,11 +13,11 @@
13
13
  "LICENSE"
14
14
  ],
15
15
  "optionalDependencies": {
16
- "@pizzapi/cli-linux-x64": "0.1.33",
17
- "@pizzapi/cli-linux-arm64": "0.1.33",
18
- "@pizzapi/cli-darwin-x64": "0.1.33",
19
- "@pizzapi/cli-darwin-arm64": "0.1.33",
20
- "@pizzapi/cli-win32-x64": "0.1.33"
16
+ "@pizzapi/cli-linux-x64": "0.1.34-dev.1",
17
+ "@pizzapi/cli-linux-arm64": "0.1.34-dev.1",
18
+ "@pizzapi/cli-darwin-x64": "0.1.34-dev.1",
19
+ "@pizzapi/cli-darwin-arm64": "0.1.34-dev.1",
20
+ "@pizzapi/cli-win32-x64": "0.1.34-dev.1"
21
21
  },
22
22
  "engines": {
23
23
  "node": ">=18"