UNPKG

@inweb/client

Version:

JavaScript REST API client for the Open Cloud Server

2,609 lines 90.3 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.
///////////////////////////////////////////////////////////////////////////////

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, 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) {
        var _a, _b;
        this._data = value;
        this._data.owner.fullName = userFullName(this._data.owner);
        this._data.owner.initials = userInitials(this._data.owner.fullName);
        (_a = this._data.owner).avatarUrl || (_a.avatarUrl = "");
        (_b = this._data.owner).lastModified || (_b.lastModified = "");
    }
    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, _c, _d;
        this._data = value;
        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 = []);
        (_c = this._data.owner).avatarUrl || (_c.avatarUrl = "");
        (_d = this._data.owner).lastModified || (_d.lastModified = "");
    }
    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 updatedAt() {
        return this.data.updatedAt || "";
    }
    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((files) => files.flatMap((file) => file.references))
            .then((references) => [...new Set(references.map((x) => JSON.stringify(x)))])
            .then((dedupedRefs) => dedupedRefs.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 && start > 0)
            searchParams.set("start", start.toString());
        if (limit && 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 ? [selectionSetA] : [];
        if (!Array.isArray(selectionSetB))
            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));
    }
}

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 = new Headers(init.headers);
    headers.delete("Content-Type");
    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.set("Content-Type", "application/json");
        }
        else if (typeof init.body === "string") {
            body = init.body;
            headers.set("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);
        const headers = new Headers(params.headers);
        headers.forEach((value, name) => {
            xhr.setRequestHeader(name, value);
        });
        const 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 body = response.body;
        if (!body)
            return response;
        const contentLength = response.headers.get("X-File-Size") || response.headers.get("Content-Length");
        const total = parseInt(contentLength || "", 10) || 1;
        const stream = new ReadableStream({
            async start(controller) {
                const reader = 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 body = response.body;
        if (!body)
            return response;
        const contentLength = response.headers.get("X-File-Size") || response.headers.get("Content-Length");
        const total = parseInt(contentLength || "", 10) || 1;
        const stream = new ReadableStream({
            async start(controller) {
                const reader = 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, _z, _0, _1, _2;
        this._data = value;
        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.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.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);
        (_z = this._data.owner).avatarUrl || (_z.avatarUrl = "");
        (_0 = this._data.owner).lastModified || (_0.lastModified = "");
        (_1 = this._data.updatedBy).avatarUrl || (_1.avatarUrl = "");
        (_2 = this._data.updatedBy).lastModified || (_2.lastModified = "");
    }
    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.preview || "";
    }
    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] || { state: "" };
                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, 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 = false) {
        return this.post("/permissions", {
            actions: Array.isArray(actions) ? actions : [actions],
            grantedTo: Array.isArray(grantedTo) ? 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 === void 0 ? void 0 : _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 });
        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) {
        var _a, _b;
        this._data = value;
        this._data.user.fullName = userFullName(this._data.user);
        this._data.user.initials = userInitials(this._data.user.fullName);
        (_a = this._data.user).avatarUrl || (_a.avatarUrl = "");
        (_b = this._data.user).lastModified || (_b.lastModified = "");
    }
    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.customFields;
    }
    set customFields(value) {
        this.data.customFields = value;
    }
    get data() {
        return this._data;
    }
    set data(value) {
        var _a, _b;
        this._data = value;
        this._data.owner.fullName = userFullName(this._data.owner);
        this._data.owner.initials = userInitials(this._data.owner.fullName);
        (_a = this._data.owner).avatarUrl || (_a.avatarUrl = "");
        (_b = this._data.owner).lastModified || (_b.lastModified = "");
    }
    get description() {
        return this.data.description;
    }
    set description(value) {
        this.data.description = value;
    }
    get endDate() {
        return this.data.endDate;
    }
    set endDate(value) {
        this.data.endDate = value instanceof Date ? value.toISOString() : value;
    }
    get id() {
        return this.data.id;
    }
    get memberCount() {
        return this.data.memberCount;
    }
    get modelCount() {
        return this.data.modelCount;
    }
    get name() {
        return this.data.name;
    }
    set name(value) {
        this.data.name = value;
    }
    get owner() {
        return this.data.owner;
    }
    get previewUrl() {
        return this._data.avatarUrl || "";
    }
    get public() {
        return this.data.public;
    }
    set public(value) {
        this.data.public = value;
    }
    get startDate() {
        return this.data.startDate;
    }
    set startDate(value) {
        this.data.startDate = value instanceof Date ? value.toISOString() : value;
    }
    get topicCount() {
        return this.data.topicCount;
    }
    get updatedAt() {
        return this.data.updatedAt;
    }
    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.text())
            .then((text) => {
            try {
                return JSON.parse(text);
            }
            catch {
                return { id: this.id };
            }
        });
    }
    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;
    }
    getRoles() {
        return this.get("/roles")
            .then((response) => response.json())
            .then((array) => array.map((data) => new Role(data, this.id, this.httpClient)));
    }
    getRole(name) {
        return this.get(`/roles/${name}`)
            .then((response) => response.json())
            .then((data) => new Role(data, this.id, this.httpClient));
    }
    createRole(name, description, permissions) {
        return this.post("/roles", {
            name,
            description,
            permissions: permissions || {},
        })
            .then((response) => response.json())
            .then((data) => new Role(data, this.id, this.httpClient));
    }
    deleteRole(name) {
        return super.delete(`/roles/${name}`).then((response) => response.json());
    }
    getMembers() {
        return this.get("/members")
            .then((response) => response.json())
            .then((array) => array.map((data) => new Member(data, this.id, this.httpClient)));
    }
    getMember(memberId) {
        return this.get(`/members/${memberId}`)
            .then((response) => response.json())
            .then((data) => new Member(data, this.id, this.httpClient));
    }
    addMember(userId, role) {
        return this.post("/members", { userId, role })
            .then((response) => response.json())
            .then((data) => new Member(data, this.id, this.httpClient));
    }
    removeMember(memberId) {
        return super.delete(`/members/${memberId}`).then((response) => response.json());
    }
    getFilesInformation() {
        const bcfProjects = new Endpoint("/bcf/3.0/projects", this.httpClient, this.headers);
        return bcfProjects
            .get(`/${this.id}/files_information`)
            .then((response) => response.json())
            .then((items) => {
            items.forEach((item) => {
                const getFieldValue = (displayName) => {
                    return (item.display_information.find((x) => x.field_display_name === displayName) || {}).field_value;
                };
                const ownerFirstName = getFieldValue("Owner First Name");
                const ownerLastName = getFieldValue("Owner Last Name");
                const ownerUserName = getFieldValue("Owner User Name");
                const ownerFullName = userFullName(ownerFirstName, ownerLastName, ownerUserName);
                const ownerInitials = userInitials(ownerFullName);
                item.display_information.push({ field_display_name: "Owner Full Name", field_value: ownerFullName });
                item.display_information.push({ field_display_name: "Owner Initials", field_value: ownerInitials });
                const updatedByFirstName = getFieldValue("Updated By First Name");
                const updatedByLastName = getFieldValue("Updated By Last Name");
                const updatedByUserName = getFieldValue("Updated By User Name");
                const updatedByFullName = userFullName(updatedByFirstName, updatedByLastName, updatedByUserName);
                const updatedByInitials = userInitials(updatedByFullName);
                item.display_information.push({ field_display_name: "Updated By Full Name", field_value: updatedByFullName });
                item.display_information.push({ field_display_name: "Updated By Initials", field_value: updatedByInitials });
                const geometry = getFieldValue("Geometry Status");
                const geometryGltf = getFieldValue("GeometryGltf Status");
                const geometryType = geometry === "done" ? "vsfx" : geometryGltf === "done" ? "gltf" : "";
                item.display_information.push({ field_display_name: "Geometry Type", field_value: geometryType });
                if (getFieldValue("Preview URL") === undefined)
                    item.display_information.push({ field_display_name: "Preview URL", field_value: "" });
                if (getFieldValue("Owner Avatar URL") === undefined)
                    item.display_information.push({ field_display_name: "Owner Avatar URL", field_value: "" });
                if (getFieldValue("Owner Last Modified") === undefined)
                    item.display_information.push({ field_display_name: "Owner Last Modified", field_value: "" });
                if (getFieldValue("Updated By Avatar URL") === undefined)
                    item.display_information.push({ field_display_name: "Updated By Avatar URL", field_value: "" });
                if (getFieldValue("Updated By Last Modified") === undefined)
                    item.display_information.push({ field_display_name: "Updated By Last Modified", field_value: "" });
            });
            return items;
        });
    }
    getModels() {
        return this.getFilesInformation()
            .then((filesInformation) => filesInformation.map((item) => item.file.reference))
            .then((ids) => {
            const files = new Endpoint("/files", this.httpClient, this.headers);
            return files.get(`?id=${normalizeParam(ids)}`);
        })
            .then((response) => response.json())
            .then((files) => files.result.map((data) => new File(data, this.httpClient)));
    }
    async addModel(fileId, actions) {
        const files = new Endpoint("/files", this.httpClient, this.headers);
        const file = await files
            .get(`/${fileId}`)
            .then((response) => response.json())
            .then((data) => new File(data, this.httpClient));
        const grantedTo = [{ project: { id: this.id, name: this.name } }];
        await file.createPermission(actions, grantedTo);
        return file;
    }
    async removeModel(fileId) {
        const files = new Endpoint("/files", this.httpClient, this.headers);
        const file = await files
            .get(`/${fileId}`)
            .then((response) => response.json())
            .then((data) => new File(data, this.httpClient));
        const permissions = await file.getPermissions();
        await Promise.allSettled(permissions
            .filter((permission) => permission.grantedTo.some((x) => { var _a; return ((_a = x.project) === null || _a === void 0 ? void 0 : _a.id) === this.id; }))
            .map((permission) => permission.delete()));
        return file;
    }
}

