apify-client 3.0.0-beta.62 → 3.0.0-beta.64

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.
@@ -1,3 +1,4 @@
1
+ import type { Readable } from 'node:stream';
1
2
  import type { STORAGE_GENERAL_ACCESS } from '@apify/consts';
2
3
  import type { ApiClientSubResourceOptions } from '../base/api_client.js';
3
4
  import { ResourceClient } from '../base/resource_client.js';
@@ -167,6 +168,34 @@ export declare class DatasetClient<Data extends Record<string | number, any> = R
167
168
  * ```
168
169
  */
169
170
  downloadItems(format: `${DownloadItemsFormat}`, options?: DatasetClientDownloadItemsOptions): Promise<Buffer>;
171
+ /**
172
+ * Downloads dataset items in a specific format as a Readable stream. Only works in Node.js.
173
+ *
174
+ * Takes the same arguments as {@link downloadItems}, but resolves to the response body as a stream, so a large
175
+ * export is processed in chunks without holding all of it in memory.
176
+ *
177
+ * The stream holds its connection open until you consume it to the end or destroy it. Iterating it with
178
+ * `for await` or passing it to `pipeline()` from `node:stream/promises` does either one for you.
179
+ *
180
+ * @param format - Output format: `'json'`, `'jsonl'`, `'csv'`, `'xlsx'`, `'xml'`, `'rss'`, or `'html'`
181
+ * @param options - Download and formatting options, the same as for {@link downloadItems}
182
+ * @param options.timeoutSecs - Timeout for the API to start responding. Default is `'long'`. Once the stream is
183
+ * returned, it only limits inactivity: the stream errors if no data arrives for that long. To stop the download
184
+ * early or cap its total duration, destroy the stream or abort `signal`.
185
+ * @returns Readable stream of the items serialized to the specified format
186
+ * @see https://docs.apify.com/api/v2/dataset-items-get
187
+ *
188
+ * @example
189
+ * ```javascript
190
+ * const { createWriteStream } = require('node:fs');
191
+ * const { pipeline } = require('node:stream/promises');
192
+ *
193
+ * // Write a CSV export straight to a file
194
+ * const stream = await client.dataset('my-dataset').streamItems('csv', { bom: true });
195
+ * await pipeline(stream, createWriteStream('output.csv'));
196
+ * ```
197
+ */
198
+ streamItems(format: `${DownloadItemsFormat}`, options?: DatasetClientDownloadItemsOptions): Promise<Readable>;
170
199
  /**
171
200
  * Stores one or more items into the dataset.
172
201
  *
@@ -3,6 +3,7 @@ import { createStorageContentSignatureAsync } from '@apify/utilities';
3
3
  import { ResourceClient } from '../base/resource_client.js';
4
4
  import * as schemas from '../schemas.js';
5
5
  import { timeoutOptionsSchema, timeoutOptionsShape } from '../timeouts.js';
6
+ import { runtime } from '#runtime';
6
7
  import { anyObjectSchema, applyQueryParamsToUrl, cast, isNonArrayObject, paginationOptionsShape, parseArgument, parseResponse, SCANNED_COUNT, } from '../utils.js';
7
8
  /**
8
9
  * Supported formats for downloading dataset items.
@@ -269,6 +270,52 @@ export class DatasetClient extends ResourceClient {
269
270
  });
270
271
  return cast(data);
271
272
  }
273
+ /**
274
+ * Downloads dataset items in a specific format as a Readable stream. Only works in Node.js.
275
+ *
276
+ * Takes the same arguments as {@link downloadItems}, but resolves to the response body as a stream, so a large
277
+ * export is processed in chunks without holding all of it in memory.
278
+ *
279
+ * The stream holds its connection open until you consume it to the end or destroy it. Iterating it with
280
+ * `for await` or passing it to `pipeline()` from `node:stream/promises` does either one for you.
281
+ *
282
+ * @param format - Output format: `'json'`, `'jsonl'`, `'csv'`, `'xlsx'`, `'xml'`, `'rss'`, or `'html'`
283
+ * @param options - Download and formatting options, the same as for {@link downloadItems}
284
+ * @param options.timeoutSecs - Timeout for the API to start responding. Default is `'long'`. Once the stream is
285
+ * returned, it only limits inactivity: the stream errors if no data arrives for that long. To stop the download
286
+ * early or cap its total duration, destroy the stream or abort `signal`.
287
+ * @returns Readable stream of the items serialized to the specified format
288
+ * @see https://docs.apify.com/api/v2/dataset-items-get
289
+ *
290
+ * @example
291
+ * ```javascript
292
+ * const { createWriteStream } = require('node:fs');
293
+ * const { pipeline } = require('node:stream/promises');
294
+ *
295
+ * // Write a CSV export straight to a file
296
+ * const stream = await client.dataset('my-dataset').streamItems('csv', { bom: true });
297
+ * await pipeline(stream, createWriteStream('output.csv'));
298
+ * ```
299
+ */
300
+ async streamItems(format, options = {}) {
301
+ parseArgument(format, itemFormatSchema);
302
+ const { timeoutSecs = 'long', signal, ...query } = parseArgument(options, downloadItemsOptionsSchema, 'DatasetClientDownloadItemsOptions');
303
+ if (!runtime.isNode) {
304
+ throw new Error('The streamItems() method can only be used in Node.js environment.');
305
+ }
306
+ const { data } = await this.httpClient.call({
307
+ url: this.buildUrl('items'),
308
+ method: 'GET',
309
+ params: this.buildParams({
310
+ format,
311
+ ...query,
312
+ }),
313
+ responseType: 'stream',
314
+ timeoutSecs,
315
+ signal,
316
+ });
317
+ return cast(data);
318
+ }
272
319
  /**
273
320
  * Stores one or more items into the dataset.
274
321
  *
@@ -19,6 +19,9 @@ import type { TimeoutOptions } from '../timeouts.js';
19
19
  * const log = await runClient.log().get();
20
20
  * console.log(log);
21
21
  *
22
+ * // Get the log content as raw bytes
23
+ * const logBuffer = await runClient.log().get({ buffer: true });
24
+ *
22
25
  * // Stream the log in real-time
23
26
  * const stream = await runClient.log().stream();
24
27
  * stream.on('line', (line) => console.log(line));
@@ -34,14 +37,26 @@ export declare class LogClient extends ResourceClient {
34
37
  /**
35
38
  * Retrieves the log as a string.
36
39
  *
40
+ * The `buffer` option only selects the return type: the bytes come back as a Buffer (Node.js) or ArrayBuffer
41
+ * (browser), not decoded to a string. Either way the whole log is downloaded in one response; to read it
42
+ * incrementally, use {@link LogClient.stream}.
43
+ *
37
44
  * @param options - Log retrieval options.
38
45
  * @param options.raw - If `true`, returns raw log content without any processing. Default is `false`.
46
+ * @param options.buffer - If `true`, the log is returned as a Buffer (Node.js) or ArrayBuffer (browser) instead of a
47
+ * string. It does not change how the log is fetched.
39
48
  * @param options.timeoutSecs - Timeout for the API request. Default is `'long'`.
40
- * @returns The log content as a string, or `undefined` if it does not exist. A chained client such as
41
- * `run.log()` throws an `ApifyApiError` on a 404, since the run itself may be what is missing.
49
+ * @returns The log content, or `undefined` if it does not exist. A chained client such as `run.log()` throws an
50
+ * `ApifyApiError` on a 404, since the run itself may be what is missing.
42
51
  * @see https://docs.apify.com/api/v2/log-get
43
52
  */
44
- get(options?: LogOptions): Promise<string | undefined>;
53
+ get(options?: LogGetOptions & {
54
+ buffer?: false;
55
+ }): Promise<string | undefined>;
56
+ get(options: LogGetOptions & {
57
+ buffer: true;
58
+ }): Promise<Buffer | undefined>;
59
+ get(options?: LogGetOptions): Promise<string | Buffer | undefined>;
45
60
  /**
46
61
  * Retrieves the log as a Readable stream. Only works in Node.js.
47
62
  *
@@ -61,6 +76,17 @@ export interface LogOptions extends TimeoutOptions {
61
76
  /** @default false */
62
77
  raw?: boolean;
63
78
  }
79
+ /**
80
+ * Options for {@link LogClient.get}.
81
+ */
82
+ export interface LogGetOptions extends LogOptions {
83
+ /**
84
+ * If `true`, the log is returned as a Buffer (Node.js) or ArrayBuffer (browser) instead of a string. It only selects
85
+ * the return type; to read the log incrementally, use {@link LogClient.stream}.
86
+ * @default false
87
+ */
88
+ buffer?: boolean;
89
+ }
64
90
  /**
65
91
  * Logger for redirected actor logs.
66
92
  * @since Added in 2.20.0
@@ -13,6 +13,7 @@ const EMPTY_LOG_STREAM_RETRY_MILLIS = 500;
13
13
  /** Upper bound on the pause between reopens of an empty log stream. */
14
14
  const EMPTY_LOG_STREAM_MAX_RETRY_MILLIS = 5_000;
15
15
  const logOptionsSchema = z.strictObject({ raw: z.boolean().optional(), ...timeoutOptionsShape });
16
+ const logGetOptionsSchema = logOptionsSchema.extend({ buffer: z.boolean().optional() });
16
17
  /** How long `StreamedLog.stop()` waits for lines already in flight before aborting the log stream request. */
17
18
  const STOP_GRACE_MILLIS = 1000;
18
19
  /**
@@ -30,6 +31,9 @@ const STOP_GRACE_MILLIS = 1000;
30
31
  * const log = await runClient.log().get();
31
32
  * console.log(log);
32
33
  *
34
+ * // Get the log content as raw bytes
35
+ * const logBuffer = await runClient.log().get({ buffer: true });
36
+ *
33
37
  * // Stream the log in real-time
34
38
  * const stream = await runClient.log().stream();
35
39
  * stream.on('line', (line) => console.log(line));
@@ -47,18 +51,8 @@ export class LogClient extends ResourceClient {
47
51
  ...options,
48
52
  });
49
53
  }
50
- /**
51
- * Retrieves the log as a string.
52
- *
53
- * @param options - Log retrieval options.
54
- * @param options.raw - If `true`, returns raw log content without any processing. Default is `false`.
55
- * @param options.timeoutSecs - Timeout for the API request. Default is `'long'`.
56
- * @returns The log content as a string, or `undefined` if it does not exist. A chained client such as
57
- * `run.log()` throws an `ApifyApiError` on a 404, since the run itself may be what is missing.
58
- * @see https://docs.apify.com/api/v2/log-get
59
- */
60
54
  async get(options = {}) {
61
- const { timeoutSecs = 'long', signal, ...params } = parseArgument(options, logOptionsSchema, 'LogOptions');
55
+ const { timeoutSecs = 'long', signal, buffer, ...params } = parseArgument(options, logGetOptionsSchema, 'LogGetOptions');
62
56
  const requestOpts = {
63
57
  url: this.buildUrl(),
64
58
  method: 'GET',
@@ -66,6 +60,8 @@ export class LogClient extends ResourceClient {
66
60
  timeoutSecs,
67
61
  signal,
68
62
  };
63
+ if (buffer)
64
+ requestOpts.responseType = 'buffer';
69
65
  try {
70
66
  const response = await this.httpClient.call(requestOpts);
71
67
  return cast(response.data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apify-client",
3
- "version": "3.0.0-beta.62",
3
+ "version": "3.0.0-beta.64",
4
4
  "description": "Apify API client for JavaScript",
5
5
  "engines": {
6
6
  "node": ">=22.13.0"