Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

client-zip

Package Overview
Dependencies
Maintainers
1
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

client-zip - npm Package Compare versions

Comparing version
1.6.3
to
1.6.4
+4
-0
CHANGES.md

@@ -0,1 +1,5 @@

## 1.6.4:
* bugfix: the output stream can now be transferred without breaking the central repository.
## 1.6.3:

@@ -2,0 +6,0 @@

+1
-1

@@ -1,1 +0,1 @@

"stream"in Blob.prototype||Object.defineProperty(Blob.prototype,"stream",{value(){return new Response(this).body}});var e=e=>new DataView(new ArrayBuffer(e)),n=e=>new Uint8Array(e.buffer||e),t=e=>(new TextEncoder).encode(String(e));function r(e,r){if(void 0===r||r instanceof Date||(r=new Date(r)),e instanceof File)return{t:r||new Date(e.lastModified),o:e.stream()};if(e instanceof Response)return{t:r||new Date(e.headers.get("Last-Modified")||Date.now()),o:e.body};if(void 0===r)r=new Date;else if(isNaN(r))throw new Error("Invalid modification date.");if("string"==typeof e)return{t:r,o:t(e)};if(e instanceof Blob)return{t:r,o:e.stream()};if(e instanceof Uint8Array||e instanceof ReadableStream)return{t:r,o:e};if(e instanceof ArrayBuffer||ArrayBuffer.isView(e))return{t:r,o:n(e)};if(Symbol.asyncIterator in e)return{t:r,o:o(e[Symbol.asyncIterator]())};throw new TypeError("Unsupported input format.")}function o(e,n=e){return new ReadableStream({async pull(n){let t=0;for(;n.desiredSize>t;){const r=await e.next();if(!r.value){n.close();break}{const e=i(r.value);n.enqueue(e),t+=e.byteLength}}},cancel(e){var t;null==(t=n.throw)||t.call(n,e)}})}function i(e){return"string"==typeof e?t(e):e instanceof Uint8Array?e:n(e)}function a(e,r,o){let[i,a]=function(e){return e?e instanceof Uint8Array?[e,1]:ArrayBuffer.isView(e)||e instanceof ArrayBuffer?[n(e),1]:[t(e),0]:[void 0,0]}(r);if(e instanceof File)return{i:s(i||t(e.name)),u:e.size,l:a};if(e instanceof Response){const n=e.headers.get("content-disposition"),r=n&&n.match(/;\s*filename\*?=["']?(.*?)["']?$/i),f=r&&r[1]||e.url&&new URL(e.url).pathname.split("/").findLast(Boolean),u=f&&decodeURIComponent(f),d=o||+e.headers.get("content-length");return{i:s(i||t(u)),u:d,l:a}}return i=s(i),"string"==typeof e?{i,u:t(e).length,l:a}:e instanceof Blob?{i,u:e.size,l:a}:e instanceof ArrayBuffer||ArrayBuffer.isView(e)?{i,u:e.byteLength,l:a}:{i,u:f(e,o),l:a}}function f(e,n){return n>-1?n:e?void 0:0}function s(e){if(!e||e.every((c=>47===c)))throw new Error("The file must have a name.");for(;47===e[e.length-1];)e=e.subarray(0,-1);return e}var u=new Uint32Array(256);for(let e=0;e<256;++e){let n=e;for(let e=0;e<8;++e)n=n>>>1^(1&n&&3988292384);u[e]=n}function d(e,n=0){n^=-1;for(var t=0,r=e.length;t<r;t++)n=n>>>8^u[255&n^e[t]];return(-1^n)>>>0}function l(e,n,t=0){const r=e.getSeconds()>>1|e.getMinutes()<<5|e.getHours()<<11,o=e.getDate()|e.getMonth()+1<<5|e.getFullYear()-1980<<9;n.setUint16(t,r,1),n.setUint16(t+2,o,1)}function y({i:e,l:n},t){return 8*(!n||(null!=t?t:function(e){try{w.decode(e)}catch(e){return 0}return 1}(e)))}var w=new TextDecoder("utf8",{fatal:1});function p(t,r=0){const o=e(30);return o.setUint32(0,1347093252),o.setUint32(4,335546368|r),l(t.t,o,10),o.setUint16(26,t.i.length,1),n(o)}async function*b(e){let{o:n}=e;if("then"in n&&(n=await n),n instanceof Uint8Array)yield n,e.m=d(n,0),e.u=n.length;else{e.u=0;const t=n.getReader();for(;;){const{value:n,done:r}=await t.read();if(r)break;e.m=d(n,e.m),e.u+=n.length,yield n}}}function v(t){const r=e(16);return r.setUint32(0,1347094280),r.setUint32(4,t.m,1),r.setUint32(8,t.u,1),r.setUint32(12,t.u,1),n(r)}function B(t,r,o=0){const i=e(46);return i.setUint32(0,1347092738),i.setUint32(4,352523264),i.setUint16(8,2048|o),l(t.t,i,12),i.setUint32(16,t.m,1),i.setUint32(20,t.u,1),i.setUint32(24,t.u,1),i.setUint16(28,t.i.length,1),i.setUint16(40,33204,1),i.setUint32(42,r,1),n(i)}function D(e){return e instanceof File||e instanceof Response?[[e],[e]]:[[e.input,e.name,e.size],[e.input,e.lastModified]]}var h=e=>function(e){var n;let t=22;for(const r of e){if(!r.i)throw new Error("Every file must have a non-empty name.");if(isNaN(null!=(n=r.u)?n:NaN))throw new Error(`Missing size for file "${(new TextDecoder).decode(r.i)}".`);t+=2*r.i.length+r.u+92}return t}(function*(e){for(const n of e)yield a(...D(n)[0])}(e));function S(t,i={}){const f={"Content-Type":"application/zip","Content-Disposition":"attachment"};Number.isInteger(i.length)&&i.length>0&&(f["Content-Length"]=i.length),i.metadata&&(f["Content-Length"]=h(i.metadata));const s=function(e){var n;const t=e[Symbol.iterator in e?Symbol.iterator:Symbol.asyncIterator]();return{async next(){const e=await t.next();if(e.done)return e;const[n,o]=D(e.value);return{done:0,value:Object.assign(r(...o),a(...n))}},throw:null==(n=t.throw)?void 0:n.bind(t),[Symbol.asyncIterator](){return this}}}(t);return new Response(o(async function*(t,r){const o=[];let i=0,a=0;for await(const e of t){const n=y(e,r.buffersAreUTF8);yield p(e,n),yield e.i,yield*b(e),yield v(e),o.push(B(e,i,n)),o.push(e.i),a++,i+=46+e.i.length+e.u}let f=0;for(const e of o)yield e,f+=e.length;const s=e(22);s.setUint32(0,1347093766),s.setUint16(8,a,1),s.setUint16(10,a,1),s.setUint32(12,f,1),s.setUint32(16,i,1),yield n(s)}(s,i),s),{headers:f})}export{S as downloadZip,h as predictLength};
"stream"in Blob.prototype||Object.defineProperty(Blob.prototype,"stream",{value(){return new Response(this).body}});var e=e=>new DataView(new ArrayBuffer(e)),n=e=>new Uint8Array(e.buffer||e),t=e=>(new TextEncoder).encode(String(e));function r(e,r){if(void 0===r||r instanceof Date||(r=new Date(r)),e instanceof File)return{t:r||new Date(e.lastModified),o:e.stream()};if(e instanceof Response)return{t:r||new Date(e.headers.get("Last-Modified")||Date.now()),o:e.body};if(void 0===r)r=new Date;else if(isNaN(r))throw new Error("Invalid modification date.");if("string"==typeof e)return{t:r,o:t(e)};if(e instanceof Blob)return{t:r,o:e.stream()};if(e instanceof Uint8Array||e instanceof ReadableStream)return{t:r,o:e};if(e instanceof ArrayBuffer||ArrayBuffer.isView(e))return{t:r,o:n(e)};if(Symbol.asyncIterator in e)return{t:r,o:o(e[Symbol.asyncIterator]())};throw new TypeError("Unsupported input format.")}function o(e,n=e){return new ReadableStream({async pull(n){let t=0;for(;n.desiredSize>t;){const r=await e.next();if(!r.value){n.close();break}{const e=i(r.value);n.enqueue(e),t+=e.byteLength}}},cancel(e){var t;null==(t=n.throw)||t.call(n,e)}})}function i(e){return"string"==typeof e?t(e):e instanceof Uint8Array?e:n(e)}function a(e,r,o){let[i,a]=function(e){return e?e instanceof Uint8Array?[e,1]:ArrayBuffer.isView(e)||e instanceof ArrayBuffer?[n(e),1]:[t(e),0]:[void 0,0]}(r);if(e instanceof File)return{i:s(i||t(e.name)),u:e.size,l:a};if(e instanceof Response){const n=e.headers.get("content-disposition"),r=n&&n.match(/;\s*filename\*?=["']?(.*?)["']?$/i),f=r&&r[1]||e.url&&new URL(e.url).pathname.split("/").findLast(Boolean),u=f&&decodeURIComponent(f),d=o||+e.headers.get("content-length");return{i:s(i||t(u)),u:d,l:a}}return i=s(i),"string"==typeof e?{i,u:t(e).length,l:a}:e instanceof Blob?{i,u:e.size,l:a}:e instanceof ArrayBuffer||ArrayBuffer.isView(e)?{i,u:e.byteLength,l:a}:{i,u:f(e,o),l:a}}function f(e,n){return n>-1?n:e?void 0:0}function s(e){if(!e||e.every((c=>47===c)))throw new Error("The file must have a name.");for(;47===e[e.length-1];)e=e.subarray(0,-1);return e}var u=new Uint32Array(256);for(let e=0;e<256;++e){let n=e;for(let e=0;e<8;++e)n=n>>>1^(1&n&&3988292384);u[e]=n}function d(e,n=0){n^=-1;for(var t=0,r=e.length;t<r;t++)n=n>>>8^u[255&n^e[t]];return(-1^n)>>>0}function l(e,n,t=0){const r=e.getSeconds()>>1|e.getMinutes()<<5|e.getHours()<<11,o=e.getDate()|e.getMonth()+1<<5|e.getFullYear()-1980<<9;n.setUint16(t,r,1),n.setUint16(t+2,o,1)}function y({i:e,l:n},t){return 8*(!n||(null!=t?t:function(e){try{w.decode(e)}catch(e){return 0}return 1}(e)))}var w=new TextDecoder("utf8",{fatal:1});function p(t,r=0){const o=e(30);return o.setUint32(0,1347093252),o.setUint32(4,335546368|r),l(t.t,o,10),o.setUint16(26,t.i.length,1),n(o)}async function*b(e){let{o:n}=e;if("then"in n&&(n=await n),n instanceof Uint8Array)yield n,e.m=d(n,0),e.u=n.length;else{e.u=0;const t=n.getReader();for(;;){const{value:n,done:r}=await t.read();if(r)break;e.m=d(n,e.m),e.u+=n.length,yield n}}}function v(t){const r=e(16);return r.setUint32(0,1347094280),r.setUint32(4,t.m,1),r.setUint32(8,t.u,1),r.setUint32(12,t.u,1),n(r)}function B(t,r,o=0){const i=e(46);return i.setUint32(0,1347092738),i.setUint32(4,352523264),i.setUint16(8,2048|o),l(t.t,i,12),i.setUint32(16,t.m,1),i.setUint32(20,t.u,1),i.setUint32(24,t.u,1),i.setUint16(28,t.i.length,1),i.setUint16(40,33204,1),i.setUint32(42,r,1),n(i)}function D(e){return e instanceof File||e instanceof Response?[[e],[e]]:[[e.input,e.name,e.size],[e.input,e.lastModified]]}var h=e=>function(e){var n;let t=22;for(const r of e){if(!r.i)throw new Error("Every file must have a non-empty name.");if(isNaN(null!=(n=r.u)?n:NaN))throw new Error(`Missing size for file "${(new TextDecoder).decode(r.i)}".`);t+=2*r.i.length+r.u+92}return t}(function*(e){for(const n of e)yield a(...D(n)[0])}(e));function S(t,i={}){const f={"Content-Type":"application/zip","Content-Disposition":"attachment"};Number.isInteger(i.length)&&i.length>0&&(f["Content-Length"]=i.length),i.metadata&&(f["Content-Length"]=h(i.metadata));const s=function(e){var n;const t=e[Symbol.iterator in e?Symbol.iterator:Symbol.asyncIterator]();return{async next(){const e=await t.next();if(e.done)return e;const[n,o]=D(e.value);return{done:0,value:Object.assign(r(...o),a(...n))}},throw:null==(n=t.throw)?void 0:n.bind(t),[Symbol.asyncIterator](){return this}}}(t);return new Response(o(async function*(t,r){const o=[];let i=0,a=0;for await(const e of t){const n=y(e,r.buffersAreUTF8);yield p(e,n),yield new Uint8Array(e.i),yield*b(e),yield v(e),o.push(B(e,i,n)),o.push(e.i),a++,i+=46+e.i.length+e.u}let f=0;for(const e of o)yield e,f+=e.length;const s=e(22);s.setUint32(0,1347093766),s.setUint16(8,a,1),s.setUint16(10,a,1),s.setUint32(12,f,1),s.setUint32(16,i,1),yield n(s)}(s,i),s),{headers:f})}export{S as downloadZip,h as predictLength};
{
"name": "client-zip",
"version": "1.6.3",
"version": "1.6.4",
"description": "A tiny and fast client-side streaming ZIP generator",

@@ -20,3 +20,3 @@ "browser": "index.js",

"type": "git",
"url": "git@github.com:Touffy/client-zip.git"
"url": "git+ssh://git@github.com/Touffy/client-zip.git"
},

@@ -23,0 +23,0 @@ "keywords": [

+22
-16

@@ -116,2 +116,4 @@ ![Test](https://github.com/Touffy/client-zip/workflows/Test/badge.svg)

*updated again in may 2023 (experiment 3)*
I started this project because I wasn't impressed with what — at the time — appeared to be the only other ZIP library for browsers, [JSZip](https://stuk.github.io/jszip/). I later found other libraries, which I've included in the new benchmarks, and JSZip has improved dramatically (version 3.6 was 40 times slower vs. currently only 40% slower).

@@ -125,18 +127,22 @@

| | | `client-zip`@1.6.0 | fflate@0.7.4 | zip.js@2.7.6 | conflux@4.0.3 | JSZip@3.10.1 |
|:------------------|--------|-------------------:|---------------:|---------------:|----------------:|----------------:|
| **experiment 1** | Safari | 1.647 (σ=21) s | 1.792 (σ=15) s | 1.912 (σ=80) s | 1.820 (σ=16) s | 2.122 (σ=60) s |
| baseline: 1.653 s | Chrome | 2.480 (σ=41) s | 1.601 (σ=4) s | 4.251 (σ=53) s | 4.268 (σ=44) s | 3.921 (σ=15) s |
| **experiment 2** | Safari | 2.173 (σ=11) s | 2.157 (σ=23) s | 3.158 (σ=17) s | 1.794 (σ=13) s | 2.631 (σ=27) s |
| baseline: 0.615 s | Chrome | 3.567 (σ=77) s | 3.506 (σ=9) s | 5.689 (σ=17) s | 3.174 (σ=22) s | 4.602 (σ=50) s |
**Experiemnt 3** is the same set of 6214 TGA files combined with very small PNG files for a total of 12 044 files (total 130 MB). This time, the files are *fetched* by a [DownloadStream](https://github.com/Touffy/dl-stream) to minimize latency.
The experiments were run 10 times (not counting a first run to let the JavaScript engine "warm up") for each lib and each dataset, *with the dev tools closed* (this is important, opening the dev tools has a noticeable impact on CPU and severe impact on HTTP latency). The numbers in the table are the mean time of the ten runs, with the standard deviation in parentheses.
| | | `client-zip`@2.4.3 | fflate@0.7.4 | zip.js@2.7.14 | conflux@4.0.3 | JSZip@3.10.1 |
|:------------------|--------|-------------------:|---------------:|----------------:|----------------:|----------------:|
| **experiment 1** | Safari | 1.647 (σ=21) s | 1.792 (σ=15) s | 1.912 (σ=80) s | 1.820 (σ=16) s | 2.122 (σ=60) s |
| baseline: 1.653 s | Chrome | 2.480 (σ=41) s | 1.601 (σ=4) s | 4.251 (σ=53) s | 4.268 (σ=44) s | 3.921 (σ=15) s |
| **experiment 2** | Safari | 2.173 (σ=11) s | 2.157 (σ=23) s | 3.158 (σ=17) s | 1.794 (σ=13) s | 2.631 (σ=27) s |
| baseline: 0.615 s | Chrome | 3.567 (σ=77) s | 3.506 (σ=9) s | 5.689 (σ=17) s | 3.174 (σ=22) s | 4.602 (σ=50) s |
| **experiment 3** | Safari | 1.768 (σ=12) s | 1.691 (σ=19) s | 3.149 (σ=45) s | 1.511 (σ=38) s | 2.703 (σ=79) s |
| baseline: 0.892 s | Chrome | 4.604 (σ=79) s | 3.972 (σ=85) s | 7.507 (σ=261) s | 3.812 (σ=80) s | 6.297 (σ=35) s |
For the baseline, I timed the `zip` process in my UNIX shell. As advertised, fflate run just as fast — in Chrome, anyway, and when there is no overhead for HTTP (experiment 1). In the same test, client-zip beats everyone else in Safari.
The experiments were run 10 times (not counting a first run to let the JavaScript engine "warm up" and ensure the browser caches everything) for each lib and each dataset, *with the dev tools closed* (this is important, opening the dev tools has a noticeable impact on CPU and severe impact on HTTP latency). The numbers in the table are the mean time of the ten runs, with the standard deviation in parentheses.
Conflux does particularly well with the second experiment because it is fed by a stream of inputs, whose buffer decreases the effect of latency. That is not an intrisic advantage of Conflux but I let it keep the win because it is the only library that recommends this in its README, and it illustrates how buffering several Responses ahead of time can improve performance when dealing with many small requests.
For the baseline, I timed the `zip -0` process in my UNIX shell. As advertised, fflate run just as fast — in Chrome, anyway, and when there is no overhead for HTTP (experiment 1). In the same test, client-zip beats everyone else in Safari.
Conflux does particularly well in the second and third experiments thanks to its internal use of ReadableStreams, which seem to run faster than async generators.
Zip.js workers were disabled because I didn't want to bother fixing the error I got from the library. Using workers on this task could only help by sacrificing lots of memory, anyway. But I suppose Zip.js really needs those workers to offset its disgraceful single-threaded performance.
It's interesting that Chrome performs so much worse than Safari with client-zip and conflux, the two libraries that rely on WHATWG Streams and (in my case) async iterables, whereas it shows better (and extremely consistent) runtimes with fflate, which uses synchronous code with callbacks. Zip.js and JSZip used to be faster in Chrome than Safari, but clearly things have changed.
It's interesting that Chrome performs so much worse than Safari with client-zip and conflux, the two libraries that rely on WHATWG Streams and (in my case) async iterables, whereas it shows better (and extremely consistent) runtimes with fflate, which uses synchronous code with callbacks, in experiment 1. Zip.js and JSZip used to be faster in Chrome than Safari, but clearly things have changed. Experiments 2 and 3 are really taxing for Chrome.

@@ -147,6 +153,6 @@ In a different experiment using Deno to avoid storing very large output files, memory usage for any amount of data remained constant or close enough. My tests maxed out at 36.1 MB of RAM while processing nearly 6 GB.

| | `client-zip`@1.6.3 | fflate@0.7.4 | zip.js@2.7.6 | conflux@4.0.3 | JSZip@3.10.1 |
| | `client-zip`@1.6.4 | fflate@0.7.4 | zip.js@2.7.14 | conflux@4.0.3 | JSZip@3.10.1 |
|--------------------|-------------------:|-------------:|--------------:|--------------:|--------------:|
| minified | 4.8 kB | 29.8 kB | 162.3 kB | 198.8 kB | 94.9 kB |
| minified + gzipped | 2.1 kB | 11 kB | 57.8 kB | 56.6 kB | 27.6 kB |
| minified | 4.8 kB | 29.8 kB | 163.2 kB | 198.8 kB | 94.9 kB |
| minified + gzipped | 2.1 kB | 11 kB | 58 kB | 56.6 kB | 27.6 kB |

@@ -157,3 +163,3 @@ The datasets I used in the new tests are not public domain, but nothing sensitive either ; I can send them if you ask.

* client-zip cannot be bundled by SSR frameworks that expect it to run in Node.js too ([workaround](https://github.com/Touffy/client-zip/issues/28#issuecomment-1018033984)).
* client-zip cannot be bundled by SSR frameworks that expect it to run server-side too ([workaround](https://github.com/Touffy/client-zip/issues/28#issuecomment-1018033984)).
* Firefox may kill a Service Worker that is still feeding a download ([workaround](https://github.com/Touffy/client-zip/issues/46#issuecomment-1259223708)).

@@ -182,7 +188,7 @@ * Safari could not download from a Service Worker until version 15.4 (released 4 march 2022).

Limited use case. If the user is going to extract the archive just after downloading anyway, it's a waste of CPU. Implementation should be relatively easy with the new CompressionStream API.
Limited use case. If the user is going to extract the archive just after downloading anyway, it's a waste of CPU. Implementation should be relatively easy with the new CompressionStream API. Incompatible with content-length prediction.
### encryption
AES and RSA encryption could be implemented quite easily with [WebCrypto](https://www.w3.org/TR/WebCryptoAPI/). I just don't see any use case for it (but if there is one, compression would be relevant for it too).
AES and RSA encryption could have been implemented with [WebCrypto](https://www.w3.org/TR/WebCryptoAPI/). However, only the proprietary PKWARE utility supports strong encryption of file contents **and metadata**. Well-supported Zip encryption methods (even using AES) do not hide metadata, giving you questionable privacy. Therefore, **this feature is no longer planned for client-zip**.

@@ -189,0 +195,0 @@ ### performance improvements

@@ -1,1 +0,1 @@

var downloadZip=(()=>{"stream"in Blob.prototype||Object.defineProperty(Blob.prototype,"stream",{value(){return new Response(this).body}});var i=e=>new DataView(new ArrayBuffer(e)),a=e=>new Uint8Array(e.buffer||e),f=e=>(new TextEncoder).encode(String(e));function s(e,n){if(void 0===n||n instanceof Date||(n=new Date(n)),e instanceof File)return{t:n||new Date(e.lastModified),o:e.stream()};if(e instanceof Response)return{t:n||new Date(e.headers.get("Last-Modified")||Date.now()),o:e.body};if(void 0===n)n=new Date;else if(isNaN(n))throw new Error("Invalid modification date.");if("string"==typeof e)return{t:n,o:f(e)};if(e instanceof Blob)return{t:n,o:e.stream()};if(e instanceof Uint8Array||e instanceof ReadableStream)return{t:n,o:e};if(e instanceof ArrayBuffer||ArrayBuffer.isView(e))return{t:n,o:a(e)};if(Symbol.asyncIterator in e)return{t:n,o:u(e[Symbol.asyncIterator]())};throw new TypeError("Unsupported input format.")}function u(e,n=e){return new ReadableStream({async pull(n){let t=0;for(;n.desiredSize>t;){const r=await e.next();if(!r.value){n.close();break}{const e=l(r.value);n.enqueue(e),t+=e.byteLength}}},cancel(e){var t;null==(t=n.throw)||t.call(n,e)}})}function l(e){return"string"==typeof e?f(e):e instanceof Uint8Array?e:a(e)}function d(e,n,t){let[r,o]=function(e){return e?e instanceof Uint8Array?[e,1]:ArrayBuffer.isView(e)||e instanceof ArrayBuffer?[a(e),1]:[f(e),0]:[void 0,0]}(n);if(e instanceof File)return{i:w(r||f(e.name)),u:e.size,l:o};if(e instanceof Response){const n=e.headers.get("content-disposition"),i=n&&n.match(/;\s*filename\*?=["']?(.*?)["']?$/i),a=i&&i[1]||e.url&&new URL(e.url).pathname.split("/").findLast(Boolean),s=a&&decodeURIComponent(a),u=t||+e.headers.get("content-length");return{i:w(r||f(s)),u,l:o}}return r=w(r),"string"==typeof e?{i:r,u:f(e).length,l:o}:e instanceof Blob?{i:r,u:e.size,l:o}:e instanceof ArrayBuffer||ArrayBuffer.isView(e)?{i:r,u:e.byteLength,l:o}:{i:r,u:y(e,t),l:o}}function y(e,n){return n>-1?n:e?void 0:0}function w(e){if(!e||e.every((c=>47===c)))throw new Error("The file must have a name.");for(;47===e[e.length-1];)e=e.subarray(0,-1);return e}var b=new Uint32Array(256);for(let e=0;e<256;++e){let n=e;for(let e=0;e<8;++e)n=n>>>1^(1&n&&3988292384);b[e]=n}function p(e,n=0){n^=-1;for(var t=0,r=e.length;t<r;t++)n=n>>>8^b[255&n^e[t]];return(-1^n)>>>0}function v(e,n,t=0){const r=e.getSeconds()>>1|e.getMinutes()<<5|e.getHours()<<11,o=e.getDate()|e.getMonth()+1<<5|e.getFullYear()-1980<<9;n.setUint16(t,r,1),n.setUint16(t+2,o,1)}function B({i:e,l:n},t){return 8*(!n||(null!=t?t:function(e){try{D.decode(e)}catch(e){return 0}return 1}(e)))}var D=new TextDecoder("utf8",{fatal:1});function h(e,n=0){const t=i(30);return t.setUint32(0,1347093252),t.setUint32(4,335546368|n),v(e.t,t,10),t.setUint16(26,e.i.length,1),a(t)}async function*S(e){let{o:n}=e;if("then"in n&&(n=await n),n instanceof Uint8Array)yield n,e.m=p(n,0),e.u=n.length;else{e.u=0;const t=n.getReader();for(;;){const{value:n,done:r}=await t.read();if(r)break;e.m=p(n,e.m),e.u+=n.length,yield n}}}function N(e){const n=i(16);return n.setUint32(0,1347094280),n.setUint32(4,e.m,1),n.setUint32(8,e.u,1),n.setUint32(12,e.u,1),a(n)}function A(e,n,t=0){const r=i(46);return r.setUint32(0,1347092738),r.setUint32(4,352523264),r.setUint16(8,2048|t),v(e.t,r,12),r.setUint32(16,e.m,1),r.setUint32(20,e.u,1),r.setUint32(24,e.u,1),r.setUint16(28,e.i.length,1),r.setUint16(40,33204,1),r.setUint32(42,n,1),a(r)}function I(e){return e instanceof File||e instanceof Response?[[e],[e]]:[[e.input,e.name,e.size],[e.input,e.lastModified]]}var R=e=>function(e){var n;let t=22;for(const r of e){if(!r.i)throw new Error("Every file must have a non-empty name.");if(isNaN(null!=(n=r.u)?n:NaN))throw new Error(`Missing size for file "${(new TextDecoder).decode(r.i)}".`);t+=2*r.i.length+r.u+92}return t}(function*(e){for(const n of e)yield d(...I(n)[0])}(e));return function(e,n={}){const t={"Content-Type":"application/zip","Content-Disposition":"attachment"};Number.isInteger(n.length)&&n.length>0&&(t["Content-Length"]=n.length),n.metadata&&(t["Content-Length"]=R(n.metadata));const r=function(e){var n;const t=e[Symbol.iterator in e?Symbol.iterator:Symbol.asyncIterator]();return{async next(){const e=await t.next();if(e.done)return e;const[n,r]=I(e.value);return{done:0,value:Object.assign(s(...r),d(...n))}},throw:null==(n=t.throw)?void 0:n.bind(t),[Symbol.asyncIterator](){return this}}}(e);return new Response(u(async function*(e,n){const t=[];let r=0,o=0;for await(const i of e){const e=B(i,n.buffersAreUTF8);yield h(i,e),yield i.i,yield*S(i),yield N(i),t.push(A(i,r,e)),t.push(i.i),o++,r+=46+i.i.length+i.u}let f=0;for(const e of t)yield e,f+=e.length;const s=i(22);s.setUint32(0,1347093766),s.setUint16(8,o,1),s.setUint16(10,o,1),s.setUint32(12,f,1),s.setUint32(16,r,1),yield a(s)}(r,n),r),{headers:t})}})();
var downloadZip=(()=>{"stream"in Blob.prototype||Object.defineProperty(Blob.prototype,"stream",{value(){return new Response(this).body}});var i=e=>new DataView(new ArrayBuffer(e)),a=e=>new Uint8Array(e.buffer||e),f=e=>(new TextEncoder).encode(String(e));function s(e,n){if(void 0===n||n instanceof Date||(n=new Date(n)),e instanceof File)return{t:n||new Date(e.lastModified),o:e.stream()};if(e instanceof Response)return{t:n||new Date(e.headers.get("Last-Modified")||Date.now()),o:e.body};if(void 0===n)n=new Date;else if(isNaN(n))throw new Error("Invalid modification date.");if("string"==typeof e)return{t:n,o:f(e)};if(e instanceof Blob)return{t:n,o:e.stream()};if(e instanceof Uint8Array||e instanceof ReadableStream)return{t:n,o:e};if(e instanceof ArrayBuffer||ArrayBuffer.isView(e))return{t:n,o:a(e)};if(Symbol.asyncIterator in e)return{t:n,o:u(e[Symbol.asyncIterator]())};throw new TypeError("Unsupported input format.")}function u(e,n=e){return new ReadableStream({async pull(n){let t=0;for(;n.desiredSize>t;){const r=await e.next();if(!r.value){n.close();break}{const e=l(r.value);n.enqueue(e),t+=e.byteLength}}},cancel(e){var t;null==(t=n.throw)||t.call(n,e)}})}function l(e){return"string"==typeof e?f(e):e instanceof Uint8Array?e:a(e)}function d(e,n,t){let[r,o]=function(e){return e?e instanceof Uint8Array?[e,1]:ArrayBuffer.isView(e)||e instanceof ArrayBuffer?[a(e),1]:[f(e),0]:[void 0,0]}(n);if(e instanceof File)return{i:w(r||f(e.name)),u:e.size,l:o};if(e instanceof Response){const n=e.headers.get("content-disposition"),i=n&&n.match(/;\s*filename\*?=["']?(.*?)["']?$/i),a=i&&i[1]||e.url&&new URL(e.url).pathname.split("/").findLast(Boolean),s=a&&decodeURIComponent(a),u=t||+e.headers.get("content-length");return{i:w(r||f(s)),u,l:o}}return r=w(r),"string"==typeof e?{i:r,u:f(e).length,l:o}:e instanceof Blob?{i:r,u:e.size,l:o}:e instanceof ArrayBuffer||ArrayBuffer.isView(e)?{i:r,u:e.byteLength,l:o}:{i:r,u:y(e,t),l:o}}function y(e,n){return n>-1?n:e?void 0:0}function w(e){if(!e||e.every((c=>47===c)))throw new Error("The file must have a name.");for(;47===e[e.length-1];)e=e.subarray(0,-1);return e}var b=new Uint32Array(256);for(let e=0;e<256;++e){let n=e;for(let e=0;e<8;++e)n=n>>>1^(1&n&&3988292384);b[e]=n}function p(e,n=0){n^=-1;for(var t=0,r=e.length;t<r;t++)n=n>>>8^b[255&n^e[t]];return(-1^n)>>>0}function v(e,n,t=0){const r=e.getSeconds()>>1|e.getMinutes()<<5|e.getHours()<<11,o=e.getDate()|e.getMonth()+1<<5|e.getFullYear()-1980<<9;n.setUint16(t,r,1),n.setUint16(t+2,o,1)}function B({i:e,l:n},t){return 8*(!n||(null!=t?t:function(e){try{D.decode(e)}catch(e){return 0}return 1}(e)))}var D=new TextDecoder("utf8",{fatal:1});function h(e,n=0){const t=i(30);return t.setUint32(0,1347093252),t.setUint32(4,335546368|n),v(e.t,t,10),t.setUint16(26,e.i.length,1),a(t)}async function*S(e){let{o:n}=e;if("then"in n&&(n=await n),n instanceof Uint8Array)yield n,e.m=p(n,0),e.u=n.length;else{e.u=0;const t=n.getReader();for(;;){const{value:n,done:r}=await t.read();if(r)break;e.m=p(n,e.m),e.u+=n.length,yield n}}}function A(e){const n=i(16);return n.setUint32(0,1347094280),n.setUint32(4,e.m,1),n.setUint32(8,e.u,1),n.setUint32(12,e.u,1),a(n)}function N(e,n,t=0){const r=i(46);return r.setUint32(0,1347092738),r.setUint32(4,352523264),r.setUint16(8,2048|t),v(e.t,r,12),r.setUint32(16,e.m,1),r.setUint32(20,e.u,1),r.setUint32(24,e.u,1),r.setUint16(28,e.i.length,1),r.setUint16(40,33204,1),r.setUint32(42,n,1),a(r)}function U(e){return e instanceof File||e instanceof Response?[[e],[e]]:[[e.input,e.name,e.size],[e.input,e.lastModified]]}var I=e=>function(e){var n;let t=22;for(const r of e){if(!r.i)throw new Error("Every file must have a non-empty name.");if(isNaN(null!=(n=r.u)?n:NaN))throw new Error(`Missing size for file "${(new TextDecoder).decode(r.i)}".`);t+=2*r.i.length+r.u+92}return t}(function*(e){for(const n of e)yield d(...U(n)[0])}(e));return function(e,n={}){const t={"Content-Type":"application/zip","Content-Disposition":"attachment"};Number.isInteger(n.length)&&n.length>0&&(t["Content-Length"]=n.length),n.metadata&&(t["Content-Length"]=I(n.metadata));const r=function(e){var n;const t=e[Symbol.iterator in e?Symbol.iterator:Symbol.asyncIterator]();return{async next(){const e=await t.next();if(e.done)return e;const[n,r]=U(e.value);return{done:0,value:Object.assign(s(...r),d(...n))}},throw:null==(n=t.throw)?void 0:n.bind(t),[Symbol.asyncIterator](){return this}}}(e);return new Response(u(async function*(e,n){const t=[];let r=0,o=0;for await(const i of e){const e=B(i,n.buffersAreUTF8);yield h(i,e),yield new Uint8Array(i.i),yield*S(i),yield A(i),t.push(N(i,r,e)),t.push(i.i),o++,r+=46+i.i.length+i.u}let f=0;for(const e of t)yield e,f+=e.length;const s=i(22);s.setUint32(0,1347093766),s.setUint16(8,o,1),s.setUint16(10,o,1),s.setUint32(12,f,1),s.setUint32(16,r,1),yield a(s)}(r,n),r),{headers:t})}})();