@elaraai/e3-ui-cli 1.0.28

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 (64) hide show
  1. package/CLA.md +26 -0
  2. package/CONTRIBUTING.md +28 -0
  3. package/LICENSE.md +31 -0
  4. package/README.md +158 -0
  5. package/bin/e3-ui.mjs +13 -0
  6. package/dist/app/assets/dm-sans-latin-ext-wght-normal-BOFOeGcA.woff2 +0 -0
  7. package/dist/app/assets/dm-sans-latin-wght-normal-Xz1IZZA0.woff2 +0 -0
  8. package/dist/app/assets/engine-Daqj4eDD-BQb68g_1.js +4 -0
  9. package/dist/app/assets/index-30g1JIHt.js +2255 -0
  10. package/dist/app/assets/index-CYR-0Grb.css +1 -0
  11. package/dist/app/assets/inter-tight-cyrillic-ext-wght-normal-okcGN4Nq.woff2 +0 -0
  12. package/dist/app/assets/inter-tight-cyrillic-wght-normal-BS41q_Tv.woff2 +0 -0
  13. package/dist/app/assets/inter-tight-greek-ext-wght-normal-DQgQPNk4.woff2 +0 -0
  14. package/dist/app/assets/inter-tight-greek-wght-normal-sS1B39LI.woff2 +0 -0
  15. package/dist/app/assets/inter-tight-latin-ext-wght-normal-B4u9PlvR.woff2 +0 -0
  16. package/dist/app/assets/inter-tight-latin-wght-normal-DX-nOvPD.woff2 +0 -0
  17. package/dist/app/assets/inter-tight-vietnamese-wght-normal-TKKdAiBA.woff2 +0 -0
  18. package/dist/app/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  19. package/dist/app/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  20. package/dist/app/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  21. package/dist/app/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  22. package/dist/app/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  23. package/dist/app/index.html +13 -0
  24. package/dist/browser.d.ts +88 -0
  25. package/dist/browser.d.ts.map +1 -0
  26. package/dist/browser.js +249 -0
  27. package/dist/browser.js.map +1 -0
  28. package/dist/capture.d.ts +80 -0
  29. package/dist/capture.d.ts.map +1 -0
  30. package/dist/capture.js +275 -0
  31. package/dist/capture.js.map +1 -0
  32. package/dist/cli.d.ts +6 -0
  33. package/dist/cli.d.ts.map +1 -0
  34. package/dist/cli.js +70 -0
  35. package/dist/cli.js.map +1 -0
  36. package/dist/commands/shot.d.ts +42 -0
  37. package/dist/commands/shot.d.ts.map +1 -0
  38. package/dist/commands/shot.js +134 -0
  39. package/dist/commands/shot.js.map +1 -0
  40. package/dist/e3-server.d.ts +21 -0
  41. package/dist/e3-server.d.ts.map +1 -0
  42. package/dist/e3-server.js +34 -0
  43. package/dist/e3-server.js.map +1 -0
  44. package/dist/index.d.ts +17 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +17 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/load-source.d.ts +21 -0
  49. package/dist/load-source.d.ts.map +1 -0
  50. package/dist/load-source.js +163 -0
  51. package/dist/load-source.js.map +1 -0
  52. package/dist/payload.d.ts +26 -0
  53. package/dist/payload.d.ts.map +1 -0
  54. package/dist/payload.js +87 -0
  55. package/dist/payload.js.map +1 -0
  56. package/dist/render.d.ts +80 -0
  57. package/dist/render.d.ts.map +1 -0
  58. package/dist/render.js +79 -0
  59. package/dist/render.js.map +1 -0
  60. package/dist/shot-payload.d.ts +31 -0
  61. package/dist/shot-payload.d.ts.map +1 -0
  62. package/dist/shot-payload.js +6 -0
  63. package/dist/shot-payload.js.map +1 -0
  64. package/package.json +82 -0
