@inweb/client
Version:
JavaScript REST API client for the Open Cloud Server
1,456 lines (1,427 loc) • 86.2 kB
JavaScript
import { EventEmitter2 } from "@inweb/eventemitter2";
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: 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 = {}}) => 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);
}
partialDownloadResource(dataId, onProgress, signal) {
console.warn("Model.partialDownloadResource() has been deprecated since 25.3 and will be removed in a future release, use Model.downloadResource() instead.");
return this.downloadResource(dataId, onProgress, signal);
}
async downloadFileRange(requestId, records, dataId, onProgress, signal) {
if (!records) return;
let ranges = [];
if (records.length) {
ranges = records.map((record => ({
begin: Number(record.begin),
end: Number(record.end),
requestId: record.reqId
})));
} else {
for (let i = 0; i < records.size(); i++) {
const record = records.get(i);
ranges.push({
begin: Number(record.begin),
end: Number(record.end),
requestId: requestId
});
record.delete();
}
}
await this.downloadResourceRange(dataId, requestId, ranges, onProgress, signal);
}
getReferences(signal) {
return this._file.getReferences(signal);
}
}
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);
signal.addEventListener("abort", abortHandler, {
once: true
});
}));
}
async function waitFor(func, params = {}) {
var _a, _b, _c;
const timeout = params.timeout || 6e5;
const interval = params.interval || 3e3;
const signal = (_a = params.signal) !== null && _a !== undefined ? _a : (new AbortController).signal;
const abortError = (_b = params.abortError) !== null && _b !== undefined ? _b : new DOMException("Aborted", "AbortError");
const timeoutError = (_c = params.timeoutError) !== null && _c !== undefined ? _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 !== undefined ? _a : firstName.name, firstName.lastName, firstName.userName);
}
return `${firstName !== null && firstName !== undefined ? firstName : ""} ${lastName !== null && lastName !== undefined ? 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 === undefined ? undefined : params.onCheckout) === null || _a === undefined ? undefined : _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 !== undefined ? _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) {
const relativePath = handles !== undefined ? `/properties?handles=${handles}` : "/properties";
return this.get(relativePath).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: 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, ranges, onProgress, {
signal: signal,
headers: this.headers
}).then((response => response.arrayBuffer()));
}
partialDownloadResource(dataId, onProgress, signal) {
console.warn("Assembly.partialDownloadResource() has been deprecated since 25.3 and will be removed in a future release, use Assembly.downloadResource() instead.");
return this.downloadResource(dataId, onProgress, signal);
}
async downloadFileRange(requestId, records, dataId, onProgress, signal) {
await this.downloadResourceRange(dataId, requestId, records, onProgress, signal);
}
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: references
};
}
waitForDone(params) {
const checkDone = () => this.checkout().then((assembly => {
var _a;
const ready = [ "done", "failed" ].includes(assembly.status);
const cancel = (_a = params === null || params === undefined ? undefined : params.onCheckout) === null || _a === undefined ? undefined : _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) {
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.get(`/clashes${queryString}`).then((response => response.json())).then((tests => ({
...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: tolerance, clearance: clearance, waitForDone: waitForDone} = params !== null && params !== undefined ? params : {};
if (!Array.isArray(selectionSetA)) selectionSetA = [ selectionSetA ];
if (!Array.isArray(selectionSetB)) selectionSetB = [ selectionSetB ];
return this.post("/clashes", {
name: name,
selectionTypeA: selectionTypeA,
selectionTypeB: selectionTypeB,
selectionSetA: selectionSetA,
selectionSetB: selectionSetB,
tolerance: tolerance,
clearance: 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 implemeted 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 implemeted in a future release"));
}
getSharedLink() {
return Promise.resolve(undefined);
}
deleteSharedLink() {
return Promise.reject(new FetchError(404));
}
}
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: headers,
body: 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: body
});
}
put(relativePath, body, init = {}) {
return $fetch(`${this.serverUrl}${relativePath}`, {
...init,
method: "PUT",
headers: {
...this.headers,
...init.headers
},
body: 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);
const contentLength = response.headers.get("Content-Length");
const total = parseInt(contentLength || "", 10) || 1;
return new Response(new ReadableStream({
async start(controller) {
const reader = response.body.getReader();
let loaded = 0;
while (true) {
const {done: done, value: value} = await reader.read();
if (done) break;
controller.enqueue(value);
loaded += value.length;
if (onProgress) onProgress(loaded / total, value);
}
controller.close();
}
}));
}
async downloadFileRange(relativePath, reserved, ranges, onProgress, init = {}) {
const headers = {
...init.headers
};
headers["Range"] = "bytes=" + ranges.map((x => `${x.begin}-${x.end}`)).join(",");
const response = await this.get(relativePath, {
...init,
headers: headers
});
const contentLength = response.headers.get("content-length");
const total = parseInt(contentLength || "", 10) || 1;
return new Response(new ReadableStream({
async start(controller) {
const reader = response.body.getReader();
let loaded = 0;
let rangedIndex = 0;
let rangePos = 0;
while (true) {
const {done: done, value: 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 - rangePos;
if (chunkLeft < rangeLeft) {
const chunk = value.subarray(chunkPos, chunkPos + chunkLeft);
if (onProgress) onProgress(loaded / total, chunk, range.requestId);
rangePos += chunkLeft;
chunkLeft = 0;
} else {
const chunk = value.subarray(chunkPos, chunkPos + rangeLeft);
if (onProgress) onProgress(loaded / total, chunk, range.requestId);
chunkPos += rangeLeft;
chunkLeft -= rangeLeft;
rangedIndex++;
rangePos = 0;
}
}
}
controller.close();
}
}));
}
}
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 === undefined ? undefined : params.onCheckout) === null || _a === undefined ? undefined : _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 !== undefined ? _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 !== undefined ? _b : _q.status = {};
(_c = (_r = this._data.status).geometry) !== null && _c !== undefined ? _c : _r.geometry = {
state: (_d = this._data.geometryStatus) !== null && _d !== undefined ? _d : "none"
};
(_e = (_s = this._data.status).properties) !== null && _e !== undefined ? _e : _s.properties = {
state: (_f = this._data.propertiesStatus) !== null && _f !== undefined ? _f : "none"
};
(_g = (_t = this._data.status).validation) !== null && _g !== undefined ? _g : _t.validation = {
state: (_h = this._data.validationStatus) !== null && _h !== undefined ? _h : "none"
};
(_j = (_u = this._data).updatedBy) !== null && _j !== undefined ? _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 !== undefined ? _k : _v.versions = [ {
...value
} ];
(_l = (_w = this._data.status).geometryGltf) !== null && _l !== undefined ? _l : _w.geometryGltf = {
state: "none"
};
(_m = (_x = this._data).isFileDeleted) !== null && _m !== undefined ? _m : _x.isFileDeleted = false;
(_o = (_y = this._data).sharedLinkToken) !== null && _o !== undefined ? _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) {
const relativePath = handles !== undefined ? `/properties?handles=${handles}` : "/properties";
return this.get(relativePath).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: signal,
headers: this.headers
}).then((response => response.arrayBuffer()));
}
downloadResource(dataId, onProgress, signal) {
return this.httpClient.downloadFile(this.getEndpointPath(`/downloads/${dataId}`), onProgress, {
signal: 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, ranges, onProgress, {
signal: signal,
headers: this.headers
}).then((response => response.arrayBuffer()));
}
partialDownloadResource(dataId, onProgress, signal) {
console.warn("File.partialDownloadResource() has been deprecated since 25.3 and will be removed in a future release, use File.downloadResource() instead.");
return this.downloadResource(dataId, onProgress, signal);
}
async downloadFileRange(requestId, records, dataId, onProgress, signal) {
await this.downloadResourceRange(dataId, requestId, records, onProgress, signal);
}
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: 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 === undefined ? undefined : params.onCheckout) === null || _a === undefined ? undefined : _a.call(params, file, ready);
return cancel || ready;
}));
return waitFor(checkDone, params).then((() => this));
}
getPermissions() {
return this.get("/permissions").then((response => response.json())).then((array => array.map((data => new Permission(data, this.id, this.httpClient)))));
}
getPermission(permissionId) {
return this.get(`/permissions/${permissionId}`).then((response => response.json())).then((data => new Permission(data, this.id, this.httpClient)));
}
createPermission(actions, grantedTo, _public) {
return this.post("/permissions", {
actions: Array.isArray(actions) ? actions : [ actions ],
grantedTo: grantedTo,
public: _public
}).then((response => response.json())).then((data => new Permission(data, this.id, this.httpClient)));
}
deletePermission(permissionId) {
return super.delete(`/permissions/${permissionId}`).then((response => response.json()));
}
async uploadVersion(file, params = {
waitForDone: false
}) {
const result = await this.httpClient.uploadFile(this.getEndpointPath("/versions"), file, (progress => {
var _a;
return (_a = params.onProgress) === null || _a === undefined ? undefined : _a.call(params, progress, file);
}), {
headers: this.headers
}).then((xhr => JSON.parse(xhr.responseText))).then((data => new File(data, this.httpClient)));
let geometryType = "";
if (this.versions[0].status.geometryGltf.state !== "none") geometryType = "gltf";
if (this.versions[0].status.geometry.state !== "none") geometryType = "vsfx";
params = {
...params
};
if (params.geometry === undefined) params.geometry = geometryType !== "";
if (params.properties === undefined) params.properties = this.versions[0].status.properties.state !== "none";
const jobs = [];
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();
await this.checkout();
return result;
}
getVersions() {
return this.get("/versions").then((response => response.json())).then((files => files.map((data => new File(data, this.httpClient))))).then((files => files.map((file => file.id == file.originalFileId ? file.useVersion(0) : file))));
}
getVersion(version) {
return this.get(`/versions/${version}`).then((response => response.json())).then((data => new File(data, this.httpClient))).then((file => file.id == file.originalFileId ? file.useVersion(0) : file));
}
async deleteVersion(version) {
const response = await super.delete(`/versions/${version}`);
const data = await response.json();
await this.checkout();
return data;
}
setActiveVersion(version) {
return this.update({
activeVersion: version
});
}
useVersion(version) {
return super.useVersion(version);
}
async deleteSource() {
const response = await super.delete("/source");
this.data = await response.json();
return this;
}
async createSharedLink(permissions) {
const shares = new Endpoint("/shares", this.httpClient, this.headers);
const response = await shares.post("", {
fileId: this.id,
permissions: permissions
});
const data = await response.json();
await this.checkout();
return new SharedLink(data, this.httpClient);
}
async getSharedLink() {
if (!this.sharedLinkToken) return Promise.resolve(undefined);
const shares = new Endpoint("/shares", this.httpClient, this.headers);
const response = await shares.get(`/${this.sharedLinkToken}`);
const data = await response.json();
return new SharedLink(data, this.httpClient);
}
async deleteSharedLink() {
const shares = new Endpoint("/shares", this.httpClient, this.headers);
const response = await shares.delete(`/${this.sharedLinkToken}`);
const data = await response.json();
await this.checkout();
return data;
}
}
class Role extends Endpoint {
constructor(data, projectId, httpClient) {
super("", httpClient);
this.projectId = projectId;
this.data = data;
}
get description() {
return this.data.description;
}
set description(value) {
this._data.description = value;
}
get data() {
return this._data;
}
set data(value) {
this._data = value;
this.path = `/projects/${this.projectId}/roles/${value.name}`;
}
get name() {
return this.data.name;
}
set name(value) {
this._data.name = value;
}
get permissions() {
return this.data.permissions;
}
set permissions(value) {
this.data.permissions = 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 Member extends Endpoint {
constructor(data, projectId, httpClient) {
super(`/projects/${projectId}/members/${data.id}`, httpClient);
this.data = data;
}
get data() {
return this._data;
}
set data(value) {
this._data = value;
this._data.user.avatarUrl = `${this.httpClient.serverUrl}/users/${this._data.user.userId}/avatar`;
this._data.user.fullName = userFullName(this._data.user);
this._data.user.initials = userInitials(this._data.user.fullName);
}
get id() {
return this.data.id;
}
get role() {
return this.data.role;
}
set role(value) {
this.data.role = value;
}
get type() {
return this.data.type;
}
get user() {
return this.data.user;
}
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 Project extends Endpoint {
constructor(data, httpClient) {
super(`/projects/${data.id}`, httpClient);
this.data = data;
}
get authorization() {
return this.data.authorization;
}
get createdAt() {
return this.data.createdAt;
}
get customFields() {
return this.data.custom