class User extends Endpoint {
    constructor(data, httpClient) {
        super("", httpClient);
        this.data = data;
    }
    get avatarUrl() {
        return this._data.avatarImage || "";
    }
    get canCreateProject() {
        return this.data.canCreateProject;
    }
    set canCreateProject(value) {
        this._data.canCreateProject = value;
    }
    get createAt() {
        return this.data.createAt;
    }
    get customFields() {
        return this.data.customFields;
    }
    set customFields(value) {
        this._data.customFields = value;
    }
    get data() {
        return this._data;
    }
    set data(value) {
        this._data = value;
        this._data.fullName = userFullName(this._data);
        this._data.initials = userInitials(this._data.fullName);
    }
    get email() {
        return this.data.email;
    }
    set email(value) {
        this._data.email = value;
    }
    get emailConfirmationId() {
        return this.data.emailConfirmationId;
    }
    get firstName() {
        return this.data.firstName;
    }
    set firstName(value) {
        this._data.firstName = value;
    }
    get fullName() {
        return this.data.fullName;
    }
    get id() {
        return this.data.id;
    }
    get initials() {
        return this.data.initials;
    }
    get isAdmin() {
        return this.data.isAdmin;
    }
    set isAdmin(value) {
        this._data.isAdmin = value;
    }
    get isEmailConfirmed() {
        return this.data.isEmailConfirmed;
    }
    get lastModified() {
        return this.data.lastModified;
    }
    get lastName() {
        return this.data.lastName;
    }
    set lastName(value) {
        this._data.lastName = value;
    }
    get lastSignIn() {
        return this.data.lastSignIn;
    }
    get projectsLimit() {
        return this.data.projectsLimit;
    }
    set projectsLimit(value) {
        this._data.projectsLimit = value;
    }
    get providerType() {
        return this.data.providerType;
    }
    get storageLimit() {
        return this.data.storageLimit;
    }
    set storageLimit(value) {
        this._data.storageLimit = value;
    }
    get storageUsed() {
        return this.data.storageUsed;
    }
    get token() {
        return this.data.tokenInfo.token;
    }
    get userName() {
        return this.data.userName;
    }
    set userName(value) {
        this._data.userName = value;
    }
    async checkout() {
        if (this.httpClient.signInUserIsAdmin) {
            const response = await this.get(`/users/${this.id}`);
            const data = await response.json();
            this.data = { id: data.id, ...data.userBrief };
        }
        else if (this.id === this.httpClient.signInUserId) {
            const response = await this.get("/user");
            const data = await response.json();
            this.data = { id: this.id, ...data };
        }
        else {
            return Promise.reject(new FetchError(403));
        }
        return this;
    }
    async update(data) {
        if (this.httpClient.signInUserIsAdmin) {
            const response = await this.put(`/users/${this.id}`, { isAdmin: data.isAdmin, userBrief: data });
            const newData = await response.json();
            this.data = { id: newData.id, ...newData.userBrief };
        }
        else if (this.id === this.httpClient.signInUserId) {
            const response = await this.put("/user", data);
            const newData = await response.json();
            this.data = { id: this.id, ...newData };
        }
        else {
            return Promise.reject(new FetchError(403));
        }
        return this;
    }
    delete() {
        if (this.httpClient.signInUserIsAdmin) {
            return super
                .delete(`/users/${this.id}`)
                .then((response) => response.json())
                .then((data) => {
                if (this.id === this.httpClient.signInUserId) {
                    delete this.httpClient.headers["Authorization"];
                    this.httpClient.signInUserId = "";
                    this.httpClient.signInUserIsAdmin = false;
                }
                return data;
            });
        }
        else {
            return Promise.reject(new FetchError(403));
        }
    }
    save() {
        return this.update(this.data);
    }
    async setAvatar(image) {
        if (!image) {
            await this.deleteAvatar();
        }
        else if (this.httpClient.signInUserIsAdmin) {
            const response = await this.post(`/users/${this.id}/avatar`, image);
            const data = await response.json();
            this.data = { id: data.id, ...data.userBrief };
        }
        else if (this.id === this.httpClient.signInUserId) {
            const response = await this.post("/user/avatar", image);
            const data = await response.json();
            this.data = { id: this.id, ...data };
        }
        else {
            return Promise.reject(new FetchError(403));
        }
        return this;
    }
    async deleteAvatar() {
        if (this.httpClient.signInUserIsAdmin) {
            const response = await super.delete(`/users/${this.id}/avatar`);
            const data = await response.json();
            this.data = { id: data.id, ...data.userBrief };
        }
        else if (this.id === this.httpClient.signInUserId) {
            const response = await super.delete("/user/avatar");
            const data = await response.json();
            this.data = { id: this.id, ...data };
        }
        else {
            return Promise.reject(new FetchError(403));
        }
        return this;
    }
    async changePassword(newPassword, oldPassword) {
        if (this.httpClient.signInUserIsAdmin) {
            const response = await this.put(`/users/${this.id}/password`, { new: newPassword });
            const data = await response.json();
            this.data = { id: data.id, ...data.userBrief };
        }
        else if (this.id === this.httpClient.signInUserId) {
            const response = await this.put("/user/password", { old: oldPassword, new: newPassword });
            const data = await response.json();
            this.data = { id: this.id, ...data };
        }
        else {
            return Promise.reject(new FetchError(403));
        }
        return this;
    }
}

