// https://unpkg.com/isomorphic-git@1.7.2/http/web/index.js /** * @typedef {Object} GitProgressEvent * @property {string} phase * @property {number} loaded * @property {number} total */ /** * @callback ProgressCallback * @param {GitProgressEvent} progress * @returns {void | Promise} */ /** * @typedef {Object} GitHttpRequest * @property {string} url - The URL to request * @property {string} [method='GET'] - The HTTP method to use * @property {Object} [headers={}] - Headers to include in the HTTP request * @property {AsyncIterableIterator} [body] - An async iterator of Uint8Arrays that make up the body of POST requests * @property {ProgressCallback} [onProgress] - Reserved for future use (emitting `GitProgressEvent`s) * @property {object} [signal] - Reserved for future use (canceling a request) */ /** * @typedef {Object} GitHttpResponse * @property {string} url - The final URL that was fetched after any redirects * @property {string} [method] - The HTTP method that was used * @property {Object} [headers] - HTTP response headers * @property {AsyncIterableIterator} [body] - An async iterator of Uint8Arrays that make up the body of the response * @property {number} statusCode - The HTTP status code * @property {string} statusMessage - The HTTP status message */ /** * @callback HttpFetch * @param {GitHttpRequest} request * @returns {Promise} */ /** * @typedef {Object} HttpClient * @property {HttpFetch} request */ // Convert a value to an Async Iterator // This will be easier with async generator functions. function fromValue(value) { let queue = [value]; return { next() { return Promise.resolve({ done: queue.length === 0, value: queue.pop() }) }, return() { queue = []; return {} }, [Symbol.asyncIterator]() { return this }, } } function getIterator(iterable) { if (iterable[Symbol.asyncIterator]) { return iterable[Symbol.asyncIterator]() } if (iterable[Symbol.iterator]) { return iterable[Symbol.iterator]() } if (iterable.next) { return iterable } return fromValue(iterable) } // Currently 'for await' upsets my linters. async function forAwait(iterable, cb) { const iter = getIterator(iterable); while (true) { const { value, done } = await iter.next(); if (value) await cb(value); if (done) break } if (iter.return) iter.return(); } async function collect(iterable) { let size = 0; const buffers = []; // This will be easier once `for await ... of` loops are available. await forAwait(iterable, value => { buffers.push(value); size += value.byteLength; }); const result = new Uint8Array(size); let nextIndex = 0; for (const buffer of buffers) { result.set(buffer, nextIndex); nextIndex += buffer.byteLength; } return result } // Convert a web ReadableStream (not Node stream!) to an Async Iterator // adapted from https://jakearchibald.com/2017/async-iterators-and-generators/ function fromStream(stream) { // Use native async iteration if it's available. if (stream[Symbol.asyncIterator]) return stream const reader = stream.getReader(); return { next() { return reader.read() }, return() { reader.releaseLock(); return {} }, [Symbol.asyncIterator]() { return this }, } } /* eslint-env browser */ /** * HttpClient * * @param {GitHttpRequest} request * @returns {Promise} */ async function request({ onProgress, url, method = 'GET', headers = {}, body, }) { // streaming uploads aren't possible yet in the browser if (body) { body = await collect(body); } const res = await fetch(url, { method, headers, body }); const iter = res.body && res.body.getReader ? fromStream(res.body) : [new Uint8Array(await res.arrayBuffer())]; // convert Header object to ordinary JSON headers = {}; for (const [key, value] of res.headers.entries()) { headers[key] = value; } return { url: res.url, method: res.method, statusCode: res.status, statusMessage: res.statusText, body: iter, headers: headers, } } var index = { request }; //export default index; //export { request };