@opencraw/core 0.1.2 → 0.1.4

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.
Files changed (195) hide show
  1. package/README.md +1 -1
  2. package/dist/access/access-broker.use-case.d.ts +43 -0
  3. package/dist/access/access-config.error.d.ts +5 -0
  4. package/dist/access/access-config.repository.d.ts +11 -0
  5. package/dist/access/access-json-schema.mapper.d.ts +8 -0
  6. package/dist/access/access-plugin.contract.d.ts +48 -0
  7. package/dist/access/access-preset.store.d.ts +19 -0
  8. package/dist/access/access-profile.contract.d.ts +95 -0
  9. package/dist/access/index.d.ts +11 -0
  10. package/dist/access/render-access.mapper.d.ts +41 -0
  11. package/dist/access/session-id.algorithm.d.ts +8 -0
  12. package/dist/api-steps/extract-from-document.use-case.d.ts +41 -0
  13. package/dist/api-steps/index.d.ts +4 -0
  14. package/dist/api-steps/run-api-step.use-case.d.ts +20 -0
  15. package/dist/api-steps/send-request.use-case.d.ts +23 -0
  16. package/dist/browser-session/browser-profile.store.d.ts +52 -0
  17. package/dist/browser-session/browser-session.config.d.ts +21 -0
  18. package/dist/browser-session/browser.client.d.ts +75 -0
  19. package/dist/browser-session/index.d.ts +6 -0
  20. package/dist/captcha/captcha-budget.model.d.ts +21 -0
  21. package/dist/captcha/captcha-detection.client.d.ts +28 -0
  22. package/dist/captcha/captcha-guard.use-case.d.ts +64 -0
  23. package/dist/captcha/captcha-solver-registry.store.d.ts +19 -0
  24. package/dist/captcha/captcha-solver.contract.d.ts +47 -0
  25. package/dist/captcha/captcha.error.d.ts +13 -0
  26. package/dist/captcha/index.d.ts +10 -0
  27. package/dist/captcha/resolve-captcha.use-case.d.ts +40 -0
  28. package/dist/crawl-events/crawl-event.contract.d.ts +169 -0
  29. package/dist/crawl-events/event-bus.store.d.ts +10 -0
  30. package/dist/crawl-events/index.d.ts +4 -0
  31. package/dist/crawl-events/trace-line.mapper.d.ts +14 -0
  32. package/dist/crawl-execution/bootstrap-session.use-case.d.ts +79 -0
  33. package/dist/crawl-execution/crawl-options.config.d.ts +67 -0
  34. package/dist/crawl-execution/crawl-report.model.d.ts +33 -0
  35. package/dist/crawl-execution/create-crawler.use-case.d.ts +20 -0
  36. package/dist/crawl-execution/index.d.ts +8 -0
  37. package/dist/crawl-execution/rotating-runner.use-case.d.ts +66 -0
  38. package/dist/crawl-execution/run-crawl.use-case.d.ts +17 -0
  39. package/dist/crawl-execution/run-input-recipe.use-case.d.ts +51 -0
  40. package/dist/deck-document/deck-document.model.d.ts +58 -0
  41. package/dist/deck-document/deck-table.algorithm.d.ts +35 -0
  42. package/dist/deck-document/index.d.ts +6 -0
  43. package/dist/deck-document/read-pptx.client.d.ts +16 -0
  44. package/dist/docx-document/index.d.ts +2 -0
  45. package/dist/docx-document/read-docx-html.client.d.ts +23 -0
  46. package/dist/extraction-scope/extraction-scope.model.d.ts +77 -0
  47. package/dist/extraction-scope/index.d.ts +5 -0
  48. package/dist/extraction-scope/live-element.model.d.ts +28 -0
  49. package/dist/hooks/hook-registry.store.d.ts +16 -0
  50. package/dist/hooks/hook.contract.d.ts +17 -0
  51. package/dist/hooks/hook.error.d.ts +7 -0
  52. package/dist/hooks/index.d.ts +4 -0
  53. package/dist/http-session/http-response.contract.d.ts +58 -0
  54. package/dist/http-session/http.client.d.ts +42 -0
  55. package/dist/http-session/index.d.ts +5 -0
  56. package/dist/http-session/text-decoding.algorithm.d.ts +35 -0
  57. package/dist/index.esm.js +1410 -95
  58. package/dist/markdown-document/index.d.ts +3 -0
  59. package/dist/markdown-document/read-markdown.client.d.ts +39 -0
  60. package/dist/output-mapping/coerce-field.mapper.d.ts +19 -0
  61. package/dist/output-mapping/generated-field.mapper.d.ts +16 -0
  62. package/dist/output-mapping/index.d.ts +9 -0
  63. package/dist/output-mapping/map-record.use-case.d.ts +27 -0
  64. package/dist/output-mapping/mapping.error.d.ts +17 -0
  65. package/dist/output-mapping/missing-value.policy.d.ts +14 -0
  66. package/dist/output-mapping/output-field.validator.d.ts +10 -0
  67. package/dist/output-mapping/output-record.model.d.ts +20 -0
  68. package/dist/pdf-document/index.d.ts +7 -0
  69. package/dist/pdf-document/pdf-document.model.d.ts +51 -0
  70. package/dist/pdf-document/pdf-table.algorithm.d.ts +43 -0
  71. package/dist/pdf-document/read-pdf.client.d.ts +18 -0
  72. package/dist/pdf-document/row-assembly.algorithm.d.ts +26 -0
  73. package/dist/recipe-loading/index.d.ts +9 -0
  74. package/dist/recipe-loading/load-recipe-set.use-case.d.ts +45 -0
  75. package/dist/recipe-loading/read-recipe-source.use-case.d.ts +14 -0
  76. package/dist/recipe-loading/recipe-binding.error.d.ts +14 -0
  77. package/dist/recipe-loading/recipe-binding.validator.d.ts +34 -0
  78. package/dist/recipe-loading/recipe-file.repository.d.ts +11 -0
  79. package/dist/recipe-loading/recipe-set.model.d.ts +12 -0
  80. package/dist/recipe-loading/recipe-source.contract.d.ts +28 -0
  81. package/dist/recipe-loading/recipe-text.mapper.d.ts +14 -0
  82. package/dist/recipe-schema/index.d.ts +15 -0
  83. package/dist/recipe-schema/input-recipe.contract.d.ts +156 -0
  84. package/dist/recipe-schema/json-schema.mapper.d.ts +15 -0
  85. package/dist/recipe-schema/output-recipe.contract.d.ts +47 -0
  86. package/dist/recipe-schema/recipe-kind.enum.d.ts +35 -0
  87. package/dist/recipe-schema/recipe-validation.error.d.ts +17 -0
  88. package/dist/recipe-schema/recipe.validator.d.ts +28 -0
  89. package/dist/recipe-schema/step.contract.d.ts +206 -0
  90. package/dist/recipe-schema/transform-rule.contract.d.ts +120 -0
  91. package/dist/record-diff/index.d.ts +4 -0
  92. package/dist/record-diff/record-diff.algorithm.d.ts +82 -0
  93. package/dist/record-diff/records-file.repository.d.ts +10 -0
  94. package/dist/record-sink/dedupe.policy.d.ts +29 -0
  95. package/dist/record-sink/index.d.ts +9 -0
  96. package/dist/record-sink/json-lines-sink.repository.d.ts +19 -0
  97. package/dist/record-sink/memory-sink.repository.d.ts +9 -0
  98. package/dist/record-sink/record-sink.contract.d.ts +17 -0
  99. package/dist/selection/html-selector.algorithm.d.ts +19 -0
  100. package/dist/selection/index.d.ts +8 -0
  101. package/dist/selection/json-path.algorithm.d.ts +9 -0
  102. package/dist/selection/json-text.algorithm.d.ts +58 -0
  103. package/dist/selection/regex.algorithm.d.ts +12 -0
  104. package/dist/selection/take-value.mapper.d.ts +27 -0
  105. package/dist/src/access/access-profile.contract.d.ts +4 -0
  106. package/dist/src/access/index.d.ts +1 -1
  107. package/dist/src/api-steps/extract-from-document.use-case.d.ts +5 -5
  108. package/dist/src/api-steps/send-request.use-case.d.ts +3 -2
  109. package/dist/src/browser-session/browser-profile.store.d.ts +52 -0
  110. package/dist/src/browser-session/browser.client.d.ts +8 -0
  111. package/dist/src/browser-session/index.d.ts +1 -0
  112. package/dist/src/crawl-events/crawl-event.contract.d.ts +8 -0
  113. package/dist/src/crawl-execution/bootstrap-session.use-case.d.ts +23 -2
  114. package/dist/src/crawl-execution/crawl-options.config.d.ts +27 -0
  115. package/dist/src/crawl-execution/rotating-runner.use-case.d.ts +9 -0
  116. package/dist/src/crawl-execution/run-crawl.use-case.d.ts +6 -2
  117. package/dist/src/crawl-execution/run-input-recipe.use-case.d.ts +11 -3
  118. package/dist/src/docx-document/index.d.ts +2 -0
  119. package/dist/src/docx-document/read-docx-html.client.d.ts +23 -0
  120. package/dist/src/extraction-scope/extraction-scope.model.d.ts +2 -1
  121. package/dist/src/http-session/http-response.contract.d.ts +2 -1
  122. package/dist/src/index.d.ts +9 -4
  123. package/dist/src/markdown-document/index.d.ts +1 -1
  124. package/dist/src/markdown-document/read-markdown.client.d.ts +10 -0
  125. package/dist/src/recipe-schema/index.d.ts +2 -2
  126. package/dist/src/recipe-schema/input-recipe.contract.d.ts +24 -1
  127. package/dist/src/recipe-schema/recipe-kind.enum.d.ts +1 -1
  128. package/dist/src/recipe-schema/step.contract.d.ts +4 -0
  129. package/dist/src/record-diff/index.d.ts +4 -0
  130. package/dist/src/record-diff/record-diff.algorithm.d.ts +82 -0
  131. package/dist/src/record-diff/records-file.repository.d.ts +10 -0
  132. package/dist/src/record-sink/dedupe.policy.d.ts +19 -7
  133. package/dist/src/record-sink/index.d.ts +1 -0
  134. package/dist/src/selection/html-selector.algorithm.d.ts +2 -1
  135. package/dist/src/step-flow/for-each.use-case.d.ts +4 -2
  136. package/dist/src/step-flow/host-throttle.policy.d.ts +49 -0
  137. package/dist/src/step-flow/index.d.ts +5 -0
  138. package/dist/src/step-flow/run-gate.policy.d.ts +12 -1
  139. package/dist/src/step-flow/step-runner.contract.d.ts +13 -0
  140. package/dist/src/step-flow/transport-retry.policy.d.ts +76 -0
  141. package/dist/src/web-steps/navigate.use-case.d.ts +3 -2
  142. package/dist/src/web-steps/run-web-step.use-case.d.ts +8 -1
  143. package/dist/src/xml-document/index.d.ts +6 -0
  144. package/dist/src/xml-document/xml-document.model.d.ts +13 -0
  145. package/dist/src/xml-document/xml-parser.client.d.ts +49 -0
  146. package/dist/src/xml-document/xpath.algorithm.d.ts +30 -0
  147. package/dist/step-flow/block-rule.policy.d.ts +21 -0
  148. package/dist/step-flow/blocked.error.d.ts +9 -0
  149. package/dist/step-flow/for-each.use-case.d.ts +20 -0
  150. package/dist/step-flow/host-throttle.policy.d.ts +49 -0
  151. package/dist/step-flow/index.d.ts +15 -0
  152. package/dist/step-flow/paginate.use-case.d.ts +17 -0
  153. package/dist/step-flow/retry.policy.d.ts +21 -0
  154. package/dist/step-flow/run-gate.policy.d.ts +50 -0
  155. package/dist/step-flow/run-steps.use-case.d.ts +39 -0
  156. package/dist/step-flow/step-failure.error.d.ts +14 -0
  157. package/dist/step-flow/step-runner.contract.d.ts +52 -0
  158. package/dist/step-flow/transport-retry.policy.d.ts +76 -0
  159. package/dist/template/expression.algorithm.d.ts +53 -0
  160. package/dist/template/index.d.ts +7 -0
  161. package/dist/template/template.algorithm.d.ts +53 -0
  162. package/dist/template/value-path.algorithm.d.ts +29 -0
  163. package/dist/template/value-text.algorithm.d.ts +18 -0
  164. package/dist/transformation/apply-transform-chain.use-case.d.ts +17 -0
  165. package/dist/transformation/collection.algorithm.d.ts +15 -0
  166. package/dist/transformation/currency.algorithm.d.ts +15 -0
  167. package/dist/transformation/date.algorithm.d.ts +13 -0
  168. package/dist/transformation/index.d.ts +10 -0
  169. package/dist/transformation/lookup.algorithm.d.ts +24 -0
  170. package/dist/transformation/number.algorithm.d.ts +30 -0
  171. package/dist/transformation/string.algorithm.d.ts +18 -0
  172. package/dist/transformation/transform-registry.store.d.ts +36 -0
  173. package/dist/transformation/transform.error.d.ts +8 -0
  174. package/dist/transformation/url.algorithm.d.ts +20 -0
  175. package/dist/web-steps/evaluate-script.use-case.d.ts +10 -0
  176. package/dist/web-steps/extract-from-page.use-case.d.ts +10 -0
  177. package/dist/web-steps/index.d.ts +2 -0
  178. package/dist/web-steps/interact.use-case.d.ts +36 -0
  179. package/dist/web-steps/navigate.use-case.d.ts +15 -0
  180. package/dist/web-steps/run-web-step.use-case.d.ts +37 -0
  181. package/dist/web-steps/snapshot-elements.use-case.d.ts +13 -0
  182. package/dist/workbook-document/csv-parser.algorithm.d.ts +26 -0
  183. package/dist/workbook-document/csv-workbook.mapper.d.ts +24 -0
  184. package/dist/workbook-document/grid-table.algorithm.d.ts +53 -0
  185. package/dist/workbook-document/html-tables.mapper.d.ts +14 -0
  186. package/dist/workbook-document/index.d.ts +9 -0
  187. package/dist/workbook-document/read-xlsx.client.d.ts +18 -0
  188. package/dist/workbook-document/workbook-document.model.d.ts +51 -0
  189. package/dist/xml-document/index.d.ts +6 -0
  190. package/dist/xml-document/xml-document.model.d.ts +13 -0
  191. package/dist/xml-document/xml-parser.client.d.ts +49 -0
  192. package/dist/xml-document/xpath.algorithm.d.ts +30 -0
  193. package/dist/yaml-document/index.d.ts +3 -0
  194. package/dist/yaml-document/read-yaml.client.d.ts +25 -0
  195. package/package.json +4 -2
