apify-client 3.0.0-beta.27 → 3.0.0-beta.29

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 (39) hide show
  1. package/dist/apify_client.d.ts +15 -3
  2. package/dist/apify_client.js +9 -6
  3. package/dist/base/api_client.js +2 -2
  4. package/dist/base/resource_client.d.ts +3 -3
  5. package/dist/base/resource_client.js +13 -9
  6. package/dist/base/resource_collection_client.d.ts +5 -4
  7. package/dist/base/resource_collection_client.js +12 -7
  8. package/dist/bundle.js +6 -6
  9. package/dist/bundle.js.map +1 -1
  10. package/dist/http_clients/base.js +1 -21
  11. package/dist/resource_clients/actor.js +17 -13
  12. package/dist/resource_clients/actor_collection.js +2 -2
  13. package/dist/resource_clients/actor_env_var.js +6 -6
  14. package/dist/resource_clients/actor_env_var_collection.js +4 -4
  15. package/dist/resource_clients/actor_version.js +6 -6
  16. package/dist/resource_clients/actor_version_collection.js +4 -4
  17. package/dist/resource_clients/build.js +8 -6
  18. package/dist/resource_clients/dataset.js +18 -14
  19. package/dist/resource_clients/dataset_collection.js +6 -5
  20. package/dist/resource_clients/key_value_store.js +19 -14
  21. package/dist/resource_clients/key_value_store_collection.js +6 -5
  22. package/dist/resource_clients/log.d.ts +2 -0
  23. package/dist/resource_clients/log.js +10 -4
  24. package/dist/resource_clients/request_queue.js +37 -21
  25. package/dist/resource_clients/request_queue_collection.js +2 -2
  26. package/dist/resource_clients/run.js +21 -15
  27. package/dist/resource_clients/schedule.js +8 -7
  28. package/dist/resource_clients/schedule_collection.js +2 -2
  29. package/dist/resource_clients/task.js +15 -12
  30. package/dist/resource_clients/task_collection.js +2 -2
  31. package/dist/resource_clients/user.js +8 -5
  32. package/dist/resource_clients/webhook.js +8 -7
  33. package/dist/resource_clients/webhook_collection.js +2 -2
  34. package/dist/resource_clients/webhook_dispatch.js +2 -2
  35. package/dist/timeouts.d.ts +12 -0
  36. package/dist/timeouts.js +6 -0
  37. package/dist/utils.d.ts +5 -0
  38. package/dist/utils.js +21 -0
  39. package/package.json +2 -2
