Skip to content

Commit 35d56f6

Browse files
authored
refactor!: remove all deprecated options (#1039)
Removes every option the client had deprecated for v3. - `ActorVersionCollectionClient.list()` and `ActorEnvVarCollectionClient.list()` take no arguments. Neither endpoint ever read `offset`, `limit` or `desc`, and both return every item in one response. - `ActorCollectionCreateOptions.restartOnError`. Use `defaultRunOptions.restartOnError`. - `exclusiveStartId` on `listRequests()` and `paginateRequests()`. Use `cursor`. BREAKING CHANGE: `ActorVersionCollectionClient.list()` and `ActorEnvVarCollectionClient.list()` take no arguments, and `ActorVersionCollectionListOptions` and `ActorEnvVarCollectionListOptions` are removed with the `offset`, `limit`, `desc` and `chunkSize` they declared. `ActorCollectionCreateOptions.restartOnError` is removed; use `defaultRunOptions.restartOnError`. `exclusiveStartId` is removed from `listRequests()` and `paginateRequests()`; use `cursor`. Closes #799 *✍️ Drafted by Claude Code*
1 parent 4e40887 commit 35d56f6

9 files changed

Lines changed: 53 additions & 130 deletions

File tree

docs/04_upgrading/upgrading_v3.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ This affects numeric options such as `waitSecs`, `timeout` and `memory`, and dat
8686

8787
Some options were declared in the TypeScript types but always rejected by the client's own validation before a request was ever sent: `chunkSize` on `DatasetClient.downloadItems()` and `createItemsPublicUrl()`, and `signature` on `createItemsPublicUrl()` and `createKeysPublicUrl()`. These are no longer part of the option types, so passing them is now a compile-time error instead of a runtime throw.
8888

89-
The reverse also happened: `chunkSize` now works on every paginating `list()` method. In v2 only `DatasetClient.listItems()` accepted it - everywhere else it type-checked and then threw.
89+
The reverse also happened: `chunkSize` now works on every `list()` method that takes pagination options. In v2 only `DatasetClient.listItems()` accepted it - everywhere else it type-checked and then threw.
9090

9191
## API errors are thrown as subclasses of `ApifyApiError`
9292

@@ -175,3 +175,15 @@ Two return types change as a result of describing what the endpoints really retu
175175

176176
- <ApiLink to="class/ScheduleClient#getLog">`ScheduleClient.getLog()`</ApiLink> was typed as a `string`, even though the endpoint returns the log as a list of entries. It's now typed as <ApiLink to="interface/ScheduleInvoked">`ScheduleInvoked[]`</ApiLink>, each entry carrying `message`, `level` and `createdAt`.
177177
- <ApiLink to="interface/TaskPublicConfig">`TaskPublicConfig`</ApiLink> now follows the specification: `publishedAt` is optional and read-only, and `categorization`, which the specification doesn't describe, is gone from the type.
178+
179+
## `versions().list()` and `envVars().list()` take no options
180+
181+
<ApiLink to="class/ActorVersionCollectionClient#list">`ActorVersionCollectionClient.list()`</ApiLink> and <ApiLink to="class/ActorEnvVarCollectionClient#list">`ActorEnvVarCollectionClient.list()`</ApiLink> now take no arguments. Neither endpoint reads `offset`, `limit` or `desc`, and both return every item in one response, so `chunkSize` had nothing to size either. The `ActorVersionCollectionListOptions` and `ActorEnvVarCollectionListOptions` types that declared those four options, deprecated since v2.21.0, are gone from the package. A call that passed an options object no longer compiles. Drop the argument and the call returns the same items as before.
182+
183+
## The last deprecated options are gone
184+
185+
Two options that carried a `@deprecated` marker throughout v2 have been removed.
186+
187+
`restartOnError` is gone from <ApiLink to="interface/ActorCollectionCreateOptions">`ActorCollectionCreateOptions`</ApiLink>, so <ApiLink to="class/ActorCollectionClient#create">`ActorCollectionClient.create()`</ApiLink> no longer accepts it at the top level. Pass it inside `defaultRunOptions` instead, as the deprecation notice advised.
188+
189+
`exclusiveStartId` is gone from <ApiLink to="class/RequestQueueClient#listRequests">`listRequests()`</ApiLink> and <ApiLink to="class/RequestQueueClient#paginateRequests">`paginateRequests()`</ApiLink>. Both paginate by `cursor` alone now, and passing `exclusiveStartId` throws an `ArgumentValidationError` about an unrecognized key. In v2 the two were mutually exclusive, so the error about combining them is gone as well. Responses are unaffected, since the API still echoes `exclusiveStartId` back in the request listing.

docs/public-api/apify-client.api.md

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,6 @@ export interface ActorCollectionCreateOptions {
124124
isPublic?: boolean;
125125
// (undocumented)
126126
name?: string;
127-
// @deprecated (undocumented)
128-
restartOnError?: boolean;
129127
seoDescription?: string;
130128
seoTitle?: string;
131129
// (undocumented)
@@ -194,13 +192,7 @@ export class ActorEnvVarClient extends ResourceClient {
194192
export class ActorEnvVarCollectionClient extends ResourceCollectionClient {
195193
constructor(options: ApiClientSubResourceOptions);
196194
create(actorEnvVar: ActorEnvironmentVariable): Promise<ActorEnvironmentVariable>;
197-
list(_options?: ActorEnvVarCollectionListOptions): Promise<ActorEnvVarListResult> & AsyncIterable<ActorEnvironmentVariable>;
198-
}
199-
200-
// @public @deprecated (undocumented)
201-
export interface ActorEnvVarCollectionListOptions extends PaginationOptions {
202-
// (undocumented)
203-
desc?: boolean;
195+
list(): Promise<ActorEnvVarListResult> & AsyncIterable<ActorEnvironmentVariable>;
204196
}
205197

206198
// @public
@@ -429,13 +421,7 @@ interface ActorVersionClientNarrowings {
429421
export class ActorVersionCollectionClient extends ResourceCollectionClient {
430422
constructor(options: ApiClientSubResourceOptions);
431423
create(actorVersion: ActorVersion): Promise<FinalActorVersion>;
432-
list(_options?: ActorVersionCollectionListOptions): Promise<ActorVersionListResult> & AsyncIterable<FinalActorVersion>;
433-
}
434-
435-
// @public @deprecated (undocumented)
436-
export interface ActorVersionCollectionListOptions extends PaginationOptions {
437-
// (undocumented)
438-
desc?: boolean;
424+
list(): Promise<ActorVersionListResult> & AsyncIterable<FinalActorVersion>;
439425
}
440426

441427
// @public
@@ -3379,8 +3365,6 @@ export interface RequestQueueClientListItem extends GeneratedHeadRequest {
33793365
// @public
33803366
export interface RequestQueueClientListRequestsOptions {
33813367
cursor?: string;
3382-
// @deprecated
3383-
exclusiveStartId?: string;
33843368
filter?: readonly RequestQueueListRequestsFilter[];
33853369
// (undocumented)
33863370
limit?: number;
@@ -3404,8 +3388,6 @@ export interface RequestQueueClientLockedListItem extends GeneratedLockedHeadReq
34043388
// @public
34053389
export interface RequestQueueClientPaginateRequestsOptions {
34063390
cursor?: string;
3407-
// @deprecated (undocumented)
3408-
exclusiveStartId?: string;
34093391
filter?: readonly RequestQueueListRequestsFilter[];
34103392
// (undocumented)
34113393
limit?: number;

src/resource_clients/actor_collection.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,6 @@ export interface ActorCollectionCreateOptions {
136136
isDeprecated?: boolean;
137137
isPublic?: boolean;
138138
name?: string;
139-
/** @deprecated Use defaultRunOptions.restartOnError instead */
140-
restartOnError?: boolean;
141139
/**
142140
* @since Added in 2.8.6
143141
*/

src/resource_clients/actor_env_var_collection.ts

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { ApiClientSubResourceOptions } from '../base/api_client.js';
22
import { ResourceCollectionClient } from '../base/resource_collection_client.js';
3-
import type { PaginatedList, PaginationOptions } from '../utils.js';
3+
import type { PaginatedList } from '../utils.js';
44
import * as schemas from '../schemas.js';
55
import { anyObjectSchema, parseArgument } from '../utils.js';
66
import type { ActorEnvironmentVariable } from './actor_version.js';
@@ -48,25 +48,22 @@ export class ActorEnvVarCollectionClient extends ResourceCollectionClient {
4848
/**
4949
* Lists all environment variables of this Actor version.
5050
*
51-
* Awaiting the return value (as you would with a Promise) will result in a single API call. The amount of fetched
52-
* items in a single API call is limited.
51+
* The endpoint returns every environment variable in one response, so awaiting the return value (as you would
52+
* with a Promise) gets the whole list.
5353
* ```javascript
54-
* const paginatedList = await client.list();
55-
*```
54+
* const { items } = await client.list();
55+
* ```
5656
*
57-
* Asynchronous iteration is also supported. This will fetch additional pages if needed until all items are
58-
* retrieved.
57+
* Asynchronous iteration is also supported, and yields the environment variables one by one.
5958
*
6059
* ```javascript
6160
* for await (const singleItem of client.list()) {...}
6261
* ```
6362
*
64-
* @returns A paginated iterator of environment variables.
63+
* @returns The environment variables, awaitable as a whole list or iterable one by one.
6564
* @see https://docs.apify.com/api/v2/act-version-env-vars-get
6665
*/
67-
list(
68-
_options: ActorEnvVarCollectionListOptions = {},
69-
): Promise<ActorEnvVarListResult> & AsyncIterable<ActorEnvironmentVariable> {
66+
list(): Promise<ActorEnvVarListResult> & AsyncIterable<ActorEnvironmentVariable> {
7067
return this._listPaginated(schemas.ListOfEnvVars());
7168
}
7269

@@ -83,15 +80,6 @@ export class ActorEnvVarCollectionClient extends ResourceCollectionClient {
8380
}
8481
}
8582

86-
/**
87-
* @deprecated No options are used in the current API implementation.
88-
* https://github.com/apify/apify-client-js/issues/799
89-
* @since Added in 2.1.0
90-
*/
91-
export interface ActorEnvVarCollectionListOptions extends PaginationOptions {
92-
desc?: boolean;
93-
}
94-
9583
/**
9684
* @since Added in 2.1.0
9785
*/

src/resource_clients/actor_version_collection.ts

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { ApiClientSubResourceOptions } from '../base/api_client.js';
22
import { ResourceCollectionClient } from '../base/resource_collection_client.js';
3-
import type { PaginatedList, PaginationOptions } from '../utils.js';
3+
import type { PaginatedList } from '../utils.js';
44
import * as schemas from '../schemas.js';
55
import { anyObjectSchema, parseArgument } from '../utils.js';
66
import type { ActorVersion, FinalActorVersion } from './actor_version.js';
@@ -45,25 +45,22 @@ export class ActorVersionCollectionClient extends ResourceCollectionClient {
4545
/**
4646
* Lists all Actor versions.
4747
*
48-
* Awaiting the return value (as you would with a Promise) will result in a single API call. The amount of fetched
49-
* items in a single API call is limited.
48+
* The endpoint returns every version in one response, so awaiting the return value (as you would with a Promise)
49+
* gets the whole list.
5050
* ```javascript
51-
* const paginatedList = await client.list();
52-
*```
51+
* const { items } = await client.list();
52+
* ```
5353
*
54-
* Asynchronous iteration is also supported. This will fetch additional pages if needed until all items are
55-
* retrieved.
54+
* Asynchronous iteration is also supported, and yields the versions one by one.
5655
*
5756
* ```javascript
5857
* for await (const singleItem of client.list()) {...}
5958
* ```
6059
*
61-
* @returns A paginated iterator of Actor versions.
60+
* @returns The Actor versions, awaitable as a whole list or iterable one by one.
6261
* @see https://docs.apify.com/api/v2/act-versions-get
6362
*/
64-
list(
65-
_options: ActorVersionCollectionListOptions = {},
66-
): Promise<ActorVersionListResult> & AsyncIterable<FinalActorVersion> {
63+
list(): Promise<ActorVersionListResult> & AsyncIterable<FinalActorVersion> {
6764
return this._listPaginated(schemas.ListOfVersions());
6865
}
6966

@@ -81,12 +78,4 @@ export class ActorVersionCollectionClient extends ResourceCollectionClient {
8178
}
8279
}
8380

84-
/**
85-
* @deprecated No options are used in the current API implementation.
86-
* https://github.com/apify/apify-client-js/issues/799
87-
*/
88-
export interface ActorVersionCollectionListOptions extends PaginationOptions {
89-
desc?: boolean;
90-
}
91-
9281
export type ActorVersionListResult = Pick<PaginatedList<FinalActorVersion>, 'total' | 'items'>;

src/resource_clients/request_queue.ts

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import {
3030
cast,
3131
catchNotFoundOrThrow,
3232
isNonArrayObject,
33-
mutuallyExclusive,
3433
parseArgument,
3534
parseDateFields,
3635
parseResponse,
@@ -78,23 +77,17 @@ const prolongRequestLockOptionsSchema = z.strictObject({
7877
forefront: z.boolean().optional(),
7978
});
8079
const requestFilterSchema = z.array(z.enum(['locked', 'pending'])).min(1);
81-
const listRequestsOptionsSchema = z
82-
.strictObject({
83-
limit: z.number().min(0).optional(),
84-
exclusiveStartId: z.string().optional(),
85-
cursor: z.string().optional(),
86-
filter: requestFilterSchema.optional(),
87-
})
88-
.refine(...mutuallyExclusive<RequestQueueClientListRequestsOptions>('exclusiveStartId', 'cursor'));
89-
const paginateRequestsOptionsSchema = z
90-
.strictObject({
91-
limit: z.number().min(0).optional(),
92-
maxPageLimit: z.number().default(DEFAULT_REQUEST_QUEUE_REQUEST_PAGE_LIMIT),
93-
exclusiveStartId: z.string().optional(),
94-
cursor: z.string().optional(),
95-
filter: requestFilterSchema.optional(),
96-
})
97-
.refine(...mutuallyExclusive<RequestQueueClientPaginateRequestsOptions>('exclusiveStartId', 'cursor'));
80+
const listRequestsOptionsSchema = z.strictObject({
81+
limit: z.number().min(0).optional(),
82+
cursor: z.string().optional(),
83+
filter: requestFilterSchema.optional(),
84+
});
85+
const paginateRequestsOptionsSchema = z.strictObject({
86+
limit: z.number().min(0).optional(),
87+
maxPageLimit: z.number().default(DEFAULT_REQUEST_QUEUE_REQUEST_PAGE_LIMIT),
88+
cursor: z.string().optional(),
89+
filter: requestFilterSchema.optional(),
90+
});
9891

9992
export type {
10093
AllowedHttpMethods,
@@ -749,8 +742,6 @@ export class RequestQueueClient extends ResourceClient {
749742
const newOptions = {
750743
...parsed,
751744
limit: remainingItems,
752-
// remove original exclusiveStartId, if there was any, and use cursor-based pagination
753-
exclusiveStartId: undefined,
754745
cursor: currentPage.nextCursor,
755746
};
756747
currentPage = await getPaginatedList(newOptions);
@@ -810,15 +801,14 @@ export class RequestQueueClient extends ResourceClient {
810801
paginateRequests(
811802
options: RequestQueueClientPaginateRequestsOptions = {},
812803
): RequestQueueRequestsAsyncIterable<RequestQueueClientListRequestsResult> {
813-
const { limit, exclusiveStartId, cursor, filter, maxPageLimit } = parseArgument(
804+
const { limit, cursor, filter, maxPageLimit } = parseArgument(
814805
options,
815806
paginateRequestsOptionsSchema,
816807
'RequestQueueClientPaginateRequestsOptions',
817808
);
818809
return new RequestQueuePaginationIterator({
819810
getPage: async (pageOptions) => this.listRequests({ ...pageOptions, filter }),
820811
limit,
821-
exclusiveStartId,
822812
cursor,
823813
maxPageLimit,
824814
});
@@ -869,11 +859,6 @@ export type RequestQueueListRequestsFilter = 'locked' | 'pending';
869859
*/
870860
export interface RequestQueueClientListRequestsOptions {
871861
limit?: number;
872-
/**
873-
* Using id of request that does not exist in request queue leads to unpredictable results.
874-
* @deprecated Use `cursor` for pagination instead.
875-
*/
876-
exclusiveStartId?: string;
877862
/**
878863
* @since Added in 2.23.2
879864
*/
@@ -891,8 +876,6 @@ export interface RequestQueueClientListRequestsOptions {
891876
export interface RequestQueueClientPaginateRequestsOptions {
892877
limit?: number;
893878
maxPageLimit?: number;
894-
/** @deprecated Use `cursor` for pagination instead. */
895-
exclusiveStartId?: string;
896879
/**
897880
* @since Added in 2.23.2
898881
*/

src/utils.ts

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ export function getVersionData(): { version: string } {
287287
}
288288

289289
/**
290-
* Helper class to create async iterators from paginated list endpoints with exclusive start key.
290+
* Helper class to create async iterators from paginated list endpoints.
291291
*/
292292
export class RequestQueuePaginationIterator {
293293
private readonly maxPageLimit: number;
@@ -298,22 +298,17 @@ export class RequestQueuePaginationIterator {
298298

299299
private readonly limit?: number;
300300

301-
private readonly exclusiveStartId?: string;
302301
private readonly cursor?: string;
303302

304303
constructor(options: RequestQueuePaginationIteratorOptions) {
305304
this.maxPageLimit = options.maxPageLimit;
306305
this.limit = options.limit;
307-
this.exclusiveStartId = options.exclusiveStartId;
308306
this.cursor = options.cursor;
309307
this.getPage = options.getPage;
310308
}
311309

312310
async *[Symbol.asyncIterator](): AsyncIterator<RequestQueueClientListRequestsResult> {
313311
let nextCursor = this.cursor;
314-
// allow using exclusiveStartId for the first page, but then we'll delete it to avoid using it for any later page
315-
let nextExclusiveStartId = this.exclusiveStartId;
316-
317312
let iterateItemCount = 0;
318313
while (true) {
319314
const pageLimit = this.limit
@@ -323,7 +318,6 @@ export class RequestQueuePaginationIterator {
323318
const page: RequestQueueClientListRequestsResult = await this.getPage({
324319
limit: pageLimit,
325320
cursor: nextCursor,
326-
exclusiveStartId: nextExclusiveStartId,
327321
});
328322
// There are no more pages to iterate
329323
if (page.items.length === 0) return;
@@ -333,7 +327,6 @@ export class RequestQueuePaginationIterator {
333327
if ((this.limit && iterateItemCount >= this.limit) || !page.nextCursor) return;
334328

335329
nextCursor = page.nextCursor;
336-
nextExclusiveStartId = undefined; // see comment above - delete it for any page after the first one, and paginate with cursor
337330
}
338331
}
339332
}
@@ -350,7 +343,6 @@ export interface RequestQueuePaginationIteratorOptions {
350343
maxPageLimit: number;
351344
getPage: (opts: RequestQueueClientListRequestsOptions) => Promise<RequestQueueClientListRequestsResult>;
352345
limit?: number;
353-
exclusiveStartId?: string;
354346
cursor?: string;
355347
}
356348

@@ -471,16 +463,6 @@ export function applyQueryParamsToUrl(
471463
return url;
472464
}
473465

474-
/**
475-
* Builds a `[check, message]` pair to spread into `.refine()`, asserting that at most one of `keys`
476-
* is present. Pass the options interface as `T`, so that a misspelled key is a type error.
477-
* @internal
478-
*/
479-
export const mutuallyExclusive = <T extends object>(...keys: (keyof T & string)[]): [(value: T) => boolean, string] => [
480-
(value) => keys.filter((key) => typeof value[key] !== 'undefined').length <= 1,
481-
`At most one of the following fields is allowed: ${keys.join(', ')}`,
482-
];
483-
484466
const pathSegmentSchema = z
485467
.string()
486468
.nonempty()

0 commit comments

Comments
 (0)