@browserless.io/browserless 2.24.0-beta-2 → 2.24.0-beta-4

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/build/utils.js CHANGED
@@ -377,13 +377,14 @@ export const waitForEvent = async (page, opts) => {
377
377
  const awaitEvent = async (event) => {
378
378
  await new Promise((resolve) => {
379
379
  document.addEventListener(event, () => resolve(), { once: true });
380
+ window.addEventListener(event, () => resolve(), { once: true });
380
381
  });
381
382
  };
382
383
  const timeout = opts.timeout || 30000;
383
384
  await Promise.race([
384
385
  page.evaluate(awaitEvent, opts.event),
385
386
  sleep(timeout).then(() => {
386
- throw new Error('Event awaiting timeout');
387
+ throw new Timeout(`Timed out waiting for event "${opts.event}"'`);
387
388
  }),
388
389
  ]);
389
390
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@browserless.io/browserless",
3
- "version": "2.24.0-beta-2",
3
+ "version": "2.24.0-beta-4",
4
4
  "license": "SSPL",
5
5
  "description": "The browserless platform",
6
6
  "author": "browserless.io",
@@ -76,23 +76,23 @@
76
76
  "@types/http-proxy": "^1.17.15",
77
77
  "@types/micromatch": "^4.0.9",
78
78
  "@types/mocha": "^10.0.10",
79
- "@types/node": "^22.9.3",
79
+ "@types/node": "^22.10.1",
80
80
  "@types/sinon": "^17.0.3",
81
- "@typescript-eslint/eslint-plugin": "^8.15.0",
82
- "@typescript-eslint/parser": "^8.15.0",
81
+ "@typescript-eslint/eslint-plugin": "^8.17.0",
82
+ "@typescript-eslint/parser": "^8.17.0",
83
83
  "assert": "^2.0.0",
84
84
  "chai": "^5.1.2",
85
85
  "cross-env": "^7.0.3",
86
86
  "env-cmd": "^10.1.0",
87
87
  "esbuild": "^0.24.0",
88
88
  "esbuild-plugin-polyfill-node": "^0.3.0",
89
- "eslint": "^9.14.0",
89
+ "eslint": "^9.16.0",
90
90
  "extract-zip": "^2.0.1",
91
91
  "gunzip-maybe": "^1.4.2",
92
- "marked": "^15.0.2",
93
- "mocha": "^10.8.2",
92
+ "marked": "^15.0.3",
93
+ "mocha": "^11.0.1",
94
94
  "move-file": "^3.1.0",
95
- "prettier": "^3.3.3",
95
+ "prettier": "^3.4.1",
96
96
  "sinon": "^19.0.2",
97
97
  "ts-node": "^10.9.2",
98
98
  "typescript": "^5.7.2",
package/src/http.ts CHANGED
@@ -126,6 +126,7 @@ export enum HTTPRoutes {
126
126
  export enum HTTPManagementRoutes {
127
127
  active = '/active?(/)',
128
128
  config = '/config?(/)',
129
+ meta = '/meta?(/)',
129
130
  metrics = '/metrics?(/)',
130
131
  metricsTotal = '/metrics/total?(/)',
131
132
  pressure = '/pressure?(/)',
@@ -0,0 +1,102 @@
1
+ import {
2
+ APITags,
3
+ BrowserlessRoutes,
4
+ ChromiumCDP,
5
+ FirefoxPlaywright,
6
+ HTTPManagementRoutes,
7
+ HTTPRoute,
8
+ Methods,
9
+ Request,
10
+ WebKitPlaywright,
11
+ availableBrowsers,
12
+ contentTypes,
13
+ jsonResponse,
14
+ } from '@browserless.io/browserless';
15
+ import { ServerResponse } from 'http';
16
+ import { createRequire } from 'module';
17
+
18
+ export interface ResponseSchema {
19
+ /**
20
+ * The semantic version of the Browserless API
21
+ */
22
+ version: string;
23
+
24
+ /**
25
+ * The version of Chromium installed, or null if not installed
26
+ */
27
+ chromium: string | null;
28
+
29
+ /**
30
+ * The version of Webkit installed, or null if not installed
31
+ */
32
+ webkit: string | null;
33
+
34
+ /**
35
+ * The version of Firefox installed, or null if not installed
36
+ */
37
+ firefox: string | null;
38
+
39
+ /**
40
+ * The supported version(s) of puppeteer
41
+ */
42
+ playwright: string[];
43
+
44
+ /**
45
+ * The supported version(s) of playwright
46
+ */
47
+ puppeteer: string[];
48
+ }
49
+
50
+ const semverReg = /(\*|\^|>|=|<|~)/gi;
51
+ const require = createRequire(import.meta.url);
52
+ const blessPackageJSON = require('../../../../package.json');
53
+ const { browsers } =
54
+ require('../../../../node_modules/playwright-core/browsers.json') as {
55
+ browsers: [
56
+ {
57
+ name: string;
58
+ browserVersion: string;
59
+ },
60
+ ];
61
+ };
62
+ const chromium = browsers.find((b) => b.name === 'chromium')!.browserVersion;
63
+ const firefox = browsers.find((b) => b.name === 'firefox')!.browserVersion;
64
+ const webkit = browsers.find((b) => b.name === 'webkit')!.browserVersion;
65
+ const playwrightCore = blessPackageJSON.dependencies['playwright-core'].replace(
66
+ semverReg,
67
+ '',
68
+ );
69
+ const puppeteer = blessPackageJSON.dependencies['puppeteer-core'].replace(
70
+ semverReg,
71
+ '',
72
+ );
73
+ const playwright = Object.entries(blessPackageJSON.playwrightVersions)
74
+ .map(([, v]) => blessPackageJSON.dependencies[v as string])
75
+ .filter((_) => !!_)
76
+ .map((v) => v.match(/[0-9.]+/g).join(''))
77
+ .concat(playwrightCore);
78
+
79
+ export default class MetaGetRoute extends HTTPRoute {
80
+ name = BrowserlessRoutes.MetaGetRoute;
81
+ accepts = [contentTypes.any];
82
+ auth = true;
83
+ browser = null;
84
+ concurrency = false;
85
+ contentTypes = [contentTypes.json];
86
+ description = `Returns a JSON payload of the current system versions, including the core API version.`;
87
+ method = Methods.get;
88
+ path = HTTPManagementRoutes.meta;
89
+ tags = [APITags.management];
90
+ async handler(_req: Request, res: ServerResponse): Promise<void> {
91
+ const installedBrowsers = await availableBrowsers;
92
+ const response: ResponseSchema = {
93
+ version: blessPackageJSON.version,
94
+ chromium: installedBrowsers.includes(ChromiumCDP) ? chromium : null,
95
+ firefox: installedBrowsers.includes(FirefoxPlaywright) ? firefox : null,
96
+ webkit: installedBrowsers.includes(WebKitPlaywright) ? webkit : null,
97
+ playwright: [...new Set(playwright)],
98
+ puppeteer: [puppeteer],
99
+ };
100
+ return jsonResponse(res, 200, response);
101
+ }
102
+ }
@@ -30,6 +30,19 @@ describe('Management APIs', function () {
30
30
  );
31
31
  });
32
32
 
33
+ it('allows requests to /meta', async () => {
34
+ await start();
35
+
36
+ await fetch('http://localhost:3000/meta?token=6R0W53R135510').then(
37
+ async (res) => {
38
+ expect(res.headers.get('content-type')).to.equal(
39
+ 'application/json; charset=UTF-8',
40
+ );
41
+ expect(res.status).to.equal(200);
42
+ },
43
+ );
44
+ });
45
+
33
46
  it('allows requests to /metrics', async () => {
34
47
  await start();
35
48
 
@@ -6,6 +6,7 @@ import {
6
6
  HTTPRoutes,
7
7
  Logger,
8
8
  Request,
9
+ ServerError,
9
10
  UnwrapPromise,
10
11
  contentTypes,
11
12
  convertIfBase64,
@@ -67,7 +68,9 @@ export default (config: Config, logger: Logger, options: HandlerOptions = {}) =>
67
68
  );
68
69
 
69
70
  if (!browserWSEndpoint) {
70
- throw new Error(`No browser endpoint was found, is the browser running?`);
71
+ throw new ServerError(
72
+ `No browser endpoint was found, is the browser running?`,
73
+ );
71
74
  }
72
75
 
73
76
  const functionCodeJS = `browserless-function-${id()}.js`;
package/src/types.ts CHANGED
@@ -661,6 +661,7 @@ export const BrowserlessWebKitRoutes = {
661
661
  export const BrowserlessManagementRoutes = {
662
662
  ActiveGetRoute: 'ActiveGetRoute',
663
663
  ConfigGetRoute: 'ConfigGetRoute',
664
+ MetaGetRoute: 'MetaGetRoute',
664
665
  MetricsGetRoute: 'MetricsGetRoute',
665
666
  MetricsTotalGetRoute: 'MetricsTotalGetRoute',
666
667
  PressureGetRoute: 'PressureGetRoute',
package/src/utils.ts CHANGED
@@ -537,6 +537,7 @@ export const waitForEvent = async (
537
537
  const awaitEvent = async (event: string) => {
538
538
  await new Promise<void>((resolve) => {
539
539
  document.addEventListener(event, () => resolve(), { once: true });
540
+ window.addEventListener(event, () => resolve(), { once: true });
540
541
  });
541
542
  };
542
543
 
@@ -545,7 +546,7 @@ export const waitForEvent = async (
545
546
  await Promise.race([
546
547
  page.evaluate(awaitEvent, opts.event),
547
548
  sleep(timeout).then(() => {
548
- throw new Error('Event awaiting timeout');
549
+ throw new Timeout(`Timed out waiting for event "${opts.event}"'`);
549
550
  }),
550
551
  ]);
551
552
  };
@@ -255,14 +255,14 @@
255
255
  "length": {
256
256
  "type": "number"
257
257
  },
258
- "__@toStringTag@14497": {
258
+ "__@toStringTag@14520": {
259
259
  "type": "string",
260
260
  "const": "Uint8Array"
261
261
  }
262
262
  },
263
263
  "required": [
264
264
  "BYTES_PER_ELEMENT",
265
- "__@toStringTag@14497",
265
+ "__@toStringTag@14520",
266
266
  "buffer",
267
267
  "byteLength",
268
268
  "byteOffset",
@@ -297,13 +297,13 @@
297
297
  "byteLength": {
298
298
  "type": "number"
299
299
  },
300
- "__@toStringTag@14497": {
300
+ "__@toStringTag@14520": {
301
301
  "type": "string"
302
302
  }
303
303
  },
304
304
  "additionalProperties": false,
305
305
  "required": [
306
- "__@toStringTag@14497",
306
+ "__@toStringTag@14520",
307
307
  "byteLength"
308
308
  ]
309
309
  },
@@ -313,18 +313,18 @@
313
313
  "byteLength": {
314
314
  "type": "number"
315
315
  },
316
- "__@species@14535": {
316
+ "__@species@14558": {
317
317
  "$ref": "#/definitions/SharedArrayBuffer"
318
318
  },
319
- "__@toStringTag@14497": {
319
+ "__@toStringTag@14520": {
320
320
  "type": "string",
321
321
  "const": "SharedArrayBuffer"
322
322
  }
323
323
  },
324
324
  "additionalProperties": false,
325
325
  "required": [
326
- "__@species@14535",
327
- "__@toStringTag@14497",
326
+ "__@species@14558",
327
+ "__@toStringTag@14520",
328
328
  "byteLength"
329
329
  ]
330
330
  },
@@ -969,7 +969,7 @@
969
969
  },
970
970
  "info": {
971
971
  "title": "Browserless",
972
- "version": "2.24.0-beta-2",
972
+ "version": "2.24.0-beta-4",
973
973
  "x-logo": {
974
974
  "altText": "browserless logo",
975
975
  "url": "./docs/browserless-logo-inline.svg"
@@ -5848,6 +5848,112 @@
5848
5848
  ]
5849
5849
  }
5850
5850
  },
5851
+ "/meta": {
5852
+ "get": {
5853
+ "definitions": {},
5854
+ "description": "Returns a JSON payload of the current system versions, including the core API version.",
5855
+ "parameters": [],
5856
+ "requestBody": {
5857
+ "content": {}
5858
+ },
5859
+ "responses": {
5860
+ "200": {
5861
+ "content": {
5862
+ "application/json": {
5863
+ "schema": {
5864
+ "type": "object",
5865
+ "properties": {
5866
+ "version": {
5867
+ "description": "The semantic version of the Browserless API",
5868
+ "type": "string"
5869
+ },
5870
+ "chromium": {
5871
+ "description": "The version of Chromium installed, or null if not installed",
5872
+ "type": [
5873
+ "null",
5874
+ "string"
5875
+ ]
5876
+ },
5877
+ "webkit": {
5878
+ "description": "The version of Webkit installed, or null if not installed",
5879
+ "type": [
5880
+ "null",
5881
+ "string"
5882
+ ]
5883
+ },
5884
+ "firefox": {
5885
+ "description": "The version of Firefox installed, or null if not installed",
5886
+ "type": [
5887
+ "null",
5888
+ "string"
5889
+ ]
5890
+ },
5891
+ "playwright": {
5892
+ "description": "The supported version(s) of puppeteer",
5893
+ "type": "array",
5894
+ "items": {
5895
+ "type": "string"
5896
+ }
5897
+ },
5898
+ "puppeteer": {
5899
+ "description": "The supported version(s) of playwright",
5900
+ "type": "array",
5901
+ "items": {
5902
+ "type": "string"
5903
+ }
5904
+ }
5905
+ },
5906
+ "additionalProperties": false,
5907
+ "required": [
5908
+ "chromium",
5909
+ "firefox",
5910
+ "playwright",
5911
+ "puppeteer",
5912
+ "version",
5913
+ "webkit"
5914
+ ],
5915
+ "$schema": "http://json-schema.org/draft-07/schema#"
5916
+ }
5917
+ }
5918
+ }
5919
+ },
5920
+ "400": {
5921
+ "code": 400,
5922
+ "description": "The request contains errors or didn't properly encode content.",
5923
+ "message": "HTTP/1.1 400 Bad Request"
5924
+ },
5925
+ "401": {
5926
+ "code": 401,
5927
+ "description": "The request is missing, or contains bad, authorization credentials.",
5928
+ "message": "HTTP/1.1 401 Unauthorized"
5929
+ },
5930
+ "404": {
5931
+ "code": 404,
5932
+ "description": "Resource couldn't be found.",
5933
+ "message": "HTTP/1.1 404 Not Found"
5934
+ },
5935
+ "408": {
5936
+ "code": 408,
5937
+ "description": "The request took has taken too long to process.",
5938
+ "message": "HTTP/1.1 408 Request Timeout"
5939
+ },
5940
+ "429": {
5941
+ "code": 429,
5942
+ "description": "Too many requests are currently being processed.",
5943
+ "message": "HTTP/1.1 429 Too Many Requests"
5944
+ },
5945
+ "500": {
5946
+ "code": 500,
5947
+ "description": "An internal error occurred when handling the request.",
5948
+ "message": "HTTP/1.1 500 Internal Server Error"
5949
+ }
5950
+ },
5951
+ "summary": "/meta",
5952
+ "tags": [
5953
+ "Management REST APIs"
5954
+ ]
5955
+ }
5956
+ },
5851
5957
  "/metrics/total": {
5852
5958
  "get": {
5853
5959
  "definitions": {},
@@ -255,14 +255,14 @@
255
255
  "length": {
256
256
  "type": "number"
257
257
  },
258
- "__@toStringTag@14497": {
258
+ "__@toStringTag@14520": {
259
259
  "type": "string",
260
260
  "const": "Uint8Array"
261
261
  }
262
262
  },
263
263
  "required": [
264
264
  "BYTES_PER_ELEMENT",
265
- "__@toStringTag@14497",
265
+ "__@toStringTag@14520",
266
266
  "buffer",
267
267
  "byteLength",
268
268
  "byteOffset",
@@ -297,13 +297,13 @@
297
297
  "byteLength": {
298
298
  "type": "number"
299
299
  },
300
- "__@toStringTag@14497": {
300
+ "__@toStringTag@14520": {
301
301
  "type": "string"
302
302
  }
303
303
  },
304
304
  "additionalProperties": false,
305
305
  "required": [
306
- "__@toStringTag@14497",
306
+ "__@toStringTag@14520",
307
307
  "byteLength"
308
308
  ]
309
309
  },
@@ -313,18 +313,18 @@
313
313
  "byteLength": {
314
314
  "type": "number"
315
315
  },
316
- "__@species@14535": {
316
+ "__@species@14558": {
317
317
  "$ref": "#/definitions/SharedArrayBuffer"
318
318
  },
319
- "__@toStringTag@14497": {
319
+ "__@toStringTag@14520": {
320
320
  "type": "string",
321
321
  "const": "SharedArrayBuffer"
322
322
  }
323
323
  },
324
324
  "additionalProperties": false,
325
325
  "required": [
326
- "__@species@14535",
327
- "__@toStringTag@14497",
326
+ "__@species@14558",
327
+ "__@toStringTag@14520",
328
328
  "byteLength"
329
329
  ]
330
330
  },
@@ -969,7 +969,7 @@
969
969
  },
970
970
  "info": {
971
971
  "title": "Browserless",
972
- "version": "2.24.0-beta-2",
972
+ "version": "2.24.0-beta-4",
973
973
  "x-logo": {
974
974
  "altText": "browserless logo",
975
975
  "url": "./docs/browserless-logo-inline.svg"
@@ -5847,6 +5847,112 @@
5847
5847
  ]
5848
5848
  }
5849
5849
  },
5850
+ "/meta": {
5851
+ "get": {
5852
+ "definitions": {},
5853
+ "description": "Returns a JSON payload of the current system versions, including the core API version.",
5854
+ "parameters": [],
5855
+ "requestBody": {
5856
+ "content": {}
5857
+ },
5858
+ "responses": {
5859
+ "200": {
5860
+ "content": {
5861
+ "application/json": {
5862
+ "schema": {
5863
+ "type": "object",
5864
+ "properties": {
5865
+ "version": {
5866
+ "description": "The semantic version of the Browserless API",
5867
+ "type": "string"
5868
+ },
5869
+ "chromium": {
5870
+ "description": "The version of Chromium installed, or null if not installed",
5871
+ "type": [
5872
+ "null",
5873
+ "string"
5874
+ ]
5875
+ },
5876
+ "webkit": {
5877
+ "description": "The version of Webkit installed, or null if not installed",
5878
+ "type": [
5879
+ "null",
5880
+ "string"
5881
+ ]
5882
+ },
5883
+ "firefox": {
5884
+ "description": "The version of Firefox installed, or null if not installed",
5885
+ "type": [
5886
+ "null",
5887
+ "string"
5888
+ ]
5889
+ },
5890
+ "playwright": {
5891
+ "description": "The supported version(s) of puppeteer",
5892
+ "type": "array",
5893
+ "items": {
5894
+ "type": "string"
5895
+ }
5896
+ },
5897
+ "puppeteer": {
5898
+ "description": "The supported version(s) of playwright",
5899
+ "type": "array",
5900
+ "items": {
5901
+ "type": "string"
5902
+ }
5903
+ }
5904
+ },
5905
+ "additionalProperties": false,
5906
+ "required": [
5907
+ "chromium",
5908
+ "firefox",
5909
+ "playwright",
5910
+ "puppeteer",
5911
+ "version",
5912
+ "webkit"
5913
+ ],
5914
+ "$schema": "http://json-schema.org/draft-07/schema#"
5915
+ }
5916
+ }
5917
+ }
5918
+ },
5919
+ "400": {
5920
+ "code": 400,
5921
+ "description": "The request contains errors or didn't properly encode content.",
5922
+ "message": "HTTP/1.1 400 Bad Request"
5923
+ },
5924
+ "401": {
5925
+ "code": 401,
5926
+ "description": "The request is missing, or contains bad, authorization credentials.",
5927
+ "message": "HTTP/1.1 401 Unauthorized"
5928
+ },
5929
+ "404": {
5930
+ "code": 404,
5931
+ "description": "Resource couldn't be found.",
5932
+ "message": "HTTP/1.1 404 Not Found"
5933
+ },
5934
+ "408": {
5935
+ "code": 408,
5936
+ "description": "The request took has taken too long to process.",
5937
+ "message": "HTTP/1.1 408 Request Timeout"
5938
+ },
5939
+ "429": {
5940
+ "code": 429,
5941
+ "description": "Too many requests are currently being processed.",
5942
+ "message": "HTTP/1.1 429 Too Many Requests"
5943
+ },
5944
+ "500": {
5945
+ "code": 500,
5946
+ "description": "An internal error occurred when handling the request.",
5947
+ "message": "HTTP/1.1 500 Internal Server Error"
5948
+ }
5949
+ },
5950
+ "summary": "/meta",
5951
+ "tags": [
5952
+ "Management REST APIs"
5953
+ ]
5954
+ }
5955
+ },
5850
5956
  "/metrics/total": {
5851
5957
  "get": {
5852
5958
  "definitions": {},