From 93a45f94b343597e08b1e8bb5afc16e701107c2a Mon Sep 17 00:00:00 2001 From: Brent Arndorfer Date: Fri, 1 Aug 2025 08:37:10 -0500 Subject: [PATCH 1/4] Generated API bindings for updated spec and added support for providing external token resolution --- api.ts | 1294 +++++++++++++++++++++++++++++++++++++-- client/vertex-client.ts | 103 +++- spec.yml | 709 +++++++++++++++++++-- 3 files changed, 2015 insertions(+), 91 deletions(-) diff --git a/api.ts b/api.ts index e5911b4..b405691 100644 --- a/api.ts +++ b/api.ts @@ -868,6 +868,25 @@ export interface CollaborationContextDataRelationships { */ account: AccountRelationship; } +/** + * + * @export + * @interface CollaborationContextList + */ +export interface CollaborationContextList { + /** + * + * @type {Array} + * @memberof CollaborationContextList + */ + data: Array; + /** + * + * @type {{ [key: string]: Link; }} + * @memberof CollaborationContextList + */ + links: { [key: string]: Link }; +} /** * * @export @@ -1796,6 +1815,59 @@ export const CreatePermissionGrantDataAttributesCapabilityEnum = { export type CreatePermissionGrantDataAttributesCapabilityEnum = (typeof CreatePermissionGrantDataAttributesCapabilityEnum)[keyof typeof CreatePermissionGrantDataAttributesCapabilityEnum]; +/** + * + * @export + * @interface CreateReplyRequest + */ +export interface CreateReplyRequest { + /** + * + * @type {CreateReplyRequestData} + * @memberof CreateReplyRequest + */ + data: CreateReplyRequestData; +} +/** + * + * @export + * @interface CreateReplyRequestData + */ +export interface CreateReplyRequestData { + /** + * Resource object type. + * @type {string} + * @memberof CreateReplyRequestData + */ + type: CreateReplyRequestDataTypeEnum; + /** + * + * @type {CreateReplyRequestDataAttributes} + * @memberof CreateReplyRequestData + */ + attributes: CreateReplyRequestDataAttributes; +} + +export const CreateReplyRequestDataTypeEnum = { + Reply: 'reply', +} as const; + +export type CreateReplyRequestDataTypeEnum = + (typeof CreateReplyRequestDataTypeEnum)[keyof typeof CreateReplyRequestDataTypeEnum]; + +/** + * + * @export + * @interface CreateReplyRequestDataAttributes + */ +export interface CreateReplyRequestDataAttributes { + /** + * + * @type {string} + * @memberof CreateReplyRequestDataAttributes + */ + body: string; +} /** * * @export @@ -6125,6 +6197,145 @@ export interface RelationshipLinks { */ related: string; } +/** + * + * @export + * @interface Reply + */ +export interface Reply { + /** + * + * @type {ReplyData} + * @memberof Reply + */ + data: ReplyData; + /** + * + * @type {{ [key: string]: Link; }} + * @memberof Reply + */ + links?: { [key: string]: Link }; + /** + * + * @type {Array} + * @memberof Reply + */ + included?: Array; +} +/** + * + * @export + * @interface ReplyData + */ +export interface ReplyData { + /** + * + * @type {string} + * @memberof ReplyData + */ + type: ReplyDataTypeEnum; + /** + * ID of the resource. + * @type {string} + * @memberof ReplyData + */ + id: string; + /** + * + * @type {ReplyDataAttributes} + * @memberof ReplyData + */ + attributes: ReplyDataAttributes; + /** + * + * @type {ReplyDataRelationships} + * @memberof ReplyData + */ + relationships: ReplyDataRelationships; + /** + * + * @type {{ [key: string]: Link; }} + * @memberof ReplyData + */ + links?: { [key: string]: Link }; +} + +export const ReplyDataTypeEnum = { + Reply: 'reply', +} as const; + +export type ReplyDataTypeEnum = + (typeof ReplyDataTypeEnum)[keyof typeof ReplyDataTypeEnum]; + +/** + * + * @export + * @interface ReplyDataAttributes + */ +export interface ReplyDataAttributes { + /** + * + * @type {string} + * @memberof ReplyDataAttributes + */ + createdAt: string; + /** + * + * @type {string} + * @memberof ReplyDataAttributes + */ + modifiedAt: string; + /** + * + * @type {string} + * @memberof ReplyDataAttributes + */ + body: string; +} +/** + * + * @export + * @interface ReplyDataRelationships + */ +export interface ReplyDataRelationships { + /** + * + * @type {ThreadRelationship} + * @memberof ReplyDataRelationships + */ + thread: ThreadRelationship; + /** + * + * @type {UserRelationship} + * @memberof ReplyDataRelationships + */ + user: UserRelationship; +} +/** + * + * @export + * @interface ReplyList + */ +export interface ReplyList { + /** + * + * @type {Array} + * @memberof ReplyList + */ + data: Array; + /** + * + * @type {{ [key: string]: Link; }} + * @memberof ReplyList + */ + links: { [key: string]: Link }; + /** + * + * @type {Array} + * @memberof ReplyList + */ + included?: Array; +} /** * * @export @@ -8035,6 +8246,12 @@ export interface Thread { * @memberof Thread */ links?: { [key: string]: Link }; + /** + * + * @type {Array} + * @memberof Thread + */ + included?: Array; } /** * @@ -8123,6 +8340,12 @@ export interface ThreadDataAttributes { * @memberof ThreadDataAttributes */ body?: string; + /** + * + * @type {number} + * @memberof ThreadDataAttributes + */ + replyCount?: number; } /** * @@ -8161,7 +8384,53 @@ export interface ThreadList { * @memberof ThreadList */ links: { [key: string]: Link }; + /** + * + * @type {Array} + * @memberof ThreadList + */ + included?: Array; +} +/** + * + * @export + * @interface ThreadRelationship + */ +export interface ThreadRelationship { + /** + * + * @type {ThreadRelationshipData} + * @memberof ThreadRelationship + */ + data: ThreadRelationshipData; +} +/** + * + * @export + * @interface ThreadRelationshipData + */ +export interface ThreadRelationshipData { + /** + * + * @type {string} + * @memberof ThreadRelationshipData + */ + type: ThreadRelationshipDataTypeEnum; + /** + * ID of the resource. + * @type {string} + * @memberof ThreadRelationshipData + */ + id: string; } + +export const ThreadRelationshipDataTypeEnum = { + Thread: 'thread', +} as const; + +export type ThreadRelationshipDataTypeEnum = + (typeof ThreadRelationshipDataTypeEnum)[keyof typeof ThreadRelationshipDataTypeEnum]; + /** * * @export @@ -8872,10 +9141,10 @@ export interface UpdateSceneItemRequestDataAttributes { export interface UpdateSceneItemRequestDataRelationships { /** * Relationship to a `geometry-set` or `part-revision`. - * @type {GeometrySetRelationship | PartRevisionRelationship} + * @type {GeometrySetRelationship | PartRevisionRelationship | object} * @memberof UpdateSceneItemRequestDataRelationships */ - source?: GeometrySetRelationship | PartRevisionRelationship; + source?: GeometrySetRelationship | PartRevisionRelationship | object | null; } /** * @@ -9406,6 +9675,46 @@ export interface UserGroupList { */ links: { [key: string]: Link }; } +/** + * + * @export + * @interface UserId + */ +export interface UserId { + /** + * Resource object type. + * @type {string} + * @memberof UserId + */ + type: UserIdTypeEnum; + /** + * ID of the resource. + * @type {string} + * @memberof UserId + */ + id: string; +} + +export const UserIdTypeEnum = { + User: 'user', +} as const; + +export type UserIdTypeEnum = + (typeof UserIdTypeEnum)[keyof typeof UserIdTypeEnum]; + +/** + * + * @export + * @interface UserIdList + */ +export interface UserIdList { + /** + * + * @type {Array} + * @memberof UserIdList + */ + data: Array; +} /** * * @export @@ -16788,7 +17097,9 @@ export const Oauth2ApiAxiosParamCreator = function ( * @param {string} [scope] * @param {string} [code] * @param {string} [redirectUri] + * @param {string} [subjectTokenType] * @param {string} [refreshToken] + * @param {string} [subjectToken] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -16797,7 +17108,9 @@ export const Oauth2ApiAxiosParamCreator = function ( scope?: string, code?: string, redirectUri?: string, + subjectTokenType?: string, refreshToken?: string, + subjectToken?: string, options: AxiosRequestConfig = {} ): Promise => { // verify required parameter 'grantType' is not null or undefined @@ -16839,10 +17152,18 @@ export const Oauth2ApiAxiosParamCreator = function ( localVarFormParams.set('grant_type', grantType as any); } + if (subjectTokenType !== undefined) { + localVarFormParams.set('subject_token_type', subjectTokenType as any); + } + if (refreshToken !== undefined) { localVarFormParams.set('refresh_token', refreshToken as any); } + if (subjectToken !== undefined) { + localVarFormParams.set('subject_token', subjectToken as any); + } + localVarHeaderParameter['Content-Type'] = 'application/x-www-form-urlencoded'; @@ -16992,7 +17313,9 @@ export const Oauth2ApiFp = function (configuration?: Configuration) { * @param {string} [scope] * @param {string} [code] * @param {string} [redirectUri] + * @param {string} [subjectTokenType] * @param {string} [refreshToken] + * @param {string} [subjectToken] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -17001,7 +17324,9 @@ export const Oauth2ApiFp = function (configuration?: Configuration) { scope?: string, code?: string, redirectUri?: string, + subjectTokenType?: string, refreshToken?: string, + subjectToken?: string, options?: AxiosRequestConfig ): Promise< (axios?: AxiosInstance, basePath?: string) => AxiosPromise @@ -17011,7 +17336,9 @@ export const Oauth2ApiFp = function (configuration?: Configuration) { scope, code, redirectUri, + subjectTokenType, refreshToken, + subjectToken, options ); return createRequestFunction( @@ -17096,7 +17423,9 @@ export const Oauth2ApiFactory = function ( * @param {string} [scope] * @param {string} [code] * @param {string} [redirectUri] + * @param {string} [subjectTokenType] * @param {string} [refreshToken] + * @param {string} [subjectToken] * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -17105,11 +17434,22 @@ export const Oauth2ApiFactory = function ( scope?: string, code?: string, redirectUri?: string, + subjectTokenType?: string, refreshToken?: string, + subjectToken?: string, options?: any ): AxiosPromise { return localVarFp - .createToken(grantType, scope, code, redirectUri, refreshToken, options) + .createToken( + grantType, + scope, + code, + redirectUri, + subjectTokenType, + refreshToken, + subjectToken, + options + ) .then((request) => request(axios, basePath)); }, /** @@ -17205,12 +17545,26 @@ export interface Oauth2ApiCreateTokenRequest { */ readonly redirectUri?: string; + /** + * + * @type {string} + * @memberof Oauth2ApiCreateToken + */ + readonly subjectTokenType?: string; + /** * * @type {string} * @memberof Oauth2ApiCreateToken */ readonly refreshToken?: string; + + /** + * + * @type {string} + * @memberof Oauth2ApiCreateToken + */ + readonly subjectToken?: string; } /** @@ -17291,7 +17645,9 @@ export class Oauth2Api extends BaseAPI { requestParameters.scope, requestParameters.code, requestParameters.redirectUri, + requestParameters.subjectTokenType, requestParameters.refreshToken, + requestParameters.subjectToken, options ) .then((request) => request(this.axios, this.basePath)); @@ -21024,36 +21380,34 @@ export class PropertyEntriesApi extends BaseAPI { } /** - * SceneAlterationsApi - axios parameter creator + * RepliesApi - axios parameter creator * @export */ -export const SceneAlterationsApiAxiosParamCreator = function ( +export const RepliesApiAxiosParamCreator = function ( configuration?: Configuration ) { return { /** - * Create a `scene-alteration` for a `scene-view`. - * @param {string} id The `scene-view` ID. - * @param {CreateSceneAlterationRequest | CreateSceneExpressionAlterationRequest} createSceneAlterationRequestCreateSceneExpressionAlterationRequest + * Create a `reply` belonging to a `thread`. + * @param {string} id The `thread` ID. + * @param {CreateReplyRequest} createReplyRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ - createSceneAlteration: async ( + createReply: async ( id: string, - createSceneAlterationRequestCreateSceneExpressionAlterationRequest: - | CreateSceneAlterationRequest - | CreateSceneExpressionAlterationRequest, + createReplyRequest: CreateReplyRequest, options: AxiosRequestConfig = {} ): Promise => { // verify required parameter 'id' is not null or undefined - assertParamExists('createSceneAlteration', 'id', id); - // verify required parameter 'createSceneAlterationRequestCreateSceneExpressionAlterationRequest' is not null or undefined + assertParamExists('createReply', 'id', id); + // verify required parameter 'createReplyRequest' is not null or undefined assertParamExists( - 'createSceneAlteration', - 'createSceneAlterationRequestCreateSceneExpressionAlterationRequest', - createSceneAlterationRequestCreateSceneExpressionAlterationRequest + 'createReply', + 'createReplyRequest', + createReplyRequest ); - const localVarPath = `/scene-views/{id}/scene-alterations`.replace( + const localVarPath = `/threads/{id}/replies`.replace( `{${'id'}}`, encodeURIComponent(String(id)) ); @@ -21091,7 +21445,7 @@ export const SceneAlterationsApiAxiosParamCreator = function ( ...options.headers, }; localVarRequestOptions.data = serializeDataIfNeeded( - createSceneAlterationRequestCreateSceneExpressionAlterationRequest, + createReplyRequest, localVarRequestOptions, configuration ); @@ -21102,18 +21456,20 @@ export const SceneAlterationsApiAxiosParamCreator = function ( }; }, /** - * Get a `queued-scene-alteration` by ID. - * @param {string} id The `queued-scene-alteration` ID. + * Get a `reply`. + * @param {string} id The `thread` ID. + * @param {string} [include] Comma-separated list of relationships to include in response. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getQueuedSceneAlteration: async ( + getReply: async ( id: string, + include?: string, options: AxiosRequestConfig = {} ): Promise => { // verify required parameter 'id' is not null or undefined - assertParamExists('getQueuedSceneAlteration', 'id', id); - const localVarPath = `/queued-scene-alterations/{id}`.replace( + assertParamExists('getReply', 'id', id); + const localVarPath = `/replies/{id}`.replace( `{${'id'}}`, encodeURIComponent(String(id)) ); @@ -21141,9 +21497,661 @@ export const SceneAlterationsApiAxiosParamCreator = function ( configuration ); - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions?.headers ?? {}; - localVarRequestOptions.headers = { + if (include !== undefined) { + localVarQueryParameter['include'] = include; + } + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions?.headers ?? {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * List `collaboration-context`s + * @param {string} [pageCursor] The cursor for the next page of items. + * @param {number} [pageSize] The number of items to return. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listCollaborationContexts: async ( + pageCursor?: string, + pageSize?: number, + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/collaboration-contexts`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { + method: 'GET', + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication OAuth2 required + // oauth required + await setOAuthToObject( + localVarHeaderParameter, + 'OAuth2', + [], + configuration + ); + + if (pageCursor !== undefined) { + localVarQueryParameter['page[cursor]'] = pageCursor; + } + + if (pageSize !== undefined) { + localVarQueryParameter['page[size]'] = pageSize; + } + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions?.headers ?? {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * List `replies` + * @param {string} [filterThreadId] Comma-separated list of supplied IDs to filter on. + * @param {string} [pageCursor] The cursor for the next page of items. + * @param {number} [pageSize] The number of items to return. + * @param {string} [include] Comma-separated list of relationships to include in response. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listReplies: async ( + filterThreadId?: string, + pageCursor?: string, + pageSize?: number, + include?: string, + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/replies`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { + method: 'GET', + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication OAuth2 required + // oauth required + await setOAuthToObject( + localVarHeaderParameter, + 'OAuth2', + [], + configuration + ); + + if (filterThreadId !== undefined) { + localVarQueryParameter['filter[threadId]'] = filterThreadId; + } + + if (pageCursor !== undefined) { + localVarQueryParameter['page[cursor]'] = pageCursor; + } + + if (pageSize !== undefined) { + localVarQueryParameter['page[size]'] = pageSize; + } + + if (include !== undefined) { + localVarQueryParameter['include'] = include; + } + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions?.headers ?? {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + }; +}; + +/** + * RepliesApi - functional programming interface + * @export + */ +export const RepliesApiFp = function (configuration?: Configuration) { + const localVarAxiosParamCreator = RepliesApiAxiosParamCreator(configuration); + return { + /** + * Create a `reply` belonging to a `thread`. + * @param {string} id The `thread` ID. + * @param {CreateReplyRequest} createReplyRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async createReply( + id: string, + createReplyRequest: CreateReplyRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.createReply( + id, + createReplyRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * Get a `reply`. + * @param {string} id The `thread` ID. + * @param {string} [include] Comma-separated list of relationships to include in response. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getReply( + id: string, + include?: string, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.getReply( + id, + include, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * List `collaboration-context`s + * @param {string} [pageCursor] The cursor for the next page of items. + * @param {number} [pageSize] The number of items to return. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async listCollaborationContexts( + pageCursor?: string, + pageSize?: number, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.listCollaborationContexts( + pageCursor, + pageSize, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * List `replies` + * @param {string} [filterThreadId] Comma-separated list of supplied IDs to filter on. + * @param {string} [pageCursor] The cursor for the next page of items. + * @param {number} [pageSize] The number of items to return. + * @param {string} [include] Comma-separated list of relationships to include in response. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async listReplies( + filterThreadId?: string, + pageCursor?: string, + pageSize?: number, + include?: string, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.listReplies( + filterThreadId, + pageCursor, + pageSize, + include, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + }; +}; + +/** + * RepliesApi - factory interface + * @export + */ +export const RepliesApiFactory = function ( + configuration?: Configuration, + basePath?: string, + axios?: AxiosInstance +) { + const localVarFp = RepliesApiFp(configuration); + return { + /** + * Create a `reply` belonging to a `thread`. + * @param {string} id The `thread` ID. + * @param {CreateReplyRequest} createReplyRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createReply( + id: string, + createReplyRequest: CreateReplyRequest, + options?: any + ): AxiosPromise { + return localVarFp + .createReply(id, createReplyRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * Get a `reply`. + * @param {string} id The `thread` ID. + * @param {string} [include] Comma-separated list of relationships to include in response. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getReply(id: string, include?: string, options?: any): AxiosPromise { + return localVarFp + .getReply(id, include, options) + .then((request) => request(axios, basePath)); + }, + /** + * List `collaboration-context`s + * @param {string} [pageCursor] The cursor for the next page of items. + * @param {number} [pageSize] The number of items to return. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listCollaborationContexts( + pageCursor?: string, + pageSize?: number, + options?: any + ): AxiosPromise { + return localVarFp + .listCollaborationContexts(pageCursor, pageSize, options) + .then((request) => request(axios, basePath)); + }, + /** + * List `replies` + * @param {string} [filterThreadId] Comma-separated list of supplied IDs to filter on. + * @param {string} [pageCursor] The cursor for the next page of items. + * @param {number} [pageSize] The number of items to return. + * @param {string} [include] Comma-separated list of relationships to include in response. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listReplies( + filterThreadId?: string, + pageCursor?: string, + pageSize?: number, + include?: string, + options?: any + ): AxiosPromise { + return localVarFp + .listReplies(filterThreadId, pageCursor, pageSize, include, options) + .then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * Request parameters for createReply operation in RepliesApi. + * @export + * @interface RepliesApiCreateReplyRequest + */ +export interface RepliesApiCreateReplyRequest { + /** + * The `thread` ID. + * @type {string} + * @memberof RepliesApiCreateReply + */ + readonly id: string; + + /** + * + * @type {CreateReplyRequest} + * @memberof RepliesApiCreateReply + */ + readonly createReplyRequest: CreateReplyRequest; +} + +/** + * Request parameters for getReply operation in RepliesApi. + * @export + * @interface RepliesApiGetReplyRequest + */ +export interface RepliesApiGetReplyRequest { + /** + * The `thread` ID. + * @type {string} + * @memberof RepliesApiGetReply + */ + readonly id: string; + + /** + * Comma-separated list of relationships to include in response. + * @type {string} + * @memberof RepliesApiGetReply + */ + readonly include?: string; +} + +/** + * Request parameters for listCollaborationContexts operation in RepliesApi. + * @export + * @interface RepliesApiListCollaborationContextsRequest + */ +export interface RepliesApiListCollaborationContextsRequest { + /** + * The cursor for the next page of items. + * @type {string} + * @memberof RepliesApiListCollaborationContexts + */ + readonly pageCursor?: string; + + /** + * The number of items to return. + * @type {number} + * @memberof RepliesApiListCollaborationContexts + */ + readonly pageSize?: number; +} + +/** + * Request parameters for listReplies operation in RepliesApi. + * @export + * @interface RepliesApiListRepliesRequest + */ +export interface RepliesApiListRepliesRequest { + /** + * Comma-separated list of supplied IDs to filter on. + * @type {string} + * @memberof RepliesApiListReplies + */ + readonly filterThreadId?: string; + + /** + * The cursor for the next page of items. + * @type {string} + * @memberof RepliesApiListReplies + */ + readonly pageCursor?: string; + + /** + * The number of items to return. + * @type {number} + * @memberof RepliesApiListReplies + */ + readonly pageSize?: number; + + /** + * Comma-separated list of relationships to include in response. + * @type {string} + * @memberof RepliesApiListReplies + */ + readonly include?: string; +} + +/** + * RepliesApi - object-oriented interface + * @export + * @class RepliesApi + * @extends {BaseAPI} + */ +export class RepliesApi extends BaseAPI { + /** + * Create a `reply` belonging to a `thread`. + * @param {RepliesApiCreateReplyRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof RepliesApi + */ + public createReply( + requestParameters: RepliesApiCreateReplyRequest, + options?: AxiosRequestConfig + ) { + return RepliesApiFp(this.configuration) + .createReply( + requestParameters.id, + requestParameters.createReplyRequest, + options + ) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * Get a `reply`. + * @param {RepliesApiGetReplyRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof RepliesApi + */ + public getReply( + requestParameters: RepliesApiGetReplyRequest, + options?: AxiosRequestConfig + ) { + return RepliesApiFp(this.configuration) + .getReply(requestParameters.id, requestParameters.include, options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * List `collaboration-context`s + * @param {RepliesApiListCollaborationContextsRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof RepliesApi + */ + public listCollaborationContexts( + requestParameters: RepliesApiListCollaborationContextsRequest = {}, + options?: AxiosRequestConfig + ) { + return RepliesApiFp(this.configuration) + .listCollaborationContexts( + requestParameters.pageCursor, + requestParameters.pageSize, + options + ) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * List `replies` + * @param {RepliesApiListRepliesRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof RepliesApi + */ + public listReplies( + requestParameters: RepliesApiListRepliesRequest = {}, + options?: AxiosRequestConfig + ) { + return RepliesApiFp(this.configuration) + .listReplies( + requestParameters.filterThreadId, + requestParameters.pageCursor, + requestParameters.pageSize, + requestParameters.include, + options + ) + .then((request) => request(this.axios, this.basePath)); + } +} + +/** + * SceneAlterationsApi - axios parameter creator + * @export + */ +export const SceneAlterationsApiAxiosParamCreator = function ( + configuration?: Configuration +) { + return { + /** + * Create a `scene-alteration` for a `scene-view`. + * @param {string} id The `scene-view` ID. + * @param {CreateSceneAlterationRequest | CreateSceneExpressionAlterationRequest} createSceneAlterationRequestCreateSceneExpressionAlterationRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createSceneAlteration: async ( + id: string, + createSceneAlterationRequestCreateSceneExpressionAlterationRequest: + | CreateSceneAlterationRequest + | CreateSceneExpressionAlterationRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('createSceneAlteration', 'id', id); + // verify required parameter 'createSceneAlterationRequestCreateSceneExpressionAlterationRequest' is not null or undefined + assertParamExists( + 'createSceneAlteration', + 'createSceneAlterationRequestCreateSceneExpressionAlterationRequest', + createSceneAlterationRequestCreateSceneExpressionAlterationRequest + ); + const localVarPath = `/scene-views/{id}/scene-alterations`.replace( + `{${'id'}}`, + encodeURIComponent(String(id)) + ); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { + method: 'POST', + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication OAuth2 required + // oauth required + await setOAuthToObject( + localVarHeaderParameter, + 'OAuth2', + [], + configuration + ); + + localVarHeaderParameter['Content-Type'] = 'application/vnd.api+json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions?.headers ?? {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + createSceneAlterationRequestCreateSceneExpressionAlterationRequest, + localVarRequestOptions, + configuration + ); + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Get a `queued-scene-alteration` by ID. + * @param {string} id The `queued-scene-alteration` ID. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getQueuedSceneAlteration: async ( + id: string, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('getQueuedSceneAlteration', 'id', id); + const localVarPath = `/queued-scene-alterations/{id}`.replace( + `{${'id'}}`, + encodeURIComponent(String(id)) + ); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { + method: 'GET', + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication OAuth2 required + // oauth required + await setOAuthToObject( + localVarHeaderParameter, + 'OAuth2', + [], + configuration + ); + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions?.headers ?? {}; + localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers, @@ -28689,11 +29697,13 @@ export const ThreadsApiAxiosParamCreator = function ( /** * Get a `thread`. * @param {string} id The `thread` ID. + * @param {string} [include] Comma-separated list of relationships to include in response. * @param {*} [options] Override http request option. * @throws {RequiredError} */ getThread: async ( id: string, + include?: string, options: AxiosRequestConfig = {} ): Promise => { // verify required parameter 'id' is not null or undefined @@ -28726,6 +29736,10 @@ export const ThreadsApiAxiosParamCreator = function ( configuration ); + if (include !== undefined) { + localVarQueryParameter['include'] = include; + } + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions?.headers ?? {}; localVarRequestOptions.headers = { @@ -28744,6 +29758,7 @@ export const ThreadsApiAxiosParamCreator = function ( * @param {string} [filterCollaborationContextId] A collaboration context to filter on. * @param {string} [pageCursor] The cursor for the next page of items. * @param {number} [pageSize] The number of items to return. + * @param {string} [include] Comma-separated list of relationships to include in response. * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -28751,6 +29766,7 @@ export const ThreadsApiAxiosParamCreator = function ( filterCollaborationContextId?: string, pageCursor?: string, pageSize?: number, + include?: string, options: AxiosRequestConfig = {} ): Promise => { const localVarPath = `/threads`; @@ -28791,6 +29807,10 @@ export const ThreadsApiAxiosParamCreator = function ( localVarQueryParameter['page[size]'] = pageSize; } + if (include !== undefined) { + localVarQueryParameter['include'] = include; + } + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions?.headers ?? {}; localVarRequestOptions.headers = { @@ -28843,17 +29863,20 @@ export const ThreadsApiFp = function (configuration?: Configuration) { /** * Get a `thread`. * @param {string} id The `thread` ID. + * @param {string} [include] Comma-separated list of relationships to include in response. * @param {*} [options] Override http request option. * @throws {RequiredError} */ async getThread( id: string, + include?: string, options?: AxiosRequestConfig ): Promise< (axios?: AxiosInstance, basePath?: string) => AxiosPromise > { const localVarAxiosArgs = await localVarAxiosParamCreator.getThread( id, + include, options ); return createRequestFunction( @@ -28868,6 +29891,7 @@ export const ThreadsApiFp = function (configuration?: Configuration) { * @param {string} [filterCollaborationContextId] A collaboration context to filter on. * @param {string} [pageCursor] The cursor for the next page of items. * @param {number} [pageSize] The number of items to return. + * @param {string} [include] Comma-separated list of relationships to include in response. * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -28875,6 +29899,7 @@ export const ThreadsApiFp = function (configuration?: Configuration) { filterCollaborationContextId?: string, pageCursor?: string, pageSize?: number, + include?: string, options?: AxiosRequestConfig ): Promise< (axios?: AxiosInstance, basePath?: string) => AxiosPromise @@ -28883,6 +29908,7 @@ export const ThreadsApiFp = function (configuration?: Configuration) { filterCollaborationContextId, pageCursor, pageSize, + include, options ); return createRequestFunction( @@ -28925,12 +29951,17 @@ export const ThreadsApiFactory = function ( /** * Get a `thread`. * @param {string} id The `thread` ID. + * @param {string} [include] Comma-separated list of relationships to include in response. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getThread(id: string, options?: any): AxiosPromise { + getThread( + id: string, + include?: string, + options?: any + ): AxiosPromise { return localVarFp - .getThread(id, options) + .getThread(id, include, options) .then((request) => request(axios, basePath)); }, /** @@ -28938,6 +29969,7 @@ export const ThreadsApiFactory = function ( * @param {string} [filterCollaborationContextId] A collaboration context to filter on. * @param {string} [pageCursor] The cursor for the next page of items. * @param {number} [pageSize] The number of items to return. + * @param {string} [include] Comma-separated list of relationships to include in response. * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -28945,10 +29977,17 @@ export const ThreadsApiFactory = function ( filterCollaborationContextId?: string, pageCursor?: string, pageSize?: number, + include?: string, options?: any ): AxiosPromise { return localVarFp - .getThreads(filterCollaborationContextId, pageCursor, pageSize, options) + .getThreads( + filterCollaborationContextId, + pageCursor, + pageSize, + include, + options + ) .then((request) => request(axios, basePath)); }, }; @@ -28987,6 +30026,13 @@ export interface ThreadsApiGetThreadRequest { * @memberof ThreadsApiGetThread */ readonly id: string; + + /** + * Comma-separated list of relationships to include in response. + * @type {string} + * @memberof ThreadsApiGetThread + */ + readonly include?: string; } /** @@ -29015,6 +30061,13 @@ export interface ThreadsApiGetThreadsRequest { * @memberof ThreadsApiGetThreads */ readonly pageSize?: number; + + /** + * Comma-separated list of relationships to include in response. + * @type {string} + * @memberof ThreadsApiGetThreads + */ + readonly include?: string; } /** @@ -29056,7 +30109,7 @@ export class ThreadsApi extends BaseAPI { options?: AxiosRequestConfig ) { return ThreadsApiFp(this.configuration) - .getThread(requestParameters.id, options) + .getThread(requestParameters.id, requestParameters.include, options) .then((request) => request(this.axios, this.basePath)); } @@ -29076,6 +30129,7 @@ export class ThreadsApi extends BaseAPI { requestParameters.filterCollaborationContextId, requestParameters.pageCursor, requestParameters.pageSize, + requestParameters.include, options ) .then((request) => request(this.axios, this.basePath)); @@ -30006,6 +31060,70 @@ export const UserGroupsApiAxiosParamCreator = function ( configuration?: Configuration ) { return { + /** + * Add a `user` to a `user-group`. + * @param {string} id A `user-group` ID. + * @param {UserIdList} userIdList + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + addUsersToUserGroup: async ( + id: string, + userIdList: UserIdList, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'id' is not null or undefined + assertParamExists('addUsersToUserGroup', 'id', id); + // verify required parameter 'userIdList' is not null or undefined + assertParamExists('addUsersToUserGroup', 'userIdList', userIdList); + const localVarPath = `/user-groups/{id}/users`.replace( + `{${'id'}}`, + encodeURIComponent(String(id)) + ); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { + method: 'POST', + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication OAuth2 required + // oauth required + await setOAuthToObject( + localVarHeaderParameter, + 'OAuth2', + [], + configuration + ); + + localVarHeaderParameter['Content-Type'] = 'application/vnd.api+json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions?.headers ?? {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + userIdList, + localVarRequestOptions, + configuration + ); + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * Create a `user-group` * @param {CreateUserGroupRequest} createUserGroupRequest @@ -30131,6 +31249,33 @@ export const UserGroupsApiFp = function (configuration?: Configuration) { const localVarAxiosParamCreator = UserGroupsApiAxiosParamCreator(configuration); return { + /** + * Add a `user` to a `user-group`. + * @param {string} id A `user-group` ID. + * @param {UserIdList} userIdList + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async addUsersToUserGroup( + id: string, + userIdList: UserIdList, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.addUsersToUserGroup( + id, + userIdList, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, /** * Create a `user-group` * @param {CreateUserGroupRequest} createUserGroupRequest @@ -30164,7 +31309,7 @@ export const UserGroupsApiFp = function (configuration?: Configuration) { id: string, options?: AxiosRequestConfig ): Promise< - (axios?: AxiosInstance, basePath?: string) => AxiosPromise + (axios?: AxiosInstance, basePath?: string) => AxiosPromise > { const localVarAxiosArgs = await localVarAxiosParamCreator.getUserGroup( id, @@ -30191,6 +31336,22 @@ export const UserGroupsApiFactory = function ( ) { const localVarFp = UserGroupsApiFp(configuration); return { + /** + * Add a `user` to a `user-group`. + * @param {string} id A `user-group` ID. + * @param {UserIdList} userIdList + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + addUsersToUserGroup( + id: string, + userIdList: UserIdList, + options?: any + ): AxiosPromise { + return localVarFp + .addUsersToUserGroup(id, userIdList, options) + .then((request) => request(axios, basePath)); + }, /** * Create a `user-group` * @param {CreateUserGroupRequest} createUserGroupRequest @@ -30211,7 +31372,7 @@ export const UserGroupsApiFactory = function ( * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getUserGroup(id: string, options?: any): AxiosPromise { + getUserGroup(id: string, options?: any): AxiosPromise { return localVarFp .getUserGroup(id, options) .then((request) => request(axios, basePath)); @@ -30219,6 +31380,27 @@ export const UserGroupsApiFactory = function ( }; }; +/** + * Request parameters for addUsersToUserGroup operation in UserGroupsApi. + * @export + * @interface UserGroupsApiAddUsersToUserGroupRequest + */ +export interface UserGroupsApiAddUsersToUserGroupRequest { + /** + * A `user-group` ID. + * @type {string} + * @memberof UserGroupsApiAddUsersToUserGroup + */ + readonly id: string; + + /** + * + * @type {UserIdList} + * @memberof UserGroupsApiAddUsersToUserGroup + */ + readonly userIdList: UserIdList; +} + /** * Request parameters for createUserGroup operation in UserGroupsApi. * @export @@ -30254,6 +31436,26 @@ export interface UserGroupsApiGetUserGroupRequest { * @extends {BaseAPI} */ export class UserGroupsApi extends BaseAPI { + /** + * Add a `user` to a `user-group`. + * @param {UserGroupsApiAddUsersToUserGroupRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof UserGroupsApi + */ + public addUsersToUserGroup( + requestParameters: UserGroupsApiAddUsersToUserGroupRequest, + options?: AxiosRequestConfig + ) { + return UserGroupsApiFp(this.configuration) + .addUsersToUserGroup( + requestParameters.id, + requestParameters.userIdList, + options + ) + .then((request) => request(this.axios, this.basePath)); + } + /** * Create a `user-group` * @param {UserGroupsApiCreateUserGroupRequest} requestParameters Request parameters. @@ -30472,14 +31674,14 @@ export const UsersApiAxiosParamCreator = function ( }, /** * List `user`s. - * @param {string} [filterClientId] Comma-separated list of client IDs to filter on. + * @param {string} [filterIdpId] Id from the idpProvider. * @param {string} [pageCursor] The cursor for the next page of items. * @param {number} [pageSize] The number of items to return. * @param {*} [options] Override http request option. * @throws {RequiredError} */ listUsers: async ( - filterClientId?: string, + filterIdpId?: string, pageCursor?: string, pageSize?: number, options: AxiosRequestConfig = {} @@ -30509,8 +31711,8 @@ export const UsersApiAxiosParamCreator = function ( configuration ); - if (filterClientId !== undefined) { - localVarQueryParameter['filter[clientId]'] = filterClientId; + if (filterIdpId !== undefined) { + localVarQueryParameter['filter[idpId]'] = filterIdpId; } if (pageCursor !== undefined) { @@ -30622,14 +31824,14 @@ export const UsersApiFp = function (configuration?: Configuration) { }, /** * List `user`s. - * @param {string} [filterClientId] Comma-separated list of client IDs to filter on. + * @param {string} [filterIdpId] Id from the idpProvider. * @param {string} [pageCursor] The cursor for the next page of items. * @param {number} [pageSize] The number of items to return. * @param {*} [options] Override http request option. * @throws {RequiredError} */ async listUsers( - filterClientId?: string, + filterIdpId?: string, pageCursor?: string, pageSize?: number, options?: AxiosRequestConfig @@ -30637,7 +31839,7 @@ export const UsersApiFp = function (configuration?: Configuration) { (axios?: AxiosInstance, basePath?: string) => AxiosPromise > { const localVarAxiosArgs = await localVarAxiosParamCreator.listUsers( - filterClientId, + filterIdpId, pageCursor, pageSize, options @@ -30708,20 +31910,20 @@ export const UsersApiFactory = function ( }, /** * List `user`s. - * @param {string} [filterClientId] Comma-separated list of client IDs to filter on. + * @param {string} [filterIdpId] Id from the idpProvider. * @param {string} [pageCursor] The cursor for the next page of items. * @param {number} [pageSize] The number of items to return. * @param {*} [options] Override http request option. * @throws {RequiredError} */ listUsers( - filterClientId?: string, + filterIdpId?: string, pageCursor?: string, pageSize?: number, options?: any ): AxiosPromise { return localVarFp - .listUsers(filterClientId, pageCursor, pageSize, options) + .listUsers(filterIdpId, pageCursor, pageSize, options) .then((request) => request(axios, basePath)); }, }; @@ -30790,11 +31992,11 @@ export interface UsersApiGetUserGroupsForUserRequest { */ export interface UsersApiListUsersRequest { /** - * Comma-separated list of client IDs to filter on. + * Id from the idpProvider. * @type {string} * @memberof UsersApiListUsers */ - readonly filterClientId?: string; + readonly filterIdpId?: string; /** * The cursor for the next page of items. @@ -30884,7 +32086,7 @@ export class UsersApi extends BaseAPI { ) { return UsersApiFp(this.configuration) .listUsers( - requestParameters.filterClientId, + requestParameters.filterIdpId, requestParameters.pageCursor, requestParameters.pageSize, options diff --git a/client/vertex-client.ts b/client/vertex-client.ts index 5b9ba64..5261d09 100644 --- a/client/vertex-client.ts +++ b/client/vertex-client.ts @@ -4,24 +4,39 @@ import { AccountsApi, ApplicationsApi, BatchesApi, + CollaborationContextsApi, Configuration, ExportsApi, + FileCollectionsApi, + FileJobsApi, FilesApi, GeometrySetsApi, HitsApi, + ModelViewsApi, Oauth2Api, OAuth2Token, + PartRenditionsApi, + PartRevisionInstancesApi, PartRevisionsApi, PartsApi, + PermissionGrantsApi, + PmiApi, + PropertyEntriesApi, + RepliesApi, SceneAlterationsApi, SceneAnnotationsApi, SceneItemOverridesApi, SceneItemsApi, ScenesApi, + SceneSynchronizationsApi, SceneViewsApi, SceneViewStatesApi, + SearchSessionsApi, StreamKeysApi, + ThreadsApi, TranslationInspectionsApi, + UserGroupsApi, + UsersApi, WebhookSubscriptionsApi, } from '../index'; import { @@ -67,6 +82,11 @@ export interface BuildReq { }; readonly initialToken?: OAuth2Token; + /** + * An async function to fetch an access token. + * If not provided, the default implementation will be used. + */ + readonly tokenFetcher?: () => Promise; } /** @@ -77,6 +97,7 @@ interface CtorReq { readonly axiosInst: AxiosInstance; readonly basePath: string; readonly token: OAuth2Token; + readonly tokenFetcher?: () => Promise; } const TenMinsInMs = 600_000; @@ -121,33 +142,56 @@ export class VertexClient { public accounts: AccountsApi; public applications: ApplicationsApi; public batches: BatchesApi; + public collaborationContexts: CollaborationContextsApi; public exports: ExportsApi; + public fileCollections: FileCollectionsApi; + public fileJobs: FileJobsApi; public files: FilesApi; public geometrySets: GeometrySetsApi; public hits: HitsApi; + public modelViews: ModelViewsApi; public oAuth2: Oauth2Api; + public partRenditions: PartRenditionsApi; + public partRevisionInstances: PartRevisionInstancesApi; public partRevisions: PartRevisionsApi; public parts: PartsApi; + public permissionGrants: PermissionGrantsApi; + public pmi: PmiApi; + public propertyEntries: PropertyEntriesApi; + public replies: RepliesApi; public sceneAlterations: SceneAlterationsApi; public sceneAnnotations: SceneAnnotationsApi; public sceneItemOverrides: SceneItemOverridesApi; public sceneItems: SceneItemsApi; + public sceneSynchronizations: SceneSynchronizationsApi; public scenes: ScenesApi; public sceneViews: SceneViewsApi; public sceneViewStates: SceneViewStatesApi; + public searchSessions: SearchSessionsApi; public streamKeys: StreamKeysApi; + public threads: ThreadsApi; public translationInspections: TranslationInspectionsApi; + public userGroups: UserGroupsApi; + public users: UsersApi; public webhookSubscriptions: WebhookSubscriptionsApi; public axiosInstance: AxiosInstance; public config: Configuration; public token: OAuth2Token; + private acquireToken: () => Promise; private tokenFetchedEpochMs: number; - private constructor({ auth, axiosInst, basePath, token }: CtorReq) { + private constructor({ + auth, + axiosInst, + basePath, + token, + tokenFetcher, + }: CtorReq) { this.oAuth2 = auth; this.token = token; + this.acquireToken = tokenFetcher || (() => createToken(auth)); this.tokenFetchedEpochMs = nowEpochMs(); this.config = new Configuration({ accessToken: this.accessTokenRefresher, @@ -157,16 +201,50 @@ export class VertexClient { this.accounts = new AccountsApi(this.config, undefined, axiosInst); this.applications = new ApplicationsApi(this.config, undefined, axiosInst); this.batches = new BatchesApi(this.config, undefined, axiosInst); + this.collaborationContexts = new CollaborationContextsApi( + this.config, + undefined, + axiosInst + ); this.exports = new ExportsApi(this.config, undefined, axiosInst); + this.fileCollections = new FileCollectionsApi( + this.config, + undefined, + axiosInst + ); + this.fileJobs = new FileJobsApi(this.config, undefined, axiosInst); this.files = new FilesApi(this.config, undefined, axiosInst); this.geometrySets = new GeometrySetsApi(this.config, undefined, axiosInst); this.hits = new HitsApi(this.config, undefined, axiosInst); + this.modelViews = new ModelViewsApi(this.config, undefined, axiosInst); + this.partRenditions = new PartRenditionsApi( + this.config, + undefined, + axiosInst + ); + this.partRevisionInstances = new PartRevisionInstancesApi( + this.config, + undefined, + axiosInst + ); this.partRevisions = new PartRevisionsApi( this.config, undefined, axiosInst ); this.parts = new PartsApi(this.config, undefined, axiosInst); + this.permissionGrants = new PermissionGrantsApi( + this.config, + undefined, + axiosInst + ); + this.pmi = new PmiApi(this.config, undefined, axiosInst); + this.propertyEntries = new PropertyEntriesApi( + this.config, + undefined, + axiosInst + ); + this.replies = new RepliesApi(this.config, undefined, axiosInst); this.sceneAlterations = new SceneAlterationsApi( this.config, undefined, @@ -183,19 +261,32 @@ export class VertexClient { axiosInst ); this.sceneItems = new SceneItemsApi(this.config, undefined, axiosInst); - this.scenes = new ScenesApi(this.config, undefined, axiosInst); - this.sceneViews = new SceneViewsApi(this.config, undefined, axiosInst); + this.sceneSynchronizations = new SceneSynchronizationsApi( + this.config, + undefined, + axiosInst + ); this.sceneViewStates = new SceneViewStatesApi( this.config, undefined, axiosInst ); + this.sceneViews = new SceneViewsApi(this.config, undefined, axiosInst); + this.scenes = new ScenesApi(this.config, undefined, axiosInst); + this.searchSessions = new SearchSessionsApi( + this.config, + undefined, + axiosInst + ); this.streamKeys = new StreamKeysApi(this.config, undefined, axiosInst); + this.threads = new ThreadsApi(this.config, undefined, axiosInst); this.translationInspections = new TranslationInspectionsApi( this.config, undefined, axiosInst ); + this.userGroups = new UserGroupsApi(this.config, undefined, axiosInst); + this.users = new UsersApi(this.config, undefined, axiosInst); this.webhookSubscriptions = new WebhookSubscriptionsApi( this.config, undefined, @@ -263,7 +354,9 @@ export class VertexClient { axiosInst ); - const token = args?.initialToken || (await createToken(auth)); + const token = + args?.initialToken || + (await (args?.tokenFetcher ? args.tokenFetcher() : createToken(auth))); return new VertexClient({ auth, axiosInst, basePath, token }); }; @@ -276,7 +369,7 @@ export class VertexClient { if (tokenValid) return this.token.access_token; console.log('Refreshing access token'); - this.token = await createToken(this.oAuth2); + this.token = await this.acquireToken(); this.tokenFetchedEpochMs = nowEpochMs(); return this.token.access_token; }; diff --git a/spec.yml b/spec.yml index 5729456..0e2a1d0 100644 --- a/spec.yml +++ b/spec.yml @@ -899,6 +899,77 @@ paths: tags: - batches /collaboration-contexts: + get: + description: List `collaboration-context`s + operationId: listCollaborationContexts + parameters: + - description: The cursor for the next page of items. + explode: true + in: query + name: page[cursor] + required: false + schema: + example: cHJkMDVFR2RLag== + type: string + style: form + - description: The number of items to return. + explode: true + in: query + name: page[size] + required: false + schema: + example: 10 + format: int32 + maximum: 200 + minimum: 1 + type: integer + style: form + responses: + '200': + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/CollaborationContextList' + description: OK + '401': + content: + application/vnd.api+json: + example: + errors: + - status: '401' + code: Unauthorized + title: Invalid or missing credentials. + schema: + $ref: '#/components/schemas/Failure' + description: Unauthorized + '404': + content: + application/vnd.api+json: + example: + errors: + - status: '404' + code: NotFound + title: The requested resource was not found. + schema: + $ref: '#/components/schemas/Failure' + description: Not Found + '415': + content: + application/vnd.api+json: + example: + errors: + - status: '415' + code: UnsupportedMediaType + title: + The provided media type is not supported. Update the Content-Type + header to application/vnd.api+json and try again. + schema: + $ref: '#/components/schemas/Failure' + description: Unsupported Media Type + security: + - OAuth2: [] + tags: + - replies post: description: Create a `collaboration-context`. operationId: createCollaborationContext @@ -1158,6 +1229,16 @@ paths: schema: $ref: '#/components/schemas/Uuid' style: simple + - description: Comma-separated list of relationships to include in response. + explode: true + in: query + name: include + required: false + schema: + example: user + maxLength: 32 + type: string + style: form responses: '200': content: @@ -1240,6 +1321,16 @@ paths: minimum: 1 type: integer style: form + - description: Comma-separated list of relationships to include in response. + explode: true + in: query + name: include + required: false + schema: + example: user + maxLength: 32 + type: string + style: form responses: '200': content: @@ -2450,6 +2541,235 @@ paths: - OAuth2: [] tags: - geometry-sets + /replies: + get: + description: List `replies` + operationId: listReplies + parameters: + - description: Comma-separated list of supplied IDs to filter on. + example: some-id-1,some-id-2 + explode: true + in: query + name: filter[threadId] + required: false + schema: + maxLength: 1024 + type: string + style: form + - description: The cursor for the next page of items. + explode: true + in: query + name: page[cursor] + required: false + schema: + example: cHJkMDVFR2RLag== + type: string + style: form + - description: The number of items to return. + explode: true + in: query + name: page[size] + required: false + schema: + example: 10 + format: int32 + maximum: 200 + minimum: 1 + type: integer + style: form + - description: Comma-separated list of relationships to include in response. + explode: true + in: query + name: include + required: false + schema: + example: user + maxLength: 32 + type: string + style: form + responses: + '200': + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ReplyList' + description: OK + '401': + content: + application/vnd.api+json: + example: + errors: + - status: '401' + code: Unauthorized + title: Invalid or missing credentials. + schema: + $ref: '#/components/schemas/Failure' + description: Unauthorized + '404': + content: + application/vnd.api+json: + example: + errors: + - status: '404' + code: NotFound + title: The requested resource was not found. + schema: + $ref: '#/components/schemas/Failure' + description: Not Found + '415': + content: + application/vnd.api+json: + example: + errors: + - status: '415' + code: UnsupportedMediaType + title: + The provided media type is not supported. Update the Content-Type + header to application/vnd.api+json and try again. + schema: + $ref: '#/components/schemas/Failure' + description: Unsupported Media Type + security: + - OAuth2: [] + tags: + - replies + /replies/{id}: + get: + description: Get a `reply`. + operationId: getReply + parameters: + - description: The `thread` ID. + explode: false + in: path + name: id + required: true + schema: + $ref: '#/components/schemas/Uuid' + style: simple + - description: Comma-separated list of relationships to include in response. + explode: true + in: query + name: include + required: false + schema: + example: user + maxLength: 32 + type: string + style: form + responses: + '200': + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Reply' + description: OK + '400': + content: + application/vnd.api+json: + example: + errors: + - status: '400' + code: BadRequest + title: Invalid, missing, or out-of-range request parameters. + schema: + $ref: '#/components/schemas/Failure' + description: Bad Request + '401': + content: + application/vnd.api+json: + example: + errors: + - status: '401' + code: Unauthorized + title: Invalid or missing credentials. + schema: + $ref: '#/components/schemas/Failure' + description: Unauthorized + '415': + content: + application/vnd.api+json: + example: + errors: + - status: '415' + code: UnsupportedMediaType + title: + The provided media type is not supported. Update the Content-Type + header to application/vnd.api+json and try again. + schema: + $ref: '#/components/schemas/Failure' + description: Unsupported Media Type + security: + - OAuth2: [] + tags: + - replies + /threads/{id}/replies: + post: + description: Create a `reply` belonging to a `thread`. + operationId: createReply + parameters: + - description: The `thread` ID. + explode: false + in: path + name: id + required: true + schema: + $ref: '#/components/schemas/Uuid' + style: simple + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/CreateReplyRequest' + required: true + responses: + '201': + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Reply' + description: Created + headers: + location: + $ref: '#/components/headers/Location' + '400': + content: + application/vnd.api+json: + example: + errors: + - status: '400' + code: BadRequest + title: Invalid, missing, or out-of-range request parameters. + schema: + $ref: '#/components/schemas/Failure' + description: Bad Request + '401': + content: + application/vnd.api+json: + example: + errors: + - status: '401' + code: Unauthorized + title: Invalid or missing credentials. + schema: + $ref: '#/components/schemas/Failure' + description: Unauthorized + '415': + content: + application/vnd.api+json: + example: + errors: + - status: '415' + code: UnsupportedMediaType + title: + The provided media type is not supported. Update the Content-Type + header to application/vnd.api+json and try again. + schema: + $ref: '#/components/schemas/Failure' + description: Unsupported Media Type + security: + - OAuth2: [] + tags: + - replies /scene-views/{id}/hits: post: description: Create a `hit` for a `scene-view`. @@ -8517,14 +8837,13 @@ paths: description: List `user`s. operationId: listUsers parameters: - - description: Comma-separated list of client IDs to filter on. + - description: Id from the idpProvider. explode: true in: query - name: filter[clientId] + name: filter[idpId] required: false schema: - example: ?filter[clientId]=some-id-1&filter[clientId]=some-id-2 - maxLength: 1024 + example: id type: string style: form - description: The cursor for the next page of items. @@ -8854,12 +9173,69 @@ paths: $ref: '#/components/schemas/Uuid' style: simple responses: - '200': + '204': + description: No Content + '401': content: application/vnd.api+json: + example: + errors: + - status: '401' + code: Unauthorized + title: Invalid or missing credentials. schema: - $ref: '#/components/schemas/UserGroup' - description: OK + $ref: '#/components/schemas/Failure' + description: Unauthorized + '404': + content: + application/vnd.api+json: + example: + errors: + - status: '404' + code: NotFound + title: The requested resource was not found. + schema: + $ref: '#/components/schemas/Failure' + description: Not Found + '415': + content: + application/vnd.api+json: + example: + errors: + - status: '415' + code: UnsupportedMediaType + title: + The provided media type is not supported. Update the Content-Type + header to application/vnd.api+json and try again. + schema: + $ref: '#/components/schemas/Failure' + description: Unsupported Media Type + security: + - OAuth2: [] + tags: + - user-groups + /user-groups/{id}/users: + post: + description: Add a `user` to a `user-group`. + operationId: addUsersToUserGroup + parameters: + - description: A `user-group` ID. + explode: false + in: path + name: id + required: true + schema: + $ref: '#/components/schemas/Uuid' + style: simple + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/UserIdList' + required: true + responses: + '204': + description: No Content '401': content: application/vnd.api+json: @@ -9766,6 +10142,17 @@ components: maxLength: 32 type: string style: form + IncludeUser: + description: Comma-separated list of relationships to include in response. + explode: true + in: query + name: include + required: false + schema: + example: user + maxLength: 32 + type: string + style: form ModelViewIdFilter: description: Filter annotations belonging to a model view. explode: true @@ -9848,8 +10235,22 @@ components: name: id required: true schema: - $ref: '#/components/schemas/Uuid' - style: simple + $ref: '#/components/schemas/Uuid' + style: simple + ThreadField: + description: + Comma-separated list of fields to return in response. An empty + value returns no fields. Due to its potential size, metadata is only returned + if explicitly requested. + explode: true + in: query + name: fields[thread] + required: false + schema: + example: replyCount + maxLength: 32 + type: string + style: form SceneId: description: The `scene` ID. explode: false @@ -10143,6 +10544,15 @@ components: example: -age,name type: string style: form + ReplyId: + description: The `thread` ID. + explode: false + in: path + name: id + required: true + schema: + $ref: '#/components/schemas/Uuid' + style: simple ThreadId: description: The `thread` ID. explode: false @@ -10152,6 +10562,17 @@ components: schema: $ref: '#/components/schemas/Uuid' style: simple + ThreadIdFilter: + description: Comma-separated list of supplied IDs to filter on. + example: some-id-1,some-id-2 + explode: true + in: query + name: filter[threadId] + required: false + schema: + maxLength: 1024 + type: string + style: form ClientIdFilter: description: Comma-separated list of client IDs to filter on. explode: true @@ -10440,6 +10861,21 @@ components: required: - vertexvis/batch:results type: object + CollaborationContextList: + additionalProperties: false + properties: + data: + items: + $ref: '#/components/schemas/CollaborationContextData' + type: array + links: + additionalProperties: + $ref: '#/components/schemas/Link' + type: object + required: + - data + - links + type: object CreateCollaborationContextRequest: additionalProperties: false properties: @@ -10487,6 +10923,10 @@ components: additionalProperties: $ref: '#/components/schemas/Link' type: object + included: + items: + $ref: '#/components/schemas/UserData' + type: array required: - data type: object @@ -10501,6 +10941,10 @@ components: additionalProperties: $ref: '#/components/schemas/Link' type: object + included: + items: + $ref: '#/components/schemas/UserData' + type: array required: - data - links @@ -10664,6 +11108,49 @@ components: required: - data type: object + ReplyList: + additionalProperties: false + properties: + data: + items: + $ref: '#/components/schemas/ReplyData' + type: array + links: + additionalProperties: + $ref: '#/components/schemas/Link' + type: object + included: + items: + $ref: '#/components/schemas/UserData' + type: array + required: + - data + - links + type: object + Reply: + additionalProperties: false + properties: + data: + $ref: '#/components/schemas/ReplyData' + links: + additionalProperties: + $ref: '#/components/schemas/Link' + type: object + included: + items: + $ref: '#/components/schemas/UserData' + type: array + required: + - data + type: object + CreateReplyRequest: + additionalProperties: false + properties: + data: + $ref: '#/components/schemas/CreateReplyRequest_data' + required: + - data + type: object CreateHitRequest: additionalProperties: false properties: @@ -10704,10 +11191,14 @@ components: $ref: '#/components/schemas/NonEmptyString' grant_type: example: client_credentials - maxLength: 32 + maxLength: 64 type: string + subject_token_type: + $ref: '#/components/schemas/NonEmptyString' refresh_token: $ref: '#/components/schemas/NonEmptyString' + subject_token: + $ref: '#/components/schemas/NonEmptyString' required: - grant_type type: object @@ -11650,6 +12141,16 @@ components: required: - data type: object + UserIdList: + additionalProperties: false + properties: + data: + items: + $ref: '#/components/schemas/UserId' + type: array + required: + - data + type: object WebhookSubscriptionList: additionalProperties: false properties: @@ -12040,6 +12541,26 @@ components: - relationships - type type: object + UserData: + additionalProperties: false + properties: + id: + description: ID of the resource. + example: f79d4760-0b71-44e4-ad0b-22743fdd4ca3 + format: uuid + maxLength: 36 + type: string + attributes: + $ref: '#/components/schemas/UserData_attributes' + links: + additionalProperties: + $ref: '#/components/schemas/Link' + type: object + required: + - attributes + - id + - type + type: object FileMetadataData: additionalProperties: false properties: @@ -12178,6 +12699,34 @@ components: required: - data type: object + ReplyData: + additionalProperties: false + properties: + type: + enum: + - reply + example: reply + type: string + id: + description: ID of the resource. + example: f79d4760-0b71-44e4-ad0b-22743fdd4ca3 + format: uuid + maxLength: 36 + type: string + attributes: + $ref: '#/components/schemas/ReplyData_attributes' + relationships: + $ref: '#/components/schemas/ReplyData_relationships' + links: + additionalProperties: + $ref: '#/components/schemas/Link' + type: object + required: + - attributes + - id + - relationships + - type + type: object Point: additionalProperties: false description: 2D point. @@ -12914,6 +13463,10 @@ components: required: - data type: object + NullableObject: + maxProperties: 0 + nullable: true + type: object CreateSceneItemRequestData: additionalProperties: false properties: @@ -13415,7 +13968,7 @@ components: - id - type type: object - UserData: + UserGroupData: additionalProperties: false properties: id: @@ -13425,7 +13978,7 @@ components: maxLength: 36 type: string attributes: - $ref: '#/components/schemas/UserData_attributes' + $ref: '#/components/schemas/UserGroupData_attributes' links: additionalProperties: $ref: '#/components/schemas/Link' @@ -13435,23 +13988,22 @@ components: - id - type type: object - UserGroupData: + UserId: additionalProperties: false properties: + type: + description: Resource object type. + enum: + - user + example: user + type: string id: description: ID of the resource. example: f79d4760-0b71-44e4-ad0b-22743fdd4ca3 format: uuid maxLength: 36 type: string - attributes: - $ref: '#/components/schemas/UserGroupData_attributes' - links: - additionalProperties: - $ref: '#/components/schemas/Link' - type: object required: - - attributes - id - type type: object @@ -13668,6 +14220,14 @@ components: required: - selector type: object + ThreadRelationship: + additionalProperties: false + properties: + data: + $ref: '#/components/schemas/ThreadRelationship_data' + required: + - data + type: object BoundingBox: additionalProperties: false description: 3D bounding-box @@ -15005,6 +15565,27 @@ components: - relationships - type type: object + CreateReplyRequest_data_attributes: + properties: + body: + type: string + required: + - body + type: object + CreateReplyRequest_data: + properties: + type: + description: Resource object type. + enum: + - reply + example: reply + type: string + attributes: + $ref: '#/components/schemas/CreateReplyRequest_data_attributes' + required: + - attributes + - type + type: object CreateHitRequest_data_attributes: properties: point: @@ -15579,7 +16160,9 @@ components: anyOf: - $ref: '#/components/schemas/GeometrySetRelationship' - $ref: '#/components/schemas/PartRevisionRelationship' + - $ref: '#/components/schemas/NullableObject' description: Relationship to a `geometry-set` or `part-revision`. + nullable: true type: object UpdateSceneItemRequest_data: properties: @@ -16345,6 +16928,9 @@ components: type: string body: type: string + replyCount: + format: int32 + type: integer required: - createdAt - modifiedAt @@ -16361,6 +16947,26 @@ components: - collaborationContext - user type: object + UserData_attributes: + properties: + fullName: + type: string + email: + type: string + createdAt: + example: 2020-01-01T12:00:00Z + format: date-time + type: string + idpId: + example: some-string + maxLength: 1024 + minLength: 1 + type: string + required: + - createdAt + - email + - fullName + type: object FileMetadataData_attributes: properties: name: @@ -16454,6 +17060,33 @@ components: - id - type type: object + ReplyData_attributes: + properties: + createdAt: + example: 2020-01-01T12:00:00Z + format: date-time + type: string + modifiedAt: + example: 2020-01-01T12:00:00Z + format: date-time + type: string + body: + type: string + required: + - body + - createdAt + - modifiedAt + type: object + ReplyData_relationships: + properties: + thread: + $ref: '#/components/schemas/ThreadRelationship' + user: + $ref: '#/components/schemas/UserRelationship' + required: + - thread + - user + type: object HitResultData_attributes: properties: point: @@ -17265,26 +17898,6 @@ components: required: - status type: object - UserData_attributes: - properties: - fullName: - type: string - email: - type: string - createdAt: - example: 2020-01-01T12:00:00Z - format: date-time - type: string - idpId: - example: some-string - maxLength: 1024 - minLength: 1 - type: string - required: - - createdAt - - email - - fullName - type: object UserGroupData_attributes: properties: name: @@ -17380,6 +17993,22 @@ components: - id - type type: object + ThreadRelationship_data: + properties: + type: + enum: + - thread + type: string + id: + description: ID of the resource. + example: f79d4760-0b71-44e4-ad0b-22743fdd4ca3 + format: uuid + maxLength: 36 + type: string + required: + - id + - type + type: object QueryById_data_attributes: properties: type: From 3fd2107a51b821c87df6071f2bce347685e042d4 Mon Sep 17 00:00:00 2001 From: Brent Arndorfer Date: Fri, 1 Aug 2025 08:37:23 -0500 Subject: [PATCH 2/4] Added file collection helper --- client/helpers/file-collections.ts | 46 ++++++++++++++++++++++++++++++ client/helpers/index.ts | 1 + 2 files changed, 47 insertions(+) create mode 100644 client/helpers/file-collections.ts diff --git a/client/helpers/file-collections.ts b/client/helpers/file-collections.ts new file mode 100644 index 0000000..1af48f9 --- /dev/null +++ b/client/helpers/file-collections.ts @@ -0,0 +1,46 @@ +import { FileCollectionMetadataData } from '../../api'; +import { DeleteReq, getPage } from '../../client/index'; + +/** + * Delete all file collections. + * + * @param args - The {@link DeleteReq}. + */ +export async function deleteAllFileCollections({ + client, + pageSize = 100, + exceptions = new Set(), +}: DeleteReq): Promise { + let fileCollections: FileCollectionMetadataData[] = []; + let pageCursor: string | undefined; + do { + // eslint-disable-next-line no-await-in-loop + const res = await getPage(() => + client.fileCollections.listFileCollections({ + pageSize, + pageCursor, + }) + ); + const ids = res.page.data + .map((d) => d.id) + .filter((id) => !exceptions.has(id)); + pageCursor = res.cursor; + // eslint-disable-next-line no-await-in-loop + const deleteRes = await Promise.allSettled( + ids.map((id) => client.fileCollections.deleteFileCollection({ id })) + ); + deleteRes.forEach((r, index) => { + if (r.status === 'rejected') { + console.error( + `Failed to delete file collection with id=${ids[index]}: ${r.reason}` + ); + exceptions.add(ids[index]); + } + }); + fileCollections = fileCollections.concat( + res.page.data as FileCollectionMetadataData[] + ); + } while (pageCursor); + + return fileCollections; +} diff --git a/client/helpers/index.ts b/client/helpers/index.ts index 5b79eb0..d121dc1 100644 --- a/client/helpers/index.ts +++ b/client/helpers/index.ts @@ -1,4 +1,5 @@ export * from './exports'; +export * from './file-collections'; export * from './files'; export * from './parts'; export * from './queued-jobs'; From d9326ad686ca6536de70d12ffafeb098c2556915 Mon Sep 17 00:00:00 2001 From: Brent Arndorfer Date: Fri, 1 Aug 2025 15:21:14 -0500 Subject: [PATCH 3/4] Updated default polling logic --- client/helpers/exports.ts | 5 +- client/helpers/index.ts | 1 + client/helpers/parts.ts | 5 +- client/helpers/polling.ts | 165 ++++++++++++++++++++++++++++++++++ client/helpers/queued-jobs.ts | 26 ++++-- client/helpers/scene-items.ts | 5 +- client/helpers/scenes.ts | 9 +- 7 files changed, 197 insertions(+), 19 deletions(-) create mode 100644 client/helpers/polling.ts diff --git a/client/helpers/exports.ts b/client/helpers/exports.ts index 7676c6b..be5c75d 100644 --- a/client/helpers/exports.ts +++ b/client/helpers/exports.ts @@ -1,9 +1,8 @@ import { CreateExportRequest, Export } from '../../index'; import { BaseReq, + DefaultPolling, isPollError, - MaxAttempts, - PollIntervalMs, pollQueuedJob, throwOnError, } from '../index'; @@ -36,7 +35,7 @@ export async function createExport({ const pollRes = await pollQueuedJob({ id: queuedId, getQueuedJob: (id) => client.exports.getQueuedExport({ id }), - polling: { intervalMs: PollIntervalMs, maxAttempts: MaxAttempts }, + polling: DefaultPolling, }); if (isPollError(pollRes.res)) throwOnError(pollRes); if (verbose) onMsg(`Completed export ${pollRes.res.data.id}`); diff --git a/client/helpers/index.ts b/client/helpers/index.ts index d121dc1..cc23f34 100644 --- a/client/helpers/index.ts +++ b/client/helpers/index.ts @@ -2,6 +2,7 @@ export * from './exports'; export * from './file-collections'; export * from './files'; export * from './parts'; +export * from './polling'; export * from './queued-jobs'; export * from './scene-items'; export * from './scene-views'; diff --git a/client/helpers/parts.ts b/client/helpers/parts.ts index 3bd369c..eb54c9f 100644 --- a/client/helpers/parts.ts +++ b/client/helpers/parts.ts @@ -15,14 +15,13 @@ import { } from '../../index'; import { BaseReq, + DefaultPolling, DeleteReq, encodeIfNotEncoded, getBySuppliedId, getPage, head, - MaxAttempts, Polling, - PollIntervalMs, prettyJson, RenderImageReq, toAccept, @@ -85,7 +84,7 @@ export async function createPartFromFile({ client, createPartReq, onMsg = console.log, - polling = { intervalMs: PollIntervalMs, maxAttempts: MaxAttempts }, + polling = DefaultPolling, returnQueued = false, verbose, ...rest diff --git a/client/helpers/polling.ts b/client/helpers/polling.ts new file mode 100644 index 0000000..c3684be --- /dev/null +++ b/client/helpers/polling.ts @@ -0,0 +1,165 @@ +/** + * Polling helpers for handling API polling operations. + */ + +import { Polling } from '..'; + +export const DefaultPollIntervalMs = 500; // 500 milliseconds +export const DefaultPollTimeoutSeconds = 60 * 60; // 60 minutes +export const DefaultShortPollIntervalMs = 50; // 50 milliseconds +export const DefaultShortPollTimeoutSeconds = 60 * 10; // 10 minutes + +/** + * Default backoff configuration for polling. + * Backoff numbers are added to `intervalMs` after the attempt number is reached + * e.g. if `intervalMs` is 500 and `backoff[10]` is 2000, then the polling interval + * will be 2500ms after the 10th attempt. + */ +export const DefaultBackoffMs: Record = { + 0: DefaultPollIntervalMs, + 1: 500, + 10: 2000, + 30: 3000, + 50: 5000, + 300: 10000, + 1000: 20000, +}; + +/** + * Default polling configuration for batch operations. + * Numbers below will result in a total delay of about 60 minutes + * prior to reaching the maximum number of attempts. + */ +export const DefaultPolling: Polling = getPollingConfiguration({ + backoff: DefaultBackoffMs, // Use backoff + maxPollDurationSeconds: DefaultPollTimeoutSeconds, // 1 hour +}); + +/** + * Default short backoff configuration for polling. + * Use this for polling for operations that complete quickly + * and require a shorter delay between polling attempts. + */ +export const DefaultShortBackoffMs: Record = { + 0: DefaultShortPollIntervalMs, + 1: 50, + 10: 200, + 20: 300, + 40: 500, + 50: 1000, + 100: 3000, + 200: 5000, +}; + +/** + * Default short polling configuration for quick running operations. + * Numbers below will result in a total delay of about 10 minutes + * prior to reaching the maximum number of attempts. + */ +export const DefaultShortPolling: Polling = getPollingConfiguration({ + backoff: DefaultShortBackoffMs, // Use short backoff + maxPollDurationSeconds: DefaultShortPollTimeoutSeconds, // 10 minutes +}); + +/** + * Builds a polling configuration object based on the provided parameters. + * + * @param param0 + * @returns + */ +export function getPollingConfiguration({ + backoff, + intervalMs = DefaultPollIntervalMs, + maxPollDurationSeconds = DefaultPollTimeoutSeconds, +}: { + backoff?: Record; + intervalMs?: number; + maxPollDurationSeconds?: number; +}): Polling { + return { + intervalMs: intervalMs, + maxAttempts: getMaxAttempts({ + intervalMs, + maxPollDurationSeconds, + backoff, + }), + backoff, + }; +} + +/** + * Calculates the polling delay for a given attempt. + * @param param0 + * @returns {number} - The delay in milliseconds for the polling attempt. + */ +export const getPollingDelay = ({ + attempt, + polling, +}: { + attempt: number; + polling: Polling; +}): number => + polling.intervalMs + getBackoffForAttempt(attempt, polling.backoff); + +/** + * Calculates the maximum number of polling attempts based on the provided + * parameters. + * @param param0 + * @returns {number} - The maximum number of polling attempts. + */ +function getMaxAttempts({ + intervalMs, + maxPollDurationSeconds, + backoff, +}: { + intervalMs: number; + maxPollDurationSeconds: number; + backoff: Record | undefined; +}): number { + if (backoff) { + let remainingTimeMs = maxPollDurationSeconds * 1000; + let attempt = 0; + const backoffKeys = getBackoffKeys(backoff); + while (remainingTimeMs > 0) { + const backoffMs = getBackoffForAttempt(attempt + 1, backoff, backoffKeys); + console.log(`Attempt ${attempt + 1}, backoffMs: ${backoffMs}`); + remainingTimeMs -= intervalMs + backoffMs; + attempt += 1; + } + return attempt; + } + return Math.max(1, Math.floor(maxPollDurationSeconds / intervalMs)); +} + +/** + * Gets the backoff delay for a specific polling attempt. + * @param attempt - The current polling attempt number. + * @param backoff - The backoff configuration. + * @param backoffKeys - Optional keys to use for backoff lookup. + * @returns {number} - The backoff delay in milliseconds. + */ +function getBackoffForAttempt( + attempt: number, + backoff?: Record, + backoffKeys?: number[] +): number { + return backoff + ? backoff[ + [...(backoffKeys ?? getBackoffKeys(backoff))].find( + (key) => attempt > key + ) ?? 0 + ] ?? 0 + : 0; +} + +/** + * Gets the backoff keys from the backoff configuration. + * @param backoff - The backoff configuration. + * @returns {number[]} - The array of backoff keys. + */ +const getBackoffKeys = ( + backoff: Record +): number[] => + Object.keys(backoff) + .map((key) => parseInt(key, 10)) + .reverse(); diff --git a/client/helpers/queued-jobs.ts b/client/helpers/queued-jobs.ts index ed85a2b..a3d68c3 100644 --- a/client/helpers/queued-jobs.ts +++ b/client/helpers/queued-jobs.ts @@ -2,7 +2,14 @@ import axios, { AxiosResponse, CancelToken } from 'axios'; import { Limit } from 'p-limit'; import { hrtime } from 'process'; -import { ApiError, Batch, Failure, Polling, QueuedJob } from '../../index'; +import { + ApiError, + Batch, + Failure, + getPollingDelay, + Polling, + QueuedJob, +} from '../../index'; import { defined, delay, @@ -14,7 +21,7 @@ import { VertexError, } from '../utils'; -export const PollIntervalMs = 5000; +export const PollIntervalMs = 1000; export const AttemptsPerMin = 60000 / PollIntervalMs; @@ -68,8 +75,9 @@ export async function pollQueuedJob({ getQueuedJob, allow404 = false, limit, - polling: { intervalMs, maxAttempts, backoff }, + polling, }: PollQueuedJobReq): Promise> { + const { maxAttempts } = polling; async function poll(attempt: number): Promise> { const cancelSrc = axios.CancelToken.source(); const timerId = setTimeout( @@ -123,7 +131,10 @@ export async function pollQueuedJob({ } let attempts = 1; - let backoffMs = backoff?.[attempts] ?? 0; + let pollDelay = getPollingDelay({ + attempt: attempts, + polling, + }); // eslint-disable-next-line prefer-const let pollRes = await poll(attempts); /* eslint-disable no-await-in-loop */ @@ -135,8 +146,11 @@ export async function pollQueuedJob({ attempts <= maxAttempts ) { attempts += 1; - backoffMs = backoff?.[attempts] ?? backoffMs; - await delay(intervalMs + backoffMs); + pollDelay = getPollingDelay({ + attempt: attempts, + polling, + }); + await delay(pollDelay); pollRes = await poll(attempts); } /* eslint-enable no-await-in-loop */ diff --git a/client/helpers/scene-items.ts b/client/helpers/scene-items.ts index 13af208..d4ef597 100644 --- a/client/helpers/scene-items.ts +++ b/client/helpers/scene-items.ts @@ -1,12 +1,11 @@ import { CreateSceneItemRequest, SceneItem } from '../../index'; import { BaseReq, + DefaultShortPolling, defined, isApiError, isPollError, - MaxAttempts, Polling, - PollIntervalMs, pollQueuedJob, throwOnError, } from '../index'; @@ -57,7 +56,7 @@ export async function createSceneItem({ client, createSceneItemReq, onMsg = console.log, - polling = { intervalMs: PollIntervalMs, maxAttempts: MaxAttempts }, + polling = DefaultShortPolling, sceneId, verbose, }: CreateSceneItemReq): Promise { diff --git a/client/helpers/scenes.ts b/client/helpers/scenes.ts index 9dab762..860f3cb 100644 --- a/client/helpers/scenes.ts +++ b/client/helpers/scenes.ts @@ -23,6 +23,8 @@ import { } from '../../index'; import { BaseReq, + DefaultPolling, + DefaultShortPolling, defined, DeleteReq, getPage, @@ -165,8 +167,7 @@ export interface QueuedSceneItem { readonly res?: Failure | QueuedJob; } -const defaultPolling: Polling = { intervalMs: 200, maxAttempts: 4500 }; // 15 minute timeout for batch completions -const sceneReadyPolling: Polling = { intervalMs: 1000, maxAttempts: 3600 }; // one hour timeout for scene state ready +const sceneReadyPolling: Polling = DefaultPolling; // one hour timeout for scene state ready /** * Create a scene with scene items. @@ -179,7 +180,7 @@ export async function createSceneAndSceneItems({ onMsg = console.log, onProgress, parallelism, - polling = defaultPolling, + polling = DefaultShortPolling, returnQueued = false, verbose, }: CreateSceneAndSceneItemsReq): Promise { @@ -467,7 +468,7 @@ export const createSceneItemBatch = async ({ onProgress, limit, sceneId, - polling = { intervalMs: PollIntervalMs, maxAttempts: MaxAttempts }, + polling = DefaultShortPolling, }: CreateSceneItemBatchReq): Promise => { let batchErrors: QueuedBatchOps[] = []; let itemErrors: SceneItemError[] = []; From c4a91213b346b3e6560abb58208a5515caa6927a Mon Sep 17 00:00:00 2001 From: Brent Arndorfer Date: Fri, 1 Aug 2025 16:58:04 -0500 Subject: [PATCH 4/4] Updated function definitions --- client/helpers/polling.ts | 44 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/client/helpers/polling.ts b/client/helpers/polling.ts index c3684be..6fac688 100644 --- a/client/helpers/polling.ts +++ b/client/helpers/polling.ts @@ -92,14 +92,26 @@ export function getPollingConfiguration({ * @param param0 * @returns {number} - The delay in milliseconds for the polling attempt. */ -export const getPollingDelay = ({ +export function getPollingDelay({ attempt, polling, }: { attempt: number; polling: Polling; -}): number => - polling.intervalMs + getBackoffForAttempt(attempt, polling.backoff); +}): number { + return polling.intervalMs + getBackoffForAttempt(attempt, polling.backoff); +} + +/** + * Gets the backoff keys from the backoff configuration. + * @param backoff - The backoff configuration. + * @returns {number[]} - The array of backoff keys. + */ +function getBackoffKeys(backoff: Record): number[] { + return Object.keys(backoff) + .map((key) => parseInt(key, 10)) + .reverse(); +} /** * Calculates the maximum number of polling attempts based on the provided @@ -122,7 +134,6 @@ function getMaxAttempts({ const backoffKeys = getBackoffKeys(backoff); while (remainingTimeMs > 0) { const backoffMs = getBackoffForAttempt(attempt + 1, backoff, backoffKeys); - console.log(`Attempt ${attempt + 1}, backoffMs: ${backoffMs}`); remainingTimeMs -= intervalMs + backoffMs; attempt += 1; } @@ -143,23 +154,10 @@ function getBackoffForAttempt( backoff?: Record, backoffKeys?: number[] ): number { - return backoff - ? backoff[ - [...(backoffKeys ?? getBackoffKeys(backoff))].find( - (key) => attempt > key - ) ?? 0 - ] ?? 0 - : 0; + if (backoff) { + const keys = backoffKeys ?? getBackoffKeys(backoff); + const foundKey = [...keys].find((key) => attempt > key); + return backoff[foundKey ?? 0] ?? 0; + } + return 0; } - -/** - * Gets the backoff keys from the backoff configuration. - * @param backoff - The backoff configuration. - * @returns {number[]} - The array of backoff keys. - */ -const getBackoffKeys = ( - backoff: Record -): number[] => - Object.keys(backoff) - .map((key) => parseInt(key, 10)) - .reverse();