@browserless.io/browserless 2.7.1 → 2.9.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.
- package/CHANGELOG.md +19 -1
- package/README.md +41 -3
- package/assets/debugger.png +0 -0
- package/bin/browserless.js +8 -4
- package/bin/scaffold/README.md +6 -4
- package/bin/scaffold/src/hello-world.http.ts +7 -1
- package/build/browserless.d.ts +8 -5
- package/build/browserless.js +23 -22
- package/build/browsers/chrome.cdp.d.ts +2 -2
- package/build/browsers/chrome.cdp.js +2 -2
- package/build/browsers/chrome.playwright.d.ts +2 -2
- package/build/browsers/chrome.playwright.js +2 -2
- package/build/browsers/chromium.cdp.d.ts +4 -4
- package/build/browsers/chromium.cdp.js +49 -32
- package/build/browsers/chromium.playwright.d.ts +4 -4
- package/build/browsers/chromium.playwright.js +14 -13
- package/build/browsers/firefox.playwright.d.ts +4 -4
- package/build/browsers/firefox.playwright.js +14 -13
- package/build/browsers/index.d.ts +24 -8
- package/build/browsers/index.js +20 -15
- package/build/browsers/webkit.playwright.d.ts +4 -4
- package/build/browsers/webkit.playwright.js +14 -13
- package/build/config.d.ts +3 -0
- package/build/config.js +3 -0
- package/build/exports.d.ts +1 -0
- package/build/exports.js +1 -0
- package/build/file-system.d.ts +2 -3
- package/build/file-system.js +2 -2
- package/build/index.js +7 -7
- package/build/limiter.d.ts +2 -3
- package/build/limiter.js +11 -11
- package/build/logger.d.ts +19 -0
- package/build/logger.js +43 -0
- package/build/monitoring.d.ts +2 -3
- package/build/monitoring.js +4 -4
- package/build/router.d.ts +4 -5
- package/build/router.js +31 -28
- package/build/routes/chrome/http/content.post.body.json +8 -8
- package/build/routes/chrome/http/pdf.post.body.json +9 -9
- package/build/routes/chrome/http/scrape.post.body.json +8 -8
- package/build/routes/chrome/http/screenshot.post.body.json +8 -8
- package/build/routes/chromium/http/content.post.body.json +8 -8
- package/build/routes/chromium/http/pdf.post.body.json +9 -9
- 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/firefox/ws/playwright.d.ts +2 -2
- package/build/routes/firefox/ws/playwright.js +1 -1
- package/build/routes/management/http/static.get.d.ts +2 -2
- package/build/routes/management/http/static.get.js +8 -10
- package/build/routes/management/tests/management.spec.js +9 -0
- package/build/routes/webkit/ws/playwright.d.ts +2 -2
- package/build/routes/webkit/ws/playwright.js +1 -1
- package/build/sdk-utils.js +23 -10
- package/build/server.d.ts +4 -5
- package/build/server.js +38 -33
- package/build/shared/browser.ws.d.ts +2 -2
- package/build/shared/browser.ws.js +1 -1
- package/build/shared/chromium.playwright.ws.d.ts +2 -2
- package/build/shared/chromium.playwright.ws.js +1 -1
- package/build/shared/chromium.ws.d.ts +2 -2
- package/build/shared/chromium.ws.js +1 -1
- package/build/shared/content.http.d.ts +2 -2
- package/build/shared/content.http.js +4 -1
- package/build/shared/download.http.d.ts +2 -2
- package/build/shared/download.http.js +11 -12
- package/build/shared/function.http.d.ts +2 -2
- package/build/shared/function.http.js +4 -5
- package/build/shared/json-protocol.http.d.ts +3 -3
- package/build/shared/json-protocol.http.js +2 -2
- package/build/shared/json-version.http.d.ts +3 -3
- package/build/shared/json-version.http.js +2 -2
- package/build/shared/page.ws.d.ts +2 -2
- package/build/shared/page.ws.js +1 -1
- package/build/shared/pdf.http.d.ts +2 -2
- package/build/shared/pdf.http.js +6 -4
- package/build/shared/performance.http.d.ts +2 -2
- package/build/shared/performance.http.js +2 -1
- package/build/shared/scrape.http.d.ts +2 -2
- package/build/shared/scrape.http.js +4 -1
- package/build/shared/screenshot.http.d.ts +2 -2
- package/build/shared/screenshot.http.js +4 -1
- package/build/shared/utils/function/handler.d.ts +2 -3
- package/build/shared/utils/function/handler.js +8 -8
- package/build/shared/utils/performance/child.js +4 -4
- package/build/shared/utils/performance/main.d.ts +1 -1
- package/build/shared/utils/performance/main.js +5 -7
- package/build/shared/utils/performance/types.d.ts +2 -1
- package/build/types.d.ts +6 -15
- package/build/types.js +1 -10
- package/build/utils.d.ts +1 -1
- package/build/utils.js +6 -2
- package/package.json +18 -15
- package/scripts/install-debugger.js +55 -15
- package/src/browserless.ts +29 -21
- package/src/browsers/chrome.cdp.ts +2 -5
- package/src/browsers/chrome.playwright.ts +2 -5
- package/src/browsers/chromium.cdp.ts +84 -35
- package/src/browsers/chromium.playwright.ts +26 -13
- package/src/browsers/firefox.playwright.ts +28 -13
- package/src/browsers/index.ts +24 -16
- package/src/browsers/webkit.playwright.ts +28 -13
- package/src/config.ts +4 -0
- package/src/exports.ts +1 -0
- package/src/file-system.ts +2 -7
- package/src/index.ts +7 -7
- package/src/limiter.ts +13 -11
- package/src/logger.ts +52 -0
- package/src/monitoring.ts +6 -8
- package/src/router.ts +29 -27
- package/src/routes/firefox/ws/playwright.ts +2 -0
- package/src/routes/management/http/static.get.ts +13 -10
- package/src/routes/management/tests/management.spec.ts +15 -0
- package/src/routes/webkit/ws/playwright.ts +2 -0
- package/src/sdk-utils.ts +20 -2
- package/src/server.ts +47 -32
- package/src/shared/browser.ws.ts +2 -0
- package/src/shared/chromium.playwright.ws.ts +2 -0
- package/src/shared/chromium.ws.ts +2 -0
- package/src/shared/content.http.ts +6 -0
- package/src/shared/download.http.ts +14 -11
- package/src/shared/function.http.ts +5 -4
- package/src/shared/json-protocol.http.ts +8 -3
- package/src/shared/json-version.http.ts +8 -4
- package/src/shared/page.ws.ts +2 -0
- package/src/shared/pdf.http.ts +7 -3
- package/src/shared/performance.http.ts +3 -0
- package/src/shared/scrape.http.ts +6 -0
- package/src/shared/screenshot.http.ts +5 -0
- package/src/shared/utils/function/handler.ts +9 -13
- package/src/shared/utils/performance/child.ts +4 -4
- package/src/shared/utils/performance/main.ts +5 -6
- package/src/shared/utils/performance/types.ts +2 -1
- package/src/types.ts +5 -9
- package/src/utils.ts +7 -2
- package/static/docs/swagger.json +11 -11
- package/static/docs/swagger.min.json +10 -10
- package/static/function/client.js +1656 -2916
- package/static/function/index.html +1656 -2916
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
# [Latest](https://github.com/browserless/chrome/compare/v2.
|
|
1
|
+
# [Latest](https://github.com/browserless/chrome/compare/v2.9.0...main)
|
|
2
|
+
- Dependency updates.
|
|
3
|
+
|
|
4
|
+
# [v2.9.0](https://github.com/browserless/chrome/compare/v2.8.0...v2.9.0)
|
|
5
|
+
- Dependency updates.
|
|
6
|
+
- Debugger is now included and mounted under the `/debugger` path.
|
|
7
|
+
- Browserless now uses the `Logger` utility internally. Better logs for certain classes as well.
|
|
8
|
+
- Fix number of connected clients when using the Page websocket route.
|
|
9
|
+
- Allows "HEAD" requests for most "GET"-based APIs.
|
|
10
|
+
-
|
|
11
|
+
|
|
12
|
+
# [v2.8.0](https://github.com/browserless/chrome/compare/v2.7.1...v2.8.0)
|
|
13
|
+
**April 12, 2024**
|
|
14
|
+
**Potentially Breaking**
|
|
15
|
+
- New `Logger` class and SDK primitives in support of that.
|
|
16
|
+
- Routes now get an instance of `Logger`, before the `browser` argument or as the last argument for HTTP routes.
|
|
17
|
+
|
|
18
|
+
**Updates**
|
|
19
|
+
- Numerous SDK fixes and updates in the CLI.
|
|
2
20
|
- Dependency updates.
|
|
3
21
|
|
|
4
22
|
# [v2.7.1](https://github.com/browserless/chrome/compare/v2.7.0...v2.7.1)
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- markdownlint-disable first-line-h1 no-emphasis-as-heading -->
|
|
1
|
+
<!-- markdownlint-disable commands-show-output first-line-h1 no-emphasis-as-heading -->
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
@@ -28,6 +28,8 @@ If you've been struggling to deploy headless browsers without running into issue
|
|
|
28
28
|
- [Puppeteer](#puppeteer)
|
|
29
29
|
- [Playwright](#playwright)
|
|
30
30
|
- [Extending (NodeJS SDK)](#extending-nodejs-sdk)
|
|
31
|
+
- [Debugger](#debugger)
|
|
32
|
+
- [Install debugger](#install-debugger)
|
|
31
33
|
- [Usage with other libraries](#usage-with-other-libraries)
|
|
32
34
|
- [Motivations](#motivations)
|
|
33
35
|
- [Licensing](#licensing)
|
|
@@ -70,7 +72,7 @@ You still execute the script itself which gives you total control over what libr
|
|
|
70
72
|
|
|
71
73
|
### Docker
|
|
72
74
|
|
|
73
|
-
> [!TIP]
|
|
75
|
+
> [!TIP]
|
|
74
76
|
> See more options on our [full documentation site](https://docs.browserless.io/Docker/docker-quickstart).
|
|
75
77
|
|
|
76
78
|
1. `docker run -p 3000:3000 ghcr.io/browserless/chromium`
|
|
@@ -107,7 +109,7 @@ const browser = await puppeteer.connect({
|
|
|
107
109
|
|
|
108
110
|
### Playwright
|
|
109
111
|
|
|
110
|
-
We support running with playwright via their their browser's
|
|
112
|
+
We support running with playwright via their their browser's remote connection protocols interface out of the box. Just make sure that your Docker image, playwright browser type _and_ endpoint match:
|
|
111
113
|
|
|
112
114
|
**Before**
|
|
113
115
|
|
|
@@ -137,6 +139,42 @@ After that, the rest of your code remains the same with no other changes require
|
|
|
137
139
|
|
|
138
140
|
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.
|
|
139
141
|
|
|
142
|
+
## Debugger
|
|
143
|
+
|
|
144
|
+
You can install a first-party interactive debugger for Browserless, that makes writing scripts faster and interactive. You can take advantage of things like `debugger;` calls and the page's console output to see what's happening on the page while your script is running. All of the Chrome devtools are there at your disposal.
|
|
145
|
+
|
|
146
|
+

|
|
147
|
+
|
|
148
|
+
A small list of features includes:
|
|
149
|
+
|
|
150
|
+
- Running `debugger;` and `console.log` calls
|
|
151
|
+
- Errors in the script are caught and show up in the console tab
|
|
152
|
+
- DOM inspection, watch network requests, and even see how the page is rendering
|
|
153
|
+
- Exporting you debugging script as a Node project
|
|
154
|
+
- Everything included in Chrome DevTools
|
|
155
|
+
|
|
156
|
+
### Install debugger
|
|
157
|
+
|
|
158
|
+
Installing the debugger is as simple as running the `install:debugger` script _after_ the project has been built. This way:
|
|
159
|
+
|
|
160
|
+
```sh
|
|
161
|
+
$ npm run build
|
|
162
|
+
$ npm run install:debugger #or npm install:dev
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
You will then see the debugger url during the startup process.
|
|
166
|
+
|
|
167
|
+
```log
|
|
168
|
+
---------------------------------------------------------
|
|
169
|
+
| browserless.io
|
|
170
|
+
| To read documentation and more, load in your browser:
|
|
171
|
+
|
|
|
172
|
+
| OpenAPI: http://localhost:3000/docs
|
|
173
|
+
| Full Documentation: https://docs.browserless.io/
|
|
174
|
+
| Debbuger: http://localhost:3000/debugger/?token=6R0W53R135510
|
|
175
|
+
---------------------------------------------------------
|
|
176
|
+
```
|
|
177
|
+
|
|
140
178
|
## Usage with other libraries
|
|
141
179
|
|
|
142
180
|
Most libraries allow you to specify a remote instance of Chrome to interact with. They are either looking for a websocket endpoint, a host and port, or some address. Browserless supports these by default, however if you're having issues please make an issue in this project and we'll try and work with the library authors to get them integrated with browserless. Please note that in V2 we no longer support selenium or webdriver integrations.
|
|
Binary file
|
package/bin/browserless.js
CHANGED
|
@@ -27,7 +27,7 @@ if (typeof process.env.DEBUG === 'undefined') {
|
|
|
27
27
|
const log = debug('browserless.io:sdk:log');
|
|
28
28
|
|
|
29
29
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
30
|
-
const cmd = process.argv[2];
|
|
30
|
+
const cmd = process.argv[2] ?? 'help';
|
|
31
31
|
const subCMD = process.argv[3];
|
|
32
32
|
const allowedCMDs = [
|
|
33
33
|
'build',
|
|
@@ -143,7 +143,7 @@ const isConstructor = (reference) => typeof reference === 'function';
|
|
|
143
143
|
const start = async (dev = false) => {
|
|
144
144
|
const { httpRoutes, webSocketRoutes, files } = dev
|
|
145
145
|
? await build()
|
|
146
|
-
: await getSourceFiles();
|
|
146
|
+
: await getSourceFiles(projectDir);
|
|
147
147
|
|
|
148
148
|
log(`Importing all class overrides if present`);
|
|
149
149
|
|
|
@@ -152,6 +152,7 @@ const start = async (dev = false) => {
|
|
|
152
152
|
Config,
|
|
153
153
|
FileSystem,
|
|
154
154
|
Limiter,
|
|
155
|
+
Logger,
|
|
155
156
|
Metrics,
|
|
156
157
|
Monitoring,
|
|
157
158
|
Router,
|
|
@@ -164,6 +165,7 @@ const start = async (dev = false) => {
|
|
|
164
165
|
importDefault(files, 'config'),
|
|
165
166
|
importDefault(files, 'file-system'),
|
|
166
167
|
importDefault(files, 'limiter'),
|
|
168
|
+
importDefault(files, 'logger'),
|
|
167
169
|
importDefault(files, 'metrics'),
|
|
168
170
|
importDefault(files, 'monitoring'),
|
|
169
171
|
importDefault(files, 'router'),
|
|
@@ -197,6 +199,7 @@ const start = async (dev = false) => {
|
|
|
197
199
|
: Router;
|
|
198
200
|
|
|
199
201
|
const browserless = new Browserless({
|
|
202
|
+
Logger,
|
|
200
203
|
browserManager,
|
|
201
204
|
config,
|
|
202
205
|
fileSystem,
|
|
@@ -369,7 +372,7 @@ const create = async () => {
|
|
|
369
372
|
}
|
|
370
373
|
}
|
|
371
374
|
|
|
372
|
-
log(`Installing npm modules...`);
|
|
375
|
+
log(`Installing browsers and npm modules, this might take a few minutes...`);
|
|
373
376
|
await installDependencies(installPath);
|
|
374
377
|
|
|
375
378
|
log(
|
|
@@ -377,7 +380,8 @@ const create = async () => {
|
|
|
377
380
|
);
|
|
378
381
|
};
|
|
379
382
|
|
|
380
|
-
const help = () => {
|
|
383
|
+
const help = async () => {
|
|
384
|
+
console.log(`Version: ${(await browserlessPackageJSON).version}`);
|
|
381
385
|
if (subCMD) {
|
|
382
386
|
if (!allowedCMDs.includes(subCMD)) {
|
|
383
387
|
throw new Error(`Unknown command of "${subCMD}" passed.`);
|
package/bin/scaffold/README.md
CHANGED
|
@@ -128,6 +128,7 @@ Internally, we use this same class-based system, so feel free to see how those w
|
|
|
128
128
|
import {
|
|
129
129
|
APITags,
|
|
130
130
|
HTTPRoute,
|
|
131
|
+
Logger,
|
|
131
132
|
Methods,
|
|
132
133
|
contentTypes,
|
|
133
134
|
writeResponse,
|
|
@@ -174,7 +175,7 @@ export default class HelloWorldRoute extends HTTPRoute {
|
|
|
174
175
|
// Handler is a function, getting the request and response objects, and is where you'll write the
|
|
175
176
|
// core logic behind this route. Use utilities like writeResponse or writeJSONResponse to help
|
|
176
177
|
// return the appropriate response.
|
|
177
|
-
handler = async (_req, res): Promise<void> => {
|
|
178
|
+
handler = async (_req, res, _logger: Logger): Promise<void> => {
|
|
178
179
|
const response: ResponseSchema = 'Hello World!';
|
|
179
180
|
return writeResponse(res, 200, ResponseSchema, contentTypes.text);
|
|
180
181
|
};
|
|
@@ -189,6 +190,7 @@ import {
|
|
|
189
190
|
BrowserWebsocketRoute,
|
|
190
191
|
ChromiumCDP,
|
|
191
192
|
CDPLaunchOptions,
|
|
193
|
+
Logger,
|
|
192
194
|
Request,
|
|
193
195
|
SystemQueryParameters,
|
|
194
196
|
WebsocketRoutes,
|
|
@@ -226,7 +228,7 @@ export default class ChromiumWebSocketRoute extends BrowserWebsocketRoute {
|
|
|
226
228
|
// Routes with a browser type get a browser argument of the Browser instance, otherwise
|
|
227
229
|
// request, socket, and head are the other 3 arguments. Here we pass them through
|
|
228
230
|
// and proxy the request into Chromium to handle.
|
|
229
|
-
handler = async (req, socket, head, chromium): Promise<void> =>
|
|
231
|
+
handler = async (req, socket, head, logger, chromium): Promise<void> =>
|
|
230
232
|
chromium.proxyWebSocket(req, socket, head);
|
|
231
233
|
}
|
|
232
234
|
```
|
|
@@ -293,7 +295,7 @@ Then, later, in your route you can define some functionality and load the config
|
|
|
293
295
|
|
|
294
296
|
```ts
|
|
295
297
|
// src/pdf.http.ts
|
|
296
|
-
import { BrowserHTTPRoute } from '@browserless.io/browserless';
|
|
298
|
+
import { BrowserHTTPRoute, Logger } from '@browserless.io/browserless';
|
|
297
299
|
import MyConfig from './config';
|
|
298
300
|
|
|
299
301
|
// Export the BodySchema for documentation site to parse, plus
|
|
@@ -342,7 +344,7 @@ export default class PDFToS3Route extends BrowserHTTPRoute {
|
|
|
342
344
|
tags = [APITags.browserAPI];
|
|
343
345
|
|
|
344
346
|
// Handler's are where we embed the logic that facilitates this route.
|
|
345
|
-
handler = async (req, res, browser): Promise<void> => {
|
|
347
|
+
handler = async (req, res, logger, browser): Promise<void> => {
|
|
346
348
|
// Modules like Config are injected via this internal methods.
|
|
347
349
|
// Use them to load core modules within the platform.
|
|
348
350
|
const config = this.config() as MyConfig;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
APITags,
|
|
3
3
|
HTTPRoute,
|
|
4
|
+
Logger,
|
|
4
5
|
Methods,
|
|
5
6
|
Request,
|
|
6
7
|
Response,
|
|
@@ -21,7 +22,12 @@ export default class HelloWorldHTTPRoute extends HTTPRoute {
|
|
|
21
22
|
method = Methods.get;
|
|
22
23
|
path = '/hello';
|
|
23
24
|
tags = [APITags.management];
|
|
24
|
-
handler = async (
|
|
25
|
+
handler = async (
|
|
26
|
+
req: Request,
|
|
27
|
+
res: Response,
|
|
28
|
+
logger: Logger,
|
|
29
|
+
): Promise<void> => {
|
|
30
|
+
logger.verbose(`${req.method} /hello was called!`);
|
|
25
31
|
const response: ResponseSchema = 'Hello World!';
|
|
26
32
|
return writeResponse(res, 200, response, contentTypes.text);
|
|
27
33
|
};
|
package/build/browserless.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
/// <reference types="debug" />
|
|
2
1
|
/// <reference types="node" />
|
|
3
2
|
/// <reference types="node" />
|
|
4
|
-
import { BrowserManager, Config, FileSystem, HTTPServer, Hooks, Limiter, Metrics, Monitoring, Router, Token, WebHooks } from '@browserless.io/browserless';
|
|
3
|
+
import { Logger as BlessLogger, BrowserHTTPRoute, BrowserManager, BrowserWebsocketRoute, Config, FileSystem, HTTPRoute, HTTPServer, Hooks, Limiter, Metrics, Monitoring, Router, Token, WebHooks, WebSocketRoute } from '@browserless.io/browserless';
|
|
5
4
|
import { EventEmitter } from 'events';
|
|
5
|
+
type routeInstances = HTTPRoute | BrowserHTTPRoute | WebSocketRoute | BrowserWebsocketRoute;
|
|
6
6
|
export declare class Browserless extends EventEmitter {
|
|
7
|
-
protected
|
|
7
|
+
protected logger: BlessLogger;
|
|
8
8
|
protected browserManager: BrowserManager;
|
|
9
9
|
protected config: Config;
|
|
10
10
|
protected fileSystem: FileSystem;
|
|
11
11
|
protected hooks: Hooks;
|
|
12
12
|
protected limiter: Limiter;
|
|
13
|
+
protected Logger: typeof BlessLogger;
|
|
13
14
|
protected metrics: Metrics;
|
|
14
15
|
protected monitoring: Monitoring;
|
|
15
16
|
protected router: Router;
|
|
@@ -22,7 +23,8 @@ export declare class Browserless extends EventEmitter {
|
|
|
22
23
|
server?: HTTPServer;
|
|
23
24
|
metricsSaveInterval: number;
|
|
24
25
|
metricsSaveIntervalID?: NodeJS.Timer;
|
|
25
|
-
constructor({ browserManager, config, fileSystem, hooks, limiter, metrics, monitoring, router, token, webhooks, }?: {
|
|
26
|
+
constructor({ browserManager, config, fileSystem, hooks, limiter, Logger: LoggerOverride, metrics, monitoring, router, token, webhooks, }?: {
|
|
27
|
+
Logger?: Browserless['Logger'];
|
|
26
28
|
browserManager?: Browserless['browserManager'];
|
|
27
29
|
config?: Browserless['config'];
|
|
28
30
|
fileSystem?: Browserless['fileSystem'];
|
|
@@ -36,7 +38,7 @@ export declare class Browserless extends EventEmitter {
|
|
|
36
38
|
});
|
|
37
39
|
protected saveMetrics: () => Promise<void>;
|
|
38
40
|
setMetricsSaveInterval: (interval: number) => void;
|
|
39
|
-
|
|
41
|
+
protected routeIsDisabled(route: routeInstances): boolean;
|
|
40
42
|
setStaticSDKDir(dir: string): void;
|
|
41
43
|
disableRoutes(...routeNames: string[]): void;
|
|
42
44
|
addHTTPRoute(httpRouteFilePath: string): void;
|
|
@@ -45,3 +47,4 @@ export declare class Browserless extends EventEmitter {
|
|
|
45
47
|
stop(): Promise<[void | undefined, void, void, void, void, void, void, void, void, void, void]>;
|
|
46
48
|
start(): Promise<void>;
|
|
47
49
|
}
|
|
50
|
+
export {};
|
package/build/browserless.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
|
-
import { BrowserManager, ChromeCDP, ChromiumCDP, ChromiumPlaywright, Config, FileSystem, FirefoxPlaywright, HTTPServer, Hooks, Limiter, Metrics, Monitoring, Router, Token, WebHooks, WebkitPlaywright, availableBrowsers,
|
|
2
|
+
import { Logger as BlessLogger, BrowserManager, ChromeCDP, ChromiumCDP, ChromiumPlaywright, Config, FileSystem, FirefoxPlaywright, HTTPServer, Hooks, Limiter, Metrics, Monitoring, Router, Token, WebHooks, WebkitPlaywright, availableBrowsers, getRouteFiles, makeExternalURL, printLogo, safeParse, } from '@browserless.io/browserless';
|
|
3
3
|
import { EventEmitter } from 'events';
|
|
4
4
|
import { readFile } from 'fs/promises';
|
|
5
5
|
import { userInfo } from 'os';
|
|
6
6
|
const routeSchemas = ['body', 'query'];
|
|
7
7
|
export class Browserless extends EventEmitter {
|
|
8
|
-
|
|
8
|
+
logger;
|
|
9
9
|
browserManager;
|
|
10
10
|
config;
|
|
11
11
|
fileSystem;
|
|
12
12
|
hooks;
|
|
13
13
|
limiter;
|
|
14
|
+
Logger;
|
|
14
15
|
metrics;
|
|
15
16
|
monitoring;
|
|
16
17
|
router;
|
|
@@ -23,8 +24,10 @@ export class Browserless extends EventEmitter {
|
|
|
23
24
|
server;
|
|
24
25
|
metricsSaveInterval = 5 * 60 * 1000;
|
|
25
26
|
metricsSaveIntervalID;
|
|
26
|
-
constructor({ browserManager, config, fileSystem, hooks, limiter, metrics, monitoring, router, token, webhooks, } = {}) {
|
|
27
|
+
constructor({ browserManager, config, fileSystem, hooks, limiter, Logger: LoggerOverride, metrics, monitoring, router, token, webhooks, } = {}) {
|
|
27
28
|
super();
|
|
29
|
+
this.Logger = LoggerOverride ?? BlessLogger;
|
|
30
|
+
this.logger = new this.Logger('index');
|
|
28
31
|
this.config = config || new Config();
|
|
29
32
|
this.metrics = metrics || new Metrics();
|
|
30
33
|
this.token = token || new Token(this.config);
|
|
@@ -38,7 +41,8 @@ export class Browserless extends EventEmitter {
|
|
|
38
41
|
limiter ||
|
|
39
42
|
new Limiter(this.config, this.metrics, this.monitoring, this.webhooks, this.hooks);
|
|
40
43
|
this.router =
|
|
41
|
-
router ||
|
|
44
|
+
router ||
|
|
45
|
+
new Router(this.config, this.browserManager, this.limiter, this.Logger);
|
|
42
46
|
}
|
|
43
47
|
saveMetrics = async () => {
|
|
44
48
|
const metricsPath = this.config.getMetricsJSONPath();
|
|
@@ -50,7 +54,7 @@ export class Browserless extends EventEmitter {
|
|
|
50
54
|
memory,
|
|
51
55
|
};
|
|
52
56
|
this.metrics.reset();
|
|
53
|
-
this.
|
|
57
|
+
this.logger.info(`Current period usage: ${JSON.stringify({
|
|
54
58
|
date: aggregatedStats.date,
|
|
55
59
|
error: aggregatedStats.error,
|
|
56
60
|
maxConcurrent: aggregatedStats.maxConcurrent,
|
|
@@ -64,7 +68,7 @@ export class Browserless extends EventEmitter {
|
|
|
64
68
|
units: aggregatedStats.units,
|
|
65
69
|
})}`);
|
|
66
70
|
if (metricsPath) {
|
|
67
|
-
this.
|
|
71
|
+
this.logger.info(`Saving metrics to "${metricsPath}"`);
|
|
68
72
|
this.fileSystem.append(metricsPath, JSON.stringify(aggregatedStats), false);
|
|
69
73
|
}
|
|
70
74
|
};
|
|
@@ -124,25 +128,26 @@ export class Browserless extends EventEmitter {
|
|
|
124
128
|
WebkitPlaywright,
|
|
125
129
|
];
|
|
126
130
|
const [[internalHttpRouteFiles, internalWsRouteFiles], installedBrowsers] = await Promise.all([getRouteFiles(this.config), availableBrowsers]);
|
|
131
|
+
const hasDebugger = await this.config.hasDebugger();
|
|
132
|
+
const debuggerURL = hasDebugger &&
|
|
133
|
+
makeExternalURL(this.config.getExternalAddress(), `/debugger/?token=${this.config.getToken()}`);
|
|
127
134
|
const docsLink = makeExternalURL(this.config.getExternalAddress(), '/docs');
|
|
128
|
-
this.
|
|
129
|
-
this.
|
|
130
|
-
this.
|
|
135
|
+
this.logger.info(printLogo(docsLink, debuggerURL));
|
|
136
|
+
this.logger.info(`Running as user "${userInfo().username}"`);
|
|
137
|
+
this.logger.info('Starting import of HTTP Routes');
|
|
131
138
|
for (const httpRoute of [
|
|
132
139
|
...this.httpRouteFiles,
|
|
133
140
|
...internalHttpRouteFiles,
|
|
134
141
|
]) {
|
|
135
142
|
if (httpRoute.endsWith('js')) {
|
|
136
|
-
const { name } = path.parse(httpRoute);
|
|
137
143
|
const [bodySchema, querySchema] = await Promise.all(routeSchemas.map(async (schemaType) => {
|
|
138
144
|
const schemaPath = path.parse(httpRoute);
|
|
139
145
|
schemaPath.base = `${schemaPath.name}.${schemaType}.json`;
|
|
140
146
|
return await readFile(path.format(schemaPath), 'utf-8').catch(() => '');
|
|
141
147
|
}));
|
|
142
148
|
const routeImport = `${this.config.getIsWin() ? 'file:///' : ''}${httpRoute}`;
|
|
143
|
-
const logger = createLogger(`http:${name}`);
|
|
144
149
|
const { default: Route, } = await import(routeImport + `?cb=${Date.now()}`);
|
|
145
|
-
const route = new Route(this.browserManager, this.config, this.fileSystem,
|
|
150
|
+
const route = new Route(this.browserManager, this.config, this.fileSystem, this.metrics, this.monitoring, this.staticSDKDir);
|
|
146
151
|
if (!this.routeIsDisabled(route)) {
|
|
147
152
|
route.bodySchema = safeParse(bodySchema);
|
|
148
153
|
route.querySchema = safeParse(querySchema);
|
|
@@ -150,35 +155,31 @@ export class Browserless extends EventEmitter {
|
|
|
150
155
|
route.metrics = () => this.metrics;
|
|
151
156
|
route.monitoring = () => this.monitoring;
|
|
152
157
|
route.fileSystem = () => this.fileSystem;
|
|
153
|
-
route.debug = () => logger;
|
|
154
158
|
route.staticSDKDir = () => this.staticSDKDir;
|
|
155
159
|
httpRoutes.push(route);
|
|
156
160
|
}
|
|
157
161
|
}
|
|
158
162
|
}
|
|
159
|
-
this.
|
|
163
|
+
this.logger.info('Starting import of WebSocket Routes');
|
|
160
164
|
for (const wsRoute of [
|
|
161
165
|
...this.webSocketRouteFiles,
|
|
162
166
|
...internalWsRouteFiles,
|
|
163
167
|
]) {
|
|
164
168
|
if (wsRoute.endsWith('js')) {
|
|
165
|
-
const { name } = path.parse(wsRoute);
|
|
166
169
|
const [, querySchema] = await Promise.all(routeSchemas.map(async (schemaType) => {
|
|
167
170
|
const schemaPath = path.parse(wsRoute);
|
|
168
171
|
schemaPath.base = `${schemaPath.name}.${schemaType}.json`;
|
|
169
172
|
return await readFile(path.format(schemaPath), 'utf-8').catch(() => '');
|
|
170
173
|
}));
|
|
171
174
|
const wsImport = `${this.config.getIsWin() ? 'file:///' : ''}${wsRoute}`;
|
|
172
|
-
const logger = createLogger(`ws:${name}`);
|
|
173
175
|
const { default: Route, } = await import(wsImport + `?cb=${Date.now()}`);
|
|
174
|
-
const route = new Route(this.browserManager, this.config, this.fileSystem,
|
|
176
|
+
const route = new Route(this.browserManager, this.config, this.fileSystem, this.metrics, this.monitoring, this.staticSDKDir);
|
|
175
177
|
if (!this.routeIsDisabled(route)) {
|
|
176
178
|
route.querySchema = safeParse(querySchema);
|
|
177
179
|
route.config = () => this.config;
|
|
178
180
|
route.metrics = () => this.metrics;
|
|
179
181
|
route.monitoring = () => this.monitoring;
|
|
180
182
|
route.fileSystem = () => this.fileSystem;
|
|
181
|
-
route.debug = () => logger;
|
|
182
183
|
route.staticSDKDir = () => this.staticSDKDir;
|
|
183
184
|
wsRoutes.push(route);
|
|
184
185
|
}
|
|
@@ -198,14 +199,14 @@ export class Browserless extends EventEmitter {
|
|
|
198
199
|
.filter((e, i, a) => a.findIndex((r) => r.name === e.name) !== i)
|
|
199
200
|
.map((r) => r.name);
|
|
200
201
|
if (duplicateNamedRoutes.length) {
|
|
201
|
-
this.
|
|
202
|
+
this.logger.warn(`Found duplicate routing names. Route names must be unique:`, duplicateNamedRoutes);
|
|
202
203
|
}
|
|
203
204
|
httpRoutes.forEach((r) => this.router.registerHTTPRoute(r));
|
|
204
205
|
wsRoutes.forEach((r) => this.router.registerWebSocketRoute(r));
|
|
205
|
-
this.
|
|
206
|
-
this.server = new HTTPServer(this.config, this.metrics, this.token, this.router, this.hooks);
|
|
206
|
+
this.logger.info(`Imported and validated all route files, starting up server.`);
|
|
207
|
+
this.server = new HTTPServer(this.config, this.metrics, this.token, this.router, this.hooks, this.Logger);
|
|
207
208
|
await this.server.start();
|
|
208
|
-
this.
|
|
209
|
+
this.logger.info(`Starting metrics collection.`);
|
|
209
210
|
this.metricsSaveIntervalID = setInterval(() => this.saveMetrics(), this.metricsSaveInterval);
|
|
210
211
|
}
|
|
211
212
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { Logger } from '@browserless.io/browserless';
|
|
2
2
|
import { ChromiumCDP } from './chromium.cdp.js';
|
|
3
3
|
export declare class ChromeCDP extends ChromiumCDP {
|
|
4
4
|
protected executablePath: string;
|
|
5
|
-
protected
|
|
5
|
+
protected logger: Logger;
|
|
6
6
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Logger, chromeExecutablePath } from '@browserless.io/browserless';
|
|
2
2
|
import { ChromiumCDP } from './chromium.cdp.js';
|
|
3
3
|
export class ChromeCDP extends ChromiumCDP {
|
|
4
4
|
executablePath = chromeExecutablePath();
|
|
5
|
-
|
|
5
|
+
logger = new Logger('browsers:chrome:cdp');
|
|
6
6
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { Logger } from '@browserless.io/browserless';
|
|
2
2
|
import { ChromiumPlaywright } from './chromium.playwright.js';
|
|
3
3
|
export declare class ChromePlaywright extends ChromiumPlaywright {
|
|
4
4
|
protected executablePath: string;
|
|
5
|
-
protected
|
|
5
|
+
protected logger: Logger;
|
|
6
6
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Logger, chromeExecutablePath } from '@browserless.io/browserless';
|
|
2
2
|
import { ChromiumPlaywright } from './chromium.playwright.js';
|
|
3
3
|
export class ChromePlaywright extends ChromiumPlaywright {
|
|
4
4
|
executablePath = chromeExecutablePath();
|
|
5
|
-
|
|
5
|
+
logger = new Logger('browsers:chrome:playwright');
|
|
6
6
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
/// <reference types="debug" />
|
|
2
1
|
/// <reference types="node" />
|
|
3
2
|
/// <reference types="node" />
|
|
4
3
|
/// <reference types="node" />
|
|
5
4
|
/// <reference types="node" />
|
|
6
5
|
/// <reference types="node" />
|
|
7
|
-
import { CDPLaunchOptions, Config, Request } from '@browserless.io/browserless';
|
|
6
|
+
import { CDPLaunchOptions, Config, Logger, Request } from '@browserless.io/browserless';
|
|
8
7
|
import { Browser, Page, Target } from 'puppeteer-core';
|
|
9
8
|
import { Duplex } from 'stream';
|
|
10
9
|
import { EventEmitter } from 'events';
|
|
@@ -17,12 +16,13 @@ export declare class ChromiumCDP extends EventEmitter {
|
|
|
17
16
|
protected browser: Browser | null;
|
|
18
17
|
protected browserWSEndpoint: string | null;
|
|
19
18
|
protected port?: number;
|
|
20
|
-
protected
|
|
19
|
+
protected logger: Logger;
|
|
21
20
|
protected proxy: httpProxy<import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>>;
|
|
22
21
|
protected executablePath: string;
|
|
23
|
-
constructor({ blockAds, config, userDataDir, }: {
|
|
22
|
+
constructor({ blockAds, config, userDataDir, logger, }: {
|
|
24
23
|
blockAds: boolean;
|
|
25
24
|
config: Config;
|
|
25
|
+
logger: Logger;
|
|
26
26
|
userDataDir: ChromiumCDP['userDataDir'];
|
|
27
27
|
});
|
|
28
28
|
protected cleanListeners(): void;
|