wretch
Version:
A tiny wrapper built around fetch with an intuitive syntax.
114 lines • 4.15 kB
JavaScript
function toStream(requestOrResponse, bodySize, callback) {
try {
const contentLength = requestOrResponse.headers.get("content-length");
let total = bodySize || (contentLength ? +contentLength : 0);
let loaded = 0;
const transform = new TransformStream({
start() {
callback === null || callback === void 0 ? void 0 : callback(loaded, total);
},
transform(chunk, controller) {
loaded += chunk.length;
if (total < loaded) {
total = loaded;
}
callback === null || callback === void 0 ? void 0 : callback(loaded, total);
controller.enqueue(chunk);
}
});
const stream = requestOrResponse.body.pipeThrough(transform);
if ("status" in requestOrResponse) {
return new Response(stream, requestOrResponse);
}
else {
// @ts-expect-error RequestInit does not yet include duplex
return new Request(requestOrResponse, { body: stream, duplex: "half" });
}
}
catch (_a) {
return requestOrResponse;
}
}
const defaultGetUploadTotal = async (url, opts) => {
let total = opts.body instanceof ArrayBuffer ? +opts.body.byteLength :
opts.body instanceof Blob ? +opts.body.size :
0;
try {
// Try to determine body size by reading it as a blob
total || (total = (await new Request(url, opts).blob()).size);
}
catch (_a) {
// Cannot determine body size
}
return total;
};
/**
* Adds the ability to monitor progress when downloading a response.
*
* _Compatible with all platforms implementing the [TransformStream WebAPI](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream#browser_compatibility)._
*
* ```js
* import ProgressAddon from "wretch/addons/progress"
*
* wretch("some_url")
* // Register the addon
* .addon(ProgressAddon())
* .get()
* // Log the progress as a percentage of completion
* .progress((loaded, total) => console.log(`${(loaded / total * 100).toFixed(0)}%`))
* ```
*/
const progress = ({ getUploadTotal = defaultGetUploadTotal } = {}) => {
function downloadMiddleware(state) {
return next => (url, opts) => {
return next(url, opts).then(response => {
if (!state.progress) {
return response;
}
return toStream(response, 0, state.progress);
});
};
}
function uploadMiddleware(state) {
return next => async (url, opts) => {
const body = opts.body;
if (!body || !state.upload) {
return next(url, opts);
}
const streameableRequest = toStream(new Request(url, opts), await getUploadTotal(url, opts), state.upload);
return next(url, streameableRequest);
};
}
return {
beforeRequest(wretch, options, state) {
const middlewares = [];
if (options.__uploadProgressCallback) {
state.upload = options.__uploadProgressCallback;
delete options.__uploadProgressCallback;
}
if (options.__downloadProgressCallback) {
state.progress = options.__downloadProgressCallback;
delete options.__downloadProgressCallback;
}
middlewares.push(uploadMiddleware(state));
middlewares.push(downloadMiddleware(state));
return wretch.middlewares(middlewares);
},
wretch: {
onUpload(onUpload) {
return this.options({ __uploadProgressCallback: onUpload });
},
onDownload(onDownload) {
return this.options({ __downloadProgressCallback: onDownload });
}
},
resolver: {
progress(onProgress) {
this._sharedState.progress = onProgress;
return this;
}
},
};
};
export default progress;
//# sourceMappingURL=progress.js.map