@opencraw/cli 0.1.12 → 0.1.14

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/dist/index.esm.js CHANGED
@@ -12,6 +12,8 @@ Commands
12
12
  run <recipe files or directories...> Crawl. Records go to --out as JSON Lines, or to stdout.
13
13
  probe <url> Fetch a page and report where its data lives.
14
14
  diff <previous.jsonl> <current.jsonl> Compare two runs' records by key: added, removed, changed.
15
+ studio [folder] Open a recipe folder in the browser: run samples, read
16
+ the trace next to the page (needs @opencraw/studio).
15
17
 
16
18
  Options for run
17
19
  --out <file> Write records to this JSON Lines file (default: stdout).
@@ -236,6 +238,14 @@ function parseArguments(argv, env = {}) {
236
238
  options
237
239
  };
238
240
  }
241
+ case 'studio':
242
+ {
243
+ if (rest.length > 1) throw new Error('studio takes at most one folder');
244
+ return {
245
+ name: 'studio',
246
+ folder: rest[0]
247
+ };
248
+ }
239
249
  default:
240
250
  {
241
251
  throw new Error(`unknown command "${name}"`);
@@ -1403,6 +1413,37 @@ function loadErrorLines(error) {
1403
1413
  return [error instanceof Error ? error.message : String(error)];
1404
1414
  }
1405
1415
 
1416
+ /**
1417
+ * Runs `opencraw studio [folder]`: imports `@opencraw/studio` lazily and
1418
+ * delegates to its own `main`, which starts the server, prints the URL with
1419
+ * the token, and keeps running until interrupted (Ctrl+C) — the cli's own
1420
+ * call does not return before that. `@opencraw/studio` is an optional peer
1421
+ * dependency (`peerDependenciesMeta`), never a hard one: the cli stays light
1422
+ * for callers who only need to crawl. When it is not installed, this prints
1423
+ * how to add it instead of letting a raw `ERR_MODULE_NOT_FOUND` stack trace
1424
+ * through.
1425
+ *
1426
+ * @param folder - The recipe folder to open; `@opencraw/studio`'s own default (the current directory) when omitted.
1427
+ * @param terminal - Where output goes.
1428
+ * @param importStudio - How the module is loaded; the real dynamic `import()` by default, replaced in tests.
1429
+ * @returns The exit code: 0 once the server has stopped, 1 when `@opencraw/studio` is missing.
1430
+ */
1431
+ async function runStudio(folder, terminal, importStudio = () => import('@opencraw/studio')) {
1432
+ let studio;
1433
+ try {
1434
+ studio = await importStudio();
1435
+ } catch (error) {
1436
+ if (!isModuleNotFound(error)) throw error;
1437
+ terminal.err('the studio is not installed: run `npm install @opencraw/studio`, then try again');
1438
+ return 1;
1439
+ }
1440
+ await studio.main(folder === undefined ? [] : [folder]);
1441
+ return 0;
1442
+ }
1443
+ function isModuleNotFound(error) {
1444
+ return error instanceof Error && 'code' in error && error.code === 'ERR_MODULE_NOT_FOUND';
1445
+ }
1446
+
1406
1447
  /**
1407
1448
  * Loads and binds recipe files, printing every problem with its JSON path.
1408
1449
  *
@@ -1496,6 +1537,10 @@ async function main(argv, terminal) {
1496
1537
  {
1497
1538
  return diffFiles(command, terminal);
1498
1539
  }
1540
+ case 'studio':
1541
+ {
1542
+ return runStudio(command.folder, terminal);
1543
+ }
1499
1544
  }
1500
1545
  }
1501
1546
 
@@ -1511,5 +1556,5 @@ function processTerminal() {
1511
1556
  };
1512
1557
  }
1513
1558
 
1514
- export { USAGE, diffReport, findData, loadForRun, loadHooks, loadPlugins, main, parseArguments, probeReport, probeUrl, processTerminal, readRecipeFiles, resolveAccess, writeChanges };
1559
+ export { USAGE, diffReport, findData, loadForRun, loadHooks, loadPlugins, main, parseArguments, probeReport, probeUrl, processTerminal, readRecipeFiles, resolveAccess, runStudio, writeChanges };
1515
1560
  //# sourceMappingURL=index.esm.js.map
@@ -65,5 +65,9 @@ export type Command = {
65
65
  /** Also render the page in a browser and watch the JSON it fetches. */
66
66
  browser: boolean;
67
67
  options: CommonOptions;
68
+ } | {
69
+ name: 'studio';
70
+ /** The recipe folder to open; the current directory when not given. */
71
+ folder?: string;
68
72
  };
