@browserless.io/browserless 2.0.0-beta-1 → 2.0.0-beta-2

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 (69) hide show
  1. package/bin/browserless.js +128 -8
  2. package/build/browserless.d.ts +23 -18
  3. package/build/browserless.js +24 -17
  4. package/build/browsers/cdp-chromium.d.ts +17 -14
  5. package/build/browsers/index.d.ts +27 -10
  6. package/build/browsers/index.js +2 -12
  7. package/build/browsers/playwright-chromium.d.ts +12 -9
  8. package/build/browsers/playwright-firefox.d.ts +12 -9
  9. package/build/browsers/playwright-webkit.d.ts +12 -9
  10. package/build/config.d.ts +31 -31
  11. package/build/exports.d.ts +2 -0
  12. package/build/exports.js +2 -0
  13. package/build/file-system.d.ts +2 -2
  14. package/build/limiter.d.ts +34 -11
  15. package/build/metrics.d.ts +17 -11
  16. package/build/monitoring.d.ts +3 -2
  17. package/build/router.d.ts +28 -0
  18. package/build/router.js +138 -0
  19. package/build/routes/chromium/http/content-post.body.json +8 -8
  20. package/build/routes/chromium/http/download-post.js +1 -1
  21. package/build/routes/chromium/http/function-post.js +1 -1
  22. package/build/routes/chromium/http/pdf-post.body.json +8 -8
  23. package/build/routes/chromium/http/performance.js +1 -1
  24. package/build/routes/chromium/http/scrape-post.body.json +8 -8
  25. package/build/routes/chromium/http/screenshot-post.body.json +8 -8
  26. package/build/routes/chromium/utils/function/client.d.ts +3 -3
  27. package/build/routes/management/http/config-get.js +1 -1
  28. package/build/routes/management/http/metrics-get.js +1 -1
  29. package/build/routes/management/http/metrics-total-get.js +1 -1
  30. package/build/routes/management/http/sessions-get.js +3 -3
  31. package/build/routes/management/http/static-get.js +1 -1
  32. package/build/server.d.ts +22 -27
  33. package/build/server.js +29 -149
  34. package/build/token.d.ts +6 -0
  35. package/build/token.js +21 -0
  36. package/build/types.d.ts +85 -14
  37. package/build/utils.d.ts +1 -2
  38. package/build/utils.js +0 -13
  39. package/build/webhooks.d.ts +2 -2
  40. package/docker/sdk/Dockerfile +2 -6
  41. package/package.json +4 -4
  42. package/src/browserless.ts +44 -32
  43. package/src/browsers/cdp-chromium.ts +13 -13
  44. package/src/browsers/index.ts +9 -24
  45. package/src/browsers/playwright-chromium.ts +9 -9
  46. package/src/browsers/playwright-firefox.ts +9 -9
  47. package/src/browsers/playwright-webkit.ts +9 -9
  48. package/src/config.ts +32 -31
  49. package/src/exports.ts +2 -0
  50. package/src/file-system.ts +2 -2
  51. package/src/limiter.ts +11 -11
  52. package/src/metrics.ts +11 -11
  53. package/src/monitoring.ts +2 -2
  54. package/src/router.ts +234 -0
  55. package/src/routes/chromium/http/download-post.ts +1 -1
  56. package/src/routes/chromium/http/function-post.ts +1 -1
  57. package/src/routes/chromium/http/performance.ts +1 -1
  58. package/src/routes/chromium/utils/function/client.ts +2 -2
  59. package/src/routes/management/http/config-get.ts +1 -1
  60. package/src/routes/management/http/metrics-get.ts +1 -1
  61. package/src/routes/management/http/metrics-total-get.ts +1 -1
  62. package/src/routes/management/http/sessions-get.ts +3 -3
  63. package/src/routes/management/http/static-get.ts +1 -1
  64. package/src/server.ts +43 -238
  65. package/src/token.ts +40 -0
  66. package/src/types.ts +92 -17
  67. package/src/utils.ts +0 -25
  68. package/src/webhooks.ts +2 -2
  69. package/static/docs/swagger.json +9 -9
