@browserless.io/browserless 2.3.0-beta-1 → 2.3.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.
Files changed (208) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/README.md +2 -2
  3. package/bin/browserless.js +47 -18
  4. package/bin/scaffold/README.md +50 -0
  5. package/bin/scaffold/src/hello-world.http.ts +2 -1
  6. package/build/browserless.d.ts +3 -5
  7. package/build/browserless.js +17 -11
  8. package/build/browsers/chrome.cdp.js +1 -1
  9. package/build/browsers/chrome.playwright.js +1 -1
  10. package/build/browsers/index.d.ts +1 -0
  11. package/build/browsers/index.js +4 -1
  12. package/build/data/classes.json +1 -1
  13. package/build/data/selectors.json +1 -1
  14. package/build/exports.d.ts +24 -38
  15. package/build/exports.js +25 -44
  16. package/build/limiter.d.ts +2 -1
  17. package/build/limiter.js +6 -3
  18. package/build/routes/chrome/http/content.post.body.json +8 -8
  19. package/build/routes/chrome/http/content.post.d.ts +2 -1
  20. package/build/routes/chrome/http/content.post.js +3 -2
  21. package/build/routes/chrome/http/download.post.body.json +11 -489
  22. package/build/routes/chrome/http/download.post.d.ts +2 -1
  23. package/build/routes/chrome/http/download.post.js +3 -2
  24. package/build/routes/chrome/http/download.post.query.json +6 -69
  25. package/build/routes/chrome/http/download.post.response.json +0 -1
  26. package/build/routes/chrome/http/function.post.body.json +11 -489
  27. package/build/routes/chrome/http/function.post.d.ts +2 -1
  28. package/build/routes/chrome/http/function.post.js +3 -2
  29. package/build/routes/chrome/http/function.post.query.json +6 -69
  30. package/build/routes/chrome/http/function.post.response.json +0 -1
  31. package/build/routes/chrome/http/json-list.get.d.ts +5 -1
  32. package/build/routes/chrome/http/json-list.get.js +5 -1
  33. package/build/routes/chrome/http/json-list.get.response.json +49 -1
  34. package/build/routes/chrome/http/json-new.put.d.ts +5 -1
  35. package/build/routes/chrome/http/json-new.put.js +5 -1
  36. package/build/routes/chrome/http/json-new.put.response.json +41 -1
  37. package/build/routes/chrome/http/json-protocol.get.d.ts +5 -1
  38. package/build/routes/chrome/http/json-protocol.get.js +5 -1
  39. package/build/routes/chrome/http/json-protocol.get.response.json +3 -1
  40. package/build/routes/chrome/http/json-version.get.d.ts +5 -1
  41. package/build/routes/chrome/http/json-version.get.js +5 -1
  42. package/build/routes/chrome/http/json-version.get.response.json +41 -1
  43. package/build/routes/chrome/http/pdf.post.body.json +153 -9
  44. package/build/routes/chrome/http/pdf.post.d.ts +2 -1
  45. package/build/routes/chrome/http/pdf.post.js +3 -2
  46. package/build/routes/chrome/http/pdf.post.query.json +6 -69
  47. package/build/routes/chrome/http/performance.post.body.json +10 -494
  48. package/build/routes/chrome/http/performance.post.d.ts +2 -1
  49. package/build/routes/chrome/http/performance.post.js +3 -2
  50. package/build/routes/chrome/http/performance.post.query.json +6 -69
  51. package/build/routes/chrome/http/performance.post.response.json +3 -1
  52. package/build/routes/chrome/http/scrape.post.body.json +56 -9
  53. package/build/routes/chrome/http/scrape.post.d.ts +2 -1
  54. package/build/routes/chrome/http/scrape.post.js +3 -2
  55. package/build/routes/chrome/http/scrape.post.response.json +305 -1
  56. package/build/routes/chrome/http/screenshot.post.body.json +99 -9
  57. package/build/routes/chrome/http/screenshot.post.d.ts +2 -1
  58. package/build/routes/chrome/http/screenshot.post.js +3 -2
  59. package/build/routes/chrome/http/screenshot.post.query.json +6 -69
  60. package/build/routes/chrome/ws/browser.d.ts +2 -1
  61. package/build/routes/chrome/ws/browser.js +3 -2
  62. package/build/routes/chrome/ws/browser.query.json +6 -69
  63. package/build/routes/chrome/ws/cdp.d.ts +2 -1
  64. package/build/routes/chrome/ws/cdp.js +3 -2
  65. package/build/routes/chrome/ws/cdp.query.json +6 -69
  66. package/build/routes/chrome/ws/page.d.ts +3 -2
  67. package/build/routes/chrome/ws/page.js +3 -2
  68. package/build/routes/chrome/ws/page.query.json +6 -69
  69. package/build/routes/chrome/ws/playwright.d.ts +1 -0
  70. package/build/routes/chrome/ws/playwright.js +2 -1
  71. package/build/routes/chrome/ws/playwright.query.json +7 -90
  72. package/build/routes/chromium/http/content.post.body.json +8 -8
  73. package/build/routes/chromium/http/download.post.body.json +11 -489
  74. package/build/routes/chromium/http/download.post.query.json +6 -69
  75. package/build/routes/chromium/http/download.post.response.json +0 -1
  76. package/build/routes/chromium/http/function.post.body.json +11 -489
  77. package/build/routes/chromium/http/function.post.query.json +6 -69
  78. package/build/routes/chromium/http/function.post.response.json +0 -1
  79. package/build/routes/chromium/http/json-list.get.response.json +49 -1
  80. package/build/routes/chromium/http/json-new.put.response.json +41 -1
  81. package/build/routes/chromium/http/json-protocol.get.response.json +3 -1
  82. package/build/routes/chromium/http/json-version.get.response.json +41 -1
  83. package/build/routes/chromium/http/pdf.post.body.json +153 -9
  84. package/build/routes/chromium/http/pdf.post.query.json +6 -69
  85. package/build/routes/chromium/http/performance.post.body.json +10 -494
  86. package/build/routes/chromium/http/performance.post.query.json +6 -69
  87. package/build/routes/chromium/http/performance.post.response.json +3 -1
  88. package/build/routes/chromium/http/scrape.post.body.json +56 -9
  89. package/build/routes/chromium/http/scrape.post.response.json +305 -1
  90. package/build/routes/chromium/http/screenshot.post.body.json +99 -9
  91. package/build/routes/chromium/http/screenshot.post.query.json +6 -69
  92. package/build/routes/chromium/ws/browser.query.json +6 -69
  93. package/build/routes/chromium/ws/cdp.query.json +6 -69
  94. package/build/routes/chromium/ws/page.query.json +6 -69
  95. package/build/routes/chromium/ws/playwright.query.json +7 -90
  96. package/build/routes/firefox/ws/playwright.d.ts +2 -1
  97. package/build/routes/firefox/ws/playwright.js +3 -2
  98. package/build/routes/firefox/ws/playwright.query.json +30 -115
  99. package/build/routes/management/http/config.get.d.ts +1 -0
  100. package/build/routes/management/http/config.get.js +2 -1
  101. package/build/routes/management/http/config.get.response.json +104 -1
  102. package/build/routes/management/http/metrics-total.get.d.ts +1 -0
  103. package/build/routes/management/http/metrics-total.get.js +2 -1
  104. package/build/routes/management/http/metrics-total.get.response.json +69 -1
  105. package/build/routes/management/http/metrics.get.d.ts +1 -0
  106. package/build/routes/management/http/metrics.get.js +2 -1
  107. package/build/routes/management/http/metrics.get.response.json +91 -1
  108. package/build/routes/management/http/sessions.get.d.ts +1 -0
  109. package/build/routes/management/http/sessions.get.js +2 -1
  110. package/build/routes/management/http/sessions.get.response.json +232 -1
  111. package/build/routes/management/http/static.get.d.ts +1 -0
  112. package/build/routes/management/http/static.get.js +2 -1
  113. package/build/routes/webkit/ws/playwright.d.ts +2 -1
  114. package/build/routes/webkit/ws/playwright.js +3 -2
  115. package/build/routes/webkit/ws/playwright.query.json +7 -90
  116. package/build/shared/browser.ws.d.ts +2 -1
  117. package/build/shared/browser.ws.js +3 -2
  118. package/build/shared/chromium.playwright.ws.d.ts +2 -1
  119. package/build/shared/chromium.playwright.ws.js +3 -2
  120. package/build/shared/chromium.ws.d.ts +2 -1
  121. package/build/shared/chromium.ws.js +3 -2
  122. package/build/shared/content.http.d.ts +2 -1
  123. package/build/shared/content.http.js +3 -2
  124. package/build/shared/download.http.d.ts +2 -1
  125. package/build/shared/download.http.js +3 -2
  126. package/build/shared/function.http.d.ts +2 -1
  127. package/build/shared/function.http.js +3 -2
  128. package/build/shared/json-list.http.d.ts +2 -1
  129. package/build/shared/json-list.http.js +3 -2
  130. package/build/shared/json-new.http.d.ts +2 -1
  131. package/build/shared/json-new.http.js +3 -2
  132. package/build/shared/json-protocol.http.d.ts +2 -1
  133. package/build/shared/json-protocol.http.js +3 -2
  134. package/build/shared/json-version.http.d.ts +2 -1
  135. package/build/shared/json-version.http.js +3 -2
  136. package/build/shared/page.ws.d.ts +2 -1
  137. package/build/shared/page.ws.js +3 -2
  138. package/build/shared/pdf.http.d.ts +2 -1
  139. package/build/shared/pdf.http.js +3 -2
  140. package/build/shared/performance.http.d.ts +1 -0
  141. package/build/shared/performance.http.js +2 -1
  142. package/build/shared/scrape.http.d.ts +2 -1
  143. package/build/shared/scrape.http.js +3 -2
  144. package/build/shared/screenshot.http.d.ts +1 -0
  145. package/build/shared/screenshot.http.js +2 -1
  146. package/build/types.d.ts +91 -0
  147. package/build/types.js +54 -0
  148. package/build/utils.d.ts +1 -1
  149. package/build/utils.js +11 -6
  150. package/docker/chrome/Dockerfile +0 -2
  151. package/docker/chromium/Dockerfile +1 -4
  152. package/docker/firefox/Dockerfile +1 -4
  153. package/docker/multi/Dockerfile +2 -6
  154. package/docker/webkit/Dockerfile +1 -4
  155. package/package.json +11 -10
  156. package/scripts/build-open-api.js +150 -141
  157. package/scripts/build-schemas.js +3 -2
  158. package/src/browserless.ts +43 -30
  159. package/src/browsers/chrome.cdp.ts +1 -1
  160. package/src/browsers/chrome.playwright.ts +1 -1
  161. package/src/browsers/index.ts +5 -1
  162. package/src/exports.ts +25 -49
  163. package/src/limiter.ts +7 -3
  164. package/src/routes/chrome/http/content.post.ts +7 -2
  165. package/src/routes/chrome/http/download.post.ts +7 -2
  166. package/src/routes/chrome/http/function.post.ts +7 -2
  167. package/src/routes/chrome/http/json-list.get.ts +7 -1
  168. package/src/routes/chrome/http/json-new.put.ts +7 -1
  169. package/src/routes/chrome/http/json-protocol.get.ts +7 -1
  170. package/src/routes/chrome/http/json-version.get.ts +7 -1
  171. package/src/routes/chrome/http/pdf.post.ts +7 -2
  172. package/src/routes/chrome/http/performance.post.ts +7 -2
  173. package/src/routes/chrome/http/scrape.post.ts +7 -2
  174. package/src/routes/chrome/http/screenshot.post.ts +7 -2
  175. package/src/routes/chrome/ws/browser.ts +3 -2
  176. package/src/routes/chrome/ws/cdp.ts +7 -2
  177. package/src/routes/chrome/ws/page.ts +3 -2
  178. package/src/routes/chrome/ws/playwright.ts +6 -1
  179. package/src/routes/firefox/ws/playwright.ts +3 -1
  180. package/src/routes/management/http/config.get.ts +2 -0
  181. package/src/routes/management/http/metrics-total.get.ts +2 -0
  182. package/src/routes/management/http/metrics.get.ts +2 -0
  183. package/src/routes/management/http/sessions.get.ts +2 -0
  184. package/src/routes/management/http/static.get.ts +2 -0
  185. package/src/routes/webkit/ws/playwright.ts +3 -1
  186. package/src/shared/browser.ws.ts +3 -1
  187. package/src/shared/chromium.playwright.ws.ts +3 -1
  188. package/src/shared/chromium.ws.ts +3 -1
  189. package/src/shared/content.http.ts +3 -1
  190. package/src/shared/download.http.ts +3 -1
  191. package/src/shared/function.http.ts +3 -1
  192. package/src/shared/json-list.http.ts +3 -1
  193. package/src/shared/json-new.http.ts +3 -1
  194. package/src/shared/json-protocol.http.ts +3 -1
  195. package/src/shared/json-version.http.ts +3 -1
  196. package/src/shared/page.ws.ts +3 -1
  197. package/src/shared/pdf.http.ts +3 -1
  198. package/src/shared/performance.http.ts +2 -0
  199. package/src/shared/scrape.http.ts +3 -1
  200. package/src/shared/screenshot.http.ts +2 -0
  201. package/src/types.ts +66 -0
  202. package/src/utils.ts +13 -7
  203. package/static/docs/swagger.json +2511 -1520
  204. package/static/docs/swagger.min.json +6697 -0
  205. package/static/function/client.js +323 -323
  206. package/build/exports.core.d.ts +0 -24
  207. package/build/exports.core.js +0 -26
  208. package/src/exports.core.ts +0 -26