package/README.md CHANGED
@@ -16,7 +16,7 @@ npx playwright install chromium # web recipes and browser bootstraps only
16
16
  | `loadRecipes(source)` | Reads, validates and binds recipes from one source holding all of them, the output recipe found by its `kind`. The source is any of the forms below. Throws `RecipeValidationError` / `RecipeBindingError` with every problem and its JSON path. |
17
17
  | `loadRecipeSet({ output, inputs })` | The same, with the output recipe given apart; each part is any of the forms below. |
18
18
  | `readRecipeSource(source)` | Decodes recipes without validating them, each with where it came from, for tooling. |
19
- | `createCrawler(options)` | Builds an engine: `hooks`, `sink` (`memorySink()` default, `jsonLinesSink(path, { append? })`), `onEvent`, `browser` settings, `dedupe` (`run` / `recipe` / `off`), `onRecipeError` (`continue` / `stop`), `resume` (skip keys the sink already has), `access` + `accessPlugins` (proxy profiles, see [access.md](../../docs/recipes/access.md)), `captchaSolvers` (see [captcha.md](../../docs/recipes/captcha.md)). |
19
+ | `createCrawler(options)` | Builds an engine: `hooks`, `sink` (`memorySink()` default, `jsonLinesSink(path, { append? })`), `onEvent`, `browser` settings, `dedupe` (`run` / `recipe` / `off`), `onRecipeError` (`continue` / `stop`), `resume` (skip keys the sink already has), `access` + `accessPlugins` (proxy profiles, see [access.md](../../docs/recipes/access.md)), `captchaSolvers` (see [captcha.md](../../docs/recipes/captcha.md)), `throttle` (per-site politeness), `retry` (requests that fail in passing), `parallel` (input recipes at once), `profilesDir` (persistent browser profiles). |
20
20
  | `loadAccessConfig(path)`, `AccessBroker`, `ACCESS_PRESETS` | Access configs: load and validate one, lease a profile outside a crawl (the cli's `probe` does), list the provider presets. |
21
21
  | `crawler.run(set)` | Runs every input recipe in sequence; returns a `CrawlReport`. |
22
22
  | `crawler.close()` | Closes the browser, if one was launched. |
@@ -0,0 +1,43 @@
1
+ import type { AccessLease, AccessPlugin, LeaseRequest } from './access-plugin.contract.js';
2
+ type Env = Record<string, string | undefined>;
3
+ /**
4
+ * Turns the runner's access config into leases: one per recipe run, shared by
5
+ * its bootstrap and its runner, and a new one on every rotation. The config is
6
+ * checked when the broker is built (profiles, presets, their parameters,
7
+ * plugin names); environment variables are checked when a profile is leased,
8
+ * so a config listing several providers only needs the variables of the one in
9
+ * use.
10
+ */
11
+ export declare class AccessBroker {
12
+ private readonly env;
13
+ private readonly config;
14
+ private readonly plugins;
15
+ private readonly poolCursor;
16
+ /**
17
+ * @param config - The access config; none means every recipe goes direct.
18
+ * @param plugins - Plugins `{ kind: 'plugin' }` profiles may name.
19
+ * @param env - Where `{{env.X}}` reads from; the process environment by default.
20
+ * @throws AccessConfigError when the config cannot work.
21
+ */
22
+ constructor(config?: unknown, plugins?: readonly AccessPlugin[], env?: Env);
23
+ /** The profile names, for messages and tools. */
24
+ get profileNames(): string[];
25
+ /**
26
+ * A lease for one recipe run.
27
+ *
28
+ * @param request - The recipe, the profile it asks for, country and stickiness.
29
+ * @returns How the run reaches the network.
30
+ * @throws AccessConfigError for an unknown profile or a missing environment variable.
31
+ */
32
+ lease(request: LeaseRequest): Promise<AccessLease>;
33
+ }
34
+ /**
35
+ * An endpoint as events may show it: scheme, host and path, without the
36
+ * credentials or tokens remote-browser URLs carry.
37
+ *
38
+ * @param endpoint - A proxy server or CDP endpoint.
39
+ * @returns The redacted form.
40
+ */
41
+ export declare function redactEndpoint(endpoint: string): string;
42
+ export {};
43
+ //# sourceMappingURL=access-broker.use-case.d.ts.map
@@ -0,0 +1,5 @@
1
+ /** An access config that cannot work: a bad profile, an unknown preset or plugin, a missing parameter or environment variable. */
2
+ export declare class AccessConfigError extends Error {
3
+ readonly name = "AccessConfigError";
4
+ }
5
+ //# sourceMappingURL=access-config.error.d.ts.map
@@ -0,0 +1,11 @@
1
+ import type { AccessConfig } from './access-profile.contract.js';
2
+ /**
3
+ * Reads an access config file. Secrets stay out of it: profiles reference
4
+ * them as `{{env.NAME}}`, resolved when a profile is leased.
5
+ *
6
+ * @param path - A JSON file.
7
+ * @returns The validated config.
8
+ * @throws AccessConfigError when the file is not JSON or not a valid config.
9
+ */
10
+ export declare function loadAccessConfig(path: string): Promise<AccessConfig>;
11
+ //# sourceMappingURL=access-config.repository.d.ts.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The JSON Schema for access config files, for editors: point `$schema` at
3
+ * `schemas/access-config.schema.json`.
4
+ *
5
+ * @returns A draft 2020-12 document.
6
+ */
7
+ export declare function accessConfigJsonSchema(): Record<string, unknown>;
8
+ //# sourceMappingURL=access-json-schema.mapper.d.ts.map
@@ -0,0 +1,48 @@
1
+ import type { BlockableResource, ProxySettings } from './access-profile.contract.js';
2
+ /** What a recipe run asks the access layer for. */
3
+ export interface LeaseRequest {
4
+ recipeId: string;
5
+ /** The profile to use; the config's default when omitted, `direct` when there is none. */
6
+ profile?: string;
7
+ /** ISO country code the recipe wants its traffic to come from. */
8
+ country?: string;
9
+ /** Overrides the profile's `session.rotate`: `true` keeps one IP for the run, `false` lets the provider rotate. */
10
+ sticky?: boolean;
11
+ /** 1 for the first lease of a run, higher after a rotation. */
12
+ attempt?: number;
13
+ }
14
+ /** How one recipe run reaches the network: applied to its browser context, its HTTP context and its bootstrap alike. */
15
+ export interface AccessLease {
16
+ profile: string;
17
+ kind: string;
18
+ proxy?: ProxySettings;
19
+ /** The sticky session id, when the lease has one. */
20
+ session?: string;
21
+ headers?: Record<string, string>;
22
+ ignoreHTTPSErrors?: boolean;
23
+ blockResources?: BlockableResource[];
24
+ /** A remote browser to connect to instead of launching one (web recipes and bootstraps only). */
25
+ cdp?: {
26
+ endpoint: string;
27
+ headers?: Record<string, string>;
28
+ };
29
+ /** Called when the run ends or rotates away from this lease. */
30
+ release?: () => Promise<void>;
31
+ }
32
+ /** What a plugin receives: the request plus its profile's options, every string rendered. */
33
+ export interface PluginLeaseRequest extends LeaseRequest {
34
+ profile: string;
35
+ options: Record<string, unknown>;
36
+ attempt: number;
37
+ }
38
+ /**
39
+ * The extension point for access that config cannot express: a remote browser
40
+ * whose URL comes from a REST call, a proxy list fetched from an API, a
41
+ * rotating credential. Registered on the crawler, referenced by name from a
42
+ * `{ kind: 'plugin', name }` profile.
43
+ */
44
+ export interface AccessPlugin {
45
+ name: string;
46
+ lease: (request: PluginLeaseRequest) => Promise<Omit<AccessLease, 'profile' | 'kind'>> | Omit<AccessLease, 'profile' | 'kind'>;
47
+ }
48
+ //# sourceMappingURL=access-plugin.contract.d.ts.map
@@ -0,0 +1,19 @@
1
+ import type { ProxyProfile } from './access-profile.contract.js';
2
+ /**
3
+ * Provider presets. Providers all speak plain HTTP proxy with basic auth; they
4
+ * differ in where targeting and session tokens go (username, password, headers)
5
+ * and in whether they intercept HTTPS. A preset is only that knowledge, as
6
+ * templates: adding a provider is adding an entry here, never code.
7
+ *
8
+ * Templates read `params.*` (the profile's parameters, which may themselves
9
+ * read `env.*`), `country` and `session` (absent when the lease is not sticky).
10
+ */
11
+ export interface AccessPreset {
12
+ /** One line for docs and error messages. */
13
+ description: string;
14
+ /** `params` the profile must set. */
15
+ requiredParams: string[];
16
+ profile: Omit<ProxyProfile, 'kind' | 'preset' | 'params'>;
17
+ }
18
+ export declare const ACCESS_PRESETS: Record<string, AccessPreset>;
19
+ //# sourceMappingURL=access-preset.store.d.ts.map
@@ -0,0 +1,95 @@
1
+ import { z } from 'zod';
2
+ import type { ThrottleConfig } from '../step-flow/index.js';
3
+ /**
4
+ * Where a crawl's traffic goes. Profiles live in the runner's access config,
5
+ * never in a recipe: they hold the user's accounts. Every string may use
6
+ * `{{ }}` templates over `env.*` (the process environment), `params.*` (the
7
+ * profile's own parameters), `session`, `country` and `recipe.id`.
8
+ */
9
+ /** A proxy in Playwright's shape; used for browser contexts and HTTP request contexts alike. */
10
+ export interface ProxySettings {
11
+ server: string;
12
+ username?: string;
13
+ password?: string;
14
+ /** Comma-separated hosts that skip the proxy. */
15
+ bypass?: string;
16
+ }
17
+ /** Resource types a page may skip loading, to save bandwidth on per-GB proxies. */
18
+ export declare const BLOCKABLE_RESOURCES: readonly ['image', 'media', 'font', 'stylesheet', 'script', 'texttrack', 'xhr', 'fetch', 'eventsource', 'websocket', 'manifest', 'other'];
19
+ export type BlockableResource = typeof BLOCKABLE_RESOURCES[number];
20
+ /** How a sticky session id is generated: character class and length, such as `alnum8` or `digits6`. */
21
+ export declare const SESSION_ID_FORMAT: RegExp;
22
+ export interface ProxySessionSettings {
23
+ /** Default `alnum10`. Providers constrain it: IPRoyal wants exactly 8 characters, NetNut digits. */
24
+ idFormat?: string;
25
+ /** `per-recipe` (default): one sticky session per recipe run. `per-request`: no session id, the provider rotates. */
26
+ rotate?: 'per-recipe' | 'per-request';
27
+ }
28
+ interface ProfileCommon {
29
+ /** Headers sent with every request: provider controls such as `x-oxylabs-geo-location`. Templates allowed; empty values are dropped. */
30
+ headers?: Record<string, string>;
31
+ /** Needed by providers that intercept HTTPS (unblockers, Bright Data residential). */
32
+ ignoreHTTPSErrors?: boolean;
33
+ /** Resource types pages skip (web mode). */
34
+ blockResources?: BlockableResource[];
35
+ }
36
+ export interface DirectProfile {
37
+ kind: 'direct';
38
+ }
39
+ export interface ProxyProfile extends ProfileCommon {
40
+ kind: 'proxy';
41
+ /** A built-in preset that fills `server`, `username`, `password`, `headers` and defaults; explicit fields override it. */
42
+ preset?: string;
43
+ /** Values the preset's templates read as `params.*`. */
44
+ params?: Record<string, string>;
45
+ server?: string;
46
+ username?: string;
47
+ password?: string;
48
+ bypass?: string;
49
+ session?: ProxySessionSettings;
50
+ }
51
+ export interface PoolProfile extends ProfileCommon {
52
+ kind: 'pool';
53
+ proxies: ProxySettings[];
54
+ /** Default `round-robin`. The pool advances per lease: per recipe run, and on every rotation. */
55
+ rotate?: 'round-robin' | 'random';
56
+ }
57
+ /**
58
+ * A remote browser reached over the Chrome DevTools Protocol (Bright Data
59
+ * Browser API, Browserless, Oxylabs, Zyte...): web recipes and bootstraps run
60
+ * in it, and it handles IPs, fingerprints and challenges. Api recipes cannot
61
+ * use it.
62
+ */
63
+ export interface CdpProfile {
64
+ kind: 'cdp';
65
+ /** `wss://...` or `http://host:port`; a template, usually carrying the token or credentials. */
66
+ endpoint: string;
67
+ /** Headers sent with the connection, such as `Authorization`. Templates. */
68
+ headers?: Record<string, string>;
69
+ params?: Record<string, string>;
70
+ session?: {
71
+ idFormat?: string;
72
+ };
73
+ blockResources?: BlockableResource[];
74
+ }
75
+ export interface PluginProfile {
76
+ kind: 'plugin';
77
+ /** The name an `AccessPlugin` was registered under. */
78
+ name: string;
79
+ /** Passed to the plugin with every string rendered. */
80
+ options?: Record<string, unknown>;
81
+ }
82
+ export type AccessProfile = DirectProfile | ProxyProfile | PoolProfile | CdpProfile | PluginProfile;
83
+ /** The runner's access config: named profiles and the one used when a recipe names none. */
84
+ export interface AccessConfig {
85
+ $schema?: string;
86
+ profiles: Record<string, AccessProfile>;
87
+ default?: string;
88
+ /** How gently each site is crawled, across every recipe: `{ delayMs?, concurrency?, domains? }`. */
89
+ throttle?: ThrottleConfig;
90
+ }
91
+ export declare const accessProfileSchema: z.ZodType<AccessProfile>;
92
+ export declare const throttleConfigSchema: z.ZodType<ThrottleConfig>;
93
+ export declare const accessConfigSchema: z.ZodType<AccessConfig>;
94
+ export {};
95
+ //# sourceMappingURL=access-profile.contract.d.ts.map
@@ -0,0 +1,11 @@
1
+ export { AccessBroker, redactEndpoint } from './access-broker.use-case.js';
2
+ export { loadAccessConfig } from './access-config.repository.js';
3
+ export { AccessConfigError } from './access-config.error.js';
4
+ export { ACCESS_PRESETS } from './access-preset.store.js';
5
+ export type { AccessPreset } from './access-preset.store.js';
6
+ export { accessConfigSchema, accessProfileSchema, throttleConfigSchema, BLOCKABLE_RESOURCES } from './access-profile.contract.js';
7
+ export type { AccessConfig, AccessProfile, ProxyProfile, PoolProfile, CdpProfile, PluginProfile, DirectProfile, ProxySettings, BlockableResource } from './access-profile.contract.js';
8
+ export type { AccessPlugin, AccessLease, LeaseRequest, PluginLeaseRequest } from './access-plugin.contract.js';
9
+ export { newSessionId } from './session-id.algorithm.js';
10
+ export { accessConfigJsonSchema } from './access-json-schema.mapper.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,41 @@
1
+ /** What access templates can read. */
2
+ export interface AccessTemplateContext {
3
+ env: Record<string, string | undefined>;
4
+ params?: Record<string, string>;
5
+ session?: string;
6
+ country?: string;
7
+ recipe?: {
8
+ id: string;
9
+ };
10
+ }
11
+ /**
12
+ * Renders one access template. An `env.*` path that is not set fails loudly:
13
+ * an empty password would otherwise reach the provider and fail as a 407.
14
+ *
15
+ * @param template - The text.
16
+ * @param context - What `{{ }}` can read.
17
+ * @param where - The profile field, for the error.
18
+ * @returns The rendered text.
19
+ * @throws AccessConfigError naming the missing environment variable.
20
+ */
21
+ export declare function renderAccessText(template: string, context: AccessTemplateContext, where: string): string;
22
+ /**
23
+ * Renders every string inside a value, keeping its shape.
24
+ *
25
+ * @param value - Plugin options, a header map...
26
+ * @param context - What `{{ }}` can read.
27
+ * @param where - For errors.
28
+ * @returns The rendered copy.
29
+ */
30
+ export declare function renderAccessDeep(value: unknown, context: AccessTemplateContext, where: string): unknown;
31
+ /**
32
+ * Renders a header map and drops headers that render empty, so a template
33
+ * such as `{{country ? upper(country) : ''}}` can leave a header out.
34
+ *
35
+ * @param headers - The templated headers.
36
+ * @param context - What `{{ }}` can read.
37
+ * @param where - For errors.
38
+ * @returns The headers to send, or `undefined` when none remain.
39
+ */
40
+ export declare function renderHeaders(headers: Record<string, string> | undefined, context: AccessTemplateContext, where: string): Record<string, string> | undefined;
41
+ //# sourceMappingURL=render-access.mapper.d.ts.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * A new random session id in a provider's format.
3
+ *
4
+ * @param format - `alnum8`, `digits6`, `hex16`...
5
+ * @returns The id. A `digits` id never starts with 0, so providers that read it as a number keep its length.
6
+ */
7
+ export declare function newSessionId(format?: string): string;
8
+ //# sourceMappingURL=session-id.algorithm.d.ts.map
@@ -0,0 +1,41 @@
1
+ import type { ExtractionScope, ScopeDocument } from '../extraction-scope/index.js';
2
+ import type { ExtractStep } from '../recipe-schema/index.js';
3
+ /**
4
+ * Runs an `extract` step against a static document: the value bound under
5
+ * `from`, else the scope's current document. `css` reads HTML (or XML),
6
+ * `xpath` reads XML (a feed, a sitemap) or HTML parsed as a browser parses
7
+ * it, `jsonpath` reads JSON (or a read PDF, workbook or deck as data), `table`
8
+ * reads the tables of a PDF, a workbook (a spreadsheet, a CSV), a deck (a
9
+ * presentation) or HTML (its `<table>`s), `regex` reads any document as text.
10
+ *
11
+ * A `jsonpath` extract whose `from` is text parses that text as JSON, and a
12
+ * list of texts (every `<script type="application/ld+json">` of a page) becomes
13
+ * an array of the entries that parse, so `$[*].actors[*].name` finds the block
14
+ * that has actors wherever it sits.
15
+ *
16
+ * @param step - The extract step.
17
+ * @param scope - Where the document and the result live.
18
+ * @throws NoMatchError when a single extract matches nothing.
19
+ */
20
+ export declare function extractFromDocument(step: ExtractStep, scope: ExtractionScope): void;
21
+ /**
22
+ * A selector may carry `{{ }}` placeholders (a trim name, an id): they render
23
+ * against the scope before the selector runs.
24
+ *
25
+ * @param selector - The recipe's selector.
26
+ * @param scope - The current scope.
27
+ * @returns The selector to run.
28
+ */
29
+ export declare function renderSelector(selector: string, scope: ExtractionScope): string;
30
+ /**
31
+ * The tables a `table` extract finds in a document: a PDF's, a workbook's, a
32
+ * deck's, or an HTML document's `<table>`s (a fetched page, rendered Markdown,
33
+ * a live page's content).
34
+ *
35
+ * @param document - The document.
36
+ * @param step - The extract step.
37
+ * @param scope - Where its selector renders.
38
+ * @returns The tables.
39
+ */
40
+ export declare function tablesIn(document: ScopeDocument, step: ExtractStep, scope: ExtractionScope): unknown[];
41
+ //# sourceMappingURL=extract-from-document.use-case.d.ts.map
@@ -0,0 +1,4 @@
1
+ export { ApiStepRunner } from './run-api-step.use-case.js';
2
+ export { extractFromDocument, renderSelector, tablesIn } from './extract-from-document.use-case.js';
3
+ export { sendRequest, documentValue } from './send-request.use-case.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,20 @@
1
+ import type { EventBus } from '../crawl-events/index.js';
2
+ import type { ExtractionScope } from '../extraction-scope/index.js';
3
+ import type { HttpSender } from '../http-session/index.js';
4
+ import type { InputRecipe, PaginateNext, Step } from '../recipe-schema/index.js';
5
+ import { RunGate } from '../step-flow/index.js';
6
+ import type { NextPageResult, StepRunner } from '../step-flow/index.js';
7
+ /** Runs api-mode leaf steps against an HTTP sender. */
8
+ export declare class ApiStepRunner implements StepRunner {
9
+ private readonly client;
10
+ private readonly recipe;
11
+ private readonly events;
12
+ private readonly gate;
13
+ constructor(client: HttpSender & {
14
+ dispose?: () => Promise<void>;
15
+ }, recipe: InputRecipe, events: EventBus, gate?: RunGate);
16
+ runLeaf(step: Step, scope: ExtractionScope): Promise<void>;
17
+ nextPage(next: PaginateNext, scope: ExtractionScope): Promise<NextPageResult>;
18
+ dispose(): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=run-api-step.use-case.d.ts.map
@@ -0,0 +1,23 @@
1
+ import type { EventBus } from '../crawl-events/index.js';
2
+ import type { ExtractionScope } from '../extraction-scope/index.js';
3
+ import type { HttpBody, HttpSender } from '../http-session/index.js';
4
+ import type { InputRecipe, RequestStep } from '../recipe-schema/index.js';
5
+ import type { RunGate } from '../step-flow/index.js';
6
+ /**
7
+ * Sends a `request` step: renders its templates, waits for the gate's throttle,
8
+ * sends (again, after a pause, while it fails in passing: `limits.retry`),
9
+ * checks the response against the recipe's block rule, then binds it as the
10
+ * scope's current document (and under the step id).
11
+ *
12
+ * @param step - The request step.
13
+ * @param scope - The scope to render in and bind into.
14
+ * @param client - The HTTP sender.
15
+ * @param recipe - The recipe: its limits, block rule and id.
16
+ * @param gate - Spaces request starts by `delayMs`.
17
+ * @param events - Where to report the visit.
18
+ * @throws BlockedError when the response is a block, or a captcha page under `session.captcha`; HttpError for any other 4xx/5xx.
19
+ */
20
+ export declare function sendRequest(step: RequestStep, scope: ExtractionScope, client: HttpSender, recipe: InputRecipe, gate: RunGate, events: EventBus): Promise<void>;
21
+ /** What a step id holds for a document: parsed JSON, the read PDF, workbook or deck, or the markup / text. */
22
+ export declare function documentValue(body: HttpBody): unknown;
23
+ //# sourceMappingURL=send-request.use-case.d.ts.map
@@ -0,0 +1,52 @@
1
+ import type { BrowserSessionConfig } from './browser-session.config.js';
2
+ import { BrowserSession } from './browser.client.js';
3
+ import type { SessionOptions } from './browser.client.js';
4
+ /** A browser profile name: it becomes a directory, so no separators or dots. */
5
+ export declare const BROWSER_PROFILE_NAME: RegExp;
6
+ /**
7
+ * Browser profiles that persist between runs: each is a directory of a real
8
+ * browser's user data (cookies, local storage, IndexedDB, cache, service
9
+ * workers), so a login, a consent choice or a site's trust in a returning
10
+ * visitor carries over to the next run. The browser equivalent of a user who
11
+ * never clears their history.
12
+ *
13
+ * A profile directory can be open in one browser at a time. Within this
14
+ * crawler, a second use waits for the first to close; the same owner (one
15
+ * recipe run reopening after a rotation) takes it over instead. Another
16
+ * crawler holding it, in this process or another, is reported, not waited
17
+ * for: a lock file in the profile names the process, and one left by a
18
+ * process that died is taken over. (Chromium's own profile lock is not
19
+ * enough: headless builds do not take it.)
20
+ */
21
+ export declare class BrowserProfiles {
22
+ readonly directory: string;
23
+ private readonly config;
24
+ private readonly held;
25
+ private readonly waiting;
26
+ /**
27
+ * @param directory - Where the profiles live, one subdirectory each.
28
+ * @param config - The crawler's browser settings (type, binary, headless, timeouts).
29
+ */
30
+ constructor(directory: string, config?: BrowserSessionConfig);
31
+ private take;
32
+ private free;
33
+ private launch;
34
+ /**
35
+ * The profile's directory.
36
+ *
37
+ * @param name - A profile name.
38
+ * @returns The absolute path.
39
+ */
40
+ pathOf(name: string): string;
41
+ /**
42
+ * Opens a profile in its own browser, waiting while another run of this
43
+ * crawler uses it.
44
+ *
45
+ * @param name - The profile.
46
+ * @param options - Proxy, headers, viewport, cookies to add. `storageState` is ignored: the profile has its own.
47
+ * @param owner - Who opens it; the same owner reopening closes its previous session first.
48
+ * @returns The session; closing it frees the profile.
49
+ */
50
+ open(name: string, options: SessionOptions, owner: object): Promise<BrowserSession>;
51
+ }
52
+ //# sourceMappingURL=browser-profile.store.d.ts.map
@@ -0,0 +1,21 @@
1
+ /** How the browser is launched. Everything is optional; the default is headless chromium. */
2
+ export interface BrowserSessionConfig {
3
+ browserType?: 'chromium' | 'firefox' | 'webkit';
4
+ /** Default `true`. */
5
+ headless?: boolean;
6
+ /** Milliseconds added to every action, for watching a crawl. */
7
+ slowMo?: number;
8
+ /** A browser binary other than the one `playwright install` fetched. */
9
+ executablePath?: string;
10
+ proxy?: {
11
+ server: string;
12
+ username?: string;
13
+ password?: string;
14
+ bypass?: string;
15
+ };
16
+ /** Default navigation and action timeout in milliseconds. */
17
+ timeoutMs?: number;
18
+ ignoreHTTPSErrors?: boolean;
19
+ }
20
+ export declare const DEFAULT_BROWSER_CONFIG: Required<Pick<BrowserSessionConfig, 'browserType' | 'headless'>>;
21
+ //# sourceMappingURL=browser-session.config.d.ts.map
@@ -0,0 +1,75 @@
1
+ import type { BrowserContext, Page } from 'playwright';
2
+ import type { BrowserSessionConfig } from './browser-session.config.js';
3
+ /** Playwright's storage state: cookies plus per-origin local storage. */
4
+ export type StorageState = Awaited<ReturnType<BrowserContext['storageState']>>;
5
+ /** What a session starts from. */
6
+ export interface SessionOptions {
7
+ storageState?: StorageState;
8
+ cookies?: Parameters<BrowserContext['addCookies']>[0];
9
+ headers?: Record<string, string>;
10
+ userAgent?: string;
11
+ viewport?: {
12
+ width: number;
13
+ height: number;
14
+ };
15
+ /** A proxy for this context only; overrides the launch-level `proxy`. */
16
+ proxy?: {
17
+ server: string;
18
+ username?: string;
19
+ password?: string;
20
+ bypass?: string;
21
+ };
22
+ /** Also accept invalid certificates in this context (a proxy that intercepts HTTPS). */
23
+ ignoreHTTPSErrors?: boolean;
24
+ /** Resource types this context never loads (`image`, `font`, `media`...), to save proxy bandwidth. */
25
+ blockResources?: readonly string[];
26
+ }
27
+ /** One browser context with one page: the unit a recipe runs in. */
28
+ export declare class BrowserSession {
29
+ readonly context: BrowserContext;
30
+ readonly page: Page;
31
+ private readonly closer?;
32
+ /**
33
+ * @param context - The browser context.
34
+ * @param page - Its page.
35
+ * @param closer - How to end the session; closing the context by default. A remote browser disconnects instead.
36
+ */
37
+ constructor(context: BrowserContext, page: Page, closer?: (() => Promise<void>) | undefined);
38
+ /** The cookies and storage this session holds now, in the shape an HTTP client or a later run can reuse. */
39
+ storageState(): Promise<StorageState>;
40
+ close(): Promise<void>;
41
+ }
42
+ /**
43
+ * What a context gets after it opened: the cookies to add and the resource
44
+ * types to skip.
45
+ *
46
+ * @param context - The context.
47
+ * @param options - The session options.
48
+ */
49
+ export declare function applySessionExtras(context: BrowserContext, options: SessionOptions): Promise<void>;
50
+ /** A launched browser; sessions are opened from it and closed independently. */
51
+ export declare class BrowserClient {
52
+ private readonly browser;
53
+ private readonly config;
54
+ static launch(config?: BrowserSessionConfig): Promise<BrowserClient>;
55
+ /**
56
+ * A session in a remote browser, over the Chrome DevTools Protocol. The
57
+ * provider's own context is reused when it offers one (several providers
58
+ * pin the proxy and fingerprint to it); cookies, headers, blocked resources
59
+ * and the viewport are applied to it. Closing the session disconnects,
60
+ * which ends it on the provider's side.
61
+ *
62
+ * @param cdp - The endpoint and connection headers.
63
+ * @param options - What the session starts from. `userAgent` cannot change on an existing context and is ignored.
64
+ * @param timeoutMs - For the connection and every action.
65
+ * @returns The session.
66
+ */
67
+ static connectOverCDP(cdp: {
68
+ endpoint: string;
69
+ headers?: Record<string, string>;
70
+ }, options?: SessionOptions, timeoutMs?: number): Promise<BrowserSession>;
71
+ private constructor();
72
+ newSession(options?: SessionOptions): Promise<BrowserSession>;
73
+ close(): Promise<void>;
74
+ }
75
+ //# sourceMappingURL=browser.client.d.ts.map
@@ -0,0 +1,6 @@
1
+ export { BrowserClient, BrowserSession } from './browser.client.js';
2
+ export { BrowserProfiles, BROWSER_PROFILE_NAME } from './browser-profile.store.js';
3
+ export type { StorageState, SessionOptions } from './browser.client.js';
4
+ export { DEFAULT_BROWSER_CONFIG } from './browser-session.config.js';
5
+ export type { BrowserSessionConfig } from './browser-session.config.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,21 @@
1
+ /** Default solves a recipe run may spend. */
2
+ export declare const DEFAULT_MAX_SOLVES = 10;
3
+ /**
4
+ * The solves a recipe run may still spend. Every solve costs money: a detector
5
+ * that matches the wrong element would drain a balance without it. Shared by
6
+ * every runner of the run, rotations included.
7
+ */
8
+ export declare class CaptchaBudget {
9
+ readonly max: number;
10
+ private used;
11
+ constructor(max?: number);
12
+ /** Solves spent so far. */
13
+ get spent(): number;
14
+ /**
15
+ * Spends one solve.
16
+ *
17
+ * @returns Whether one was left.
18
+ */
19
+ take(): boolean;
20
+ }
21
+ //# sourceMappingURL=captcha-budget.model.d.ts.map
@@ -0,0 +1,28 @@
1
+ import type { Page } from 'playwright';
2
+ import type { CaptchaChallenge } from './captcha-solver.contract.js';
3
+ /** The widgets detection looks for when a recipe names none: reCAPTCHA v2, hCaptcha and Turnstile, as a container or as their iframe. */
4
+ export declare const DEFAULT_CAPTCHA_SELECTOR: string;
5
+ /**
6
+ * The first visible challenge on the page, if any. An element counts only
7
+ * when visible: sites keep hidden widgets around after a solve, and an
8
+ * invisible reCAPTCHA shows nothing until it challenges.
9
+ *
10
+ * @param page - The live page.
11
+ * @param selector - Where challenges are; `DEFAULT_CAPTCHA_SELECTOR` when omitted.
12
+ * @param options - `v3`: also report a reCAPTCHA v3 script (a `captcha` step asks for it; the automatic checks do not, since v3 never blocks a page by itself).
13
+ * @returns The challenge, or `undefined`.
14
+ */
15
+ export declare function detectChallenge(page: Page, selector?: string, options?: {
16
+ v3?: boolean;
17
+ }): Promise<CaptchaChallenge | undefined>;
18
+ /**
19
+ * Whether the page is clear of challenges, tolerating a page that is
20
+ * navigating (a solve often submits a form): an evaluation cut short by the
21
+ * navigation counts as not clear yet.
22
+ *
23
+ * @param page - The live page.
24
+ * @param selector - Where challenges are.
25
+ * @returns Whether no challenge is visible.
26
+ */
27
+ export declare function isClear(page: Page, selector: string): Promise<boolean>;
28
+ //# sourceMappingURL=captcha-detection.client.d.ts.map