69
73
  //# sourceMappingURL=command.contract.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import type { Command } from './command.contract.js';
2
- export declare const USAGE = "opencraw <command> [options]\n\nCommands\n validate <recipe files or directories...> Parse and bind the recipes; list every problem with its path.\n run <recipe files or directories...> Crawl. Records go to --out as JSON Lines, or to stdout.\n probe <url> Fetch a page and report where its data lives.\n diff <previous.jsonl> <current.jsonl> Compare two runs' records by key: added, removed, changed.\n\nOptions for run\n --out <file> Write records to this JSON Lines file (default: stdout).\n --append Keep what --out holds and add to it (each line carries _key).\n --resume Skip records --out already has (needs --append).\n --only <id> Run only this input recipe (repeatable).\n --dry-run One record per input, printed with the scope it was mapped from.\n --trace Print the crawl trace to stderr.\n --headed Show the browser.\n --parallel <n> Run this many input recipes at once (default 1). Iterations inside a recipe\n follow its limits.concurrency.\n --retries <n> Tries per request that fails in passing (connection, timeout, 429, 5xx), for\n recipes whose limits.retry says nothing. Default 3; 1 turns retrying off.\n --profiles <dir> Where recipes' session.browserProfile profiles live (or OPENCRAW_PROFILES;\n default .opencraw/profiles).\n --diff <file> Compare this run's records with a previous run's JSON Lines file (it may be\n --out itself: it is read before the crawl). Keys come from the output recipe.\n --host-delay <ms> At least this long between two requests to one site, across every recipe.\n --host-concurrency <n>\n At most this many requests to one site in flight, across every recipe.\n Both override the access config's \"throttle\" defaults.\n\nOptions for diff\n --key <a,b> The fields that identify a record (default: each line's _key).\n --ignore <a,b> Fields left out of the comparison (a date the crawl stamps, say).\n --changes <file> Also write every change as a JSON line (run --diff takes it too).\n\nOptions for probe\n --browser Also render the page in a browser and list the JSON it fetches.\n\nOptions for both\n --browser-path <p> A browser binary other than the one Playwright installed (or OPENCRAW_CHROMIUM).\n --insecure-tls Accept an intercepting proxy's certificate (or OPENCRAW_INSECURE_TLS=1).\n --user-agent <ua> The user agent to send.\n --access <file> An access config: proxy profiles, credentials as {{env.NAME}} (or OPENCRAW_ACCESS).\n --access-profile <name>\n The access profile to use when a recipe names none.\n --plugins <file> A JavaScript module exporting hooks (the recipes' hook steps and transforms),\n accessPlugins (for { kind: \"plugin\" } access profiles) and captchaSolvers\n (for session.captcha and captcha steps); --hooks, or OPENCRAW_PLUGINS /\n OPENCRAW_HOOKS. It runs as your code: trust it.\n --help, --version";
2
+ export declare const USAGE = "opencraw <command> [options]\n\nCommands\n validate <recipe files or directories...> Parse and bind the recipes; list every problem with its path.\n run <recipe files or directories...> Crawl. Records go to --out as JSON Lines, or to stdout.\n probe <url> Fetch a page and report where its data lives.\n diff <previous.jsonl> <current.jsonl> Compare two runs' records by key: added, removed, changed.\n studio [folder] Open a recipe folder in the browser: run samples, read\n the trace next to the page (needs @opencraw/studio).\n\nOptions for run\n --out <file> Write records to this JSON Lines file (default: stdout).\n --append Keep what --out holds and add to it (each line carries _key).\n --resume Skip records --out already has (needs --append).\n --only <id> Run only this input recipe (repeatable).\n --dry-run One record per input, printed with the scope it was mapped from.\n --trace Print the crawl trace to stderr.\n --headed Show the browser.\n --parallel <n> Run this many input recipes at once (default 1). Iterations inside a recipe\n follow its limits.concurrency.\n --retries <n> Tries per request that fails in passing (connection, timeout, 429, 5xx), for\n recipes whose limits.retry says nothing. Default 3; 1 turns retrying off.\n --profiles <dir> Where recipes' session.browserProfile profiles live (or OPENCRAW_PROFILES;\n default .opencraw/profiles).\n --diff <file> Compare this run's records with a previous run's JSON Lines file (it may be\n --out itself: it is read before the crawl). Keys come from the output recipe.\n --host-delay <ms> At least this long between two requests to one site, across every recipe.\n --host-concurrency <n>\n At most this many requests to one site in flight, across every recipe.\n Both override the access config's \"throttle\" defaults.\n\nOptions for diff\n --key <a,b> The fields that identify a record (default: each line's _key).\n --ignore <a,b> Fields left out of the comparison (a date the crawl stamps, say).\n --changes <file> Also write every change as a JSON line (run --diff takes it too).\n\nOptions for probe\n --browser Also render the page in a browser and list the JSON it fetches.\n\nOptions for both\n --browser-path <p> A browser binary other than the one Playwright installed (or OPENCRAW_CHROMIUM).\n --insecure-tls Accept an intercepting proxy's certificate (or OPENCRAW_INSECURE_TLS=1).\n --user-agent <ua> The user agent to send.\n --access <file> An access config: proxy profiles, credentials as {{env.NAME}} (or OPENCRAW_ACCESS).\n --access-profile <name>\n The access profile to use when a recipe names none.\n --plugins <file> A JavaScript module exporting hooks (the recipes' hook steps and transforms),\n accessPlugins (for { kind: \"plugin\" } access profiles) and captchaSolvers\n (for session.captcha and captcha steps); --hooks, or OPENCRAW_PLUGINS /\n OPENCRAW_HOOKS. It runs as your code: trust it.\n --help, --version";
3
3
  /**
4
4
  * Turns argv into a command.
5
5
  *
@@ -13,4 +13,6 @@ export type { CommonOptions } from './arguments/index.js';
13
13
  export { resolveAccess } from './access/index.js';
14
14
  export { loadHooks, loadPlugins } from './hooks-module/index.js';
15
15
  export type { PluginModule } from './hooks-module/index.js';
16
+ export { runStudio } from './studio/index.js';
17
+ export type { StudioModule } from './studio/index.js';
16
18
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ export { runStudio } from './run-studio.use-case.js';
2
+ export type { StudioModule } from './run-studio.use-case.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,22 @@
1
+ import type { Terminal } from '../terminal/index.js';
2
+ /** The one export the cli needs from `@opencraw/studio`. */
3
+ export interface StudioModule {
4
+ main: (argv: readonly string[]) => Promise<void>;
5
+ }
6
+ /**
7
+ * Runs `opencraw studio [folder]`: imports `@opencraw/studio` lazily and
8
+ * delegates to its own `main`, which starts the server, prints the URL with
9
+ * the token, and keeps running until interrupted (Ctrl+C) — the cli's own
10
+ * call does not return before that. `@opencraw/studio` is an optional peer
11
+ * dependency (`peerDependenciesMeta`), never a hard one: the cli stays light
12
+ * for callers who only need to crawl. When it is not installed, this prints
13
+ * how to add it instead of letting a raw `ERR_MODULE_NOT_FOUND` stack trace
14
+ * through.
15
+ *
16
+ * @param folder - The recipe folder to open; `@opencraw/studio`'s own default (the current directory) when omitted.
17
+ * @param terminal - Where output goes.
18
+ * @param importStudio - How the module is loaded; the real dynamic `import()` by default, replaced in tests.
19
+ * @returns The exit code: 0 once the server has stopped, 1 when `@opencraw/studio` is missing.
20
+ */
21
+ export declare function runStudio(folder: string | undefined, terminal: Terminal, importStudio?: () => Promise<StudioModule>): Promise<number>;
22
+ //# sourceMappingURL=run-studio.use-case.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencraw/cli",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "type": "module",
5
5
  "main": "./dist/index.esm.js",
6
6
  "module": "./dist/index.esm.js",
@@ -24,9 +24,17 @@
24
24
  "!**/*.js.map"
25
25
  ],
26
26
  "dependencies": {
27
- "@opencraw/core": "^0.1.12",
27
+ "@opencraw/core": "^0.1.14",
28
28
  "playwright": "^1.63.0"
29
29
  },
30
+ "peerDependencies": {
31
+ "@opencraw/studio": "^0.0.3"
32
+ },
33
+ "peerDependenciesMeta": {
34
+ "@opencraw/studio": {
35
+ "optional": true
36
+ }
37
+ },
30
38
  "publishConfig": {
31
39
  "access": "public"
32
40
  },