class OAuthClient extends Endpoint {
    constructor(data, httpClient) {
        super(`/oauth/clients/${data.clientId}`, httpClient);
        this.data = data;
    }
    get authUrl() {
        return this.data.authUrl;
    }
    get accessTokenUrl() {
        return this.data.accessTokenUrl;
    }
    get clientId() {
        return this.data.clientId;
    }
    get createdAt() {
        return this.data.createdAt;
    }
    get description() {
        return this.data.description;
    }
    set description(value) {
        this._data.description = value;
    }
    get data() {
        return this._data;
    }
    set data(value) {
        this._data = value;
    }
    get name() {
        return this.data.name;
    }
    set name(value) {
        this._data.name = value;
    }
    get redirectUrl() {
        return this.data.redirectUrl;
    }
    set redirectUrl(value) {
        this.data.redirectUrl = value;
    }
    get secret() {
        return this.data.secret;
    }
    get updatedAt() {
        return this.data.updatedAt;
    }
    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 revoke() {
        await this.post("/revoke");
        return this;
    }
}

class SharedFile extends File {
    constructor(data, password, httpClient) {
        super(data.file, httpClient);
        this.path = `/shares/${data.file.sharedLinkToken}`;
        this.headers = { "InWeb-Password": password };
    }
    async checkout() {
        const response = await this.get("/info");
        const data = await response.json();
        this.data = data.file;
        return this;
    }
    async update(data) {
        const response = await this.put("/info", data);
        this.data = await response.json();
        return this;
    }
    getVersions() {
        return Promise.resolve(undefined);
    }
    useVersion(version) {
        return this;
    }
}

