@pizzapi/pizza 0.1.34 → 0.1.35-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.
- package/bin/install.mjs +110 -44
- package/package.json +6 -6
package/bin/install.mjs
CHANGED
|
@@ -4,13 +4,16 @@
|
|
|
4
4
|
* PizzaPi postinstall script.
|
|
5
5
|
*
|
|
6
6
|
* Runs after `npm install @pizzapi/pizza` to ensure the platform-specific
|
|
7
|
-
* binary package is present
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* binary package is present **and at the correct version**.
|
|
8
|
+
*
|
|
9
|
+
* npm doesn't always install optionalDependencies reliably — especially with
|
|
10
|
+
* nvm-windows, global installs, or when the lockfile is stale (npm/cli#4828).
|
|
11
|
+
* Even when the binary exists, a stale platform package from a previous
|
|
12
|
+
* version can linger after an upgrade, causing hard-to-debug issues.
|
|
10
13
|
*
|
|
11
14
|
* Strategy:
|
|
12
|
-
* 1.
|
|
13
|
-
* 2. If
|
|
15
|
+
* 1. Locate the platform binary package
|
|
16
|
+
* 2. If missing OR its version doesn't match @pizzapi/pizza, (re)install it
|
|
14
17
|
*
|
|
15
18
|
* This mirrors the approach used by esbuild, rollup, swc, etc.
|
|
16
19
|
*/
|
|
@@ -39,6 +42,7 @@ if (!pkgName) {
|
|
|
39
42
|
process.exit(0);
|
|
40
43
|
}
|
|
41
44
|
|
|
45
|
+
/** Read our own version from @pizzapi/pizza's package.json. */
|
|
42
46
|
function getOwnVersion() {
|
|
43
47
|
try {
|
|
44
48
|
return JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8")).version;
|
|
@@ -47,38 +51,71 @@ function getOwnVersion() {
|
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Find the platform package's directory.
|
|
56
|
+
* Returns the path to its package.json directory, or null if not found.
|
|
57
|
+
*/
|
|
58
|
+
function findPlatformPkgDir() {
|
|
53
59
|
const parts = pkgName.split("/");
|
|
54
60
|
|
|
55
|
-
//
|
|
61
|
+
// Strategy 1: require.resolve
|
|
56
62
|
try {
|
|
57
63
|
const require = createRequire(join(__dirname, "..", "package.json"));
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
if (existsSync(binPath)) return true;
|
|
64
|
+
const pkgJsonPath = require.resolve(`${pkgName}/package.json`);
|
|
65
|
+
return dirname(pkgJsonPath);
|
|
61
66
|
} catch {}
|
|
62
67
|
|
|
63
|
-
//
|
|
68
|
+
// Strategy 2: sibling scoped package
|
|
64
69
|
{
|
|
65
|
-
const
|
|
66
|
-
|
|
70
|
+
const siblingDir = join(__dirname, "..", "..", parts[1]);
|
|
71
|
+
const siblingPkg = join(siblingDir, "package.json");
|
|
72
|
+
if (existsSync(siblingPkg)) return siblingDir;
|
|
67
73
|
}
|
|
68
74
|
|
|
69
|
-
//
|
|
75
|
+
// Strategy 3: walk up looking for node_modules
|
|
70
76
|
{
|
|
71
77
|
let dir = __dirname;
|
|
72
78
|
for (let i = 0; i < 10; i++) {
|
|
73
|
-
const candidate = join(dir, "node_modules", parts[0], parts[1]
|
|
74
|
-
|
|
79
|
+
const candidate = join(dir, "node_modules", parts[0], parts[1]);
|
|
80
|
+
const candidatePkg = join(candidate, "package.json");
|
|
81
|
+
if (existsSync(candidatePkg)) return candidate;
|
|
75
82
|
const parent = dirname(dir);
|
|
76
83
|
if (parent === dir) break;
|
|
77
84
|
dir = parent;
|
|
78
85
|
}
|
|
79
86
|
}
|
|
80
87
|
|
|
81
|
-
return
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Check that the platform binary exists AND its version matches ours.
|
|
93
|
+
* Returns: "ok" | "missing" | "stale"
|
|
94
|
+
*/
|
|
95
|
+
function checkPlatformPackage() {
|
|
96
|
+
const pkgDir = findPlatformPkgDir();
|
|
97
|
+
if (!pkgDir) return "missing";
|
|
98
|
+
|
|
99
|
+
// Verify binary file exists
|
|
100
|
+
const binName = process.platform === "win32" ? "pizza.exe" : "pizza";
|
|
101
|
+
const binPath = join(pkgDir, "bin", binName);
|
|
102
|
+
if (!existsSync(binPath)) return "missing";
|
|
103
|
+
|
|
104
|
+
// Verify version matches
|
|
105
|
+
const ownVersion = getOwnVersion();
|
|
106
|
+
if (!ownVersion) return "ok"; // can't check — assume fine
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const platformPkg = JSON.parse(readFileSync(join(pkgDir, "package.json"), "utf-8"));
|
|
110
|
+
if (platformPkg.version !== ownVersion) {
|
|
111
|
+
return "stale";
|
|
112
|
+
}
|
|
113
|
+
} catch {
|
|
114
|
+
// Can't read — assume stale to be safe
|
|
115
|
+
return "stale";
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return "ok";
|
|
82
119
|
}
|
|
83
120
|
|
|
84
121
|
/** Detect the package manager that invoked this install. */
|
|
@@ -104,47 +141,76 @@ function isGlobalInstall() {
|
|
|
104
141
|
return false;
|
|
105
142
|
}
|
|
106
143
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (binaryExists()) {
|
|
110
|
-
// All good — optionalDependencies did its job
|
|
111
|
-
process.exit(0);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const version = getOwnVersion();
|
|
115
|
-
const versionSpec = version ? `${pkgName}@${version}` : pkgName;
|
|
116
|
-
const pm = detectPackageManager();
|
|
117
|
-
const global = isGlobalInstall();
|
|
118
|
-
|
|
119
|
-
console.log(`[pizzapi] Platform package ${pkgName} was not installed automatically.`);
|
|
120
|
-
console.log(`[pizzapi] Installing with ${pm}...`);
|
|
121
|
-
|
|
122
|
-
try {
|
|
144
|
+
/** Run package manager install command. */
|
|
145
|
+
function installPlatformPackage(versionSpec, pm, isGlobal) {
|
|
123
146
|
if (pm === "yarn") {
|
|
124
|
-
const cmd =
|
|
147
|
+
const cmd = isGlobal ? `yarn global add ${versionSpec}` : `yarn add ${versionSpec}`;
|
|
125
148
|
execSync(cmd, { stdio: "inherit", env: process.env });
|
|
126
149
|
} else if (pm === "pnpm") {
|
|
127
|
-
const flag =
|
|
150
|
+
const flag = isGlobal ? " -g" : "";
|
|
128
151
|
execSync(`pnpm add${flag} ${versionSpec}`, { stdio: "inherit", env: process.env });
|
|
129
152
|
} else if (pm === "bun") {
|
|
130
|
-
const flag =
|
|
153
|
+
const flag = isGlobal ? " -g" : "";
|
|
131
154
|
execSync(`bun add${flag} ${versionSpec}`, { stdio: "inherit", env: process.env });
|
|
132
155
|
} else {
|
|
133
156
|
// npm
|
|
134
|
-
const flag =
|
|
157
|
+
const flag = isGlobal ? " -g" : "";
|
|
135
158
|
execSync(`npm install${flag} ${versionSpec}`, { stdio: "inherit", env: process.env });
|
|
136
159
|
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// --- Main ---
|
|
163
|
+
|
|
164
|
+
const status = checkPlatformPackage();
|
|
137
165
|
|
|
138
|
-
|
|
139
|
-
|
|
166
|
+
if (status === "ok") {
|
|
167
|
+
// Binary exists and version matches — nothing to do
|
|
168
|
+
process.exit(0);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const version = getOwnVersion();
|
|
172
|
+
const versionSpec = version ? `${pkgName}@${version}` : pkgName;
|
|
173
|
+
const pm = detectPackageManager();
|
|
174
|
+
const isGlobal = isGlobalInstall();
|
|
175
|
+
|
|
176
|
+
if (status === "stale") {
|
|
177
|
+
console.log(`[pizzapi] Platform package ${pkgName} is outdated (expected ${version}).`);
|
|
178
|
+
console.log(`[pizzapi] Upgrading with ${pm}...`);
|
|
179
|
+
} else {
|
|
180
|
+
console.log(`[pizzapi] Platform package ${pkgName} was not installed automatically.`);
|
|
181
|
+
console.log(`[pizzapi] Installing with ${pm}...`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
installPlatformPackage(versionSpec, pm, isGlobal);
|
|
186
|
+
|
|
187
|
+
const postStatus = checkPlatformPackage();
|
|
188
|
+
if (postStatus === "ok") {
|
|
189
|
+
console.log(`[pizzapi] Successfully installed ${pkgName}@${version}.`);
|
|
190
|
+
} else if (postStatus === "stale") {
|
|
191
|
+
// Installed but still wrong version — try removing first then reinstalling
|
|
192
|
+
console.log(`[pizzapi] Version mismatch persists — removing stale package and retrying...`);
|
|
193
|
+
try {
|
|
194
|
+
if (pm === "npm") {
|
|
195
|
+
const flag = isGlobal ? " -g" : "";
|
|
196
|
+
execSync(`npm rm${flag} ${pkgName}`, { stdio: "inherit", env: process.env });
|
|
197
|
+
}
|
|
198
|
+
installPlatformPackage(versionSpec, pm, isGlobal);
|
|
199
|
+
} catch {}
|
|
200
|
+
|
|
201
|
+
if (checkPlatformPackage() === "ok") {
|
|
202
|
+
console.log(`[pizzapi] Successfully installed ${pkgName}@${version}.`);
|
|
203
|
+
} else {
|
|
204
|
+
throw new Error("Version mismatch after reinstall");
|
|
205
|
+
}
|
|
140
206
|
} else {
|
|
141
207
|
throw new Error("Binary not found after install");
|
|
142
208
|
}
|
|
143
209
|
} catch (err) {
|
|
144
|
-
console.error(`[pizzapi] Failed to install ${pkgName} automatically.`);
|
|
210
|
+
console.error(`[pizzapi] Failed to install ${pkgName}@${version} automatically.`);
|
|
145
211
|
console.error(`[pizzapi] Please install it manually:`);
|
|
146
|
-
if (
|
|
147
|
-
console.error(`[pizzapi] npm install -g ${versionSpec}`);
|
|
212
|
+
if (isGlobal) {
|
|
213
|
+
console.error(`[pizzapi] npm rm -g ${pkgName} && npm install -g ${versionSpec}`);
|
|
148
214
|
} else {
|
|
149
215
|
console.error(`[pizzapi] npm install ${versionSpec}`);
|
|
150
216
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pizzapi/pizza",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35-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
|
"scripts": {
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
"LICENSE"
|
|
17
17
|
],
|
|
18
18
|
"optionalDependencies": {
|
|
19
|
-
"@pizzapi/cli-linux-x64": "0.1.
|
|
20
|
-
"@pizzapi/cli-linux-arm64": "0.1.
|
|
21
|
-
"@pizzapi/cli-darwin-x64": "0.1.
|
|
22
|
-
"@pizzapi/cli-darwin-arm64": "0.1.
|
|
23
|
-
"@pizzapi/cli-win32-x64": "0.1.
|
|
19
|
+
"@pizzapi/cli-linux-x64": "0.1.35-dev.1",
|
|
20
|
+
"@pizzapi/cli-linux-arm64": "0.1.35-dev.1",
|
|
21
|
+
"@pizzapi/cli-darwin-x64": "0.1.35-dev.1",
|
|
22
|
+
"@pizzapi/cli-darwin-arm64": "0.1.35-dev.1",
|
|
23
|
+
"@pizzapi/cli-win32-x64": "0.1.35-dev.1"
|
|
24
24
|
},
|
|
25
25
|
"engines": {
|
|
26
26
|
"node": ">=18"
|