@datafuel/sdk 0.2.0 → 0.4.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/README.md +40 -7
- package/dist/index.cjs +75 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +84 -9
- package/dist/index.d.ts +84 -9
- package/dist/index.js +74 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +57 -4
- package/src/core.ts +29 -20
- package/src/errors.ts +12 -1
- package/src/index.ts +5 -0
- package/src/models.ts +52 -3
package/dist/index.d.cts
CHANGED
|
@@ -40,7 +40,9 @@ interface AI {
|
|
|
40
40
|
prompt?: string;
|
|
41
41
|
/** Example JSON object the output must follow. */
|
|
42
42
|
format?: unknown;
|
|
43
|
-
|
|
43
|
+
/** Required. One of the providers `df.aiProviders()` lists; the API answers 400 INVALID_ATTRIBUTES without it. */
|
|
44
|
+
provider?: string;
|
|
45
|
+
/** One of the models `df.aiProviders()` lists for `provider`. Omit for the provider's default. */
|
|
44
46
|
model?: string;
|
|
45
47
|
apiKey?: string;
|
|
46
48
|
}
|
|
@@ -54,9 +56,15 @@ interface ScrapeOptions {
|
|
|
54
56
|
jsRendering?: boolean;
|
|
55
57
|
waitFor?: string;
|
|
56
58
|
waitForTimeoutMs?: number;
|
|
57
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Browser actions run after load: an array of single-action objects, run in
|
|
61
|
+
* order, e.g. `[{ click: "#more" }, { wait_ms: 1000 }, { click: "#more" }]`.
|
|
62
|
+
* An object keyed by action is still accepted, but its order is not
|
|
63
|
+
* guaranteed and an action cannot repeat. `df.jsInstructions()` lists them.
|
|
64
|
+
*/
|
|
58
65
|
jsInstructions?: unknown;
|
|
59
|
-
|
|
66
|
+
/** Resource types the browser must not load: one, e.g. `"Image"`, or several. */
|
|
67
|
+
blockResource?: string | string[];
|
|
60
68
|
/** Markdown only: always render just the `<main>` / `<article>` container. */
|
|
61
69
|
mainContentOnly?: boolean;
|
|
62
70
|
/** Markdown only: `false` drops images and saves tokens. */
|
|
@@ -310,6 +318,8 @@ interface TransactionsOptions {
|
|
|
310
318
|
interface Transaction {
|
|
311
319
|
id: number;
|
|
312
320
|
amount: number;
|
|
321
|
+
/** The part of `amount` that moved plan credits, same sign; the rest moved pay-as-you-go credits. */
|
|
322
|
+
plan_amount?: number;
|
|
313
323
|
operation: TransactionOperation;
|
|
314
324
|
/** What `reference_id` points to, e.g. `task_id` or `job_id`. */
|
|
315
325
|
reference_type: string;
|
|
@@ -400,13 +410,29 @@ interface Analytics {
|
|
|
400
410
|
})[];
|
|
401
411
|
by_status_code: StatusCodeBreakdown[];
|
|
402
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* Credits by pool. Plan credits are spent first, roll over when the plan renews and
|
|
415
|
+
* expire if it is not renewed. Pay-as-you-go credits come from credit packs, are spent
|
|
416
|
+
* after plan credits and never expire.
|
|
417
|
+
*/
|
|
418
|
+
interface BalanceSplit {
|
|
419
|
+
/** Total spendable credits: `plan_balance` plus `payg_balance`. */
|
|
420
|
+
balance: number;
|
|
421
|
+
plan_balance: number;
|
|
422
|
+
payg_balance: number;
|
|
423
|
+
}
|
|
403
424
|
/** The account behind the API key. */
|
|
404
425
|
interface Profile {
|
|
405
426
|
email: string;
|
|
406
427
|
username: string;
|
|
407
428
|
current_concurrency: number;
|
|
408
429
|
concurrency_limit: number;
|
|
430
|
+
/** Total spendable credits: `plan_credit_balance` plus `payg_credit_balance`. */
|
|
409
431
|
credit_balance: number;
|
|
432
|
+
/** Spent first; expire if the plan is not renewed. */
|
|
433
|
+
plan_credit_balance?: number;
|
|
434
|
+
/** Spent after plan credits; never expire. */
|
|
435
|
+
payg_credit_balance?: number;
|
|
410
436
|
monthly_credit_limit: number;
|
|
411
437
|
}
|
|
412
438
|
/** One argument of a browser action. */
|
|
@@ -427,6 +453,28 @@ interface JsInstruction {
|
|
|
427
453
|
iframe: boolean;
|
|
428
454
|
example: unknown;
|
|
429
455
|
}
|
|
456
|
+
/** An LLM provider `ai.provider` accepts, with the models `ai.model` accepts for it. */
|
|
457
|
+
interface AIProvider {
|
|
458
|
+
name: string;
|
|
459
|
+
models: string[];
|
|
460
|
+
}
|
|
461
|
+
/** The anti-bot protection in front of one host and path, from `checkProtection`. */
|
|
462
|
+
interface ProtectionCheck {
|
|
463
|
+
host: string;
|
|
464
|
+
path: string;
|
|
465
|
+
/** cloudflare, cloudflare_5sec, akamai, imperva, perimeterx or unprotected. */
|
|
466
|
+
protection_type: string;
|
|
467
|
+
}
|
|
468
|
+
/** The state of the API. `checks` is filled by a deep check only, keyed by dependency. */
|
|
469
|
+
interface Health {
|
|
470
|
+
status: "ok" | "degraded" | (string & {});
|
|
471
|
+
checks?: Record<string, {
|
|
472
|
+
status: "ok" | "fail" | (string & {});
|
|
473
|
+
latency_ms: number;
|
|
474
|
+
}>;
|
|
475
|
+
/** Whether the API can serve requests. */
|
|
476
|
+
ok: boolean;
|
|
477
|
+
}
|
|
430
478
|
/** A named proxy location: a city, or an ASN. */
|
|
431
479
|
interface ProxyLocation {
|
|
432
480
|
code: string;
|
|
@@ -470,7 +518,7 @@ declare class Capabilities {
|
|
|
470
518
|
|
|
471
519
|
declare const DEFAULT_BASE_URL = "https://scraping-api.datafuel.ai/api/v1";
|
|
472
520
|
/** Kept in step with package.json by a test; see test/hardening.test.ts. */
|
|
473
|
-
declare const VERSION = "0.
|
|
521
|
+
declare const VERSION = "0.4.0";
|
|
474
522
|
/** Options for the llm_scraping module, which reads its proxy country here. */
|
|
475
523
|
interface AskOptions {
|
|
476
524
|
engine: Engine | string;
|
|
@@ -538,7 +586,10 @@ interface SearchOptions {
|
|
|
538
586
|
ludocid?: string;
|
|
539
587
|
lsig?: string;
|
|
540
588
|
ibp?: string;
|
|
541
|
-
/**
|
|
589
|
+
/**
|
|
590
|
+
* Accepted but not used yet: searches leave through DataFuel's own pool.
|
|
591
|
+
* Target a market with `country` and `language`.
|
|
592
|
+
*/
|
|
542
593
|
proxyCountry?: string;
|
|
543
594
|
/** Default json. */
|
|
544
595
|
format?: "json" | "html" | "markdown";
|
|
@@ -721,6 +772,21 @@ declare class DataFuel {
|
|
|
721
772
|
capabilities(options?: CallOptions): Promise<Capabilities>;
|
|
722
773
|
/** The browser actions `jsInstructions` accepts, with their arguments. Needs no key. */
|
|
723
774
|
jsInstructions(options?: CallOptions): Promise<JsInstruction[]>;
|
|
775
|
+
/** The LLM providers and models `ai` accepts. Needs no key. */
|
|
776
|
+
aiProviders(options?: CallOptions): Promise<AIProvider[]>;
|
|
777
|
+
/**
|
|
778
|
+
* Whether the API is up. `deep` also checks the dependencies it needs to
|
|
779
|
+
* serve scrapes. A degraded report is returned, not thrown: read `ok`.
|
|
780
|
+
* Needs no key.
|
|
781
|
+
*/
|
|
782
|
+
health(options?: CallOptions & {
|
|
783
|
+
deep?: boolean;
|
|
784
|
+
}): Promise<Health>;
|
|
785
|
+
/**
|
|
786
|
+
* Which anti-bot protection sits in front of each URL. Nothing is scraped
|
|
787
|
+
* and nothing is charged; invalid URLs are skipped.
|
|
788
|
+
*/
|
|
789
|
+
checkProtection(urls: string[], options?: CallOptions): Promise<ProtectionCheck[]>;
|
|
724
790
|
/** Countries, regions and cities a proxy type can exit from. */
|
|
725
791
|
proxyLocations(options?: CallOptions & {
|
|
726
792
|
proxyType?: string;
|
|
@@ -729,10 +795,12 @@ declare class DataFuel {
|
|
|
729
795
|
proxyAsns(country: string, options?: CallOptions & {
|
|
730
796
|
proxyType?: string;
|
|
731
797
|
}): Promise<ProxyLocation[]>;
|
|
732
|
-
/** Remaining credits. */
|
|
798
|
+
/** Remaining credits: plan and pay-as-you-go together. */
|
|
733
799
|
balance(options?: CallOptions): Promise<number>;
|
|
800
|
+
/** Remaining credits by pool: plan credits (spent first) and pay-as-you-go credits. */
|
|
801
|
+
balanceSplit(options?: CallOptions): Promise<BalanceSplit>;
|
|
734
802
|
/**
|
|
735
|
-
* Credit movements, newest first: purchases, usage, refunds, expiry.
|
|
803
|
+
* Credit movements, newest first: plan assignments, credit pack purchases, usage, refunds, expiry.
|
|
736
804
|
* `sums` totals each operation over the whole range, not just this page.
|
|
737
805
|
*/
|
|
738
806
|
transactions(options?: TransactionsOptions & CallOptions): Promise<TransactionsPage>;
|
|
@@ -772,7 +840,7 @@ declare class NoApiKey extends DataFuelError {
|
|
|
772
840
|
declare class TransportError extends DataFuelError {
|
|
773
841
|
}
|
|
774
842
|
/** The `code` of an API error. The API may add codes; unknown ones pass through. */
|
|
775
|
-
type ErrorCode = "UNAUTHORIZED" | "INVALID_API_KEY" | "FORBIDDEN" | "INSUFFICIENT_CREDITS" | "RATE_LIMIT_EXCEEDED" | "CONCURRENCY_LIMIT_REACHED" | "INVALID_REQUEST_BODY" | "INVALID_ATTRIBUTES" | "MISSING_TARGET" | "UNSUPPORTED_TASK_TYPE" | "JOB_REQUIRES_MULTIPLE_TARGETS" | "INVALID_IDEMPOTENCY_KEY" | "IDEMPOTENCY_KEY_REUSED" | "INVALID_TASK_ID" | "INVALID_JOB_ID" | "TASK_NOT_FOUND" | "JOB_NOT_FOUND" | "CRAWL_NOT_FOUND" | "JOB_NOT_CANCELLABLE" | "INVALID_CRAWL_PATTERN" | "CRAWL_UNSUPPORTED_OPTION" | "INVALID_CURSOR" | "INVALID_QUERY_PARAM" | "INVALID_PROXY_TYPE" | "INVALID_COUNTRY" | "INVALID_DATE_FORMAT" | "INVALID_DATE_RANGE" | "INVALID_INTERVAL" | "MODULE_UNAVAILABLE" | "ENGINE_UNAVAILABLE" | "API_KEY_RESET_FAILED" | "TASK_RESULT_TIMEOUT" | "INTERNAL_ERROR" | (string & {});
|
|
843
|
+
type ErrorCode = "UNAUTHORIZED" | "INVALID_API_KEY" | "FORBIDDEN" | "INSUFFICIENT_CREDITS" | "RATE_LIMIT_EXCEEDED" | "CONCURRENCY_LIMIT_REACHED" | "INVALID_REQUEST_BODY" | "INVALID_ATTRIBUTES" | "MISSING_TARGET" | "UNSUPPORTED_TASK_TYPE" | "JOB_REQUIRES_MULTIPLE_TARGETS" | "INVALID_IDEMPOTENCY_KEY" | "IDEMPOTENCY_KEY_REUSED" | "INVALID_TASK_ID" | "INVALID_JOB_ID" | "TASK_NOT_FOUND" | "JOB_NOT_FOUND" | "CRAWL_NOT_FOUND" | "JOB_NOT_CANCELLABLE" | "TASK_ALREADY_EXISTS" | "JOB_ALREADY_EXISTS" | "URL_LENGTH_CANNOT_BE_ZERO" | "ANALYTICS_FETCH_FAILED" | "INVALID_CRAWL_PATTERN" | "CRAWL_UNSUPPORTED_OPTION" | "INVALID_CURSOR" | "INVALID_QUERY_PARAM" | "INVALID_PROXY_TYPE" | "INVALID_COUNTRY" | "INVALID_DATE_FORMAT" | "INVALID_DATE_RANGE" | "INVALID_INTERVAL" | "MODULE_UNAVAILABLE" | "ENGINE_UNAVAILABLE" | "API_KEY_RESET_FAILED" | "TASK_RESULT_TIMEOUT" | "INTERNAL_ERROR" | (string & {});
|
|
776
844
|
/** A non-2xx answer from the API itself. */
|
|
777
845
|
declare class APIError extends DataFuelError {
|
|
778
846
|
readonly status: number;
|
|
@@ -805,6 +873,13 @@ declare class IdempotencyKeyReused extends APIError {
|
|
|
805
873
|
/** 409 JOB_NOT_CANCELLABLE: the job or crawl already finished. */
|
|
806
874
|
declare class JobNotCancellable extends APIError {
|
|
807
875
|
}
|
|
876
|
+
/**
|
|
877
|
+
* 409 TASK_ALREADY_EXISTS / JOB_ALREADY_EXISTS: the create collided with an
|
|
878
|
+
* existing task or job and is not an idempotent replay. Nothing was charged;
|
|
879
|
+
* send the request again.
|
|
880
|
+
*/
|
|
881
|
+
declare class AlreadyExists extends APIError {
|
|
882
|
+
}
|
|
808
883
|
/** 503: an operator switched something off, or a dependency is down. The message carries the reason. */
|
|
809
884
|
declare class Unavailable extends APIError {
|
|
810
885
|
}
|
|
@@ -844,4 +919,4 @@ declare class WaitTimeout extends DataFuelError {
|
|
|
844
919
|
constructor(message: string, id?: string, status?: unknown);
|
|
845
920
|
}
|
|
846
921
|
|
|
847
|
-
export { type AI, APIError, type Analytics, type AnalyticsCounts, type AnalyticsOptions, type AskOptions, Blocked, type CallOptions, type CancelResult, Capabilities, type Capability, type ClientOptions, type CrawlOptions, CrawlPage, type CrawlResult, type CrawlResultsPage, type CrawlStatus, DEFAULT_BASE_URL, DataFuel, DataFuelError, type Engine, EngineUnavailable, type ErrorCode, Forbidden, type Format, IdempotencyKeyReused, InsufficientCredits, InvalidAttributes, JobNotCancellable, type JobResults, type JobStatus, type JobSummary, type JobsPage, type JsInstruction, type JsInstructionArg, type Link, type ListOptions, type ListTasksOptions, type MapOptions, ModuleUnavailable, NoApiKey, NotFound, type Payload, type PreviousPeriod, type Profile, type Proxy, type ProxyCountry, type ProxyLocation, type ProxyType, RateLimited, Result, type ScrapeOptions, type SearchOptions, type SiteMap, type Status, type StatusCodeBreakdown, TaskFailed, type TaskSummary, type TaskType, type TasksPage, type Transaction, type TransactionOperation, type TransactionSum, type TransactionsOptions, type TransactionsPage, TransportError, Unauthorized, Unavailable, VERSION, WaitTimeout, isDone };
|
|
922
|
+
export { type AI, type AIProvider, APIError, AlreadyExists, type Analytics, type AnalyticsCounts, type AnalyticsOptions, type AskOptions, type BalanceSplit, Blocked, type CallOptions, type CancelResult, Capabilities, type Capability, type ClientOptions, type CrawlOptions, CrawlPage, type CrawlResult, type CrawlResultsPage, type CrawlStatus, DEFAULT_BASE_URL, DataFuel, DataFuelError, type Engine, EngineUnavailable, type ErrorCode, Forbidden, type Format, type Health, IdempotencyKeyReused, InsufficientCredits, InvalidAttributes, JobNotCancellable, type JobResults, type JobStatus, type JobSummary, type JobsPage, type JsInstruction, type JsInstructionArg, type Link, type ListOptions, type ListTasksOptions, type MapOptions, ModuleUnavailable, NoApiKey, NotFound, type Payload, type PreviousPeriod, type Profile, type ProtectionCheck, type Proxy, type ProxyCountry, type ProxyLocation, type ProxyType, RateLimited, Result, type ScrapeOptions, type SearchOptions, type SiteMap, type Status, type StatusCodeBreakdown, TaskFailed, type TaskSummary, type TaskType, type TasksPage, type Transaction, type TransactionOperation, type TransactionSum, type TransactionsOptions, type TransactionsPage, TransportError, Unauthorized, Unavailable, VERSION, WaitTimeout, isDone };
|
package/dist/index.d.ts
CHANGED
|
@@ -40,7 +40,9 @@ interface AI {
|
|
|
40
40
|
prompt?: string;
|
|
41
41
|
/** Example JSON object the output must follow. */
|
|
42
42
|
format?: unknown;
|
|
43
|
-
|
|
43
|
+
/** Required. One of the providers `df.aiProviders()` lists; the API answers 400 INVALID_ATTRIBUTES without it. */
|
|
44
|
+
provider?: string;
|
|
45
|
+
/** One of the models `df.aiProviders()` lists for `provider`. Omit for the provider's default. */
|
|
44
46
|
model?: string;
|
|
45
47
|
apiKey?: string;
|
|
46
48
|
}
|
|
@@ -54,9 +56,15 @@ interface ScrapeOptions {
|
|
|
54
56
|
jsRendering?: boolean;
|
|
55
57
|
waitFor?: string;
|
|
56
58
|
waitForTimeoutMs?: number;
|
|
57
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Browser actions run after load: an array of single-action objects, run in
|
|
61
|
+
* order, e.g. `[{ click: "#more" }, { wait_ms: 1000 }, { click: "#more" }]`.
|
|
62
|
+
* An object keyed by action is still accepted, but its order is not
|
|
63
|
+
* guaranteed and an action cannot repeat. `df.jsInstructions()` lists them.
|
|
64
|
+
*/
|
|
58
65
|
jsInstructions?: unknown;
|
|
59
|
-
|
|
66
|
+
/** Resource types the browser must not load: one, e.g. `"Image"`, or several. */
|
|
67
|
+
blockResource?: string | string[];
|
|
60
68
|
/** Markdown only: always render just the `<main>` / `<article>` container. */
|
|
61
69
|
mainContentOnly?: boolean;
|
|
62
70
|
/** Markdown only: `false` drops images and saves tokens. */
|
|
@@ -310,6 +318,8 @@ interface TransactionsOptions {
|
|
|
310
318
|
interface Transaction {
|
|
311
319
|
id: number;
|
|
312
320
|
amount: number;
|
|
321
|
+
/** The part of `amount` that moved plan credits, same sign; the rest moved pay-as-you-go credits. */
|
|
322
|
+
plan_amount?: number;
|
|
313
323
|
operation: TransactionOperation;
|
|
314
324
|
/** What `reference_id` points to, e.g. `task_id` or `job_id`. */
|
|
315
325
|
reference_type: string;
|
|
@@ -400,13 +410,29 @@ interface Analytics {
|
|
|
400
410
|
})[];
|
|
401
411
|
by_status_code: StatusCodeBreakdown[];
|
|
402
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* Credits by pool. Plan credits are spent first, roll over when the plan renews and
|
|
415
|
+
* expire if it is not renewed. Pay-as-you-go credits come from credit packs, are spent
|
|
416
|
+
* after plan credits and never expire.
|
|
417
|
+
*/
|
|
418
|
+
interface BalanceSplit {
|
|
419
|
+
/** Total spendable credits: `plan_balance` plus `payg_balance`. */
|
|
420
|
+
balance: number;
|
|
421
|
+
plan_balance: number;
|
|
422
|
+
payg_balance: number;
|
|
423
|
+
}
|
|
403
424
|
/** The account behind the API key. */
|
|
404
425
|
interface Profile {
|
|
405
426
|
email: string;
|
|
406
427
|
username: string;
|
|
407
428
|
current_concurrency: number;
|
|
408
429
|
concurrency_limit: number;
|
|
430
|
+
/** Total spendable credits: `plan_credit_balance` plus `payg_credit_balance`. */
|
|
409
431
|
credit_balance: number;
|
|
432
|
+
/** Spent first; expire if the plan is not renewed. */
|
|
433
|
+
plan_credit_balance?: number;
|
|
434
|
+
/** Spent after plan credits; never expire. */
|
|
435
|
+
payg_credit_balance?: number;
|
|
410
436
|
monthly_credit_limit: number;
|
|
411
437
|
}
|
|
412
438
|
/** One argument of a browser action. */
|
|
@@ -427,6 +453,28 @@ interface JsInstruction {
|
|
|
427
453
|
iframe: boolean;
|
|
428
454
|
example: unknown;
|
|
429
455
|
}
|
|
456
|
+
/** An LLM provider `ai.provider` accepts, with the models `ai.model` accepts for it. */
|
|
457
|
+
interface AIProvider {
|
|
458
|
+
name: string;
|
|
459
|
+
models: string[];
|
|
460
|
+
}
|
|
461
|
+
/** The anti-bot protection in front of one host and path, from `checkProtection`. */
|
|
462
|
+
interface ProtectionCheck {
|
|
463
|
+
host: string;
|
|
464
|
+
path: string;
|
|
465
|
+
/** cloudflare, cloudflare_5sec, akamai, imperva, perimeterx or unprotected. */
|
|
466
|
+
protection_type: string;
|
|
467
|
+
}
|
|
468
|
+
/** The state of the API. `checks` is filled by a deep check only, keyed by dependency. */
|
|
469
|
+
interface Health {
|
|
470
|
+
status: "ok" | "degraded" | (string & {});
|
|
471
|
+
checks?: Record<string, {
|
|
472
|
+
status: "ok" | "fail" | (string & {});
|
|
473
|
+
latency_ms: number;
|
|
474
|
+
}>;
|
|
475
|
+
/** Whether the API can serve requests. */
|
|
476
|
+
ok: boolean;
|
|
477
|
+
}
|
|
430
478
|
/** A named proxy location: a city, or an ASN. */
|
|
431
479
|
interface ProxyLocation {
|
|
432
480
|
code: string;
|
|
@@ -470,7 +518,7 @@ declare class Capabilities {
|
|
|
470
518
|
|
|
471
519
|
declare const DEFAULT_BASE_URL = "https://scraping-api.datafuel.ai/api/v1";
|
|
472
520
|
/** Kept in step with package.json by a test; see test/hardening.test.ts. */
|
|
473
|
-
declare const VERSION = "0.
|
|
521
|
+
declare const VERSION = "0.4.0";
|
|
474
522
|
/** Options for the llm_scraping module, which reads its proxy country here. */
|
|
475
523
|
interface AskOptions {
|
|
476
524
|
engine: Engine | string;
|
|
@@ -538,7 +586,10 @@ interface SearchOptions {
|
|
|
538
586
|
ludocid?: string;
|
|
539
587
|
lsig?: string;
|
|
540
588
|
ibp?: string;
|
|
541
|
-
/**
|
|
589
|
+
/**
|
|
590
|
+
* Accepted but not used yet: searches leave through DataFuel's own pool.
|
|
591
|
+
* Target a market with `country` and `language`.
|
|
592
|
+
*/
|
|
542
593
|
proxyCountry?: string;
|
|
543
594
|
/** Default json. */
|
|
544
595
|
format?: "json" | "html" | "markdown";
|
|
@@ -721,6 +772,21 @@ declare class DataFuel {
|
|
|
721
772
|
capabilities(options?: CallOptions): Promise<Capabilities>;
|
|
722
773
|
/** The browser actions `jsInstructions` accepts, with their arguments. Needs no key. */
|
|
723
774
|
jsInstructions(options?: CallOptions): Promise<JsInstruction[]>;
|
|
775
|
+
/** The LLM providers and models `ai` accepts. Needs no key. */
|
|
776
|
+
aiProviders(options?: CallOptions): Promise<AIProvider[]>;
|
|
777
|
+
/**
|
|
778
|
+
* Whether the API is up. `deep` also checks the dependencies it needs to
|
|
779
|
+
* serve scrapes. A degraded report is returned, not thrown: read `ok`.
|
|
780
|
+
* Needs no key.
|
|
781
|
+
*/
|
|
782
|
+
health(options?: CallOptions & {
|
|
783
|
+
deep?: boolean;
|
|
784
|
+
}): Promise<Health>;
|
|
785
|
+
/**
|
|
786
|
+
* Which anti-bot protection sits in front of each URL. Nothing is scraped
|
|
787
|
+
* and nothing is charged; invalid URLs are skipped.
|
|
788
|
+
*/
|
|
789
|
+
checkProtection(urls: string[], options?: CallOptions): Promise<ProtectionCheck[]>;
|
|
724
790
|
/** Countries, regions and cities a proxy type can exit from. */
|
|
725
791
|
proxyLocations(options?: CallOptions & {
|
|
726
792
|
proxyType?: string;
|
|
@@ -729,10 +795,12 @@ declare class DataFuel {
|
|
|
729
795
|
proxyAsns(country: string, options?: CallOptions & {
|
|
730
796
|
proxyType?: string;
|
|
731
797
|
}): Promise<ProxyLocation[]>;
|
|
732
|
-
/** Remaining credits. */
|
|
798
|
+
/** Remaining credits: plan and pay-as-you-go together. */
|
|
733
799
|
balance(options?: CallOptions): Promise<number>;
|
|
800
|
+
/** Remaining credits by pool: plan credits (spent first) and pay-as-you-go credits. */
|
|
801
|
+
balanceSplit(options?: CallOptions): Promise<BalanceSplit>;
|
|
734
802
|
/**
|
|
735
|
-
* Credit movements, newest first: purchases, usage, refunds, expiry.
|
|
803
|
+
* Credit movements, newest first: plan assignments, credit pack purchases, usage, refunds, expiry.
|
|
736
804
|
* `sums` totals each operation over the whole range, not just this page.
|
|
737
805
|
*/
|
|
738
806
|
transactions(options?: TransactionsOptions & CallOptions): Promise<TransactionsPage>;
|
|
@@ -772,7 +840,7 @@ declare class NoApiKey extends DataFuelError {
|
|
|
772
840
|
declare class TransportError extends DataFuelError {
|
|
773
841
|
}
|
|
774
842
|
/** The `code` of an API error. The API may add codes; unknown ones pass through. */
|
|
775
|
-
type ErrorCode = "UNAUTHORIZED" | "INVALID_API_KEY" | "FORBIDDEN" | "INSUFFICIENT_CREDITS" | "RATE_LIMIT_EXCEEDED" | "CONCURRENCY_LIMIT_REACHED" | "INVALID_REQUEST_BODY" | "INVALID_ATTRIBUTES" | "MISSING_TARGET" | "UNSUPPORTED_TASK_TYPE" | "JOB_REQUIRES_MULTIPLE_TARGETS" | "INVALID_IDEMPOTENCY_KEY" | "IDEMPOTENCY_KEY_REUSED" | "INVALID_TASK_ID" | "INVALID_JOB_ID" | "TASK_NOT_FOUND" | "JOB_NOT_FOUND" | "CRAWL_NOT_FOUND" | "JOB_NOT_CANCELLABLE" | "INVALID_CRAWL_PATTERN" | "CRAWL_UNSUPPORTED_OPTION" | "INVALID_CURSOR" | "INVALID_QUERY_PARAM" | "INVALID_PROXY_TYPE" | "INVALID_COUNTRY" | "INVALID_DATE_FORMAT" | "INVALID_DATE_RANGE" | "INVALID_INTERVAL" | "MODULE_UNAVAILABLE" | "ENGINE_UNAVAILABLE" | "API_KEY_RESET_FAILED" | "TASK_RESULT_TIMEOUT" | "INTERNAL_ERROR" | (string & {});
|
|
843
|
+
type ErrorCode = "UNAUTHORIZED" | "INVALID_API_KEY" | "FORBIDDEN" | "INSUFFICIENT_CREDITS" | "RATE_LIMIT_EXCEEDED" | "CONCURRENCY_LIMIT_REACHED" | "INVALID_REQUEST_BODY" | "INVALID_ATTRIBUTES" | "MISSING_TARGET" | "UNSUPPORTED_TASK_TYPE" | "JOB_REQUIRES_MULTIPLE_TARGETS" | "INVALID_IDEMPOTENCY_KEY" | "IDEMPOTENCY_KEY_REUSED" | "INVALID_TASK_ID" | "INVALID_JOB_ID" | "TASK_NOT_FOUND" | "JOB_NOT_FOUND" | "CRAWL_NOT_FOUND" | "JOB_NOT_CANCELLABLE" | "TASK_ALREADY_EXISTS" | "JOB_ALREADY_EXISTS" | "URL_LENGTH_CANNOT_BE_ZERO" | "ANALYTICS_FETCH_FAILED" | "INVALID_CRAWL_PATTERN" | "CRAWL_UNSUPPORTED_OPTION" | "INVALID_CURSOR" | "INVALID_QUERY_PARAM" | "INVALID_PROXY_TYPE" | "INVALID_COUNTRY" | "INVALID_DATE_FORMAT" | "INVALID_DATE_RANGE" | "INVALID_INTERVAL" | "MODULE_UNAVAILABLE" | "ENGINE_UNAVAILABLE" | "API_KEY_RESET_FAILED" | "TASK_RESULT_TIMEOUT" | "INTERNAL_ERROR" | (string & {});
|
|
776
844
|
/** A non-2xx answer from the API itself. */
|
|
777
845
|
declare class APIError extends DataFuelError {
|
|
778
846
|
readonly status: number;
|
|
@@ -805,6 +873,13 @@ declare class IdempotencyKeyReused extends APIError {
|
|
|
805
873
|
/** 409 JOB_NOT_CANCELLABLE: the job or crawl already finished. */
|
|
806
874
|
declare class JobNotCancellable extends APIError {
|
|
807
875
|
}
|
|
876
|
+
/**
|
|
877
|
+
* 409 TASK_ALREADY_EXISTS / JOB_ALREADY_EXISTS: the create collided with an
|
|
878
|
+
* existing task or job and is not an idempotent replay. Nothing was charged;
|
|
879
|
+
* send the request again.
|
|
880
|
+
*/
|
|
881
|
+
declare class AlreadyExists extends APIError {
|
|
882
|
+
}
|
|
808
883
|
/** 503: an operator switched something off, or a dependency is down. The message carries the reason. */
|
|
809
884
|
declare class Unavailable extends APIError {
|
|
810
885
|
}
|
|
@@ -844,4 +919,4 @@ declare class WaitTimeout extends DataFuelError {
|
|
|
844
919
|
constructor(message: string, id?: string, status?: unknown);
|
|
845
920
|
}
|
|
846
921
|
|
|
847
|
-
export { type AI, APIError, type Analytics, type AnalyticsCounts, type AnalyticsOptions, type AskOptions, Blocked, type CallOptions, type CancelResult, Capabilities, type Capability, type ClientOptions, type CrawlOptions, CrawlPage, type CrawlResult, type CrawlResultsPage, type CrawlStatus, DEFAULT_BASE_URL, DataFuel, DataFuelError, type Engine, EngineUnavailable, type ErrorCode, Forbidden, type Format, IdempotencyKeyReused, InsufficientCredits, InvalidAttributes, JobNotCancellable, type JobResults, type JobStatus, type JobSummary, type JobsPage, type JsInstruction, type JsInstructionArg, type Link, type ListOptions, type ListTasksOptions, type MapOptions, ModuleUnavailable, NoApiKey, NotFound, type Payload, type PreviousPeriod, type Profile, type Proxy, type ProxyCountry, type ProxyLocation, type ProxyType, RateLimited, Result, type ScrapeOptions, type SearchOptions, type SiteMap, type Status, type StatusCodeBreakdown, TaskFailed, type TaskSummary, type TaskType, type TasksPage, type Transaction, type TransactionOperation, type TransactionSum, type TransactionsOptions, type TransactionsPage, TransportError, Unauthorized, Unavailable, VERSION, WaitTimeout, isDone };
|
|
922
|
+
export { type AI, type AIProvider, APIError, AlreadyExists, type Analytics, type AnalyticsCounts, type AnalyticsOptions, type AskOptions, type BalanceSplit, Blocked, type CallOptions, type CancelResult, Capabilities, type Capability, type ClientOptions, type CrawlOptions, CrawlPage, type CrawlResult, type CrawlResultsPage, type CrawlStatus, DEFAULT_BASE_URL, DataFuel, DataFuelError, type Engine, EngineUnavailable, type ErrorCode, Forbidden, type Format, type Health, IdempotencyKeyReused, InsufficientCredits, InvalidAttributes, JobNotCancellable, type JobResults, type JobStatus, type JobSummary, type JobsPage, type JsInstruction, type JsInstructionArg, type Link, type ListOptions, type ListTasksOptions, type MapOptions, ModuleUnavailable, NoApiKey, NotFound, type Payload, type PreviousPeriod, type Profile, type ProtectionCheck, type Proxy, type ProxyCountry, type ProxyLocation, type ProxyType, RateLimited, Result, type ScrapeOptions, type SearchOptions, type SiteMap, type Status, type StatusCodeBreakdown, TaskFailed, type TaskSummary, type TaskType, type TasksPage, type Transaction, type TransactionOperation, type TransactionSum, type TransactionsOptions, type TransactionsPage, TransportError, Unauthorized, Unavailable, VERSION, WaitTimeout, isDone };
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,8 @@ var IdempotencyKeyReused = class extends APIError {
|
|
|
37
37
|
};
|
|
38
38
|
var JobNotCancellable = class extends APIError {
|
|
39
39
|
};
|
|
40
|
+
var AlreadyExists = class extends APIError {
|
|
41
|
+
};
|
|
40
42
|
var Unavailable = class extends APIError {
|
|
41
43
|
};
|
|
42
44
|
var ModuleUnavailable = class extends Unavailable {
|
|
@@ -74,14 +76,15 @@ var BY_CODE = {
|
|
|
74
76
|
IDEMPOTENCY_KEY_REUSED: IdempotencyKeyReused,
|
|
75
77
|
INVALID_API_KEY: Unauthorized,
|
|
76
78
|
FORBIDDEN: Forbidden,
|
|
77
|
-
JOB_NOT_CANCELLABLE: JobNotCancellable
|
|
79
|
+
JOB_NOT_CANCELLABLE: JobNotCancellable,
|
|
80
|
+
TASK_ALREADY_EXISTS: AlreadyExists,
|
|
81
|
+
JOB_ALREADY_EXISTS: AlreadyExists
|
|
78
82
|
};
|
|
79
83
|
var BY_STATUS = {
|
|
80
84
|
401: Unauthorized,
|
|
81
85
|
402: InsufficientCredits,
|
|
82
86
|
403: Forbidden,
|
|
83
87
|
404: NotFound,
|
|
84
|
-
409: JobNotCancellable,
|
|
85
88
|
422: IdempotencyKeyReused,
|
|
86
89
|
429: RateLimited,
|
|
87
90
|
503: Unavailable
|
|
@@ -102,19 +105,20 @@ function apiError(status, body, retryAfter = 0) {
|
|
|
102
105
|
|
|
103
106
|
// src/core.ts
|
|
104
107
|
var DEFAULT_BASE_URL = "https://scraping-api.datafuel.ai/api/v1";
|
|
105
|
-
var VERSION = "0.
|
|
108
|
+
var VERSION = "0.4.0";
|
|
106
109
|
var DEFAULT_TIMEOUT_MS = 18e4;
|
|
107
110
|
var STILL_PROCESSING_DELAY_MS = 2e3;
|
|
108
111
|
var STILL_PROCESSING = "TASK_STILL_PROCESSING";
|
|
109
112
|
var MAX_IDEMPOTENCY_KEY = 255;
|
|
110
113
|
var Request = class {
|
|
111
|
-
constructor(method, path, params, body, idempotencyKey, auth = true) {
|
|
114
|
+
constructor(method, path, params, body, idempotencyKey, auth = true, degradedOk = false) {
|
|
112
115
|
this.method = method;
|
|
113
116
|
this.path = path;
|
|
114
117
|
this.params = params;
|
|
115
118
|
this.body = body;
|
|
116
119
|
this.idempotencyKey = idempotencyKey;
|
|
117
120
|
this.auth = auth;
|
|
121
|
+
this.degradedOk = degradedOk;
|
|
118
122
|
}
|
|
119
123
|
method;
|
|
120
124
|
path;
|
|
@@ -122,6 +126,7 @@ var Request = class {
|
|
|
122
126
|
body;
|
|
123
127
|
idempotencyKey;
|
|
124
128
|
auth;
|
|
129
|
+
degradedOk;
|
|
125
130
|
/** GETs are safe by nature, writes because they carry an idempotency key. */
|
|
126
131
|
get retryable() {
|
|
127
132
|
return this.method === "GET" || this.idempotencyKey !== void 0;
|
|
@@ -169,15 +174,8 @@ function aiAttributes(ai) {
|
|
|
169
174
|
return out;
|
|
170
175
|
}
|
|
171
176
|
function validateAI(ai) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
model: ai.model !== void 0,
|
|
175
|
-
apiKey: ai.apiKey !== void 0
|
|
176
|
-
};
|
|
177
|
-
const present = Object.values(given).filter(Boolean).length;
|
|
178
|
-
if (present > 0 && present < 3) {
|
|
179
|
-
const missing = Object.entries(given).filter(([, ok]) => !ok).map(([name]) => name).join(", ");
|
|
180
|
-
throw new TypeError(`ai needs provider, model and apiKey together; missing: ${missing}`);
|
|
177
|
+
if (!ai.provider) {
|
|
178
|
+
throw new TypeError("ai needs a provider; aiProviders() lists the ones the API supports");
|
|
181
179
|
}
|
|
182
180
|
}
|
|
183
181
|
function scrapeAttributes(options = {}) {
|
|
@@ -187,7 +185,9 @@ function scrapeAttributes(options = {}) {
|
|
|
187
185
|
if (options.waitFor) attrs.wait_for_selector = options.waitFor;
|
|
188
186
|
if (options.waitForTimeoutMs) attrs.wait_for_selector_timeout_ms = options.waitForTimeoutMs;
|
|
189
187
|
if (options.jsInstructions) attrs.js_instructions = options.jsInstructions;
|
|
190
|
-
if (options.blockResource)
|
|
188
|
+
if (options.blockResource?.length) {
|
|
189
|
+
attrs.block_resource = typeof options.blockResource === "string" ? options.blockResource : [...options.blockResource];
|
|
190
|
+
}
|
|
191
191
|
if (options.mainContentOnly) attrs.main_content_only = true;
|
|
192
192
|
if (options.includeImages !== void 0) attrs.include_images = options.includeImages;
|
|
193
193
|
if (options.extract) attrs.extract_selector = selector(options.extract);
|
|
@@ -369,6 +369,17 @@ function crawlResultsRequest(crawlId, cursor, limit) {
|
|
|
369
369
|
Object.keys(params).length > 0 ? params : void 0
|
|
370
370
|
);
|
|
371
371
|
}
|
|
372
|
+
function healthRequest(deep) {
|
|
373
|
+
return new Request(
|
|
374
|
+
"GET",
|
|
375
|
+
"/healthz",
|
|
376
|
+
deep ? { deep: "1" } : void 0,
|
|
377
|
+
void 0,
|
|
378
|
+
void 0,
|
|
379
|
+
false,
|
|
380
|
+
true
|
|
381
|
+
);
|
|
382
|
+
}
|
|
372
383
|
function day(value) {
|
|
373
384
|
return typeof value === "string" ? value : value.toISOString().slice(0, 10);
|
|
374
385
|
}
|
|
@@ -601,7 +612,7 @@ var DataFuel = class {
|
|
|
601
612
|
const signal = this.signalFor(opts);
|
|
602
613
|
const send = this.fetchImpl;
|
|
603
614
|
const response = await send(url, signal ? { ...init, signal } : init);
|
|
604
|
-
return await parse(response);
|
|
615
|
+
return await parse(response, request.degradedOk);
|
|
605
616
|
} catch (caught) {
|
|
606
617
|
if (isAbort(caught)) {
|
|
607
618
|
throw new TransportError("the request was aborted or timed out", { cause: caught });
|
|
@@ -963,6 +974,37 @@ var DataFuel = class {
|
|
|
963
974
|
const body = record(await this.send(request, options));
|
|
964
975
|
return Array.isArray(body.instructions) ? body.instructions : [];
|
|
965
976
|
}
|
|
977
|
+
/** The LLM providers and models `ai` accepts. Needs no key. */
|
|
978
|
+
async aiProviders(options = {}) {
|
|
979
|
+
const request = new Request(
|
|
980
|
+
"GET",
|
|
981
|
+
"/config/ai-providers",
|
|
982
|
+
void 0,
|
|
983
|
+
void 0,
|
|
984
|
+
void 0,
|
|
985
|
+
false
|
|
986
|
+
);
|
|
987
|
+
const body = record(await this.send(request, options));
|
|
988
|
+
return Array.isArray(body.providers) ? body.providers : [];
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Whether the API is up. `deep` also checks the dependencies it needs to
|
|
992
|
+
* serve scrapes. A degraded report is returned, not thrown: read `ok`.
|
|
993
|
+
* Needs no key.
|
|
994
|
+
*/
|
|
995
|
+
async health(options = {}) {
|
|
996
|
+
const body = record(await this.send(healthRequest(options.deep ?? false), options));
|
|
997
|
+
return { ...body, ok: body.status === "ok" };
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* Which anti-bot protection sits in front of each URL. Nothing is scraped
|
|
1001
|
+
* and nothing is charged; invalid URLs are skipped.
|
|
1002
|
+
*/
|
|
1003
|
+
async checkProtection(urls, options = {}) {
|
|
1004
|
+
return list(
|
|
1005
|
+
await this.send(new Request("POST", "/filter/check", void 0, [...urls]), options)
|
|
1006
|
+
);
|
|
1007
|
+
}
|
|
966
1008
|
/** Countries, regions and cities a proxy type can exit from. */
|
|
967
1009
|
async proxyLocations(options = {}) {
|
|
968
1010
|
const params = options.proxyType ? { proxy_type: options.proxyType } : void 0;
|
|
@@ -978,13 +1020,22 @@ var DataFuel = class {
|
|
|
978
1020
|
await this.send(new Request("GET", "/config/proxy/asn", params), options)
|
|
979
1021
|
);
|
|
980
1022
|
}
|
|
981
|
-
/** Remaining credits. */
|
|
1023
|
+
/** Remaining credits: plan and pay-as-you-go together. */
|
|
982
1024
|
async balance(options = {}) {
|
|
983
1025
|
const body = await this.send(new Request("GET", "/users/@me/balance"), options);
|
|
984
1026
|
return intField(body, "balance");
|
|
985
1027
|
}
|
|
1028
|
+
/** Remaining credits by pool: plan credits (spent first) and pay-as-you-go credits. */
|
|
1029
|
+
async balanceSplit(options = {}) {
|
|
1030
|
+
const body = await this.send(new Request("GET", "/users/@me/balance"), options);
|
|
1031
|
+
return {
|
|
1032
|
+
balance: intField(body, "balance"),
|
|
1033
|
+
plan_balance: intField(body, "plan_balance"),
|
|
1034
|
+
payg_balance: intField(body, "payg_balance")
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
986
1037
|
/**
|
|
987
|
-
* Credit movements, newest first: purchases, usage, refunds, expiry.
|
|
1038
|
+
* Credit movements, newest first: plan assignments, credit pack purchases, usage, refunds, expiry.
|
|
988
1039
|
* `sums` totals each operation over the whole range, not just this page.
|
|
989
1040
|
*/
|
|
990
1041
|
async transactions(options = {}) {
|
|
@@ -1025,7 +1076,7 @@ var DataFuel = class {
|
|
|
1025
1076
|
function envApiKey() {
|
|
1026
1077
|
return typeof process !== "undefined" ? process.env?.DATAFUEL_API_KEY : void 0;
|
|
1027
1078
|
}
|
|
1028
|
-
async function parse(response) {
|
|
1079
|
+
async function parse(response, degradedOk = false) {
|
|
1029
1080
|
const text = await response.text();
|
|
1030
1081
|
let body;
|
|
1031
1082
|
if (text.length > 0) {
|
|
@@ -1035,6 +1086,7 @@ async function parse(response) {
|
|
|
1035
1086
|
body = text;
|
|
1036
1087
|
}
|
|
1037
1088
|
}
|
|
1089
|
+
if (degradedOk && response.status === 503 && isHealthReport(body)) return body;
|
|
1038
1090
|
if (!response.ok) {
|
|
1039
1091
|
const header = response.headers.get("Retry-After");
|
|
1040
1092
|
const retryAfter = header !== null && !Number.isNaN(Number(header)) ? Number(header) : 0;
|
|
@@ -1042,6 +1094,9 @@ async function parse(response) {
|
|
|
1042
1094
|
}
|
|
1043
1095
|
return body;
|
|
1044
1096
|
}
|
|
1097
|
+
function isHealthReport(body) {
|
|
1098
|
+
return body !== null && typeof body === "object" && "status" in body;
|
|
1099
|
+
}
|
|
1045
1100
|
function isAbort(error) {
|
|
1046
1101
|
return error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
|
|
1047
1102
|
}
|
|
@@ -1098,6 +1153,7 @@ function intField(body, name) {
|
|
|
1098
1153
|
}
|
|
1099
1154
|
export {
|
|
1100
1155
|
APIError,
|
|
1156
|
+
AlreadyExists,
|
|
1101
1157
|
Blocked,
|
|
1102
1158
|
Capabilities,
|
|
1103
1159
|
CrawlPage,
|