@zenbu-labs/pixel 0.0.20 → 0.0.22
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/dist/bin.js +8 -8
- package/dist/devtools.d.ts +0 -5
- package/dist/devtools.js +1 -2
- package/dist/preload/index.d.ts +0 -1
- package/dist/react/native.d.ts +0 -1
- package/dist/react/reconciler-config.d.ts +0 -1
- package/dist/root.js +2 -2
- package/dist/sandbox.js +2 -1
- package/dist/ssh/index.d.ts +0 -6
- package/dist/ssh/index.js +15 -18
- package/dist/terminal/terminals/ghostty-script.js +2 -2
- package/dist/terminal/terminals/ghostty.js +2 -2
- package/dist/webview.js +2 -2
- package/package.json +8 -8
- package/scripts/postinstall.mjs +23 -8
package/dist/bin.js
CHANGED
|
@@ -27,12 +27,12 @@ function resolveEntry(given) {
|
|
|
27
27
|
}
|
|
28
28
|
const entry = node_path_1.default.join(target, main);
|
|
29
29
|
if (!node_fs_1.default.existsSync(entry)) {
|
|
30
|
-
fail(
|
|
30
|
+
fail(`${entry} does not exist. Build your app or point "main" in package.json at the built entry.`);
|
|
31
31
|
}
|
|
32
32
|
return entry;
|
|
33
33
|
}
|
|
34
34
|
if (!node_fs_1.default.existsSync(target))
|
|
35
|
-
fail(`
|
|
35
|
+
fail(`no such file ${target}`);
|
|
36
36
|
return target;
|
|
37
37
|
}
|
|
38
38
|
function appName(dir) {
|
|
@@ -55,7 +55,7 @@ function appDir(entry) {
|
|
|
55
55
|
function electronBinary() {
|
|
56
56
|
const dist = node_path_1.default.resolve(__dirname, "..", "electron", "dist");
|
|
57
57
|
if (!node_fs_1.default.existsSync(node_path_1.default.join(dist, ".zenbu-electron-sha256"))) {
|
|
58
|
-
fail("
|
|
58
|
+
fail("the patched electron build is not installed. Run `node node_modules/@zenbu-labs/pixel/scripts/postinstall.mjs` (npm normally runs it for you on install).");
|
|
59
59
|
}
|
|
60
60
|
return process.platform === "darwin"
|
|
61
61
|
? node_path_1.default.join(dist, "Electron.app", "Contents", "MacOS", "pixel")
|
|
@@ -74,7 +74,7 @@ function ownTty() {
|
|
|
74
74
|
return out;
|
|
75
75
|
}
|
|
76
76
|
catch { }
|
|
77
|
-
return fail("
|
|
77
|
+
return fail("could not work out which tty this shell is on");
|
|
78
78
|
}
|
|
79
79
|
async function main() {
|
|
80
80
|
const args = process.argv.slice(2);
|
|
@@ -82,22 +82,22 @@ async function main() {
|
|
|
82
82
|
const own = passthrough < 0 ? args : args.slice(0, passthrough);
|
|
83
83
|
const appArgs = passthrough < 0 ? [] : args.slice(passthrough + 1);
|
|
84
84
|
if (own.includes("--help") || own.includes("-h")) {
|
|
85
|
-
process.stdout.write("
|
|
85
|
+
process.stdout.write("usage: pixel [entry|dir] [-- app args]\n Runs an app's main file inside the pixel runtime, in this terminal pane.\n");
|
|
86
86
|
return 0;
|
|
87
87
|
}
|
|
88
88
|
const stray = own.slice(1).find((arg) => arg.startsWith("-")) ?? own.find((arg) => arg.startsWith("-"));
|
|
89
89
|
if (stray) {
|
|
90
|
-
fail(`
|
|
90
|
+
fail(`unknown option ${stray}. pixel takes an entry and nothing else; put your app's arguments after --`);
|
|
91
91
|
}
|
|
92
92
|
if (own.length > 1)
|
|
93
|
-
fail(`
|
|
93
|
+
fail(`unexpected ${own[1]}; put your app's arguments after --`);
|
|
94
94
|
const entry = resolveEntry(own[0] ?? ".");
|
|
95
95
|
const tty = process.env.PIXEL_TTY ?? ownTty();
|
|
96
96
|
const owner = (0, instances_1.findOwner)(tty);
|
|
97
97
|
const announced = owner ? (0, instances_1.announceGuest)(owner, appName(appDir(entry))) : null;
|
|
98
98
|
if (!owner && !process.env.PIXEL_EMBED) {
|
|
99
99
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
100
|
-
fail("
|
|
100
|
+
fail("tty required");
|
|
101
101
|
}
|
|
102
102
|
const check = await (0, terminal_1.checkTerminal)((0, terminal_1.detect)());
|
|
103
103
|
if (check.graphics === "unsupported") {
|
package/dist/devtools.d.ts
CHANGED
|
@@ -18,16 +18,11 @@ export declare function DevtoolsDockPane({ rect, dock, rem, theme, surface, divi
|
|
|
18
18
|
onDividerHover(hovering: boolean): void;
|
|
19
19
|
}): import("react").JSX.Element;
|
|
20
20
|
export interface DevToolsProps {
|
|
21
|
-
/** [placeholder copy: The WebView to inspect, as the ref you gave it or the handle itself.] */
|
|
22
21
|
target: RefObject<WebViewHandle | null> | WebViewHandle;
|
|
23
22
|
style?: Style;
|
|
24
23
|
dock?: DevtoolsDock;
|
|
25
|
-
/** [placeholder copy: Devtools panel to show once open, for example "console" or "elements".] */
|
|
26
24
|
panel?: string;
|
|
27
|
-
/** [placeholder copy: The devtools toolbar asked to close or to dock elsewhere. Unmount or change dock in response.] */
|
|
28
25
|
onAction?(action: "close" | "dock-bottom" | "dock-right"): void;
|
|
29
|
-
/** [placeholder copy: Keep showing the last frame, stretched, while the pane changes size instead of clearing until devtools repaint. Defaults to true.] */
|
|
30
26
|
keepFrame?: boolean;
|
|
31
27
|
}
|
|
32
|
-
/** [placeholder copy: Renders a WebView's devtools wherever this sits in the tree. Mounting opens them, unmounting closes them.] */
|
|
33
28
|
export declare function DevTools({ target, style, dock, panel, onAction, keepFrame }: DevToolsProps): import("react").JSX.Element;
|
package/dist/devtools.js
CHANGED
|
@@ -45,11 +45,10 @@ function resolveEntry(target) {
|
|
|
45
45
|
const handle = "current" in target ? target.current : target;
|
|
46
46
|
return handle ? registry_1.handleEntries.get(handle) ?? null : null;
|
|
47
47
|
}
|
|
48
|
-
/** [placeholder copy: Renders a WebView's devtools wherever this sits in the tree. Mounting opens them, unmounting closes them.] */
|
|
49
48
|
function DevTools({ target, style, dock = "right", panel, onAction, keepFrame = true }) {
|
|
50
49
|
const registry = (0, react_1.useContext)(registry_1.RootContext);
|
|
51
50
|
if (!registry) {
|
|
52
|
-
throw new Error("
|
|
51
|
+
throw new Error("<DevTools> has to be rendered by a root from createRoot()");
|
|
53
52
|
}
|
|
54
53
|
const boxRef = (0, react_1.useRef)(null);
|
|
55
54
|
const rect = (0, layout_1.useNodeRect)(boxRef, registry);
|
package/dist/preload/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/// <reference path="../../electron/electron.d.ts" preserve="true" />
|
|
2
|
-
/** [placeholder copy: The terminal's colours as rgb triples. `ansi` has 16 slots and is null where the terminal did not report a colour.] */
|
|
3
2
|
export interface TerminalTheme {
|
|
4
3
|
background: number[];
|
|
5
4
|
foreground: number[];
|
package/dist/react/native.d.ts
CHANGED
|
@@ -51,7 +51,6 @@ export interface HostOptions {
|
|
|
51
51
|
socket: string;
|
|
52
52
|
pane: string;
|
|
53
53
|
name: string;
|
|
54
|
-
/** [placeholder copy: Set when the host is not pixel: frames are drawn into this terminal as kitty virtual placements the host positions.] */
|
|
55
54
|
tty?: string;
|
|
56
55
|
}
|
|
57
56
|
export interface HighlightSpan {
|
|
@@ -65,7 +65,6 @@ export interface ContainerSelection {
|
|
|
65
65
|
export interface BoxProps {
|
|
66
66
|
style?: Style;
|
|
67
67
|
id?: string;
|
|
68
|
-
/** [placeholder copy: Lays the box out as nothing and paints none of it, keeping its children mounted.] */
|
|
69
68
|
hidden?: boolean;
|
|
70
69
|
onClick?: (event: ClickEvent) => void;
|
|
71
70
|
onClickOutside?: (event: ClickEvent) => void;
|
package/dist/root.js
CHANGED
|
@@ -62,7 +62,7 @@ function waitForSocket(socket) {
|
|
|
62
62
|
}
|
|
63
63
|
function createRoot(options = {}) {
|
|
64
64
|
if (!electron_1.app.isReady()) {
|
|
65
|
-
throw new Error("
|
|
65
|
+
throw new Error("createRoot() needs electron to be ready. Run your entry with `pixel .`, which waits for app.whenReady() before loading it.");
|
|
66
66
|
}
|
|
67
67
|
const env = options.sessionEnv ?? process.env;
|
|
68
68
|
const terminal = (0, terminal_1.detect)(env);
|
|
@@ -310,7 +310,7 @@ function createRoot(options = {}) {
|
|
|
310
310
|
root.render((0, jsx_runtime_1.jsx)(webview_1.WebView, { ref: pageRef, src: url, style: { width: "100%", height: "100%" }, ...options }));
|
|
311
311
|
});
|
|
312
312
|
if (!pageRef.current)
|
|
313
|
-
throw new Error("
|
|
313
|
+
throw new Error("the page did not mount");
|
|
314
314
|
return pageRef.current;
|
|
315
315
|
};
|
|
316
316
|
const root = {
|
package/dist/sandbox.js
CHANGED
|
@@ -11,7 +11,8 @@ const node_child_process_1 = require("node:child_process");
|
|
|
11
11
|
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
12
12
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
13
|
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
-
|
|
14
|
+
// probably need app name injection support here
|
|
15
|
+
const REFUSAL = `the codex sandbox blocks commands that are needed to determine the terminal pane the command is ran from.]
|
|
15
16
|
Re-run this command with escalated permissions.`;
|
|
16
17
|
function inCodex() {
|
|
17
18
|
return Boolean(process.env.CODEX_THREAD_ID ?? process.env.CODEX_PERMISSION_PROFILE);
|
package/dist/ssh/index.d.ts
CHANGED
|
@@ -10,7 +10,6 @@ export interface RemoteBundle {
|
|
|
10
10
|
}
|
|
11
11
|
export type StatusLine = (line: string) => void;
|
|
12
12
|
export interface SshOptions {
|
|
13
|
-
/** [placeholder copy: Whether ssh may use this process's terminal for password and host key prompts. Off when called from inside a running app, where the terminal is already taken; ssh then fails instead of prompting.] */
|
|
14
13
|
terminal?: boolean;
|
|
15
14
|
}
|
|
16
15
|
export declare function parseSshTarget(target: string): {
|
|
@@ -26,20 +25,15 @@ export declare function resolveSshTarget(target: string): ResolvedTarget;
|
|
|
26
25
|
export declare function validateSshTarget(target: string): void;
|
|
27
26
|
export declare function openSshTunnel(target: string, status: StatusLine, options?: SshOptions): Promise<SshTunnel>;
|
|
28
27
|
export interface SshSessionOptions extends SshOptions {
|
|
29
|
-
/** [placeholder copy: Where to connect, as you would type it after ssh: user@host, host:port, a full ssh command with flags, or a shell alias.] */
|
|
30
28
|
target: string;
|
|
31
|
-
/** [placeholder copy: A directory to install and start on the host. It must hold an executable start that prints READY <url>; setup and stop are optional.] */
|
|
32
29
|
bundle?: string | null;
|
|
33
|
-
/** [placeholder copy: Directory on the host that bundles are installed under.] */
|
|
34
30
|
remoteBase?: string | null;
|
|
35
31
|
status?: StatusLine;
|
|
36
32
|
}
|
|
37
33
|
export interface SshSession {
|
|
38
34
|
destination: string;
|
|
39
35
|
socksPort: number;
|
|
40
|
-
/** [placeholder copy: The url the bundle's start script announced, when a bundle was given.] */
|
|
41
36
|
url: string | undefined;
|
|
42
|
-
/** [placeholder copy: Props for the WebView that should browse through this host: spread them onto it.] */
|
|
43
37
|
view: {
|
|
44
38
|
proxy: string;
|
|
45
39
|
partition: string;
|
package/dist/ssh/index.js
CHANGED
|
@@ -21,7 +21,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
21
21
|
function parseSshTarget(target) {
|
|
22
22
|
const match = /^([A-Za-z0-9._-]+@)?([A-Za-z0-9._-]+)(:(\d+))?$/.exec(target);
|
|
23
23
|
if (!match) {
|
|
24
|
-
throw new Error(`
|
|
24
|
+
throw new Error(`invalid ssh target ${target} (user@host, host, user@host:port, or a shell alias for ssh)`);
|
|
25
25
|
}
|
|
26
26
|
return { destination: `${match[1] ?? ""}${match[2]}`, sshPort: match[4] ?? null };
|
|
27
27
|
}
|
|
@@ -62,12 +62,12 @@ function parseSshWords(words, target) {
|
|
|
62
62
|
continue;
|
|
63
63
|
}
|
|
64
64
|
if (found) {
|
|
65
|
-
throw new Error(`
|
|
65
|
+
throw new Error(`invalid ssh target ${target} (both ${found} and ${token} look like destinations)`);
|
|
66
66
|
}
|
|
67
67
|
found = token;
|
|
68
68
|
}
|
|
69
69
|
if (!found)
|
|
70
|
-
throw new Error(`
|
|
70
|
+
throw new Error(`invalid ssh target ${target} (no destination)`);
|
|
71
71
|
const { destination, sshPort } = parseSshTarget(found);
|
|
72
72
|
return { destination, hostArgs: [...hostArgs, ...(sshPort ? ["-p", sshPort] : [])] };
|
|
73
73
|
}
|
|
@@ -151,7 +151,7 @@ async function openSshTunnel(target, status, options = {}) {
|
|
|
151
151
|
});
|
|
152
152
|
if (code !== 0) {
|
|
153
153
|
const detail = stderr.filter(Boolean).join("\n");
|
|
154
|
-
throw new Error(`
|
|
154
|
+
throw new Error(`ssh to ${destination} failed${detail ? `: ${detail}` : ""}`);
|
|
155
155
|
}
|
|
156
156
|
await waitForSocks(socksPort, destination);
|
|
157
157
|
status(`connected ${destination}`);
|
|
@@ -170,9 +170,6 @@ async function openSshTunnel(target, status, options = {}) {
|
|
|
170
170
|
},
|
|
171
171
|
};
|
|
172
172
|
}
|
|
173
|
-
// The whole ssh mode in one step: tunnel, then bundle, then the props a page
|
|
174
|
-
// needs to browse through the host. Stopping runs in reverse and also happens
|
|
175
|
-
// when the process exits.
|
|
176
173
|
async function connectSsh(options) {
|
|
177
174
|
const status = options.status ?? (() => { });
|
|
178
175
|
const terminal = options.terminal ?? true;
|
|
@@ -222,19 +219,19 @@ function validateBundleDir(dir) {
|
|
|
222
219
|
stat = node_fs_1.default.statSync(dir);
|
|
223
220
|
}
|
|
224
221
|
catch {
|
|
225
|
-
throw new Error(`
|
|
222
|
+
throw new Error(`bundle ${dir} does not exist`);
|
|
226
223
|
}
|
|
227
224
|
if (!stat.isDirectory())
|
|
228
|
-
throw new Error(`
|
|
225
|
+
throw new Error(`bundle ${dir} is not a directory`);
|
|
229
226
|
let start;
|
|
230
227
|
try {
|
|
231
228
|
start = node_fs_1.default.statSync(node_path_1.default.join(dir, "start"));
|
|
232
229
|
}
|
|
233
230
|
catch {
|
|
234
|
-
throw new Error(`
|
|
231
|
+
throw new Error(`bundle ${dir} has no start script`);
|
|
235
232
|
}
|
|
236
233
|
if (!start.isFile() || !(start.mode & 0o111)) {
|
|
237
|
-
throw new Error(`
|
|
234
|
+
throw new Error(`bundle ${dir}/start is not executable`);
|
|
238
235
|
}
|
|
239
236
|
}
|
|
240
237
|
const READY_TIMEOUT_MS = 120_000;
|
|
@@ -303,12 +300,12 @@ function upload(tunnel, dir, remoteDir) {
|
|
|
303
300
|
maxBuffer: 256 * 1024 * 1024,
|
|
304
301
|
});
|
|
305
302
|
if (tar.status !== 0 || !tar.stdout)
|
|
306
|
-
throw new Error(`
|
|
303
|
+
throw new Error(`could not pack ${dir}`);
|
|
307
304
|
const result = run(tunnel, `mkdir -p "${remoteDir}" && tar -xz -C "${remoteDir}"`, {
|
|
308
305
|
input: tar.stdout,
|
|
309
306
|
});
|
|
310
307
|
if (result.status !== 0) {
|
|
311
|
-
throw new Error(`
|
|
308
|
+
throw new Error(`could not upload the bundle to ${tunnel.destination}`);
|
|
312
309
|
}
|
|
313
310
|
}
|
|
314
311
|
function setup(tunnel, remoteDir, terminal, status) {
|
|
@@ -319,7 +316,7 @@ function setup(tunnel, remoteDir, terminal, status) {
|
|
|
319
316
|
status(line);
|
|
320
317
|
}
|
|
321
318
|
if (result.status !== 0) {
|
|
322
|
-
throw new Error(`
|
|
319
|
+
throw new Error(`the bundle's setup script failed on ${tunnel.destination}`);
|
|
323
320
|
}
|
|
324
321
|
}
|
|
325
322
|
function launch(tunnel, name, remoteDir, status) {
|
|
@@ -358,7 +355,7 @@ function launch(tunnel, name, remoteDir, status) {
|
|
|
358
355
|
}
|
|
359
356
|
};
|
|
360
357
|
const timer = setTimeout(() => {
|
|
361
|
-
finish(new Error(
|
|
358
|
+
finish(new Error(`${name} never printed READY <url>\n${tail.join("\n")}`));
|
|
362
359
|
}, READY_TIMEOUT_MS);
|
|
363
360
|
const sawLine = (line) => {
|
|
364
361
|
tail.push(line);
|
|
@@ -369,7 +366,7 @@ function launch(tunnel, name, remoteDir, status) {
|
|
|
369
366
|
return;
|
|
370
367
|
const url = pageUrl(ready[1]);
|
|
371
368
|
if (!url) {
|
|
372
|
-
finish(new Error(
|
|
369
|
+
finish(new Error(`${name} printed READY ${ready[1]}, which is not an http(s) url`));
|
|
373
370
|
return;
|
|
374
371
|
}
|
|
375
372
|
status(`${name} is up at ${url}`);
|
|
@@ -390,7 +387,7 @@ function launch(tunnel, name, remoteDir, status) {
|
|
|
390
387
|
child.once("close", (code) => {
|
|
391
388
|
if (buffer.trim())
|
|
392
389
|
sawLine(buffer.trim());
|
|
393
|
-
finish(new Error(
|
|
390
|
+
finish(new Error(`${name} exited with code ${code} before printing READY <url>\n${tail.join("\n")}`));
|
|
394
391
|
});
|
|
395
392
|
});
|
|
396
393
|
}
|
|
@@ -430,7 +427,7 @@ function waitForSocks(port, destination) {
|
|
|
430
427
|
const socket = node_net_1.default.connect(port, "127.0.0.1");
|
|
431
428
|
const timer = setTimeout(() => {
|
|
432
429
|
socket.destroy();
|
|
433
|
-
reject(new Error(`
|
|
430
|
+
reject(new Error(`the ssh proxy for ${destination} never started listening`));
|
|
434
431
|
}, 5000);
|
|
435
432
|
socket.once("connect", () => {
|
|
436
433
|
clearTimeout(timer);
|
|
@@ -61,13 +61,13 @@ function send(pid, eventClass, eventId, params) {
|
|
|
61
61
|
const failure = Ref();
|
|
62
62
|
const reply = event.sendEventWithOptionsTimeoutError(WAIT_FOR_REPLY, 10, failure);
|
|
63
63
|
if (reply.isNil()) {
|
|
64
|
-
throw new Error("
|
|
64
|
+
throw new Error("Ghostty (pid " + pid + ") did not answer: " + ObjC.unwrap(failure[0].localizedDescription) );
|
|
65
65
|
}
|
|
66
66
|
const number = reply.paramDescriptorForKeyword(code("errn"));
|
|
67
67
|
if (!number.isNil()) {
|
|
68
68
|
const message = reply.paramDescriptorForKeyword(code("errs"));
|
|
69
69
|
const detail = message.isNil() ? "" : ": " + ObjC.unwrap(message.stringValue);
|
|
70
|
-
const error = new Error("
|
|
70
|
+
const error = new Error("Ghostty (pid " + pid + ") refused the request (" + number.int32Value + ")" + detail );
|
|
71
71
|
error.code = number.int32Value;
|
|
72
72
|
throw error;
|
|
73
73
|
}
|
|
@@ -107,9 +107,9 @@ const ghostty = (env, run) => {
|
|
|
107
107
|
if (running.length === 1)
|
|
108
108
|
return running[0];
|
|
109
109
|
if (running.length === 0) {
|
|
110
|
-
throw new Error("
|
|
110
|
+
throw new Error("Ghostty is not running, so there is no window to script");
|
|
111
111
|
}
|
|
112
|
-
throw new Error(
|
|
112
|
+
throw new Error(`${running.length} Ghostty processes are running (pids ${running.join(", ")}) and this shell is not inside any of them, so we cannot tell which one to script`);
|
|
113
113
|
}
|
|
114
114
|
async function ghosttyCommand(command, args, tty = null) {
|
|
115
115
|
return osascript(ghostty_script_1.GHOSTTY_SCRIPT, [String(await ownerPid(tty)), command, ...args]);
|
package/dist/webview.js
CHANGED
|
@@ -361,7 +361,7 @@ exports.WebView = (0, react_1.forwardRef)(function WebView(props, ref) {
|
|
|
361
361
|
const host = () => {
|
|
362
362
|
const current = hostRef.current;
|
|
363
363
|
if (!current) {
|
|
364
|
-
throw new Error("
|
|
364
|
+
throw new Error("this WebView has already been unmounted]");
|
|
365
365
|
}
|
|
366
366
|
return current;
|
|
367
367
|
};
|
|
@@ -430,7 +430,7 @@ exports.WebView = (0, react_1.forwardRef)(function WebView(props, ref) {
|
|
|
430
430
|
width: page.width,
|
|
431
431
|
height: page.height,
|
|
432
432
|
cornerRadius: props.style?.cornerRadius,
|
|
433
|
-
background: theme.bg,
|
|
433
|
+
background: props.browserWindowOptions?.transparent ? undefined : theme.bg,
|
|
434
434
|
opaque: !props.browserWindowOptions?.transparent,
|
|
435
435
|
}, onPointer: (event) => {
|
|
436
436
|
if (menuRef.current) {
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenbu-labs/pixel",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.22",
|
|
4
|
+
"description": "Build graphical applications in the terminal",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/zenbu-labs/
|
|
9
|
-
"directory": "packages/pixel"
|
|
8
|
+
"url": "git+https://github.com/zenbu-labs/terminal-browser.git",
|
|
9
|
+
"directory": "pixel/packages/pixel"
|
|
10
10
|
},
|
|
11
11
|
"main": "dist/index.js",
|
|
12
12
|
"types": "dist/index.d.ts",
|
|
@@ -58,10 +58,10 @@
|
|
|
58
58
|
"react": "^18.3.1"
|
|
59
59
|
},
|
|
60
60
|
"optionalDependencies": {
|
|
61
|
-
"@zenbu-labs/pixel-native-darwin-arm64": "0.0.
|
|
62
|
-
"@zenbu-labs/pixel-native-darwin-x64": "0.0.
|
|
63
|
-
"@zenbu-labs/pixel-native-linux-arm64": "0.0.
|
|
64
|
-
"@zenbu-labs/pixel-native-linux-x64": "0.0.
|
|
61
|
+
"@zenbu-labs/pixel-native-darwin-arm64": "0.0.22",
|
|
62
|
+
"@zenbu-labs/pixel-native-darwin-x64": "0.0.22",
|
|
63
|
+
"@zenbu-labs/pixel-native-linux-arm64": "0.0.22",
|
|
64
|
+
"@zenbu-labs/pixel-native-linux-x64": "0.0.22"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@types/node": "^22.0.0",
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -25,9 +25,15 @@ if (!platform) {
|
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
// Patched electron builds are published as electron-v<version> releases. Newer ones live on
|
|
29
|
+
// the terminal-browser repo, where pixel now lives; older ones stayed on the archived pixel repo.
|
|
30
|
+
const mirrors = process.env.PIXEL_ELECTRON_MIRROR
|
|
31
|
+
? [process.env.PIXEL_ELECTRON_MIRROR]
|
|
32
|
+
: [
|
|
33
|
+
`https://github.com/zenbu-labs/terminal-browser/releases/download/electron-v${version}`,
|
|
34
|
+
`https://github.com/zenbu-labs/pixel/releases/download/electron-v${version}`,
|
|
35
|
+
];
|
|
36
|
+
let mirror = mirrors[0];
|
|
31
37
|
const zipName = `electron-v${version}-${platform}.zip`;
|
|
32
38
|
|
|
33
39
|
async function fetchBytes(url) {
|
|
@@ -59,13 +65,22 @@ function readMarker(file) {
|
|
|
59
65
|
fs.mkdirSync(electronDir, { recursive: true });
|
|
60
66
|
|
|
61
67
|
let shasums;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
let lastError;
|
|
69
|
+
for (const candidate of mirrors) {
|
|
70
|
+
try {
|
|
71
|
+
shasums = (await fetchBytes(`${candidate}/SHASUMS256.txt`)).toString("utf8");
|
|
72
|
+
mirror = candidate;
|
|
73
|
+
break;
|
|
74
|
+
} catch (error) {
|
|
75
|
+
lastError = error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (!shasums) {
|
|
79
|
+
const error = lastError;
|
|
65
80
|
if (skipBinary && fs.existsSync(typesFile)) process.exit(0);
|
|
66
81
|
process.stderr.write(
|
|
67
|
-
`pixel:
|
|
68
|
-
`This release of pixel is built against electron ${version}; a newer pixel may be needed
|
|
82
|
+
`pixel: no patched electron v${version} is published (${error.message}). ` +
|
|
83
|
+
`This release of pixel is built against electron ${version}; a newer pixel may be needed.\n`,
|
|
69
84
|
);
|
|
70
85
|
process.exit(1);
|
|
71
86
|
}
|