@@ -1,7 +1,6 @@
1
- ARG FROM=ghcr.io/browserless/multi
2
- ARG VERSION=latest
1
+ ARG FROM=ghcr.io/browserless/multi:latest
3
2
 
4
- FROM ${FROM}:${VERSION}
3
+ FROM ${FROM}
5
4
 
6
5
  # Change to root for install
7
6
  USER root
@@ -17,9 +16,6 @@ COPY src src
17
16
  COPY package.json .
18
17
  COPY package-lock.json .
19
18
  COPY tsconfig.json .
20
-
21
- # Optional files that might not always be there
22
- COPY *browserless.io-browserless-*.tgz .
23
19
  COPY *README.md .
24
20
 
25
21
  # Install dependencies
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@browserless.io/browserless",
3
- "version": "2.0.0-beta-1",
3
+ "version": "2.0.0-beta-2",
4
4
  "license": "SSPL",
5
5
  "description": "The browserless platform",
6
6
  "author": "browserless.io",
@@ -71,13 +71,13 @@
71
71
  "@types/mocha": "^10.0.6",
72
72
  "@types/node": "^20.10.5",
73
73
  "@types/sinon": "^17.0.2",
74
- "@typescript-eslint/eslint-plugin": "^6.14.0",
75
- "@typescript-eslint/parser": "^6.14.0",
74
+ "@typescript-eslint/eslint-plugin": "^6.15.0",
75
+ "@typescript-eslint/parser": "^6.15.0",
76
76
  "assert": "^2.0.0",
77
77
  "chai": "^4.3.6",
78
78
  "cross-env": "^7.0.3",
79
79
  "env-cmd": "^10.1.0",
80
- "esbuild": "^0.19.9",
80
+ "esbuild": "^0.19.10",
81
81
  "esbuild-plugin-polyfill-node": "^0.3.0",
82
82
  "eslint": "^8.56.0",
83
83
  "eslint-plugin-import": "^2.29.1",
