@browserless.io/browserless 2.2.0 → 2.3.0-beta-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.
Files changed (80) hide show
  1. package/bin/browserless.js +25 -14
  2. package/build/browserless.d.ts +6 -1
  3. package/build/browserless.js +38 -20
  4. package/build/exports.core.d.ts +24 -0
  5. package/build/exports.core.js +26 -0
  6. package/build/exports.d.ts +38 -24
  7. package/build/exports.js +44 -26
  8. package/build/routes/chrome/http/content.post.body.json +8 -8
  9. package/build/routes/chrome/http/download.post.body.json +489 -11
  10. package/build/routes/chrome/http/download.post.query.json +69 -6
  11. package/build/routes/chrome/http/download.post.response.json +1 -0
  12. package/build/routes/chrome/http/function.post.body.json +489 -11
  13. package/build/routes/chrome/http/function.post.query.json +69 -6
  14. package/build/routes/chrome/http/function.post.response.json +1 -0
  15. package/build/routes/chrome/http/json-list.get.response.json +1 -49
  16. package/build/routes/chrome/http/json-new.put.response.json +1 -41
  17. package/build/routes/chrome/http/json-protocol.get.response.json +1 -3
  18. package/build/routes/chrome/http/json-version.get.response.json +1 -41
  19. package/build/routes/chrome/http/pdf.post.body.json +9 -153
  20. package/build/routes/chrome/http/pdf.post.query.json +69 -6
  21. package/build/routes/chrome/http/performance.post.body.json +494 -10
  22. package/build/routes/chrome/http/performance.post.query.json +69 -6
  23. package/build/routes/chrome/http/performance.post.response.json +1 -3
  24. package/build/routes/chrome/http/scrape.post.body.json +9 -56
  25. package/build/routes/chrome/http/scrape.post.response.json +1 -305
  26. package/build/routes/chrome/http/screenshot.post.body.json +9 -99
  27. package/build/routes/chrome/http/screenshot.post.query.json +69 -6
  28. package/build/routes/chrome/ws/browser.query.json +69 -6
  29. package/build/routes/chrome/ws/cdp.query.json +69 -6
  30. package/build/routes/chrome/ws/page.query.json +69 -6
  31. package/build/routes/chrome/ws/playwright.query.json +90 -7
  32. package/build/routes/chromium/http/content.post.body.json +8 -8
  33. package/build/routes/chromium/http/download.post.body.json +489 -11
  34. package/build/routes/chromium/http/download.post.query.json +69 -6
  35. package/build/routes/chromium/http/download.post.response.json +1 -0
  36. package/build/routes/chromium/http/function.post.body.json +489 -11
  37. package/build/routes/chromium/http/function.post.query.json +69 -6
  38. package/build/routes/chromium/http/function.post.response.json +1 -0
  39. package/build/routes/chromium/http/json-list.get.response.json +1 -49
  40. package/build/routes/chromium/http/json-new.put.response.json +1 -41
  41. package/build/routes/chromium/http/json-protocol.get.response.json +1 -3
  42. package/build/routes/chromium/http/json-version.get.response.json +1 -41
  43. package/build/routes/chromium/http/pdf.post.body.json +9 -153
  44. package/build/routes/chromium/http/pdf.post.query.json +69 -6
  45. package/build/routes/chromium/http/performance.post.body.json +494 -10
  46. package/build/routes/chromium/http/performance.post.query.json +69 -6
  47. package/build/routes/chromium/http/performance.post.response.json +1 -3
  48. package/build/routes/chromium/http/scrape.post.body.json +9 -56
  49. package/build/routes/chromium/http/scrape.post.response.json +1 -305
  50. package/build/routes/chromium/http/screenshot.post.body.json +9 -99
  51. package/build/routes/chromium/http/screenshot.post.query.json +69 -6
  52. package/build/routes/chromium/ws/browser.query.json +69 -6
  53. package/build/routes/chromium/ws/cdp.query.json +69 -6
  54. package/build/routes/chromium/ws/page.query.json +69 -6
  55. package/build/routes/chromium/ws/playwright.query.json +90 -7
  56. package/build/routes/firefox/ws/playwright.d.ts +5 -1
  57. package/build/routes/firefox/ws/playwright.query.json +90 -7
  58. package/build/routes/management/http/config.get.response.json +1 -104
  59. package/build/routes/management/http/metrics-total.get.response.json +1 -69
  60. package/build/routes/management/http/metrics.get.response.json +1 -91
  61. package/build/routes/management/http/sessions.get.response.json +1 -232
  62. package/build/routes/management/http/static.get.js +7 -7
  63. package/build/routes/webkit/ws/playwright.query.json +90 -7
  64. package/build/shared/utils/performance/main.js +1 -1
  65. package/docker/chrome/Dockerfile +2 -0
  66. package/docker/chromium/Dockerfile +2 -0
  67. package/docker/firefox/Dockerfile +2 -0
  68. package/docker/multi/Dockerfile +2 -0
  69. package/docker/webkit/Dockerfile +2 -0
  70. package/package.json +1 -2
  71. package/scripts/build-open-api.js +18 -9
  72. package/scripts/build-schemas.js +2 -3
  73. package/src/browserless.ts +61 -36
  74. package/src/exports.core.ts +26 -0
  75. package/src/exports.ts +48 -26
  76. package/src/router.ts +6 -2
  77. package/src/routes/firefox/ws/playwright.ts +3 -1
  78. package/src/routes/management/http/static.get.ts +14 -9
  79. package/src/shared/utils/performance/main.ts +1 -2
  80. package/static/docs/swagger.json +1338 -2287
