@somewhere-tech/cli 0.29.1 → 0.30.0
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/commands/browser.js +111 -16
- package/dist/commands/browser.js.map +1 -1
- package/dist/commands/dev.js +64 -7
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/errors.js +29 -6
- package/dist/commands/errors.js.map +1 -1
- package/dist/commands/status.js +30 -0
- package/dist/commands/status.js.map +1 -1
- package/dist/local/browser-run.js +242 -0
- package/dist/local/browser-run.js.map +1 -0
- package/dist/local/chrome.js +287 -0
- package/dist/local/chrome.js.map +1 -0
- package/dist/local/runtime.js +66 -2
- package/dist/local/runtime.js.map +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
- package/runtime/VENDOR.json +4 -3
- package/runtime/browser-probes.mjs +6 -0
- package/runtime/compiler/VENDOR.json +3 -3
- package/runtime/compiler/compile-core.cjs +18 -0
- package/runtime/compiler/typed-functions.cjs +31 -1
- package/runtime/platform-context.mjs +241 -23
- package/runtime/sw-init.mjs +1 -1
package/dist/commands/status.js
CHANGED
|
@@ -22,6 +22,16 @@ export function previewCandidatesFromDeployment(deployment) {
|
|
|
22
22
|
}];
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
|
+
/** "— included on the Pro and Scale plans", from whatever the platform named.
|
|
26
|
+
* Empty when it named nothing: better to say less than to guess a plan. */
|
|
27
|
+
export function localDevDbPlanHint(plans) {
|
|
28
|
+
if (!plans || plans.length === 0)
|
|
29
|
+
return '— `somewhere deploy` publishes on every plan';
|
|
30
|
+
const named = plans
|
|
31
|
+
.map((p) => (p.length === 0 ? p : p[0].toUpperCase() + p.slice(1)))
|
|
32
|
+
.reduce((acc, name, i, all) => (i === 0 ? name : `${acc}${i === all.length - 1 ? ' and ' : ', '}${name}`), '');
|
|
33
|
+
return `— included on the ${named} plan${plans.length === 1 ? '' : 's'}; \`somewhere deploy\` publishes on every plan`;
|
|
34
|
+
}
|
|
25
35
|
export function registerStatus(program) {
|
|
26
36
|
program
|
|
27
37
|
.command('status [project]')
|
|
@@ -55,6 +65,14 @@ export function registerStatus(program) {
|
|
|
55
65
|
if (p.updated_at) {
|
|
56
66
|
info(`Last deploy: ${timeAgo(p.updated_at)}`);
|
|
57
67
|
}
|
|
68
|
+
// The `somewhere dev` question, answered here so it can be checked
|
|
69
|
+
// BEFORE a local-first workflow is chosen (tsk_4df056ea). Deploying is
|
|
70
|
+
// never gated by it, which is why the refused line says so.
|
|
71
|
+
if (typeof p.local_dev_db_allowed === 'boolean') {
|
|
72
|
+
info(p.local_dev_db_allowed
|
|
73
|
+
? `Local dev database: available ${dim('— `somewhere dev` reads and writes this project\'s database')}`
|
|
74
|
+
: `Local dev database: not on this plan ${dim(localDevDbPlanHint(p.local_dev_db_required_plans))}`);
|
|
75
|
+
}
|
|
58
76
|
}
|
|
59
77
|
}
|
|
60
78
|
catch (err) {
|
|
@@ -129,6 +147,18 @@ export function registerStatus(program) {
|
|
|
129
147
|
workspace: workspaceStatus,
|
|
130
148
|
project_error: projectError,
|
|
131
149
|
deployment_error: deploymentError,
|
|
150
|
+
// Lifted to the top level so a script reads one key rather than
|
|
151
|
+
// knowing the project shape — and so this surface, the `somewhere dev`
|
|
152
|
+
// startup line and the platform's own refusal cannot drift apart.
|
|
153
|
+
// `null` = the platform did not say; it is never a refusal.
|
|
154
|
+
local_dev_db: projectStatus === null
|
|
155
|
+
|| typeof projectStatus.local_dev_db_allowed !== 'boolean'
|
|
156
|
+
? null
|
|
157
|
+
: {
|
|
158
|
+
allowed: projectStatus.local_dev_db_allowed,
|
|
159
|
+
required_plans: projectStatus.local_dev_db_required_plans ?? [],
|
|
160
|
+
deploy_affected: false,
|
|
161
|
+
},
|
|
132
162
|
});
|
|
133
163
|
}
|
|
134
164
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AASzF,MAAM,UAAU,+BAA+B,CAC7C,UAAmC;IAEnC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC;QACtD,CAAC,CAAC,UAAU,CAAC,kBAAkB;QAC/B,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC;YACxB,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC;YACpB,CAAC,CAAC,EAAE,CAAC;IACX,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;QAChD,IAAI,OAAO,SAAS,CAAC,QAAQ,KAAK,QAAQ;eACnC,OAAO,SAAS,CAAC,oBAAoB,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACrE,OAAO,CAAC;gBACN,QAAQ,EAAE,SAAS,CAAC,QAAQ;gBAC5B,oBAAoB,EAAE,SAAS,CAAC,oBAAoB;gBACpD,GAAG,CAAC,OAAO,SAAS,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,SAAS,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrG,GAAG,CAAC,OAAO,SAAS,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC1F,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO;SACJ,OAAO,CAAC,kBAAkB,CAAC;SAC3B,WAAW,CAAC,mCAAmC,CAAC;SAChD,MAAM,CAAC,QAAQ,EAAE,wCAAwC,CAAC;SAC1D,MAAM,CAAC,KAAK,EAAE,UAA8B,EAAE,IAAI,EAAE,EAAE;QACrD,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC;QAEpC,IAAI,SAAS,GAAG,UAAU,CAAC;QAC3B,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;YACnC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,KAAK,CAAC,+FAA+F,CAAC,CAAC;gBACvG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;QAChC,CAAC;QAED,IAAI,aAAa,
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run the `somewhere browser` health check against a page on this machine.
|
|
3
|
+
*
|
|
4
|
+
* Produces exactly the report shape the hosted browser produces, so the
|
|
5
|
+
* command's formatter, exit code, and `--json` output do not care which half
|
|
6
|
+
* answered. The interactive-element map comes from the platform's own vendored
|
|
7
|
+
* probe (runtime/browser-probes.mjs) — the point of the local path is a
|
|
8
|
+
* preview of the hosted answer, not a second opinion.
|
|
9
|
+
*/
|
|
10
|
+
import { writeFileSync } from 'node:fs';
|
|
11
|
+
import { dirname, join } from 'node:path';
|
|
12
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
13
|
+
import { findBrowser, launchLocalBrowser, NO_BROWSER_MESSAGE, } from './chrome.js';
|
|
14
|
+
/** Loopback and link-local hosts: the addresses only this machine can reach. */
|
|
15
|
+
const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]', '::1', '0.0.0.0', '[::]']);
|
|
16
|
+
/**
|
|
17
|
+
* Is this URL an address only this machine can reach? The hosted browser is
|
|
18
|
+
* remote, so these can only ever be served by the local half.
|
|
19
|
+
*/
|
|
20
|
+
export function isLoopbackUrl(raw) {
|
|
21
|
+
let url;
|
|
22
|
+
try {
|
|
23
|
+
url = new URL(raw);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
const host = url.hostname.toLowerCase();
|
|
29
|
+
if (LOOPBACK_HOSTS.has(host) || LOOPBACK_HOSTS.has(`[${host}]`))
|
|
30
|
+
return true;
|
|
31
|
+
if (host.endsWith('.localhost'))
|
|
32
|
+
return true;
|
|
33
|
+
// 127.0.0.0/8 in full.
|
|
34
|
+
return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host);
|
|
35
|
+
}
|
|
36
|
+
/** The platform's interactive-element probe, vendored verbatim. */
|
|
37
|
+
async function domOutlineScript() {
|
|
38
|
+
const path = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'runtime', 'browser-probes.mjs');
|
|
39
|
+
const probes = (await import(pathToFileURL(path).href));
|
|
40
|
+
return probes.DOM_OUTLINE_SCRIPT;
|
|
41
|
+
}
|
|
42
|
+
const SETTLE_MS = 250;
|
|
43
|
+
const POLL_MS = 100;
|
|
44
|
+
/**
|
|
45
|
+
* Timers are unref'd: the load race below arms one for the whole remaining
|
|
46
|
+
* budget, and a ref'd timer would hold the process open for the rest of it
|
|
47
|
+
* after the page had already loaded.
|
|
48
|
+
*/
|
|
49
|
+
function sleep(ms) {
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
setTimeout(resolve, ms).unref();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/** Evaluate an expression in the page and return its JSON-ish value. */
|
|
55
|
+
async function evaluate(session, expression) {
|
|
56
|
+
const res = (await session.send('Runtime.evaluate', {
|
|
57
|
+
expression,
|
|
58
|
+
returnByValue: true,
|
|
59
|
+
awaitPromise: true,
|
|
60
|
+
}));
|
|
61
|
+
if (res.exceptionDetails) {
|
|
62
|
+
const detail = res.exceptionDetails.exception?.description ?? res.exceptionDetails.text ?? 'evaluation failed';
|
|
63
|
+
throw new Error(detail);
|
|
64
|
+
}
|
|
65
|
+
return res.result?.value;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Drive the local browser and return the report.
|
|
69
|
+
*
|
|
70
|
+
* The whole run shares one deadline. A step that fails is reported as a failed
|
|
71
|
+
* step and the run still returns everything it captured — the caller asked what
|
|
72
|
+
* the page looks like, and "it broke here, and here is the rest" is the useful
|
|
73
|
+
* answer.
|
|
74
|
+
*/
|
|
75
|
+
export async function runLocalBrowser(req) {
|
|
76
|
+
const found = findBrowser();
|
|
77
|
+
if (!found)
|
|
78
|
+
throw new Error(NO_BROWSER_MESSAGE);
|
|
79
|
+
const deadline = Date.now() + req.timeoutMs;
|
|
80
|
+
const launched = await launchLocalBrowser({
|
|
81
|
+
executablePath: found.path,
|
|
82
|
+
viewport: req.viewport,
|
|
83
|
+
timeoutMs: Math.min(req.timeoutMs, 20_000),
|
|
84
|
+
});
|
|
85
|
+
const { session } = launched;
|
|
86
|
+
const consoleErrors = [];
|
|
87
|
+
const pageErrors = [];
|
|
88
|
+
const failedRequests = [];
|
|
89
|
+
const steps = [];
|
|
90
|
+
const screenshots = [];
|
|
91
|
+
const requestMethods = new Map();
|
|
92
|
+
try {
|
|
93
|
+
session.on('Runtime.consoleAPICalled', (params) => {
|
|
94
|
+
if (params['type'] !== 'error')
|
|
95
|
+
return;
|
|
96
|
+
const args = params['args'] ?? [];
|
|
97
|
+
consoleErrors.push(args.map((a) => (a.value !== undefined ? String(a.value) : a.description ?? '')).join(' ').trim());
|
|
98
|
+
});
|
|
99
|
+
session.on('Runtime.exceptionThrown', (params) => {
|
|
100
|
+
const details = params['exceptionDetails'];
|
|
101
|
+
pageErrors.push(details?.exception?.description ?? details?.text ?? 'uncaught error');
|
|
102
|
+
});
|
|
103
|
+
session.on('Network.requestWillBeSent', (params) => {
|
|
104
|
+
const id = String(params['requestId'] ?? '');
|
|
105
|
+
const request = params['request'];
|
|
106
|
+
if (id)
|
|
107
|
+
requestMethods.set(id, request?.method ?? 'GET');
|
|
108
|
+
});
|
|
109
|
+
session.on('Network.responseReceived', (params) => {
|
|
110
|
+
const response = params['response'];
|
|
111
|
+
if (!response || typeof response.status !== 'number' || response.status < 400)
|
|
112
|
+
return;
|
|
113
|
+
failedRequests.push({
|
|
114
|
+
status: response.status,
|
|
115
|
+
method: requestMethods.get(String(params['requestId'] ?? '')) ?? 'GET',
|
|
116
|
+
url: response.url,
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
session.on('Network.loadingFailed', (params) => {
|
|
120
|
+
// A cancelled request is the page's own choice, not a failure.
|
|
121
|
+
if (params['canceled'] === true)
|
|
122
|
+
return;
|
|
123
|
+
failedRequests.push({
|
|
124
|
+
method: requestMethods.get(String(params['requestId'] ?? '')) ?? 'GET',
|
|
125
|
+
url: String(params['errorText'] ?? 'request failed'),
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
await session.send('Page.enable');
|
|
129
|
+
await session.send('Runtime.enable');
|
|
130
|
+
await session.send('Network.enable');
|
|
131
|
+
await session.send('Emulation.setDeviceMetricsOverride', {
|
|
132
|
+
width: req.viewport.width,
|
|
133
|
+
height: req.viewport.height,
|
|
134
|
+
deviceScaleFactor: 1,
|
|
135
|
+
mobile: false,
|
|
136
|
+
});
|
|
137
|
+
const startUrl = req.path ? new URL(req.path, req.url).toString() : req.url;
|
|
138
|
+
const loaded = new Promise((resolve) => {
|
|
139
|
+
session.on('Page.loadEventFired', () => resolve());
|
|
140
|
+
});
|
|
141
|
+
await session.send('Page.navigate', { url: startUrl });
|
|
142
|
+
// Either the page loads or the budget runs out; whichever comes first, drop
|
|
143
|
+
// the other's timer rather than leaving it armed for the rest of the budget.
|
|
144
|
+
let loadTimer;
|
|
145
|
+
await Promise.race([
|
|
146
|
+
loaded,
|
|
147
|
+
new Promise((resolve) => {
|
|
148
|
+
loadTimer = setTimeout(resolve, Math.max(0, deadline - Date.now()));
|
|
149
|
+
loadTimer.unref();
|
|
150
|
+
}),
|
|
151
|
+
]);
|
|
152
|
+
if (loadTimer)
|
|
153
|
+
clearTimeout(loadTimer);
|
|
154
|
+
await sleep(SETTLE_MS);
|
|
155
|
+
if (req.path)
|
|
156
|
+
steps.push({ action: 'goto', ok: true, path: req.path });
|
|
157
|
+
if (req.wait) {
|
|
158
|
+
const selector = req.wait;
|
|
159
|
+
const step = { action: 'wait_for', ok: false, selector };
|
|
160
|
+
const expression = `!!document.querySelector(${JSON.stringify(selector)})`;
|
|
161
|
+
while (Date.now() < deadline) {
|
|
162
|
+
let matched = false;
|
|
163
|
+
try {
|
|
164
|
+
matched = (await evaluate(session, expression)) === true;
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
step.error = err instanceof Error ? err.message : String(err);
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
if (matched) {
|
|
171
|
+
step.ok = true;
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
await sleep(POLL_MS);
|
|
175
|
+
}
|
|
176
|
+
if (!step.ok && !step.error)
|
|
177
|
+
step.error = `Timed out waiting for \`${selector}\`.`;
|
|
178
|
+
steps.push(step);
|
|
179
|
+
}
|
|
180
|
+
if (req.eval) {
|
|
181
|
+
const step = { action: 'eval', ok: true, script: req.eval };
|
|
182
|
+
try {
|
|
183
|
+
step.result = await evaluate(session, req.eval);
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
step.ok = false;
|
|
187
|
+
step.error = err instanceof Error ? err.message : String(err);
|
|
188
|
+
}
|
|
189
|
+
steps.push(step);
|
|
190
|
+
}
|
|
191
|
+
// The interactive-element map, read AFTER the steps — the same ordering the
|
|
192
|
+
// hosted browser uses, so the map describes the page the run left behind
|
|
193
|
+
// rather than the page before the wait resolved.
|
|
194
|
+
let domOutline = [];
|
|
195
|
+
let testidMap = {};
|
|
196
|
+
try {
|
|
197
|
+
const probe = (await evaluate(session, await domOutlineScript()));
|
|
198
|
+
domOutline = Array.isArray(probe?.outline) ? probe.outline : [];
|
|
199
|
+
testidMap = probe?.testid_map ?? {};
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
consoleErrors.push(`[inspect] DOM probe failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
203
|
+
}
|
|
204
|
+
if (req.screenshotPath) {
|
|
205
|
+
const step = { action: 'screenshot', ok: true, path: req.screenshotPath };
|
|
206
|
+
try {
|
|
207
|
+
const shot = (await session.send('Page.captureScreenshot', { format: 'jpeg', quality: 70 }));
|
|
208
|
+
writeFileSync(req.screenshotPath, Buffer.from(shot.data ?? '', 'base64'));
|
|
209
|
+
screenshots.push({ label: 'page', path: req.screenshotPath });
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
step.ok = false;
|
|
213
|
+
step.error = err instanceof Error ? err.message : String(err);
|
|
214
|
+
}
|
|
215
|
+
steps.push(step);
|
|
216
|
+
}
|
|
217
|
+
let finalUrl = startUrl;
|
|
218
|
+
try {
|
|
219
|
+
finalUrl = String(await evaluate(session, 'location.href'));
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
/* keep the URL we navigated to */
|
|
223
|
+
}
|
|
224
|
+
const passed = steps.every((s) => s.ok) && pageErrors.length === 0 && failedRequests.length === 0;
|
|
225
|
+
return {
|
|
226
|
+
passed,
|
|
227
|
+
final_url: finalUrl,
|
|
228
|
+
console_errors: consoleErrors,
|
|
229
|
+
page_errors: pageErrors,
|
|
230
|
+
failed_requests: failedRequests,
|
|
231
|
+
steps,
|
|
232
|
+
screenshots,
|
|
233
|
+
dom_outline: domOutline,
|
|
234
|
+
testid_map: testidMap,
|
|
235
|
+
environment: 'local',
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
finally {
|
|
239
|
+
await launched.close();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=browser-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-run.js","sourceRoot":"","sources":["../../src/local/browser-run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A browser for the app on localhost.
|
|
3
|
+
*
|
|
4
|
+
* `somewhere browser` drives the platform's hosted browser, which lives on the
|
|
5
|
+
* internet and therefore cannot reach a developer's loopback address — the two
|
|
6
|
+
* halves of this CLI could not talk to each other, so the app `somewhere dev`
|
|
7
|
+
* was serving was the one address its own browser tool refused to visit. Every
|
|
8
|
+
* visual and DOM check had to wait until after the first production deploy.
|
|
9
|
+
*
|
|
10
|
+
* This is the loopback half: the browser already installed on the developer's
|
|
11
|
+
* machine, driven directly over the DevTools protocol. No new dependency (the
|
|
12
|
+
* socket comes from undici, which the CLI already bundles) and no download —
|
|
13
|
+
* if there is no browser on the machine we say so plainly instead of fetching
|
|
14
|
+
* one hundreds of megabytes at a time.
|
|
15
|
+
*
|
|
16
|
+
* The probe it runs is the PLATFORM's probe, vendored in
|
|
17
|
+
* runtime/browser-probes.mjs, so the interactive-element map you get for
|
|
18
|
+
* localhost is the same map the hosted browser reports for the deployed app.
|
|
19
|
+
*/
|
|
20
|
+
import { spawn } from 'node:child_process';
|
|
21
|
+
import { existsSync, mkdtempSync, rmSync } from 'node:fs';
|
|
22
|
+
import { homedir, tmpdir } from 'node:os';
|
|
23
|
+
import { join } from 'node:path';
|
|
24
|
+
import { readdirSync } from 'node:fs';
|
|
25
|
+
import { WebSocket } from 'undici';
|
|
26
|
+
/** Env vars that name a browser binary, in the order they win. */
|
|
27
|
+
export const BROWSER_PATH_ENV_VARS = [
|
|
28
|
+
'SOMEWHERE_BROWSER_PATH',
|
|
29
|
+
'CHROME_PATH',
|
|
30
|
+
'PUPPETEER_EXECUTABLE_PATH',
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* Where a Chrome-family browser normally lives, per platform. Ordered: a real
|
|
34
|
+
* installed browser first, then the caches the common tooling downloads into.
|
|
35
|
+
*/
|
|
36
|
+
function candidatePaths() {
|
|
37
|
+
const home = homedir();
|
|
38
|
+
const out = [];
|
|
39
|
+
if (process.platform === 'darwin') {
|
|
40
|
+
out.push('/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', '/Applications/Chromium.app/Contents/MacOS/Chromium', '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge', '/Applications/Brave Browser.app/Contents/MacOS/Brave Browser', join(home, 'Applications/Google Chrome.app/Contents/MacOS/Google Chrome'));
|
|
41
|
+
}
|
|
42
|
+
else if (process.platform === 'win32') {
|
|
43
|
+
const programFiles = [
|
|
44
|
+
process.env['PROGRAMFILES'] ?? 'C:\\Program Files',
|
|
45
|
+
process.env['PROGRAMFILES(X86)'] ?? 'C:\\Program Files (x86)',
|
|
46
|
+
process.env['LOCALAPPDATA'] ?? join(home, 'AppData', 'Local'),
|
|
47
|
+
];
|
|
48
|
+
for (const base of programFiles) {
|
|
49
|
+
out.push(join(base, 'Google\\Chrome\\Application\\chrome.exe'), join(base, 'Microsoft\\Edge\\Application\\msedge.exe'), join(base, 'Chromium\\Application\\chrome.exe'));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
out.push('/usr/bin/google-chrome', '/usr/bin/google-chrome-stable', '/usr/bin/chromium', '/usr/bin/chromium-browser', '/usr/bin/microsoft-edge', '/snap/bin/chromium');
|
|
54
|
+
}
|
|
55
|
+
out.push(...puppeteerCachePaths(join(home, '.cache', 'puppeteer')));
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Browsers the common tooling has already downloaded. Worth checking: a
|
|
60
|
+
* developer whose project uses Playwright or Puppeteer has a working browser
|
|
61
|
+
* on disk even when the machine has no browser installed for a human.
|
|
62
|
+
*/
|
|
63
|
+
function puppeteerCachePaths(cacheDir) {
|
|
64
|
+
const out = [];
|
|
65
|
+
let products;
|
|
66
|
+
try {
|
|
67
|
+
products = readdirSync(cacheDir);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
for (const product of products) {
|
|
73
|
+
if (!product.startsWith('chrome'))
|
|
74
|
+
continue;
|
|
75
|
+
let builds;
|
|
76
|
+
try {
|
|
77
|
+
builds = readdirSync(join(cacheDir, product)).sort().reverse();
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
for (const build of builds) {
|
|
83
|
+
const base = join(cacheDir, product, build);
|
|
84
|
+
out.push(join(base, 'chrome-mac-arm64', 'Google Chrome for Testing.app', 'Contents', 'MacOS', 'Google Chrome for Testing'), join(base, 'chrome-mac-x64', 'Google Chrome for Testing.app', 'Contents', 'MacOS', 'Google Chrome for Testing'), join(base, 'chrome-linux64', 'chrome'), join(base, 'chrome-win64', 'chrome.exe'), join(base, 'chrome-headless-shell-mac-arm64', 'chrome-headless-shell'), join(base, 'chrome-headless-shell-mac-x64', 'chrome-headless-shell'), join(base, 'chrome-headless-shell-linux64', 'chrome-headless-shell'), join(base, 'chrome-headless-shell-win64', 'chrome-headless-shell.exe'));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The browser this machine will use, or null when it has none. An env var
|
|
91
|
+
* always wins — including one that points at a path that does not exist, which
|
|
92
|
+
* is reported as the error it is rather than silently ignored in favour of some
|
|
93
|
+
* other browser.
|
|
94
|
+
*/
|
|
95
|
+
export function findBrowser(env = process.env, exists = existsSync) {
|
|
96
|
+
for (const key of BROWSER_PATH_ENV_VARS) {
|
|
97
|
+
const value = env[key];
|
|
98
|
+
if (value)
|
|
99
|
+
return { path: value, source: 'env' };
|
|
100
|
+
}
|
|
101
|
+
for (const candidate of candidatePaths()) {
|
|
102
|
+
if (exists(candidate))
|
|
103
|
+
return { path: candidate, source: 'installed' };
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
export const NO_BROWSER_MESSAGE = 'No browser found on this machine to open the local app with. ' +
|
|
108
|
+
'Install Chrome, Chromium, Edge, or Brave, or point ' +
|
|
109
|
+
`${BROWSER_PATH_ENV_VARS[0]} at a browser you already have.`;
|
|
110
|
+
/** One request/response + event channel to a running browser. */
|
|
111
|
+
export class DevToolsSession {
|
|
112
|
+
socket;
|
|
113
|
+
nextId = 1;
|
|
114
|
+
pending = new Map();
|
|
115
|
+
listeners = new Map();
|
|
116
|
+
closed = false;
|
|
117
|
+
constructor(socket) {
|
|
118
|
+
this.socket = socket;
|
|
119
|
+
socket.addEventListener('message', (event) => this.onMessage(String(event.data)));
|
|
120
|
+
socket.addEventListener('close', () => this.failAll(new Error('The browser closed the connection.')));
|
|
121
|
+
socket.addEventListener('error', () => this.failAll(new Error('The connection to the browser failed.')));
|
|
122
|
+
}
|
|
123
|
+
static async connect(wsUrl, timeoutMs) {
|
|
124
|
+
const socket = new WebSocket(wsUrl);
|
|
125
|
+
await new Promise((resolve, reject) => {
|
|
126
|
+
const timer = setTimeout(() => reject(new Error('Timed out connecting to the browser.')), timeoutMs);
|
|
127
|
+
socket.addEventListener('open', () => { clearTimeout(timer); resolve(); }, { once: true });
|
|
128
|
+
socket.addEventListener('error', () => { clearTimeout(timer); reject(new Error('Could not connect to the browser.')); }, { once: true });
|
|
129
|
+
});
|
|
130
|
+
return new DevToolsSession(socket);
|
|
131
|
+
}
|
|
132
|
+
onMessage(raw) {
|
|
133
|
+
let msg;
|
|
134
|
+
try {
|
|
135
|
+
msg = JSON.parse(raw);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const id = msg['id'];
|
|
141
|
+
if (typeof id === 'number') {
|
|
142
|
+
const waiter = this.pending.get(id);
|
|
143
|
+
if (!waiter)
|
|
144
|
+
return;
|
|
145
|
+
this.pending.delete(id);
|
|
146
|
+
const error = msg['error'];
|
|
147
|
+
if (error)
|
|
148
|
+
waiter.reject(new Error(error.message ?? 'The browser rejected the command.'));
|
|
149
|
+
else
|
|
150
|
+
waiter.resolve(msg['result'] ?? {});
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const method = msg['method'];
|
|
154
|
+
if (typeof method !== 'string')
|
|
155
|
+
return;
|
|
156
|
+
for (const fn of this.listeners.get(method) ?? []) {
|
|
157
|
+
fn(msg['params'] ?? {});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
failAll(err) {
|
|
161
|
+
this.closed = true;
|
|
162
|
+
for (const waiter of this.pending.values())
|
|
163
|
+
waiter.reject(err);
|
|
164
|
+
this.pending.clear();
|
|
165
|
+
}
|
|
166
|
+
on(method, fn) {
|
|
167
|
+
const list = this.listeners.get(method) ?? [];
|
|
168
|
+
list.push(fn);
|
|
169
|
+
this.listeners.set(method, list);
|
|
170
|
+
}
|
|
171
|
+
send(method, params = {}) {
|
|
172
|
+
if (this.closed)
|
|
173
|
+
return Promise.reject(new Error('The connection to the browser is closed.'));
|
|
174
|
+
const id = this.nextId++;
|
|
175
|
+
this.socket.send(JSON.stringify({ id, method, params, sessionId: this.sessionId }));
|
|
176
|
+
return new Promise((resolve, reject) => {
|
|
177
|
+
this.pending.set(id, { resolve, reject });
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/** Set once the session is attached to a page target. */
|
|
181
|
+
sessionId;
|
|
182
|
+
close() {
|
|
183
|
+
this.closed = true;
|
|
184
|
+
try {
|
|
185
|
+
this.socket.close();
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
/* already gone */
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/** The DevTools endpoint a freshly launched browser prints on stderr. */
|
|
193
|
+
function readEndpoint(child, timeoutMs) {
|
|
194
|
+
return new Promise((resolve, reject) => {
|
|
195
|
+
let buffered = '';
|
|
196
|
+
const timer = setTimeout(() => {
|
|
197
|
+
cleanup();
|
|
198
|
+
reject(new Error(`The browser did not report a DevTools endpoint within ${timeoutMs}ms.`));
|
|
199
|
+
}, timeoutMs);
|
|
200
|
+
const onData = (chunk) => {
|
|
201
|
+
buffered += chunk.toString('utf8');
|
|
202
|
+
const match = buffered.match(/ws:\/\/[^\s]+/);
|
|
203
|
+
if (!match)
|
|
204
|
+
return;
|
|
205
|
+
cleanup();
|
|
206
|
+
resolve(match[0]);
|
|
207
|
+
};
|
|
208
|
+
const onExit = (code) => {
|
|
209
|
+
cleanup();
|
|
210
|
+
reject(new Error(`The browser exited (code ${code ?? 'unknown'}) before it was ready.`));
|
|
211
|
+
};
|
|
212
|
+
function cleanup() {
|
|
213
|
+
clearTimeout(timer);
|
|
214
|
+
child.stderr?.off('data', onData);
|
|
215
|
+
child.off('exit', onExit);
|
|
216
|
+
}
|
|
217
|
+
child.stderr?.on('data', onData);
|
|
218
|
+
child.on('exit', onExit);
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Launch a headless browser and attach to a fresh page.
|
|
223
|
+
*
|
|
224
|
+
* Every run gets its own empty profile directory, so a local check never reads
|
|
225
|
+
* or writes the developer's real browser profile — no cookies of theirs leak
|
|
226
|
+
* into the page, and nothing the page does survives the run.
|
|
227
|
+
*/
|
|
228
|
+
export async function launchLocalBrowser(opts) {
|
|
229
|
+
const profileDir = mkdtempSync(join(tmpdir(), 'somewhere-browser-'));
|
|
230
|
+
const child = spawn(opts.executablePath, [
|
|
231
|
+
'--headless=new',
|
|
232
|
+
'--remote-debugging-port=0',
|
|
233
|
+
`--user-data-dir=${profileDir}`,
|
|
234
|
+
`--window-size=${opts.viewport.width},${opts.viewport.height}`,
|
|
235
|
+
'--no-first-run',
|
|
236
|
+
'--no-default-browser-check',
|
|
237
|
+
'--disable-background-networking',
|
|
238
|
+
'--disable-extensions',
|
|
239
|
+
'--disable-gpu',
|
|
240
|
+
'--hide-scrollbars',
|
|
241
|
+
'about:blank',
|
|
242
|
+
], { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
243
|
+
const cleanup = async () => {
|
|
244
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
245
|
+
const exited = new Promise((resolve) => {
|
|
246
|
+
child.once('exit', () => resolve());
|
|
247
|
+
setTimeout(resolve, 2_000).unref();
|
|
248
|
+
});
|
|
249
|
+
try {
|
|
250
|
+
child.kill('SIGKILL');
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
/* already gone */
|
|
254
|
+
}
|
|
255
|
+
await exited;
|
|
256
|
+
}
|
|
257
|
+
// The profile is a scratch directory in the OS temp dir. Failing to remove
|
|
258
|
+
// it is not worth failing a run over — the browser may still be flushing —
|
|
259
|
+
// and the OS reclaims it.
|
|
260
|
+
try {
|
|
261
|
+
rmSync(profileDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
/* the OS will reclaim it */
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
let session;
|
|
268
|
+
try {
|
|
269
|
+
const endpoint = await readEndpoint(child, opts.timeoutMs);
|
|
270
|
+
session = await DevToolsSession.connect(endpoint, opts.timeoutMs);
|
|
271
|
+
const { targetId } = (await session.send('Target.createTarget', { url: 'about:blank' }));
|
|
272
|
+
const attached = (await session.send('Target.attachToTarget', { targetId, flatten: true }));
|
|
273
|
+
session.sessionId = attached.sessionId;
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
await cleanup();
|
|
277
|
+
throw err;
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
session,
|
|
281
|
+
close: async () => {
|
|
282
|
+
session.close();
|
|
283
|
+
await cleanup();
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=chrome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../src/local/chrome.ts"],"names":[],"mappings":"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"}
|