@browserless/cli 13.16.4 → 14.0.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/README.md +30 -0
- package/package.json +12 -5
- package/src/commands/exec.js +36 -0
- package/src/help.js +1 -0
- package/src/index.js +5 -3
package/README.md
CHANGED
|
@@ -51,6 +51,36 @@ The `@browserless/cli` package allows you to:
|
|
|
51
51
|
| `ping <url>` | Get response info: status code, redirects, headers |
|
|
52
52
|
| `status <url>` | Get the HTTP status code |
|
|
53
53
|
| `goto <url>` | Navigate to a URL and return page/response info |
|
|
54
|
+
| `exec <file>` | Run a script file against a new page and print what it returns |
|
|
55
|
+
|
|
56
|
+
### Exec examples
|
|
57
|
+
|
|
58
|
+
`exec` takes a file instead of a URL. The file exports a function (CommonJS
|
|
59
|
+
`module.exports` or ES module `export default`). The CLI opens a page and calls
|
|
60
|
+
the function with `{ page, browserless, opts }`:
|
|
61
|
+
|
|
62
|
+
- `page`: a new Puppeteer page in a fresh browser context.
|
|
63
|
+
- `browserless`: the browserless context, for `browserless.goto(page, { url })` and the rest of the API.
|
|
64
|
+
- `opts`: the command-line flags, plus the CLI default `codeScheme`. `--headless` and `--verbose` are consumed by the CLI and not passed. `--timeout` is passed and also sets the browser timeout.
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
// title.js
|
|
68
|
+
module.exports = async ({ page, browserless, opts }) => {
|
|
69
|
+
await browserless.goto(page, { url: opts.url })
|
|
70
|
+
return { title: await page.title() }
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
browserless exec title.js --url=https://example.com
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The file path resolves from the current directory. A returned string is printed
|
|
79
|
+
as is and any other value as indented JSON. `undefined` and binary values
|
|
80
|
+
(buffers and typed arrays, such as the result of `page.screenshot()`) print
|
|
81
|
+
nothing, so write binary output to a file from the script. The file is checked
|
|
82
|
+
before the browser starts. A thrown error is
|
|
83
|
+
printed and the process exits with code 1.
|
|
54
84
|
|
|
55
85
|
### Capture examples
|
|
56
86
|
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@browserless/cli",
|
|
3
3
|
"description": "Command-line interface for headless browser automation. Take screenshots, generate PDFs, and extract content from websites.",
|
|
4
4
|
"homepage": "https://browserless.js.org",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "14.0.0",
|
|
6
6
|
"bin": {
|
|
7
7
|
"browserless": "src/index.js"
|
|
8
8
|
},
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"web-scraping"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@browserless/capture": "
|
|
37
|
+
"@browserless/capture": "14.0.0",
|
|
38
38
|
"beauty-error": "~1.2.23",
|
|
39
|
-
"browserless": "
|
|
39
|
+
"browserless": "14.0.0",
|
|
40
40
|
"dark-mode": "~3.0.0",
|
|
41
41
|
"dset": "~3.1.4",
|
|
42
42
|
"mri": "~1.2.0",
|
|
@@ -49,6 +49,9 @@
|
|
|
49
49
|
"term-img": "~5.0.0",
|
|
50
50
|
"unique-random-array": "~3.0.0"
|
|
51
51
|
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"ava": "5"
|
|
54
|
+
},
|
|
52
55
|
"engines": {
|
|
53
56
|
"node": ">= 24"
|
|
54
57
|
},
|
|
@@ -56,8 +59,12 @@
|
|
|
56
59
|
"src"
|
|
57
60
|
],
|
|
58
61
|
"scripts": {
|
|
59
|
-
"test": "
|
|
62
|
+
"test": "ava"
|
|
60
63
|
},
|
|
61
64
|
"license": "MIT",
|
|
62
|
-
"
|
|
65
|
+
"ava": {
|
|
66
|
+
"timeout": "2m",
|
|
67
|
+
"workerThreads": false
|
|
68
|
+
},
|
|
69
|
+
"gitHead": "bf10b39022a6cc44cccd545756f162bed90dd589"
|
|
63
70
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { pathToFileURL } = require('url')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const fs = require('fs')
|
|
6
|
+
|
|
7
|
+
const resolveFile = file => {
|
|
8
|
+
if (!file) throw new TypeError('exec requires a script file: browserless exec <file>')
|
|
9
|
+
const filepath = path.resolve(file)
|
|
10
|
+
if (!fs.existsSync(filepath)) throw new TypeError(`Script file not found: ${filepath}`)
|
|
11
|
+
return filepath
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const loadScript = async filepath => {
|
|
15
|
+
const { default: script } = await import(pathToFileURL(filepath))
|
|
16
|
+
const run = typeof script === 'function' ? script : script?.default
|
|
17
|
+
if (typeof run !== 'function') throw new TypeError(`${filepath} must export a function.`)
|
|
18
|
+
return run
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const toBuffer = view => Buffer.from(view.buffer, view.byteOffset, view.byteLength)
|
|
22
|
+
|
|
23
|
+
const serialize = result => {
|
|
24
|
+
if (result === undefined) return ''
|
|
25
|
+
if (typeof result === 'string') return result
|
|
26
|
+
if (ArrayBuffer.isView(result)) return toBuffer(result)
|
|
27
|
+
return JSON.stringify(result, null, 2)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = async ({ file, browserless, opts }) => {
|
|
31
|
+
const run = await loadScript(file)
|
|
32
|
+
const page = await browserless.page()
|
|
33
|
+
return [serialize(await run({ page, browserless, opts }))]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports.resolveFile = resolveFile
|
package/src/help.js
CHANGED
|
@@ -9,6 +9,7 @@ const printCommand = command => `⬩ ${command.replace(path.extname(command), ''
|
|
|
9
9
|
module.exports = commands => `
|
|
10
10
|
Usage
|
|
11
11
|
$ browserless <command> <url> [flags]
|
|
12
|
+
$ browserless exec <file> [flags]
|
|
12
13
|
|
|
13
14
|
Commands
|
|
14
15
|
${gray(commands.map(printCommand).join(EOL + ' '))}`
|
package/src/index.js
CHANGED
|
@@ -62,9 +62,11 @@ const isPageReady = ({ title = '', bodyText = '', url = '', isWhite = false } =
|
|
|
62
62
|
const run = async () => {
|
|
63
63
|
if (cli.input.length === 0) return cli.showHelp()
|
|
64
64
|
spinner.start()
|
|
65
|
-
const [command,
|
|
66
|
-
const url = new URL(rawUrl).toString()
|
|
65
|
+
const [command, input] = cli.input
|
|
67
66
|
const fn = require(`./commands/${command}`)
|
|
67
|
+
const target = fn.resolveFile
|
|
68
|
+
? { file: fn.resolveFile(input) }
|
|
69
|
+
: { url: new URL(input).toString() }
|
|
68
70
|
const launchOpts = { headless }
|
|
69
71
|
|
|
70
72
|
if (command === 'capture') {
|
|
@@ -87,7 +89,7 @@ const run = async () => {
|
|
|
87
89
|
const browserless = await browser.createContext(
|
|
88
90
|
launchOpts.timeout != null ? { timeout: launchOpts.timeout } : undefined
|
|
89
91
|
)
|
|
90
|
-
return fn({
|
|
92
|
+
return fn({ ...target, browserless, opts: parsedOpts, isPageReady })
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
run()
|