package/CHANGELOG.md CHANGED
@@ -1,4 +1,12 @@
1
- # [Latest](https://github.com/browserless/chrome/compare/v2.2.0...main)
1
+ # [Latest](https://github.com/browserless/chrome/compare/v2.3.0...main)
2
+ - Dependency updates.
3
+
4
+ # [v2.3.0](https://github.com/browserless/chrome/compare/v2.2.0...v2.3.0)
5
+ **Potentially Breaking**
6
+ - Routes must define a unique `name` property in order to remove them in SDK projects.
7
+ - A new `browserless` object in the SDK `package.json` file can specify module overrides, in camelCase, instead of using a path-based semantic.
8
+ - Fixes issues with `npx playwright-core install...` potentially installing other browser versions than what is a dependency of Browserless.
9
+ - Fixes and other general improvements.
2
10
  - Dependency updates.
3
11
 
4
12
  # [v2.2.0](https://github.com/browserless/chrome/compare/v2.1.0...v2.2.0)
package/README.md CHANGED
@@ -23,7 +23,7 @@ If you've been struggling to deploy headless browsers without running into issue
23
23
  4. [Hosting](#hosting-providers)
24
24
  5. [Puppeteer](#puppeteer)
25
25
  6. [Playwright](#playwright)
26
- 7. [Extending with NodeJS SDK](#extending-nodejs-skd)
26
+ 7. [Extending with NodeJS SDK](#extending-nodejs-sdk)
27
27
  8. [Licensing](#licensing)
28
28
  9. [Changelog](https://github.com/browserless/chrome/blob/master/CHANGELOG.md)
29
29
 
@@ -102,7 +102,7 @@ const browser = await pw.chromium.connectOverCDP('ws://localhost:3000');
102
102
 
103
103
  After that, the rest of your code remains the same with no other changes required.
104
104
 
105
- # Extending (NodeJS SKD)
105
+ # Extending (NodeJS SDK)
106
106
 
107
107
  Browserless comes with built-in extension capabilities, and allows for extending nearly any aspect of the system (for Version 2+). For more details on how to write your own routes, build docker images, and more, [see our SDK README.md](/bin/scaffold/README.md) or simply run "npx @browserless.io/browserless create" in a terminal and follow the onscreen prompts.
108
108
 
@@ -33,11 +33,6 @@ const allowedCMDs = [
33
33
  'help',
34
34
  'clean',
35
35
  ];
36
- const projectDir = process.cwd();
37
- const compiledDir = path.join(projectDir, 'build');
38
- const packageJSON = readFile(path.join(__dirname, '..', 'package.json')).then(
39
- (r) => JSON.parse(r.toString()),
40
- );
41
36
 
42
37
  if (!allowedCMDs.includes(cmd)) {
43
38
  throw new Error(
@@ -45,6 +40,21 @@ if (!allowedCMDs.includes(cmd)) {
45
40
  );
46
41
  }
47
42
 
43
+ const projectDir = process.cwd();
44
+ const buildDir = 'build';
45
+ const srcDir = 'src';
46
+ const compiledDir = path.join(projectDir, buildDir);
47
+
48
+ const projectPackageJSON = readFile(path.join(projectDir, 'package.json'))
49
+ .then((r) => JSON.parse(r.toString()))
50
+ .catch(() => null);
51
+
52
+ const browserlessPackageJSON = readFile(
53
+ path.join(__dirname, '..', 'package.json'),
54
+ ).then((r) => JSON.parse(r.toString()));
55
+
56
+ const camelCase = (str) => str.replace(/-([a-z])/g, (_, w) => w.toUpperCase());
57
+
48
58
  const prompt = async (question) => {
49
59
  const rl = createInterface({
50
60
  input: process.stdin,
@@ -60,7 +70,28 @@ const prompt = async (question) => {
60
70
  });
61
71
  };
62
72
 
73
+ const translateSrcToBuild = (directory) => {
74
+ const srcToBuild = directory.replace(srcDir, '');
75
+ const pathParsed = path.parse(srcToBuild);
76
+ return path.format({ ...pathParsed, base: '', ext: '.js' });
77
+ };
78
+
63
79
  const importDefault = async (files, fileName) => {
80
+ const pJSON = await projectPackageJSON;
81
+ // Check first if overrides are manually specified in the project's package.json
82
+ if (pJSON && pJSON.browserless && typeof pJSON.browserless === 'object') {
83
+ const camelCaseFileName = camelCase(fileName);
84
+ const relativePath = pJSON.browserless[camelCaseFileName];
85
+ if (relativePath) {
86
+ const fullFilePath = path.join(
87
+ compiledDir,
88
+ translateSrcToBuild(relativePath),
89
+ );
90
+ log(`Importing module from package.json: "${fullFilePath}"`);
91
+ return (await import(fullFilePath)).default;
92
+ }
93
+ }
94
+
64
95
  const classModuleFile = files.find((f) =>
65
96
  path.parse(f).name.endsWith(fileName),
66
97
  );
@@ -74,7 +105,7 @@ const importDefault = async (files, fileName) => {
74
105
  if (!classModuleFile) {
75
106
  return;
76
107
  }
77
- log(`Importing module "${fullFilePath}"`);
108
+ log(`Importing module from found files: "${fullFilePath}"`);
78
109
  return (await import(fullFilePath)).default;
79
110
  };
80
111
 
@@ -120,7 +151,7 @@ const buildDockerImage = async (cmd) => {
120
151
 
121
152
  const buildTypeScript = async () =>
122
153
  new Promise((resolve, reject) => {
123
- spawn('npx', ['tsc', '--outDir', 'build'], {
154
+ spawn('npx', ['tsc', '--outDir', buildDir], {
124
155
  cwd: projectDir,
125
156
  stdio: 'inherit',
126
157
  }).once('close', (code) => {
@@ -209,7 +240,8 @@ const build = async () => {
209
240
  );
210
241
 
211
242
  log(`Generating OpenAPI JSON file`);
212
- await buildOpenAPI(httpRoutes, webSocketRoutes);
243
+ const disabledRoutes = await importDefault(files, 'disabled-routes');
244
+ await buildOpenAPI(httpRoutes, webSocketRoutes, disabledRoutes);
213
245
 
214
246
  log(`All built assets complete`);
215
247
 
@@ -239,7 +271,7 @@ const start = async (dev = false) => {
239
271
  Router,
240
272
  Token,
241
273
  Webhooks,
242
- DisabledRoutes,
274
+ disabledRoutes,
243
275
  ] = await Promise.all([
244
276
  importDefault(files, 'browser-manager'),
245
277
  importDefault(files, 'config'),
@@ -287,13 +319,13 @@ const start = async (dev = false) => {
287
319
  webhooks,
288
320
  });
289
321
 
290
- if (DisabledRoutes !== undefined) {
291
- if (!Array.isArray(DisabledRoutes)) {
322
+ if (disabledRoutes !== undefined) {
323
+ if (!Array.isArray(disabledRoutes)) {
292
324
  throw new Error(
293
325
  `The "disabled-routes.ts" default export should be an array of Route classes.`,
294
326
  );
295
327
  }
296
- DisabledRoutes.forEach((R) => browserless.disableRoute(R));
328
+ browserless.disableRoutes(...disabledRoutes);
297
329
  }
298
330
 
299
331
  httpRoutes.forEach((r) => browserless.addHTTPRoute(r));
@@ -339,7 +371,7 @@ const start = async (dev = false) => {
339
371
  };
340
372
 
341
373
  const buildDocker = async () => {
342
- const finalDockerPath = path.join(projectDir, 'build', 'Dockerfile');
374
+ const finalDockerPath = path.join(compiledDir, 'Dockerfile');
343
375
  const argSwitches = getArgSwitches();
344
376
 
345
377
  await build();
@@ -350,10 +382,7 @@ const buildDocker = async () => {
350
382
 
351
383
  log(`Generating Dockerfile at "${finalDockerPath}"`);
352
384
 
353
- await fs.writeFile(
354
- path.join(projectDir, 'build', 'Dockerfile'),
355
- dockerContents,
356
- );
385
+ await fs.writeFile(compiledDir, dockerContents);
357
386
 
358
387
  const from =
359
388
  argSwitches.from ||
@@ -435,7 +464,7 @@ const create = async () => {
435
464
  const to = path.join(installPath, sdkFile);
436
465
  if (sdkFile === 'package.json') {
437
466
  const sdkPackageJSONTemplate = (await readFile(from)).toString();
438
- const { version } = await packageJSON;
467
+ const { version } = await browserlessPackageJSON;
439
468
  const sdkPackageJSON = sdkPackageJSONTemplate.replace(
440
469
  '${BROWSERLESS_VERSION}',
441
470
  version,
@@ -13,6 +13,7 @@ Finally, this SDK and Browserless.io are built to support businesses and enterpr
13
13
  - [Routing](#routing)
14
14
  - [Utilities](#utilities)
15
15
  - [Extending Modules](#extending-modules)
16
+ - [Disabling Routes](#dis)
16
17
  - [Running in Development](#running-in-development)
17
18
  - [Building for Production](#building-for-production)
18
19
  - [Running without Building](#running-without-building)
@@ -133,6 +134,9 @@ export type ResponseSchema = string;
133
134
 
134
135
  // Similar to React and other ecosystems, extend our basic HTTPRoute
135
136
  export default class HelloWorldRoute extends HTTPRoute {
137
+ // Must have a unique name for things like disabling to work if desired
138
+ name = 'PDFToS3Route';
139
+
136
140
  // Detail any content-types that this route should except. "contentTypes.any" here means any content-type.
137
141
  // If the content-type does not match then a 404 will be sent back
138
142
  accepts = [contentTypes.any];
@@ -192,6 +196,9 @@ export interface QuerySchema extends SystemQueryParameters {
192
196
  }
193
197
 
194
198
  export default class ChromiumWebSocketRoute extends BrowserWebsocketRoute {
199
+ // Must have a unique name for things like disabling to work if desired
200
+ name = 'ChromiumWebSocketRoute';
201
+
195
202
  // This route requires a valid authorization token.
196
203
  auth = true;
197
204
 
@@ -297,6 +304,9 @@ export interface BodySchema {
297
304
  }
298
305
 
299
306
  export default class PDFToS3Route extends BrowserHTTPRoute {
307
+ // Must have a unique name for things like disabling to work if desired
308
+ name = 'PDFToS3Route';
309
+
300
310
  // Our route only accepts JSON content-types, and the rest 404
301
311
  accepts = [contentTypes.json];
302
312
 
@@ -347,6 +357,46 @@ export default class PDFToS3Route extends BrowserHTTPRoute {
347
357
 
348
358
  With this approach you can effectively write, extend and author your own workflows within browserless!
349
359
 
360
+ ## Disabling Routes
361
+
362
+ You can disable access to core routes by specifying the route names you want to disable in a file named `disabled-routes.ts`. Browserless will scan all directories for a file named as such, and disable the named classes exported by this file. The alternative is to create a `browserless` property in your package.json file that contains a `disabledRoutes` string pointing to the relative path of your disabled routes file.
363
+
364
+ For example, if you want to disable all metrics, config, and session information your `src/disabled-routes.ts` file would look like this:
365
+
366
+ ```ts
367
+ import { BrowserlessRoutes } from '@browserless.io/browserless';
368
+
369
+ export default [
370
+ BrowserlessRoutes.ConfigGetRoute,
371
+ BrowserlessRoutes.SessionsGetGetRoute,
372
+ BrowserlessRoutes.MetricsGetRoute,
373
+ BrowserlessRoutes.MetricsTotalGetRoute,
374
+ ];
375
+ ```
376
+
377
+ And in the package.json file, it'd look like this:
378
+
379
+ ```json
380
+ {
381
+ // ... lots of package.json stuff
382
+ "browserless": {
383
+ "disabledRoutes": "./src/disabled-routes.ts"
384
+ }
385
+ }
386
+ ```
387
+
388
+ In order for route-disabling to work, you must have a `default` export that's an array of names. Browserless exports every route name it builds and runs internally, meaning you simply need to pass them through this `disabled-routes.ts` file after importing them.
389
+
390
+ Disabling a route will do several things:
391
+
392
+ - Return a `404` HTTP response when trying to call any of these routes.
393
+ - Remove them from the embedded documentation site that is auto-generated.
394
+ - Removes them from the OpenAPI JSON Schematic.
395
+ - Prevents their type information from being converted from TypeScript to runtime validation.
396
+ - It doesn't, however, remove them from Node's Module cache.
397
+
398
+ All of Browserless' internal routes are side-effect free, meaning their largely state-less and don't do exhibit kind of behavior aside from route handling and metrics reporting. Having them in Node's module cache is fine since they're never mounted in the router and set up as a potential route.
399
+
350
400
  ## Running in Development
351
401
 
352
402
  After the project has been set up, you can use npm commands to build and run your code. The most important of these is the `npm run dev` command, which will do the following:
@@ -10,7 +10,8 @@ import {
10
10
 
11
11
  export type ResponseSchema = string;
12
12
 
13
- export default class HelloWorldRoute extends HTTPRoute {
13
+ export default class HelloWorldHTTPRoute extends HTTPRoute {
14
+ name = 'HelloWorldHTTPRoute';
14
15
  accepts = [contentTypes.any];
15
16
  auth = true;
16
17
  browser = null;
@@ -1,7 +1,6 @@
1
1
  /// <reference types="debug" />
2
2
  /// <reference types="node" />
3
- import { BrowserHTTPRoute, BrowserManager, BrowserWebsocketRoute, Config, FileSystem, HTTPRoute, HTTPServer, Limiter, Metrics, Monitoring, Router, Token, WebHooks, WebSocketRoute } from '@browserless.io/browserless';
4
- type RouteTypes = typeof HTTPRoute | typeof BrowserHTTPRoute | typeof WebSocketRoute | typeof BrowserWebsocketRoute;
3
+ import { BrowserManager, Config, FileSystem, HTTPServer, Limiter, Metrics, Monitoring, Router, Token, WebHooks } from '@browserless.io/browserless';
5
4
  export declare class Browserless {
6
5
  protected debug: debug.Debugger;
7
6
  protected browserManager: BrowserManager;
@@ -13,7 +12,7 @@ export declare class Browserless {
13
12
  protected router: Router;
14
13
  protected token: Token;
15
14
  protected webhooks: WebHooks;
16
- DisabledRoutes: RouteTypes[];
15
+ disabledRouteNames: string[];
17
16
  webSocketRouteFiles: string[];
18
17
  httpRouteFiles: string[];
19
18
  server?: HTTPServer;
@@ -33,11 +32,10 @@ export declare class Browserless {
33
32
  protected saveMetrics: () => Promise<void>;
34
33
  setMetricsSaveInterval: (interval: number) => void;
35
34
  private routeIsDisabled;
36
- disableRoute(Route: RouteTypes): void;
35
+ disableRoutes(...routeNames: string[]): void;
37
36
  addHTTPRoute(httpRouteFilePath: string): void;
38
37
  addWebSocketRoute(webSocketRouteFilePath: string): void;
39
38
  setPort(port: number): void;
40
39
  stop(): Promise<[void | undefined]>;
41
40
  start(): Promise<void>;
42
41
  }
43
- export {};
@@ -14,7 +14,7 @@ export class Browserless {
14
14
  router;
15
15
  token;
16
16
  webhooks;
17
- DisabledRoutes = [];
17
+ disabledRouteNames = [];
18
18
  webSocketRouteFiles = [];
19
19
  httpRouteFiles = [];
20
20
  server;
@@ -70,12 +70,11 @@ export class Browserless {
70
70
  this.metricsSaveInterval = interval;
71
71
  this.metricsSaveIntervalID = setInterval(this.saveMetrics, this.metricsSaveInterval);
72
72
  };
73
- routeIsDisabled(Route) {
74
- const Stringified = Route.toString();
75
- return this.DisabledRoutes.some((r) => r.toString() === Stringified);
73
+ routeIsDisabled(route) {
74
+ return this.disabledRouteNames.some((name) => name === route.name);
76
75
  }
77
- disableRoute(Route) {
78
- this.DisabledRoutes.push(Route);
76
+ disableRoutes(...routeNames) {
77
+ this.disabledRouteNames.push(...routeNames);
79
78
  }
80
79
  addHTTPRoute(httpRouteFilePath) {
81
80
  this.httpRouteFiles.push(httpRouteFilePath);
@@ -122,8 +121,8 @@ export class Browserless {
122
121
  const routeImport = `${this.config.getIsWin() ? 'file:///' : ''}${httpRoute}`;
123
122
  const logger = createLogger(`http:${name}`);
124
123
  const { default: Route, } = await import(routeImport + `?cb=${Date.now()}`);
125
- if (!this.routeIsDisabled(Route)) {
126
- const route = new Route(this.browserManager, this.config, this.fileSystem, logger, this.metrics, this.monitoring);
124
+ const route = new Route(this.browserManager, this.config, this.fileSystem, logger, this.metrics, this.monitoring);
125
+ if (!this.routeIsDisabled(route)) {
127
126
  route.bodySchema = safeParse(bodySchema);
128
127
  route.querySchema = safeParse(querySchema);
129
128
  route.config = () => this.config;
@@ -150,8 +149,8 @@ export class Browserless {
150
149
  const wsImport = `${this.config.getIsWin() ? 'file:///' : ''}${wsRoute}`;
151
150
  const logger = createLogger(`ws:${name}`);
152
151
  const { default: Route, } = await import(wsImport + `?cb=${Date.now()}`);
153
- if (!this.routeIsDisabled(Route)) {
154
- const route = new Route(this.browserManager, this.config, this.fileSystem, logger, this.metrics, this.monitoring);
152
+ const route = new Route(this.browserManager, this.config, this.fileSystem, logger, this.metrics, this.monitoring);
153
+ if (!this.routeIsDisabled(route)) {
155
154
  route.querySchema = safeParse(querySchema);
156
155
  route.config = () => this.config;
157
156
  route.metrics = () => this.metrics;
@@ -162,8 +161,9 @@ export class Browserless {
162
161
  }
163
162
  }
164
163
  }
164
+ const allRoutes = [...httpRoutes, ...wsRoutes];
165
165
  // Validate that we have the browsers they are asking for
166
- [...httpRoutes, ...wsRoutes].forEach((route) => {
166
+ allRoutes.forEach((route) => {
167
167
  if ('browser' in route &&
168
168
  route.browser &&
169
169
  internalBrowsers.includes(route.browser) &&
@@ -171,6 +171,12 @@ export class Browserless {
171
171
  throw new Error(`Couldn't load route "${route.path}" due to missing browser binary for "${route.browser?.name}"`);
172
172
  }
173
173
  });
174
+ const duplicateNamedRoutes = allRoutes
175
+ .filter((e, i, a) => a.findIndex((r) => r.name === e.name) !== i)
176
+ .map((r) => r.name);
177
+ if (duplicateNamedRoutes.length) {
178
+ this.debug(`Found duplicate routing names. Route names must be unique:`, duplicateNamedRoutes);
179
+ }
174
180
  httpRoutes.forEach((r) => this.router.registerHTTPRoute(r));
175
181
  wsRoutes.forEach((r) => this.router.registerWebSocketRoute(r));
176
182
  this.debug(`Imported and validated all route files, starting up server.`);
@@ -1,6 +1,6 @@
1
1
  import { chromeExecutablePath, createLogger, } from '@browserless.io/browserless';
2
2
  import { ChromiumCDP } from './chromium.cdp.js';
3
3
  export class ChromeCDP extends ChromiumCDP {
4
- executablePath = chromeExecutablePath;
4
+ executablePath = chromeExecutablePath();
5
5
  debug = createLogger('browsers:chrome:cdp');
6
6
  }
@@ -1,6 +1,6 @@
1
1
  import { chromeExecutablePath, createLogger, } from '@browserless.io/browserless';
2
2
  import { ChromiumPlaywright } from './chromium.playwright.js';
3
3
  export class ChromePlaywright extends ChromiumPlaywright {
4
- executablePath = chromeExecutablePath;
4
+ executablePath = chromeExecutablePath();
5
5
  debug = createLogger('browsers:chrome:playwright');
6
6
  }
@@ -11,6 +11,7 @@ export declare class BrowserManager {
11
11
  constructor(config: Config);
12
12
  private browserIsChrome;
13
13
  protected removeUserDataDir: (userDataDir: string | null) => Promise<void>;
14
+ protected onNewPage: (req: Request, page: unknown) => Promise<void>;
14
15
  /**
15
16
  * Returns the /json/protocol API contents from Chromium or Chrome, whichever is installed,
16
17
  * and modifies URLs to set them to the appropriate addresses configured.
@@ -26,6 +26,9 @@ export class BrowserManager {
26
26
  });
27
27
  }
28
28
  };
29
+ onNewPage = async (req, page) => {
30
+ await pageHook({ meta: req.parsed, page });
31
+ };
29
32
  /**
30
33
  * Returns the /json/protocol API contents from Chromium or Chrome, whichever is installed,
31
34
  * and modifies URLs to set them to the appropriate addresses configured.
@@ -316,7 +319,7 @@ export class BrowserManager {
316
319
  await browser.launch(launchOptions);
317
320
  await browserHook({ browser, meta: req.parsed });
318
321
  browser.on('newPage', async (page) => {
319
- await pageHook({ meta: req.parsed, page });
322
+ await this.onNewPage(req, page);
320
323
  (router.onNewPage || noop)(req.parsed || '', page);
321
324
  });
322
325
  return browser;
@@ -1 +1 @@
1
- ["b-modal-banner--disabled","blocked","bodyBlocked","c24-cc-visible","cbar","ccm-blocked","cmp-open","consent-modal-open","consent-modal-overflow","CookiePolicy--show","cookies","cu_k_cookie_consent_modal_open","gcdc-locked","gdpr-infobar-visible","gdprbanner_consent_gdpr_consent","gdprCookieBanner-acceptedAll","hasCookieBanner","ibeugdpr-disabled","idxrcookies-block-user-nav","modal--is-open","modal-open","no_scroll","no-scroll","noScroll","popin-gdpr-no-scroll","shopee-no-scroll","show-cookie-policy-info","sp-message-open","start-cookies","ta-cc-modal-open","touchevents-false","wt-cli-eu-country","wt-cli-geoip-on"]
1
+ ["appconsent_noscroll","b-modal-banner--disabled","blocked","bodyBlocked","c24-cc-visible","cbar","ccm-blocked","cmp-open","consent-modal-open","consent-modal-overflow","cookie_consent","CookiePolicy--show","cookies","cu_k_cookie_consent_modal_open","didomi-popup-open","gcdc-locked","gdpr-infobar-visible","gdprbanner_consent_gdpr_consent","gdprCookieBanner-acceptedAll","hasCookieBanner","ibeugdpr-disabled","idxrcookies-block-user-nav","modal--is-open","modal-open","no_scroll","no-scroll","noScroll","popin-gdpr-no-scroll","shopee-no-scroll","show-cookie-policy-info","sp-message-open","start-cookies","ta-cc-modal-open","touchevents-false","wt-cli-eu-country","wt-cli-geoip-on"]