apify-client 3.0.0-beta.9 → 3.0.0-beta.90

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 (122) hide show
  1. package/README.md +16 -2
  2. package/dist/apify_api_error.d.ts +13 -27
  3. package/dist/apify_api_error.js +33 -23
  4. package/dist/apify_client.d.ts +125 -10
  5. package/dist/apify_client.js +133 -48
  6. package/dist/apify_client_error.d.ts +10 -0
  7. package/dist/apify_client_error.js +10 -0
  8. package/dist/base/api_client.d.ts +7 -7
  9. package/dist/base/api_client.js +36 -36
  10. package/dist/base/resource_client.d.ts +21 -8
  11. package/dist/base/resource_client.js +70 -36
  12. package/dist/base/resource_collection_client.d.ts +12 -4
  13. package/dist/base/resource_collection_client.js +34 -11
  14. package/dist/body_parser.d.ts +3 -4
  15. package/dist/body_parser.js +19 -26
  16. package/dist/bundle.js +27 -22
  17. package/dist/bundle.js.map +1 -1
  18. package/dist/generated/api.d.ts +3040 -971
  19. package/dist/generated/schemas.d.ts +2369 -934
  20. package/dist/generated/schemas.js +570 -229
  21. package/dist/http_clients/axios.d.ts +61 -0
  22. package/dist/http_clients/axios.js +119 -0
  23. package/dist/http_clients/base.d.ts +386 -0
  24. package/dist/http_clients/base.js +650 -0
  25. package/dist/http_clients/index.d.ts +4 -0
  26. package/dist/http_clients/index.js +2 -0
  27. package/dist/http_compressors/base.d.ts +40 -0
  28. package/dist/http_compressors/base.js +9 -0
  29. package/dist/http_compressors/brotli.d.ts +33 -0
  30. package/dist/http_compressors/brotli.js +39 -0
  31. package/dist/http_compressors/gzip.d.ts +33 -0
  32. package/dist/http_compressors/gzip.js +39 -0
  33. package/dist/http_compressors/index.d.ts +6 -0
  34. package/dist/http_compressors/index.js +2 -0
  35. package/dist/http_compressors/resolve.d.ts +23 -0
  36. package/dist/http_compressors/resolve.js +27 -0
  37. package/dist/index.d.ts +6 -1
  38. package/dist/index.js +5 -1
  39. package/dist/invalid_response_body_error.d.ts +14 -0
  40. package/dist/invalid_response_body_error.js +18 -0
  41. package/dist/models.d.ts +166 -243
  42. package/dist/models.js +6 -4
  43. package/dist/resource_clients/actor.d.ts +104 -34
  44. package/dist/resource_clients/actor.js +130 -56
  45. package/dist/resource_clients/actor_collection.d.ts +18 -12
  46. package/dist/resource_clients/actor_collection.js +11 -3
  47. package/dist/resource_clients/actor_env_var.d.ts +11 -4
  48. package/dist/resource_clients/actor_env_var.js +16 -6
  49. package/dist/resource_clients/actor_env_var_collection.d.ts +9 -4
  50. package/dist/resource_clients/actor_env_var_collection.js +11 -4
  51. package/dist/resource_clients/actor_server.d.ts +141 -0
  52. package/dist/resource_clients/actor_server.js +195 -0
  53. package/dist/resource_clients/actor_version.d.ts +20 -5
  54. package/dist/resource_clients/actor_version.js +19 -9
  55. package/dist/resource_clients/actor_version_collection.d.ts +11 -4
  56. package/dist/resource_clients/actor_version_collection.js +13 -4
  57. package/dist/resource_clients/build.d.ts +20 -7
  58. package/dist/resource_clients/build.js +35 -15
  59. package/dist/resource_clients/build_collection.d.ts +7 -5
  60. package/dist/resource_clients/build_collection.js +4 -1
  61. package/dist/resource_clients/dataset.d.ts +83 -37
  62. package/dist/resource_clients/dataset.js +107 -121
  63. package/dist/resource_clients/dataset_collection.d.ts +10 -6
  64. package/dist/resource_clients/dataset_collection.js +13 -2
  65. package/dist/resource_clients/key_value_store.d.ts +108 -26
  66. package/dist/resource_clients/key_value_store.js +134 -52
  67. package/dist/resource_clients/key_value_store_collection.d.ts +10 -6
  68. package/dist/resource_clients/key_value_store_collection.js +13 -2
  69. package/dist/resource_clients/log.d.ts +40 -21
  70. package/dist/resource_clients/log.js +144 -66
  71. package/dist/resource_clients/request_queue.d.ts +76 -31
  72. package/dist/resource_clients/request_queue.js +178 -93
  73. package/dist/resource_clients/request_queue_collection.d.ts +9 -5
  74. package/dist/resource_clients/request_queue_collection.js +9 -3
  75. package/dist/resource_clients/run.d.ts +126 -28
  76. package/dist/resource_clients/run.js +193 -49
  77. package/dist/resource_clients/run_collection.d.ts +5 -3
  78. package/dist/resource_clients/run_collection.js +4 -1
  79. package/dist/resource_clients/schedule.d.ts +16 -7
  80. package/dist/resource_clients/schedule.js +30 -22
  81. package/dist/resource_clients/schedule_collection.d.ts +6 -2
  82. package/dist/resource_clients/schedule_collection.js +9 -3
  83. package/dist/resource_clients/store_collection.d.ts +6 -4
  84. package/dist/resource_clients/store_collection.js +4 -1
  85. package/dist/resource_clients/task.d.ts +36 -13
  86. package/dist/resource_clients/task.js +79 -46
  87. package/dist/resource_clients/task_collection.d.ts +9 -5
  88. package/dist/resource_clients/task_collection.js +9 -3
  89. package/dist/resource_clients/user.d.ts +19 -10
  90. package/dist/resource_clients/user.js +42 -38
  91. package/dist/resource_clients/webhook.d.ts +17 -8
  92. package/dist/resource_clients/webhook.js +30 -22
  93. package/dist/resource_clients/webhook_collection.d.ts +8 -4
  94. package/dist/resource_clients/webhook_collection.js +9 -3
  95. package/dist/resource_clients/webhook_dispatch.d.ts +4 -1
  96. package/dist/resource_clients/webhook_dispatch.js +7 -2
  97. package/dist/resource_clients/webhook_dispatch_collection.d.ts +3 -1
  98. package/dist/resource_clients/webhook_dispatch_collection.js +4 -1
  99. package/dist/response_validation_error.d.ts +2 -1
  100. package/dist/response_validation_error.js +2 -1
  101. package/dist/runtime/node.d.ts +6 -0
  102. package/dist/runtime/node.js +80 -0
  103. package/dist/runtime/types.d.ts +60 -0
  104. package/dist/runtime/types.js +1 -0
  105. package/dist/runtime/web.d.ts +5 -0
  106. package/dist/runtime/web.js +21 -0
  107. package/dist/schemas.d.ts +368 -4
  108. package/dist/schemas.js +26 -4
  109. package/dist/statistics.d.ts +1 -6
  110. package/dist/statistics.js +2 -2
  111. package/dist/timeouts.d.ts +84 -0
  112. package/dist/timeouts.js +37 -0
  113. package/dist/timezones.d.ts +1 -1
  114. package/dist/utils.d.ts +89 -59
  115. package/dist/utils.js +216 -158
  116. package/dist/wait_for_resources.d.ts +8 -0
  117. package/dist/wait_for_resources.js +39 -0
  118. package/package.json +37 -34
  119. package/dist/http_client.d.ts +0 -88
  120. package/dist/http_client.js +0 -255
  121. package/dist/interceptors.d.ts +0 -19
  122. package/dist/interceptors.js +0 -105
