npm package: @so_0/browser-cli
Description: Lightweight Playwright record & replay CLI with parameterized replay
Author: soleil0-0
Latest version: 0.1.2

# browser-cli

Lightweight Playwright record & replay CLI with parameter substitution and post-run extraction.

## Quick install

Clone this repo and install the small dependencies:

```bash
npm install
```

You do not need a globally installed Playwright — replay uses `npx` with a pinned Playwright
version so the runtime is reproducible.

You can also run the CLI directly via `npx` after the package is published to npm (scoped name shown):

```bash
# run the published CLI (after you publish):
npx @so_0/browser-cli replay recorded.js -p @params.json
```

To test the package locally without publishing, create a tarball and run it with `npx`:

```bash
# create a packed tarball in the current folder
npm pack

# then run npx against the generated tarball (replace the filename accordingly).
# For a scoped package the tarball name will be like `so_0-browser-cli-0.1.0.tgz`:
npx ./so_0-browser-cli-0.1.0.tgz replay recorded.js -p @params.json
```

## Commands

- Record (uses Playwright codegen):

```bash
# interactive recorder that saves to recorded.js (published CLI or local test via npm pack)
npx @so_0/browser-cli record https://example.com -o recorded.js
```

- Replay with parameter substitution:

```bash
# pass params as a JSON string
npx @so_0/browser-cli replay recorded.js -p '{"query":"github"}'

# or load params from a file
npx @so_0/browser-cli replay recorded.js -p @params.json
```

## Placeholders / Parameters

- In your recorded script, place placeholders inside string literals using `{{key}}`.
- Dot notation is supported: `{{user.name}}` will be replaced with `params.user.name`.
- Replacement is textual: the code replaces matching `{{...}}` with `String(value)` from
	the provided params. To avoid JS syntax errors, keep placeholders inside quotes in the
	recorded script (e.g. `await page.fill('#q', '{{query}}')`).

## Extraction (output values after replay)

You can instruct the tool to extract values from the page(s) after replay and either
print them or write them to a file.

- Option: `-e, --extract <json>` — JSON string or `@file` that describes extraction targets.
- Option: `--extract-out <file>` — write extraction results (JSON) to a file. If omitted,
	results are printed to stdout prefixed with `[replay] EXTRACTION_RESULT:`.

Extraction spec is an array of objects. Each object supports:

- `selector` (required): CSS selector used with `page.locator(selector)`.
- `name` (optional): key name for the result; defaults to the selector if omitted.
- `property` (optional): one of `text` (default), `html`, `href`, `attr:NAME`, or `table`.
- `page` (optional): page variable name to use (e.g. `page1`). If omitted, the tool will try
	common names (`page`, `page1`, ... ) and `context.pages()`.

Example `extract.json`:

```json
[
	{"name":"title","selector":"h1","property":"text"},
	{"name":"first_link","selector":"a.result","property":"href"},
	{"name":"results_table","selector":"table#results","property":"table"}
]
```

Run replay and extract:

```bash
npx @so_0/browser-cli replay recorded.js -p @params.json -e @extract.json

# write extraction results to file
npx @so_0/browser-cli replay recorded.js -p @params.json -e @extract.json --extract-out results.json
```

Output example (stdout):

```
[replay] EXTRACTION_RESULT:{"title":"Page Title","first_link":"https://...","results_table":[["H1","H2"],["r1c1","r1c2"]]}
```

## Notes & limitations

- The extraction block is appended to the end of the temporary replay script so it can
	access variables defined in the script (for example `page`, `page1`, `context`). Make sure
	the recorded script does not close the browser/context/pages before extraction runs.
- Placeholder replacement is simple text substitution. Keep placeholders inside string
	literals to produce valid JS after replacement. If your param contains quotes/newlines,
	consider putting it into a JSON file and referencing with `-p @params.json`.
- This tool executes a temporary generated JS file. Only run it with trusted recordings/params
	to avoid code injection risks.

If you want I can add helpers to automatically insert extraction before `browser.close()` or
to escape parameters for you — tell me which you'd prefer.