class Plugin extends Endpoint {
    constructor(data, httpClient) {
        super(`/plugins/${data.name}/${data.version}`, httpClient);
        this.data = data;
    }
    get author() {
        return this.data.author;
    }
    get data() {
        return this._data;
    }
    set data(value) {
        this._data = value;
    }
    get description() {
        return this.data.description;
    }
    get enabled() {
        return this.data.enabled;
    }
    get homepage() {
        return this.data.homepage;
    }
    get id() {
        return this.data.id;
    }
    get license() {
        return this.data.license;
    }
    get name() {
        return this.data.name;
    }
    get permissions() {
        return this.data.permissions;
    }
    get pluginType() {
        return this.data.pluginType;
    }
    get version() {
        return this.data.version;
    }
    async checkout() {
        const response = await this.get("");
        this.data = await response.json();
        return this;
    }
    delete() {
        return super.delete("").then((response) => response.json());
    }
    async enable() {
        const response = await this.put("/enable");
        this.data = await response.json();
        return this;
    }
    async disable() {
        const response = await this.put("/disable");
        this.data = await response.json();
        return this;
    }
    download(onProgress, signal) {
        return this.httpClient
            .downloadFile(this.getEndpointPath("/download"), onProgress, { signal, headers: this.headers })
            .then((response) => response.arrayBuffer());
    }
    getManifest() {
        return this.get("/manifest").then((response) => response.json());
    }
    getSettings() {
        return this.get("/settings").then((response) => response.json());
    }
    updateSettings(settings) {
        return this.post("/settings", settings).then((response) => response.json());
    }
    executeCommand(command, parameters) {
        const commands = new Endpoint(`/plugins/${this.name}/commands`, this.httpClient, this.headers);
        return commands.post(`/${command}?version=${this.version}`, parameters).then((response) => response.json());
    }
}

