@opencraw/driver 0.4.0 → 0.5.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/dist/index.esm.js CHANGED
@@ -240,8 +240,8 @@ function clientAccessPlugins(names, runId, ask) {
240
240
  // src/site-access/resolve-site-access.use-case.ts
241
241
  import { resolveAccess } from "@opencraw/cli";
242
242
  async function resolveSiteAccess(params, runId, ask, env = process.env) {
243
- const file = params.accessConfig ?? env.OPENCRAW_ACCESS;
244
- if (file === void 0 && params.access !== void 0) throw new Error(`access profile "${params.access}" needs an access config: give "accessConfig", or set OPENCRAW_ACCESS where the driver runs`);
243
+ const file = params.accessConfig ?? (env.OPENCRAW_ACCESS === "" ? void 0 : env.OPENCRAW_ACCESS);
244
+ if (file === void 0 && params.access !== void 0) throw new Error(`access profile "${params.access}" needs an access config, and there is none: no "accessConfig" was given, and OPENCRAW_ACCESS is not set where OpenCraw runs`);
245
245
  const access = await resolveAccess({ insecureTls: false, access: file, accessProfile: params.access });
246
246
  return { access, accessPlugins: clientAccessPlugins(params.accessPlugins ?? [], runId, ask) };
247
247
  }
@@ -344,17 +344,17 @@ function streamingSink() {
344
344
  }
345
345
 
346
346
  // src/session/run-session.use-case.ts
347
- function runSessions(notify, ask) {
347
+ function runSessions(notify, ask, local = {}) {
348
348
  const running = /* @__PURE__ */ new Map();
349
349
  let next = 1;
350
350
  const crawlerFor = async (runId, params) => {
351
351
  const { access, accessPlugins } = await resolveSiteAccess(params, runId, ask);
352
352
  return createCrawler({
353
353
  sink: params.out === void 0 ? streamingSink() : fileSink2(params.out, { append: params.append, browser: { executablePath: params.browser?.executablePath } }),
354
- hooks: clientHooks(params.hooks ?? [], runId, ask),
355
- captchaSolvers: clientCaptchaSolvers(params.captchaSolvers ?? [], runId, ask),
354
+ hooks: { ...local.hooks, ...clientHooks(params.hooks ?? [], runId, ask) },
355
+ captchaSolvers: [...local.captchaSolvers ?? [], ...clientCaptchaSolvers(params.captchaSolvers ?? [], runId, ask)],
356
356
  access,
357
- accessPlugins,
357
+ accessPlugins: [...local.accessPlugins ?? [], ...accessPlugins],
358
358
  profilesDir: process.env.OPENCRAW_PROFILES,
359
359
  parallel: params.parallel,
360
360
  resume: params.resume,
@@ -380,15 +380,16 @@ function runSessions(notify, ask) {
380
380
  }
381
381
  })();
382
382
  };
383
+ const startLoaded = async (loaded, params) => {
384
+ const set = params.dryRun === true ? new RecipeSet(loaded.output, loaded.inputs.map((input) => ({ ...input, limits: { ...input.limits, maxRecords: 1 } }))) : loaded;
385
+ const runId = `run-${next++}`;
386
+ const crawler = await crawlerFor(runId, params);
387
+ track(runId, crawler, async () => await crawler.run(set));
388
+ return runId;
389
+ };
383
390
  return {
384
- start: async (params) => {
385
- const loaded = await loadRecipes(params);
386
- const set = params.dryRun === true ? new RecipeSet(loaded.output, loaded.inputs.map((input) => ({ ...input, limits: { ...input.limits, maxRecords: 1 } }))) : loaded;
387
- const runId = `run-${next++}`;
388
- const crawler = await crawlerFor(runId, params);
389
- track(runId, crawler, async () => await crawler.run(set));
390
- return runId;
391
- },
391
+ start: async (params) => await startLoaded(await loadRecipes(params), params),
392
+ startLoaded,
392
393
  startWork: async (params) => {
393
394
  const set = await loadRecipes(params);
394
395
  const runId = `run-${next++}`;
package/dist/main.esm.js CHANGED
@@ -201,8 +201,8 @@ function clientAccessPlugins(names, runId, ask) {
201
201
  // src/site-access/resolve-site-access.use-case.ts
202
202
  import { resolveAccess } from "@opencraw/cli";
203
203
  async function resolveSiteAccess(params, runId, ask, env = process.env) {
204
- const file = params.accessConfig ?? env.OPENCRAW_ACCESS;
205
- if (file === void 0 && params.access !== void 0) throw new Error(`access profile "${params.access}" needs an access config: give "accessConfig", or set OPENCRAW_ACCESS where the driver runs`);
204
+ const file = params.accessConfig ?? (env.OPENCRAW_ACCESS === "" ? void 0 : env.OPENCRAW_ACCESS);
205
+ if (file === void 0 && params.access !== void 0) throw new Error(`access profile "${params.access}" needs an access config, and there is none: no "accessConfig" was given, and OPENCRAW_ACCESS is not set where OpenCraw runs`);
206
206
  const access = await resolveAccess({ insecureTls: false, access: file, accessProfile: params.access });
207
207
  return { access, accessPlugins: clientAccessPlugins(params.accessPlugins ?? [], runId, ask) };
208
208
  }
@@ -305,17 +305,17 @@ function streamingSink() {
305
305
  }
306
306
 
307
307
  // src/session/run-session.use-case.ts
308
- function runSessions(notify, ask) {
308
+ function runSessions(notify, ask, local = {}) {
309
309
  const running = /* @__PURE__ */ new Map();
310
310
  let next = 1;
311
311
  const crawlerFor = async (runId, params) => {
312
312
  const { access, accessPlugins } = await resolveSiteAccess(params, runId, ask);
313
313
  return createCrawler({
314
314
  sink: params.out === void 0 ? streamingSink() : fileSink2(params.out, { append: params.append, browser: { executablePath: params.browser?.executablePath } }),
315
- hooks: clientHooks(params.hooks ?? [], runId, ask),
316
- captchaSolvers: clientCaptchaSolvers(params.captchaSolvers ?? [], runId, ask),
315
+ hooks: { ...local.hooks, ...clientHooks(params.hooks ?? [], runId, ask) },
316
+ captchaSolvers: [...local.captchaSolvers ?? [], ...clientCaptchaSolvers(params.captchaSolvers ?? [], runId, ask)],
317
317
  access,
318
- accessPlugins,
318
+ accessPlugins: [...local.accessPlugins ?? [], ...accessPlugins],
319
319
  profilesDir: process.env.OPENCRAW_PROFILES,
320
320
  parallel: params.parallel,
321
321
  resume: params.resume,
@@ -341,15 +341,16 @@ function runSessions(notify, ask) {
341
341
  }
342
342
  })();
343
343
  };
344
+ const startLoaded = async (loaded, params) => {
345
+ const set = params.dryRun === true ? new RecipeSet(loaded.output, loaded.inputs.map((input) => ({ ...input, limits: { ...input.limits, maxRecords: 1 } }))) : loaded;
346
+ const runId = `run-${next++}`;
347
+ const crawler = await crawlerFor(runId, params);
348
+ track(runId, crawler, async () => await crawler.run(set));
349
+ return runId;
350
+ };
344
351
  return {
345
- start: async (params) => {
346
- const loaded = await loadRecipes(params);
347
- const set = params.dryRun === true ? new RecipeSet(loaded.output, loaded.inputs.map((input) => ({ ...input, limits: { ...input.limits, maxRecords: 1 } }))) : loaded;
348
- const runId = `run-${next++}`;
349
- const crawler = await crawlerFor(runId, params);
350
- track(runId, crawler, async () => await crawler.run(set));
351
- return runId;
352
- },
352
+ start: async (params) => await startLoaded(await loadRecipes(params), params),
353
+ startLoaded,
353
354
  startWork: async (params) => {
354
355
  const set = await loadRecipes(params);
355
356
  const runId = `run-${next++}`;
@@ -5,7 +5,7 @@ export type { InitializeParams, InitializeResult, ValidateParams, ValidateResult
5
5
  export { openLineChannel, RPC_ERRORS, RpcFailure } from './transport/index.js';
6
6
  export type { LineChannel, RequestHandler, RpcError, RpcMessage } from './transport/index.js';
7
7
  export { runSessions, validateRecipes, streamingSink } from './session/index.js';
8
- export type { RunSessions } from './session/index.js';
8
+ export type { LocalPlugins, RunSessions } from './session/index.js';
9
9
  export { clientHooks, clientCaptchaSolvers, clientAccessPlugins } from './callout-bridge/index.js';
10
10
  export type { AskClient, NotifyClient } from './callout-bridge/index.js';
11
11
  export { clientWorkSource } from './work-bridge/index.js';
@@ -1,5 +1,5 @@
1
1
  export { runSessions } from './run-session.use-case.js';
2
- export type { RunSessions } from './run-session.use-case.js';
2
+ export type { LocalPlugins, RunSessions } from './run-session.use-case.js';
3
3
  export { validateRecipes, hooksOf, loadRecipes, sourceOf } from './recipe-loading.use-case.js';
4
4
  export { streamingSink } from './streaming-sink.repository.js';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1,12 +1,22 @@
1
+ import { RecipeSet } from '@opencraw/core';
2
+ import type { AccessPlugin, CaptchaSolver, HookMap } from '@opencraw/core';
1
3
  import type { AskClient, NotifyClient } from '../callout-bridge/index.js';
2
4
  import type { RunParams, WorkParams } from '../protocol/index.js';
3
5
  /** The runs a driver has going, by id, so `cancel` can reach them and `shutdown` close them all. */
4
6
  export interface RunSessions {
5
7
  start: (params: RunParams) => Promise<string>;
8
+ /** As `start`, for recipes the host has already loaded and bound (`params`' recipe source is ignored). */
9
+ startLoaded: (set: RecipeSet, params: Omit<RunParams, 'paths' | 'recipes'>) => Promise<string>;
6
10
  startWork: (params: WorkParams) => Promise<string>;
7
11
  cancel: (runId: string) => Promise<boolean>;
8
12
  closeAll: () => Promise<void>;
9
13
  }
14
+ /** What the host serves itself, in process, besides what the client serves: an MCP server's plugins module. */
15
+ export interface LocalPlugins {
16
+ hooks?: HookMap;
17
+ captchaSolvers?: CaptchaSolver[];
18
+ accessPlugins?: AccessPlugin[];
19
+ }
10
20
  /**
11
21
  * Starts and tracks runs and worker pools. `start` and `startWork` load and bind the recipes (a bad
12
22
  * recipe fails the request itself, with its problems), answer with a run id at once, and crawl in the
@@ -18,7 +28,8 @@ export interface RunSessions {
18
28
  *
19
29
  * @param notify - The channel's notify.
20
30
  * @param ask - The channel's request, for callouts and work.
31
+ * @param local - Hooks, captcha solvers and access plugins the host serves itself, beside the client's.
21
32
  * @returns The sessions.
22
33
  */
23
- export declare function runSessions(notify: NotifyClient, ask: AskClient): RunSessions;
34
+ export declare function runSessions(notify: NotifyClient, ask: AskClient, local?: LocalPlugins): RunSessions;
24
35
  //# sourceMappingURL=run-session.use-case.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencraw/driver",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "OpenCraw's driver: the engine over JSON-RPC on stdio, for clients in other languages",
5
5
  "license": "MIT",
6
6
  "type": "module",