pi-webapp 0.1.11 → 0.1.13
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/pi-webapp.mjs +29 -8
- package/dist/extension.js +17 -17
- package/docs/sentry-triage.md +75 -0
- package/docs/sentry.md +6 -0
- package/package.json +5 -3
- package/web/dist/.vite/manifest.json +17 -17
- package/web/dist/assets/{app-Bt_cH1DY.js → app-Boh5DRzv.js} +44 -44
- package/web/dist/assets/app.js +3 -3
- package/web/dist/assets/{graphql-DE5WRYe4.js → graphql-IPoCyjbx.js} +1 -1
- package/web/dist/assets/{http-d6mcwHrJ.js → http-k59Hanmf.js} +1 -1
- package/web/dist/assets/{php-RwSFu5XI.js → php-BG9P_ECJ.js} +1 -1
- package/web/dist/assets/{rst-Bcl8mngr.js → rst-Rxh6XweC.js} +1 -1
- package/web/dist/assets/{ruby-DiBb-yPX.js → ruby-vsmpeItB.js} +1 -1
- package/web/dist/assets/{svelte-CNtCH4kD.js → svelte-BbsEXeJC.js} +1 -1
- package/web/dist/assets/{vue-CRYi94cV.js → vue-DgFjFt96.js} +1 -1
- package/web/src/ui/README.md +0 -15
- package/web/src/ui/shared/README.md +0 -25
package/bin/pi-webapp.mjs
CHANGED
|
@@ -131,26 +131,43 @@ async function serve(pi, args) {
|
|
|
131
131
|
let runningUrl = null;
|
|
132
132
|
let buffer = "";
|
|
133
133
|
let killTimer;
|
|
134
|
+
let stopReason;
|
|
135
|
+
let forceStopRequested = false;
|
|
136
|
+
const instanceId = randomUUID();
|
|
137
|
+
const startedAt = performance.now();
|
|
138
|
+
const lifecycle = (event, fields = {}) => {
|
|
139
|
+
try {
|
|
140
|
+
console.error(JSON.stringify({ timestamp: new Date().toISOString(), event,
|
|
141
|
+
level: event === "pi_process_exit" && (!stopping || failed) ? "error" : "info",
|
|
142
|
+
instanceId, pid: process.pid, piPid: child.pid, uptimeMs: Math.round(performance.now() - startedAt), ...fields }));
|
|
143
|
+
} catch { /* Diagnostics must not interrupt process supervision. */ }
|
|
144
|
+
};
|
|
134
145
|
const devWatchers = [];
|
|
135
146
|
let devReloadTimer;
|
|
136
147
|
let devReloadCount = 0;
|
|
137
148
|
let devReloadCommand;
|
|
138
|
-
const shutdown = () => {
|
|
149
|
+
const shutdown = (reason) => {
|
|
139
150
|
if (stopping) return;
|
|
140
151
|
stopping = true;
|
|
152
|
+
stopReason = reason;
|
|
153
|
+
lifecycle("launcher_stop_requested", { reason });
|
|
141
154
|
child.stdin?.end();
|
|
142
|
-
killTimer = setTimeout(() =>
|
|
155
|
+
killTimer = setTimeout(() => {
|
|
156
|
+
forceStopRequested = true;
|
|
157
|
+
lifecycle("pi_force_stop", { reason, signal: "SIGTERM" });
|
|
158
|
+
child.kill("SIGTERM");
|
|
159
|
+
}, 5000);
|
|
143
160
|
killTimer.unref();
|
|
144
161
|
};
|
|
145
162
|
const fail = (message) => {
|
|
146
163
|
if (failed || ready) return;
|
|
147
164
|
failed = true;
|
|
148
165
|
notifyParent({ type: "error", message });
|
|
149
|
-
shutdown();
|
|
166
|
+
shutdown("startup_failure");
|
|
150
167
|
};
|
|
151
168
|
const startupTimer = setTimeout(() => fail(`Pi 启动超时。日志:${logPath}`), 60000);
|
|
152
169
|
const stopTimer = setInterval(async () => {
|
|
153
|
-
try { if ((await readFile(stopPath, "utf8")).trim() === nonce) shutdown(); }
|
|
170
|
+
try { if ((await readFile(stopPath, "utf8")).trim() === nonce) shutdown("stop_request"); }
|
|
154
171
|
catch { /* No stop request. */ }
|
|
155
172
|
if (stopping) return;
|
|
156
173
|
try {
|
|
@@ -158,12 +175,12 @@ async function serve(pi, args) {
|
|
|
158
175
|
const prepared = JSON.parse(await readFile(updatePath, "utf8"));
|
|
159
176
|
if (request.nonce === nonce && request.launcher === prepared.launcher && existsSync(request.launcher)) {
|
|
160
177
|
restartRequest = request;
|
|
161
|
-
shutdown();
|
|
178
|
+
shutdown("restart_request");
|
|
162
179
|
}
|
|
163
180
|
} catch { /* No valid restart request. */ }
|
|
164
181
|
}, 400);
|
|
165
|
-
process.on("SIGTERM", shutdown);
|
|
166
|
-
process.on("SIGINT", shutdown);
|
|
182
|
+
process.on("SIGTERM", () => shutdown("signal_sigterm"));
|
|
183
|
+
process.on("SIGINT", () => shutdown("signal_sigint"));
|
|
167
184
|
child.stdout?.on("data", (chunk) => {
|
|
168
185
|
if (failed) return;
|
|
169
186
|
buffer += chunk.toString("utf8");
|
|
@@ -210,6 +227,7 @@ async function serve(pi, args) {
|
|
|
210
227
|
if (closed || failed) return;
|
|
211
228
|
ready = true;
|
|
212
229
|
clearTimeout(startupTimer);
|
|
230
|
+
lifecycle("launcher_ready", { port: Number(url.port) });
|
|
213
231
|
notifyParent({ type: "ready", pid: process.pid, url: url.href });
|
|
214
232
|
for (const root of pluginRoots) {
|
|
215
233
|
try {
|
|
@@ -233,8 +251,11 @@ async function serve(pi, args) {
|
|
|
233
251
|
child.stdin?.write(JSON.stringify({ id: "list-commands", type: "get_commands" }) + "\n");
|
|
234
252
|
await new Promise((resolveExit) => {
|
|
235
253
|
child.once("error", (error) => { fail(`无法启动 Pi:${error.message}`); resolveExit(); });
|
|
236
|
-
child.once("close", (code) => {
|
|
254
|
+
child.once("close", (code, signal) => {
|
|
237
255
|
closed = true;
|
|
256
|
+
lifecycle("pi_process_exit", { ready, exitCode: code, signal,
|
|
257
|
+
reason: stopReason ?? (ready ? "unexpected_exit" : "startup_failure"), forceStopRequested,
|
|
258
|
+
port: runningUrl ? Number(new URL(runningUrl).port) : null });
|
|
238
259
|
if (!ready) fail(`Pi 提前退出(代码 ${code ?? "未知"})。日志:${logPath}`);
|
|
239
260
|
resolveExit();
|
|
240
261
|
});
|