@@ -401,7 +401,10 @@ export declare class ApifyClient {
401
401
  * Configuration options for ApifyClient.
402
402
  */
403
403
  export interface ApifyClientOptions {
404
- /** @default https://api.apify.com */
404
+ /**
405
+ * URL of the Apify API, with or without the `/v2` version path, which is appended when missing.
406
+ * @default https://api.apify.com
407
+ */
405
408
  baseUrl?: string;
406
409
  /**
407
410
  * Compression of request bodies: the name of a built-in algorithm, or an {@link HttpCompressor} for a custom
@@ -416,6 +419,8 @@ export interface ApifyClientOptions {
416
419
  */
417
420
  headers?: Record<string, string>;
418
421
  /**
422
+ * Publicly accessible URL of the Apify API, used in the URLs the client generates. Like `baseUrl`, with or
423
+ * without the `/v2` version path.
419
424
  * @default https://api.apify.com
420
425
  * @since Added in 2.17.0
421
426
  */
@@ -456,9 +461,16 @@ export interface ApifyClientOptions {
456
461
  * on the HTTP client itself.
457
462
  */
458
463
  export interface ApifyClientCustomHttpClientOptions {
459
- /** @default https://api.apify.com */
464
+ /**
465
+ * URL of the Apify API, with or without the `/v2` version path, which is appended when missing.
466
+ * @default https://api.apify.com
467
+ */
460
468
  baseUrl?: string;
461
- /** @default https://api.apify.com */
469
+ /**
470
+ * Publicly accessible URL of the Apify API, used in the URLs the client generates. Like `baseUrl`, with or
471
+ * without the `/v2` version path.
472
+ * @default https://api.apify.com
473
+ */
462
474
  publicBaseUrl?: string;
463
475
  /** Set as the HTTP client's `Authorization` header, unless it already has one. */
464
476
  token?: string;
@@ -31,6 +31,13 @@ import { Statistics } from './statistics.js';
31
31
  import { DEFAULT_TIMEOUT_LONG_SECS, DEFAULT_TIMEOUT_MAX_SECS, DEFAULT_TIMEOUT_MEDIUM_SECS, DEFAULT_TIMEOUT_SHORT_SECS, } from './timeouts.js';
32
32
  import { getEnv, parseArgument } from './utils.js';
33
33
  const DEFAULT_API_URL = 'https://api.apify.com';
34
+ const API_VERSION_PATH = '/v2';
35
+ function toApiBaseUrl(url) {
36
+ const parsed = new URL(url);
37
+ const path = parsed.pathname.replace(/\/+$/, '');
38
+ parsed.pathname = path.endsWith(API_VERSION_PATH) ? path : `${path}${API_VERSION_PATH}`;
39
+ return parsed.href;
40
+ }
34
41
  const clientOptionsSchema = z.strictObject({
35
42
  baseUrl: z.string().default(DEFAULT_API_URL),
36
43
  compression: compressionSchema.default('brotli'),
@@ -105,12 +112,8 @@ export class ApifyClient {
105
112
  constructor(options = {}) {
106
113
  const parsed = parseArgument(options, clientOptionsSchema, 'ApifyClientOptions');
107
114
  const { baseUrl, compression, headers, publicBaseUrl, maxRetries, minDelayBetweenRetriesMillis, timeoutShortSecs, timeoutMediumSecs, timeoutLongSecs, timeoutMaxSecs, token, } = parsed;
108
- const tempBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, baseUrl.length - 1) : baseUrl;
109
- this.baseUrl = `${tempBaseUrl}/v2`;
110
- const tempPublicBaseUrl = publicBaseUrl.endsWith('/')
111
- ? publicBaseUrl.slice(0, publicBaseUrl.length - 1)
112
- : publicBaseUrl;
113
- this.publicBaseUrl = `${tempPublicBaseUrl}/v2`;
115
+ this.baseUrl = toApiBaseUrl(baseUrl);
116
+ this.publicBaseUrl = toApiBaseUrl(publicBaseUrl);
114
117
  this.token = token;
115
118
  this.stats = new Statistics();
116
119
  this.logger = logger.child({ prefix: 'ApifyClient' });
@@ -67,8 +67,8 @@ export class ApiClient {
67
67
  return Math.min(a, b);
68
68
  };
69
69
  // `chunkSize` only sizes this loop's requests; it is not an API parameter, so it must not reach
70
- // `buildParams()` and the query string. The same goes for `timeoutSecs`, which callers take out before
71
- // calling this, since it also picks the timeout of every page request.
70
+ // `buildParams()` and the query string. The same goes for `timeoutSecs` and `signal`, which callers take out
71
+ // before calling this, since they also apply to every page request.
72
72
  const { chunkSize, ...listOptions } = options;
73
73
  const paginatedListPromise = getPaginatedList({
74
74
  ...listOptions,
@@ -18,13 +18,13 @@ export declare class ResourceClient extends ApiClient {
18
18
  * A 404 resolves to `undefined` only when the client names its resource by ID. A chained client without one, such
19
19
  * as `run.dataset()`, throws it instead (see `catchNotFoundForResourceOrThrow()`).
20
20
  */
21
- protected getResource<T, R>(schema: z.ZodType, options: T, timeoutSecs: Timeout): Promise<R | undefined>;
22
- protected updateResource<T, R>(schema: z.ZodType, newFields: T, timeoutSecs: Timeout): Promise<R>;
21
+ protected getResource<T, R>(schema: z.ZodType, options: T, timeoutSecs: Timeout, signal?: AbortSignal): Promise<R | undefined>;
22
+ protected updateResource<T, R>(schema: z.ZodType, newFields: T, timeoutSecs: Timeout, signal?: AbortSignal): Promise<R>;
23
23
  /**
24
24
  * A 404 is swallowed, keeping the DELETE idempotent, only when the client names its resource by ID. A chained client
25
25
  * without one throws it instead (see `catchNotFoundForResourceOrThrow()`).
26
26
  */
27
- protected deleteResource(timeoutSecs: Timeout): Promise<void>;
27
+ protected deleteResource(timeoutSecs: Timeout, signal?: AbortSignal): Promise<void>;
28
28
  /**
29
29
  * This function is used in Build and Run endpoints so it's kept
30
30
  * here to stay DRY.
@@ -1,5 +1,5 @@
1
1
  import { ACT_JOB_TERMINAL_STATUSES } from '@apify/consts';
2
- import { catchNotFoundForResourceOrThrow, catchNotFoundOrThrow, parseResponse } from '../utils.js';
2
+ import { catchNotFoundForResourceOrThrow, catchNotFoundOrThrow, parseResponse, sleep } from '../utils.js';
3
3
  import { ApiClient } from './api_client.js';
4
4
  /**
5
5
  * We need to supply some number for the API,
@@ -34,12 +34,13 @@ export class ResourceClient extends ApiClient {
34
34
  * A 404 resolves to `undefined` only when the client names its resource by ID. A chained client without one, such
35
35
  * as `run.dataset()`, throws it instead (see `catchNotFoundForResourceOrThrow()`).
36
36
  */
37
- async getResource(schema, options, timeoutSecs) {
37
+ async getResource(schema, options, timeoutSecs, signal) {
38
38
  const requestOpts = {
39
39
  url: this.buildUrl(),
40
40
  method: 'GET',
41
41
  params: this.buildParams(options),
42
42
  timeoutSecs,
43
+ signal,
43
44
  };
44
45
  try {
45
46
  const response = await this.httpClient.call(requestOpts);
@@ -50,13 +51,14 @@ export class ResourceClient extends ApiClient {
50
51
  }
51
52
  return undefined;
52
53
  }
53
- async updateResource(schema, newFields, timeoutSecs) {
54
+ async updateResource(schema, newFields, timeoutSecs, signal) {
54
55
  const response = await this.httpClient.call({
55
56
  url: this.buildUrl(),
56
57
  method: 'PUT',
57
58
  params: this.buildParams(),
58
59
  data: newFields,
59
60
  timeoutSecs,
61
+ signal,
60
62
  });
61
63
  return parseResponse(response, schema);
62
64
  }
@@ -64,13 +66,14 @@ export class ResourceClient extends ApiClient {
64
66
  * A 404 is swallowed, keeping the DELETE idempotent, only when the client names its resource by ID. A chained client
65
67
  * without one throws it instead (see `catchNotFoundForResourceOrThrow()`).
66
68
  */
67
- async deleteResource(timeoutSecs) {
69
+ async deleteResource(timeoutSecs, signal) {
68
70
  try {
69
71
  await this.httpClient.call({
70
72
  url: this.buildUrl(),
71
73
  method: 'DELETE',
72
74
  params: this.buildParams(),
73
75
  timeoutSecs,
76
+ signal,
74
77
  });
75
78
  }
76
79
  catch (err) {
@@ -82,7 +85,7 @@ export class ResourceClient extends ApiClient {
82
85
  * here to stay DRY.
83
86
  */
84
87
  async waitForJobFinish(schema, options = {}) {
85
- const { waitSecs = MAX_WAIT_FOR_FINISH, timeoutSecs = 'noTimeout' } = options;
88
+ const { waitSecs = MAX_WAIT_FOR_FINISH, timeoutSecs = 'noTimeout', signal } = options;
86
89
  const waitMillis = waitSecs * 1000;
87
90
  let job;
88
91
  const startedAt = Date.now();
@@ -102,6 +105,7 @@ export class ResourceClient extends ApiClient {
102
105
  method: 'GET',
103
106
  params: this.buildParams({ waitForFinish }),
104
107
  timeoutSecs,
108
+ signal,
105
109
  };
106
110
  try {
107
111
  const response = await this.httpClient.call(requestOpts);
@@ -113,10 +117,10 @@ export class ResourceClient extends ApiClient {
113
117
  }
114
118
  // It might take some time for database replicas to get up-to-date,
115
119
  // so getRun() might return null. Wait a little bit and try it again.
116
- if (!job)
117
- await new Promise((resolve) => {
118
- setTimeout(resolve, 250);
119
- });
120
+ if (!job) {
121
+ await sleep(250, signal);
122
+ signal?.throwIfAborted();
123
+ }
120
124
  } while (shouldRepeat());
121
125
  if (!job) {
122
126
  const constructorName = this.constructor.name;
@@ -10,12 +10,13 @@ export declare class ResourceCollectionClient extends ApiClient {
10
10
  /**
11
11
  * @private
12
12
  */
13
- protected listResources<T, R>(schema: z.ZodType, options: T | undefined, timeoutSecs: Timeout): Promise<R>;
13
+ protected listResources<T, R>(schema: z.ZodType, options: T | undefined, timeoutSecs: Timeout, signal?: AbortSignal): Promise<R>;
14
14
  /**
15
15
  * Returns async iterator to iterate through all items and Promise that can be awaited to get first page of results.
16
- * `defaultTimeoutSecs` applies to every page request unless `options.timeoutSecs` overrides it.
16
+ * `defaultTimeoutSecs` applies to every page request unless `options.timeoutSecs` overrides it, and
17
+ * `options.signal` goes to every page request.
17
18
  */
18
19
  protected listResourcesPaginated<T extends PaginationOptions & TimeoutOptions, Data, R extends PaginatedResponse<Data>>(schema: z.ZodType, options: T, defaultTimeoutSecs: Timeout): AsyncIterable<Data> & Promise<R>;
19
- protected createResource<D, R>(schema: z.ZodType, resource: D, timeoutSecs: Timeout): Promise<R>;
20
- protected getOrCreateResource<D, R>(schema: z.ZodType, name: string | undefined, resource: D | undefined, timeoutSecs: Timeout): Promise<R>;
20
+ protected createResource<D, R>(schema: z.ZodType, resource: D, timeoutSecs: Timeout, signal?: AbortSignal): Promise<R>;
21
+ protected getOrCreateResource<D, R>(schema: z.ZodType, name: string | undefined, resource: D | undefined, timeoutSecs: Timeout, signal?: AbortSignal): Promise<R>;
21
22
  }
@@ -8,41 +8,46 @@ export class ResourceCollectionClient extends ApiClient {
8
8
  /**
9
9
  * @private
10
10
  */
11
- async listResources(schema, options, timeoutSecs) {
11
+ async listResources(schema, options, timeoutSecs, signal) {
12
12
  const response = await this.httpClient.call({
13
13
  url: this.buildUrl(),
14
14
  method: 'GET',
15
15
  params: this.buildParams(options),
16
16
  timeoutSecs,
17
+ signal,
17
18
  });
18
19
  return parseResponse(response, schema);
19
20
  }
20
21
  /**
21
22
  * Returns async iterator to iterate through all items and Promise that can be awaited to get first page of results.
22
- * `defaultTimeoutSecs` applies to every page request unless `options.timeoutSecs` overrides it.
23
+ * `defaultTimeoutSecs` applies to every page request unless `options.timeoutSecs` overrides it, and
24
+ * `options.signal` goes to every page request.
23
25
  */
24
26
  listResourcesPaginated(schema, options, defaultTimeoutSecs) {
25
- // `timeoutSecs` only times the page requests; it is not an API parameter, so it must not reach the query string.
26
- const { timeoutSecs = defaultTimeoutSecs, ...listOptions } = options;
27
- return this.listPaginatedFromCallback(async (pageOptions) => this.listResources(schema, pageOptions, timeoutSecs), listOptions);
27
+ // `timeoutSecs` and `signal` only apply to the page requests; they are not API parameters, so they must not
28
+ // reach the query string.
29
+ const { timeoutSecs = defaultTimeoutSecs, signal, ...listOptions } = options;
30
+ return this.listPaginatedFromCallback(async (pageOptions) => this.listResources(schema, pageOptions, timeoutSecs, signal), listOptions);
28
31
  }
29
- async createResource(schema, resource, timeoutSecs) {
32
+ async createResource(schema, resource, timeoutSecs, signal) {
30
33
  const response = await this.httpClient.call({
31
34
  url: this.buildUrl(),
32
35
  method: 'POST',
33
36
  params: this.buildParams(),
34
37
  data: resource,
35
38
  timeoutSecs,
39
+ signal,
36
40
  });
37
41
  return parseResponse(response, schema);
38
42
  }
39
- async getOrCreateResource(schema, name, resource, timeoutSecs) {
43
+ async getOrCreateResource(schema, name, resource, timeoutSecs, signal) {
40
44
  const response = await this.httpClient.call({
41
45
  url: this.buildUrl(),
42
46
  method: 'POST',
43
47
  params: this.buildParams({ name }),
44
48
  data: resource,
45
49
  timeoutSecs,
50
+ signal,
46
51
  });
47
52
  return parseResponse(response, schema);
48
53
  }