@@ -0,0 +1,61 @@
1
+ import type http from 'node:http';
2
+ import type https from 'node:https';
3
+ import type { AxiosInstance, AxiosInterceptorManager, InternalAxiosRequestConfig } from 'axios';
4
+ import type { HttpClientOptions, HttpRequest, HttpResponse } from './base.js';
5
+ import { HttpClient } from './base.js';
6
+ /**
7
+ * An [axios request interceptor](https://axios-http.com/docs/interceptors). It runs on every attempt, right before
8
+ * the request is handed to axios, and sees the request as the shared pipeline prepared it: headers merged and the
9
+ * body already serialized and compressed.
10
+ */
11
+ export type RequestInterceptorFunction = Parameters<AxiosInterceptorManager<InternalAxiosRequestConfig>['use']>[0];
12
+ /**
13
+ * Configuration of {@link AxiosHttpClient}.
14
+ */
15
+ export interface AxiosHttpClientOptions extends HttpClientOptions {
16
+ /** @default [] */
17
+ requestInterceptors?: RequestInterceptorFunction[];
18
+ }
19
+ /**
20
+ * The default HTTP client of {@link ApifyClient}, built on [axios](https://axios-http.com).
21
+ *
22
+ * It inherits the request pipeline from {@link HttpClient} and adds the transport: in Node.js, keep-alive agents
23
+ * that honor the `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` environment variables; in the browser, the XHR
24
+ * adapter of axios. Network errors are retried, timeouts included, and a stream body is sent without following
25
+ * redirects, since the part of it already sent could not be replayed.
26
+ */
27
+ export declare class AxiosHttpClient extends HttpClient {
28
+ #private;
29
+ /** The axios instance the requests go through. */
30
+ axios: AxiosInstance;
31
+ /**
32
+ * Keep-alive agent for plain HTTP, created with the first request in Node.js. It is the same `ProxyAgent` as
33
+ * {@link httpsAgent}, so the socket pool is shared across both schemes.
34
+ */
35
+ httpAgent?: http.Agent;
36
+ /** Keep-alive agent for HTTPS. The same instance as {@link httpAgent}. */
37
+ httpsAgent?: https.Agent;
38
+ constructor(options?: AxiosHttpClientOptions);
39
+ /**
40
+ * A timeout is an axios error coded `ECONNABORTED` or `ETIMEDOUT`, besides the `TimeoutError` the base class
41
+ * recognizes.
42
+ */
43
+ isTimeoutError(error: unknown): boolean;
44
+ /**
45
+ * A network failure is an axios error that carries the request it was sending: a connection that could not be
46
+ * made, dropped mid-way or timed out. Errors raised before a request exists, such as an invalid URL, are not
47
+ * retried.
48
+ */
49
+ isRetryableTransportError(error: unknown): boolean;
50
+ /**
51
+ * Destroys the keep-alive agents, closing every pooled socket. A client that never sent a request in Node.js
52
+ * has nothing to close.
53
+ */
54
+ close(): Promise<void>;
55
+ /**
56
+ * Sends the request through axios and hands the raw response back. A stream body is sent without following
57
+ * redirects, since the part of it already sent could not be replayed, and so is a request with
58
+ * `followRedirects: false`. In the browser, the browser follows redirects itself.
59
+ */
60
+ sendRequest(request: HttpRequest): Promise<HttpResponse>;
61
+ }
@@ -0,0 +1,119 @@
1
+ import axios, { AxiosError, AxiosHeaders } from 'axios';
2
+ import { runtime } from '#runtime';
3
+ import { isStream } from '../utils.js';
4
+ import { HttpClient } from './base.js';
5
+ /**
6
+ * The default HTTP client of {@link ApifyClient}, built on [axios](https://axios-http.com).
7
+ *
8
+ * It inherits the request pipeline from {@link HttpClient} and adds the transport: in Node.js, keep-alive agents
9
+ * that honor the `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` environment variables; in the browser, the XHR
10
+ * adapter of axios. Network errors are retried, timeouts included, and a stream body is sent without following
11
+ * redirects, since the part of it already sent could not be replayed.
12
+ */
13
+ export class AxiosHttpClient extends HttpClient {
14
+ /** The axios instance the requests go through. */
15
+ axios;
16
+ /**
17
+ * Keep-alive agent for plain HTTP, created with the first request in Node.js. It is the same `ProxyAgent` as
18
+ * {@link httpsAgent}, so the socket pool is shared across both schemes.
19
+ */
20
+ httpAgent;
21
+ /** Keep-alive agent for HTTPS. The same instance as {@link httpAgent}. */
22
+ httpsAgent;
23
+ #httpAgentsPromise;
24
+ constructor(options = {}) {
25
+ super(options);
26
+ this.axios = axios.create({
27
+ // The agents handle the proxy environment variables.
28
+ proxy: false,
29
+ validateStatus: null,
30
+ // The shared pipeline serializes and parses the bodies, so axios only moves bytes.
31
+ transformRequest: [],
32
+ transformResponse: [],
33
+ responseType: 'arraybuffer',
34
+ // maxBodyLength needs to be Infinity, because -1 falls back to a 10 MB default
35
+ // from an axios subdependency - 'follow-redirects'
36
+ maxBodyLength: Infinity,
37
+ // maxContentLength must be -1, because Infinity will cause axios to run super slow
38
+ // thanks to a bug that's now fixed, but not released yet https://github.com/axios/axios/pull/3738
39
+ maxContentLength: -1,
40
+ });
41
+ // The pipeline merges every header the client sends, so the axios defaults would only get in the way.
42
+ this.axios.defaults.headers = new AxiosHeaders();
43
+ for (const interceptor of options.requestInterceptors ?? []) {
44
+ this.axios.interceptors.request.use(interceptor);
45
+ }
46
+ }
47
+ /**
48
+ * A timeout is an axios error coded `ECONNABORTED` or `ETIMEDOUT`, besides the `TimeoutError` the base class
49
+ * recognizes.
50
+ */
51
+ isTimeoutError(error) {
52
+ if (super.isTimeoutError(error))
53
+ return true;
54
+ // Axios aborts the request when its own timeout fires, which gives ECONNABORTED, or ETIMEDOUT under
55
+ // `clarifyTimeoutError`. ETIMEDOUT also arrives straight from the socket, when the connection itself
56
+ // times out.
57
+ return (axios.isAxiosError(error) && (error.code === AxiosError.ECONNABORTED || error.code === AxiosError.ETIMEDOUT));
58
+ }
59
+ /**
60
+ * A network failure is an axios error that carries the request it was sending: a connection that could not be
61
+ * made, dropped mid-way or timed out. Errors raised before a request exists, such as an invalid URL, are not
62
+ * retried.
63
+ */
64
+ isRetryableTransportError(error) {
65
+ if (!axios.isAxiosError(error))
66
+ return false;
67
+ return typeof error.request === 'object' && error.request !== null && error.config != null;
68
+ }
69
+ /**
70
+ * Destroys the keep-alive agents, closing every pooled socket. A client that never sent a request in Node.js
71
+ * has nothing to close.
72
+ */
73
+ async close() {
74
+ // A failed initialization left nothing to release, and its error belongs to the request that hit it.
75
+ await this.#httpAgentsPromise?.catch(() => { });
76
+ this.httpAgent?.destroy();
77
+ this.httpsAgent?.destroy();
78
+ }
79
+ /**
80
+ * Sends the request through axios and hands the raw response back. A stream body is sent without following
81
+ * redirects, since the part of it already sent could not be replayed, and so is a request with
82
+ * `followRedirects: false`. In the browser, the browser follows redirects itself.
83
+ */
84
+ async sendRequest(request) {
85
+ await this.#ensureHttpAgents();
86
+ const { method, url, headers, body, timeoutMillis, stream, followRedirects, signal } = request;
87
+ const response = await this.axios.request({
88
+ method,
89
+ url,
90
+ headers,
91
+ data: body,
92
+ // Axios reads 0 as no timeout.
93
+ timeout: timeoutMillis ?? 0,
94
+ signal,
95
+ responseType: stream ? 'stream' : 'arraybuffer',
96
+ // See axios/axios#1045 for why axios must not buffer a stream body to follow redirects. The XHR adapter
97
+ // ignores `maxRedirects`, since the browser follows redirects itself.
98
+ ...(isStream(body) || !followRedirects ? { maxRedirects: 0 } : {}),
99
+ });
100
+ return {
101
+ status: response.status,
102
+ headers: AxiosHeaders.from(response.headers).toJSON(),
103
+ body: response.data,
104
+ };
105
+ }
106
+ async #ensureHttpAgents() {
107
+ this.#httpAgentsPromise ??= this.#initHttpAgents();
108
+ return this.#httpAgentsPromise;
109
+ }
110
+ async #initHttpAgents() {
111
+ const agents = await runtime.createHttpAgents({ timeoutMillis: this.timeoutMaxMillis });
112
+ if (!agents)
113
+ return;
114
+ this.httpAgent = agents.httpAgent;
115
+ this.httpsAgent = agents.httpsAgent;
116
+ this.axios.defaults.httpAgent = this.httpAgent;
117
+ this.axios.defaults.httpsAgent = this.httpsAgent;
118
+ }
119
+ }
@@ -0,0 +1,386 @@
1
+ import type { Readable } from 'node:stream';
2
+ import { z } from 'zod';
3
+ import type { Log } from '@apify/log';
4
+ import type { HttpCompressor } from '../http_compressors/base.js';
5
+ import type { HttpCompressionAlgorithm } from '../http_compressors/resolve.js';
6
+ import type { HttpMethod } from '../models.js';
7
+ import { Statistics } from '../statistics.js';
8
+ import type { Timeout, TimeoutTier } from '../timeouts.js';
9
+ export type { HttpMethod } from '../models.js';
10
+ export declare const DEFAULT_MAX_RETRIES = 8;
11
+ export declare const DEFAULT_MIN_DELAY_BETWEEN_RETRIES_MILLIS = 500;
12
+ /**
13
+ * Bounds of the numeric {@link HttpClientOptions}. `ApifyClientOptions` checks the same bounds and adds the defaults.
14
+ * @internal
15
+ */
16
+ export declare const httpClientOptionsShape: {
17
+ maxRetries: z.ZodNumber;
18
+ minDelayBetweenRetriesMillis: z.ZodNumber;
19
+ timeoutShortSecs: z.ZodNumber;
20
+ timeoutMediumSecs: z.ZodNumber;
21
+ timeoutLongSecs: z.ZodNumber;
22
+ timeoutMaxSecs: z.ZodNumber;
23
+ };
24
+ /**
25
+ * Response headers keyed by lowercase header name. A header the server sent more than once may arrive as an array.
26
+ */
27
+ export type HttpResponseHeaders = Record<string, string | string[] | undefined>;
28
+ /**
29
+ * A request body as the transport receives it: already serialized, and compressed when that paid off. A `Readable`
30
+ * is passed through untouched and is only available in Node.js. A `Blob` body reaches a Node.js transport as a
31
+ * fresh `Readable` over its bytes for every attempt, and a transport in any other runtime as the `Blob` itself.
32
+ */
33
+ export type HttpRequestBody = string | Buffer | ArrayBuffer | ArrayBufferView | Readable | Blob;
34
+ /**
35
+ * A response body as the transport hands it back: the raw bytes, a `Readable` when the request asked for a streamed
36
+ * response, or `undefined` when the response carried no body.
37
+ */
38
+ export type HttpResponseBody = Buffer | ArrayBuffer | Readable | undefined;
39
+ /**
40
+ * How {@link HttpClient.call} hands back the response body.
41
+ *
42
+ * - `parsed` (the default) decodes it by content type: JSON becomes an object, text and XML become a string, anything
43
+ * else stays a `Buffer` (an `ArrayBuffer` in the browser).
44
+ * - `buffer` skips the decoding and hands back the raw bytes.
45
+ * - `stream` hands back a `Readable` with the body unread. Node.js only.
46
+ */
47
+ export type ApifyResponseType = 'parsed' | 'buffer' | 'stream';
48
+ /**
49
+ * A request as the resource clients hand it to {@link HttpClient.call}.
50
+ */
51
+ export interface ApifyRequestConfig {
52
+ /** Full URL of the endpoint, without the query string. */
53
+ url: string;
54
+ /** HTTP method. */
55
+ method: HttpMethod;
56
+ /**
57
+ * Query parameters. `undefined` values are dropped, booleans are sent as `1` and `0`, `Date` values as ISO 8601
58
+ * strings and arrays comma-separated.
59
+ */
60
+ params?: Record<string, unknown>;
61
+ /** Per-request headers. They win over the client's default headers, header names compared case-insensitively. */
62
+ headers?: Record<string, string>;
63
+ /**
64
+ * Request body. A plain object or array is serialized to JSON and sent as `application/json`, or form-encoded
65
+ * when a `Content-Type: application/x-www-form-urlencoded` header asks for it. A string, binary value
66
+ * (`Buffer`, `ArrayBuffer`, typed array) or `Readable` is sent as it is, and `URLSearchParams` is sent
67
+ * form-encoded. A `Blob` or `File`, such as one from `fs.openAsBlob()`, is streamed without being held in
68
+ * memory, under its own `type` when no `Content-Type` header is set. A `FormData` or web `ReadableStream` is
69
+ * rejected with a `TypeError`, since serializing one would send an empty body.
70
+ */
71
+ data?: unknown;
72
+ /**
73
+ * Timeout of the request: a tier name, a number of seconds, or `'noTimeout'`. The client resolves it to the
74
+ * timeout of each attempt in milliseconds, doubling it with every retry up to `timeoutMaxSecs`.
75
+ * @default 'medium'
76
+ */
77
+ timeoutSecs?: Timeout;
78
+ /** @default 'parsed' */
79
+ responseType?: ApifyResponseType;
80
+ /**
81
+ * Serialize function-valued fields of a JSON body to their source instead of dropping them, which is how
82
+ * Actor input carrying page functions reaches the API.
83
+ */
84
+ stringifyFunctions?: boolean;
85
+ /** Give up on the first transport timeout instead of retrying it. */
86
+ doNotRetryTimeouts?: boolean;
87
+ /**
88
+ * How to compress the request body: an {@link HttpCompressor} for this request only, or `false` to send the body
89
+ * uncompressed. Defaults to the client's {@link HttpClient.httpCompressor}.
90
+ */
91
+ compression?: HttpCompressor | false;
92
+ /**
93
+ * Header that carries the client's API token for this request. The Apify API reads `Authorization`. Actor
94
+ * servers also accept `X-Apify-Authorization`, which the platform removes before the request reaches the Actor,
95
+ * so the `Authorization` header stays free for the Actor's own authentication. A per-request header of either
96
+ * name still wins.
97
+ * @default 'Authorization'
98
+ */
99
+ authorizationHeader?: 'Authorization' | 'X-Apify-Authorization';
100
+ /**
101
+ * Whether an error status throws {@link ApifyApiError}. With `false`, the call resolves to the error response
102
+ * once no retry follows, and a rate limit (429) doesn't count toward the client's statistics, which track the
103
+ * API's rate limits.
104
+ * @default true
105
+ */
106
+ throwOnErrorStatus?: boolean;
107
+ /** Status codes to retry. Defaults to rate limits (429) and server errors (5xx). */
108
+ retryStatusCodes?: readonly number[];
109
+ /**
110
+ * Whether transport errors, timeouts included, are retried. With `false`, the first one fails the call, since the
111
+ * request may have reached the server before it failed.
112
+ * @default true
113
+ */
114
+ retryTransportErrors?: boolean;
115
+ /**
116
+ * Whether the transport follows redirects. With `false`, a redirect response is handled like an error status, so
117
+ * headers that carry the token never go to a host the server picked.
118
+ * @default true
119
+ */
120
+ followRedirects?: boolean;
121
+ /**
122
+ * Aborts the call. Once the signal aborts, the attempt in flight is ended, no retry follows, and the call
123
+ * rejects with the signal's `reason`.
124
+ */
125
+ signal?: AbortSignal;
126
+ }
127
+ /**
128
+ * A response as {@link HttpClient.call} resolves to it: a success, or an error response when the request sets
129
+ * {@link ApifyRequestConfig.throwOnErrorStatus} to `false`.
130
+ *
131
+ * @template T - Type of the parsed body.
132
+ */
133
+ export interface ApifyResponse<T = any> {
134
+ /** HTTP status code. */
135
+ status: number;
136
+ /** Response headers keyed by lowercase header name. */
137
+ headers: HttpResponseHeaders;
138
+ /** The response body, decoded according to the request's {@link ApifyRequestConfig.responseType}. */
139
+ data: T;
140
+ /** The request this response answers, as it was passed to {@link HttpClient.call}. */
141
+ config: ApifyRequestConfig;
142
+ }
143
+ /**
144
+ * One prepared request attempt, as {@link HttpClient.sendRequest} receives it from the shared pipeline.
145
+ */
146
+ export interface HttpRequest {
147
+ /** HTTP method. */
148
+ method: HttpMethod;
149
+ /** Full request URL with the query string already encoded into it. */
150
+ url: string;
151
+ /** Final request headers, with the client's default headers already merged in. */
152
+ headers: Record<string, string>;
153
+ /** Request body, already serialized and compressed, or `undefined` for a request without one. */
154
+ body?: HttpRequestBody;
155
+ /**
156
+ * Timeout for this attempt in milliseconds, or `undefined` for a request that runs without one, which is what
157
+ * `timeoutSecs: 'noTimeout'` asks for.
158
+ */
159
+ timeoutMillis?: number;
160
+ /** Whether to hand the body back unread as a `Readable`, so the caller can stream it. */
161
+ stream: boolean;
162
+ /**
163
+ * Whether to follow redirects. With `false`, return a redirect response as it is: the request carries a token
164
+ * that must not follow a redirect to another host.
165
+ */
166
+ followRedirects: boolean;
167
+ /**
168
+ * The caller's abort signal, to hand to the HTTP library alongside the timeout. The pipeline stops retrying
169
+ * once it aborts, so the transport only has to end the request in flight.
170
+ */
171
+ signal?: AbortSignal;
172
+ }
173
+ /**
174
+ * A response as the transport returns it from {@link HttpClient.sendRequest}, error statuses included.
175
+ */
176
+ export interface HttpResponse {
177
+ /** HTTP status code. */
178
+ status: number;
179
+ /** Response headers keyed by lowercase header name. */
180
+ headers: HttpResponseHeaders;
181
+ /** The body as raw bytes, or unread as a `Readable` when the request asked for a stream. */
182
+ body: HttpResponseBody;
183
+ }
184
+ /**
185
+ * Configuration shared by every {@link HttpClient}.
186
+ */
187
+ export interface HttpClientOptions {
188
+ /** Apify API token, sent as a `Bearer` token in the `Authorization` header. */
189
+ token?: string;
190
+ /** How many times a failed request is retried at most. @default 8 */
191
+ maxRetries?: number;
192
+ /**
193
+ * Lower bound for the delay before the first retry in milliseconds. It doubles with every further retry.
194
+ * @default 500
195
+ */
196
+ minDelayBetweenRetriesMillis?: number;
197
+ /** Duration of the `short` timeout tier, in seconds. @default 5 */
198
+ timeoutShortSecs?: number;
199
+ /** Duration of the `medium` timeout tier, in seconds. @default 30 */
200
+ timeoutMediumSecs?: number;
201
+ /** Duration of the `long` timeout tier, in seconds. @default 360 */
202
+ timeoutLongSecs?: number;
203
+ /** Upper bound for the timeout of a single attempt, in seconds. @default 360 */
204
+ timeoutMaxSecs?: number;
205
+ /**
206
+ * Compression of request bodies: the name of a built-in algorithm, or an {@link HttpCompressor} for a custom
207
+ * quality or algorithm.
208
+ * @default 'brotli'
209
+ */
210
+ compression?: HttpCompressionAlgorithm | HttpCompressor;
211
+ /** Additional headers sent with every request. They win over the built-in defaults. */
212
+ headers?: Record<string, string>;
213
+ /** Statistics the client records its calls into. Created when omitted. */
214
+ stats?: Statistics;
215
+ /** Logger for the retry warnings. Defaults to a child of the `@apify/log` default with an `ApifyClient` prefix. */
216
+ logger?: Log;
217
+ /** Value of the `X-Apify-Workflow-Key` header. Defaults to the `APIFY_WORKFLOW_KEY` environment variable. */
218
+ workflowKey?: string;
219
+ /** @internal */
220
+ userAgentSuffix?: string | string[];
221
+ }
222
+ /**
223
+ * Base class for the HTTP clients used by {@link ApifyClient}.
224
+ *
225
+ * It holds the shared request pipeline: {@link call} merges the default headers in, serializes and compresses the
226
+ * body, encodes the query parameters, retries transient failures with exponential backoff, grows the timeout with
227
+ * every attempt, decodes the response body by content type, records statistics and converts error statuses to
228
+ * {@link ApifyApiError}. A concrete client only has to implement {@link sendRequest}, the transport that moves one
229
+ * prepared request over the wire, and can override the classification and lifecycle hooks {@link isTimeoutError},
230
+ * {@link isRetryableTransportError} and {@link close}.
231
+ *
232
+ * Overriding {@link call} itself is also supported and bypasses the transport hooks entirely. Such a client has
233
+ * to send the default headers from `defaultHeaders` with every request, otherwise the `Authorization` header never
234
+ * reaches the API. It also has to honor the per-request options {@link ApifyRequestConfig.compression},
235
+ * {@link ApifyRequestConfig.authorizationHeader}, {@link ApifyRequestConfig.throwOnErrorStatus},
236
+ * {@link ApifyRequestConfig.retryStatusCodes}, {@link ApifyRequestConfig.retryTransportErrors} and
237
+ * {@link ApifyRequestConfig.followRedirects}.
238
+ * {@link ActorServerClient.request} relies on them to keep the token away from the Actor's code, to return the
239
+ * server's error responses and to avoid sending a request to the Actor twice. The protected helpers
240
+ * `prepareRequest()`, `buildUrl()` and `computeTimeoutMillis()` stay available to it.
241
+ *
242
+ * @example
243
+ * ```javascript
244
+ * import { ApifyClient, HttpClient } from 'apify-client';
245
+ *
246
+ * class FetchHttpClient extends HttpClient {
247
+ * async sendRequest({ method, url, headers, body, timeoutMillis, signal }) {
248
+ * const signals = signal ? [signal] : [];
249
+ * if (timeoutMillis !== undefined) signals.push(AbortSignal.timeout(timeoutMillis));
250
+ * const response = await fetch(url, { method, headers, body, signal: AbortSignal.any(signals) });
251
+ * return {
252
+ * status: response.status,
253
+ * headers: Object.fromEntries(response.headers),
254
+ * body: Buffer.from(await response.arrayBuffer()),
255
+ * };
256
+ * }
257
+ *
258
+ * isRetryableTransportError(error) {
259
+ * // Without this the client gives up on the first connection failure.
260
+ * return this.isTimeoutError(error) || error instanceof TypeError;
261
+ * }
262
+ * }
263
+ *
264
+ * const client = ApifyClient.withCustomHttpClient({ token: 'my-token', httpClient: new FetchHttpClient() });
265
+ * ```
266
+ */
267
+ export declare abstract class HttpClient {
268
+ #private;
269
+ /** Statistics of the API calls made through this client. */
270
+ stats: Statistics;
271
+ /** Logger for the retry warnings. */
272
+ logger: Log;
273
+ /** How many times a failed request is retried at most. */
274
+ maxRetries: number;
275
+ /** Lower bound for the delay before the first retry in milliseconds. It doubles with every further retry. */
276
+ minDelayBetweenRetriesMillis: number;
277
+ /** Duration of each timeout tier, in milliseconds. */
278
+ timeoutMillis: Record<TimeoutTier, number>;
279
+ /** Upper bound for the timeout of a single attempt, in milliseconds. */
280
+ timeoutMaxMillis: number;
281
+ /** Compressor the request pipeline runs the bodies worth compressing through. */
282
+ readonly httpCompressor: HttpCompressor;
283
+ /**
284
+ * Headers sent with every request: the `Authorization` header built from the token, the `User-Agent` where the
285
+ * runtime lets a client set one, the `X-Apify-Workflow-Key` when a workflow key is configured, and whatever
286
+ * {@link HttpClientOptions.headers} added.
287
+ */
288
+ protected readonly defaultHeaders: Record<string, string>;
289
+ /**
290
+ * @param options - Configuration of the pipeline. The retry and timeout options are validated the same way the
291
+ * `ApifyClient` constructor validates them.
292
+ * @throws {ArgumentValidationError} When a retry or timeout option is out of bounds.
293
+ */
294
+ constructor(options?: HttpClientOptions);
295
+ /**
296
+ * Sets the `Authorization` header from the token, unless an authorization header is already configured.
297
+ *
298
+ * @param token - The Apify API token to send as the `Bearer` token.
299
+ */
300
+ setDefaultAuthorization(token: string): void;
301
+ /**
302
+ * Whether an error thrown by the transport is a timeout.
303
+ *
304
+ * Recognizes errors named `TimeoutError`, which is what `AbortSignal.timeout()` produces. Transports extend it
305
+ * with the timeout errors their HTTP library throws. The classification is independent of retryability: a
306
+ * timeout the retry loop should retry has to be covered by {@link isRetryableTransportError} too.
307
+ */
308
+ isTimeoutError(error: unknown): boolean;
309
+ /**
310
+ * Whether an error thrown by the transport is worth retrying.
311
+ *
312
+ * The default classifies nothing as retryable, so a transport that does not override it gives up on the first
313
+ * connection failure. Every transport should map its own transient errors here: connection resets, refused
314
+ * connections, timeouts and the like. Error responses are not the transport's concern, the pipeline decides on
315
+ * them from the status code.
316
+ */
317
+ isRetryableTransportError(_error: unknown): boolean;
318
+ /**
319
+ * Releases resources owned by the transport, such as a connection pool. The default does nothing.
320
+ */
321
+ close(): Promise<void>;
322
+ /**
323
+ * Sends one prepared request through the underlying HTTP library.
324
+ *
325
+ * The inherited {@link call} needs it, so every transport has to implement it. Let the library's errors
326
+ * propagate unwrapped: {@link call} classifies them through {@link isRetryableTransportError} and
327
+ * {@link isTimeoutError}. Return error responses as they are too, the pipeline turns them into
328
+ * {@link ApifyApiError} and decides whether to retry. Reject when the connection drops before the body is
329
+ * complete: the pipeline takes a returned body as whole and does not retry one that fails to parse. When
330
+ * `request.followRedirects` is `false`, return a redirect response as it is, since the request carries a token.
331
+ *
332
+ * @param request - The request to send, with the headers merged, the body serialized and the query encoded.
333
+ * @returns The response, with the body unread when `request.stream` is set and as raw bytes otherwise.
334
+ */
335
+ sendRequest(request: HttpRequest): Promise<HttpResponse>;
336
+ /**
337
+ * Makes an API request with automatic retries and exponential backoff.
338
+ *
339
+ * Network errors the transport classifies as retryable, rate limits (HTTP 429) and server errors (HTTP 5xx)
340
+ * are retried up to {@link maxRetries} times, and `config.retryStatusCodes` picks other statuses to retry. Any
341
+ * other error status is thrown as {@link ApifyApiError} right away, or returned when `config.throwOnErrorStatus`
342
+ * is `false`. A request whose body is a `Readable` is never retried, since part of the stream has already been
343
+ * consumed by the time the failure shows. A `Blob` body is read again for every attempt, so it is retried like
344
+ * any other, unless reading the blob itself fails: that error is thrown right away, with the transport error
345
+ * as its `cause` when that error does not already wrap it. Aborting `config.signal` ends the attempt in flight,
346
+ * skips the remaining retries and rejects the call with the signal's `reason`.
347
+ *
348
+ * @template T - Type of the parsed response body.
349
+ * @param config - The request to make.
350
+ * @returns The successful response, or the error response when `config.throwOnErrorStatus` is `false`.
351
+ * @throws {ApifyApiError} When the API responds with an error status the retries could not fix, unless
352
+ * `config.throwOnErrorStatus` is `false`.
353
+ */
354
+ call<T = any>(config: ApifyRequestConfig): Promise<ApifyResponse<T>>;
355
+ /**
356
+ * Prepares the headers and the body of a request.
357
+ *
358
+ * Merges the client's default headers with the per-request ones, header names compared case-insensitively and the
359
+ * per-request values winning, after moving the default `Authorization` header to `X-Apify-Authorization` when
360
+ * `config.authorizationHeader` asks for it. Serializes an object body to JSON, setting
361
+ * `Content-Type: application/json` unless the caller supplied a content type. Runs the body through
362
+ * {@link httpCompressor}, or the compressor in `config.compression`, unless `config.compression` is `false`, a
363
+ * `Content-Encoding` header is already set, the body is too small, or its content type says the payload is already
364
+ * compressed. A caller-supplied `Content-Encoding` is forwarded as it is, which is how a pre-encoded body is
365
+ * uploaded, and `Content-Encoding: identity` opts a single request out of compression.
366
+ */
367
+ protected prepareRequest(config: ApifyRequestConfig): Promise<{
368
+ headers: Record<string, string>;
369
+ body: HttpRequestBody | undefined;
370
+ }>;
371
+ /**
372
+ * Appends the query parameters to the URL. `undefined` values are dropped, booleans are sent as `1` and `0`,
373
+ * `Date` values as ISO 8601 strings and arrays comma-separated.
374
+ */
375
+ protected buildUrl(url: string, params?: Record<string, unknown>): string;
376
+ /**
377
+ * Resolves `timeoutSecs` to the number of milliseconds the given attempt gets. A tier name resolves to its
378
+ * configured duration, a number is taken as seconds, and `'noTimeout'` becomes `undefined`. The result doubles
379
+ * with each attempt and is capped at `timeoutMaxMillis`. A requested value above the cap is capped too, which
380
+ * warns once, since it does not take effect in full.
381
+ *
382
+ * @param attempt - Current attempt number, starting at 1.
383
+ * @param timeoutSecs - The request's timeout. Defaults to the `medium` tier.
384
+ */
385
+ protected computeTimeoutMillis(attempt: number, timeoutSecs?: Timeout): number | undefined;
386
+ }