UNPKG

@inweb/client

Version:

JavaScript REST API client for the Open Cloud Server

1,120 lines (1,051 loc) 40.1 kB
/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a // license agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// import { EventEmitter2 } from "@inweb/eventemitter2"; import { IHttpClient } from "./IHttpClient"; import { HttpClient } from "./HttpClient"; import { FetchError } from "./FetchError"; import { ClientEventMap } from "./ClientEvents"; import { Assembly } from "./Assembly"; import { File } from "./File"; import { Job } from "./Job"; import { Project } from "./Project"; import { User } from "./User"; import { OAuthClient } from "./OAuthClient"; import { ISharedLinkPermissions } from "./ISharedLink"; import { SharedLink } from "./SharedLink"; import { SharedFile } from "./SharedFile"; import { parseArgs } from "./Utils"; /** * Provides methods for managing Open Cloud Server resources such as users, files, assemblies, jobs, * projects, etc. */ export class Client extends EventEmitter2<ClientEventMap> { private _serverUrl = ""; private _httpClient: IHttpClient = new HttpClient(""); private _user: User | null = null; public eventEmitter: EventEmitter2 = this; /** * @param params - An object containing client configuration parameters. * @param params.serverUrl - Open Cloud REST API server URL. * @param params.url - Deprecated since `25.8`. Use `serverUrl` instead. */ constructor(params: { serverUrl?: string; url?: string } = {}) { super(); this.configure(params); } /** * Open Cloud REST API server URL. Use {@link configure | configure()} to change server URL. * * @readonly */ get serverUrl(): string { return this._serverUrl; } /** * HTTP client instance used to send requests to the REST API server. * * @readonly */ get httpClient(): IHttpClient { return this._httpClient; } /** * Deprecated since `25.3`. Use `Viewer.options()` instead to change `Viewer` parameters. * * @deprecated */ get options(): any { console.warn( "Client.options has been deprecated since 25.3 and will be removed in a future release, use Viewer.options instead." ); const data = { showWCS: true, cameraAnimation: true, antialiasing: true, groundShadow: false, shadows: false, cameraAxisXSpeed: 4, cameraAxisYSpeed: 1, ambientOcclusion: false, enableStreamingMode: true, enablePartialMode: false, memoryLimit: 3294967296, cuttingPlaneFillColor: { red: 0xff, green: 0x98, blue: 0x00 }, edgesColor: { r: 0xff, g: 0x98, b: 0x00 }, facesColor: { r: 0xff, g: 0x98, b: 0x00 }, edgesVisibility: true, edgesOverlap: true, facesOverlap: false, facesTransparancy: 200, enableCustomHighlight: true, sceneGraph: false, edgeModel: true, reverseZoomWheel: false, enableZoomWheel: true, enableGestures: true, }; return { ...data, data, defaults: () => data, resetToDefaults: () => {}, saveToStorage: () => {}, loadFromStorage: () => {}, }; } /** * Changes the client parameters. * * After changing the parameters, you must re-login. * * @param params - An object containing new parameters. * @param params.serverUrl - Open Cloud REST API server URL. */ configure(params: { serverUrl?: string }): this { this._serverUrl = (params.serverUrl || "").replace(/\/+$/, ""); this._httpClient = new HttpClient(this.serverUrl); this._user = null; return this; } /** * Returns client and server versions. * * No login is required to obtain the version. */ version(): Promise<{ server: string; client: string; hash: string }> { return this.httpClient .get("/version") .then((response) => response.json()) .then((data) => ({ ...data, server: data.version, client: "CLIENT_JS_VERSION", })); } /** * Registers a new user on the server. * * No login is required to register a new user. * * @param email - User email. Cannot be empty. Must be unique within the server. * @param password - User password. Cannot be empty. Password can only contain letters (a-z, A-Z), * numbers (0-9), and special characters (~!@#$%^&*()_-+={}[]<>|/'":;.,?). * @param userName - User name. Cannot be empty or blank if defined. this to `undefined` to use * `username` from email. */ registerUser(email: string, password: string, userName?: string): Promise<any> { return this.httpClient .post("/register", { email, password, userName: userName ?? (email + "").split("@").at(0), }) .then((response) => response.json()); } /** * Resends a Confirmation Email to the new user. If the user's email is already confirmed, an exception * will be thrown. * * @param email - User email. * @param password - User password. */ resendConfirmationEmail(email: string, password: string): Promise<any> { return this.httpClient .post("/register/email-confirmation", { email, password }) .then((response) => response.json()); } /** * Marks the user's email address as confirmed. If the user's email is already confirmed, an exception * will be thrown. * * @param emailConfirmationId - Confirmation code from the Confirmation Email. */ confirmUserEmail(emailConfirmationId: string): Promise<any> { return this.httpClient .get(`/register/email-confirmation/${emailConfirmationId}`) .then((response) => response.json()); } /** * Log in an existing user using email or user name. * * @param email - An email or user name for authentication request. * @param password - Password for authentication request. */ async signInWithEmail(email: string, password: string): Promise<User> { const credentials = btoa(unescape(encodeURIComponent(email + ":" + password))); this.httpClient.headers["Authorization"] = "Basic " + credentials; const response = await this.httpClient.get("/token"); const data = await response.json(); return this.setCurrentUser(data); } /** * Log in an existing user using access token (API Key). * * @param token - An access token for authentication request. See {@link User.token} for more details. */ async signInWithToken(token: string): Promise<User> { this.httpClient.headers["Authorization"] = token; const response = await this.httpClient.get("/user"); const data = await response.json(); return this.setCurrentUser(data); } /** * Log out. * * You must log in again using {@link signInWithEmail} or {@link signInWithToken} to continue making * requests to the server */ signOut(): void { this.clearCurrentUser(); } // Save the current logged in user information for internal use. private setCurrentUser(data: any): User { this._user = new User(data, this.httpClient); this.httpClient.headers["Authorization"] = data.tokenInfo.token; this.httpClient.signInUserId = this._user.id; this.httpClient.signInUserIsAdmin = this._user.isAdmin; return this._user; } private clearCurrentUser(): void { this._user = null; delete this.httpClient.headers["Authorization"]; this.httpClient.signInUserId = ""; this.httpClient.signInUserIsAdmin = false; } /** * Returns the current logged in user. Returns `null` if the user is not logged in or the logged in * user has deleted themself. */ getCurrentUser(): User | null { if (this._user && !this.httpClient.signInUserId) this._user = null; return this._user; } /** * Returns the list of server enabled indentity providers. */ getIdentityProviders(): Promise<{ name: string; url: string }[]> { return this.httpClient.get("/identity").then((response) => response.json()); } /** * Returns the current server settings. * * @returns Returns an object with server settings. For more information, see * {@link https://cloud.opendesign.com/docs//pages/server/api.html#Settings | Open Cloud Settings API}. */ getServerSettings(): Promise<any> { return this.httpClient.get("/settings").then((response) => response.json()); } /** * Changes the server settings. * * Only administrators can change server settings. If the current logged in user is not an * administrator, an exception will be thrown. * * @param settings - An object with the new server settings or part of the settings. For more * information, see * {@link https://cloud.opendesign.com/docs//pages/server/api.html#Settings | Open Cloud Settings API}. * @returns Returns an object with updated server settings. */ updateServerSettings(settings: any): Promise<any> { return this.httpClient.put("/settings", settings).then((response) => response.json()); } /** * Result for OAuth client list. * * @typedef {any} OAuthClientsResult * @property {OAuthClient[]} result - Result client list. * @property {number} start - The starting index in the client list in the request. * @property {number} limit - The maximum number of requested clients. * @property {number} allSize - Total number of OAuth clients on the server. * @property {number} size - The number of clients in the result list. */ /** * Returns a list of OAuth clients of the server. * * Only administrators can get a list of OAuth clients. If the current logged in user is not an * administrator, an exception will be thrown. * * @param start - The starting index in the client list. Used for paging. * @param limit - The maximum number of clients that should be returned per request. Used for paging. */ getOAuthClients( start?: number, limit?: number ): Promise<{ result: OAuthClient[]; start: number; limit: number; allSize: number; size: number; }> { const searchParams = new URLSearchParams(); if (start > 0) searchParams.set("start", start.toString()); if (limit > 0) searchParams.set("limit", limit.toString()); let queryString = searchParams.toString(); if (queryString) queryString = "?" + queryString; return this.httpClient .get(`/oauth/clients${queryString}`) .then((response) => response.json()) .then((clients) => { return { ...clients, result: clients.result.map((data) => new OAuthClient(data, this.httpClient)), }; }); } /** * Returns information about the specified OAuth client. * * Only administrators can get OAuth clients. If the current logged in user is not an administrator, an * exception will be thrown. * * @param clientId - Client ID. */ getOAuthClient(clientId: string): Promise<OAuthClient> { return this.httpClient .get(`/oauth/clients/${clientId}`) .then((response) => response.json()) .then((data) => new OAuthClient(data, this.httpClient)); } /** * Creates a new OAuth client on the server. * * Only administrators can create OAuth clients. If the current logged in user is not an administrator, * an exception will be thrown. * * @param name - Client name. * @param redirectUrl - Endpoint to which the OAuth 2.0 server sends the response. * @param description - Client description. */ createOAuthClient(name: string, redirectUrl: string, description?: string): Promise<OAuthClient> { return this.httpClient .post("/oauth/clients", { name, redirectUrl, description, }) .then((response) => response.json()) .then((data) => new OAuthClient(data, this.httpClient)); } /** * Deletes the specified OAuth client from the server. * * Only administrators can delete OAuth clients. If the current logged in user is not an administrator, * an exception will be thrown. * * @param clientId - Client ID. * @returns Returns the raw data of a deleted client. For more information, see * {@link https://cloud.opendesign.com/docs//pages/server/api.html#OAuthClient | Open Cloud OAuth Clients API}. */ deleteOAuthClient(clientId: string): Promise<any> { return this.httpClient.delete(`/oauth/clients/${clientId}`).then((response) => response.json()); } /** * Returns the list of server users. * * Only administrators can get a list of users. If the current logged in user is not an administrator, * an exception will be thrown. */ getUsers(): Promise<User[]> { return this.httpClient .get("/users") .then((response) => response.json()) .then((array) => array.map((data) => ({ id: data.id, ...data.userBrief }))) .then((array) => array.map((data) => new User(data, this.httpClient))); } /** * Returns information about the specified user. * * Only administrators can get other users. If the current logged in user is not an administrator, they * can only get themselves, otherwise an exception will be thrown. * * @param userId - User ID. */ getUser(userId: string): Promise<User> { if (this.httpClient.signInUserIsAdmin) { return this.httpClient .get(`/users/${userId}`) .then((response) => response.json()) .then((data) => ({ id: data.id, ...data.userBrief })) .then((data) => new User(data, this.httpClient)); } else if (userId === this.httpClient.signInUserId) { return this.httpClient .get("/user") .then((response) => response.json()) .then((data) => ({ id: userId, ...data })) .then((data) => new User(data, this.httpClient)); } else { return Promise.reject(new FetchError(403)); } } /** * Creates a new user on the server. * * Only administrators can create users. If the current logged in user is not an administrator, an * exception will be thrown. * * @param email - User email. Cannot be empty. Must be unique within the server. * @param password - User password. Cannot be empty. Password can only contain latin letters (a-z, * A-Z), numbers (0-9), and special characters (~!@#$%^&*()_-+={}[]<>|/'":;.,?). * @param params - Additional user data. * @param params.isAdmin - `true` if user is an administrator. * @param params.userName - User name. Cannot be empty or blank if defined. Specify `undefined` to use * `username` from email. * @param params.firstName - First name. * @param params.lastName - Last name. * @param params.canCreateProject - `true` if user is allowed to create a project. * @param params.projectsLimit - The maximum number of projects that the user can create. * @param params.storageLimit - The size of the file storage available to the user in bytes. */ createUser( email: string, password: string, params: { isAdmin?: boolean; userName?: string; firstName?: string; lastName?: string; canCreateProject?: boolean; projectsLimit?: number; storageLimit?: number; } = {} ): Promise<User> { const { isAdmin, userName, ...rest } = params; return this.httpClient .post("/users", { isAdmin, userBrief: { ...rest, email, userName: userName ?? (email + "").split("@").at(0), }, password, }) .then((response) => response.json()) .then((data) => ({ id: data.id, ...data.userBrief })) .then((data) => new User(data, this.httpClient)); } /** * Deletes the specified user from the server. * * Only administrators can delete users. If the current logged in user is not an administrator, an * exception will be thrown. * * Administrators can delete themselves or other administrators. An administrator can only delete * themself if they is not the last administrator. * * You need to re-login after deleting the current logged in user. * * @param userId - User ID. * @returns Returns the raw data of a deleted user. For more information, see * {@link https://cloud.opendesign.com/docs//pages/server/api.html#Users | Open Cloud Users API}. */ deleteUser(userId: string): Promise<any> { if (this.httpClient.signInUserIsAdmin) { return this.httpClient .delete(`/users/${userId}`) .then((response) => response.json()) .then((data) => { if (userId === this.httpClient.signInUserId) { this.clearCurrentUser(); } return data; }); } else { return Promise.reject(new FetchError(403)); } } /** * Result for file list. * * @typedef {any} FilesResult * @property {File[]} result - Result file list. * @property {number} start - The starting index in the file list in the request. * @property {number} limit - The maximum number of requested files. * @property {number} allSize - Total number of files the user has access to. * @property {number} size - The number of files in the result list. */ /** * Returns a list of files that the current logged in user has uploaded to the server or has access to. * * @param start - The starting index in the file list. Used for paging. * @param limit - The maximum number of files that should be returned per request. Used for paging. * @param name - Filter the files by part of the name. Case sensitive. * @param ext - Filter the files by extension. Extension can be `dgn`, `dwf`, `dwg`, `dxf`, `ifc`, * `ifczip`, `nwc`, `nwd`, `obj`, `rcs`, `rfa`, `rvt`, `step`, `stl`, `stp`, `vsf`, or any other file * type extension. * @param ids - List of file IDs to return. * @param sortByDesc - Allows to specify the descending order of the result. By default, files are * sorted by name in ascending order. * @param sortField - Allows to specify sort field. * @param shared - Returns shared files only. */ getFiles( start?: number, limit?: number, name?: string, ext?: string | string[], ids?: string | string[], sortByDesc?: boolean, sortField?: string, shared?: boolean ): Promise<{ result: File[]; start: number; limit: number; allSize: number; size: number; }> { const searchParams = new URLSearchParams(); if (start > 0) searchParams.set("start", start.toString()); if (limit > 0) searchParams.set("limit", limit.toString()); if (name) searchParams.set("name", name); if (ext) { if (Array.isArray(ext)) ext = ext.join("|"); if (typeof ext === "string") ext = ext.toLowerCase(); if (ext) searchParams.set("ext", ext); } if (ids) { if (Array.isArray(ids)) ids = ids.join("|"); searchParams.set("id", ids); } if (sortByDesc !== undefined) searchParams.set("sortBy", sortByDesc ? "desc" : "asc"); if (sortField) searchParams.set("sortField", sortField); if (shared) searchParams.set("shared", "true"); let queryString = searchParams.toString(); if (queryString) queryString = "?" + queryString; return this.httpClient .get(`/files${queryString}`) .then((response) => response.json()) .then((files) => { return { ...files, result: files.result.map((data) => new File(data, this.httpClient)), }; }); } /** * Returns information about the specified file. * * @param fileId - File ID. */ getFile(fileId: string): Promise<File> { return this.httpClient .get(`/files/${fileId}`) .then((response) => response.json()) .then((data) => new File(data, this.httpClient)); } /** * Upload a drawing or reference file to the server. * * Fires: * * - {@link UploadProgressEvent | uploadprogress} * * @param file - {@link https://developer.mozilla.org/docs/Web/API/File | Web API File} object are * generally retrieved from a {@link https://developer.mozilla.org/docs/Web/API/FileList | FileList} * object returned as a result of a user selecting files using the HTML `<input>` element. * @param params - An object containing upload parameters. * @param params.geometry - Create job to convert file geometry data. Can be: * * - `true` - Convert file geometry data to `VSFX` format to open the file in `VisualizeJS` viewer. * - `vsfx` - Convert file geometry data to `VSFX` format to open the file in `VisualizeJS` viewer. * - `gltf` - Convert file geometry data to `glTF` format to open the file in `Three.js` viewer. * * @param params.properties - Create job to extract file properties. * @param params.waitForDone - Wait for geometry and properties jobs to complete. * @param params.timeout - The time, in milliseconds that the function should wait jobs. If no one jobs * are done during this time, the `TimeoutError` exception will be thrown. * @param params.interval - The time, in milliseconds, the function should delay in between checking * jobs status. * @param params.signal - An * {@link https://developer.mozilla.org/docs/Web/API/AbortController | AbortController} signal, which * can be used to abort waiting as desired. * @param params.onProgress - Upload progress callback. */ async uploadFile( file: globalThis.File, params: { geometry?: boolean | string; properties?: boolean; waitForDone?: boolean; timeout?: number; interval?: number; signal?: AbortSignal; onProgress?: (progress: number, file: globalThis.File) => void; } = { geometry: true, properties: false, waitForDone: false, } ): Promise<File> { const result = await this.httpClient .uploadFile("/files", file, (progress) => { this.emitEvent({ type: "uploadprogress", data: progress, file }); params.onProgress?.(progress, file); }) .then((xhr: XMLHttpRequest) => JSON.parse(xhr.responseText)) .then((data) => new File(data, this.httpClient)); const geometryType = typeof params.geometry === "string" ? params.geometry : "vsfx"; const jobs: string[] = []; if (params.geometry) jobs.push((await result.extractGeometry(geometryType)).outputFormat); if (params.properties) jobs.push((await result.extractProperties()).outputFormat); if (jobs.length > 0) if (params.waitForDone) await result.waitForDone(jobs, true, params); else await result.checkout(); return result; } /** * Deletes the specified file and all its versions from the server. * * You cannot delete a version file using `deleteFile()`, only the original file. To delete a version * file use {@link File.deleteVersion | File.deleteVersion()}. * * @param fileId - File ID. * @returns Returns the raw data of a deleted file. For more information, see * {@link https://cloud.opendesign.com/docs//pages/server/api.html#Files | Open Cloud Files API}. */ deleteFile(fileId: string): Promise<any> { return this.httpClient.delete(`/files/${fileId}`).then((response) => response.json()); } /** * Downloads the specified file from the server. * * @param fileId - File ID. * @param onProgress - Download progress callback. * @param signal - An * {@link https://developer.mozilla.org/docs/Web/API/AbortController | AbortController} signal. Allows * to communicate with a fetch request and abort it if desired. */ downloadFile(fileId: string, onProgress?: (progress: number) => void, signal?: AbortSignal): Promise<ArrayBuffer> { return this.httpClient .downloadFile(`/files/${fileId}/downloads`, onProgress, { signal }) .then((response) => response.arrayBuffer()); } /** * Result for job list. * * @typedef {any} JobsResult * @property {Job[]} result - Result job list. * @property {number} start - The starting index in the job list in the request. * @property {number} limit - The maximum number of requested jobs. * @property {number} allSize - Total number of jobs created by the user. * @property {number} size - The number of jobs in the result list. */ /** * Returns a list of jobs started by the current logged in user. * * @param status - Filter the jobs by status. Status can be `waiting`, `inpogress`, `done` or `failed`. * @param limit - The maximum number of jobs that should be returned per request. Used for paging. * @param start - The starting index in the job list. Used for paging. * @param sortByDesc - Allows to specify the descending order of the result. By default, jobs are * sorted by creation time in ascending order. * @param {boolean} sortField - Allows to specify sort field. */ getJobs( status?: string | string[], limit?: number, start?: number, sortByDesc?: boolean, sortField?: string ): Promise<{ result: Job[]; start: number; limit: number; allSize: number; size: number; }> { const searchParams = new URLSearchParams(); if (start > 0) searchParams.set("start", start.toString()); if (limit > 0) searchParams.set("limit", limit.toString()); if (status) { if (Array.isArray(status)) status = status.join("|"); if (typeof status === "string") status = status.trim().toLowerCase(); if (status) searchParams.set("status", status); } if (sortByDesc !== undefined) searchParams.set("sortBy", sortByDesc ? "desc" : "asc"); if (sortField) searchParams.set("sortField", sortField); let queryString = searchParams.toString(); if (queryString) queryString = "?" + queryString; return this.httpClient .get(`/jobs${queryString}`) .then((response) => response.json()) .then((jobs) => ({ ...jobs, result: jobs.result.map((data) => new Job(data, this.httpClient)), })); } /** * Returns information about the specified job. * * @param jobId - Job ID. */ getJob(jobId: string): Promise<Job> { return this.httpClient .get(`/jobs/${jobId}`) .then((response) => response.json()) .then((data) => new Job(data, this.httpClient)); } /** * Runs a new job on the server for the sepecified file. * * @param fileId - File ID. * @param outputFormat - The job type. Can be one of: * * - `geometry` - Convert file geometry data to `VSFX` format suitable for `VisualizeJS` viewer. * - `geometryGltf` - Convert file geometry data to `glTF` format suitable for `Three.js` viewer. * - `properties` - Extract file properties. * - `validation` - Validate the file. Only for `IFC` files. * - `dwg`, `obj`, `gltf`, `glb`, `vsf`, `pdf`, `3dpdf` - Export file to the one of the supported format. * - Other custom job name. Custom job runner must be registered in the job templates table before * creating a job. * * @param parameters - Parameters for the job runner. Can be given as command line arguments for the * File Converter tool in form `--arg=value`. */ createJob(fileId: string, outputFormat: string, parameters?: string | object): Promise<Job> { return this.httpClient .post("/jobs", { fileId, outputFormat, parameters: parseArgs(parameters), }) .then((response) => response.json()) .then((data) => new Job(data, this.httpClient)); } /** * Deletes the specified job from the server job list. Jobs that are in progress or have already been * completed cannot be deleted. * * @param jobId - Job ID. * @returns Returns the raw data of a deleted job. For more information, see * {@link https://cloud.opendesign.com/docs//pages/server/api.html#Jobs | Open Cloud Jobs API}. */ deleteJob(jobId: string): Promise<any> { return this.httpClient.delete(`/jobs/${jobId}`).then((response) => response.json()); } /** * Result for assembly list. * * @typedef {any} AssembliesResult * @property {Assembly[]} result - Result assembly list. * @property {number} start - The starting index in the assembly list in the request. * @property {number} limit - The maximum number of requested assemblies. * @property {number} allSize - Total number of assemblies the user has access to. * @property {number} size - The number of assemblies in the result list. */ /** * Returns a list of assemblies created by the current logged in user. * * @param start - The starting index in the assembly list. Used for paging. * @param limit - The maximum number of assemblies that should be returned per request. Used for * paging. * @param name - Filter the assemblies by part of the name. Case sensitive. * @param ids - List of assembly IDs to return. * @param sortByDesc - Allows to specify the descending order of the result. By default assemblies are * sorted by name in ascending order. * @param sortField - Allows to specify sort field. */ getAssemblies( start?: number, limit?: number, name?: string, ids?: string | string[], sortByDesc?: boolean, sortField?: string ): Promise<{ result: Assembly[]; start: number; limit: number; allSize: number; size: number; }> { const searchParams = new URLSearchParams(); if (start > 0) searchParams.set("start", start.toString()); if (limit > 0) searchParams.set("limit", limit.toString()); if (name) searchParams.set("name", name); if (ids) { if (Array.isArray(ids)) ids = ids.join("|"); if (typeof ids === "string") ids = ids.trim(); if (ids) searchParams.set("id", ids); } if (sortByDesc !== undefined) searchParams.set("sortBy", sortByDesc ? "desc" : "asc"); if (sortField) searchParams.set("sortField", sortField); let queryString = searchParams.toString(); if (queryString) queryString = "?" + queryString; return this.httpClient .get(`/assemblies${queryString}`) .then((response) => response.json()) .then((assemblies) => { return { ...assemblies, result: assemblies.result.map((data) => new Assembly(data, this.httpClient)), }; }); } /** * Returns information about the specified assembly. * * @param assemblyId - Assembly ID. */ getAssembly(assemblyId: string): Promise<Assembly> { return this.httpClient .get(`/assemblies/${assemblyId}`) .then((response) => response.json()) .then((data) => new Assembly(data, this.httpClient)); } /** * Creates a new assembly on the server. * * @param files - List of file IDs. * @param name - Assembly name. * @param params - Additional assembly creating parameters. * @param params.waitForDone - Wait for assembly to be created. * @param params.timeout - The time, in milliseconds, that the function should wait for the assembly to * be created. If the assembly is not created within this time, a TimeoutError exception will be * thrown. * @param params.interval - The time, in milliseconds, the function should delay in between checking * assembly status. * @param params.signal - An * {@link https://developer.mozilla.org/docs/Web/API/AbortController | AbortController} signal, which * can be used to abort waiting as desired. * @param params.onCheckout - Waiting progress callback. Return `true` to cancel waiting. */ createAssembly( files: string[], name: string, params?: { waitForDone?: boolean; timeout?: number; interval?: number; signal?: AbortSignal; onCheckout?: (assembly: Assembly, ready: boolean) => boolean; } ): Promise<Assembly> { const { waitForDone } = params ?? {}; return this.httpClient .post("/assemblies", { name, files }) .then((response) => response.json()) .then((data) => new Assembly(data, this.httpClient)) .then((result) => (waitForDone ? result.waitForDone(params) : result)); } /** * Deletes the specified assembly from the server. * * @param assemblyId - Assembly ID. * @returns Returns the raw data of a deleted assembly. For more information, see * {@link https://cloud.opendesign.com/docs//pages/server/api.html#Assemblies | Open Cloud API}. */ deleteAssembly(assemblyId: string): Promise<any> { return this.httpClient.delete(`/assemblies/${assemblyId}`).then((response) => response.json()); } /** * Result for project list. * * @typedef {any} ProjectsResult * @property {Project[]} result - Result project list. * @property {number} start - The starting index in the project list in the request. * @property {number} limit - The maximum number of requested projects. * @property {number} allSize - Total number of projects the user has access to. * @property {number} size - The number of projects in the result list. */ /** * Returns a list of projects that the currently logged in user has created or has access to. * * @param start - The starting index in the project list. Used for paging. * @param limit - The maximum number of projects that should be returned per request. Used for paging. * @param name - Filter the projects by part of the name. Case sensitive. * @param ids - List of project IDs to return. * @param sortByDesc - Allows to specify the descending order of the result. By default projects are * sorted by name in ascending order. */ getProjects( start?: number, limit?: number, name?: string, ids?: string | string[], sortByDesc?: boolean ): Promise<{ result: Project[]; start: number; limit: number; allSize: number; size: number; }> { const searchParams = new URLSearchParams(); if (start > 0) searchParams.set("start", start.toString()); if (limit > 0) searchParams.set("limit", limit.toString()); if (name) searchParams.set("name", name); if (ids) { if (Array.isArray(ids)) ids = ids.join("|"); if (typeof ids === "string") ids = ids.trim(); if (ids) searchParams.set("id", ids); } if (sortByDesc !== undefined) searchParams.set("sortBy", sortByDesc ? "desc" : "asc"); let queryString = searchParams.toString(); if (queryString) queryString = "?" + queryString; return this.httpClient .get(`/projects${queryString}`) .then((response) => response.json()) .then((projects) => { // fix for server 23.5 and below if (Array.isArray(projects)) { let result = projects; if (ids) result = result.filter((x) => ids.includes(x.id)); if (name) result = result.filter((x) => x.name.includes(name)); if (limit > 0) { const begin = start > 0 ? start : 0; result = result.slice(begin, begin + limit); } return { allSize: projects.length, start, limit, result, size: result.length, }; } return projects; }) .then((projects) => { return { ...projects, result: projects.result.map((data) => new Project(data, this.httpClient)), }; }); } /** * Returns information about the specified project. * * @param projectId - Project ID. */ getProject(projectId: string): Promise<Project> { return this.httpClient .get(`/projects/${projectId}`) .then((response) => response.json()) .then((data) => new Project(data, this.httpClient)); } /** * Creates a new project on the server. * * @param name - Project name. * @param description - Project description. * @param startDate - Project start date. * @param endDate - Project end date. */ createProject( name: string, description?: string, startDate?: Date | string, endDate?: Date | string ): Promise<Project> { return this.httpClient .post("/projects", { name, description, startDate: startDate instanceof Date ? startDate.toISOString() : startDate, endDate: endDate instanceof Date ? endDate.toISOString() : endDate, }) .then((response) => response.json()) .then((data) => new Project(data, this.httpClient)); } /** * Deletes the specified project from the server. * * @param projectId - Project ID. * @returns Returns the raw data of a deleted project. For more information, see * {@link https://cloud.opendesign.com/docs//pages/server/api.html#Project | Open Cloud Projects API}. */ deleteProject(projectId: string): Promise<any> { return this.httpClient .delete(`/projects/${projectId}`) .then((response) => response.text()) .then((text) => { // fix for server 23.5 and below try { return JSON.parse(text); } catch { return { id: projectId }; } }); } /** * Returns information about the specified file shared link. * * @param token - Shared link token. */ getSharedLink(token: string): Promise<SharedLink> { return this.httpClient .get(`/shares/${token}`) .then((response) => response.json()) .then((data) => new SharedLink(data, this.httpClient)); } /** * Creates a shared link for the specified file. * * @param fileId - File ID. * @param permissions - Share permissions. */ createSharedLink(fileId: string, permissions?: ISharedLinkPermissions): Promise<SharedLink> { return this.httpClient .post("/shares", { fileId, permissions, }) .then((response) => response.json()) .then((data) => new SharedLink(data, this.httpClient)); } /** * Deletes the specified shared link. * * Only file owner can delete shared link. If the current logged in user is not a file owner, an * exception will be thrown. * * @param token - Shared link token. * @returns Returns the raw data of a deleted shared link. For more information, see * {@link https://cloud.opendesign.com/docs//pages/server/api.html#ShareLinks | Open Cloud SharedLinks API}. */ deleteSharedLink(token: string): Promise<any> { return this.httpClient.delete(`/shares/${token}`).then((response) => response.json()); } /** * Returns information about a file from a shared link. * * Some file features are not available via shared link: * * - Updating file properties, preview, and viewpoints * - Running file jobs * - Managing file permissions * - Managing file versions * - Deleting file * * @param token - Shared link token. * @param password - Password to get access to the file. */ getSharedFile(token: string, password?: string): Promise<File> { return this.httpClient .get(`/shares/${token}/info`, { headers: { "InWeb-Password": password } }) .then((response) => response.json()) .then((data) => new SharedFile(data, password, this.httpClient)); } }