class Client extends EventEmitter2 {
    constructor(params = {}) {
        super();
        this._serverUrl = "";
        this._httpClient = new HttpClient("");
        this._user = null;
        this.eventEmitter = this;
        this.configure(params);
    }
    get serverUrl() {
        return this._serverUrl;
    }
    get httpClient() {
        return this._httpClient;
    }
    configure(params) {
        this._serverUrl = (params.serverUrl || "").replace(/\/+$/, "");
        this._httpClient.serverUrl = this.serverUrl;
        this.clearCurrentUser();
        return this;
    }
    version() {
        return this.httpClient
            .get("/version")
            .then((response) => response.json())
            .then((data) => ({
            ...data,
            server: data.version,
            client: "27.8.1",
        }));
    }
    registerUser(email, password, userName) {
        return this.httpClient
            .post("/register", {
            email,
            password,
            userName: userName !== null && userName !== void 0 ? userName : (email + "").split("@").shift(),
        })
            .then((response) => response.json());
    }
    resendConfirmationEmail(email, password) {
        return this.httpClient
            .post("/register/email-confirmation", { email, password })
            .then((response) => response.json());
    }
    confirmUserEmail(emailConfirmationId) {
        return this.httpClient
            .get(`/register/email-confirmation/${emailConfirmationId}`)
            .then((response) => response.json());
    }
    async signInWithEmail(email, password) {
        const credentials = btoa(unescape(encodeURIComponent(email + ":" + password)));
        this.httpClient.headers["Authorization"] = "Basic " + credentials;
        const response = await this.httpClient.get("/token");
        const data = await response.json();
        return this.setCurrentUser(data);
    }
    async signInWithToken(token) {
        this.httpClient.headers["Authorization"] = token;
        const response = await this.httpClient.get("/user");
        const data = await response.json();
        return this.setCurrentUser(data);
    }
    signOut() {
        this.clearCurrentUser();
    }
    setCurrentUser(data) {
        this._user = new User(data, this.httpClient);
        this.httpClient.headers["Authorization"] = data.tokenInfo.token;
        this.httpClient.signInUserId = this._user.id;
        this.httpClient.signInUserIsAdmin = this._user.isAdmin;
        return this._user;
    }
    clearCurrentUser() {
        this._user = null;
        delete this.httpClient.headers["Authorization"];
        this.httpClient.signInUserId = "";
        this.httpClient.signInUserIsAdmin = false;
    }
    getCurrentUser() {
        if (this._user && !this.httpClient.signInUserId)
            this._user = null;
        return this._user;
    }
    getIdentityProviders() {
        return this.httpClient.get("/identity").then((response) => response.json());
    }
    getServerSettings() {
        return this.httpClient.get("/settings").then((response) => response.json());
    }
    updateServerSettings(settings) {
        return this.httpClient.put("/settings", settings).then((response) => response.json());
    }
    getOAuthClients(start, limit) {
        const searchParams = new URLSearchParams();
        if (start && start > 0)
            searchParams.set("start", start.toString());
        if (limit && limit > 0)
            searchParams.set("limit", limit.toString());
        let queryString = searchParams.toString();
        if (queryString)
            queryString = "?" + queryString;
        return this.httpClient
            .get(`/oauth/clients${queryString}`)
            .then((response) => response.json())
            .then((clients) => {
            return {
                ...clients,
                result: clients.result.map((data) => new OAuthClient(data, this.httpClient)),
            };
        });
    }
    getOAuthClient(clientId) {
        return this.httpClient
            .get(`/oauth/clients/${clientId}`)
            .then((response) => response.json())
            .then((data) => new OAuthClient(data, this.httpClient));
    }
    createOAuthClient(name, redirectUrl, description) {
        return this.httpClient
            .post("/oauth/clients", {
            name,
            redirectUrl,
            description,
        })
            .then((response) => response.json())
            .then((data) => new OAuthClient(data, this.httpClient));
    }
    deleteOAuthClient(clientId) {
        return this.httpClient.delete(`/oauth/clients/${clientId}`).then((response) => response.json());
    }
    getUsers() {
        return this.httpClient
            .get("/users")
            .then((response) => response.json())
            .then((array) => array.map((data) => ({ id: data.id, ...data.userBrief })))
            .then((array) => array.map((data) => new User(data, this.httpClient)));
    }
    getUser(userId) {
        if (this.httpClient.signInUserIsAdmin) {
            return this.httpClient
                .get(`/users/${userId}`)
                .then((response) => response.json())
                .then((data) => ({ id: data.id, ...data.userBrief }))
                .then((data) => new User(data, this.httpClient));
        }
        else if (userId === this.httpClient.signInUserId) {
            return this.httpClient
                .get("/user")
                .then((response) => response.json())
                .then((data) => ({ id: userId, ...data }))
                .then((data) => new User(data, this.httpClient));
        }
        else {
            return Promise.reject(new FetchError(403));
        }
    }
    createUser(email, password, params = {}) {
        const { isAdmin, userName, ...rest } = params;
        return this.httpClient
            .post("/users", {
            isAdmin,
            userBrief: {
                ...rest,
                email,
                userName: userName !== null && userName !== void 0 ? userName : (email + "").split("@").shift(),
            },
            password,
        })
            .then((response) => response.json())
            .then((data) => ({ id: data.id, ...data.userBrief }))
            .then((data) => new User(data, this.httpClient));
    }
    deleteUser(userId) {
        if (this.httpClient.signInUserIsAdmin) {
            return this.httpClient
                .delete(`/users/${userId}`)
                .then((response) => response.json())
                .then((data) => {
                if (userId === this.httpClient.signInUserId) {
                    this.clearCurrentUser();
                }
                return data;
            });
        }
        else {
            return Promise.reject(new FetchError(403));
        }
    }
    getFiles(start, limit, name, ext, ids, sortByDesc, sortField, shared) {
        const searchParams = new URLSearchParams();
        if (start && start > 0)
            searchParams.set("start", start.toString());
        if (limit && limit > 0)
            searchParams.set("limit", limit.toString());
        if (name)
            searchParams.set("name", name);
        if (ext) {
            ext = normalizeParam(ext);
            if (ext)
                searchParams.set("ext", ext.toLowerCase());
        }
        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);
        if (shared)
            searchParams.set("shared", "true");
        let queryString = searchParams.toString();
        if (queryString)
            queryString = "?" + queryString;
        return this.httpClient
            .get(`/files${queryString}`)
            .then((response) => response.json())
            .then((files) => {
            return {
                ...files,
                result: files.result.map((data) => new File(data, this.httpClient)),
            };
        });
    }
    getFile(fileId) {
        return this.httpClient
            .get(`/files/${fileId}`)
            .then((response) => response.json())
            .then((data) => new File(data, this.httpClient));
    }
    async uploadFile(file, params = {
        geometry: true,
        properties: false,
        waitForDone: false,
    }) {
        const result = await this.httpClient
            .uploadFile("/files", file, (progress) => {
            var _a;
            this.emitEvent({ type: "uploadprogress", data: progress, file });
            (_a = params.onProgress) === null || _a === void 0 ? void 0 : _a.call(params, progress, file);
        })
            .then((xhr) => JSON.parse(xhr.responseText))
            .then((data) => new File(data, this.httpClient));
        const geometryType = typeof params.geometry === "string" ? params.geometry : "vsfx";
        const jobParameters = params.jobParameters || {};
        const jobs = [];
        if (params.geometry)
            jobs.push((await result.extractGeometry(geometryType, jobParameters.geometry)).outputFormat);
        if (params.properties)
            jobs.push((await result.extractProperties(jobParameters.properties)).outputFormat);
        if (jobs.length > 0)
            if (params.waitForDone)
                await result.waitForDone(jobs, true, params);
            else
                await result.checkout();
        return result;
    }
    deleteFile(fileId) {
        return this.httpClient.delete(`/files/${fileId}`).then((response) => response.json());
    }
    downloadFile(fileId, onProgress, signal) {
        return this.httpClient
            .downloadFile(`/files/${fileId}/downloads`, onProgress, { signal })
            .then((response) => response.arrayBuffer());
    }
    getJobs(status, limit, start, sortByDesc, sortField) {
        const searchParams = new URLSearchParams();
        if (start && start > 0)
            searchParams.set("start", start.toString());
        if (limit && limit > 0)
            searchParams.set("limit", limit.toString());
        if (status) {
            status = normalizeParam(status);
            if (status)
                searchParams.set("status", status.toLowerCase());
        }
        if (sortByDesc !== undefined)
            searchParams.set("sortBy", sortByDesc ? "desc" : "asc");
        if (sortField)
            searchParams.set("sortField", sortField);
        let queryString = searchParams.toString();
        if (queryString)
            queryString = "?" + queryString;
        return this.httpClient
            .get(`/jobs${queryString}`)
            .then((response) => response.json())
            .then((jobs) => ({
            ...jobs,
            result: jobs.result.map((data) => new Job(data, this.httpClient)),
        }));
    }
    getJob(jobId) {
        return this.httpClient
            .get(`/jobs/${jobId}`)
            .then((response) => response.json())
            .then((data) => new Job(data, this.httpClient));
    }
    createJob(fileId, outputFormat, parameters) {
        return this.httpClient
            .post("/jobs", {
            fileId,
            outputFormat,
            parameters: parseArgs(parameters),
        })
            .then((response) => response.json())
            .then((data) => new Job(data, this.httpClient));
    }
    deleteJob(jobId) {
        return this.httpClient.delete(`/jobs/${jobId}`).then((response) => response.json());
    }
    getAssemblies(start, limit, name, ids, sortByDesc, sortField) {
        const searchParams = new URLSearchParams();
        if (start && start > 0)
            searchParams.set("start", start.toString());
        if (limit && 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.httpClient
            .get(`/assemblies${queryString}`)
            .then((response) => response.json())
            .then((assemblies) => {
            return {
                ...assemblies,
                result: assemblies.result.map((data) => new Assembly(data, this.httpClient)),
            };
        });
    }
    getAssembly(assemblyId) {
        return this.httpClient
            .get(`/assemblies/${assemblyId}`)
            .then((response) => response.json())
            .then((data) => new Assembly(data, this.httpClient));
    }
    createAssembly(files, name, params = {}) {
        const jobParameters = params.jobParameters || {};
        return this.httpClient
            .post("/assemblies", {
            name,
            files,
            jobParameters: {
                geometry: parseArgs(jobParameters.geometry),
                properties: parseArgs(jobParameters.properties),
            },
        })
            .then((response) => response.json())
            .then((data) => new Assembly(data, this.httpClient))
            .then((result) => (params.waitForDone ? result.waitForDone(params) : result));
    }
    deleteAssembly(assemblyId) {
        return this.httpClient.delete(`/assemblies/${assemblyId}`).then((response) => response.json());
    }
    getProjects(start, limit, name, ids, sortByDesc, sortField) {
        const searchParams = new URLSearchParams();
        if (start && start > 0)
            searchParams.set("start", start.toString());
        if (limit && 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.httpClient
            .get(`/projects${queryString}`)
            .then((response) => response.json())
            .then((projects) => {
            if (Array.isArray(projects)) {
                let result = projects;
                if (ids)
                    result = result.filter((x) => ids.includes(x.id));
                if (name)
                    result = result.filter((x) => x.name.includes(name));
                if (limit && limit > 0) {
                    const begin = start && start > 0 ? start : 0;
                    result = result.slice(begin, begin + limit);
                }
                return {
                    allSize: projects.length,
                    start,
                    limit,
                    result,
                    size: result.length,
                };
            }
            return projects;
        })
            .then((projects) => {
            return {
                ...projects,
                result: projects.result.map((data) => new Project(data, this.httpClient)),
            };
        });
    }
    getProject(projectId) {
        return this.httpClient
            .get(`/projects/${projectId}`)
            .then((response) => response.json())
            .then((data) => new Project(data, this.httpClient));
    }
    createProject(name, description, startDate, endDate) {
        return this.httpClient
            .post("/projects", {
            name,
            description,
            startDate: startDate instanceof Date ? startDate.toISOString() : startDate,
            endDate: endDate instanceof Date ? endDate.toISOString() : endDate,
        })
            .then((response) => response.json())
            .then((data) => new Project(data, this.httpClient));
    }
    deleteProject(projectId) {
        return this.httpClient
            .delete(`/projects/${projectId}`)
            .then((response) => response.text())
            .then((text) => {
            try {
                return JSON.parse(text);
            }
            catch {
                return { id: projectId };
            }
        });
    }
    getSharedLink(token) {
        return this.httpClient
            .get(`/shares/${token}`)
            .then((response) => response.json())
            .then((data) => new SharedLink(data, this.httpClient));
    }
    createSharedLink(fileId, permissions) {
        return this.httpClient
            .post("/shares", {
            fileId,
            permissions,
        })
            .then((response) => response.json())
            .then((data) => new SharedLink(data, this.httpClient));
    }
    deleteSharedLink(token) {
        return this.httpClient.delete(`/shares/${token}`).then((response) => response.json());
    }
    getSharedFile(token, password = "") {
        return this.httpClient
            .get(`/shares/${token}/info`, { headers: { "InWeb-Password": password } })
            .then((response) => response.json())
            .then((data) => new SharedFile(data, password, this.httpClient));
    }
    getPlugins() {
        return this.httpClient
            .get("/plugins")
            .then((response) => response.json())
            .then((array) => array.map((data) => new Plugin(data, this.httpClient)));
    }
    getPlugin(name, version) {
        return this.httpClient
            .get(`/plugins/${name}/${version}`)
            .then((response) => response.json())
            .then((data) => new Plugin(data, this.httpClient));
    }
    async uploadPlugin(file, onProgress) {
        return await this.httpClient
            .uploadFile("/plugins", file, (progress) => {
            this.emitEvent({ type: "uploadprogress", data: progress, file });
            if (onProgress)
                onProgress(progress, file);
        })
            .then((xhr) => JSON.parse(xhr.responseText))
            .then((data) => new Plugin(data, this.httpClient));
    }
    deletePlugin(name, version) {
        return this.httpClient.delete(`/plugins/${name}/${version}`).then((response) => response.json());
    }
    downloadPlugin(name, version, onProgress, signal) {
        return this.httpClient
            .downloadFile(`/plugins/${name}/${version}/download`, onProgress, { signal })
            .then((response) => response.arrayBuffer());
    }
    executePluginCommand(name, version, command, parameters) {
        const searchParams = new URLSearchParams();
        if (version)
            searchParams.set("version", version);
        let queryString = searchParams.toString();
        if (queryString)
            queryString = "?" + queryString;
        return this.httpClient
            .post(`/plugins/${name}/commands/${command}${queryString}`, parameters)
            .then((response) => response.json());
    }
}

const version = "27.8.1";

export { Assembly, ClashTest, Client, Endpoint, FetchError, File, Job, Member, Model, OAuthClient, Permission, Plugin, Project, Role, SharedFile, SharedLink, User, delay, normalizeParam, parseArgs, statusText, userFullName, userInitials, version, waitFor };
//# sourceMappingURL=client.module.js.map