UNPKG

@inweb/client

Version:

JavaScript REST API client for the Open Cloud Server

186 lines (174 loc) 6.61 kB
/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a // license agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// import { IHttpClient } from "./IHttpClient"; import { $fetch } from "./Fetch"; import { $xmlhttp } from "./XMLHttp"; export class HttpClient implements IHttpClient { public serverUrl: string; public headers: HeadersInit = {}; public signInUserId = ""; public signInUserIsAdmin = false; constructor(serverUrl: string) { this.serverUrl = serverUrl; } get(relativePath: string, init: RequestInit = {}): Promise<Response> { return $fetch(`${this.serverUrl}${relativePath}`, { ...init, method: "GET", headers: { ...this.headers, ...init.headers }, }); } post(relativePath: string, body?: BodyInit | object, init: RequestInit = {}): Promise<Response> { return $fetch(`${this.serverUrl}${relativePath}`, { ...init, method: "POST", headers: { ...this.headers, ...init.headers }, body, }); } put(relativePath: string, body?: BodyInit | object, init: RequestInit = {}): Promise<Response> { return $fetch(`${this.serverUrl}${relativePath}`, { ...init, method: "PUT", headers: { ...this.headers, ...init.headers }, body, }); } delete(relativePath: string, init: RequestInit = {}): Promise<Response> { return $fetch(`${this.serverUrl}${relativePath}`, { ...init, method: "DELETE", headers: { ...this.headers, ...init.headers }, }); } uploadFile( relativePath: string, file: File, onProgress?: (progress: number) => void, init: RequestInit = {} ): Promise<XMLHttpRequest> { 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: string, // onProgress?: (progress: number, chunk: Uint8Array) => void, // init: RequestInit = {} // ): Promise<Response> { // const response = await this.get(relativePath, init); // const teedOff = response.body.tee(); // if (onProgress) { // const contentLength = response.headers.get("Content-Length"); // const total = parseInt(contentLength, 10) || 1; // let loaded = 0; // const reader = teedOff[0].getReader(); // reader.read().then(function processChunk({ done, value }) { // if (done) return; // loaded += value.length; // onProgress(loaded / total, value); // reader.read().then(processChunk); // }); // } // return new Response(teedOff[1]); // } async downloadFile( relativePath: string, onProgress?: (progress: number, chunk: Uint8Array) => void, init: RequestInit = {} ): Promise<Response> { 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, value } = await reader.read(); if (done) break; controller.enqueue(value); loaded += value.length; if (onProgress) onProgress(loaded / total, value); } controller.close(); }, }) ); } async downloadFileRange( relativePath: string, reserved: number, ranges: Array<{ begin: number; end: number; requestId: number }>, onProgress?: (progress: number, chunk: Uint8Array, requestId: number) => void, init: RequestInit = {} ): Promise<Response> { const headers = { ...init.headers }; headers["Range"] = "bytes=" + ranges.map((x) => `${x.begin}-${x.end}`).join(","); const response = await this.get(relativePath, { ...init, 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, 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(); }, }) ); } }