@browserless.io/browserless 2.0.0-beta-1 → 2.0.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/bin/browserless.js +157 -15
- package/build/browserless.d.ts +23 -18
- package/build/browserless.js +24 -17
- package/build/browsers/cdp-chromium.d.ts +17 -14
- package/build/browsers/index.d.ts +27 -10
- package/build/browsers/index.js +2 -12
- package/build/browsers/playwright-chromium.d.ts +12 -9
- package/build/browsers/playwright-firefox.d.ts +12 -9
- package/build/browsers/playwright-webkit.d.ts +12 -9
- package/build/config.d.ts +31 -31
- package/build/exports.d.ts +2 -0
- package/build/exports.js +2 -0
- package/build/file-system.d.ts +2 -2
- package/build/limiter.d.ts +34 -11
- package/build/metrics.d.ts +17 -11
- package/build/monitoring.d.ts +3 -2
- package/build/router.d.ts +28 -0
- package/build/router.js +138 -0
- package/build/routes/chromium/http/content-post.body.json +8 -8
- package/build/routes/chromium/http/download-post.js +1 -1
- package/build/routes/chromium/http/function-post.js +1 -1
- package/build/routes/chromium/http/pdf-post.body.json +8 -8
- package/build/routes/chromium/http/performance.js +1 -1
- package/build/routes/chromium/http/scrape-post.body.json +8 -8
- package/build/routes/chromium/http/screenshot-post.body.json +8 -8
- package/build/routes/chromium/utils/function/client.d.ts +3 -3
- package/build/routes/management/http/config-get.js +1 -1
- package/build/routes/management/http/metrics-get.js +1 -1
- package/build/routes/management/http/metrics-total-get.js +1 -1
- package/build/routes/management/http/sessions-get.js +3 -3
- package/build/routes/management/http/static-get.js +1 -1
- package/build/server.d.ts +22 -27
- package/build/server.js +29 -149
- package/build/token.d.ts +6 -0
- package/build/token.js +21 -0
- package/build/types.d.ts +85 -14
- package/build/utils.d.ts +1 -2
- package/build/utils.js +0 -13
- package/build/webhooks.d.ts +2 -2
- package/docker/sdk/Dockerfile +2 -6
- package/package.json +6 -6
- package/src/browserless.ts +44 -32
- package/src/browsers/cdp-chromium.ts +13 -13
- package/src/browsers/index.ts +9 -24
- package/src/browsers/playwright-chromium.ts +9 -9
- package/src/browsers/playwright-firefox.ts +9 -9
- package/src/browsers/playwright-webkit.ts +9 -9
- package/src/config.ts +32 -31
- package/src/exports.ts +2 -0
- package/src/file-system.ts +2 -2
- package/src/limiter.ts +11 -11
- package/src/metrics.ts +11 -11
- package/src/monitoring.ts +2 -2
- package/src/router.ts +234 -0
- package/src/routes/chromium/http/download-post.ts +1 -1
- package/src/routes/chromium/http/function-post.ts +1 -1
- package/src/routes/chromium/http/performance.ts +1 -1
- package/src/routes/chromium/utils/function/client.ts +2 -2
- package/src/routes/management/http/config-get.ts +1 -1
- package/src/routes/management/http/metrics-get.ts +1 -1
- package/src/routes/management/http/metrics-total-get.ts +1 -1
- package/src/routes/management/http/sessions-get.ts +3 -3
- package/src/routes/management/http/static-get.ts +1 -1
- package/src/server.ts +43 -238
- package/src/token.ts +40 -0
- package/src/types.ts +91 -17
- package/src/utils.ts +0 -25
- package/src/webhooks.ts +2 -2
- package/static/docs/swagger.json +9 -9
- package/tsconfig.json +7 -10
package/bin/browserless.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Browserless } from '@browserless.io/browserless';
|
|
|
5
5
|
import buildOpenAPI from '../scripts/build-open-api.js';
|
|
6
6
|
import buildSchemas from '../scripts/build-schemas.js';
|
|
7
7
|
|
|
8
|
+
import { createInterface } from 'readline';
|
|
8
9
|
import debug from 'debug';
|
|
9
10
|
import { fileURLToPath } from 'url';
|
|
10
11
|
import fs from 'fs/promises';
|
|
@@ -12,6 +13,7 @@ import path from 'path';
|
|
|
12
13
|
import { spawn } from 'child_process';
|
|
13
14
|
|
|
14
15
|
const log = debug('browserless:sdk:log');
|
|
16
|
+
const promptLog = debug('browserless:prompt');
|
|
15
17
|
|
|
16
18
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
17
19
|
const cmd = process.argv[2];
|
|
@@ -25,6 +27,21 @@ if (!allowedCMDs.includes(cmd)) {
|
|
|
25
27
|
);
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
const prompt = async (question) => {
|
|
31
|
+
const rl = createInterface({
|
|
32
|
+
input: process.stdin,
|
|
33
|
+
output: process.stdout,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return new Promise((resolve) => {
|
|
37
|
+
promptLog(question);
|
|
38
|
+
rl.question(' > ', (a) => {
|
|
39
|
+
rl.close();
|
|
40
|
+
resolve(a.trim());
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
28
45
|
const importClassOverride = async (files, className) => {
|
|
29
46
|
const classModuleFile = files.find((f) =>
|
|
30
47
|
path.parse(f).name.endsWith(className),
|
|
@@ -43,6 +60,24 @@ const importClassOverride = async (files, className) => {
|
|
|
43
60
|
return (await import(classModuleFullFilePath)).default;
|
|
44
61
|
};
|
|
45
62
|
|
|
63
|
+
const buildDockerImage = async (cmd) => {
|
|
64
|
+
new Promise((resolve, reject) => {
|
|
65
|
+
const [docker, ...args] = cmd.split(' ');
|
|
66
|
+
spawn(docker, args, {
|
|
67
|
+
cwd,
|
|
68
|
+
stdio: 'inherit',
|
|
69
|
+
}).once('close', (code) => {
|
|
70
|
+
if (code === 0) {
|
|
71
|
+
log(`Successfully built the docker image.`);
|
|
72
|
+
return resolve();
|
|
73
|
+
}
|
|
74
|
+
return reject(
|
|
75
|
+
`Error when building Docker image, see output for more details`,
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
|
|
46
81
|
const buildTypeScript = async () =>
|
|
47
82
|
new Promise((resolve, reject) => {
|
|
48
83
|
spawn('npx', ['tsc', '--outDir', 'build'], {
|
|
@@ -83,6 +118,35 @@ const getSourceFiles = async () => {
|
|
|
83
118
|
};
|
|
84
119
|
};
|
|
85
120
|
|
|
121
|
+
const getArgSwitches = () => {
|
|
122
|
+
return process.argv.reduce((accum, arg, idx) => {
|
|
123
|
+
if (!arg.startsWith('--')) {
|
|
124
|
+
return accum;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (arg.includes('=')) {
|
|
128
|
+
const [parameter, value] = arg.split('=');
|
|
129
|
+
accum[parameter.replace(/-/gi, '')] = value || true;
|
|
130
|
+
return accum;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const nextSwitchOrParameter = process.argv[idx + 1];
|
|
134
|
+
const param = arg.replace(/-/gi, '');
|
|
135
|
+
|
|
136
|
+
if (
|
|
137
|
+
typeof nextSwitchOrParameter === 'undefined' ||
|
|
138
|
+
nextSwitchOrParameter?.startsWith('--')
|
|
139
|
+
) {
|
|
140
|
+
accum[param] = true;
|
|
141
|
+
return accum;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
accum[param] = nextSwitchOrParameter;
|
|
145
|
+
|
|
146
|
+
return accum;
|
|
147
|
+
}, {});
|
|
148
|
+
};
|
|
149
|
+
|
|
86
150
|
/**
|
|
87
151
|
* Build
|
|
88
152
|
* Responsible for compiling TypeScript, generating routes meta-data
|
|
@@ -113,20 +177,25 @@ const build = async () => {
|
|
|
113
177
|
};
|
|
114
178
|
};
|
|
115
179
|
|
|
180
|
+
const isConstructor = (reference) => typeof reference === 'function';
|
|
181
|
+
|
|
116
182
|
const start = async (dev = false) => {
|
|
117
183
|
const { httpRoutes, webSocketRoutes, files } = dev
|
|
118
184
|
? await build()
|
|
119
185
|
: await getSourceFiles();
|
|
120
186
|
|
|
121
187
|
log(`Importing all class overrides if present`);
|
|
188
|
+
|
|
122
189
|
const [
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
190
|
+
BrowserManager,
|
|
191
|
+
Config,
|
|
192
|
+
FileSystem,
|
|
193
|
+
Limiter,
|
|
194
|
+
Metrics,
|
|
195
|
+
Monitoring,
|
|
196
|
+
Router,
|
|
197
|
+
Token,
|
|
198
|
+
Webhooks,
|
|
130
199
|
] = await Promise.all([
|
|
131
200
|
importClassOverride(files, 'browser-manager'),
|
|
132
201
|
importClassOverride(files, 'config'),
|
|
@@ -134,10 +203,33 @@ const start = async (dev = false) => {
|
|
|
134
203
|
importClassOverride(files, 'limiter'),
|
|
135
204
|
importClassOverride(files, 'metrics'),
|
|
136
205
|
importClassOverride(files, 'monitoring'),
|
|
206
|
+
importClassOverride(files, 'router'),
|
|
207
|
+
importClassOverride(files, 'token'),
|
|
137
208
|
importClassOverride(files, 'webhooks'),
|
|
138
209
|
]);
|
|
139
210
|
|
|
140
211
|
log(`Starting Browserless`);
|
|
212
|
+
|
|
213
|
+
const config = isConstructor(Config) ? new Config() : config;
|
|
214
|
+
const metrics = isConstructor(Metrics) ? new Metrics() : metrics;
|
|
215
|
+
const token = isConstructor(Token) ? new Token(config) : token;
|
|
216
|
+
const webhooks = isConstructor(Webhooks) ? new Webhooks(config) : webhooks;
|
|
217
|
+
const browserManager = isConstructor(BrowserManager)
|
|
218
|
+
? new BrowserManager(config)
|
|
219
|
+
: browserManager;
|
|
220
|
+
const monitoring = isConstructor(Monitoring)
|
|
221
|
+
? new Monitoring(config)
|
|
222
|
+
: monitoring;
|
|
223
|
+
const fileSystem = isConstructor(FileSystem)
|
|
224
|
+
? new FileSystem(config)
|
|
225
|
+
: fileSystem;
|
|
226
|
+
const limiter = isConstructor(Limiter)
|
|
227
|
+
? new Limiter(config, metrics, monitoring, webhooks)
|
|
228
|
+
: limiter;
|
|
229
|
+
const router = isConstructor(Router)
|
|
230
|
+
? new Router(config, browserManager, limiter)
|
|
231
|
+
: router;
|
|
232
|
+
|
|
141
233
|
const browserless = new Browserless({
|
|
142
234
|
browserManager,
|
|
143
235
|
config,
|
|
@@ -145,6 +237,8 @@ const start = async (dev = false) => {
|
|
|
145
237
|
limiter,
|
|
146
238
|
metrics,
|
|
147
239
|
monitoring,
|
|
240
|
+
router,
|
|
241
|
+
token,
|
|
148
242
|
webhooks,
|
|
149
243
|
});
|
|
150
244
|
|
|
@@ -191,21 +285,69 @@ const start = async (dev = false) => {
|
|
|
191
285
|
};
|
|
192
286
|
|
|
193
287
|
const buildDocker = async () => {
|
|
194
|
-
const from = process.argv[3] ?? 'ghcr.io/browserless/multi';
|
|
195
|
-
const version = process.argv[4] ?? 'latest';
|
|
196
288
|
const finalDockerPath = path.join(cwd, 'build', 'Dockerfile');
|
|
289
|
+
const argSwitches = getArgSwitches();
|
|
290
|
+
|
|
291
|
+
await build();
|
|
197
292
|
|
|
198
293
|
const dockerContents = (
|
|
199
294
|
await fs.readFile(path.join(__dirname, '..', 'docker', 'sdk', 'Dockerfile'))
|
|
200
295
|
).toString();
|
|
201
296
|
|
|
202
|
-
log(`
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
297
|
+
log(`Generating Dockerfile at "${finalDockerPath}"`);
|
|
298
|
+
|
|
299
|
+
await fs.writeFile(path.join(cwd, 'build', 'Dockerfile'), dockerContents);
|
|
300
|
+
|
|
301
|
+
const from =
|
|
302
|
+
argSwitches.from ||
|
|
303
|
+
(await prompt(
|
|
304
|
+
'Which docker image do you want to use (defaults to: ghcr.io/browserless/multi)?',
|
|
305
|
+
)) ||
|
|
306
|
+
'ghcr.io/browserless/multi';
|
|
207
307
|
|
|
208
|
-
|
|
308
|
+
const action =
|
|
309
|
+
argSwitches.action ||
|
|
310
|
+
(await prompt(
|
|
311
|
+
'Do you want to push the image or load it locally (defaults to load)?',
|
|
312
|
+
)) ||
|
|
313
|
+
'load';
|
|
314
|
+
|
|
315
|
+
const tag =
|
|
316
|
+
argSwitches.tag ||
|
|
317
|
+
(await prompt(
|
|
318
|
+
'What do you want to name the resulting image (eg, my-browserless:latest)?',
|
|
319
|
+
));
|
|
320
|
+
|
|
321
|
+
if (!tag || !tag.includes(':')) {
|
|
322
|
+
throw new Error(`A name for the image is required with a ":" and version.`);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const platformsPrompt =
|
|
326
|
+
action === 'load'
|
|
327
|
+
? `Which platform do you want to build for (defaults to linux/amd64)?`
|
|
328
|
+
: `Which platforms do you want to build? (defaults to "linux/amd64", must be comma-separated)?`;
|
|
329
|
+
|
|
330
|
+
const platforms =
|
|
331
|
+
argSwitches.platform || (await prompt(platformsPrompt)) || 'linux/amd64';
|
|
332
|
+
|
|
333
|
+
if (action === 'load' && platforms.includes(',')) {
|
|
334
|
+
throw new Error(
|
|
335
|
+
`When "load" is specified, only one platform can be built due to limitations in buildx.`,
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const cmd = `docker buildx build --build-arg FROM=${from} --platform ${platforms} --${action} -f ./build/Dockerfile -t ${tag} .`;
|
|
340
|
+
|
|
341
|
+
const proceed =
|
|
342
|
+
argSwitches.proceed ||
|
|
343
|
+
(await prompt(`Will execute "${cmd}" Proceed (y/n)?`)) ||
|
|
344
|
+
'n';
|
|
345
|
+
|
|
346
|
+
if (proceed || !proceed.includes('n')) {
|
|
347
|
+
log(`Starting docker build`);
|
|
348
|
+
await buildDockerImage(cmd);
|
|
349
|
+
process.exit(0);
|
|
350
|
+
}
|
|
209
351
|
};
|
|
210
352
|
|
|
211
353
|
switch (cmd) {
|
package/build/browserless.d.ts
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
|
+
/// <reference types="debug" />
|
|
1
2
|
/// <reference types="node" />
|
|
2
|
-
import { BrowserManager, Config, FileSystem, HTTPServer, Limiter, Metrics, Monitoring, WebHooks } from '@browserless.io/browserless';
|
|
3
|
+
import { BrowserManager, Config, FileSystem, HTTPServer, Limiter, Metrics, Monitoring, Router, Token, WebHooks } from '@browserless.io/browserless';
|
|
3
4
|
export declare class Browserless {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
protected debug: debug.Debugger;
|
|
6
|
+
protected browserManager: BrowserManager;
|
|
7
|
+
protected config: Config;
|
|
8
|
+
protected fileSystem: FileSystem;
|
|
9
|
+
protected limiter: Limiter;
|
|
10
|
+
protected metrics: Metrics;
|
|
11
|
+
protected monitoring: Monitoring;
|
|
12
|
+
protected router: Router;
|
|
13
|
+
protected token: Token;
|
|
14
|
+
protected webhooks: WebHooks;
|
|
12
15
|
webSocketRouteFiles: string[];
|
|
13
16
|
httpRouteFiles: string[];
|
|
14
17
|
server?: HTTPServer;
|
|
15
18
|
metricsSaveInterval: number;
|
|
16
19
|
metricsSaveIntervalID?: NodeJS.Timer;
|
|
17
|
-
constructor({ browserManager, config,
|
|
18
|
-
browserManager?:
|
|
19
|
-
config?:
|
|
20
|
-
fileSystem?:
|
|
21
|
-
limiter?:
|
|
22
|
-
metrics?:
|
|
23
|
-
monitoring?:
|
|
24
|
-
|
|
20
|
+
constructor({ browserManager, config, fileSystem, limiter, metrics, monitoring, router, token, webhooks, }?: {
|
|
21
|
+
browserManager?: Browserless['browserManager'];
|
|
22
|
+
config?: Browserless['config'];
|
|
23
|
+
fileSystem?: Browserless['fileSystem'];
|
|
24
|
+
limiter?: Browserless['limiter'];
|
|
25
|
+
metrics?: Browserless['metrics'];
|
|
26
|
+
monitoring?: Browserless['monitoring'];
|
|
27
|
+
router?: Browserless['router'];
|
|
28
|
+
token?: Browserless['token'];
|
|
29
|
+
webhooks?: Browserless['webhooks'];
|
|
25
30
|
});
|
|
26
|
-
|
|
31
|
+
protected saveMetrics: () => Promise<void>;
|
|
27
32
|
setMetricsSaveInterval: (interval: number) => void;
|
|
28
33
|
addHTTPRoute(httpRouteFilePath: string): void;
|
|
29
34
|
addWebSocketRoute(webSocketRouteFilePath: string): void;
|
package/build/browserless.js
CHANGED
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
|
-
import { BrowserManager, Config, FileSystem, HTTPServer, Limiter, Metrics, Monitoring, WebHooks, availableBrowsers, createLogger, getRouteFiles, makeExternalURL, printLogo, safeParse, } from '@browserless.io/browserless';
|
|
2
|
+
import { BrowserManager, Config, FileSystem, HTTPServer, Limiter, Metrics, Monitoring, Router, Token, WebHooks, availableBrowsers, createLogger, getRouteFiles, makeExternalURL, printLogo, safeParse, } from '@browserless.io/browserless';
|
|
3
3
|
import { readFile } from 'fs/promises';
|
|
4
4
|
import { userInfo } from 'os';
|
|
5
5
|
const routeSchemas = ['body', 'query'];
|
|
6
6
|
export class Browserless {
|
|
7
|
+
debug = createLogger('index');
|
|
8
|
+
browserManager;
|
|
7
9
|
config;
|
|
8
|
-
monitoring;
|
|
9
|
-
metrics;
|
|
10
10
|
fileSystem;
|
|
11
|
-
browserManager;
|
|
12
11
|
limiter;
|
|
12
|
+
metrics;
|
|
13
|
+
monitoring;
|
|
14
|
+
router;
|
|
15
|
+
token;
|
|
13
16
|
webhooks;
|
|
14
|
-
debug = createLogger('index');
|
|
15
17
|
webSocketRouteFiles = [];
|
|
16
18
|
httpRouteFiles = [];
|
|
17
19
|
server;
|
|
18
20
|
metricsSaveInterval = 5 * 60 * 1000;
|
|
19
21
|
metricsSaveIntervalID;
|
|
20
|
-
constructor({ browserManager, config,
|
|
22
|
+
constructor({ browserManager, config, fileSystem, limiter, metrics, monitoring, router, token, webhooks, } = {}) {
|
|
21
23
|
this.config = config || new Config();
|
|
22
24
|
this.metrics = metrics || new Metrics();
|
|
25
|
+
this.token = token || new Token(this.config);
|
|
23
26
|
this.webhooks = webhooks || new WebHooks(this.config);
|
|
24
27
|
this.browserManager = browserManager || new BrowserManager(this.config);
|
|
25
28
|
this.monitoring = monitoring || new Monitoring(this.config);
|
|
@@ -27,6 +30,8 @@ export class Browserless {
|
|
|
27
30
|
this.limiter =
|
|
28
31
|
limiter ||
|
|
29
32
|
new Limiter(this.config, this.metrics, this.monitoring, this.webhooks);
|
|
33
|
+
this.router =
|
|
34
|
+
router || new Router(this.config, this.browserManager, this.limiter);
|
|
30
35
|
}
|
|
31
36
|
saveMetrics = async () => {
|
|
32
37
|
const metricsPath = this.config.getMetricsJSONPath();
|
|
@@ -101,11 +106,11 @@ export class Browserless {
|
|
|
101
106
|
const { default: route } = await import(routeImport + `?cb=${Date.now()}`);
|
|
102
107
|
route.bodySchema = safeParse(bodySchema);
|
|
103
108
|
route.querySchema = safeParse(querySchema);
|
|
104
|
-
route.
|
|
105
|
-
route.
|
|
106
|
-
route.
|
|
107
|
-
route.
|
|
108
|
-
route.
|
|
109
|
+
route.getConfig = () => this.config;
|
|
110
|
+
route.getMetrics = () => this.metrics;
|
|
111
|
+
route.getMonitoring = () => this.monitoring;
|
|
112
|
+
route.getFileSystem = () => this.fileSystem;
|
|
113
|
+
route.getDebug = () => logger;
|
|
109
114
|
httpRoutes.push(route);
|
|
110
115
|
}
|
|
111
116
|
}
|
|
@@ -122,11 +127,11 @@ export class Browserless {
|
|
|
122
127
|
const logger = createLogger(`ws:${name}`);
|
|
123
128
|
const { default: route, } = await import(wsImport + `?cb=${Date.now()}`);
|
|
124
129
|
route.querySchema = safeParse(querySchema);
|
|
125
|
-
route.
|
|
126
|
-
route.
|
|
127
|
-
route.
|
|
128
|
-
route.
|
|
129
|
-
route.
|
|
130
|
+
route.getConfig = () => this.config;
|
|
131
|
+
route.getMetrics = () => this.metrics;
|
|
132
|
+
route.getMonitoring = () => this.monitoring;
|
|
133
|
+
route.getFileSystem = () => this.fileSystem;
|
|
134
|
+
route.getDebug = () => logger;
|
|
130
135
|
wsRoutes.push(route);
|
|
131
136
|
}
|
|
132
137
|
}
|
|
@@ -137,8 +142,10 @@ export class Browserless {
|
|
|
137
142
|
throw new Error(`Couldn't load route "${route.path}" due to missing browser of "${route.browser.name}"`);
|
|
138
143
|
}
|
|
139
144
|
});
|
|
145
|
+
httpRoutes.forEach((r) => this.router.registerHTTPRoute(r));
|
|
146
|
+
wsRoutes.forEach((r) => this.router.registerWebSocketRoute(r));
|
|
140
147
|
this.debug(`Imported and validated all route files, starting up server.`);
|
|
141
|
-
this.server = new HTTPServer(this.config, this.metrics, this.
|
|
148
|
+
this.server = new HTTPServer(this.config, this.metrics, this.token, this.router);
|
|
142
149
|
await this.server.start();
|
|
143
150
|
this.debug(`Starting metrics collection.`);
|
|
144
151
|
this.metricsSaveIntervalID = setInterval(() => this.saveMetrics(), this.metricsSaveInterval);
|
|
@@ -1,33 +1,36 @@
|
|
|
1
|
+
/// <reference types="debug" />
|
|
2
|
+
/// <reference types="node" />
|
|
1
3
|
/// <reference types="node" />
|
|
2
4
|
/// <reference types="node" />
|
|
3
5
|
/// <reference types="node" />
|
|
4
6
|
/// <reference types="node" />
|
|
5
7
|
import { CDPLaunchOptions, Config, Request } from '@browserless.io/browserless';
|
|
6
|
-
import { Browser, Page } from 'puppeteer-core';
|
|
8
|
+
import { Browser, Page, Target } from 'puppeteer-core';
|
|
7
9
|
import { Duplex } from 'stream';
|
|
8
10
|
import { EventEmitter } from 'events';
|
|
11
|
+
import httpProxy from 'http-proxy';
|
|
9
12
|
export declare class CDPChromium extends EventEmitter {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
protected config: Config;
|
|
14
|
+
protected userDataDir: string | null;
|
|
15
|
+
protected record: boolean;
|
|
16
|
+
protected blockAds: boolean;
|
|
17
|
+
protected running: boolean;
|
|
18
|
+
protected browser: Browser | null;
|
|
19
|
+
protected browserWSEndpoint: string | null;
|
|
20
|
+
protected port?: number;
|
|
21
|
+
protected debug: import("debug").Debugger;
|
|
22
|
+
protected proxy: httpProxy<import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>>;
|
|
20
23
|
constructor({ userDataDir, config, record, blockAds, }: {
|
|
21
24
|
blockAds: boolean;
|
|
22
25
|
config: Config;
|
|
23
26
|
record: boolean;
|
|
24
27
|
userDataDir: CDPChromium['userDataDir'];
|
|
25
28
|
});
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
protected cleanListeners(): void;
|
|
30
|
+
protected setUpEmbeddedAPI: (page: Page, id: string, record: boolean) => Promise<void>;
|
|
28
31
|
getPageId: (page: Page) => string;
|
|
29
32
|
makeLiveURL: (browserId: string, pageId: string) => string;
|
|
30
|
-
|
|
33
|
+
protected onTargetCreated: (target: Target) => Promise<void>;
|
|
31
34
|
isRunning: () => boolean;
|
|
32
35
|
newPage: () => Promise<Page>;
|
|
33
36
|
close: () => Promise<void>;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="debug" />
|
|
2
|
+
import { BrowserHTTPRoute, BrowserInstance, BrowserServerOptions, BrowserWebsocketRoute, BrowserlessSession, BrowserlessSessionJSON, CDPLaunchOptions, Config, Request } from '@browserless.io/browserless';
|
|
2
3
|
export declare class BrowserManager {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
protected config: Config;
|
|
5
|
+
protected browsers: Map<BrowserInstance, BrowserlessSession>;
|
|
6
|
+
protected launching: Map<string, Promise<unknown>>;
|
|
7
|
+
protected timers: Map<string, number>;
|
|
8
|
+
protected debug: import("debug").Debugger;
|
|
8
9
|
constructor(config: Config);
|
|
9
|
-
|
|
10
|
+
protected removeUserDataDir: (userDataDir: string | null) => Promise<void>;
|
|
10
11
|
/**
|
|
11
12
|
* Generates a directory for the user-data-dir contents to be saved in. Uses
|
|
12
13
|
* the provided sessionId, or creates one when omitted,
|
|
@@ -16,10 +17,26 @@ export declare class BrowserManager {
|
|
|
16
17
|
* @param sessionId The ID of the session
|
|
17
18
|
* @returns Promise<string> of the fully-qualified path of the directory
|
|
18
19
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
protected generateDataDir: (sessionId?: string) => Promise<string>;
|
|
21
|
+
protected generateSessionJson: (browser: BrowserInstance, session: BrowserlessSession) => {
|
|
22
|
+
browser: string;
|
|
23
|
+
browserId: string | undefined;
|
|
24
|
+
initialConnectURL: string;
|
|
25
|
+
killURL: string | null;
|
|
26
|
+
running: boolean;
|
|
27
|
+
timeAliveMs: number;
|
|
28
|
+
id: string | null;
|
|
29
|
+
isTempDataDir: boolean;
|
|
30
|
+
launchOptions: CDPLaunchOptions | BrowserServerOptions;
|
|
31
|
+
numbConnected: number;
|
|
32
|
+
resolver: (val: unknown) => void;
|
|
33
|
+
routePath: string;
|
|
34
|
+
startedOn: number;
|
|
35
|
+
ttl: number;
|
|
36
|
+
userDataDir: string | null;
|
|
37
|
+
};
|
|
21
38
|
close: (browser: BrowserInstance, session: BrowserlessSession) => Promise<void>;
|
|
22
|
-
getAllSessions: (
|
|
39
|
+
getAllSessions: () => Promise<BrowserlessSessionJSON[]>;
|
|
23
40
|
complete: (browser: BrowserInstance) => Promise<void>;
|
|
24
41
|
getBrowserForRequest: (req: Request, router: BrowserHTTPRoute | BrowserWebsocketRoute) => Promise<BrowserInstance>;
|
|
25
42
|
stop: () => Promise<void>;
|
package/build/browsers/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BadRequest, CDPChromium, HTTPManagementRoutes, NotFound, ServerError, browserHook, convertIfBase64, createLogger, exists,
|
|
1
|
+
import { BadRequest, CDPChromium, HTTPManagementRoutes, NotFound, ServerError, browserHook, convertIfBase64, createLogger, exists, id, makeExternalURL, noop, pageHook, parseBooleanParam, } from '@browserless.io/browserless';
|
|
2
2
|
import path, { join } from 'path';
|
|
3
3
|
import { deleteAsync } from 'del';
|
|
4
4
|
import { mkdir } from 'fs/promises';
|
|
@@ -67,13 +67,8 @@ export class BrowserManager {
|
|
|
67
67
|
}
|
|
68
68
|
await Promise.all(cleanupACtions.map((a) => a()));
|
|
69
69
|
};
|
|
70
|
-
getAllSessions = async (
|
|
70
|
+
getAllSessions = async () => {
|
|
71
71
|
const sessions = Array.from(this.browsers);
|
|
72
|
-
const requestToken = getTokenFromRequest(req);
|
|
73
|
-
const token = this.config.getToken();
|
|
74
|
-
if (token && !requestToken) {
|
|
75
|
-
throw new BadRequest(`Couldn't locate your API token`);
|
|
76
|
-
}
|
|
77
72
|
return sessions.map(([browser, session]) => this.generateSessionJson(browser, session));
|
|
78
73
|
};
|
|
79
74
|
complete = async (browser) => {
|
|
@@ -113,11 +108,6 @@ export class BrowserManager {
|
|
|
113
108
|
catch (err) {
|
|
114
109
|
throw new BadRequest(`Error parsing launch-options: ${err}. Launch options must be a JSON or base64-encoded JSON object`);
|
|
115
110
|
}
|
|
116
|
-
const requestToken = getTokenFromRequest(req);
|
|
117
|
-
const token = this.config.getToken();
|
|
118
|
-
if (token && !requestToken) {
|
|
119
|
-
throw new ServerError(`Error locating authorization token`);
|
|
120
|
-
}
|
|
121
111
|
const routerOptions = typeof router.defaultLaunchOptions === 'function'
|
|
122
112
|
? router.defaultLaunchOptions(req)
|
|
123
113
|
: router.defaultLaunchOptions;
|
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="debug" />
|
|
3
|
+
/// <reference types="node" />
|
|
2
4
|
/// <reference types="node" />
|
|
3
5
|
/// <reference types="node" />
|
|
4
6
|
import { BrowserServerOptions, Config, Request } from '@browserless.io/browserless';
|
|
5
7
|
import playwright, { Page } from 'playwright-core';
|
|
6
8
|
import { Duplex } from 'stream';
|
|
7
9
|
import { EventEmitter } from 'events';
|
|
10
|
+
import httpProxy from 'http-proxy';
|
|
8
11
|
export declare class PlaywrightChromium extends EventEmitter {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
protected config: Config;
|
|
13
|
+
protected userDataDir: string | null;
|
|
14
|
+
protected record: boolean;
|
|
15
|
+
protected running: boolean;
|
|
16
|
+
protected proxy: httpProxy<import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>>;
|
|
17
|
+
protected browser: playwright.BrowserServer | null;
|
|
18
|
+
protected browserWSEndpoint: string | null;
|
|
19
|
+
protected debug: import("debug").Debugger;
|
|
17
20
|
constructor({ config, userDataDir, record, }: {
|
|
18
21
|
config: Config;
|
|
19
22
|
record: boolean;
|
|
20
23
|
userDataDir: PlaywrightChromium['userDataDir'];
|
|
21
24
|
});
|
|
22
|
-
|
|
25
|
+
protected cleanListeners(): void;
|
|
23
26
|
isRunning: () => boolean;
|
|
24
27
|
close: () => Promise<void>;
|
|
25
28
|
pages: () => Promise<[]>;
|
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="debug" />
|
|
3
|
+
/// <reference types="node" />
|
|
2
4
|
/// <reference types="node" />
|
|
3
5
|
/// <reference types="node" />
|
|
4
6
|
import { BrowserServerOptions, Config, Request } from '@browserless.io/browserless';
|
|
5
7
|
import playwright, { Page } from 'playwright-core';
|
|
6
8
|
import { Duplex } from 'stream';
|
|
7
9
|
import { EventEmitter } from 'events';
|
|
10
|
+
import httpProxy from 'http-proxy';
|
|
8
11
|
export declare class PlaywrightFirefox extends EventEmitter {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
protected config: Config;
|
|
13
|
+
protected userDataDir: string | null;
|
|
14
|
+
protected record: boolean;
|
|
15
|
+
protected running: boolean;
|
|
16
|
+
protected proxy: httpProxy<import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>>;
|
|
17
|
+
protected browser: playwright.BrowserServer | null;
|
|
18
|
+
protected browserWSEndpoint: string | null;
|
|
19
|
+
protected debug: import("debug").Debugger;
|
|
17
20
|
constructor({ config, userDataDir, record, }: {
|
|
18
21
|
config: Config;
|
|
19
22
|
record: boolean;
|
|
20
23
|
userDataDir: PlaywrightFirefox['userDataDir'];
|
|
21
24
|
});
|
|
22
|
-
|
|
25
|
+
protected cleanListeners(): void;
|
|
23
26
|
isRunning: () => boolean;
|
|
24
27
|
close: () => Promise<void>;
|
|
25
28
|
pages: () => Promise<[]>;
|
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="debug" />
|
|
3
|
+
/// <reference types="node" />
|
|
2
4
|
/// <reference types="node" />
|
|
3
5
|
/// <reference types="node" />
|
|
4
6
|
import { BrowserServerOptions, Config, Request } from '@browserless.io/browserless';
|
|
5
7
|
import playwright, { Page } from 'playwright-core';
|
|
6
8
|
import { Duplex } from 'stream';
|
|
7
9
|
import { EventEmitter } from 'events';
|
|
10
|
+
import httpProxy from 'http-proxy';
|
|
8
11
|
export declare class PlaywrightWebkit extends EventEmitter {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
protected config: Config;
|
|
13
|
+
protected userDataDir: string | null;
|
|
14
|
+
protected record: boolean;
|
|
15
|
+
protected running: boolean;
|
|
16
|
+
protected proxy: httpProxy<import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>>;
|
|
17
|
+
protected browser: playwright.BrowserServer | null;
|
|
18
|
+
protected browserWSEndpoint: string | null;
|
|
19
|
+
protected debug: import("debug").Debugger;
|
|
17
20
|
constructor({ config, userDataDir, record, }: {
|
|
18
21
|
config: Config;
|
|
19
22
|
record: boolean;
|
|
20
23
|
userDataDir: PlaywrightWebkit['userDataDir'];
|
|
21
24
|
});
|
|
22
|
-
|
|
25
|
+
protected cleanListeners(): void;
|
|
23
26
|
isRunning: () => boolean;
|
|
24
27
|
close: () => Promise<void>;
|
|
25
28
|
pages: () => Promise<[]>;
|