@@ -4,6 +4,8 @@ LABEL org.opencontainers.image.source https://github.com/browserless/browserless
4
4
 
5
5
  COPY fonts/* /usr/share/fonts/truetype/
6
6
  COPY src src/
7
+ # Only use core as exports since routes are lazy loaded and not always present
8
+ COPY src/exports.core.ts src/exports.ts
7
9
  RUN rm -r src/routes/
8
10
  COPY src/routes/management src/routes/management/
9
11
  COPY src/routes/firefox src/routes/firefox/
@@ -7,6 +7,8 @@ ENV TARGETPLATFORM=${TARGETPLATFORM}
7
7
 
8
8
  COPY fonts/* /usr/share/fonts/truetype/
9
9
  COPY src src/
10
+ # Only use core as exports since routes are lazy loaded and not always present
11
+ COPY src/exports.core.ts src/exports.ts
10
12
 
11
13
  RUN echo "ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true" | debconf-set-selections &&\
12
14
  apt-get -y -qq install software-properties-common &&\
@@ -5,6 +5,8 @@ LABEL org.opencontainers.image.source https://github.com/browserless/browserless
5
5
  # Install Fonts
6
6
  COPY fonts/* /usr/share/fonts/truetype/
7
7
  COPY src src/
8
+ # Only use core as exports since routes are lazy loaded and not always present
9
+ COPY src/exports.core.ts src/exports.ts
8
10
  RUN rm -r src/routes/
9
11
  COPY src/routes/management src/routes/management/
10
12
  COPY src/routes/webkit src/routes/webkit/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@browserless.io/browserless",
3
- "version": "2.2.0",
3
+ "version": "2.3.0-beta-1",
4
4
  "license": "SSPL",
5
5
  "description": "The browserless platform",
6
6
  "author": "browserless.io",
@@ -81,7 +81,6 @@
81
81
  "esbuild": "^0.20.1",
82
82
  "esbuild-plugin-polyfill-node": "^0.3.0",
83
83
  "eslint": "^8.56.0",
84
- "eslint-plugin-import": "^2.29.1",
85
84
  "eslint-plugin-typescript-sort-keys": "^3.1.0",
86
85
  "extract-zip": "^2.0.1",
87
86
  "marked": "^12.0.0",
@@ -3,9 +3,12 @@
3
3
  'use strict';
4
4
 
5
5
  import { join, parse } from 'path';
6
+ import { Config } from '../build/config.js';
6
7
  import { dirname } from 'path';
8
+ import { errorCodes } from '../build/http.js';
7
9
  import { fileURLToPath } from 'url';
8
10
  import fs from 'fs/promises';
11
+ import { getRouteFiles } from '../build/utils.js';
9
12
  import { marked } from 'marked';
10
13
 
11
14
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -39,17 +42,17 @@ const sortSwaggerRequiredAlpha = (prop, otherProp) => {
39
42
  return Number(otherProp.required) - Number(prop.required);
40
43
  };
41
44
 
45
+ const routeIsDisabled = (Route, DisabledRoutes) => {
46
+ const stringified = Route.toString();
47
+ return DisabledRoutes.some((r) => r.toString() === stringified);
48
+ };
49
+
42
50
  const buildOpenAPI = async (
43
51
  externalHTTPRoutes = [],
44
52
  externalWebSocketRoutes = [],
53
+ DisabledRoutes = [],
45
54
  ) => {
46
- const [{ getRouteFiles }, { Config }, { errorCodes }, packageJSON] =
47
- await Promise.all([
48
- import('../build/utils.js'),
49
- import('../build/config.js'),
50
- import('../build/http.js'),
51
- fs.readFile(packageJSONPath),
52
- ]);
55
+ const packageJSON = await fs.readFile(packageJSONPath);
53
56
 
54
57
  const isWin = process.platform === 'win32';
55
58
  const readme = (await fs.readFile('README.md').catch(() => '')).toString();
@@ -90,7 +93,12 @@ const buildOpenAPI = async (
90
93
  const routeImport = `${isWin ? 'file:///' : ''}${routeModule}`;
91
94
  const { default: Route } = await import(routeImport);
92
95
  if (!Route) {
93
- throw new Error(`Invalid route file to import docs ${routeModule}`);
96
+ throw new Error(
97
+ `Invalid route file found while building OpenAPI JSON: "${routeModule}"`,
98
+ );
99
+ }
100
+ if (routeIsDisabled(Route, DisabledRoutes)) {
101
+ return null;
94
102
  }
95
103
  const route = new Route();
96
104
  const { name } = parse(routeModule);
@@ -127,7 +135,8 @@ const buildOpenAPI = async (
127
135
  tags,
128
136
  title,
129
137
  };
130
- }),
138
+ })
139
+ .filter((r) => r !== null),
131
140
  );
132
141
 
133
142
  const paths = routeMetaData.reduce((accum, r) => {
@@ -2,6 +2,8 @@
2
2
  /* global console, process */