@@ -11,6 +11,8 @@ import {
11
11
  Limiter,
12
12
  Metrics,
13
13
  Monitoring,
14
+ Router,
15
+ Token,
14
16
  WebHooks,
15
17
  WebSocketRoute,
16
18
  availableBrowsers,
@@ -26,14 +28,16 @@ import { userInfo } from 'os';
26
28
  const routeSchemas = ['body', 'query'];
27
29
 
28
30
  export class Browserless {
29
- private config: Config;
30
- private monitoring: Monitoring;
31
- private metrics: Metrics;
32
- private fileSystem: FileSystem;
33
- private browserManager: BrowserManager;
34
- private limiter: Limiter;
35
- private webhooks: WebHooks;
36
- private debug: debug.Debugger = createLogger('index');
31
+ protected debug: debug.Debugger = createLogger('index');
32
+ protected browserManager: BrowserManager;
33
+ protected config: Config;
34
+ protected fileSystem: FileSystem;
35
+ protected limiter: Limiter;
36
+ protected metrics: Metrics;
37
+ protected monitoring: Monitoring;
38
+ protected router: Router;
39
+ protected token: Token;
40
+ protected webhooks: WebHooks;
37
41
 
38
42
  webSocketRouteFiles: string[] = [];
39
43
  httpRouteFiles: string[] = [];
@@ -44,22 +48,27 @@ export class Browserless {
44
48
  constructor({
45
49
  browserManager,
46
50
  config,
47
- monitoring,
51
+ fileSystem,
48
52
  limiter,
49
53
  metrics,
50
- fileSystem,
54
+ monitoring,
55
+ router,
56
+ token,
51
57
  webhooks,
52
58
  }: {
53
- browserManager?: BrowserManager;
54
- config?: Config;
55
- fileSystem?: FileSystem;
56
- limiter?: Limiter;
57
- metrics?: Metrics;
58
- monitoring?: Monitoring;
59
- webhooks?: WebHooks;
59
+ browserManager?: Browserless['browserManager'];
60
+ config?: Browserless['config'];
61
+ fileSystem?: Browserless['fileSystem'];
62
+ limiter?: Browserless['limiter'];
63
+ metrics?: Browserless['metrics'];
64
+ monitoring?: Browserless['monitoring'];
65
+ router?: Browserless['router'];
66
+ token?: Browserless['token'];
67
+ webhooks?: Browserless['webhooks'];
60
68
  } = {}) {
61
69
  this.config = config || new Config();
62
70
  this.metrics = metrics || new Metrics();
71
+ this.token = token || new Token(this.config);
63
72
  this.webhooks = webhooks || new WebHooks(this.config);
64
73
  this.browserManager = browserManager || new BrowserManager(this.config);
65
74
  this.monitoring = monitoring || new Monitoring(this.config);
@@ -67,9 +76,11 @@ export class Browserless {
67
76
  this.limiter =
68
77
  limiter ||
69
78
  new Limiter(this.config, this.metrics, this.monitoring, this.webhooks);
79
+ this.router =
80
+ router || new Router(this.config, this.browserManager, this.limiter);
70
81
  }
71
82
 
72
- private saveMetrics = async (): Promise<void> => {
83
+ protected saveMetrics = async (): Promise<void> => {
73
84
  const metricsPath = this.config.getMetricsJSONPath();
74
85
  const { cpu, memory } = await this.monitoring.getMachineStats();
75
86
  const metrics = await this.metrics.get();
@@ -175,11 +186,11 @@ export class Browserless {
175
186
 
176
187
  route.bodySchema = safeParse(bodySchema);
177
188
  route.querySchema = safeParse(querySchema);
178
- route._config = () => this.config;
179
- route._metrics = () => this.metrics;
180
- route._monitor = () => this.monitoring;
181
- route._fileSystem = () => this.fileSystem;
182
- route._debug = () => logger;
189
+ route.getConfig = () => this.config;
190
+ route.getMetrics = () => this.metrics;
191
+ route.getMonitoring = () => this.monitoring;
192
+ route.getFileSystem = () => this.fileSystem;
193
+ route.getDebug = () => logger;
183
194
 
184
195
  httpRoutes.push(route);
185
196
  }
@@ -210,11 +221,11 @@ export class Browserless {
210
221
  );
211
222
 
212
223
  route.querySchema = safeParse(querySchema);
213
- route._config = () => this.config;
214
- route._metrics = () => this.metrics;
215
- route._monitor = () => this.monitoring;
216
- route._fileSystem = () => this.fileSystem;
217
- route._debug = () => logger;
224
+ route.getConfig = () => this.config;
225
+ route.getMetrics = () => this.metrics;
226
+ route.getMonitoring = () => this.monitoring;
227
+ route.getFileSystem = () => this.fileSystem;
228
+ route.getDebug = () => logger;
218
229
 
219
230
  wsRoutes.push(route);
220
231
  }
@@ -232,15 +243,16 @@ export class Browserless {
232
243
  }
233
244
  });
234
245
 
246
+ httpRoutes.forEach((r) => this.router.registerHTTPRoute(r));
247
+ wsRoutes.forEach((r) => this.router.registerWebSocketRoute(r));
248
+
235
249
  this.debug(`Imported and validated all route files, starting up server.`);
236
250
 
237
251
  this.server = new HTTPServer(
238
252
  this.config,
239
253
  this.metrics,
240
- this.browserManager,
241
- this.limiter,
242
- httpRoutes,
243
- wsRoutes,
254
+ this.token,
255
+ this.router,
244
256
  );
245
257
 
246
258
  await this.server.start();
@@ -24,16 +24,16 @@ import puppeteerStealth from 'puppeteer-extra';
24
24
  puppeteerStealth.use(StealthPlugin());
25
25
 
26
26
  export class CDPChromium extends EventEmitter {
27
- private config: Config;
28
- private userDataDir: string | null;
29
- private record: boolean;
30
- private blockAds: boolean;
31
- private running = false;
32
- private browser: Browser | null = null;
33
- private browserWSEndpoint: string | null = null;
34
- private port?: number;
35
- private debug = createLogger('browsers:cdp:chromium');
36
- private proxy = httpProxy.createProxyServer();
27
+ protected config: Config;
28
+ protected userDataDir: string | null;
29
+ protected record: boolean;
30
+ protected blockAds: boolean;
31
+ protected running = false;
32
+ protected browser: Browser | null = null;
33
+ protected browserWSEndpoint: string | null = null;
34
+ protected port?: number;
35
+ protected debug = createLogger('browsers:cdp:chromium');
36
+ protected proxy = httpProxy.createProxyServer();
37
37
 
38
38
  constructor({
39
39
  userDataDir,
@@ -55,12 +55,12 @@ export class CDPChromium extends EventEmitter {
55
55
  this.debug(`Starting new browser instance`);
56
56
  }
57
57
 
58
- private cleanListeners() {
58
+ protected cleanListeners() {
59
59
  this.browser?.removeAllListeners();
60
60
  this.removeAllListeners();
61
61
  }
62
62
 
63
- private setUpEmbeddedAPI = async (
63
+ protected setUpEmbeddedAPI = async (
64
64
  page: Page,
65
65
  id: string,
66
66
  record: boolean,
@@ -189,7 +189,7 @@ export class CDPChromium extends EventEmitter {
189
189
  return makeExternalURL(serverAddress, 'live', query);
190
190
  };
191
191
 
192
- private onTargetCreated = async (target: Target) => {
192
+ protected onTargetCreated = async (target: Target) => {
193
193
  if (target.type() === 'page') {
194
194
  const page = await target.page().catch((e) => {
195
195
  this.debug(`Error in new page ${e}`);
@@ -17,7 +17,6 @@ import {
17
17
  convertIfBase64,
18
18
  createLogger,
19
19
  exists,
20
- getTokenFromRequest,
21
20
  id,
22
21
  makeExternalURL,
23
22
  noop,
@@ -29,14 +28,14 @@ import { deleteAsync } from 'del';
29
28
  import { mkdir } from 'fs/promises';
30
29
 
31
30
  export class BrowserManager {
32
- private browsers: Map<BrowserInstance, BrowserlessSession> = new Map();
33
- private launching: Map<string, Promise<unknown>> = new Map();
34
- private timers: Map<string, number> = new Map();
35
- private debug = createLogger('browser-manager');
31
+ protected browsers: Map<BrowserInstance, BrowserlessSession> = new Map();
32
+ protected launching: Map<string, Promise<unknown>> = new Map();
33
+ protected timers: Map<string, number> = new Map();
34
+ protected debug = createLogger('browser-manager');
36
35
 
37
- constructor(private config: Config) {}
36
+ constructor(protected config: Config) {}
38
37
 
39
- private removeUserDataDir = async (userDataDir: string | null) => {
38
+ protected removeUserDataDir = async (userDataDir: string | null) => {
40
39
  if (userDataDir && (await exists(userDataDir))) {
41
40
  this.debug(`Deleting data directory "${userDataDir}"`);
42
41
  await deleteAsync(userDataDir, { force: true }).catch((err) => {
@@ -56,7 +55,7 @@ export class BrowserManager {
56
55
  * @param sessionId The ID of the session
57
56
  * @returns Promise<string> of the fully-qualified path of the directory
58
57
  */
59
- private generateDataDir = async (
58
+ protected generateDataDir = async (
60
59
  sessionId: string = id(),
61
60
  ): Promise<string> => {
62
61
  const baseDirectory = await this.config.getDataDir();
@@ -83,7 +82,7 @@ export class BrowserManager {
83
82
  return dataDirPath;
84
83
  };
85
84
 
86
- private generateSessionJson = (
85
+ protected generateSessionJson = (
87
86
  browser: BrowserInstance,
88
87
  session: BrowserlessSession,
89
88
  ) => {
@@ -127,17 +126,9 @@ export class BrowserManager {
127
126
  await Promise.all(cleanupACtions.map((a) => a()));
128
127
  };
129
128
 
130
- public getAllSessions = async (
131
- req: Request,
132
- ): Promise<BrowserlessSessionJSON[]> => {
129
+ public getAllSessions = async (): Promise<BrowserlessSessionJSON[]> => {
133
130
  const sessions = Array.from(this.browsers);
134
131
 
135
- const requestToken = getTokenFromRequest(req);
136
- const token = this.config.getToken();
137
- if (token && !requestToken) {
138
- throw new BadRequest(`Couldn't locate your API token`);
139
- }
140
-
141
132
  return sessions.map(([browser, session]) =>
142
133
  this.generateSessionJson(browser, session),
143
134
  );
@@ -203,12 +194,6 @@ export class BrowserManager {
203
194
  `Error parsing launch-options: ${err}. Launch options must be a JSON or base64-encoded JSON object`,
204
195
  );
205
196
  }
206
- const requestToken = getTokenFromRequest(req);
207
- const token = this.config.getToken();
208
-
209
- if (token && !requestToken) {
210
- throw new ServerError(`Error locating authorization token`);
211
- }
212
197
 
213
198
  const routerOptions =
214
199
  typeof router.defaultLaunchOptions === 'function'
@@ -11,14 +11,14 @@ import { EventEmitter } from 'events';
11
11
  import httpProxy from 'http-proxy';
12
12
 
13
13
  export class PlaywrightChromium extends EventEmitter {
14
- private config: Config;
15
- private userDataDir: string | null;
16
- private record: boolean;
17
- private running = false;
18
- private proxy = httpProxy.createProxyServer();
19
- private browser: playwright.BrowserServer | null = null;
20
- private browserWSEndpoint: string | null = null;
21
- private debug = createLogger('browsers:playwright:chromium');
14
+ protected config: Config;
15
+ protected userDataDir: string | null;
16
+ protected record: boolean;
17
+ protected running = false;
18
+ protected proxy = httpProxy.createProxyServer();
19
+ protected browser: playwright.BrowserServer | null = null;
20
+ protected browserWSEndpoint: string | null = null;
21
+ protected debug = createLogger('browsers:playwright:chromium');
22
22
 
23
23
  constructor({
24
24
  config,
@@ -38,7 +38,7 @@ export class PlaywrightChromium extends EventEmitter {
38
38
  this.debug(`Starting new browser instance`);
39
39
  }
40
40
 
41
- private cleanListeners() {
41
+ protected cleanListeners() {
42
42
  this.removeAllListeners();
43
43
  }
44
44
 
@@ -11,14 +11,14 @@ import { EventEmitter } from 'events';
11
11
  import httpProxy from 'http-proxy';
12
12
 
13
13
  export class PlaywrightFirefox extends EventEmitter {
14
- private config: Config;
15
- private userDataDir: string | null;
16
- private record: boolean;
17
- private running = false;
18
- private proxy = httpProxy.createProxyServer();
19
- private browser: playwright.BrowserServer | null = null;
20
- private browserWSEndpoint: string | null = null;
21
- private debug = createLogger('browsers:playwright:firefox');
14
+ protected config: Config;
15
+ protected userDataDir: string | null;
16
+ protected record: boolean;
17
+ protected running = false;
18
+ protected proxy = httpProxy.createProxyServer();
19
+ protected browser: playwright.BrowserServer | null = null;
20
+ protected browserWSEndpoint: string | null = null;
21
+ protected debug = createLogger('browsers:playwright:firefox');
22
22
 
23
23
  constructor({
24
24
  config,
@@ -38,7 +38,7 @@ export class PlaywrightFirefox extends EventEmitter {
38
38
  this.debug(`Starting new browser instance`);
39
39
  }
40
40
 
41
- private cleanListeners() {
41
+ protected cleanListeners() {
42
42
  this.removeAllListeners();
43
43
  }
44
44
 
@@ -11,14 +11,14 @@ import { EventEmitter } from 'events';
11
11
  import httpProxy from 'http-proxy';
12
12
 
13
13
  export class PlaywrightWebkit extends EventEmitter {
14
- private config: Config;
15
- private userDataDir: string | null;
16
- private record: boolean;
17
- private running = false;
18
- private proxy = httpProxy.createProxyServer();
19
- private browser: playwright.BrowserServer | null = null;
20
- private browserWSEndpoint: string | null = null;
21
- private debug = createLogger('browsers:playwright:webkit');
14
+ protected config: Config;
15
+ protected userDataDir: string | null;
16
+ protected record: boolean;
17
+ protected running = false;
18
+ protected proxy = httpProxy.createProxyServer();
19
+ protected browser: playwright.BrowserServer | null = null;
20
+ protected browserWSEndpoint: string | null = null;
21
+ protected debug = createLogger('browsers:playwright:webkit');
22
22
 
23
23
  constructor({
24
24
  config,
@@ -38,7 +38,7 @@ export class PlaywrightWebkit extends EventEmitter {
38
38
  this.debug(`Starting new browser instance`);
39
39
  }
40
40
 
41
- private cleanListeners() {
41
+ protected cleanListeners() {
42
42
  this.removeAllListeners();
43
43
  }
44
44
 
package/src/config.ts CHANGED
@@ -109,60 +109,61 @@ const getDebug = () => {
109
109
  };
110
110
 
111
111
  export class Config extends EventEmitter {
112
- private readonly debug = getDebug();
113
- private readonly host = process.env.HOST ?? 'localhost';
114
- private readonly external = process.env.PROXY_URL ?? process.env.EXTERNAL;
115
- private readonly isWin = process.platform === 'win32';
112
+ protected readonly debug = getDebug();
113
+ protected readonly host = process.env.HOST ?? 'localhost';
114
+ protected readonly external = process.env.PROXY_URL ?? process.env.EXTERNAL;
115
+ protected readonly isWin = process.platform === 'win32';
116
116
 
117
- private port = +(process.env.PORT ?? '3000');
117
+ protected port = +(process.env.PORT ?? '3000');
118
118
 
119
- private downloadsDir = process.env.DOWNLOAD_DIR
119
+ protected downloadsDir = process.env.DOWNLOAD_DIR
120
120
  ? untildify(process.env.DOWNLOAD_DIR)
121
121
  : path.join(tmpdir(), 'browserless-download-dirs');
122
122
 
123
- private dataDir = process.env.DATA_DIR
123
+ protected dataDir = process.env.DATA_DIR
124
124
  ? untildify(process.env.DATA_DIR)
125
125
  : path.join(tmpdir(), 'browserless-data-dirs');
126
126
 
127
- private metricsJSONPath = process.env.METRICS_JSON_PATH
127
+ protected metricsJSONPath = process.env.METRICS_JSON_PATH
128
128
  ? untildify(process.env.METRICS_JSON_PATH)
129
129
  : path.join(tmpdir(), 'browserless-metrics.json');
130
130
 
131
- private createDataDir = !process.env.DATA_DIR;
132
- private createDownloadsDir = !process.env.DOWNLOAD_DIR;
131
+ protected createDataDir = !process.env.DATA_DIR;
132
+ protected createDownloadsDir = !process.env.DOWNLOAD_DIR;
133
133
 
134
- private routes = process.env.ROUTES
134
+ protected routes = process.env.ROUTES
135
135
  ? untildify(process.env.ROUTES)
136
136
  : path.join(__dirname, '..', 'build', 'routes');
137
137
 
138
- private token = process.env.TOKEN || null;
139
- private concurrent = +(
138
+ protected token = process.env.TOKEN || null;
139
+ protected concurrent = +(
140
140
  process.env.CONCURRENT ??
141
141
  process.env.MAX_CONCURRENT_SESSIONS ??
142
142
  '10'
143
143
  );
144
- private queued = +(process.env.QUEUE_LENGTH ?? process.env.QUEUED ?? '10');
145
- private timeout = +(
144
+ protected queued = +(process.env.QUEUE_LENGTH ?? process.env.QUEUED ?? '10');
145
+ protected timeout = +(
146
146
  process.env.TIMEOUT ??
147
147
  process.env.CONNECTION_TIMEOUT ??
148
148
  '30000'
149
149
  );
150
- private static = process.env.STATIC ?? path.join(__dirname, '..', 'static');
151
- private retries = +(process.env.RETRIES ?? '5');
152
- private allowFileProtocol = !!parseEnvVars(false, 'ALLOW_FILE_PROTOCOL');
153
- private allowGet = !!parseEnvVars(false, 'ALLOW_GET', 'ENABLE_API_GET');
154
- private allowCors = !!parseEnvVars(false, 'CORS', 'ENABLE_CORS');
155
- private corsMethods = process.env.CORS_ALLOW_METHODS ?? 'OPTIONS, POST, GET';
156
- private corsOrigin = process.env.CORS_ALLOW_ORIGIN ?? '*';
157
- private corsMaxAge = +(process.env.CORS_MAX_AGE ?? '2592000');
158
- private maxCpu = +(process.env.MAX_CPU_PERCENT ?? '99');
159
- private maxMemory = +(process.env.MAX_MEMORY_PERCENT ?? '99');
160
- private healthCheck = !!parseEnvVars(false, 'HEALTH');
161
- private failedHealthURL = process.env.FAILED_HEALTH_URL ?? null;
162
- private queueAlertURL = process.env.QUEUE_ALERT_URL ?? null;
163
- private rejectAlertURL = process.env.REJECT_ALERT_URL ?? null;
164
- private timeoutAlertURL = process.env.TIMEOUT_ALERT_URL ?? null;
165
- private errorAlertURL = process.env.ERROR_ALERT_URL ?? null;
150
+ protected static = process.env.STATIC ?? path.join(__dirname, '..', 'static');
151
+ protected retries = +(process.env.RETRIES ?? '5');
152
+ protected allowFileProtocol = !!parseEnvVars(false, 'ALLOW_FILE_PROTOCOL');
153
+ protected allowGet = !!parseEnvVars(false, 'ALLOW_GET', 'ENABLE_API_GET');
154
+ protected allowCors = !!parseEnvVars(false, 'CORS', 'ENABLE_CORS');
155
+ protected corsMethods =
156
+ process.env.CORS_ALLOW_METHODS ?? 'OPTIONS, POST, GET';
157
+ protected corsOrigin = process.env.CORS_ALLOW_ORIGIN ?? '*';
158
+ protected corsMaxAge = +(process.env.CORS_MAX_AGE ?? '2592000');
159
+ protected maxCpu = +(process.env.MAX_CPU_PERCENT ?? '99');
160
+ protected maxMemory = +(process.env.MAX_MEMORY_PERCENT ?? '99');
161
+ protected healthCheck = !!parseEnvVars(false, 'HEALTH');
162
+ protected failedHealthURL = process.env.FAILED_HEALTH_URL ?? null;
163
+ protected queueAlertURL = process.env.QUEUE_ALERT_URL ?? null;
164
+ protected rejectAlertURL = process.env.REJECT_ALERT_URL ?? null;
165
+ protected timeoutAlertURL = process.env.TIMEOUT_ALERT_URL ?? null;
166
+ protected errorAlertURL = process.env.ERROR_ALERT_URL ?? null;
166
167
 
167
168
  public getRoutes = (): string => this.routes;
168
169
  public getHost = (): string => this.host;
package/src/exports.ts CHANGED
@@ -9,8 +9,10 @@ export * from './limiter.js';
9
9
  export * from './metrics.js';
10
10
  export * from './mime-types.js';
11
11
  export * from './monitoring.js';
12
+ export * from './router.js';
12
13
  export * from './server.js';
13
14
  export * from './shim.js';
15
+ export * from './token.js';
14
16
  export * from './types.js';
15
17
  export * from './utils.js';
16
18
  export * from './webhooks.js';
@@ -2,9 +2,9 @@ import { Config, decrypt, encrypt } from '@browserless.io/browserless';
2
2
  import { readFile, writeFile } from 'fs/promises';
3
3
 
4
4
  export class FileSystem {
5
- private fsMap: Map<string, string[]> = new Map();
5
+ protected fsMap: Map<string, string[]> = new Map();
6
6
 
7
- constructor(private config: Config) {}
7
+ constructor(protected config: Config) {}
8
8
 
9
9
  /**
10
10
  * Appends contents to a file-path for persistance. File contents are
package/src/limiter.ts CHANGED
@@ -25,14 +25,14 @@ interface Job {
25
25
  }
26
26
 
27
27
  export class Limiter extends q {
28
- private queued: number;
29
- private debug = createLogger('limiter');
28
+ protected queued: number;
29
+ protected debug = createLogger('limiter');
30
30
 
31
31
  constructor(
32
- private config: Config,
33
- private metrics: Metrics,
34
- private monitor: Monitoring,
35
- private webhooks: WebHooks,
32
+ protected config: Config,
33
+ protected metrics: Metrics,
34
+ protected monitor: Monitoring,
35
+ protected webhooks: WebHooks,
36
36
  ) {
37
37
  super({
38
38
  autostart: true,
@@ -73,11 +73,11 @@ export class Limiter extends q {
73
73
  this.addEventListener('end', this.handleEnd);
74
74
  }
75
75
 
76
- private handleEnd() {
76
+ protected handleEnd() {
77
77
  this.logQueue('All jobs complete.');
78
78
  }
79
79
 
80
- private handleSuccess({ detail: { job } }: { detail: { job: Job } }) {
80
+ protected handleSuccess({ detail: { job } }: { detail: { job: Job } }) {
81
81
  const timeUsed = Date.now() - job.start;
82
82
  this.debug(
83
83
  `Job has succeeded after ${timeUsed.toLocaleString()}ms of activity.`,
@@ -91,7 +91,7 @@ export class Limiter extends q {
91
91
  } as AfterResponse);
92
92
  }
93
93
 
94
- private handleJobTimeout({
94
+ protected handleJobTimeout({
95
95
  detail: { next, job },
96
96
  }: {
97
97
  detail: { job: Job; next: Job };
@@ -113,7 +113,7 @@ export class Limiter extends q {
113
113
  next();
114
114
  }
115
115
 
116
- private handleFail({
116
+ protected handleFail({
117
117
  detail: { error, job },
118
118
  }: {
119
119
  detail: { error: unknown; job: Job };
@@ -128,7 +128,7 @@ export class Limiter extends q {
128
128
  } as AfterResponse);
129
129
  }
130
130
 
131
- private logQueue(message: string) {
131
+ protected logQueue(message: string) {
132
132
  this.debug(
133
133
  `(Running: ${this.executing}, Pending: ${this.waiting}) ${message} `,
134
134
  );
package/src/metrics.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import { IBrowserlessStats } from '@browserless.io/browserless';
2
2
 
3
3
  export class Metrics {
4
- private sessionTimes: number[] = [];
5
- private successful = 0;
6
- private queued = 0;
7
- private rejected = 0;
8
- private unauthorized = 0;
9
- private concurrent = 0;
10
- private timedout = 0;
11
- private running = 0;
12
- private unhealthy = 0;
13
- private error = 0;
4
+ protected sessionTimes: number[] = [];
5
+ protected successful = 0;
6
+ protected queued = 0;
7
+ protected rejected = 0;
8
+ protected unauthorized = 0;
9
+ protected concurrent = 0;
10
+ protected timedout = 0;
11
+ protected running = 0;
12
+ protected unhealthy = 0;
13
+ protected error = 0;
14
14
 
15
15
  addSuccessful = (sessionTime: number): number => {
16
16
  --this.running;
@@ -90,7 +90,7 @@ export class Metrics {
90
90
  this.sessionTimes = [];
91
91
  };
92
92
 
93
- private calculateStats(sessionTimes: number[]) {
93
+ protected calculateStats(sessionTimes: number[]) {
94
94
  return {
95
95
  maxTime: Math.max(...sessionTimes) || 0,
96
96
  meanTime: sessionTimes.reduce(
package/src/monitoring.ts CHANGED
@@ -6,8 +6,8 @@ import {
6
6
  import si from 'systeminformation';
7
7
 
8
8
  export class Monitoring {
9
- private log = createLogger('hardware');
10
- constructor(private config: Config) {}
9
+ protected log = createLogger('hardware');
10
+ constructor(protected config: Config) {}
11
11
 
12
12
  public getMachineStats = async (): Promise<IResourceLoad> => {
13
13
  const [cpuLoad, memLoad] = await Promise.all([