@@ -0,0 +1 @@
1
+ @font-face{font-family:DM Sans Variable;font-style:normal;font-display:swap;font-weight:100 1000;src:url(./dm-sans-latin-ext-wght-normal-BOFOeGcA.woff2) format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:DM Sans Variable;font-style:normal;font-display:swap;font-weight:100 1000;src:url(./dm-sans-latin-wght-normal-Xz1IZZA0.woff2) format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-cyrillic-ext-wght-normal-okcGN4Nq.woff2) format("woff2-variations");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-cyrillic-wght-normal-BS41q_Tv.woff2) format("woff2-variations");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-greek-ext-wght-normal-DQgQPNk4.woff2) format("woff2-variations");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-greek-wght-normal-sS1B39LI.woff2) format("woff2-variations");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-vietnamese-wght-normal-TKKdAiBA.woff2) format("woff2-variations");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-latin-ext-wght-normal-B4u9PlvR.woff2) format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter Tight Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./inter-tight-latin-wght-normal-DX-nOvPD.woff2) format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(data:font/woff2;base64,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) format("woff2-variations");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(./jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2) format("woff2-variations");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(./jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2) format("woff2-variations");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(./jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2) format("woff2-variations");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(./jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2) format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:JetBrains Mono Variable;font-style:normal;font-display:swap;font-weight:100 800;src:url(./jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2) format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>e3-ui shot</title>
7
+ <script type="module" crossorigin src="./assets/index-30g1JIHt.js"></script>
8
+ <link rel="stylesheet" crossorigin href="./assets/index-CYR-0Grb.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ import { type Browser } from 'playwright-core';
6
+ /** The env vars honored as an explicit browser override, in precedence order. */
7
+ export declare const BROWSER_ENV_VARS: readonly ["E3_UI_CHROMIUM_PATH", "PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH"];
8
+ /**
9
+ * Return the explicit browser override from the environment, if any.
10
+ *
11
+ * @param env - Environment to read (injectable for tests)
12
+ * @returns The overriding executable path, or `null` when unset
13
+ */
14
+ export declare function envBrowserPath(env?: NodeJS.ProcessEnv): string | null;
15
+ /**
16
+ * Candidate system-browser executables for a platform, most-preferred first.
17
+ *
18
+ * @param platform - `process.platform` value (injectable for tests)
19
+ * @param env - Environment for Windows `%ProgramFiles%`-style roots
20
+ * @returns Absolute candidate paths (existence NOT yet checked)
21
+ */
22
+ export declare function systemBrowserCandidates(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): string[];
23
+ /**
24
+ * Whether a candidate is a real browser binary rather than Ubuntu's snap shim.
25
+ * Rejects a path whose realpath resolves under `/snap/`, or whose file starts
26
+ * with `#!` (`/usr/bin/chromium-browser` on Ubuntu is a `#!/bin/sh` script
27
+ * that execs the confined snap — useless for automation).
28
+ *
29
+ * @param executablePath - Existing candidate path to vet
30
+ * @returns True when the candidate is launchable
31
+ */
32
+ export declare function isRealBrowserBinary(executablePath: string): boolean;
33
+ /**
34
+ * Find the first usable system browser.
35
+ *
36
+ * @param platform - `process.platform` value (injectable for tests)
37
+ * @param env - Environment for Windows roots
38
+ * @returns The executable path, or `null` when none is usable
39
+ */
40
+ export declare function findSystemBrowser(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): string | null;
41
+ /** How the launched browser was obtained (surfaced by `doctor` and errors). */
42
+ export type BrowserSource = {
43
+ kind: 'env';
44
+ executablePath: string;
45
+ } | {
46
+ kind: 'managed';
47
+ } | {
48
+ kind: 'system';
49
+ executablePath: string;
50
+ };
51
+ /** One-line remediation block shared by the launch error and `doctor`. */
52
+ export declare function launchRemediation(): string;
53
+ /**
54
+ * Launch headless Chromium via the acquisition cascade.
55
+ *
56
+ * @param env - Environment to read overrides from (injectable for tests)
57
+ * @returns The browser plus which source of the cascade provided it
58
+ * @throws When no browser can be launched; the message carries the full
59
+ * remediation (install-browser / E3_UI_CHROMIUM_PATH / doctor)
60
+ */
61
+ export declare function launchBrowser(env?: NodeJS.ProcessEnv): Promise<{
62
+ browser: Browser;
63
+ source: BrowserSource;
64
+ }>;
65
+ /**
66
+ * Download the version-matched `chromium-headless-shell` into playwright's
67
+ * managed cache (honors `PLAYWRIGHT_BROWSERS_PATH`), by spawning the bundled
68
+ * playwright-core CLI: `install --only-shell chromium`. The shell build is the
69
+ * one a bare headless launch selects, and is ~100 MB lighter than full
70
+ * Chromium with no X11/D-Bus system libraries.
71
+ *
72
+ * @param opts - `withDeps` also installs OS packages (Linux only; skipped with
73
+ * a note elsewhere — Windows/macOS need no system libraries)
74
+ * @returns The spawned process exit code
75
+ */
76
+ export declare function installBrowser(opts?: {
77
+ withDeps?: boolean;
78
+ }): Promise<number>;
79
+ /**
80
+ * Diagnose the browser setup: report env overrides, run the real launch
81
+ * cascade against `about:blank`, and print what worked — or per-OS remediation
82
+ * for what didn't.
83
+ *
84
+ * @param env - Environment to diagnose (injectable for tests)
85
+ * @returns Process exit code (0 healthy, 1 not)
86
+ */
87
+ export declare function doctor(env?: NodeJS.ProcessEnv): Promise<number>;
88
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6BH,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAMzD,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,yEAA0E,CAAC;AAExG;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,IAAI,CAMlF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACnC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACrC,MAAM,EAAE,CA8BV;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAcnE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC7B,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACrC,MAAM,GAAG,IAAI,CAKf;AAED,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GACnB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,0EAA0E;AAC1E,wBAAgB,iBAAiB,IAAI,MAAM,CAQ1C;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACrC,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAC,CAsCtD;AAMD;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAevF;AAED;;;;;;;GAOG;AACH,wBAAsB,MAAM,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BlF"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Browser acquisition and launch for headless capture.
7
+ *
8
+ * The launch cascade (in order):
9
+ * 1. `E3_UI_CHROMIUM_PATH` / `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH` — an
10
+ * explicit executable wins outright.
11
+ * 2. A bare `chromium.launch({ headless: true })` — playwright-core resolves
12
+ * its own managed cache (the `chromium-headless-shell` build installed by
13
+ * `e3-ui install-browser`, or a full build; honors
14
+ * `PLAYWRIGHT_BROWSERS_PATH`). `chromium.executablePath()` must NEVER be
15
+ * fed back into `launch()` here: it always names the FULL chromium
16
+ * binary, which does not exist after an `--only-shell` install.
17
+ * 3. A system-installed Chromium-family browser, per platform — skipping
18
+ * Ubuntu's snap shims (`/usr/bin/chromium-browser` is a shell script that
19
+ * execs the confined snap, which breaks automation).
20
+ *
21
+ * Sandboxing: playwright launches Chromium with `--no-sandbox` by default
22
+ * (`chromiumSandbox` defaults to false) — correct for rendering trusted local
23
+ * components, and why running as root just works.
24
+ *
25
+ * @packageDocumentation
26
+ */
27
+ import { spawn } from 'node:child_process';
28
+ import { createRequire } from 'node:module';
29
+ import { existsSync, openSync, readSync, closeSync, realpathSync } from 'node:fs';
30
+ import * as path from 'node:path';
31
+ import { chromium } from 'playwright-core';
32
+ /** Chromium args shared by every launch — `--disable-gpu` matches the in-repo
33
+ * snapshot pipeline so CLI captures are pixel-comparable with it. */
34
+ const LAUNCH_ARGS = ['--disable-gpu'];
35
+ /** The env vars honored as an explicit browser override, in precedence order. */
36
+ export const BROWSER_ENV_VARS = ['E3_UI_CHROMIUM_PATH', 'PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH'];
37
+ /**
38
+ * Return the explicit browser override from the environment, if any.
39
+ *
40
+ * @param env - Environment to read (injectable for tests)
41
+ * @returns The overriding executable path, or `null` when unset
42
+ */
43
+ export function envBrowserPath(env = process.env) {
44
+ for (const name of BROWSER_ENV_VARS) {
45
+ const value = env[name];
46
+ if (value)
47
+ return value;
48
+ }
49
+ return null;
50
+ }
51
+ /**
52
+ * Candidate system-browser executables for a platform, most-preferred first.
53
+ *
54
+ * @param platform - `process.platform` value (injectable for tests)
55
+ * @param env - Environment for Windows `%ProgramFiles%`-style roots
56
+ * @returns Absolute candidate paths (existence NOT yet checked)
57
+ */
58
+ export function systemBrowserCandidates(platform = process.platform, env = process.env) {
59
+ switch (platform) {
60
+ case 'linux':
61
+ return [
62
+ '/opt/google/chrome/chrome',
63
+ '/usr/bin/google-chrome-stable',
64
+ '/usr/bin/google-chrome',
65
+ '/usr/bin/chromium',
66
+ '/usr/bin/chromium-browser',
67
+ ];
68
+ case 'darwin':
69
+ return [
70
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
71
+ '/Applications/Chromium.app/Contents/MacOS/Chromium',
72
+ '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
73
+ ];
74
+ case 'win32': {
75
+ const roots = [
76
+ env['ProgramFiles'],
77
+ env['ProgramFiles(x86)'],
78
+ env['LocalAppData'],
79
+ ].filter((r) => !!r);
80
+ return [
81
+ ...roots.map(r => path.join(r, 'Google', 'Chrome', 'Application', 'chrome.exe')),
82
+ ...roots.map(r => path.join(r, 'Microsoft', 'Edge', 'Application', 'msedge.exe')),
83
+ ];
84
+ }
85
+ default:
86
+ return [];
87
+ }
88
+ }
89
+ /**
90
+ * Whether a candidate is a real browser binary rather than Ubuntu's snap shim.
91
+ * Rejects a path whose realpath resolves under `/snap/`, or whose file starts
92
+ * with `#!` (`/usr/bin/chromium-browser` on Ubuntu is a `#!/bin/sh` script
93
+ * that execs the confined snap — useless for automation).
94
+ *
95
+ * @param executablePath - Existing candidate path to vet
96
+ * @returns True when the candidate is launchable
97
+ */
98
+ export function isRealBrowserBinary(executablePath) {
99
+ try {
100
+ if (realpathSync(executablePath).split(path.sep).includes('snap'))
101
+ return false;
102
+ const fd = openSync(executablePath, 'r');
103
+ try {
104
+ const head = Buffer.alloc(2);
105
+ const n = readSync(fd, head, 0, 2, 0);
106
+ return !(n === 2 && head[0] === 0x23 && head[1] === 0x21); // "#!"
107
+ }
108
+ finally {
109
+ closeSync(fd);
110
+ }
111
+ }
112
+ catch {
113
+ return false;
114
+ }
115
+ }
116
+ /**
117
+ * Find the first usable system browser.
118
+ *
119
+ * @param platform - `process.platform` value (injectable for tests)
120
+ * @param env - Environment for Windows roots
121
+ * @returns The executable path, or `null` when none is usable
122
+ */
123
+ export function findSystemBrowser(platform = process.platform, env = process.env) {
124
+ for (const candidate of systemBrowserCandidates(platform, env)) {
125
+ if (existsSync(candidate) && isRealBrowserBinary(candidate))
126
+ return candidate;
127
+ }
128
+ return null;
129
+ }
130
+ /** One-line remediation block shared by the launch error and `doctor`. */
131
+ export function launchRemediation() {
132
+ return (` - Run \`e3-ui install-browser\` to download a version-matched headless Chromium` +
133
+ ` (add --with-deps on a fresh Linux server to also install system libraries).\n` +
134
+ ` - Or set E3_UI_CHROMIUM_PATH to a Chrome/Chromium/Edge executable` +
135
+ ` (not Ubuntu's snap chromium — its confinement breaks automation).\n` +
136
+ ` - Run \`e3-ui doctor\` for a full diagnosis.`);
137
+ }
138
+ /**
139
+ * Launch headless Chromium via the acquisition cascade.
140
+ *
141
+ * @param env - Environment to read overrides from (injectable for tests)
142
+ * @returns The browser plus which source of the cascade provided it
143
+ * @throws When no browser can be launched; the message carries the full
144
+ * remediation (install-browser / E3_UI_CHROMIUM_PATH / doctor)
145
+ */
146
+ export async function launchBrowser(env = process.env) {
147
+ const override = envBrowserPath(env);
148
+ if (override) {
149
+ try {
150
+ const browser = await chromium.launch({ headless: true, executablePath: override, args: LAUNCH_ARGS });
151
+ return { browser, source: { kind: 'env', executablePath: override } };
152
+ }
153
+ catch (err) {
154
+ throw new Error(`Could not launch the browser set by ${BROWSER_ENV_VARS.find(v => env[v]) ?? BROWSER_ENV_VARS[0]} ` +
155
+ `(${override}): ${firstLine(err)}\n${launchRemediation()}`);
156
+ }
157
+ }
158
+ let managedError;
159
+ try {
160
+ const browser = await chromium.launch({ headless: true, args: LAUNCH_ARGS });
161
+ return { browser, source: { kind: 'managed' } };
162
+ }
163
+ catch (err) {
164
+ managedError = err;
165
+ }
166
+ const system = findSystemBrowser();
167
+ if (system) {
168
+ try {
169
+ const browser = await chromium.launch({ headless: true, executablePath: system, args: LAUNCH_ARGS });
170
+ return { browser, source: { kind: 'system', executablePath: system } };
171
+ }
172
+ catch (err) {
173
+ throw new Error(`No managed browser (${firstLine(managedError)}), and the system browser at ${system} ` +
174
+ `failed to launch: ${firstLine(err)}\n${launchRemediation()}`);
175
+ }
176
+ }
177
+ throw new Error(`Could not launch headless Chromium: ${firstLine(managedError)}\n${launchRemediation()}`);
178
+ }
179
+ function firstLine(err) {
180
+ return (err instanceof Error ? err.message : String(err)).split('\n')[0] ?? 'unknown error';
181
+ }
182
+ /**
183
+ * Download the version-matched `chromium-headless-shell` into playwright's
184
+ * managed cache (honors `PLAYWRIGHT_BROWSERS_PATH`), by spawning the bundled
185
+ * playwright-core CLI: `install --only-shell chromium`. The shell build is the
186
+ * one a bare headless launch selects, and is ~100 MB lighter than full
187
+ * Chromium with no X11/D-Bus system libraries.
188
+ *
189
+ * @param opts - `withDeps` also installs OS packages (Linux only; skipped with
190
+ * a note elsewhere — Windows/macOS need no system libraries)
191
+ * @returns The spawned process exit code
192
+ */
193
+ export async function installBrowser(opts = {}) {
194
+ // playwright-core exports no `./cli` subpath — resolve cli.js at the
195
+ // package root via the always-exported package.json.
196
+ const require = createRequire(import.meta.url);
197
+ const cliJs = path.join(path.dirname(require.resolve('playwright-core/package.json')), 'cli.js');
198
+ const withDeps = (opts.withDeps ?? false) && process.platform === 'linux';
199
+ if (opts.withDeps && !withDeps) {
200
+ console.log('(--with-deps is only needed on Linux — skipped.)');
201
+ }
202
+ const args = [cliJs, 'install', '--only-shell', ...(withDeps ? ['--with-deps'] : []), 'chromium'];
203
+ const child = spawn(process.execPath, args, { stdio: 'inherit' });
204
+ return await new Promise((resolve, reject) => {
205
+ child.on('error', reject);
206
+ child.on('exit', code => resolve(code ?? 1));
207
+ });
208
+ }
209
+ /**
210
+ * Diagnose the browser setup: report env overrides, run the real launch
211
+ * cascade against `about:blank`, and print what worked — or per-OS remediation
212
+ * for what didn't.
213
+ *
214
+ * @param env - Environment to diagnose (injectable for tests)
215
+ * @returns Process exit code (0 healthy, 1 not)
216
+ */
217
+ export async function doctor(env = process.env) {
218
+ for (const name of BROWSER_ENV_VARS) {
219
+ console.log(`${name}: ${env[name] ?? '(unset)'}`);
220
+ }
221
+ console.log(`PLAYWRIGHT_BROWSERS_PATH: ${env['PLAYWRIGHT_BROWSERS_PATH'] ?? '(default cache)'}`);
222
+ let result;
223
+ try {
224
+ result = await launchBrowser(env);
225
+ }
226
+ catch (err) {
227
+ console.error(`\nBrowser launch: FAILED\n${err instanceof Error ? err.message : String(err)}`);
228
+ return 1;
229
+ }
230
+ try {
231
+ const page = await result.browser.newPage();
232
+ await page.goto('about:blank');
233
+ const version = result.browser.version();
234
+ const source = result.source.kind === 'managed'
235
+ ? 'playwright-managed cache'
236
+ : `${result.source.kind === 'env' ? 'env override' : 'system browser'} at ${result.source.executablePath}`;
237
+ console.log(`\nBrowser launch: OK (Chromium ${version}, ${source})`);
238
+ console.log('e3-ui shot is ready to render.');
239
+ return 0;
240
+ }
241
+ catch (err) {
242
+ console.error(`\nBrowser launched but failed to open a page: ${err instanceof Error ? err.message : String(err)}`);
243
+ return 1;
244
+ }
245
+ finally {
246
+ await result.browser.close();
247
+ }
248
+ }
249
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ import type { ShotPayload } from './payload.js';
6
+ /** Default capture parameters — single source of truth (CLI help text in
7
+ * `cli.ts` documents these values; keep them in sync). */
8
+ export declare const CAPTURE_DEFAULTS: {
9
+ readonly viewport: {
10
+ readonly width: 1280;
11
+ readonly height: 900;
12
+ };
13
+ readonly deviceScaleFactor: 2;
14
+ readonly settleMs: 300;
15
+ readonly timeoutMs: 30000;
16
+ readonly storageKey: "shot";
17
+ readonly statusPollMs: 100;
18
+ readonly skeletonPollMs: 200;
19
+ readonly errorTextLimit: 600;
20
+ };
21
+ /** How the screenshot is framed. */
22
+ export type CaptureMode = {
23
+ kind: 'frame';
24
+ } | {
25
+ kind: 'full-page';
26
+ } | {
27
+ kind: 'element';
28
+ selector: string;
29
+ };
30
+ /** Options for a single capture. */
31
+ export interface CaptureOptions {
32
+ /** Directory of the prebuilt app bundle (the built `dist/app`). */
33
+ appDir: string;
34
+ /** The render payload (base64 IR). */
35
+ payload: ShotPayload;
36
+ /** Output PNG path. */
37
+ outPng: string;
38
+ /** When set, also write a self-contained HTML snapshot here. */
39
+ outHtml?: string | undefined;
40
+ /** Storage key prefix for persisted component state. */
41
+ storageKey?: string;
42
+ /** Chromium viewport. Default 1280×900. */
43
+ viewport?: {
44
+ width: number;
45
+ height: number;
46
+ };
47
+ /** Device scale factor (DPR). Default 2. */
48
+ deviceScaleFactor?: number;
49
+ /** Framing. Default `{ kind: 'frame' }`. */
50
+ mode?: CaptureMode;
51
+ /** Grace period (ms) after skeletons clear before capture. Default 300. */
52
+ settleMs?: number;
53
+ /** Per-navigation timeout (ms). Default 30000. */
54
+ timeoutMs?: number;
55
+ }
56
+ /** Serve the prebuilt app directory over a random localhost port. */
57
+ /**
58
+ * Resolve a URL pathname to a file within `root`, or `null` if it would escape
59
+ * (path traversal). Uses a separator-boundary check so a sibling dir sharing the
60
+ * root's prefix cannot pass. Exported for unit tests.
61
+ */
62
+ export declare function resolveWithinRoot(root: string, urlPathname: string): string | null;
63
+ /** Escape text for safe inclusion in HTML. Exported for unit tests. */
64
+ export declare function escapeHtml(s: string): string;
65
+ /**
66
+ * Inline `url(...woff2)` font references in CSS as base64 data URIs (read from
67
+ * the app's built `assets/`), so the standalone HTML renders with the brand
68
+ * fonts over `file://` with no server. A font that cannot be read is left as its
69
+ * original (server-relative) URL and a warning is emitted — a silently broken
70
+ * `--html` is worse than a visible warning. Exported for unit tests.
71
+ */
72
+ export declare function inlineFonts(css: string, appDir: string): Promise<string>;
73
+ /**
74
+ * Render a component payload to a PNG (and optionally a standalone HTML).
75
+ *
76
+ * @param opts - Capture options
77
+ * @throws If the app reports a compile/render error, or capture times out
78
+ */
79
+ export declare function capture(opts: CaptureOptions): Promise<void>;
80
+ //# sourceMappingURL=capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAsBH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;2DAC2D;AAC3D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;CASnB,CAAC;AAEX,oCAAoC;AACpC,MAAM,MAAM,WAAW,GACjB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5C,oCAAoC;AACpC,MAAM,WAAW,cAAc;IAC3B,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,OAAO,EAAE,WAAW,CAAC;IACrB,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,4CAA4C;IAC5C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAgBD,qEAAqE;AACrE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMlF;AA8BD,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmB9E;AA4CD;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAqHjE"}