fastbrowser_cli 1.0.10 → 1.0.13

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 CHANGED
@@ -5,6 +5,8 @@ Control a live Chrome browser from the command line: navigate, click, fill forms
5
5
  A lighter alternative to Chrome DevTools MCP or Puppeteer, designed for AI agents and shell workflows. A persistent HTTP daemon keeps an MCP connection to the browser alive so each command incurs minimal latency.
6
6
 
7
7
  - rely on [chrome-devtools-mcp](https://github.com/ChromeDevTools/chrome-devtools-mcp) for robust browser control
8
+ - rely on [a11y_parse](https://github.com/jeromeetienne/skillmd_collection/tree/main/packages/a11y_parse) for accessibility tree parsing and querying.
9
+ Especially a CSS-like selector syntax optimized for the accessibility tree.
8
10
  - expose a curated, efficient toolset optimized for AI agent use cases
9
11
  - minimize the required round-trips and boilerplate to perform common tasks
10
12
  - minimize the output size, thus reducing LLM input size and parsing complexity.
@@ -32,7 +34,7 @@ npm install -g fastbrowser_cli
32
34
  Or install just the SKILL.md into an agent folder so an AI agent can use it:
33
35
 
34
36
  ```bash
35
- npx fastbrowser_cli --install <skill-folder>
37
+ npx fastbrowser_cli install <skill-folder>
36
38
  ```
37
39
 
38
40
  This copies `SKILL.md` to `<skill-folder>/skills/fastbrowser/SKILL.md`.
@@ -64,6 +66,7 @@ npx fastbrowser_cli click -s 'link[name="More information..."]'
64
66
  | `click` | Click an element by accessibility selector | `-s, --selector` |
65
67
  | `fill_form` | Fill a form field by accessibility selector | `-s, --selector`, `--value` |
66
68
  | `press_keys` | Press a comma-separated key sequence | `--keys` |
69
+ | `install [skill-folder]` | Install SKILL.md into `<skill-folder>/skills/fastbrowser` (default: `.`) | — |
67
70
  | `server start` | Start the HTTP daemon | — |
68
71
  | `server status` | Report daemon running/stopped | — |
69
72
  | `server stop` | Stop the HTTP daemon | — |
@@ -4,13 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- // node imports
8
7
  const node_fs_1 = __importDefault(require("node:fs"));
9
8
  const node_path_1 = __importDefault(require("node:path"));
10
- // npm imports
11
9
  const commander_1 = require("commander");
12
10
  const string_argv_1 = __importDefault(require("string-argv"));
13
- // local imports
14
11
  const http_client_js_1 = require("./libs/http-client.js");
15
12
  const server_manager_js_1 = require("./libs/server-manager.js");
16
13
  class SilentExitError extends Error {
@@ -18,123 +15,175 @@ class SilentExitError extends Error {
18
15
  super('silent-exit');
19
16
  }
20
17
  }
21
- function getServerFromCmd(cmd) {
22
- const globalOpts = cmd.optsWithGlobals();
23
- return http_client_js_1.HttpClient.getServerUrl(globalOpts.server);
24
- }
25
- function getAutostartFromCmd(cmd) {
26
- const globalOpts = cmd.optsWithGlobals();
27
- return globalOpts.autostart !== false;
28
- }
29
- async function runTool(cmd, routeName, body) {
30
- const server = getServerFromCmd(cmd);
31
- if (getAutostartFromCmd(cmd) === true) {
32
- await server_manager_js_1.ServerManager.ensureRunning(server);
33
- }
34
- const response = await http_client_js_1.HttpClient.postTool(server, routeName, body);
35
- http_client_js_1.HttpClient.printResponse(response);
36
- }
37
- ///////////////////////////////////////////////////////////////////////////////
38
18
  ///////////////////////////////////////////////////////////////////////////////
39
- //
40
- ///////////////////////////////////////////////////////////////////////////////
41
- ///////////////////////////////////////////////////////////////////////////////
42
- function buildQuerySelectorsBody(opts) {
43
- if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
44
- let parsed;
45
- try {
46
- parsed = JSON.parse(opts.selectorsJson);
19
+ class MainHelper {
20
+ static getServerFromCmd(cmd) {
21
+ const globalOpts = cmd.optsWithGlobals();
22
+ return http_client_js_1.HttpClient.getServerUrl(globalOpts.server);
23
+ }
24
+ static getAutostartFromCmd(cmd) {
25
+ const globalOpts = cmd.optsWithGlobals();
26
+ return globalOpts.autostart !== false;
27
+ }
28
+ static async runTool(cmd, routeName, body) {
29
+ const server = MainHelper.getServerFromCmd(cmd);
30
+ if (MainHelper.getAutostartFromCmd(cmd) === true) {
31
+ await server_manager_js_1.ServerManager.ensureRunning(server);
47
32
  }
48
- catch (err) {
49
- throw new Error(`--selectors-json is not valid JSON: ${err.message}`);
33
+ const response = await http_client_js_1.HttpClient.postTool(server, routeName, body);
34
+ http_client_js_1.HttpClient.printResponse(response);
35
+ }
36
+ static buildQuerySelectorsBody(opts) {
37
+ if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
38
+ let parsed;
39
+ try {
40
+ parsed = JSON.parse(opts.selectorsJson);
41
+ }
42
+ catch (err) {
43
+ throw new Error(`--selectors-json is not valid JSON: ${err.message}`);
44
+ }
45
+ if (Array.isArray(parsed) === false) {
46
+ throw new Error('--selectors-json must be a JSON array');
47
+ }
48
+ return { selectors: parsed };
50
49
  }
51
- if (Array.isArray(parsed) === false) {
52
- throw new Error('--selectors-json must be a JSON array');
50
+ const selectorList = opts.selector ?? [];
51
+ if (selectorList.length === 0) {
52
+ throw new Error('At least one --selector or --selectors-json is required');
53
53
  }
54
- return { selectors: parsed };
55
- }
56
- const selectorList = opts.selector ?? [];
57
- if (selectorList.length === 0) {
58
- throw new Error('At least one --selector or --selectors-json is required');
54
+ const limit = opts.limit === undefined ? 0 : Number.parseInt(opts.limit, 10);
55
+ if (Number.isNaN(limit) === true) {
56
+ throw new Error(`Invalid --limit: ${opts.limit}`);
57
+ }
58
+ const withAncestors = opts.withAncestors !== false;
59
+ const selectors = selectorList.map((selector) => ({
60
+ selector,
61
+ limit,
62
+ withAncestors,
63
+ }));
64
+ return { selectors };
59
65
  }
60
- const limit = opts.limit === undefined ? 0 : Number.parseInt(opts.limit, 10);
61
- if (Number.isNaN(limit) === true) {
62
- throw new Error(`Invalid --limit: ${opts.limit}`);
66
+ static buildQuerySelectorFirstBody(opts) {
67
+ if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
68
+ let parsed;
69
+ try {
70
+ parsed = JSON.parse(opts.selectorsJson);
71
+ }
72
+ catch (err) {
73
+ throw new Error(`--selectors-json is not valid JSON: ${err.message}`);
74
+ }
75
+ if (Array.isArray(parsed) === false) {
76
+ throw new Error('--selectors-json must be a JSON array');
77
+ }
78
+ return { selectors: parsed };
79
+ }
80
+ const selectorList = opts.selector ?? [];
81
+ if (selectorList.length === 0) {
82
+ throw new Error('At least one --selector or --selectors-json is required');
83
+ }
84
+ const withAncestors = opts.withAncestors !== false;
85
+ const selectors = selectorList.map((selector) => ({
86
+ selector,
87
+ withAncestors,
88
+ }));
89
+ return { selectors };
63
90
  }
64
- const withAncestors = opts.withAncestors !== false;
65
- const selectors = selectorList.map((selector) => ({
66
- selector,
67
- limit,
68
- withAncestors,
69
- }));
70
- return { selectors };
71
- }
72
- function buildQuerySelectorFirstBody(opts) {
73
- if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
74
- let parsed;
91
+ static async runInstall(skillFolder) {
92
+ const sourceSkillMd = node_path_1.default.resolve(__dirname, '../../skills/fastbrowser/SKILL.md');
93
+ const targetDir = node_path_1.default.resolve(skillFolder, 'skills', 'fastbrowser');
94
+ const targetSkillMd = node_path_1.default.join(targetDir, 'SKILL.md');
75
95
  try {
76
- parsed = JSON.parse(opts.selectorsJson);
96
+ await node_fs_1.default.promises.mkdir(targetDir, { recursive: true });
97
+ await node_fs_1.default.promises.copyFile(sourceSkillMd, targetSkillMd);
98
+ console.log(`Installed fastbrowser SKILL.md at ${targetSkillMd}`);
77
99
  }
78
100
  catch (err) {
79
- throw new Error(`--selectors-json is not valid JSON: ${err.message}`);
80
- }
81
- if (Array.isArray(parsed) === false) {
82
- throw new Error('--selectors-json must be a JSON array');
101
+ const message = err instanceof Error ? err.message : String(err);
102
+ console.error(`fastbrowser-cli error: ${message}`);
103
+ process.exit(1);
83
104
  }
84
- return { selectors: parsed };
85
105
  }
86
- const selectorList = opts.selector ?? [];
87
- if (selectorList.length === 0) {
88
- throw new Error('At least one --selector or --selectors-json is required');
106
+ static async readBatchSource(file, inlineScript) {
107
+ if (inlineScript !== undefined && inlineScript !== '') {
108
+ return inlineScript;
109
+ }
110
+ if (file !== undefined && file !== '') {
111
+ return await node_fs_1.default.promises.readFile(file, 'utf-8');
112
+ }
113
+ if (process.stdin.isTTY === true) {
114
+ throw new Error('batch: no input. Provide a file path, --script, or pipe commands on stdin.');
115
+ }
116
+ return await MainHelper.readStdinToString();
89
117
  }
90
- const withAncestors = opts.withAncestors !== false;
91
- const selectors = selectorList.map((selector) => ({
92
- selector,
93
- withAncestors,
94
- }));
95
- return { selectors };
96
- }
97
- ///////////////////////////////////////////////////////////////////////////////
98
- ///////////////////////////////////////////////////////////////////////////////
99
- //
100
- ///////////////////////////////////////////////////////////////////////////////
101
- ///////////////////////////////////////////////////////////////////////////////
102
- async function runInstall(skillFolder) {
103
- const sourceSkillMd = node_path_1.default.resolve(__dirname, '../../skills/fastbrowser/SKILL.md');
104
- const targetDir = node_path_1.default.resolve(skillFolder, 'skills', 'fastbrowser');
105
- const targetSkillMd = node_path_1.default.join(targetDir, 'SKILL.md');
106
- try {
107
- await node_fs_1.default.promises.mkdir(targetDir, { recursive: true });
108
- await node_fs_1.default.promises.copyFile(sourceSkillMd, targetSkillMd);
109
- console.log(`Installed fastbrowser SKILL.md at ${targetSkillMd}`);
118
+ static async readStdinToString() {
119
+ const chunks = [];
120
+ return await new Promise((resolve, reject) => {
121
+ process.stdin.on('data', (chunk) => chunks.push(chunk));
122
+ process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
123
+ process.stdin.on('error', (err) => reject(err));
124
+ });
110
125
  }
111
- catch (err) {
112
- const message = err instanceof Error ? err.message : String(err);
113
- console.error(`fastbrowser-cli error: ${message}`);
114
- process.exit(1);
126
+ static async runBatch(program, source, stopOnError, batchCmd) {
127
+ const globalOpts = batchCmd.optsWithGlobals();
128
+ const globalFlags = [];
129
+ if (globalOpts.server !== undefined) {
130
+ globalFlags.push('--server', globalOpts.server);
131
+ }
132
+ if (globalOpts.autostart === false) {
133
+ globalFlags.push('--no-autostart');
134
+ }
135
+ const lines = source.split('\n');
136
+ let ok = 0;
137
+ let failed = 0;
138
+ for (const rawLine of lines) {
139
+ const line = rawLine.trim();
140
+ if (line === '' || line.startsWith('#') === true)
141
+ continue;
142
+ const argv = (0, string_argv_1.default)(line);
143
+ if (argv.length === 0)
144
+ continue;
145
+ console.log(`> ${line}`);
146
+ try {
147
+ await program.parseAsync([...globalFlags, ...argv], { from: 'user' });
148
+ ok += 1;
149
+ }
150
+ catch (err) {
151
+ failed += 1;
152
+ if (err instanceof SilentExitError === false && err instanceof commander_1.CommanderError === false) {
153
+ const message = err instanceof Error ? err.message : String(err);
154
+ console.error(`fastbrowser-cli error: ${message}`);
155
+ }
156
+ if (stopOnError === true) {
157
+ throw new SilentExitError();
158
+ }
159
+ }
160
+ }
161
+ if (stopOnError === false) {
162
+ console.log(`batch: ${ok} ok, ${failed} failed`);
163
+ }
164
+ if (failed > 0) {
165
+ throw new SilentExitError();
166
+ }
115
167
  }
116
168
  }
117
169
  ///////////////////////////////////////////////////////////////////////////////
118
170
  ///////////////////////////////////////////////////////////////////////////////
119
- //
171
+ //
120
172
  ///////////////////////////////////////////////////////////////////////////////
121
173
  ///////////////////////////////////////////////////////////////////////////////
122
174
  async function main() {
123
- const installIdx = process.argv.indexOf('--install');
124
- if (installIdx !== -1) {
125
- const next = process.argv[installIdx + 1];
126
- const skillFolder = (next !== undefined && next.startsWith('-') === false) ? next : '.';
127
- await runInstall(skillFolder);
128
- return;
129
- }
130
175
  const program = new commander_1.Command();
131
176
  program
132
177
  .name('fastbrowser-cli')
133
178
  .description('CLI client for fastbrowser')
134
179
  .option('--server <url>', 'fastbrowser-httpd URL (default: env FASTBROWSER_SERVER or http://localhost:8787)')
135
180
  .option('--autostart', 'Auto-start the server before a command if it is not running', true)
136
- .option('--no-autostart', 'Do not auto-start the server before a command')
137
- .option('--install [skill-folder]', 'Install SKILL.md into <skill-folder>/skills/fastbrowser (default: .)');
181
+ .option('--no-autostart', 'Do not auto-start the server before a command');
182
+ ///////////////////////////////////////////////////////////////////////////////
183
+ ///////////////////////////////////////////////////////////////////////////////
184
+ //
185
+ ///////////////////////////////////////////////////////////////////////////////
186
+ ///////////////////////////////////////////////////////////////////////////////
138
187
  const serverCmd = program
139
188
  .command('server')
140
189
  .description('Manage the fastbrowser HTTP server');
@@ -142,38 +191,43 @@ async function main() {
142
191
  .command('start')
143
192
  .description('Start the fastbrowser HTTP server as a detached daemon')
144
193
  .action(async (_opts, cmd) => {
145
- const server = getServerFromCmd(cmd);
194
+ const server = MainHelper.getServerFromCmd(cmd);
146
195
  await server_manager_js_1.ServerManager.start(server);
147
196
  });
148
197
  serverCmd
149
198
  .command('stop')
150
199
  .description('Stop the fastbrowser HTTP server')
151
200
  .action(async (_opts, cmd) => {
152
- const server = getServerFromCmd(cmd);
201
+ const server = MainHelper.getServerFromCmd(cmd);
153
202
  await server_manager_js_1.ServerManager.stop(server);
154
203
  });
155
204
  serverCmd
156
205
  .command('status')
157
206
  .description('Report whether the fastbrowser HTTP server is running')
158
207
  .action(async (_opts, cmd) => {
159
- const server = getServerFromCmd(cmd);
208
+ const server = MainHelper.getServerFromCmd(cmd);
160
209
  const state = await server_manager_js_1.ServerManager.status(server);
161
210
  console.log(`fastbrowser server at ${server}: ${state}`);
162
211
  if (state === 'stopped')
163
212
  throw new SilentExitError();
164
213
  });
214
+ ///////////////////////////////////////////////////////////////////////////////
215
+ ///////////////////////////////////////////////////////////////////////////////
216
+ //
217
+ ///////////////////////////////////////////////////////////////////////////////
218
+ ///////////////////////////////////////////////////////////////////////////////
165
219
  program
166
220
  .command('list_pages')
167
221
  .description('List all open browser pages')
168
222
  .action(async (_opts, cmd) => {
169
- await runTool(cmd, 'list_pages', {});
223
+ await MainHelper.runTool(cmd, 'list_pages', {});
170
224
  });
171
225
  program
172
226
  .command('new_page')
173
227
  .description('Open a new browser page')
174
228
  .requiredOption('--url <url>', 'URL to open')
175
229
  .action(async (opts, cmd) => {
176
- await runTool(cmd, 'new_page', { url: opts.url });
230
+ await MainHelper.runTool(cmd, 'new_page', { url: opts.url });
177
231
  });
178
232
  program
179
233
  .command('close_page')
@@ -184,21 +238,21 @@ async function main() {
184
238
  if (Number.isNaN(pageId) === true) {
185
239
  throw new Error(`Invalid --page-id: ${opts.pageId}`);
186
240
  }
187
- await runTool(cmd, 'close_page', { pageId });
241
+ await MainHelper.runTool(cmd, 'close_page', { pageId });
188
242
  });
189
243
  program
190
244
  .command('navigate_page')
191
245
  .description('Navigate the current page to a URL')
192
246
  .requiredOption('--url <url>', 'URL to navigate to')
193
247
  .action(async (opts, cmd) => {
194
- await runTool(cmd, 'navigate_page', { url: opts.url });
248
+ await MainHelper.runTool(cmd, 'navigate_page', { url: opts.url });
195
249
  });
196
250
  program
197
251
  .command('click')
198
252
  .description('Click an element by its accessibility selector')
199
253
  .requiredOption('-s, --selector <selector>', 'Accessibility selector (e.g. "#1_3" or \'button[name="Submit"]\')')
200
254
  .action(async (opts, cmd) => {
201
- await runTool(cmd, 'click', { selector: opts.selector });
255
+ await MainHelper.runTool(cmd, 'click', { selector: opts.selector });
202
256
  });
203
257
  program
204
258
  .command('fill_form')
@@ -206,7 +260,7 @@ async function main() {
206
260
  .requiredOption('-s, --selector <selector>', 'Accessibility selector (e.g. "#1_3" or \'textbox[name="Email"]\')')
207
261
  .requiredOption('-v, --value <value>', 'Value to fill')
208
262
  .action(async (opts, cmd) => {
209
- await runTool(cmd, 'fill_form', {
263
+ await MainHelper.runTool(cmd, 'fill_form', {
210
264
  elements: [{ selector: opts.selector, value: opts.value }],
211
265
  });
212
266
  });
@@ -222,8 +276,8 @@ async function main() {
222
276
  .option('--no-with-ancestors', 'Exclude ancestor nodes')
223
277
  .option('--selectors-json <json>', 'JSON array of {selector,limit,withAncestors} for per-selector control')
224
278
  .action(async (opts, cmd) => {
225
- const body = buildQuerySelectorsBody(opts);
226
- await runTool(cmd, 'query_selectors_all', body);
279
+ const body = MainHelper.buildQuerySelectorsBody(opts);
280
+ await MainHelper.runTool(cmd, 'query_selectors_all', body);
227
281
  });
228
282
  program
229
283
  .command('query_selectors')
@@ -236,21 +290,27 @@ async function main() {
236
290
  .option('--no-with-ancestors', 'Exclude ancestor nodes')
237
291
  .option('--selectors-json <json>', 'JSON array of {selector,withAncestors} for per-selector control')
238
292
  .action(async (opts, cmd) => {
239
- const body = buildQuerySelectorFirstBody(opts);
240
- await runTool(cmd, 'query_selectors', body);
293
+ const body = MainHelper.buildQuerySelectorFirstBody(opts);
294
+ await MainHelper.runTool(cmd, 'query_selectors', body);
241
295
  });
242
296
  program
243
297
  .command('take_snapshot')
244
298
  .description('Take an accessibility-tree snapshot of the current page')
245
299
  .action(async (_opts, cmd) => {
246
- await runTool(cmd, 'take_snapshot', {});
300
+ await MainHelper.runTool(cmd, 'take_snapshot', {});
247
301
  });
248
302
  program
249
303
  .command('press_keys')
250
304
  .description('Press a sequence of keys')
251
305
  .requiredOption('--keys <keys>', "Comma-separated keys. E.g. 'Hello, Tab, Enter'")
252
306
  .action(async (opts, cmd) => {
253
- await runTool(cmd, 'press_keys', { keys: opts.keys });
307
+ await MainHelper.runTool(cmd, 'press_keys', { keys: opts.keys });
308
+ });
309
+ program
310
+ .command('install [skill-folder]')
311
+ .description('Install SKILL.md into <skill-folder>/skills/fastbrowser (default: .)')
312
+ .action(async (skillFolder) => {
313
+ await MainHelper.runInstall(skillFolder ?? '.');
254
314
  });
255
315
  program
256
316
  .command('batch [file]')
@@ -258,86 +318,15 @@ async function main() {
258
318
  .option('--script <script>', 'Inline multi-line script (overrides [file] and stdin)')
259
319
  .option('--no-stop-on-error', 'Continue running subsequent lines after a failure (default: stop on first error)')
260
320
  .action(async (file, opts, cmd) => {
261
- const source = await readBatchSource(file, opts.script);
262
- await runBatch(program, source, opts.stopOnError !== false, cmd);
263
- });
264
- program.exitOverride();
265
- try {
266
- await program.parseAsync(process.argv);
267
- }
268
- catch (err) {
269
- if (err instanceof SilentExitError) {
270
- process.exit(1);
271
- }
272
- if (err instanceof commander_1.CommanderError) {
273
- process.exit(err.exitCode === undefined ? 1 : err.exitCode);
274
- }
275
- const message = err instanceof Error ? err.message : String(err);
276
- console.error(`fastbrowser-cli error: ${message}`);
277
- process.exit(1);
278
- }
279
- }
280
- async function readBatchSource(file, inlineScript) {
281
- if (inlineScript !== undefined && inlineScript !== '') {
282
- return inlineScript;
283
- }
284
- if (file !== undefined && file !== '') {
285
- return await node_fs_1.default.promises.readFile(file, 'utf-8');
286
- }
287
- if (process.stdin.isTTY === true) {
288
- throw new Error('batch: no input. Provide a file path, --script, or pipe commands on stdin.');
289
- }
290
- return await readStdinToString();
291
- }
292
- async function readStdinToString() {
293
- const chunks = [];
294
- return await new Promise((resolve, reject) => {
295
- process.stdin.on('data', (chunk) => chunks.push(chunk));
296
- process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
297
- process.stdin.on('error', (err) => reject(err));
321
+ const source = await MainHelper.readBatchSource(file, opts.script);
322
+ await MainHelper.runBatch(program, source, opts.stopOnError !== false, cmd);
298
323
  });
299
- }
300
- async function runBatch(program, source, stopOnError, batchCmd) {
301
- const globalOpts = batchCmd.optsWithGlobals();
302
- const globalFlags = [];
303
- if (globalOpts.server !== undefined) {
304
- globalFlags.push('--server', globalOpts.server);
305
- }
306
- if (globalOpts.autostart === false) {
307
- globalFlags.push('--no-autostart');
308
- }
309
- const lines = source.split('\n');
310
- let ok = 0;
311
- let failed = 0;
312
- for (const rawLine of lines) {
313
- const line = rawLine.trim();
314
- if (line === '' || line.startsWith('#') === true)
315
- continue;
316
- const argv = (0, string_argv_1.default)(line);
317
- if (argv.length === 0)
318
- continue;
319
- console.log(`> ${line}`);
320
- try {
321
- await program.parseAsync([...globalFlags, ...argv], { from: 'user' });
322
- ok += 1;
323
- }
324
- catch (err) {
325
- failed += 1;
326
- if (err instanceof SilentExitError === false && err instanceof commander_1.CommanderError === false) {
327
- const message = err instanceof Error ? err.message : String(err);
328
- console.error(`fastbrowser-cli error: ${message}`);
329
- }
330
- if (stopOnError === true) {
331
- throw new SilentExitError();
332
- }
333
- }
334
- }
335
- if (stopOnError === false) {
336
- console.log(`batch: ${ok} ok, ${failed} failed`);
337
- }
338
- if (failed > 0) {
339
- throw new SilentExitError();
340
- }
324
+ ///////////////////////////////////////////////////////////////////////////////
325
+ ///////////////////////////////////////////////////////////////////////////////
326
+ //
327
+ ///////////////////////////////////////////////////////////////////////////////
328
+ ///////////////////////////////////////////////////////////////////////////////
329
+ await program.parseAsync();
341
330
  }
342
331
  void main();
343
332
  //# sourceMappingURL=fastbrowser_cli.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fastbrowser_cli.js","sourceRoot":"","sources":["../../src/fastbrowser_cli/fastbrowser_cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fastbrowser_cli.js","sourceRoot":"","sources":["../../src/fastbrowser_cli/fastbrowser_cli.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastbrowser_cli",
3
- "version": "1.0.10",
3
+ "version": "1.0.13",
4
4
  "description": "",
5
5
  "main": "dist/fastbrowser_cli/fastbrowser_cli.js",
6
6
  "bin": {
@@ -19,6 +19,11 @@
19
19
  "keywords": [],
20
20
  "author": "",
21
21
  "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/jeromeetienne/skillmd_collecetion.git"
25
+ },
26
+ "homepage": "https://github.com/jeromeetienne/skillmd_collection/packages/fastbrowser_cli#readme",
22
27
  "type": "commonjs",
23
28
  "dependencies": {
24
29
  "@modelcontextprotocol/sdk": "^1.29.0",
@@ -1,23 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // node imports
4
3
  import fs from 'node:fs';
5
4
  import path from 'node:path';
6
5
 
7
- // npm imports
8
6
  import { Command, CommanderError } from 'commander';
9
7
  import stringArgv from 'string-argv';
10
8
 
11
- // local imports
12
9
  import { HttpClient } from './libs/http-client.js';
13
10
  import { ServerManager } from './libs/server-manager.js';
14
11
  import type { QuerySelectorInput, QuerySelectorFirstInput, QuerySelectorsAllRequest, QuerySelectorRequest } from '../fastbrowser_httpd/libs/tool-schemas.js';
15
12
 
16
-
17
- ///////////////////////////////////////////////////////////////////////////////
18
- ///////////////////////////////////////////////////////////////////////////////
19
- //
20
- ///////////////////////////////////////////////////////////////////////////////
21
13
  ///////////////////////////////////////////////////////////////////////////////
22
14
 
23
15
  type GlobalOpts = {
@@ -31,145 +23,200 @@ class SilentExitError extends Error {
31
23
  }
32
24
  }
33
25
 
34
- function getServerFromCmd(cmd: Command): string {
35
- const globalOpts = cmd.optsWithGlobals<GlobalOpts>();
36
- return HttpClient.getServerUrl(globalOpts.server);
37
- }
26
+ ///////////////////////////////////////////////////////////////////////////////
38
27
 
39
- function getAutostartFromCmd(cmd: Command): boolean {
40
- const globalOpts = cmd.optsWithGlobals<GlobalOpts>();
41
- return globalOpts.autostart !== false;
42
- }
28
+ class MainHelper {
29
+ static getServerFromCmd(cmd: Command): string {
30
+ const globalOpts = cmd.optsWithGlobals<GlobalOpts>();
31
+ return HttpClient.getServerUrl(globalOpts.server);
32
+ }
43
33
 
44
- async function runTool(cmd: Command, routeName: string, body: unknown): Promise<void> {
45
- const server = getServerFromCmd(cmd);
46
- if (getAutostartFromCmd(cmd) === true) {
47
- await ServerManager.ensureRunning(server);
34
+ static getAutostartFromCmd(cmd: Command): boolean {
35
+ const globalOpts = cmd.optsWithGlobals<GlobalOpts>();
36
+ return globalOpts.autostart !== false;
48
37
  }
49
- const response = await HttpClient.postTool(server, routeName, body);
50
- HttpClient.printResponse(response);
51
- }
52
38
 
53
- ///////////////////////////////////////////////////////////////////////////////
54
- ///////////////////////////////////////////////////////////////////////////////
55
- //
56
- ///////////////////////////////////////////////////////////////////////////////
57
- ///////////////////////////////////////////////////////////////////////////////
39
+ static async runTool(cmd: Command, routeName: string, body: unknown): Promise<void> {
40
+ const server = MainHelper.getServerFromCmd(cmd);
41
+ if (MainHelper.getAutostartFromCmd(cmd) === true) {
42
+ await ServerManager.ensureRunning(server);
43
+ }
44
+ const response = await HttpClient.postTool(server, routeName, body);
45
+ HttpClient.printResponse(response);
46
+ }
58
47
 
59
- function buildQuerySelectorsBody(opts: {
60
- selector?: string[];
61
- limit?: string;
62
- withAncestors?: boolean;
63
- selectorsJson?: string;
64
- }): QuerySelectorsAllRequest {
65
- if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
66
- let parsed: unknown;
67
- try {
68
- parsed = JSON.parse(opts.selectorsJson);
69
- } catch (err) {
70
- throw new Error(`--selectors-json is not valid JSON: ${(err as Error).message}`);
48
+ static buildQuerySelectorsBody(opts: {
49
+ selector?: string[];
50
+ limit?: string;
51
+ withAncestors?: boolean;
52
+ selectorsJson?: string;
53
+ }): QuerySelectorsAllRequest {
54
+ if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
55
+ let parsed: unknown;
56
+ try {
57
+ parsed = JSON.parse(opts.selectorsJson);
58
+ } catch (err) {
59
+ throw new Error(`--selectors-json is not valid JSON: ${(err as Error).message}`);
60
+ }
61
+ if (Array.isArray(parsed) === false) {
62
+ throw new Error('--selectors-json must be a JSON array');
63
+ }
64
+ return { selectors: parsed as QuerySelectorInput[] };
71
65
  }
72
- if (Array.isArray(parsed) === false) {
73
- throw new Error('--selectors-json must be a JSON array');
66
+
67
+ const selectorList = opts.selector ?? [];
68
+ if (selectorList.length === 0) {
69
+ throw new Error('At least one --selector or --selectors-json is required');
74
70
  }
75
- return { selectors: parsed as QuerySelectorInput[] };
76
- }
77
71
 
78
- const selectorList = opts.selector ?? [];
79
- if (selectorList.length === 0) {
80
- throw new Error('At least one --selector or --selectors-json is required');
72
+ const limit = opts.limit === undefined ? 0 : Number.parseInt(opts.limit, 10);
73
+ if (Number.isNaN(limit) === true) {
74
+ throw new Error(`Invalid --limit: ${opts.limit}`);
75
+ }
76
+ const withAncestors = opts.withAncestors !== false;
77
+
78
+ const selectors: QuerySelectorInput[] = selectorList.map((selector) => ({
79
+ selector,
80
+ limit,
81
+ withAncestors,
82
+ }));
83
+ return { selectors };
81
84
  }
82
85
 
83
- const limit = opts.limit === undefined ? 0 : Number.parseInt(opts.limit, 10);
84
- if (Number.isNaN(limit) === true) {
85
- throw new Error(`Invalid --limit: ${opts.limit}`);
86
+ static buildQuerySelectorFirstBody(opts: {
87
+ selector?: string[];
88
+ withAncestors?: boolean;
89
+ selectorsJson?: string;
90
+ }): QuerySelectorRequest {
91
+ if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
92
+ let parsed: unknown;
93
+ try {
94
+ parsed = JSON.parse(opts.selectorsJson);
95
+ } catch (err) {
96
+ throw new Error(`--selectors-json is not valid JSON: ${(err as Error).message}`);
97
+ }
98
+ if (Array.isArray(parsed) === false) {
99
+ throw new Error('--selectors-json must be a JSON array');
100
+ }
101
+ return { selectors: parsed as QuerySelectorFirstInput[] };
102
+ }
103
+
104
+ const selectorList = opts.selector ?? [];
105
+ if (selectorList.length === 0) {
106
+ throw new Error('At least one --selector or --selectors-json is required');
107
+ }
108
+
109
+ const withAncestors = opts.withAncestors !== false;
110
+
111
+ const selectors: QuerySelectorFirstInput[] = selectorList.map((selector) => ({
112
+ selector,
113
+ withAncestors,
114
+ }));
115
+ return { selectors };
86
116
  }
87
- const withAncestors = opts.withAncestors !== false;
88
-
89
- const selectors: QuerySelectorInput[] = selectorList.map((selector) => ({
90
- selector,
91
- limit,
92
- withAncestors,
93
- }));
94
- return { selectors };
95
- }
96
117
 
97
- function buildQuerySelectorFirstBody(opts: {
98
- selector?: string[];
99
- withAncestors?: boolean;
100
- selectorsJson?: string;
101
- }): QuerySelectorRequest {
102
- if (opts.selectorsJson !== undefined && opts.selectorsJson !== '') {
103
- let parsed: unknown;
118
+ static async runInstall(skillFolder: string): Promise<void> {
119
+ const sourceSkillMd = path.resolve(__dirname, '../../skills/fastbrowser/SKILL.md');
120
+ const targetDir = path.resolve(skillFolder, 'skills', 'fastbrowser');
121
+ const targetSkillMd = path.join(targetDir, 'SKILL.md');
104
122
  try {
105
- parsed = JSON.parse(opts.selectorsJson);
123
+ await fs.promises.mkdir(targetDir, { recursive: true });
124
+ await fs.promises.copyFile(sourceSkillMd, targetSkillMd);
125
+ console.log(`Installed fastbrowser SKILL.md at ${targetSkillMd}`);
106
126
  } catch (err) {
107
- throw new Error(`--selectors-json is not valid JSON: ${(err as Error).message}`);
108
- }
109
- if (Array.isArray(parsed) === false) {
110
- throw new Error('--selectors-json must be a JSON array');
127
+ const message = err instanceof Error ? err.message : String(err);
128
+ console.error(`fastbrowser-cli error: ${message}`);
129
+ process.exit(1);
111
130
  }
112
- return { selectors: parsed as QuerySelectorFirstInput[] };
113
131
  }
114
132
 
115
- const selectorList = opts.selector ?? [];
116
- if (selectorList.length === 0) {
117
- throw new Error('At least one --selector or --selectors-json is required');
133
+ static async readBatchSource(file: string | undefined, inlineScript: string | undefined): Promise<string> {
134
+ if (inlineScript !== undefined && inlineScript !== '') {
135
+ return inlineScript;
136
+ }
137
+ if (file !== undefined && file !== '') {
138
+ return await fs.promises.readFile(file, 'utf-8');
139
+ }
140
+ if (process.stdin.isTTY === true) {
141
+ throw new Error('batch: no input. Provide a file path, --script, or pipe commands on stdin.');
142
+ }
143
+ return await MainHelper.readStdinToString();
118
144
  }
119
145
 
120
- const withAncestors = opts.withAncestors !== false;
146
+ static async readStdinToString(): Promise<string> {
147
+ const chunks: Buffer[] = [];
148
+ return await new Promise((resolve, reject) => {
149
+ process.stdin.on('data', (chunk) => chunks.push(chunk as Buffer));
150
+ process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
151
+ process.stdin.on('error', (err) => reject(err));
152
+ });
153
+ }
121
154
 
122
- const selectors: QuerySelectorFirstInput[] = selectorList.map((selector) => ({
123
- selector,
124
- withAncestors,
125
- }));
126
- return { selectors };
127
- }
155
+ static async runBatch(program: Command, source: string, stopOnError: boolean, batchCmd: Command): Promise<void> {
156
+ const globalOpts = batchCmd.optsWithGlobals<GlobalOpts>();
157
+ const globalFlags: string[] = [];
158
+ if (globalOpts.server !== undefined) {
159
+ globalFlags.push('--server', globalOpts.server);
160
+ }
161
+ if (globalOpts.autostart === false) {
162
+ globalFlags.push('--no-autostart');
163
+ }
128
164
 
129
- ///////////////////////////////////////////////////////////////////////////////
130
- ///////////////////////////////////////////////////////////////////////////////
131
- //
132
- ///////////////////////////////////////////////////////////////////////////////
133
- ///////////////////////////////////////////////////////////////////////////////
165
+ const lines = source.split('\n');
166
+ let ok = 0;
167
+ let failed = 0;
168
+ for (const rawLine of lines) {
169
+ const line = rawLine.trim();
170
+ if (line === '' || line.startsWith('#') === true) continue;
171
+
172
+ const argv = stringArgv(line);
173
+ if (argv.length === 0) continue;
174
+
175
+ console.log(`> ${line}`);
176
+ try {
177
+ await program.parseAsync([...globalFlags, ...argv], { from: 'user' });
178
+ ok += 1;
179
+ } catch (err) {
180
+ failed += 1;
181
+ if (err instanceof SilentExitError === false && err instanceof CommanderError === false) {
182
+ const message = err instanceof Error ? err.message : String(err);
183
+ console.error(`fastbrowser-cli error: ${message}`);
184
+ }
185
+ if (stopOnError === true) {
186
+ throw new SilentExitError();
187
+ }
188
+ }
189
+ }
134
190
 
135
- async function runInstall(skillFolder: string): Promise<void> {
136
- const sourceSkillMd = path.resolve(__dirname, '../../skills/fastbrowser/SKILL.md');
137
- const targetDir = path.resolve(skillFolder, 'skills', 'fastbrowser');
138
- const targetSkillMd = path.join(targetDir, 'SKILL.md');
139
- try {
140
- await fs.promises.mkdir(targetDir, { recursive: true });
141
- await fs.promises.copyFile(sourceSkillMd, targetSkillMd);
142
- console.log(`Installed fastbrowser SKILL.md at ${targetSkillMd}`);
143
- } catch (err) {
144
- const message = err instanceof Error ? err.message : String(err);
145
- console.error(`fastbrowser-cli error: ${message}`);
146
- process.exit(1);
191
+ if (stopOnError === false) {
192
+ console.log(`batch: ${ok} ok, ${failed} failed`);
193
+ }
194
+ if (failed > 0) {
195
+ throw new SilentExitError();
196
+ }
147
197
  }
148
198
  }
149
199
 
150
200
  ///////////////////////////////////////////////////////////////////////////////
151
201
  ///////////////////////////////////////////////////////////////////////////////
152
- //
202
+ //
153
203
  ///////////////////////////////////////////////////////////////////////////////
154
204
  ///////////////////////////////////////////////////////////////////////////////
155
205
 
156
206
  async function main(): Promise<void> {
157
- const installIdx = process.argv.indexOf('--install');
158
- if (installIdx !== -1) {
159
- const next = process.argv[installIdx + 1];
160
- const skillFolder = (next !== undefined && next.startsWith('-') === false) ? next : '.';
161
- await runInstall(skillFolder);
162
- return;
163
- }
164
-
165
207
  const program = new Command();
166
208
  program
167
209
  .name('fastbrowser-cli')
168
210
  .description('CLI client for fastbrowser')
169
211
  .option('--server <url>', 'fastbrowser-httpd URL (default: env FASTBROWSER_SERVER or http://localhost:8787)')
170
212
  .option('--autostart', 'Auto-start the server before a command if it is not running', true)
171
- .option('--no-autostart', 'Do not auto-start the server before a command')
172
- .option('--install [skill-folder]', 'Install SKILL.md into <skill-folder>/skills/fastbrowser (default: .)');
213
+ .option('--no-autostart', 'Do not auto-start the server before a command');
214
+
215
+ ///////////////////////////////////////////////////////////////////////////////
216
+ ///////////////////////////////////////////////////////////////////////////////
217
+ //
218
+ ///////////////////////////////////////////////////////////////////////////////
219
+ ///////////////////////////////////////////////////////////////////////////////
173
220
 
174
221
  const serverCmd = program
175
222
  .command('server')
@@ -179,7 +226,7 @@ async function main(): Promise<void> {
179
226
  .command('start')
180
227
  .description('Start the fastbrowser HTTP server as a detached daemon')
181
228
  .action(async (_opts, cmd: Command) => {
182
- const server = getServerFromCmd(cmd);
229
+ const server = MainHelper.getServerFromCmd(cmd);
183
230
  await ServerManager.start(server);
184
231
  });
185
232
 
@@ -187,7 +234,7 @@ async function main(): Promise<void> {
187
234
  .command('stop')
188
235
  .description('Stop the fastbrowser HTTP server')
189
236
  .action(async (_opts, cmd: Command) => {
190
- const server = getServerFromCmd(cmd);
237
+ const server = MainHelper.getServerFromCmd(cmd);
191
238
  await ServerManager.stop(server);
192
239
  });
193
240
 
@@ -195,17 +242,23 @@ async function main(): Promise<void> {
195
242
  .command('status')
196
243
  .description('Report whether the fastbrowser HTTP server is running')
197
244
  .action(async (_opts, cmd: Command) => {
198
- const server = getServerFromCmd(cmd);
245
+ const server = MainHelper.getServerFromCmd(cmd);
199
246
  const state = await ServerManager.status(server);
200
247
  console.log(`fastbrowser server at ${server}: ${state}`);
201
248
  if (state === 'stopped') throw new SilentExitError();
202
249
  });
203
250
 
251
+ ///////////////////////////////////////////////////////////////////////////////
252
+ ///////////////////////////////////////////////////////////////////////////////
253
+ //
254
+ ///////////////////////////////////////////////////////////////////////////////
255
+ ///////////////////////////////////////////////////////////////////////////////
256
+
204
257
  program
205
258
  .command('list_pages')
206
259
  .description('List all open browser pages')
207
260
  .action(async (_opts, cmd: Command) => {
208
- await runTool(cmd, 'list_pages', {});
261
+ await MainHelper.runTool(cmd, 'list_pages', {});
209
262
  });
210
263
 
211
264
  program
@@ -213,7 +266,7 @@ async function main(): Promise<void> {
213
266
  .description('Open a new browser page')
214
267
  .requiredOption('--url <url>', 'URL to open')
215
268
  .action(async (opts: { url: string }, cmd: Command) => {
216
- await runTool(cmd, 'new_page', { url: opts.url });
269
+ await MainHelper.runTool(cmd, 'new_page', { url: opts.url });
217
270
  });
218
271
 
219
272
  program
@@ -225,7 +278,7 @@ async function main(): Promise<void> {
225
278
  if (Number.isNaN(pageId) === true) {
226
279
  throw new Error(`Invalid --page-id: ${opts.pageId}`);
227
280
  }
228
- await runTool(cmd, 'close_page', { pageId });
281
+ await MainHelper.runTool(cmd, 'close_page', { pageId });
229
282
  });
230
283
 
231
284
  program
@@ -233,7 +286,7 @@ async function main(): Promise<void> {
233
286
  .description('Navigate the current page to a URL')
234
287
  .requiredOption('--url <url>', 'URL to navigate to')
235
288
  .action(async (opts: { url: string }, cmd: Command) => {
236
- await runTool(cmd, 'navigate_page', { url: opts.url });
289
+ await MainHelper.runTool(cmd, 'navigate_page', { url: opts.url });
237
290
  });
238
291
 
239
292
  program
@@ -241,7 +294,7 @@ async function main(): Promise<void> {
241
294
  .description('Click an element by its accessibility selector')
242
295
  .requiredOption('-s, --selector <selector>', 'Accessibility selector (e.g. "#1_3" or \'button[name="Submit"]\')')
243
296
  .action(async (opts: { selector: string }, cmd: Command) => {
244
- await runTool(cmd, 'click', { selector: opts.selector });
297
+ await MainHelper.runTool(cmd, 'click', { selector: opts.selector });
245
298
  });
246
299
 
247
300
  program
@@ -250,7 +303,7 @@ async function main(): Promise<void> {
250
303
  .requiredOption('-s, --selector <selector>', 'Accessibility selector (e.g. "#1_3" or \'textbox[name="Email"]\')')
251
304
  .requiredOption('-v, --value <value>', 'Value to fill')
252
305
  .action(async (opts: { selector: string; value: string }, cmd: Command) => {
253
- await runTool(cmd, 'fill_form', {
306
+ await MainHelper.runTool(cmd, 'fill_form', {
254
307
  elements: [{ selector: opts.selector, value: opts.value }],
255
308
  });
256
309
  });
@@ -272,8 +325,8 @@ async function main(): Promise<void> {
272
325
  withAncestors?: boolean;
273
326
  selectorsJson?: string;
274
327
  }, cmd: Command) => {
275
- const body = buildQuerySelectorsBody(opts);
276
- await runTool(cmd, 'query_selectors_all', body);
328
+ const body = MainHelper.buildQuerySelectorsBody(opts);
329
+ await MainHelper.runTool(cmd, 'query_selectors_all', body);
277
330
  });
278
331
 
279
332
  program
@@ -291,15 +344,15 @@ async function main(): Promise<void> {
291
344
  withAncestors?: boolean;
292
345
  selectorsJson?: string;
293
346
  }, cmd: Command) => {
294
- const body = buildQuerySelectorFirstBody(opts);
295
- await runTool(cmd, 'query_selectors', body);
347
+ const body = MainHelper.buildQuerySelectorFirstBody(opts);
348
+ await MainHelper.runTool(cmd, 'query_selectors', body);
296
349
  });
297
350
 
298
351
  program
299
352
  .command('take_snapshot')
300
353
  .description('Take an accessibility-tree snapshot of the current page')
301
354
  .action(async (_opts, cmd: Command) => {
302
- await runTool(cmd, 'take_snapshot', {});
355
+ await MainHelper.runTool(cmd, 'take_snapshot', {});
303
356
  });
304
357
 
305
358
  program
@@ -307,7 +360,14 @@ async function main(): Promise<void> {
307
360
  .description('Press a sequence of keys')
308
361
  .requiredOption('--keys <keys>', "Comma-separated keys. E.g. 'Hello, Tab, Enter'")
309
362
  .action(async (opts: { keys: string }, cmd: Command) => {
310
- await runTool(cmd, 'press_keys', { keys: opts.keys });
363
+ await MainHelper.runTool(cmd, 'press_keys', { keys: opts.keys });
364
+ });
365
+
366
+ program
367
+ .command('install [skill-folder]')
368
+ .description('Install SKILL.md into <skill-folder>/skills/fastbrowser (default: .)')
369
+ .action(async (skillFolder: string | undefined) => {
370
+ await MainHelper.runInstall(skillFolder ?? '.');
311
371
  });
312
372
 
313
373
  program
@@ -316,91 +376,17 @@ async function main(): Promise<void> {
316
376
  .option('--script <script>', 'Inline multi-line script (overrides [file] and stdin)')
317
377
  .option('--no-stop-on-error', 'Continue running subsequent lines after a failure (default: stop on first error)')
318
378
  .action(async (file: string | undefined, opts: { script?: string; stopOnError: boolean }, cmd: Command) => {
319
- const source = await readBatchSource(file, opts.script);
320
- await runBatch(program, source, opts.stopOnError !== false, cmd);
379
+ const source = await MainHelper.readBatchSource(file, opts.script);
380
+ await MainHelper.runBatch(program, source, opts.stopOnError !== false, cmd);
321
381
  });
322
382
 
323
- program.exitOverride();
324
-
325
- try {
326
- await program.parseAsync(process.argv);
327
- } catch (err) {
328
- if (err instanceof SilentExitError) {
329
- process.exit(1);
330
- }
331
- if (err instanceof CommanderError) {
332
- process.exit(err.exitCode === undefined ? 1 : err.exitCode);
333
- }
334
- const message = err instanceof Error ? err.message : String(err);
335
- console.error(`fastbrowser-cli error: ${message}`);
336
- process.exit(1);
337
- }
338
- }
383
+ ///////////////////////////////////////////////////////////////////////////////
384
+ ///////////////////////////////////////////////////////////////////////////////
385
+ //
386
+ ///////////////////////////////////////////////////////////////////////////////
387
+ ///////////////////////////////////////////////////////////////////////////////
339
388
 
340
- async function readBatchSource(file: string | undefined, inlineScript: string | undefined): Promise<string> {
341
- if (inlineScript !== undefined && inlineScript !== '') {
342
- return inlineScript;
343
- }
344
- if (file !== undefined && file !== '') {
345
- return await fs.promises.readFile(file, 'utf-8');
346
- }
347
- if (process.stdin.isTTY === true) {
348
- throw new Error('batch: no input. Provide a file path, --script, or pipe commands on stdin.');
349
- }
350
- return await readStdinToString();
351
- }
352
-
353
- async function readStdinToString(): Promise<string> {
354
- const chunks: Buffer[] = [];
355
- return await new Promise((resolve, reject) => {
356
- process.stdin.on('data', (chunk) => chunks.push(chunk as Buffer));
357
- process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
358
- process.stdin.on('error', (err) => reject(err));
359
- });
360
- }
361
-
362
- async function runBatch(program: Command, source: string, stopOnError: boolean, batchCmd: Command): Promise<void> {
363
- const globalOpts = batchCmd.optsWithGlobals<GlobalOpts>();
364
- const globalFlags: string[] = [];
365
- if (globalOpts.server !== undefined) {
366
- globalFlags.push('--server', globalOpts.server);
367
- }
368
- if (globalOpts.autostart === false) {
369
- globalFlags.push('--no-autostart');
370
- }
371
-
372
- const lines = source.split('\n');
373
- let ok = 0;
374
- let failed = 0;
375
- for (const rawLine of lines) {
376
- const line = rawLine.trim();
377
- if (line === '' || line.startsWith('#') === true) continue;
378
-
379
- const argv = stringArgv(line);
380
- if (argv.length === 0) continue;
381
-
382
- console.log(`> ${line}`);
383
- try {
384
- await program.parseAsync([...globalFlags, ...argv], { from: 'user' });
385
- ok += 1;
386
- } catch (err) {
387
- failed += 1;
388
- if (err instanceof SilentExitError === false && err instanceof CommanderError === false) {
389
- const message = err instanceof Error ? err.message : String(err);
390
- console.error(`fastbrowser-cli error: ${message}`);
391
- }
392
- if (stopOnError === true) {
393
- throw new SilentExitError();
394
- }
395
- }
396
- }
397
-
398
- if (stopOnError === false) {
399
- console.log(`batch: ${ok} ok, ${failed} failed`);
400
- }
401
- if (failed > 0) {
402
- throw new SilentExitError();
403
- }
389
+ await program.parseAsync();
404
390
  }
405
391
 
406
392
  void main();
@@ -1,7 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(npx fastbrowser_cli *)"
5
- ]
6
- }
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(npx tsx *)"
5
- ]
6
- }
7
- }