UNPKG

@inweb/client

Version:

JavaScript REST API client for the Open Cloud Server

1,312 lines (1,297 loc) 103 kB
/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2026, 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-2026 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.ODA = global.ODA || {}, global.ODA.Api = global.ODA.Api || {}))); })(this, (function (exports) { 'use strict'; class Endpoint { constructor(path, httpClient, headers = {}) { this.path = path; this.httpClient = httpClient; this.headers = headers; } appendVersionParam(relativePath) { if (this._useVersion === undefined) return relativePath; const delimiter = relativePath.includes("?") ? "&" : "?"; return `${relativePath}${delimiter}version=${this._useVersion}`; } getEndpointPath(relativePath) { return this.appendVersionParam(`${this.path}${relativePath}`); } get(relativePath, signal) { return this.httpClient.get(this.getEndpointPath(relativePath), { signal, headers: this.headers }); } post(relativePath, body) { return this.httpClient.post(this.getEndpointPath(relativePath), body, { headers: this.headers }); } put(relativePath, body) { return this.httpClient.put(this.getEndpointPath(relativePath), body, { headers: this.headers }); } delete(relativePath) { return this.httpClient.delete(this.getEndpointPath(relativePath), { headers: this.headers }); } useVersion(version) { this._useVersion = version; return this; } } const STATUS_CODES = { 100: "Continue", 101: "Switching Protocols", 102: "Processing", 103: "Early Hints", 200: "OK", 201: "Created", 202: "Accepted", 203: "Non-Authoritative Information", 204: "No Content", 205: "Reset Content", 206: "Partial Content", 207: "Multi-Status", 208: "Already Reported", 226: "IM Used", 300: "Multiple Choices", 301: "Moved Permanently", 302: "Found", 303: "See Other", 304: "Not Modified", 305: "Use Proxy", 307: "Temporary Redirect", 308: "Permanent Redirect", 400: "Bad Request", 401: "Unauthorized", 402: "Payment Required", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 406: "Not Acceptable", 407: "Proxy Authentication Required", 408: "Request Time-out", 409: "Conflict", 410: "Gone", 411: "Length Required", 412: "Precondition Failed", 413: "Payload Too Large", 414: "URI Too Long", 415: "Unsupported Media Type", 416: "Range Not Satisfiable", 417: "Expectation Failed", 418: "I'm a teapot", 421: "Misdirected Request", 422: "Unprocessable Entity", 423: "Locked", 424: "Failed Dependency", 425: "Too Early", 426: "Upgrade Required", 428: "Precondition Required", 429: "Too Many Requests", 431: "Header Fields Too Large", 451: "Unavailable For Legal Reasons", 500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway", 503: "Service Unavailable", 504: "Gateway Timeout", 505: "HTTP Version Not Supported", 506: "Variant Also Negotiates", 507: "Insufficient Storage", 508: "Loop Detected", 509: "Bandwidth Limit Exceeded", 510: "Not Extended", 511: "Network Authentication Required", }; function statusText(status) { return STATUS_CODES[status] || `Error ${status}`; } function error400(text, _default = "400") { try { return JSON.parse(text).description; } catch { return _default; } } class FetchError extends Error { constructor(status, message) { super(message || statusText(status)); this.name = "FetchError"; this.status = status; this.statusText = statusText(status); } } class Model extends Endpoint { constructor(data, file) { super(`${file.path}/downloads`, file.httpClient); this._data = data; this._file = file; } get assembly() { return this._file; } get data() { return this._data; } set data(value) { this._data = value; } get database() { return this.data.database; } get default() { return this.data.default; } get file() { return this._file; } get fileId() { return this.data.fileId; } get geometry() { return this.data.geometry; } get id() { return this.data.id; } get name() { return this.data.name; } get type() { return this.file.type; } get version() { return this.data.version; } getModels() { return Promise.resolve([this]); } getModelTransformMatrix(handle) { return this.file.getModelTransformMatrix(handle); } setModelTransformMatrix(handle, transform) { return this.file.setModelTransformMatrix(handle, transform).then(() => this); } getViewpoints() { return this._file .getViewpoints() .then((array) => array.filter(({ custom_fields = {} }) => custom_fields.modelId === this.id || custom_fields.modelName === this.name)); } saveViewpoint(viewpoint) { return this._file.saveViewpoint({ ...viewpoint, custom_fields: { ...viewpoint.custom_fields, modelId: this.id, modelName: this.name }, }); } deleteViewpoint(guid) { return this._file.deleteViewpoint(guid); } getSnapshot(guid) { return this._file.getSnapshot(guid); } getSnapshotData(guid, bitmapGuid) { return this._file.getSnapshotData(guid, bitmapGuid); } downloadResource(dataId, onProgress, signal) { return this._file.downloadResource(dataId, onProgress, signal); } downloadResourceRange(dataId, requestId, ranges, onProgress, signal) { return this._file.downloadResourceRange(dataId, requestId, ranges, onProgress, signal); } getReferences(signal) { return this._file.getReferences(signal); } } function normalizeParam(param, separator = "|") { if (typeof param === "string") param = param.split(","); if (Array.isArray(param)) param = param.filter((x) => x).join(separator); if (typeof param === "string") param = param.trim(); return param.toString(); } function delay(ms, signal) { return new Promise((resolve) => { let timeoutId = 0; const abortHandler = () => { clearTimeout(timeoutId); resolve(true); }; timeoutId = window.setTimeout(() => { signal.removeEventListener("abort", abortHandler); resolve(false); }, ms || 0); signal.addEventListener("abort", abortHandler, { once: true }); }); } async function waitFor(func, params = {}) { var _a, _b, _c; const timeout = params.timeout || 600000; const interval = params.interval || 3000; const signal = (_a = params.signal) !== null && _a !== void 0 ? _a : new AbortController().signal; const abortError = (_b = params.abortError) !== null && _b !== void 0 ? _b : new DOMException("Aborted", "AbortError"); const timeoutError = (_c = params.timeoutError) !== null && _c !== void 0 ? _c : new DOMException("Timeout", "TimeoutError"); const end = performance.now() + timeout; let count = timeout / interval; do { if (await func(params)) return Promise.resolve(params.result); if ((await delay(interval, signal)) || signal.aborted) return Promise.reject(abortError); } while (performance.now() < end && --count > 0); return Promise.reject(timeoutError); } function parseArgs(args) { if (typeof args === "string") { const firstArg = args.indexOf("--"); if (firstArg !== -1) args = args.slice(firstArg); const argArray = args .split("--") .map((x) => x .split("=") .map((y) => y.split(" ")) .flat()) .filter((x) => x[0]) .map((x) => x.concat([""])); return Object.fromEntries(argArray); } return args || {}; } function userFullName(firstName, lastName = "", userName = "") { var _a; if (firstName && typeof firstName !== "string") { return userFullName((_a = firstName.firstName) !== null && _a !== void 0 ? _a : firstName.name, firstName.lastName, firstName.userName); } return `${firstName !== null && firstName !== void 0 ? firstName : ""} ${lastName !== null && lastName !== void 0 ? lastName : ""}`.trim() || userName; } function userInitials(fullName = "") { const names = fullName.split(" ").filter((x) => x); return names .reduce((initials, name, index) => { if (index === 0 || index === names.length - 1) initials += name.charAt(0); return initials; }, "") .toUpperCase(); } class ClashTest extends Endpoint { constructor(data, path, httpClient) { super(`${path}/clashes/${data.id}`, httpClient); this.data = data; } get clearance() { return this.data.clearance; } get createdAt() { return this.data.createdAt; } get data() { return this._data; } set data(value) { this._data = value; this._data.owner.avatarUrl = `${this.httpClient.serverUrl}/users/${this._data.owner.userId}/avatar`; this._data.owner.fullName = userFullName(this._data.owner); this._data.owner.initials = userInitials(this._data.owner.fullName); } get id() { return this.data.id; } get lastModifiedAt() { return this.data.lastModifiedAt; } get name() { return this.data.name; } set name(value) { this.data.name = value; } get owner() { return this.data.owner; } get selectionSetA() { return this.data.selectionSetA; } get selectionTypeA() { return this.data.selectionTypeA; } get selectionSetB() { return this.data.selectionSetB; } get selectionTypeB() { return this.data.selectionTypeB; } get status() { return this.data.status; } get tolerance() { return this.data.tolerance; } async checkout() { const response = await this.get(""); this.data = await response.json(); return this; } async update(data) { const response = await this.put("", data); this.data = await response.json(); return this; } delete() { return super.delete("").then((response) => response.json()); } save() { return this.update(this.data); } waitForDone(params) { const checkDone = () => this.checkout().then((test) => { var _a; const ready = ["done", "failed"].includes(test.status); const cancel = (_a = params === null || params === void 0 ? void 0 : params.onCheckout) === null || _a === void 0 ? void 0 : _a.call(params, test, ready); return cancel || ready; }); return waitFor(checkDone, params).then(() => this); } getReport() { return this.get("/report").then((response) => response.json()); } } class Assembly extends Endpoint { constructor(data, httpClient) { super(`/assemblies/${data.id}`, httpClient); this.data = data; } get activeVersion() { return this.data.activeVersion; } get associatedFiles() { return this.data.associatedFiles; } get created() { return this.data.created; } get data() { return this._data; } set data(value) { var _a; var _b; this._data = value; this._data.owner.avatarUrl = `${this.httpClient.serverUrl}/users/${this._data.owner.userId}/avatar`; this._data.owner.fullName = userFullName(this._data.owner); this._data.owner.initials = userInitials(this._data.owner.fullName); (_a = (_b = this._data).associatedFiles) !== null && _a !== void 0 ? _a : (_b.associatedFiles = []); this._data.associatedFiles.forEach((file) => (file.link = `${this.httpClient.serverUrl}/files/${file.fileId}`)); } get files() { return this.data.files; } get geometryType() { return this.status === "done" ? "vsfx" : ""; } get id() { return this.data.id; } get name() { return this.data.name; } set name(value) { this.data.name = value; } get originalAssemblyId() { return this.data.originalAssemblyId; } get owner() { return this.data.owner; } get previewUrl() { return this.data.previewUrl || ""; } get relatedJobs() { return this.data.relatedJobs; } get status() { return this.data.status; } get type() { return "assembly"; } get version() { return this.data.version; } get versions() { return this.data.versions; } async checkout() { const response = await this.get(""); this.data = await response.json(); return this; } async update(data) { const response = await this.put("", data); this.data = await response.json(); return this; } delete() { return super.delete("").then((response) => response.json()); } save() { return this.update(this.data); } setPreview(image) { console.warn("Assembly does not support preview"); return Promise.resolve(this); } deletePreview() { console.warn("Assembly does not support preview"); return Promise.resolve(this); } getModels() { return this.get("/geometry") .then((response) => response.json()) .then((array) => array.map((data) => new Model(data, this))); } getModelTransformMatrix(handle) { return this.data.transform[handle]; } setModelTransformMatrix(handle, transform) { const obj = { ...this.data.transform }; obj[handle] = transform; return this.update({ transform: obj }); } getProperties(handles, group = false) { const searchParams = new URLSearchParams(); if (handles) { if (Array.isArray(handles)) handles = handles.join(","); if (typeof handles === "string") handles = handles.trim(); if (handles) searchParams.set("handles", handles); } if (group) searchParams.set("group", "true"); let queryString = searchParams.toString(); if (queryString) queryString = "?" + queryString; return this.get(`/properties${queryString}`).then((response) => response.json()); } searchProperties(searchPattern) { return this.post("/properties/search", searchPattern).then((response) => response.json()); } getCdaTree() { return this.get(`/properties/tree`).then((response) => response.json()); } getViewpoints() { return this.get("/viewpoints") .then((response) => response.json()) .then((viewpoints) => viewpoints.result); } saveViewpoint(viewpoint) { return this.post("/viewpoints", viewpoint).then((response) => response.json()); } deleteViewpoint(guid) { return super.delete(`/viewpoints/${guid}`).then((response) => response.json()); } getSnapshot(guid) { return this.get(`/viewpoints/${guid}/snapshot`).then((response) => response.text()); } getSnapshotData(guid, bitmapGuid) { return this.get(`/viewpoints/${guid}/bitmaps/${bitmapGuid}`).then((response) => response.text()); } downloadResource(dataId, onProgress, signal) { return this.httpClient .downloadFile(this.getEndpointPath(`/downloads/${dataId}`), onProgress, { signal, headers: this.headers }) .then((response) => response.arrayBuffer()); } downloadResourceRange(dataId, requestId, ranges, onProgress, signal) { return this.httpClient .downloadFileRange(this.getEndpointPath(`/downloads/${dataId}${requestId ? "?requestId=" + requestId : ""}`), requestId, ranges, onProgress, { signal, headers: this.headers }) .then((response) => response.arrayBuffer()); } async getReferences(signal) { const files = new Endpoint("/files", this.httpClient, this.headers); const references = await Promise.all(this.associatedFiles .map((file) => `/${file.fileId}/references`) .map((link) => files.get(link, signal).then((response) => response.json()))) .then((references) => references.map((x) => x.references)) .then((references) => references.reduce((x, v) => [...v, ...x], [])) .then((references) => [...new Set(references.map(JSON.stringify))].map((x) => JSON.parse(x))); return { id: "", references }; } waitForDone(params) { const checkDone = () => this.checkout().then((assembly) => { var _a; const ready = ["done", "failed"].includes(assembly.status); const cancel = (_a = params === null || params === void 0 ? void 0 : params.onCheckout) === null || _a === void 0 ? void 0 : _a.call(params, assembly, ready); return cancel || ready; }); return waitFor(checkDone, params).then(() => this); } getClashTests(start, limit, name, ids, sortByDesc, sortField) { 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) { ids = normalizeParam(ids); 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.get(`/clashes${queryString}`) .then((response) => response.json()) .then((tests) => { return { ...tests, result: tests.result.map((data) => new ClashTest(data, this.path, this.httpClient)), }; }); } getClashTest(testId) { return this.get(`/clashes/${testId}`) .then((response) => response.json()) .then((data) => new ClashTest(data, this.path, this.httpClient)); } createClashTest(name, selectionTypeA, selectionTypeB, selectionSetA, selectionSetB, params) { const { tolerance, clearance, waitForDone } = params !== null && params !== void 0 ? params : {}; if (!Array.isArray(selectionSetA)) selectionSetA = [selectionSetA]; if (!Array.isArray(selectionSetB)) selectionSetB = [selectionSetB]; return this.post("/clashes", { name, selectionTypeA, selectionTypeB, selectionSetA, selectionSetB, tolerance, clearance, }) .then((response) => response.json()) .then((data) => new ClashTest(data, this.path, this.httpClient)) .then((result) => (waitForDone ? result.waitForDone(params) : result)); } deleteClashTest(testId) { return super.delete(`/clashes/${testId}`).then((response) => response.json()); } updateVersion(files, params = { waitForDone: false, }) { return Promise.reject(new Error("Assembly version support will be implemented in a future release")); } getVersions() { return Promise.resolve(undefined); } getVersion(version) { return Promise.reject(new FetchError(404)); } deleteVersion(version) { return Promise.reject(new FetchError(404)); } setActiveVersion(version) { return this.update({ activeVersion: version }); } createSharedLink(permissions) { return Promise.reject(new Error("Assembly shared link will be implemented in a future release")); } getSharedLink() { return Promise.resolve(undefined); } deleteSharedLink() { return Promise.reject(new FetchError(404)); } } class EventEmitter2 { constructor() { this._listeners = {}; } addEventListener(type, listener) { if (this._listeners[type] === undefined) this._listeners[type] = []; this._listeners[type].push(listener); return this; } removeEventListener(type, listener) { if (this._listeners[type] === undefined) return this; const listeners = this._listeners[type].filter((x) => x !== listener); if (listeners.length !== 0) this._listeners[type] = listeners; else delete this._listeners[type]; return this; } removeAllListeners(type) { if (type) delete this._listeners[type]; else this._listeners = {}; return this; } emitEvent(event) { if (this._listeners[event.type] === undefined) return false; const invoke = this._listeners[event.type].slice(); invoke.forEach((listener) => listener.call(this, event)); return true; } on(type, listener) { return this.addEventListener(type, listener); } off(type, listener) { return this.removeEventListener(type, listener); } emit(type, ...args) { if (typeof type === "string") return this.emitEvent({ type, args }); else if (typeof type === "object") return this.emitEvent(type); else return false; } } function handleFetchError(response) { if (!response.ok) { switch (response.status) { case 400: { return response.text().then((text) => { console.error(text); return Promise.reject(new FetchError(400, error400(text))); }); } case 500: { return response.text().then((text) => { console.error(error400(text, text)); return Promise.reject(new FetchError(500)); }); } default: return Promise.reject(new FetchError(response.status)); } } return Promise.resolve(response); } function $fetch(url, init = { method: "GET" }) { const headers = { ...init.headers }; delete headers["Content-Type"]; Object.keys(headers) .filter((x) => headers[x] === undefined) .forEach((x) => delete headers[x]); let body = undefined; if (init.method === "POST" || init.method === "PUT") { if (init.body instanceof FormData) { body = init.body; } else if (init.body instanceof Blob) { body = new FormData(); body.append("file", init.body); } else if (init.body instanceof ArrayBuffer) { body = new FormData(); body.append("file", new Blob([init.body])); } else if (typeof init.body === "object") { body = JSON.stringify(init.body); headers["Content-Type"] = "application/json"; } else if (typeof init.body === "string") { body = init.body; headers["Content-Type"] = "text/plain"; } } return fetch(url, { ...init, headers, body }).then(handleFetchError); } function handleXMLHttpError(xhr) { if (xhr.status === 0) { return Promise.reject(new FetchError(0, "Network error")); } if (xhr.status < 200 || xhr.status > 299) { switch (xhr.status) { case 400: { console.error(xhr.responseText); return Promise.reject(new FetchError(400, error400(xhr.responseText))); } case 500: { console.error(error400(xhr.responseText, xhr.responseText)); return Promise.reject(new FetchError(500)); } default: { return Promise.reject(new FetchError(xhr.status)); } } } return Promise.resolve(xhr); } function $xmlhttp(url, params = { method: "GET" }) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open(params.method, url, true); for (const key in params.headers) { xhr.setRequestHeader(key, params.headers[key]); } function calcProgress(event) { return event.lengthComputable ? event.loaded / event.total : 1; } xhr.upload.onprogress = (event) => params.uploadProgress && params.uploadProgress(calcProgress(event)); xhr.onprogress = (event) => params.downloadProgress && params.downloadProgress(calcProgress(event)); xhr.onloadend = (event) => handleXMLHttpError(event.target).then(resolve, reject); xhr.send(params.body); }); } class HttpClient { constructor(serverUrl) { this.headers = {}; this.signInUserId = ""; this.signInUserIsAdmin = false; this.serverUrl = serverUrl; } get(relativePath, init = {}) { return $fetch(`${this.serverUrl}${relativePath}`, { ...init, method: "GET", headers: { ...this.headers, ...init.headers }, }); } post(relativePath, body, init = {}) { return $fetch(`${this.serverUrl}${relativePath}`, { ...init, method: "POST", headers: { ...this.headers, ...init.headers }, body, }); } put(relativePath, body, init = {}) { return $fetch(`${this.serverUrl}${relativePath}`, { ...init, method: "PUT", headers: { ...this.headers, ...init.headers }, body, }); } delete(relativePath, init = {}) { return $fetch(`${this.serverUrl}${relativePath}`, { ...init, method: "DELETE", headers: { ...this.headers, ...init.headers }, }); } uploadFile(relativePath, file, onProgress, init = {}) { const data = new FormData(); data.append("file", file); return $xmlhttp(`${this.serverUrl}${relativePath}`, { method: "POST", headers: { ...this.headers, ...init.headers }, body: data, uploadProgress: onProgress, }); } async downloadFile(relativePath, onProgress, init = {}) { const response = await this.get(relativePath, init); if (!onProgress) return response; const contentLength = response.headers.get("Content-Length"); const total = parseInt(contentLength || "", 10) || 1; const stream = new ReadableStream({ async start(controller) { const reader = response.body.getReader(); let loaded = 0; while (true) { const { done, value } = await reader.read(); if (done) break; controller.enqueue(value); loaded += value.length; onProgress(loaded / total, value); } controller.close(); }, }); return new Response(stream); } async downloadFileRange(relativePath, reserved, ranges, onProgress, init = {}) { const headers = { ...init.headers, Range: "bytes=" + ranges.map((x) => `${x.begin}-${x.end}`).join(","), }; const response = await this.get(relativePath, { ...init, headers }); if (!onProgress) return response; const contentLength = response.headers.get("content-length"); const total = parseInt(contentLength || "", 10) || 1; const stream = new ReadableStream({ async start(controller) { const reader = response.body.getReader(); let loaded = 0; let rangedIndex = 0; let rangePos = 0; while (true) { const { done, value } = await reader.read(); if (done) break; controller.enqueue(value); loaded += value.length; let chunkLeft = value.length; let chunkPos = 0; while (chunkLeft > 0) { const range = ranges[rangedIndex]; const rangeLeft = range.end - range.begin + 1 - rangePos; if (chunkLeft < rangeLeft) { const chunk = value.subarray(chunkPos, chunkPos + chunkLeft); onProgress(loaded / total, chunk, range.requestId); rangePos += chunkLeft; chunkLeft = 0; } else { const chunk = value.subarray(chunkPos, chunkPos + rangeLeft); onProgress(loaded / total, chunk, range.requestId); chunkPos += rangeLeft; chunkLeft -= rangeLeft; rangedIndex++; rangePos = 0; } } } controller.close(); }, }); return new Response(stream); } } class Permission extends Endpoint { constructor(data, fileId, httpClient) { super(`/files/${fileId}/permissions/${data.id}`, httpClient); this.data = data; } get actions() { return this.data.actions; } set actions(value) { this._data.actions = value; } get data() { return this._data; } set data(value) { this._data = value; } get id() { return this.data.id; } get grantedTo() { return this.data.grantedTo; } set grantedTo(value) { this.data.grantedTo = value; } get public() { return this.data.public; } set public(value) { this.data.public = value; } async checkout() { const response = await this.get(""); this.data = await response.json(); return this; } async update(data) { const response = await this.put("", data); this.data = await response.json(); return this; } delete() { return super.delete("").then((response) => response.json()); } save() { return this.update(this.data); } } class Job extends Endpoint { constructor(data, httpClient) { super(`/jobs/${data.id}`, httpClient); this.data = data; } get assemblyId() { return this.data.assemblyId; } get authorId() { return this.data.authorId; } get createdAt() { return this.data.createdAt; } get data() { return this._data; } set data(value) { this._data = value; } get done() { return this.data.status === "done" || this.data.status === "failed"; } get fileId() { return this.data.fileId; } get id() { return this.data.id; } get lastUpdate() { return this.data.lastUpdate; } get outputFormat() { return this.data.outputFormat; } get parameters() { return this.data.parameters; } get status() { return this.data.status; } get statusMessage() { return this.data.statusMessage; } get startedAt() { return this.data.startedAt; } async checkout() { const response = await this.get(""); this.data = await response.json(); return this; } async update(data) { const response = await this.put("", data); this.data = await response.json(); return this; } delete() { return super.delete("").then((response) => response.json()); } waitForDone(params) { const checkDone = () => this.checkout().then((job) => { var _a; const ready = ["done", "failed"].includes(job.status); const cancel = (_a = params === null || params === void 0 ? void 0 : params.onCheckout) === null || _a === void 0 ? void 0 : _a.call(params, job, ready); return cancel || ready; }); return waitFor(checkDone, params).then(() => this); } } class SharedLink extends Endpoint { constructor(data, httpClient) { super(`/shares/${data.token}`, httpClient); this.data = data; } get createdAt() { return this.data.createdAt; } get data() { return this._data; } set data(value) { this._data = value; } get permissions() { return this.data.permissions; } set permissions(value) { this.data.permissions = { ...this.data.permissions, ...value }; } get token() { return this.data.token; } get url() { return this.data.url; } async checkout() { const response = await this.get(""); this.data = await response.json(); return this; } async update(data) { const response = await this.put("", data); this.data = await response.json(); return this; } delete() { return super.delete("").then((response) => response.json()); } save() { return this.update(this.data); } } class File extends Endpoint { constructor(data, httpClient) { super(`/files/${data.id}`, httpClient); this.data = data; } get activeVersion() { return this.data.activeVersion; } get created() { return this.data.created; } get customFields() { return this.data.customFields; } set customFields(value) { this.data.customFields = value; } get data() { return this._data; } set data(value) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o; var _p, _q, _r, _s, _t, _u, _v, _w, _x, _y; this._data = value; this._data.previewUrl = value.preview ? `${this.httpClient.serverUrl}${this.path}/preview?updated=${value.updatedAt}` : ""; if (typeof this._data.owner === "string") this._data.owner = { userId: this._data.owner }; (_a = (_p = this._data).owner) !== null && _a !== void 0 ? _a : (_p.owner = {}); this._data.owner.avatarUrl = `${this.httpClient.serverUrl}/users/${this._data.owner.userId}/avatar`; this._data.owner.fullName = userFullName(this._data.owner); this._data.owner.initials = userInitials(this._data.owner.fullName); (_b = (_q = this._data).status) !== null && _b !== void 0 ? _b : (_q.status = {}); (_c = (_r = this._data.status).geometry) !== null && _c !== void 0 ? _c : (_r.geometry = { state: (_d = this._data.geometryStatus) !== null && _d !== void 0 ? _d : "none" }); (_e = (_s = this._data.status).properties) !== null && _e !== void 0 ? _e : (_s.properties = { state: (_f = this._data.propertiesStatus) !== null && _f !== void 0 ? _f : "none" }); (_g = (_t = this._data.status).validation) !== null && _g !== void 0 ? _g : (_t.validation = { state: (_h = this._data.validationStatus) !== null && _h !== void 0 ? _h : "none" }); (_j = (_u = this._data).updatedBy) !== null && _j !== void 0 ? _j : (_u.updatedBy = {}); this._data.updatedBy.avatarUrl = `${this.httpClient.serverUrl}/users/${this._data.updatedBy.userId}/avatar`; this._data.updatedBy.fullName = userFullName(this._data.updatedBy); this._data.updatedBy.initials = userInitials(this._data.updatedBy.fullName); (_k = (_v = this._data).versions) !== null && _k !== void 0 ? _k : (_v.versions = [{ ...value }]); (_l = (_w = this._data.status).geometryGltf) !== null && _l !== void 0 ? _l : (_w.geometryGltf = { state: "none" }); (_m = (_x = this._data).isFileDeleted) !== null && _m !== void 0 ? _m : (_x.isFileDeleted = false); (_o = (_y = this._data).sharedLinkToken) !== null && _o !== void 0 ? _o : (_y.sharedLinkToken = null); } get exports() { return this.data.exports; } get geometryType() { if (this.status.geometryGltf.state === "done") return "gltf"; else if (this.status.geometry.state === "done") return "vsfx"; else return ""; } get id() { return this.data.id; } get isFileDeleted() { return this.data.isFileDeleted; } get name() { return this.data.name; } set name(value) { this.data.name = value; } get originalFileId() { return this.data.originalFileId; } get owner() { return this.data.owner; } get previewUrl() { return this.data.previewUrl; } get size() { return this.data.size; } get sizeTotal() { return this.data.sizeTotal; } get sharedLinkToken() { return this.data.sharedLinkToken; } get status() { return this.data.status; } get type() { return this.data.type; } get updatedAt() { return this.data.updatedAt; } get updatedBy() { return this.data.updatedBy; } get version() { return this.data.version; } get versions() { return this.data.versions; } async checkout() { const response = await this.get(""); this.data = await response.json(); return this; } async update(data) { const response = await this.put("", data); this.data = await response.json(); return this; } delete() { return super.delete("").then((response) => response.json()); } save() { return this.update(this.data); } async setPreview(image) { if (!image) { await this.deletePreview(); } else { const response = await this.post("/preview", image); this.data = await response.json(); } return this; } async deletePreview() { const response = await super.delete("/preview"); this.data = await response.json(); return this; } getModels() { return this.get("/geometry") .then((response) => response.json()) .then((array) => array.map((data) => new Model(data, this))); } getModelTransformMatrix(handle) { return undefined; } setModelTransformMatrix(handle, transform) { console.warn("File does not support model transformation"); return Promise.resolve(this); } getProperties(handles, group = false) { const searchParams = new URLSearchParams(); if (handles) { if (Array.isArray(handles)) handles = handles.join(","); if (typeof handles === "string") handles = handles.trim(); if (handles) searchParams.set("handles", handles); } if (group) searchParams.set("group", "true"); let queryString = searchParams.toString(); if (queryString) queryString = "?" + queryString; return this.get(`/properties${queryString}`).then((response) => response.json()); } searchProperties(searchPattern) { return this.post("/properties/search", searchPattern).then((response) => response.json()); } getCdaTree() { return this.get(`/properties/tree`).then((response) => response.json()); } getViewpoints() { return this.get("/viewpoints") .then((response) => response.json()) .then((viewpoints) => viewpoints.result); } saveViewpoint(viewpoint) { return this.post("/viewpoints", viewpoint).then((response) => response.json()); } deleteViewpoint(guid) { return super.delete(`/viewpoints/${guid}`).then((response) => response.json()); } getSnapshot(guid) { return this.get(`/viewpoints/${guid}/snapshot`).then((response) => response.text()); } getSnapshotData(guid, bitmapGuid) { return this.get(`/viewpoints/${guid}/bitmaps/${bitmapGuid}`).then((response) => response.text()); } download(onProgress, signal) { return this.httpClient .downloadFile(this.getEndpointPath("/downloads"), onProgress, { signal, headers: this.headers }) .then((response) => response.arrayBuffer()); } downloadResource(dataId, onProgress, signal) { return this.httpClient .downloadFile(this.getEndpointPath(`/downloads/${dataId}`), onProgress, { signal, headers: this.headers }) .then((response) => response.arrayBuffer()); } downloadResourceRange(dataId, requestId, ranges, onProgress, signal) { return this.httpClient .downloadFileRange(this.getEndpointPath(`/downloads/${dataId}${requestId ? "?requestId=" + requestId : ""}`), requestId, ranges, onProgress, { signal, headers: this.headers }) .then((response) => response.arrayBuffer()); } getReferences(signal) { return this.get("/references", signal).then((response) => response.json()); } setReferences(references) { return this.put("/references", references).then((response) => response.json()); } createJob(outputFormat, parameters) { const jobs = new Endpoint("/jobs", this.httpClient, this.headers); return jobs .post(this.appendVersionParam(""), { fileId: this.id, outputFormat, parameters: parseArgs(parameters), }) .then((response) => response.json()) .then((data) => new Job(data, this.httpClient)); } extractGeometry(type, parameters) { return this.createJob(type === "gltf" ? "geometryGltf" : "geometry", parameters); } extractProperties(parameters) { return this.createJob("properties", parameters); } validate(parameters) { return this.createJob("validation", parameters); } waitForDone(jobs, waitAll, params) { const waitJobs = Array.isArray(jobs) ? jobs : [jobs]; if (waitAll === undefined) waitAll = true; const checkDone = () => this.checkout().then((file) => { var _a; const readyJobs = waitJobs.filter((job) => { const jobStatus = file.status[job] || {}; return ["none", "done", "failed"].includes(jobStatus.state || "none"); }); const ready = waitAll ? readyJobs.length === waitJobs.length : readyJobs.length > 0; const cancel = (_a = params === null || params === void 0 ? void 0 : params.onCheckout) === null || _a === void 0 ? void 0 : _a.call(params, file, ready); return cancel || ready; }); return waitFor(checkDone, pa