apify-client 3.0.0-beta.20 → 3.0.0-beta.22

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.
@@ -4,8 +4,8 @@ import { APIFY_ENV_VARS } from '@apify/consts';
4
4
  import { concatStreamToBuffer } from '@apify/utilities';
5
5
  import { ApifyApiError } from './apify_api_error.js';
6
6
  import { InvalidResponseBodyError, requestInterceptors, responseInterceptors } from './interceptors.js';
7
- import { asArray, cast, getVersionData, isNode, isStream } from './utils.js';
8
- const { version } = getVersionData();
7
+ import { runtime } from '#runtime';
8
+ import { asArray, cast, getEnv, isStream, version } from './utils.js';
9
9
  const RATE_LIMIT_EXCEEDED_STATUS_CODE = 429;
10
10
  export class HttpClient {
11
11
  stats;
@@ -21,8 +21,7 @@ export class HttpClient {
21
21
  httpsAgent;
22
22
  axios;
23
23
  workflowKey;
24
- #nodeInitPromise;
25
- #userAgentSuffix;
24
+ #httpAgentsPromise;
26
25
  constructor(options) {
27
26
  const { token } = options;
28
27
  this.stats = options.apifyClientStats;
@@ -36,8 +35,7 @@ export class HttpClient {
36
35
  };
37
36
  this.timeoutMaxMillis = options.timeoutMaxSecs * 1000;
38
37
  this.logger = options.logger;
39
- this.workflowKey = options.workflowKey || process.env[APIFY_ENV_VARS.WORKFLOW_KEY];
40
- this.#userAgentSuffix = options.userAgentSuffix;
38
+ this.workflowKey = options.workflowKey || getEnv(APIFY_ENV_VARS.WORKFLOW_KEY);
41
39
  this.axios = axios.create({
42
40
  // Disable axios's built-in proxy handling since we're using custom agents
43
41
  proxy: false,
@@ -79,64 +77,34 @@ export class HttpClient {
79
77
  if (token) {
80
78
  this.axios.defaults.headers.Authorization = `Bearer ${token}`;
81
79
  }
80
+ // Browsers do not let a page set the header, so it is only sent where the runtime describes its platform.
81
+ if (runtime.platform) {
82
+ const isAtHome = !!getEnv(APIFY_ENV_VARS.IS_AT_HOME);
83
+ let userAgent = `ApifyClient/${version} (${runtime.platform}); isAtHome/${isAtHome}`;
84
+ if (options.userAgentSuffix) {
85
+ userAgent += `; ${asArray(options.userAgentSuffix).join('; ')}`;
86
+ }
87
+ this.axios.defaults.headers['User-Agent'] = userAgent;
88
+ }
82
89
  requestInterceptors.forEach((i) => this.axios.interceptors.request.use(i));
83
90
  this.userProvidedRequestInterceptors.forEach((i) => this.axios.interceptors.request.use(i));
84
91
  responseInterceptors.forEach((i) => this.axios.interceptors.response.use(i));
85
92
  }
86
- async #ensureNodeInit() {
87
- if (!isNode())
88
- return;
89
- this.#nodeInitPromise ??= this.#initNode();
90
- return this.#nodeInitPromise;
93
+ async #ensureHttpAgents() {
94
+ this.#httpAgentsPromise ??= this.#initHttpAgents();
95
+ return this.#httpAgentsPromise;
91
96
  }
92
- async #initNode() {
93
- if (!isNode())
97
+ async #initHttpAgents() {
98
+ const agents = await runtime.createHttpAgents({ timeoutMillis: this.timeoutMaxMillis });
99
+ if (!agents)
94
100
  return;
95
- const [{ ProxyAgent }, os] = await Promise.all([import('proxy-agent'), import('node:os')]);
96
- // We want to keep sockets alive for better performance.
97
- // Enhanced agent configuration based on agentkeepalive best practices:
98
- // - Nagle's algorithm disabled for lower latency
99
- // - Free socket timeout to prevent socket leaks
100
- // - LIFO scheduling to reuse recent sockets
101
- // - Socket TTL for connection freshness
102
- const agentOptions = {
103
- keepAlive: true,
104
- // Timeout for inactive sockets
105
- // Prevents socket leaks from idle connections
106
- timeout: this.timeoutMaxMillis,
107
- // Keep alive timeout for free sockets (15 seconds)
108
- // Node.js will close unused sockets after this period
109
- keepAliveMsecs: 15_000,
110
- // Maximum number of sockets per host
111
- maxSockets: 256,
112
- maxFreeSockets: 256,
113
- // LIFO scheduling - reuse most recently used sockets for better performance
114
- scheduling: 'lifo',
115
- };
116
- // Use ProxyAgent which automatically detects proxy from environment variables
117
- // and supports CONNECT tunneling
118
- const proxyAgent = new ProxyAgent(agentOptions);
119
- this.httpAgent = proxyAgent;
120
- this.httpsAgent = proxyAgent;
121
- // Disable Nagle's algorithm for lower latency
122
- // This sends data immediately instead of buffering small packets
123
- const setNoDelay = (socket) => {
124
- socket.setNoDelay(true);
125
- };
126
- this.httpAgent.on('socket', setNoDelay);
127
- this.httpsAgent.on('socket', setNoDelay);
101
+ this.httpAgent = agents.httpAgent;
102
+ this.httpsAgent = agents.httpsAgent;
128
103
  this.axios.defaults.httpAgent = this.httpAgent;
129
104
  this.axios.defaults.httpsAgent = this.httpsAgent;
130
- // Works only in Node. Cannot be set in browser
131
- const isAtHome = !!process.env[APIFY_ENV_VARS.IS_AT_HOME];
132
- let userAgent = `ApifyClient/${version} (${os.platform()}; Node/${process.version}); isAtHome/${isAtHome}`;
133
- if (this.#userAgentSuffix) {
134
- userAgent += `; ${asArray(this.#userAgentSuffix).join('; ')}`;
135
- }
136
- this.axios.defaults.headers['User-Agent'] = userAgent;
137
105
  }
138
106
  async call(config) {
139
- await this.#ensureNodeInit();
107
+ await this.#ensureHttpAgents();
140
108
  this.stats.calls++;
141
109
  const makeRequest = this.#createRequestHandler(config);
142
110
  return retry(makeRequest, {
@@ -1,7 +1,7 @@
1
1
  import axios, { AxiosHeaders } from 'axios';
2
2
  import contentTypeParser from 'content-type';
3
3
  import { maybeParseBody } from './body_parser.js';
4
- import { isCompressibleContentType, isNode, maybeCompressValue } from './utils.js';
4
+ import { isCompressibleContentType, maybeCompressValue } from './utils.js';
5
5
  /**
6
6
  * This error exists for the quite common situation, where only a partial JSON response is received and
7
7
  * an attempt to parse the JSON throws an error. In most cases this can be resolved by retrying the
@@ -100,8 +100,8 @@ function parseResponseData(response) {
100
100
  ) {
101
101
  return response;
102
102
  }
103
- const isBufferEmpty = isNode() ? !response.data.length : !response.data.byteLength;
104
- if (isBufferEmpty) {
103
+ // A `Buffer` from the Node.js adapter and an `ArrayBuffer` from the browser ones both carry `byteLength`.
104
+ if (!response.data.byteLength) {
105
105
  // undefined is better than an empty buffer
106
106
  response.data = undefined;
107
107
  return response;
@@ -158,13 +158,14 @@ export declare class DatasetClient<Data extends Record<string | number, any> = R
158
158
  /**
159
159
  * Stores one or more items into the dataset.
160
160
  *
161
- * Items can be objects, strings, or arrays thereof. Each item will be stored as a separate
162
- * record in the dataset. Objects are automatically serialized to JSON. If you provide an array,
163
- * all items will be stored in order. This method is idempotent - calling it multiple times
164
- * with the same data will not create duplicates, but will append items each time.
161
+ * Each item will be stored as a separate record in the dataset. Objects are automatically
162
+ * serialized to JSON. If you provide an array, all items will be stored in order. This method
163
+ * is idempotent - calling it multiple times with the same data will not create duplicates, but
164
+ * will append items each time.
165
165
  *
166
- * @param items - A single item (object or string) or an array of items to store.
167
- * Objects are automatically stringified to JSON. Strings are stored as-is.
166
+ * @param items - A single item, an array of items, or a string that is the JSON serialization of
167
+ * either - the API only accepts an object or an array of objects, so a plain string
168
+ * is not a valid item on its own.
168
169
  * @param options - Request options
169
170
  * @param options.timeoutSecs - Timeout for the API request. Default is `'medium'`.
170
171
  * @see https://docs.apify.com/api/v2/dataset-items-post
@@ -184,12 +185,9 @@ export declare class DatasetClient<Data extends Record<string | number, any> = R
184
185
  * { url: 'https://test.com', title: 'Test' },
185
186
  * { url: 'https://demo.com', title: 'Demo' }
186
187
  * ]);
187
- *
188
- * // Store string items
189
- * await client.dataset('my-dataset').pushItems(['item1', 'item2', 'item3']);
190
188
  * ```
191
189
  */
192
- pushItems(items: Data | Data[] | string | string[], options?: TimeoutOptions): Promise<void>;
190
+ pushItems(items: Data | Data[] | string, options?: TimeoutOptions): Promise<void>;
193
191
  /**
194
192
  * Gets statistical information about the dataset.
195
193
  *
@@ -43,7 +43,7 @@ const downloadItemsOptionsSchema = z.strictObject({
43
43
  signature: z.string().optional(),
44
44
  ...timeoutOptionsShape,
45
45
  });
46
- const pushItemsSchema = z.union([itemSchema, z.string(), z.array(z.union([itemSchema, z.string()]))]);
46
+ const pushItemsSchema = z.union([itemSchema, z.string(), z.array(itemSchema)]);
47
47
  // Apart from `timeoutSecs` and `expiresInSecs`, every option becomes a query parameter of the generated URL, so
48
48
  // `chunkSize` (client-side only) and `signature` (which this method produces) are left out. The options type
49
49
  // omits both to match.
@@ -255,13 +255,14 @@ export class DatasetClient extends ResourceClient {
255
255
  /**
256
256
  * Stores one or more items into the dataset.
257
257
  *
258
- * Items can be objects, strings, or arrays thereof. Each item will be stored as a separate
259
- * record in the dataset. Objects are automatically serialized to JSON. If you provide an array,
260
- * all items will be stored in order. This method is idempotent - calling it multiple times
261
- * with the same data will not create duplicates, but will append items each time.
258
+ * Each item will be stored as a separate record in the dataset. Objects are automatically
259
+ * serialized to JSON. If you provide an array, all items will be stored in order. This method
260
+ * is idempotent - calling it multiple times with the same data will not create duplicates, but
261
+ * will append items each time.
262
262
  *
263
- * @param items - A single item (object or string) or an array of items to store.
264
- * Objects are automatically stringified to JSON. Strings are stored as-is.
263
+ * @param items - A single item, an array of items, or a string that is the JSON serialization of
264
+ * either - the API only accepts an object or an array of objects, so a plain string
265
+ * is not a valid item on its own.
265
266
  * @param options - Request options
266
267
  * @param options.timeoutSecs - Timeout for the API request. Default is `'medium'`.
267
268
  * @see https://docs.apify.com/api/v2/dataset-items-post
@@ -281,9 +282,6 @@ export class DatasetClient extends ResourceClient {
281
282
  * { url: 'https://test.com', title: 'Test' },
282
283
  * { url: 'https://demo.com', title: 'Demo' }
283
284
  * ]);
284
- *
285
- * // Store string items
286
- * await client.dataset('my-dataset').pushItems(['item1', 'item2', 'item3']);
287
285
  * ```
288
286
  */
289
287
  async pushItems(items, options = {}) {
@@ -4,7 +4,8 @@ import { createHmacSignatureAsync, createStorageContentSignatureAsync } from '@a
4
4
  import { ResourceClient } from '../base/resource_client.js';
5
5
  import * as schemas from '../schemas.js';
6
6
  import { timeoutOptionsSchema, timeoutOptionsShape } from '../timeouts.js';
7
- import { anyObjectSchema, applyQueryParamsToUrl, catchNotFoundOrThrow, isBuffer, isNode, isStream, parseArgument, parseResponse, } from '../utils.js';
7
+ import { runtime } from '#runtime';
8
+ import { anyObjectSchema, applyQueryParamsToUrl, catchNotFoundOrThrow, isBuffer, isStream, parseArgument, parseResponse, } from '../utils.js';
8
9
  const listKeysOptionsSchema = z.strictObject({
9
10
  limit: z.number().min(0).optional(),
10
11
  exclusiveStartKey: z.string().optional(),
@@ -310,7 +311,7 @@ export class KeyValueStoreClient extends ResourceClient {
310
311
  async getRecord(key, options = {}) {
311
312
  parseArgument(key, keySchema);
312
313
  const parsed = parseArgument(options, getRecordOptionsSchema, 'KeyValueClientGetRecordOptions');
313
- if (parsed.stream && !isNode()) {
314
+ if (parsed.stream && !runtime.isNode) {
314
315
  throw new Error('The stream option can only be used in Node.js environment.');
315
316
  }
316
317
  if ('disableRedirect' in parsed) {
@@ -3,7 +3,7 @@ import { z } from 'zod';
3
3
  import log, { Logger, LogLevel } from '@apify/log';
4
4
  import { ResourceClient } from '../base/resource_client.js';
5
5
  import { timeoutOptionsShape } from '../timeouts.js';
6
- import { cast, catchNotFoundForResourceOrThrow, parseArgument } from '../utils.js';
6
+ import { cast, catchNotFoundForResourceOrThrow, concatBytes, parseArgument } from '../utils.js';
7
7
  const logOptionsSchema = z.strictObject({ raw: z.boolean().optional(), ...timeoutOptionsShape });
8
8
  /**
9
9
  * Client for accessing Actor run or build logs.
@@ -132,6 +132,7 @@ export class LoggerActorRedirect extends Logger {
132
132
  export class StreamedLog {
133
133
  #destinationLog;
134
134
  #streamBuffer = [];
135
+ #decoder = new TextDecoder();
135
136
  #splitMarker = /(?:\n|^)(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z)/g;
136
137
  #relevancyTimeLimit;
137
138
  #logClient;
@@ -184,7 +185,7 @@ export class StreamedLog {
184
185
  }
185
186
  const lastChunkRemainder = await this.#logStreamChunks(logStream);
186
187
  // Process whatever is left when exiting. Maybe it is incomplete, maybe it is last log without EOL.
187
- const lastMessage = Buffer.from(lastChunkRemainder).toString().trim();
188
+ const lastMessage = this.#decoder.decode(lastChunkRemainder).trim();
188
189
  if (lastMessage.length) {
189
190
  this.#destinationLog.info(lastMessage);
190
191
  }
@@ -205,7 +206,7 @@ export class StreamedLog {
205
206
  const lastCompleteMessageIndex = chunkWithPreviousRemainder.lastIndexOf(0x0a);
206
207
  previousChunkRemainder = chunkWithPreviousRemainder.slice(lastCompleteMessageIndex);
207
208
  // Push complete part of the chunk to the buffer
208
- this.#streamBuffer.push(Buffer.from(chunkWithPreviousRemainder.slice(0, lastCompleteMessageIndex)));
209
+ this.#streamBuffer.push(chunkWithPreviousRemainder.slice(0, lastCompleteMessageIndex));
209
210
  this.#logBufferContent();
210
211
  // Keep processing the new data until stopped
211
212
  if (this.#stopLogging) {
@@ -218,7 +219,7 @@ export class StreamedLog {
218
219
  * Parse the buffer and log complete messages.
219
220
  */
220
221
  #logBufferContent() {
221
- const allParts = Buffer.concat(this.#streamBuffer).toString().split(this.#splitMarker).slice(1);
222
+ const allParts = this.#decoder.decode(concatBytes(this.#streamBuffer)).split(this.#splitMarker).slice(1);
222
223
  // Parse the buffer parts into complete messages
223
224
  const messageMarkers = allParts.filter((_, i) => i % 2 === 0);
224
225
  const messageContents = allParts.filter((_, i) => i % 2 !== 0);
@@ -3,7 +3,8 @@ import { LEVELS, Log } from '@apify/log';
3
3
  import { ResourceClient } from '../base/resource_client.js';
4
4
  import * as schemas from '../schemas.js';
5
5
  import { optionalTimeoutSchema, timeoutOptionsSchema, timeoutOptionsShape } from '../timeouts.js';
6
- import { anyObjectSchema, isNode, parseArgument, parseResponse } from '../utils.js';
6
+ import { runtime } from '#runtime';
7
+ import { anyObjectSchema, parseArgument, parseResponse } from '../utils.js';
7
8
  import { DatasetClient } from './dataset.js';
8
9
  import { KeyValueStoreClient } from './key_value_store.js';
9
10
  import { LogClient, LoggerActorRedirect, StreamedLog } from './log.js';
@@ -426,7 +427,7 @@ export class RunClient extends ResourceClient {
426
427
  parseArgument(options.timeoutSecs, optionalTimeoutSchema);
427
428
  const { fromStart = true, timeoutSecs = 'long' } = options;
428
429
  let { toLog } = options;
429
- if (toLog === null || !isNode()) {
430
+ if (toLog === null || !runtime.isNode) {
430
431
  // Explicitly no logging or not in Node.js
431
432
  return undefined;
432
433
  }
@@ -0,0 +1,6 @@
1
+ import type { Runtime } from './types.js';
2
+ /**
3
+ * The Node.js implementation of {@link Runtime}. Deno and Bun resolve the `node` condition too and
4
+ * provide the built-ins it uses.
5
+ */
6
+ export declare const runtime: Runtime;
@@ -0,0 +1,58 @@
1
+ import os from 'node:os';
2
+ import { promisify } from 'node:util';
3
+ import { brotliCompress, constants, gzip } from 'node:zlib';
4
+ /**
5
+ * The Node.js implementation of {@link Runtime}. Deno and Bun resolve the `node` condition too and
6
+ * provide the built-ins it uses.
7
+ */
8
+ export const runtime = {
9
+ isNode: true,
10
+ platform: `${os.platform()}; Node/${process.version}`,
11
+ async compress(data) {
12
+ try {
13
+ // `promisify()` belongs inside the fallback chain: a partial `node:zlib` can export
14
+ // `brotliCompress` without implementing it, and `promisify(undefined)` throws. At module scope
15
+ // that would fail the whole import instead of falling through to gzip.
16
+ const options = { params: { [constants.BROTLI_PARAM_QUALITY]: 6 } };
17
+ return { data: await promisify(brotliCompress)(data, options), encoding: 'br' };
18
+ }
19
+ catch {
20
+ // Runtimes that only provide a partial `node:zlib` (Node.js compatibility shims) may not implement
21
+ // brotli, but usually do implement gzip.
22
+ }
23
+ try {
24
+ return { data: await promisify(gzip)(data), encoding: 'gzip' };
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ },
30
+ async createHttpAgents({ timeoutMillis }) {
31
+ // Loaded on the first request rather than with the client: the proxy support pulls in a sizeable
32
+ // dependency tree that a client which never sends a request should not pay for.
33
+ const { ProxyAgent } = await import('proxy-agent');
34
+ // We want to keep sockets alive for better performance.
35
+ const agentOptions = {
36
+ keepAlive: true,
37
+ // Timeout for inactive sockets
38
+ // Prevents socket leaks from idle connections
39
+ timeout: timeoutMillis,
40
+ // Keep alive timeout for free sockets (15 seconds)
41
+ // Node.js will close unused sockets after this period
42
+ keepAliveMsecs: 15_000,
43
+ // Maximum number of sockets per host
44
+ maxSockets: 256,
45
+ maxFreeSockets: 256,
46
+ // LIFO scheduling - reuse most recently used sockets for better performance
47
+ scheduling: 'lifo',
48
+ };
49
+ // ProxyAgent picks the proxy up from the environment variables and supports CONNECT tunneling.
50
+ const agent = new ProxyAgent(agentOptions);
51
+ // Disable Nagle's algorithm for lower latency
52
+ // This sends data immediately instead of buffering small packets
53
+ agent.on('socket', (socket) => {
54
+ socket.setNoDelay(true);
55
+ });
56
+ return { httpAgent: agent, httpsAgent: agent };
57
+ },
58
+ };
@@ -0,0 +1,50 @@
1
+ import type http from 'node:http';
2
+ import type https from 'node:https';
3
+ /**
4
+ * A request body compressed for transport, with the `content-encoding` value that declares it.
5
+ * @internal
6
+ */
7
+ export interface CompressedValue {
8
+ data: Uint8Array;
9
+ encoding: 'br' | 'gzip';
10
+ }
11
+ /**
12
+ * The agents axios's Node.js adapter sends requests through.
13
+ * @internal
14
+ */
15
+ export interface HttpAgents {
16
+ httpAgent: http.Agent;
17
+ httpsAgent: https.Agent;
18
+ }
19
+ /**
20
+ * The runtime-specific part of the client. `#runtime` resolves to the Node.js implementation under the `node`
21
+ * condition and to the Web API one everywhere else (see the `imports` field of `package.json`), so a bundler
22
+ * targeting a browser or an edge runtime never sees the Node.js built-ins the Node.js one uses.
23
+ * @internal
24
+ */
25
+ export interface Runtime {
26
+ /**
27
+ * Whether the Node.js implementation was selected, which the `node` condition settles when `#runtime` is
28
+ * resolved - so a Node.js application bundled for a browser or a neutral target reports `false`. The
29
+ * features that need a Node.js `Readable` response - log streaming and the `stream` record option - are
30
+ * gated on it.
31
+ */
32
+ isNode: boolean;
33
+ /**
34
+ * The platform part of the `User-Agent` header, or `undefined` where the runtime does not let a client
35
+ * set that header (browsers).
36
+ */
37
+ platform: string | undefined;
38
+ /**
39
+ * Compresses a request body, or resolves to `undefined` where compression is not available. Compression
40
+ * is a best-effort optimization, so it never throws.
41
+ */
42
+ compress(data: Uint8Array): Promise<CompressedValue | undefined>;
43
+ /**
44
+ * Creates the agents axios's Node.js adapter sends requests through, or resolves to `undefined` where
45
+ * axios does not use agents.
46
+ */
47
+ createHttpAgents(options: {
48
+ timeoutMillis: number;
49
+ }): Promise<HttpAgents | undefined>;
50
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { Runtime } from './types.js';
2
+ /**
3
+ * The {@link Runtime} for browsers and edge runtimes, built on Web APIs only.
4
+ */
5
+ export declare const runtime: Runtime;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The {@link Runtime} for browsers and edge runtimes, built on Web APIs only.
3
+ */
4
+ export const runtime = {
5
+ isNode: false,
6
+ // Browsers do not let a page set the `User-Agent` header.
7
+ platform: undefined,
8
+ // No request compression: brotli has no Web API, and a `content-encoding` request header is not on the
9
+ // list of headers the Apify API allows in a cross-origin request, so a browser would fail the preflight.
10
+ async compress() {
11
+ return undefined;
12
+ },
13
+ // The XHR and fetch adapters of axios do not use agents.
14
+ async createHttpAgents() {
15
+ return undefined;
16
+ },
17
+ };
package/dist/utils.d.ts CHANGED
@@ -4,8 +4,10 @@ import { z } from 'zod';
4
4
  import type { ApifyApiError } from './apify_api_error.js';
5
5
  import { parseArgument } from '@apify/validations';
6
6
  import type { ApifyResponse } from './http_client.js';
7
+ import type { CompressedValue } from './runtime/types.js';
7
8
  import type { RequestQueueClientListRequestsOptions, RequestQueueClientListRequestsResult } from './resource_clients/request_queue.js';
8
9
  import type { WebhookUpdateData } from './resource_clients/webhook.js';
10
+ export declare const version: any;
9
11
  export { parseArgument };
10
12
  /**
11
13
  * Accepts any non-null, non-array object as a predicate for `z.custom()`.
@@ -59,10 +61,16 @@ export declare function catchNotFoundForResourceOrThrow(err: ApifyApiError, reso
59
61
  * Helper function that converts array of webhooks to base64 string
60
62
  */
61
63
  export declare function stringifyWebhooksToBase64(webhooks?: readonly WebhookUpdateData[]): string | undefined;
62
- export interface CompressedValue {
63
- data: Buffer;
64
- encoding: 'br' | 'gzip';
65
- }
64
+ /**
65
+ * Encodes bytes as base64. `btoa()` takes a binary string, and the bytes are turned into one in slices,
66
+ * because spreading them all into a single `String.fromCharCode()` call overflows the argument limit on
67
+ * inputs of a few tens of kilobytes.
68
+ */
69
+ export declare function bytesToBase64(bytes: Uint8Array): string;
70
+ /**
71
+ * Concatenates byte chunks into one array.
72
+ */
73
+ export declare function concatBytes(chunks: Uint8Array[]): Uint8Array;
66
74
  /**
67
75
  * Decides whether a request body with the given content type is worth compressing.
68
76
  *
@@ -74,10 +82,14 @@ export interface CompressedValue {
74
82
  */
75
83
  export declare function isCompressibleContentType(contentType?: string): boolean;
76
84
  /**
77
- * Compress the passed value using brotli, falling back to gzip. Returns undefined if the data is
78
- * too small / wrong type, or if neither algorithm is available.
85
+ * Compresses the passed value with the runtime's best available algorithm. Returns `undefined` if the data
86
+ * is too small, is not a string or binary value, or if the runtime does not offer compression.
79
87
  */
80
88
  export declare function maybeCompressValue(value: unknown): Promise<CompressedValue | undefined>;
89
+ /**
90
+ * Reads an environment variable, on runtimes that have them.
91
+ */
92
+ export declare function getEnv(name: string): string | undefined;
81
93
  /**
82
94
  * Returns the UTF-8 byte length of a string.
83
95
  */
@@ -94,12 +106,8 @@ export declare function splitIntoJsonArrayBatches<T extends {
94
106
  maxCount: number;
95
107
  maxByteLength: number;
96
108
  }): T[][];
97
- export declare function isNode(): boolean;
98
109
  export declare function isBuffer(value: unknown): value is Buffer | ArrayBuffer | TypedArray;
99
110
  export declare function isStream(value: unknown): value is Readable;
100
- export declare function getVersionData(): {
101
- version: string;
102
- };
103
111
  /**
104
112
  * Helper class to create async iterators from paginated list endpoints.
105
113
  */
@@ -108,10 +116,6 @@ export declare class RequestQueuePaginationIterator {
108
116
  constructor(options: RequestQueuePaginationIteratorOptions);
109
117
  [Symbol.asyncIterator](): AsyncIterator<RequestQueueClientListRequestsResult>;
110
118
  }
111
- declare global {
112
- export const BROWSER_BUILD: boolean | undefined;
113
- export const VERSION: string | undefined;
114
- }
115
119
  /**
116
120
  * Options for creating a pagination iterator.
117
121
  */