@inweb/client
Version:
JavaScript REST API client for the Open Cloud Server
1,312 lines (1,297 loc) • 103 kB
JavaScript
///////////////////////////////////////////////////////////////////////////////
// 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