@opencraw/driver-client 0.2.10

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 ADDED
@@ -0,0 +1,52 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/Open-Craw/OpenCraw/main/docs/assets/opencraw-logo.svg" alt="OpenCraw" width="360">
3
+ </p>
4
+
5
+ # @opencraw/driver-client
6
+
7
+ A thin TypeScript client for [`@opencraw/driver`](../driver/README.md): it starts the driver program, speaks its
8
+ JSON-RPC protocol over the pipes, and answers the driver's callouts with your functions. It is the reference
9
+ client the conformance suite is held to, and the model every other language's package follows. To crawl from
10
+ TypeScript in the same process, use [`@opencraw/core`](../core/README.md) instead.
11
+
12
+ ```sh
13
+ npm install @opencraw/driver-client
14
+ ```
15
+
16
+ ```ts
17
+ import { openDriver } from '@opencraw/driver-client'
18
+
19
+ const driver = await openDriver({
20
+ hooks: { tidy: input => String(input).trim().toLowerCase() },
21
+ accessPlugins: { pool: async ({ phase }) => phase === 'lease' ? { proxy: { server: 'http://proxy:8080' } } : {} },
22
+ })
23
+
24
+ const run = await driver.run({ paths: ['recipes/'], onRecord: ({ data }) => { console.log(data) } })
25
+ const { report, error } = await run.finished
26
+
27
+ await driver.close()
28
+ ```
29
+
30
+ - **What you serve is registered once**, by name: `hooks`, `captchaSolvers` and `accessPlugins`. Every run,
31
+ worker pool and probe may use them; a handler's return value is the callout's answer, and a handler that
32
+ throws answers `error` with its message, which fails that call, not the run.
33
+ - **`run`** answers once the driver has started it; `onEvent` and `onRecord` stream as it crawls, and
34
+ `finished` settles with the report (it never rejects). `cancel()` stops it.
35
+ - **`work`** is worker mode: `next()` gives each window its item (`{ id, vars }`), and may wait until there is
36
+ one; `null` ends the work. `onDone` and `onFailed` say how each item ended.
37
+ - **`validate`, `probe`, `diff`, `export`** answer as the driver's methods do.
38
+ - **`close`** asks the driver to shut down and waits for it to exit.
39
+
40
+ The driver program is the installed `@opencraw/driver`'s, run with this Node; `command` starts another one, and
41
+ `runtime: { version }` starts a release's own runtime, which needs no Node: `ensureDriverRuntime` downloads this
42
+ platform's archive once (named in the release's `driver-runtime.json`), refuses it when its SHA-256 differs,
43
+ and unpacks it into `~/.cache/opencraw/driver/<version>/<platform>/`. `OPENCRAW_DRIVER=<folder>` uses an
44
+ unpacked runtime as it is, and `OPENCRAW_DRIVER_OFFLINE=1` (or `offline: true`) never downloads: a runtime not
45
+ already cached is an error. Every client in another language follows the same steps.
46
+
47
+ ## Development
48
+
49
+ `smith test -p driver,driver-client`. The client's tests start the built driver program: they run a crawl
50
+ and a worker pool against a local site, a probe through a served access plugin, and every transcript in
51
+ `packages/driver/conformance/` over the program's pipes. The `driver-conformance` workflow runs them on
52
+ Linux, macOS and Windows.
@@ -0,0 +1,205 @@
1
+ // src/driver-session/open-driver.use-case.ts
2
+ import { once } from "node:events";
3
+ import { openLineChannel, PROTOCOL_VERSION } from "@opencraw/driver";
4
+
5
+ // src/driver-process/driver-process.client.ts
6
+ import { spawn } from "node:child_process";
7
+ import { readFileSync } from "node:fs";
8
+ import { createRequire } from "node:module";
9
+ import { dirname, join } from "node:path";
10
+ function installedDriverCommand() {
11
+ const manifest = createRequire(import.meta.url).resolve("@opencraw/driver/package.json");
12
+ const { bin } = JSON.parse(readFileSync(manifest, "utf8"));
13
+ return [process.execPath, join(dirname(manifest), bin["opencraw-driver"])];
14
+ }
15
+ function startDriverProcess(options = {}) {
16
+ const [program, ...args] = options.command ?? installedDriverCommand();
17
+ const child = spawn(program, args, { env: options.env ?? process.env, cwd: options.cwd, stdio: ["pipe", "pipe", options.stderr ?? "inherit"], windowsHide: true });
18
+ if (child.stdin === null || child.stdout === null) throw new Error("the driver started without its pipes");
19
+ const exited = new Promise((resolve2, reject) => {
20
+ child.once("error", reject);
21
+ child.once("exit", (code) => {
22
+ resolve2(code);
23
+ });
24
+ });
25
+ return {
26
+ input: child.stdin,
27
+ output: child.stdout,
28
+ ...child.stderr !== null && { logs: child.stderr },
29
+ exited,
30
+ kill: () => {
31
+ child.kill();
32
+ }
33
+ };
34
+ }
35
+
36
+ // src/driver-runtime/ensure-driver-runtime.use-case.ts
37
+ import { execFileSync } from "node:child_process";
38
+ import { createHash } from "node:crypto";
39
+ import { existsSync, readFileSync as readFileSync2 } from "node:fs";
40
+ import { mkdir, mkdtemp, rename, rm, writeFile } from "node:fs/promises";
41
+ import { homedir } from "node:os";
42
+ import { join as join2, resolve } from "node:path";
43
+ import { runtimeManifestSchema } from "@opencraw/driver";
44
+ var RELEASES_URL = "https://github.com/Open-Craw/OpenCraw/releases/download";
45
+ async function ensureDriverRuntime(options) {
46
+ const env = options.env ?? process.env;
47
+ if (env.OPENCRAW_DRIVER !== void 0 && env.OPENCRAW_DRIVER !== "") return runtimeIn(resolve(env.OPENCRAW_DRIVER));
48
+ const platform = options.platform ?? `${process.platform}-${process.arch}`;
49
+ const cache = options.cacheDir ?? join2(homedir(), ".cache", "opencraw", "driver");
50
+ const folder = join2(cache, options.version, platform);
51
+ if (existsSync(join2(folder, "runtime.json"))) return runtimeIn(folder);
52
+ if (options.offline ?? env.OPENCRAW_DRIVER_OFFLINE === "1") throw new Error(`driver ${options.version} for ${platform} is not in ${cache}, and downloading is off (OPENCRAW_DRIVER_OFFLINE)`);
53
+ const get = options.fetch ?? fetch;
54
+ const release = `${options.baseUrl ?? RELEASES_URL}/${encodeURIComponent(`driver@${options.version}`)}`;
55
+ const listing = await download(get, `${release}/driver-runtime.json`);
56
+ const manifest = runtimeManifestSchema.parse(await listing.json());
57
+ const archive = manifest.archives[platform];
58
+ if (archive === void 0) throw new Error(`driver ${options.version} has no runtime for ${platform}: it has ${Object.keys(manifest.archives).join(", ")}`);
59
+ const fetched = await download(get, `${release}/${archive.file}`);
60
+ const bytes = Buffer.from(await fetched.arrayBuffer());
61
+ const sha256 = createHash("sha256").update(bytes).digest("hex");
62
+ if (sha256 !== archive.sha256) throw new Error(`${archive.file} does not match driver-runtime.json (sha256 ${sha256}, expected ${archive.sha256}): refusing it`);
63
+ await mkdir(join2(cache, options.version), { recursive: true });
64
+ const unpacking = await mkdtemp(join2(cache, options.version, `.${platform}-`));
65
+ try {
66
+ await writeFile(join2(unpacking, archive.file), bytes);
67
+ execFileSync("tar", ["-xzf", archive.file], { cwd: unpacking, stdio: "ignore" });
68
+ await rm(join2(unpacking, archive.file));
69
+ await rename(unpacking, folder);
70
+ } catch (error) {
71
+ await rm(unpacking, { recursive: true, force: true });
72
+ if (existsSync(join2(folder, "runtime.json"))) return runtimeIn(folder);
73
+ throw error;
74
+ }
75
+ return runtimeIn(folder);
76
+ }
77
+ async function download(get, url) {
78
+ const response = await get(url);
79
+ if (!response.ok) throw new Error(`GET ${url}: ${String(response.status)} ${response.statusText}`);
80
+ return response;
81
+ }
82
+ function runtimeIn(folder) {
83
+ const { command } = JSON.parse(readFileSync2(join2(folder, "runtime.json"), "utf8"));
84
+ const [program, ...args] = command.map((part) => join2(folder, part));
85
+ return { folder, command: [program, ...args] };
86
+ }
87
+
88
+ // src/driver-session/answer-callout.use-case.ts
89
+ async function answerCallout(request, handlers) {
90
+ try {
91
+ if (request.kind === "hook") {
92
+ const hook = handlers.hooks?.[request.name];
93
+ if (hook === void 0) return { status: "error", error: `this client serves no hook "${request.name}"` };
94
+ return { status: "ok", output: await hook(request.input, request.args, request) };
95
+ }
96
+ if (request.kind === "captcha") {
97
+ const solver = handlers.captchaSolvers?.[request.name];
98
+ if (solver === void 0) return { status: "error", error: `this client serves no captcha solver "${request.name}"` };
99
+ return { status: "ok", output: await solver(request.input, request) };
100
+ }
101
+ const plugin = handlers.accessPlugins?.[request.name];
102
+ if (plugin === void 0) return { status: "error", error: `this client serves no access plugin "${request.name}"` };
103
+ return { status: "ok", output: await plugin(request.input, request) };
104
+ } catch (error) {
105
+ return { status: "error", error: error instanceof Error ? error.message : String(error) };
106
+ }
107
+ }
108
+
109
+ // src/driver-session/open-driver.use-case.ts
110
+ async function openDriver(options = {}) {
111
+ const runtime = options.command === void 0 && options.runtime !== void 0 ? await ensureDriverRuntime(options.runtime) : void 0;
112
+ const command = options.command ?? runtime?.command;
113
+ const driver = startDriverProcess({ ...options, command });
114
+ const routes = /* @__PURE__ */ new Map();
115
+ let closing;
116
+ const handlers = { hooks: options.hooks, captchaSolvers: options.captchaSolvers, accessPlugins: options.accessPlugins };
117
+ const served = {
118
+ hooks: Object.keys(options.hooks ?? {}),
119
+ captchaSolvers: Object.keys(options.captchaSolvers ?? {}),
120
+ accessPlugins: Object.keys(options.accessPlugins ?? {})
121
+ };
122
+ const routed = new EventTarget();
123
+ const routeOf = async (runId) => {
124
+ const known = routes.get(runId);
125
+ if (known !== void 0) return known;
126
+ await once(routed, runId);
127
+ return routes.get(runId);
128
+ };
129
+ const deliver = {
130
+ "work.next": async (route) => ({ item: await route.work?.next() ?? null }),
131
+ "event": (route, message) => route.onEvent?.(message.event),
132
+ "record": (route, message) => route.onRecord?.(withoutRunId(message)),
133
+ "work.done": (route, message) => route.work?.onDone?.(withoutRunId(message)),
134
+ "work.failed": (route, message) => route.work?.onFailed?.(withoutRunId(message)),
135
+ "finished": (route, message) => {
136
+ routes.delete(message.runId);
137
+ route.finish(withoutRunId(message));
138
+ }
139
+ };
140
+ const channel = openLineChannel(driver.output, driver.input, async (method, params) => {
141
+ const message = params;
142
+ if (method === "callout") return await answerCallout(message.request, handlers);
143
+ if (!Object.hasOwn(deliver, method)) return null;
144
+ const answer = await deliver[method](await routeOf(message.runId), message);
145
+ return method === "work.next" ? answer : null;
146
+ });
147
+ const ask = async (method, params) => await channel.request(method, params);
148
+ const info = await ask("initialize", { clientName: options.clientName ?? "@opencraw/driver-client", clientVersion: options.clientVersion ?? "0.0.0", protocolVersion: PROTOCOL_VERSION });
149
+ const start = async (method, params, route) => {
150
+ const { runId } = await ask(method, { ...params, ...served });
151
+ const ending = new EventTarget();
152
+ const finished = (async () => {
153
+ const [event] = await once(ending, "finished");
154
+ return event.detail;
155
+ })();
156
+ routes.set(runId, { ...route, finish: (detail) => {
157
+ ending.dispatchEvent(new CustomEvent("finished", { detail }));
158
+ } });
159
+ routed.dispatchEvent(new Event(runId));
160
+ return {
161
+ runId,
162
+ finished,
163
+ cancel: async () => {
164
+ const answer = await ask("cancel", { runId });
165
+ return answer.cancelled;
166
+ }
167
+ };
168
+ };
169
+ return {
170
+ info,
171
+ validate: async (params) => await ask("validate", params),
172
+ run: async ({ onEvent, onRecord, ...params }) => await start("run", params, { onEvent, onRecord }),
173
+ work: async (work) => {
174
+ const { onEvent, onRecord, next, onDone, onFailed, ...params } = work;
175
+ return await start("work", params, { onEvent, onRecord, work: { next, onDone, onFailed } });
176
+ },
177
+ probe: async (params) => await ask("probe", { ...params, accessPlugins: served.accessPlugins }),
178
+ diff: async (params) => await ask("diff", params),
179
+ export: async (params) => await ask("export", params),
180
+ close: async () => {
181
+ closing ??= (async () => {
182
+ try {
183
+ await ask("shutdown");
184
+ } catch {
185
+ }
186
+ driver.input.end();
187
+ await driver.exited;
188
+ })();
189
+ await closing;
190
+ }
191
+ };
192
+ }
193
+ function withoutRunId(message) {
194
+ const { runId: _runId, ...rest } = message;
195
+ return rest;
196
+ }
197
+ export {
198
+ RELEASES_URL,
199
+ answerCallout,
200
+ ensureDriverRuntime,
201
+ installedDriverCommand,
202
+ openDriver,
203
+ startDriverProcess
204
+ };
205
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1,39 @@
1
+ import type { Readable, Writable } from 'node:stream';
2
+ /** How to start the driver. */
3
+ export interface DriverProcessOptions {
4
+ /** The program and its arguments; default: Node running the installed `@opencraw/driver`'s `opencraw-driver`. */
5
+ command?: readonly [string, ...string[]];
6
+ /** Its environment; default: this process's. */
7
+ env?: NodeJS.ProcessEnv;
8
+ /** Its working directory; default: this process's. */
9
+ cwd?: string;
10
+ /** Where its stderr (its logs) goes; default: this process's stderr. */
11
+ stderr?: 'inherit' | 'ignore' | 'pipe';
12
+ }
13
+ /** A started driver: its pipes, and how it ends. */
14
+ export interface DriverProcess {
15
+ /** Its stdin: messages to it. */
16
+ input: Writable;
17
+ /** Its stdout: messages from it. */
18
+ output: Readable;
19
+ /** Its stderr, when `stderr` was `pipe`. */
20
+ logs?: Readable;
21
+ /** Settles with its exit code (null when a signal ended it). */
22
+ exited: Promise<number | null>;
23
+ /** Ends it at once, without `shutdown`. */
24
+ kill: () => void;
25
+ }
26
+ /**
27
+ * The installed driver's program: the `opencraw-driver` bin of `@opencraw/driver`, run with this Node.
28
+ *
29
+ * @returns The command.
30
+ */
31
+ export declare function installedDriverCommand(): [string, string];
32
+ /**
33
+ * Starts the driver as a child process, its stdin and stdout the protocol's pipes.
34
+ *
35
+ * @param options - The command, environment, working directory and where its logs go.
36
+ * @returns The process.
37
+ */
38
+ export declare function startDriverProcess(options?: DriverProcessOptions): DriverProcess;
39
+ //# sourceMappingURL=driver-process.client.d.ts.map
@@ -0,0 +1,3 @@
1
+ export { installedDriverCommand, startDriverProcess } from './driver-process.client.js';
2
+ export type { DriverProcess, DriverProcessOptions } from './driver-process.client.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,36 @@
1
+ /** Where the driver's releases are: `<base>/driver@<version>/driver-runtime.json` and the archives beside it. */
2
+ export declare const RELEASES_URL = "https://github.com/Open-Craw/OpenCraw/releases/download";
3
+ /** Which runtime to use, and where it may come from. */
4
+ export interface DriverRuntimeOptions {
5
+ /** The driver release (`0.6.0`). */
6
+ version: string;
7
+ /** Default: `~/.cache/opencraw/driver`. */
8
+ cacheDir?: string;
9
+ /** Refuse to download (default: `OPENCRAW_DRIVER_OFFLINE=1`). */
10
+ offline?: boolean;
11
+ /** Default: `<process.platform>-<process.arch>`. */
12
+ platform?: string;
13
+ /** Default: the project's GitHub releases. */
14
+ baseUrl?: string;
15
+ /** Where `OPENCRAW_DRIVER` and `OPENCRAW_DRIVER_OFFLINE` are read. */
16
+ env?: NodeJS.ProcessEnv;
17
+ fetch?: typeof fetch;
18
+ }
19
+ /** A runtime ready to start: its folder and the command, absolute. */
20
+ export interface DriverRuntime {
21
+ folder: string;
22
+ command: [string, ...string[]];
23
+ }
24
+ /**
25
+ * The driver's runtime for this platform, downloaded once into a per-user cache: what lets a client run
26
+ * the driver with no Node of its own. `OPENCRAW_DRIVER` names an unpacked runtime to use as it is. A
27
+ * cached one is used as it is. Otherwise, unless offline, the release's `driver-runtime.json` names this
28
+ * platform's archive; it is downloaded, refused when its SHA-256 differs, unpacked into a temporary
29
+ * folder and moved into the cache in one step, so a half-written runtime is never used.
30
+ *
31
+ * @param options - The version, and where the runtime may come from.
32
+ * @returns The runtime's folder and its command.
33
+ * @throws Error When offline and not cached, when the release has no archive for the platform, or when the archive's hash is wrong.
34
+ */
35
+ export declare function ensureDriverRuntime(options: DriverRuntimeOptions): Promise<DriverRuntime>;
36
+ //# sourceMappingURL=ensure-driver-runtime.use-case.d.ts.map
@@ -0,0 +1,3 @@
1
+ export { ensureDriverRuntime, RELEASES_URL } from './ensure-driver-runtime.use-case.js';
2
+ export type { DriverRuntime, DriverRuntimeOptions } from './ensure-driver-runtime.use-case.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,14 @@
1
+ import type { CalloutRequest, CalloutResponse } from '@opencraw/core';
2
+ import type { ClientHandlers } from './driver-client.contract.js';
3
+ /**
4
+ * Answers a `callout` the driver sent: the handler registered for its kind and name answers it, and
5
+ * what the handler returns is the `ok` answer's output. A handler that throws answers `error` with its
6
+ * message, and a name nothing is registered for answers `error` too, so a run fails the call, not the
7
+ * channel.
8
+ *
9
+ * @param request - Core's callout request, as the driver sent it.
10
+ * @param handlers - What the client serves.
11
+ * @returns The callout response.
12
+ */
13
+ export declare function answerCallout(request: CalloutRequest, handlers: ClientHandlers): Promise<CalloutResponse>;
14
+ //# sourceMappingURL=answer-callout.use-case.d.ts.map
@@ -0,0 +1,68 @@
1
+ import type { AccessCalloutInput, AccessCalloutOutput, CalloutRequest, CaptchaCalloutInput, CaptchaCalloutOutput, CrawlEvent, CrawlReport, WorkReport } from '@opencraw/core';
2
+ import type { DiffParams, DiffResult, ExportParams, ExportResult, FinishedParams, InitializeResult, ProbeParams, RecordParams, RunParams, ValidateParams, ValidateResult, WorkDoneParams, WorkFailedParams, WorkItemMessage, WorkParams } from '@opencraw/driver';
3
+ import type { DriverProcessOptions } from '../driver-process/index.js';
4
+ import type { DriverRuntimeOptions } from '../driver-runtime/index.js';
5
+ /** A hook the client serves: the value the recipe passes, its arguments, and the whole request. */
6
+ export type HookHandler = (input: unknown, args: Record<string, unknown>, request: CalloutRequest) => unknown;
7
+ /** A captcha solver the client serves: the challenge, answered with a `token` or the `text` to type. */
8
+ export type CaptchaHandler = (input: CaptchaCalloutInput, request: CalloutRequest) => CaptchaCalloutOutput | Promise<CaptchaCalloutOutput>;
9
+ /** An access plugin the client serves: a lease (`phase: "lease"`), or the release of one (`phase: "release"`). */
10
+ export type AccessHandler = (input: AccessCalloutInput, request: CalloutRequest) => AccessCalloutOutput | Promise<AccessCalloutOutput>;
11
+ /** What the client serves, by name. Every run and probe may use any of them. */
12
+ export interface ClientHandlers {
13
+ hooks?: Record<string, HookHandler>;
14
+ captchaSolvers?: Record<string, CaptchaHandler>;
15
+ accessPlugins?: Record<string, AccessHandler>;
16
+ }
17
+ /** How to start a driver and talk to it. */
18
+ export interface OpenDriverOptions extends DriverProcessOptions, ClientHandlers {
19
+ /** The name the client gives the driver in `initialize`. */
20
+ clientName?: string;
21
+ clientVersion?: string;
22
+ /** Run the downloaded runtime of this release (no Node needed) instead of the installed `@opencraw/driver`; ignored when `command` is given. */
23
+ runtime?: DriverRuntimeOptions;
24
+ }
25
+ /** What a run streams back, as it happens. */
26
+ export interface RunCallbacks {
27
+ onEvent?: (event: CrawlEvent) => void;
28
+ /** Each record, unless the run has `out`. */
29
+ onRecord?: (record: Omit<RecordParams, 'runId'>) => void;
30
+ }
31
+ /** A run's options: the protocol's, without the names of what the client serves (it serves all it registered). */
32
+ export type RunOptions = Omit<RunParams, 'hooks' | 'captchaSolvers' | 'accessPlugins'> & RunCallbacks;
33
+ /** A worker pool's options: where its items come from, and how each ended. */
34
+ export type WorkOptions = Omit<WorkParams, 'hooks' | 'captchaSolvers' | 'accessPlugins'> & RunCallbacks & {
35
+ /** The next item for a window, waiting until there is one; `null` ends the work. */
36
+ next: () => Promise<WorkItemMessage | null> | WorkItemMessage | null;
37
+ onDone?: (done: Omit<WorkDoneParams, 'runId'>) => void;
38
+ onFailed?: (failed: Omit<WorkFailedParams, 'runId'>) => void;
39
+ };
40
+ /** A probe's options, without the names of the access plugins the client serves. */
41
+ export type ProbeOptions = Omit<ProbeParams, 'accessPlugins'>;
42
+ /** A run (or a worker pool) the driver is crawling. */
43
+ export interface RunHandle<Report> {
44
+ runId: string;
45
+ /** Settles when it ends: its report, or why it could not run (it never rejects). */
46
+ finished: Promise<{
47
+ report?: Report;
48
+ error?: string;
49
+ }>;
50
+ /** Stops it; it still ends through `finished`. */
51
+ cancel: () => Promise<boolean>;
52
+ }
53
+ /** A started driver. */
54
+ export interface OpenCrawDriver {
55
+ /** What the driver said in `initialize`. */
56
+ info: InitializeResult;
57
+ validate: (params: ValidateParams) => Promise<ValidateResult>;
58
+ run: (options: RunOptions) => Promise<RunHandle<CrawlReport>>;
59
+ work: (options: WorkOptions) => Promise<RunHandle<WorkReport>>;
60
+ probe: (options: ProbeOptions) => Promise<Record<string, unknown>>;
61
+ diff: (params: DiffParams) => Promise<DiffResult>;
62
+ export: (params: ExportParams) => Promise<ExportResult>;
63
+ /** Asks for `shutdown` and waits for the process to exit. */
64
+ close: () => Promise<void>;
65
+ }
66
+ /** A `finished` notification, without its run id. */
67
+ export type Finished = Omit<FinishedParams, 'runId'>;
68
+ //# sourceMappingURL=driver-client.contract.d.ts.map
@@ -0,0 +1,4 @@
1
+ export { openDriver } from './open-driver.use-case.js';
2
+ export { answerCallout } from './answer-callout.use-case.js';
3
+ export type { AccessHandler, CaptchaHandler, ClientHandlers, HookHandler, OpenCrawDriver, OpenDriverOptions, ProbeOptions, RunCallbacks, RunHandle, RunOptions, WorkOptions, } from './driver-client.contract.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,13 @@
1
+ import type { OpenCrawDriver, OpenDriverOptions } from './driver-client.contract.js';
2
+ /**
3
+ * Starts a driver and initializes it: the thin client the conformance suite is held to, and a way to
4
+ * drive the engine from another process. Hooks, captcha solvers and access plugins are registered once
5
+ * here, by name; every run, worker pool and probe may use them, and the driver asks for them through
6
+ * `callout` requests. A run streams through its callbacks and settles `finished`.
7
+ *
8
+ * @param options - How to start the driver, and what the client serves.
9
+ * @returns The driver, initialized.
10
+ * @throws RpcFailure When the driver refuses `initialize` (another protocol major).
11
+ */
12
+ export declare function openDriver(options?: OpenDriverOptions): Promise<OpenCrawDriver>;
13
+ //# sourceMappingURL=open-driver.use-case.d.ts.map
@@ -0,0 +1,8 @@
1
+ export { openDriver } from './driver-session/index.js';
2
+ export type { AccessHandler, CaptchaHandler, ClientHandlers, HookHandler, OpenCrawDriver, OpenDriverOptions, ProbeOptions, RunCallbacks, RunHandle, RunOptions, WorkOptions, } from './driver-session/index.js';
3
+ export { ensureDriverRuntime, RELEASES_URL } from './driver-runtime/index.js';
4
+ export type { DriverRuntime, DriverRuntimeOptions } from './driver-runtime/index.js';
5
+ export { installedDriverCommand, startDriverProcess } from './driver-process/index.js';
6
+ export type { DriverProcess, DriverProcessOptions } from './driver-process/index.js';
7
+ export { answerCallout } from './driver-session/index.js';
8
+ //# sourceMappingURL=index.d.ts.map
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@opencraw/driver-client",
3
+ "version": "0.2.10",
4
+ "description": "A thin TypeScript client for OpenCraw's driver: the conformance suite's reference client, and a way to drive the engine from another process",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "smith": {
8
+ "kind": "package",
9
+ "stack": "node-vitest"
10
+ },
11
+ "main": "./dist/index.esm.js",
12
+ "module": "./dist/index.esm.js",
13
+ "types": "./dist/src/index.d.ts",
14
+ "exports": {
15
+ "./package.json": "./package.json",
16
+ ".": {
17
+ "types": "./dist/src/index.d.ts",
18
+ "import": "./dist/index.esm.js",
19
+ "default": "./dist/index.esm.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "!**/*.tsbuildinfo",
25
+ "!**/*.d.ts.map",
26
+ "!**/*.js.map"
27
+ ],
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "scripts": {
32
+ "build": "esbuild src/index.ts --bundle --packages=external --platform=node --format=esm --outdir=dist --out-extension:.js=.esm.js --sourcemap && tsc -p tsconfig.build.json && node ../../declaration-specifiers.mjs dist/src",
33
+ "typecheck": "tsc -p tsconfig.json",
34
+ "lint": "eslint .",
35
+ "test": "vitest run"
36
+ },
37
+ "dependencies": {
38
+ "@opencraw/core": "^0.5.0",
39
+ "@opencraw/driver": "^0.7.10"
40
+ }
41
+ }