3
3
  'use strict';
4
4
 
5
+ import { getRouteFiles, tsExtension } from '../build/utils.js';
6
+ import { Config } from '../build/config.js';
5
7
  import TJS from 'typescript-json-schema';
6
8
  import fs from 'fs/promises';
7
9
  import path from 'path';
@@ -12,8 +14,6 @@ const buildSchemas = async (
12
14
  externalHTTPRoutes = [],
13
15
  externalWebSocketRoutes = [],
14
16
  ) => {
15
- const { getRouteFiles, tsExtension } = await import('../build/utils.js');
16
-
17
17
  const schemas = ['BodySchema', 'QuerySchema', 'ResponseSchema'];
18
18
  const settings = {
19
19
  ignoreErrors: true,
@@ -25,7 +25,6 @@ const buildSchemas = async (
25
25
  await fs.readFile('tsconfig.json', 'utf-8'),
26
26
  );
27
27
 
28
- const { Config } = await import('../build/config.js');
29
28
  const [httpRoutes, wsRoutes] = await getRouteFiles(new Config());
30
29
 
31
30
  // Depending on if we're parsing an external projects routes,
@@ -36,6 +36,12 @@ type Implements<T> = {
36
36
  new (...args: unknown[]): T;
37
37
  };
38
38
 
39
+ type RouteTypes =
40
+ | typeof HTTPRoute
41
+ | typeof BrowserHTTPRoute
42
+ | typeof WebSocketRoute
43
+ | typeof BrowserWebsocketRoute;
44
+
39
45
  export class Browserless {
40
46
  protected debug: debug.Debugger = createLogger('index');
41
47
  protected browserManager: BrowserManager;
@@ -48,6 +54,7 @@ export class Browserless {
48
54
  protected token: Token;
49
55
  protected webhooks: WebHooks;
50
56
 
57
+ DisabledRoutes: RouteTypes[] = [];
51
58
  webSocketRouteFiles: string[] = [];
52
59
  httpRouteFiles: string[] = [];
53
60
  server?: HTTPServer;
@@ -138,6 +145,15 @@ export class Browserless {
138
145
  );
139
146
  };
140
147
 
148
+ private routeIsDisabled(Route: RouteTypes) {
149
+ const Stringified = Route.toString();
150
+ return this.DisabledRoutes.some((r) => r.toString() === Stringified);
151
+ }
152
+
153
+ public disableRoute(Route: RouteTypes) {
154
+ this.DisabledRoutes.push(Route);
155
+ }
156
+
141
157
  public addHTTPRoute(httpRouteFilePath: string) {
142
158
  this.httpRouteFiles.push(httpRouteFilePath);
143
159
  }
@@ -171,7 +187,7 @@ export class Browserless {
171
187
  WebkitPlaywright,
172
188
  ];
173
189
 
174
- const [[httpRouteFiles, wsRouteFiles], installedBrowsers] =
190
+ const [[internalHttpRouteFiles, internalWsRouteFiles], installedBrowsers] =
175
191
  await Promise.all([getRouteFiles(this.config), availableBrowsers]);
176
192
 
177
193
  const docsLink = makeExternalURL(this.config.getExternalAddress(), '/docs');
@@ -180,7 +196,10 @@ export class Browserless {
180
196
  this.debug(`Running as user "${userInfo().username}"`);
181
197
  this.debug('Starting import of HTTP Routes');
182
198
 
183
- for (const httpRoute of [...httpRouteFiles, ...this.httpRouteFiles]) {
199
+ for (const httpRoute of [
200
+ ...internalHttpRouteFiles,
201
+ ...this.httpRouteFiles,
202
+ ]) {
184
203
  if (httpRoute.endsWith('js')) {
185
204
  const { name } = path.parse(httpRoute);
186
205
  const [bodySchema, querySchema] = await Promise.all(
@@ -201,28 +220,33 @@ export class Browserless {
201
220
  default: Route,
202
221
  }: { default: Implements<HTTPRoute> | Implements<BrowserHTTPRoute> } =
203
222
  await import(routeImport + `?cb=${Date.now()}`);
204
- const route = new Route(
205
- this.browserManager,
206
- this.config,
207
- this.fileSystem,
208
- logger,
209
- this.metrics,
210
- this.monitoring,
211
- );
212
- route.bodySchema = safeParse(bodySchema);
213
- route.querySchema = safeParse(querySchema);
214
- route.config = () => this.config;
215
- route.metrics = () => this.metrics;
216
- route.monitoring = () => this.monitoring;
217
- route.fileSystem = () => this.fileSystem;
218
- route.debug = () => logger;
219
-
220
- httpRoutes.push(route);
223
+ if (!this.routeIsDisabled(Route)) {
224
+ const route = new Route(
225
+ this.browserManager,
226
+ this.config,
227
+ this.fileSystem,
228
+ logger,
229
+ this.metrics,
230
+ this.monitoring,
231
+ );
232
+ route.bodySchema = safeParse(bodySchema);
233
+ route.querySchema = safeParse(querySchema);
234
+ route.config = () => this.config;
235
+ route.metrics = () => this.metrics;
236
+ route.monitoring = () => this.monitoring;
237
+ route.fileSystem = () => this.fileSystem;
238
+ route.debug = () => logger;
239
+
240
+ httpRoutes.push(route);
241
+ }
221
242
  }
222
243
  }
223
244
 
224
245
  this.debug('Starting import of WebSocket Routes');
225
- for (const wsRoute of [...wsRouteFiles, ...this.webSocketRouteFiles]) {
246
+ for (const wsRoute of [
247
+ ...internalWsRouteFiles,
248
+ ...this.webSocketRouteFiles,
249
+ ]) {
226
250
  if (wsRoute.endsWith('js')) {
227
251
  const { name } = path.parse(wsRoute);
228
252
  const [, querySchema] = await Promise.all(
@@ -246,23 +270,24 @@ export class Browserless {
246
270
  | Implements<WebSocketRoute>
247
271
  | Implements<BrowserWebsocketRoute>;
248
272
  } = await import(wsImport + `?cb=${Date.now()}`);
273
+ if (!this.routeIsDisabled(Route)) {
274
+ const route = new Route(
275
+ this.browserManager,
276
+ this.config,
277
+ this.fileSystem,
278
+ logger,
279
+ this.metrics,
280
+ this.monitoring,
281
+ );
282
+ route.querySchema = safeParse(querySchema);
283
+ route.config = () => this.config;
284
+ route.metrics = () => this.metrics;
285
+ route.monitoring = () => this.monitoring;
286
+ route.fileSystem = () => this.fileSystem;
287
+ route.debug = () => logger;
249
288
 
250
- const route = new Route(
251
- this.browserManager,
252
- this.config,
253
- this.fileSystem,
254
- logger,
255
- this.metrics,
256
- this.monitoring,
257
- );
258
- route.querySchema = safeParse(querySchema);
259
- route.config = () => this.config;
260
- route.metrics = () => this.metrics;
261
- route.monitoring = () => this.monitoring;
262
- route.fileSystem = () => this.fileSystem;
263
- route.debug = () => logger;
264
-
265
- wsRoutes.push(route);
289
+ wsRoutes.push(route);
290
+ }
266
291
  }
267
292
  }
268
293
 
@@ -0,0 +1,26 @@
1
+ // This file takes the place of 'exports.ts' when doing our docker builds
2
+ // since docker images are missing some/most of the browser routes depending.
3
+ export * from './browserless.js';
4
+ export * from './config.js';
5
+ export * from './constants.js';
6
+ export * from './file-system.js';
7
+ export * from './hooks.js';
8
+ export * from './http.js';
9
+ export * from './limiter.js';
10
+ export * from './metrics.js';
11
+ export * from './mime-types.js';
12
+ export * from './monitoring.js';
13
+ export * from './router.js';
14
+ export * from './server.js';
15
+ export * from './shim.js';
16
+ export * from './token.js';
17
+ export * from './types.js';
18
+ export * from './utils.js';
19
+ export * from './webhooks.js';
20
+ export * from './browsers/index.js';
21
+ export * from './browsers/chrome.cdp.js';
22
+ export * from './browsers/chrome.playwright.js';
23
+ export * from './browsers/chromium.cdp.js';
24
+ export * from './browsers/chromium.playwright.js';
25
+ export * from './browsers/firefox.playwright.js';
26
+ export * from './browsers/webkit.playwright.js';
package/src/exports.ts CHANGED
@@ -1,27 +1,49 @@
1
- // Main Files
2
- export * from './browserless.js';
3
- export * from './config.js';
4
- export * from './constants.js';
5
- export * from './file-system.js';
6
- export * from './hooks.js';
7
- export * from './http.js';
8
- export * from './limiter.js';
9
- export * from './metrics.js';
10
- export * from './mime-types.js';
11
- export * from './monitoring.js';
12
- export * from './router.js';
13
- export * from './server.js';
14
- export * from './shim.js';
15
- export * from './token.js';
16
- export * from './types.js';
17
- export * from './utils.js';
18
- export * from './webhooks.js';
1
+ // Core
2
+ export * from './exports.core.js';
19
3
 
20
- // Browsers and Helpers
21
- export * from './browsers/index.js';
22
- export * from './browsers/chrome.cdp.js';
23
- export * from './browsers/chrome.playwright.js';
24
- export * from './browsers/chromium.cdp.js';
25
- export * from './browsers/chromium.playwright.js';
26
- export * from './browsers/firefox.playwright.js';
27
- export * from './browsers/webkit.playwright.js';
4
+ // Chrome
5
+ export { default as ChromeContentPostRoute } from './routes/chrome/http/content.post.js';
6
+ export { default as ChromeDownloadPostRoute } from './routes/chrome/http/download.post.js';
7
+ export { default as ChromeFunctionPostRoute } from './routes/chrome/http/function.post.js';
8
+ export { default as ChromeJSONListGetRoute } from './routes/chrome/http/json-list.get.js';
9
+ export { default as ChromeJSONNewPutRoute } from './routes/chrome/http/json-new.put.js';
10
+ export { default as ChromeJSONProtocolGetRoute } from './routes/chrome/http/json-protocol.get.js';
11
+ export { default as ChromeJSONVersionGetRoute } from './routes/chrome/http/json-version.get.js';
12
+ export { default as ChromePDFPostRoute } from './routes/chrome/http/pdf.post.js';
13
+ export { default as ChromePerformancePostRoute } from './routes/chrome/http/performance.post.js';
14
+ export { default as ChromeScrapePostRoute } from './routes/chrome/http/scrape.post.js';
15
+ export { default as ChromeScreenshotPostRoute } from './routes/chrome/http/screenshot.post.js';
16
+ export { default as ChromeBrowserWebSocketRoute } from './routes/chrome/ws/browser.js';
17
+ export { default as ChromeCDPWebSocketRoute } from './routes/chrome/ws/cdp.js';
18
+ export { default as ChromePageWebSocketRoute } from './routes/chrome/ws/page.js';
19
+ export { default as ChromePlaywrightWebSocketRoute } from './routes/chrome/ws/playwright.js';
20
+
21
+ // Chromium
22
+ export { default as ChromiumContentPostRoute } from './routes/chromium/http/content.post.js';
23
+ export { default as ChromiumDownloadPostRoute } from './routes/chromium/http/download.post.js';
24
+ export { default as ChromiumFunctionPostRoute } from './routes/chromium/http/function.post.js';
25
+ export { default as ChromiumJSONListGetRoute } from './routes/chromium/http/json-list.get.js';
26
+ export { default as ChromiumJSONNewPutRoute } from './routes/chromium/http/json-new.put.js';
27
+ export { default as ChromiumJSONProtocolGetRoute } from './routes/chromium/http/json-protocol.get.js';
28
+ export { default as ChromiumJSONVersionGetRoute } from './routes/chromium/http/json-version.get.js';
29
+ export { default as ChromiumPDFPostRoute } from './routes/chromium/http/pdf.post.js';
30
+ export { default as ChromiumPerformancePostRoute } from './routes/chromium/http/performance.post.js';
31
+ export { default as ChromiumScrapePostRoute } from './routes/chromium/http/scrape.post.js';
32
+ export { default as ChromiumScreenshotPostRoute } from './routes/chromium/http/screenshot.post.js';
33
+ export { default as ChromiumBrowserWebSocketRoute } from './routes/chromium/ws/browser.js';
34
+ export { default as ChromiumCDPWebSocketRoute } from './routes/chromium/ws/cdp.js';
35
+ export { default as ChromiumPageWebSocketRoute } from './routes/chromium/ws/page.js';
36
+ export { default as ChromiumPlaywrightWebSocketRoute } from './routes/chromium/ws/playwright.js';
37
+
38
+ // Firefox
39
+ export { default as FirefoxPlaywrightWebSocketRoute } from './routes/firefox/ws/playwright.js';
40
+
41
+ // WebKit
42
+ export { default as WebKitPlaywrightWebSocketRoute } from './routes/webkit/ws/playwright.js';
43
+
44
+ // Management
45
+ export { default as ConfigGetRoute } from './routes/management/http/config.get.js';
46
+ export { default as MetricsTotalGetRoute } from './routes/management/http/metrics-total.get.js';
47
+ export { default as MetricsGetRoute } from './routes/management/http/metrics.get.js';
48
+ export { default as SessionsGetGetRoute } from './routes/management/http/sessions.get.js';
49
+ export { default as StaticGetRoute } from './routes/management/http/static.get.js';
package/src/router.ts CHANGED
@@ -166,7 +166,9 @@ export class Router {
166
166
  : wrapped;
167
167
  route.path = Array.isArray(route.path) ? route.path : [route.path];
168
168
  const registeredPaths = this.httpRoutes.map((r) => r.path).flat();
169
- const duplicatePaths = registeredPaths.filter((path) => route.path.includes(path));
169
+ const duplicatePaths = registeredPaths.filter((path) =>
170
+ route.path.includes(path),
171
+ );
170
172
 
171
173
  if (duplicatePaths.length) {
172
174
  this.log(`Found duplicate routes: ${duplicatePaths.join(', ')}`);
@@ -194,7 +196,9 @@ export class Router {
194
196
  : wrapped;
195
197
  route.path = Array.isArray(route.path) ? route.path : [route.path];
196
198
  const registeredPaths = this.webSocketRoutes.map((r) => r.path).flat();
197
- const duplicatePaths = registeredPaths.filter((path) => route.path.includes(path));
199
+ const duplicatePaths = registeredPaths.filter((path) =>
200
+ route.path.includes(path),
201
+ );
198
202
 
199
203
  if (duplicatePaths.length) {
200
204
  this.log(`Found duplicate routes: ${duplicatePaths.join(', ')}`);
@@ -11,7 +11,9 @@ import {
11
11
  import { Duplex } from 'stream';
12
12
 
13
13
  export interface QuerySchema extends SystemQueryParameters {
14
- launch?: BrowserServerOptions | string;
14
+ launch?: BrowserServerOptions & {
15
+ firefoxUserPrefs?: { [key: string]: string | number | boolean };
16
+ };
15
17
  }
16
18
 
17
19
  export default class FirefoxPlayWrightRoute extends BrowserWebsocketRoute {
@@ -6,7 +6,6 @@ import {
6
6
  NotFound,
7
7
  Request,
8
8
  contentTypes,
9
- createLogger,
10
9
  fileExists,
11
10
  mimeTypes,
12
11
  } from '@browserless.io/browserless';
@@ -14,9 +13,6 @@ import { ServerResponse } from 'http';
14
13
  import { createReadStream } from 'fs';
15
14
  import path from 'path';
16
15
 
17
- const debug = createLogger('http:static');
18
- const verbose = createLogger('http:static:verbose');
19
-
20
16
  const pathMap: Map<
21
17
  string,
22
18
  {
@@ -25,10 +21,15 @@ const pathMap: Map<
25
21
  }
26
22
  > = new Map();
27
23
 
28
- const streamFile = (res: ServerResponse, file: string, contentType?: string) =>
24
+ const streamFile = (
25
+ debug: debug.Debugger,
26
+ res: ServerResponse,
27
+ file: string,
28
+ contentType?: string,
29
+ ) =>
29
30
  new Promise((resolve, reject) => {
30
31
  if (contentType) {
31
- verbose(`Setting content-type ${contentType}`);
32
+ debug(`Setting content-type ${contentType}`);
32
33
  res.setHeader('Content-Type', contentType);
33
34
  }
34
35
 
@@ -59,9 +60,11 @@ export default class StaticGetRoute extends HTTPRoute {
59
60
  handler = async (req: Request, res: ServerResponse): Promise<unknown> => {
60
61
  const { pathname } = req.parsed;
61
62
  const fileCache = pathMap.get(pathname);
63
+ const debug = this.debug();
64
+ const verbose = debug.extend('verbose');
62
65
 
63
66
  if (fileCache) {
64
- return streamFile(res, fileCache.path, fileCache.contentType);
67
+ return streamFile(verbose, res, fileCache.path, fileCache.contentType);
65
68
  }
66
69
 
67
70
  const config = this.config();
@@ -78,7 +81,9 @@ export default class StaticGetRoute extends HTTPRoute {
78
81
  ).find((_) => !!_);
79
82
 
80
83
  if (!filePath) {
81
- throw new NotFound(`No route or file found for resource ${req.method}: ${pathname}`);
84
+ throw new NotFound(
85
+ `No route or file found for resource ${req.method}: ${pathname}`,
86
+ );
82
87
  }
83
88
 
84
89
  verbose(`Found new file "${filePath}", caching path and serving`);
@@ -96,6 +101,6 @@ export default class StaticGetRoute extends HTTPRoute {
96
101
  path: filePath,
97
102
  });
98
103
 
99
- return streamFile(res, filePath, contentType);
104
+ return streamFile(verbose, res, filePath, contentType);
100
105
  };
101
106
  }
@@ -7,14 +7,13 @@ const DEFAULT_AUDIT_CONFIG = {
7
7
  extends: 'lighthouse:default',
8
8
  };
9
9
 
10
- const debug = createLogger('http:performance:main');
11
-
12
10
  export default async ({
13
11
  browser,
14
12
  context,
15
13
  timeout,
16
14
  }: mainOptions): Promise<unknown> => {
17
15
  return new Promise((resolve, reject) => {
16
+ const debug = createLogger('http:performance:main');
18
17
  const childPath = path.join(
19
18
  './',
20
19
  'build',