@zip.js/zip.js 2.6.33 → 2.6.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/z-worker-fflate.js +1 -1
  2. package/dist/z-worker-pako.js +1 -1
  3. package/dist/z-worker.js +1 -1
  4. package/dist/zip-fs-full.js +2479 -2364
  5. package/dist/zip-fs-full.min.js +1 -1
  6. package/dist/zip-fs.js +1236 -1121
  7. package/dist/zip-fs.min.js +1 -1
  8. package/dist/zip-full.js +1235 -1120
  9. package/dist/zip-full.min.js +1 -1
  10. package/dist/zip-no-worker-deflate.min.js +1 -1
  11. package/dist/zip-no-worker-inflate.min.js +1 -1
  12. package/dist/zip-no-worker.min.js +1 -1
  13. package/dist/zip.js +1236 -1121
  14. package/dist/zip.min.js +1 -1
  15. package/index-fflate.js +3 -1
  16. package/index.cjs +2479 -2364
  17. package/index.d.ts +33 -2
  18. package/index.js +3 -1
  19. package/lib/core/codec-pool.js +2 -2
  20. package/lib/core/codec-worker.js +321 -0
  21. package/lib/core/configuration.js +3 -3
  22. package/lib/core/constants.js +6 -5
  23. package/lib/core/io.js +64 -1
  24. package/lib/core/streams/aes-crypto-stream.js +2 -0
  25. package/lib/core/streams/codec-stream.js +60 -13
  26. package/lib/core/streams/codecs/sjcl.js +1 -1
  27. package/lib/core/streams/stream-adapter.js +55 -0
  28. package/lib/core/streams/zip-crypto-stream.js +1 -0
  29. package/lib/core/streams/zip-entry-stream.js +1 -0
  30. package/lib/core/util/stream-codec-shim.js +2 -0
  31. package/lib/core/z-worker-core.js +21 -11
  32. package/lib/core/zip-entry.js +2 -1
  33. package/lib/core/zip-fs-core.js +1 -0
  34. package/lib/core/zip-reader.js +7 -5
  35. package/lib/core/zip-writer.js +88 -42
  36. package/lib/z-worker-inline.js +1 -1
  37. package/lib/zip.js +1 -1
  38. package/package.json +5 -5
  39. package/tests/all/test-http-split-zip.js +37 -0
  40. package/tests/all/test-split-zip.js +25 -22
  41. package/tests/tests-data.js +2 -1
  42. package/lib/core/codec-interface.js +0 -115
  43. package/lib/core/codec-pool-worker.js +0 -293
package/index.d.ts CHANGED
@@ -7,6 +7,7 @@ declare global {
7
7
  *
8
8
  * @see {@link https://wicg.github.io/entries-api/#api-entry|specification}
9
9
  */
10
+ // deno-lint-ignore no-empty-interface
10
11
  interface FileSystemEntry { }
11
12
  }
12
13
 
@@ -141,6 +142,7 @@ interface WorkerConfiguration {
141
142
  * @param registerDataHandler The function called to handle the `data` events triggered by a third-party codec implementation.
142
143
  * @returns An instance containing classes compatible with `ZipDeflate` and `ZipInflate`.
143
144
  */
145
+ // deno-lint-ignore no-explicit-any
144
146
  export function initShimAsyncCodec(library: EventBasedZipLibrary, constructorOptions: any | null, registerDataHandler: registerDataHandler): ZipLibrary
145
147
 
146
148
  /**
@@ -367,11 +369,13 @@ export class Uint8ArrayReader extends Reader<Uint8Array> { }
367
369
  /**
368
370
  * Represents a `Reader` instance used to read data provided as an array of `Reader` instances (i.e. split zip files).
369
371
  */
372
+ // deno-lint-ignore no-explicit-any
370
373
  export class SplitZipReader extends Reader<Reader<any>[] | ReadableReader[] | ReadableStream[]> { }
371
374
 
372
375
  /**
373
376
  * Represents a URL stored into a `string`.
374
377
  */
378
+ // deno-lint-ignore no-empty-interface
375
379
  interface URLString extends String { }
376
380
 
377
381
  /**
@@ -538,6 +542,27 @@ export class Data64URIWriter extends Writer<string> {
538
542
  constructor(mimeString?: string)
539
543
  }
540
544
 
545
+ /**
546
+ * Represents a `Writer` instance used to retrieve the written data from a generator of `Writer` instances (i.e. split zip files).
547
+ */
548
+ export class SplitZipWriter implements DataProcessor, WritableWriter {
549
+ /**
550
+ * The `WritableStream` instance.
551
+ */
552
+ writable: WritableStream
553
+ /**
554
+ * Initializes the instance asynchronously
555
+ */
556
+ init(): Promise<void>
557
+ /**
558
+ * Creates the `SplitZipWriter` instance
559
+ *
560
+ * @param writerGenerator The MIME type of the content.
561
+ * @param maxSize The maximum size of the data written into `Writer` instances.
562
+ */
563
+ constructor(writerGenerator: AsyncGenerator<Writer<any> | WritableWriter | WritableStream, boolean>, maxSize: number)
564
+ }
565
+
541
566
  /**
542
567
  * Represents a `Writer` instance used to retrieve the written data as a `Uint8Array` instance.
543
568
  */
@@ -582,6 +607,7 @@ export class ZipReader<Type> {
582
607
  * @param reader The `Reader` instance used to read data.
583
608
  * @param options The options.
584
609
  */
610
+ // deno-lint-ignore no-explicit-any
585
611
  constructor(reader: Reader<Type> | ReadableReader | ReadableStream | Reader<any>[] | ReadableReader[] | ReadableStream[], options?: ZipReaderConstructorOptions)
586
612
  /**
587
613
  * The global comment of the zip file.
@@ -792,6 +818,10 @@ export interface Entry {
792
818
  * The external file attribute (raw).
793
819
  */
794
820
  externalFileAttribute: number
821
+ /**
822
+ * The number of the disk where the entry data starts.
823
+ */
824
+ diskNumberStart: number
795
825
  /**
796
826
  * Returns the content of the entry
797
827
  *
@@ -834,7 +864,7 @@ export class ZipWriter<Type> {
834
864
  * @param writer The `Writer` instance where the zip content will be written.
835
865
  * @param options The options.
836
866
  */
837
- constructor(writer: Writer<Type> | WritableWriter | WritableStream, options?: ZipWriterConstructorOptions)
867
+ constructor(writer: Writer<Type> | WritableWriter | WritableStream | SplitZipWriter | AsyncGenerator<Writer<any> | WritableWriter | WritableStream, boolean>, options?: ZipWriterConstructorOptions)
838
868
  /**
839
869
  * `true` if the zip contains at least one entry that has been partially written.
840
870
  */
@@ -1444,4 +1474,5 @@ export const ERR_INVALID_EXTRAFIELD_TYPE: string
1444
1474
  export const ERR_INVALID_EXTRAFIELD_DATA: string
1445
1475
  export const ERR_INVALID_ENCRYPTION_STRENGTH: string
1446
1476
  export const ERR_UNSUPPORTED_FORMAT: string
1447
- export const ERR_SPLIT_ZIP_FILE: string
1477
+ export const ERR_SPLIT_ZIP_FILE: string
1478
+ export const ERR_ITERATOR_COMPLETED_TOO_SOON: string
package/index.js CHANGED
@@ -55,6 +55,7 @@ export {
55
55
  Uint8ArrayWriter,
56
56
  Uint8ArrayReader,
57
57
  SplitZipReader,
58
+ SplitZipWriter,
58
59
  ERR_HTTP_RANGE,
59
60
  ERR_BAD_FORMAT,
60
61
  ERR_EOCDR_NOT_FOUND,
@@ -77,6 +78,7 @@ export {
77
78
  ERR_INVALID_EXTRAFIELD_DATA,
78
79
  ERR_INVALID_ENCRYPTION_STRENGTH,
79
80
  ERR_UNSUPPORTED_FORMAT,
80
- ERR_SPLIT_ZIP_FILE
81
+ ERR_SPLIT_ZIP_FILE,
82
+ ERR_ITERATOR_COMPLETED_TOO_SOON
81
83
  } from "./lib/zip-fs.js";
82
84
  export { getMimeType, terminateWorkers };
@@ -34,8 +34,8 @@ import {
34
34
  CODEC_DEFLATE,
35
35
  ERR_INVALID_SIGNATURE,
36
36
  ERR_INVALID_PASSWORD
37
- } from "./codec-interface.js";
38
- import { CodecWorker } from "./codec-pool-worker.js";
37
+ } from "./streams/codec-stream.js";
38
+ import { CodecWorker } from "./codec-worker.js";
39
39
 
40
40
  let pool = [];
41
41
  const pendingRequests = [];
@@ -0,0 +1,321 @@
1
+ /*
2
+ Copyright (c) 2022 Gildas Lormeau. All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in
12
+ the documentation and/or other materials provided with the distribution.
13
+
14
+ 3. The names of the authors may not be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
18
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
19
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
20
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ /* global Worker, URL, TransformStream, WritableStream */
30
+
31
+ import {
32
+ UNDEFINED_TYPE,
33
+ FUNCTION_TYPE
34
+ } from "./constants.js";
35
+ import {
36
+ CodecStream,
37
+ MESSAGE_EVENT_TYPE,
38
+ MESSAGE_START,
39
+ MESSAGE_PULL,
40
+ MESSAGE_DATA,
41
+ MESSAGE_ACK_DATA,
42
+ MESSAGE_CLOSE
43
+ } from "./streams/codec-stream.js";
44
+
45
+ // deno-lint-ignore valid-typeof
46
+ const WEB_WORKERS_SUPPORTED = typeof Worker != UNDEFINED_TYPE;
47
+
48
+ export {
49
+ CodecWorker
50
+ };
51
+
52
+ class CodecWorker {
53
+
54
+ constructor(workerData, stream, workerOptions, onTaskFinished) {
55
+ const { readable, writable } = stream;
56
+ const { options, config, streamOptions, useWebWorkers, transferStreams, scripts } = workerOptions;
57
+ const { signal } = streamOptions;
58
+ Object.assign(workerData, {
59
+ busy: true,
60
+ readable: readable.pipeThrough(new ReadableStreamHooks(readable, streamOptions, config), { signal }),
61
+ writable,
62
+ options: Object.assign({}, options),
63
+ scripts,
64
+ transferStreams,
65
+ terminate() {
66
+ const { worker, busy } = workerData;
67
+ if (worker && !busy) {
68
+ worker.terminate();
69
+ workerData.interface = null;
70
+ }
71
+ },
72
+ onTaskFinished() {
73
+ workerData.busy = false;
74
+ onTaskFinished(workerData);
75
+ }
76
+ });
77
+ return (useWebWorkers && WEB_WORKERS_SUPPORTED ? createWebWorkerInterface : createWorkerInterface)(workerData, config);
78
+ }
79
+ }
80
+
81
+ class ReadableStreamHooks extends TransformStream {
82
+
83
+ constructor(readableSource, { onstart, onprogress, size, onend }, { chunkSize }) {
84
+ let chunkOffset = 0;
85
+ super({
86
+ start() {
87
+ if (onstart) {
88
+ callHandler(onstart, size);
89
+ }
90
+ },
91
+ async transform(chunk, controller) {
92
+ chunkOffset += chunk.length;
93
+ if (onprogress) {
94
+ await callHandler(onprogress, chunkOffset, size);
95
+ }
96
+ controller.enqueue(chunk);
97
+ },
98
+ flush() {
99
+ readableSource.size = chunkOffset;
100
+ if (onend) {
101
+ callHandler(onend, chunkOffset);
102
+ }
103
+ }
104
+ }, { highWaterMark: 1, size: () => chunkSize });
105
+ }
106
+ }
107
+
108
+ async function callHandler(handler, ...parameters) {
109
+ try {
110
+ await handler(...parameters);
111
+ } catch (_error) {
112
+ // ignored
113
+ }
114
+ }
115
+
116
+ function createWorkerInterface(workerData, config) {
117
+ return {
118
+ run: () => runWorker(workerData, config)
119
+ };
120
+ }
121
+
122
+ function createWebWorkerInterface(workerData, { baseURL, chunkSize }) {
123
+ if (!workerData.interface) {
124
+ Object.assign(workerData, {
125
+ worker: getWebWorker(workerData.scripts[0], baseURL, workerData),
126
+ interface: {
127
+ run: () => runWebWorker(workerData, { chunkSize })
128
+ }
129
+ });
130
+ }
131
+ return workerData.interface;
132
+ }
133
+
134
+ async function runWorker({ options, readable, writable, onTaskFinished }, config) {
135
+ const codecStream = new CodecStream(options, config);
136
+ try {
137
+ await readable.pipeThrough(codecStream).pipeTo(writable, { preventClose: true, preventAbort: true });
138
+ const {
139
+ signature,
140
+ size
141
+ } = codecStream;
142
+ return {
143
+ signature,
144
+ size
145
+ };
146
+ } finally {
147
+ onTaskFinished();
148
+ }
149
+ }
150
+
151
+ async function runWebWorker(workerData, config) {
152
+ let resolveResult, rejectResult;
153
+ const result = new Promise((resolve, reject) => {
154
+ resolveResult = resolve;
155
+ rejectResult = reject;
156
+ });
157
+ Object.assign(workerData, {
158
+ reader: null,
159
+ writer: null,
160
+ resolveResult,
161
+ rejectResult,
162
+ result
163
+ });
164
+ const { readable, options } = workerData;
165
+ const { writable, closed } = detectClosedStream(workerData.writable);
166
+ const streamsTransferred = sendMessage({
167
+ type: MESSAGE_START,
168
+ scripts: workerData.scripts.slice(1),
169
+ options,
170
+ config,
171
+ readable,
172
+ writable
173
+ }, workerData);
174
+ if (!streamsTransferred) {
175
+ Object.assign(workerData, {
176
+ reader: readable.getReader(),
177
+ writer: writable.getWriter()
178
+ });
179
+ }
180
+ const resultValue = await result;
181
+ try {
182
+ await writable.close();
183
+ } catch (_error) {
184
+ // ignored
185
+ }
186
+ await closed;
187
+ return resultValue;
188
+ }
189
+
190
+ function detectClosedStream(writableSource) {
191
+ const writer = writableSource.getWriter();
192
+ let resolveStreamClosed;
193
+ const closed = new Promise(resolve => resolveStreamClosed = resolve);
194
+ const writable = new WritableStream({
195
+ async write(chunk) {
196
+ await writer.ready;
197
+ await writer.write(chunk);
198
+ },
199
+ close() {
200
+ writer.releaseLock();
201
+ resolveStreamClosed();
202
+ },
203
+ abort(reason) {
204
+ writer.abort(reason);
205
+ }
206
+ });
207
+ return { writable, closed };
208
+ }
209
+
210
+ let classicWorkersSupported = true;
211
+ let transferStreamsSupported = true;
212
+
213
+ function getWebWorker(url, baseURL, workerData) {
214
+ const workerOptions = { type: "module" };
215
+ let scriptUrl, worker;
216
+ if (typeof url == FUNCTION_TYPE) {
217
+ url = url();
218
+ }
219
+ try {
220
+ scriptUrl = new URL(url, baseURL);
221
+ } catch (_error) {
222
+ scriptUrl = url;
223
+ }
224
+ if (classicWorkersSupported) {
225
+ try {
226
+ worker = new Worker(scriptUrl);
227
+ } catch (_error) {
228
+ classicWorkersSupported = false;
229
+ worker = new Worker(scriptUrl, workerOptions);
230
+ }
231
+ } else {
232
+ worker = new Worker(scriptUrl, workerOptions);
233
+ }
234
+ worker.addEventListener(MESSAGE_EVENT_TYPE, event => onMessage(event, workerData));
235
+ return worker;
236
+ }
237
+
238
+ function sendMessage(message, { worker, writer, onTaskFinished, transferStreams }) {
239
+ try {
240
+ let { data, readable, writable } = message;
241
+ const transferrables = [];
242
+ if (data) {
243
+ const { buffer, length } = data;
244
+ if (length != buffer.byteLength) {
245
+ data = new Uint8Array(data);
246
+ }
247
+ message.data = data.buffer;
248
+ transferrables.push(message.data);
249
+ }
250
+ if (transferStreams && transferStreamsSupported) {
251
+ if (readable) {
252
+ transferrables.push(readable);
253
+ }
254
+ if (writable) {
255
+ transferrables.push(writable);
256
+ }
257
+ } else {
258
+ message.readable = message.writable = null;
259
+ }
260
+ if (transferrables.length) {
261
+ try {
262
+ worker.postMessage(message, transferrables);
263
+ return true;
264
+ } catch (_error) {
265
+ transferStreamsSupported = false;
266
+ message.readable = message.writable = null;
267
+ worker.postMessage(message);
268
+ }
269
+ } else {
270
+ worker.postMessage(message);
271
+ }
272
+ } catch (error) {
273
+ if (writer) {
274
+ writer.releaseLock();
275
+ }
276
+ onTaskFinished();
277
+ throw error;
278
+ }
279
+ }
280
+
281
+ async function onMessage(event, workerData) {
282
+ const message = event.data;
283
+ const { reader, writer, resolveResult, rejectResult, onTaskFinished } = workerData;
284
+ const { type, data, messageId, result } = message;
285
+ const reponseError = message.error;
286
+ try {
287
+ if (reponseError) {
288
+ const { message, stack, code, name } = reponseError;
289
+ const error = new Error(message);
290
+ Object.assign(error, { stack, code, name });
291
+ close(error);
292
+ } else {
293
+ if (type == MESSAGE_PULL) {
294
+ const { value, done } = await reader.read();
295
+ sendMessage({ type: MESSAGE_DATA, data: value, done, messageId }, workerData);
296
+ }
297
+ if (type == MESSAGE_DATA) {
298
+ await writer.ready;
299
+ await writer.write(new Uint8Array(data));
300
+ sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
301
+ }
302
+ if (type == MESSAGE_CLOSE) {
303
+ close(null, result);
304
+ }
305
+ }
306
+ } catch (error) {
307
+ close(error);
308
+ }
309
+
310
+ function close(error, result) {
311
+ if (error) {
312
+ rejectResult(error);
313
+ } else {
314
+ resolveResult(result);
315
+ }
316
+ if (writer) {
317
+ writer.releaseLock();
318
+ }
319
+ onTaskFinished();
320
+ }
321
+ }
@@ -28,11 +28,11 @@
28
28
 
29
29
  /* global navigator, CompressionStream, DecompressionStream */
30
30
 
31
- import { getCodecStreamClass } from "./codec-interface.js";
32
31
  import {
33
32
  UNDEFINED_VALUE,
34
33
  UNDEFINED_TYPE
35
34
  } from "./constants.js";
35
+ import { StreamAdapter } from "./streams/stream-adapter.js";
36
36
 
37
37
  const MINIMUM_CHUNK_SIZE = 64;
38
38
  let maxWorkers = 2;
@@ -91,10 +91,10 @@ function configure(configuration) {
91
91
  setIfDefined("useCompressionStream", useCompressionStream);
92
92
  setIfDefined("useWebWorkers", useWebWorkers);
93
93
  if (Deflate) {
94
- config.CompressionStream = getCodecStreamClass(Deflate);
94
+ config.CompressionStream = new StreamAdapter(Deflate);
95
95
  }
96
96
  if (Inflate) {
97
- config.DecompressionStream = getCodecStreamClass(Inflate);
97
+ config.DecompressionStream = new StreamAdapter(Inflate);
98
98
  }
99
99
  setIfDefined("CompressionStream", CompressionStream);
100
100
  setIfDefined("DecompressionStream", DecompressionStream);
@@ -33,7 +33,8 @@ const COMPRESSION_METHOD_STORE = 0x00;
33
33
  const COMPRESSION_METHOD_AES = 0x63;
34
34
 
35
35
  const LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;
36
- const DATA_DESCRIPTOR_RECORD_SIGNATURE = 0x08074b50;
36
+ const SPLIT_ZIP_FILE_SIGNATURE = 0x08074b50;
37
+ const DATA_DESCRIPTOR_RECORD_SIGNATURE = SPLIT_ZIP_FILE_SIGNATURE;
37
38
  const CENTRAL_FILE_HEADER_SIGNATURE = 0x02014b50;
38
39
  const END_OF_CENTRAL_DIR_SIGNATURE = 0x06054b50;
39
40
  const ZIP64_END_OF_CENTRAL_DIR_SIGNATURE = 0x06064b50;
@@ -43,8 +44,6 @@ const ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH = 20;
43
44
  const ZIP64_END_OF_CENTRAL_DIR_LENGTH = 56;
44
45
  const ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH = END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LENGTH;
45
46
 
46
- const ZIP64_TOTAL_NUMBER_OF_DISKS = 1;
47
-
48
47
  const EXTRAFIELD_TYPE_ZIP64 = 0x0001;
49
48
  const EXTRAFIELD_TYPE_AES = 0x9901;
50
49
  const EXTRAFIELD_TYPE_NTFS = 0x000a;
@@ -70,6 +69,7 @@ const MIN_DATE = new Date(1980, 0, 1);
70
69
 
71
70
  const UNDEFINED_VALUE = undefined;
72
71
  const UNDEFINED_TYPE = "undefined";
72
+ const FUNCTION_TYPE = "function";
73
73
 
74
74
  export {
75
75
  MAX_32_BITS,
@@ -77,6 +77,7 @@ export {
77
77
  COMPRESSION_METHOD_DEFLATE,
78
78
  COMPRESSION_METHOD_STORE,
79
79
  COMPRESSION_METHOD_AES,
80
+ SPLIT_ZIP_FILE_SIGNATURE,
80
81
  LOCAL_FILE_HEADER_SIGNATURE,
81
82
  DATA_DESCRIPTOR_RECORD_SIGNATURE,
82
83
  CENTRAL_FILE_HEADER_SIGNATURE,
@@ -94,7 +95,6 @@ export {
94
95
  ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH,
95
96
  ZIP64_END_OF_CENTRAL_DIR_LENGTH,
96
97
  ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH,
97
- ZIP64_TOTAL_NUMBER_OF_DISKS,
98
98
  BITFLAG_ENCRYPTED,
99
99
  BITFLAG_LEVEL,
100
100
  BITFLAG_DATA_DESCRIPTOR,
@@ -107,5 +107,6 @@ export {
107
107
  MIN_DATE,
108
108
  MAX_DATE,
109
109
  UNDEFINED_VALUE,
110
- UNDEFINED_TYPE
110
+ UNDEFINED_TYPE,
111
+ FUNCTION_TYPE
111
112
  };
package/lib/core/io.js CHANGED
@@ -27,9 +27,11 @@
27
27
  */
28
28
 
29
29
  /* global Blob, atob, btoa, XMLHttpRequest, URL, fetch, ReadableStream, WritableStream, FileReader, TransformStream, Response */
30
+ // deno-lint-ignore-file no-this-alias
30
31
 
31
32
  const ERR_HTTP_STATUS = "HTTP error ";
32
33
  const ERR_HTTP_RANGE = "HTTP Range not supported";
34
+ const ERR_ITERATOR_COMPLETED_TOO_SOON = "Writer iterator completed too soon";
33
35
 
34
36
  const CONTENT_TYPE_TEXT_PLAIN = "text/plain";
35
37
  const HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
@@ -565,6 +567,65 @@ class SplitZipReader extends Reader {
565
567
  }
566
568
  }
567
569
 
570
+ class SplitZipWriter extends Stream {
571
+
572
+ constructor(writerGenerator, maxSize = 4294967296) {
573
+ super();
574
+ const writer = this;
575
+ Object.assign(writer, {
576
+ diskNumber: 0,
577
+ diskOffset: 0,
578
+ size: 0,
579
+ availableSize: maxSize
580
+ });
581
+ let currentWriter, diskWritable, diskWriter;
582
+ const writable = new WritableStream({
583
+ async write(chunk) {
584
+ if (!diskWriter) {
585
+ const { value, done } = await writerGenerator.next();
586
+ if (done && !value) {
587
+ throw new Error(ERR_ITERATOR_COMPLETED_TOO_SOON);
588
+ } else {
589
+ currentWriter = value;
590
+ currentWriter.size = 0;
591
+ diskWritable = value.writable;
592
+ diskWriter = diskWritable.getWriter();
593
+ }
594
+ await this.write(chunk);
595
+ } else if (diskWriter && currentWriter.size + chunk.length > maxSize) {
596
+ await diskWriter.ready;
597
+ const chunkLength = maxSize - currentWriter.size;
598
+ await diskWriter.write(chunk.slice(0, chunkLength));
599
+ chunk = chunk.slice(chunkLength);
600
+ currentWriter.size += chunkLength;
601
+ writer.size += chunkLength;
602
+ writer.diskOffset += diskWritable.size = currentWriter.size;
603
+ writer.diskNumber++;
604
+ await diskWriter.close();
605
+ diskWriter = null;
606
+ await this.write(chunk);
607
+ } else {
608
+ await diskWriter.ready;
609
+ await diskWriter.write(chunk);
610
+ currentWriter.size += chunk.length;
611
+ writer.size += chunk.length;
612
+ }
613
+ writer.availableSize = maxSize - currentWriter.size;
614
+ },
615
+ async close() {
616
+ await diskWriter.ready;
617
+ diskWritable.size = currentWriter.size;
618
+ await diskWriter.close();
619
+ }
620
+ });
621
+ Object.defineProperty(writer, PROPERTY_NAME_WRITABLE, {
622
+ get() {
623
+ return writable;
624
+ }
625
+ });
626
+ }
627
+ }
628
+
568
629
  function isHttpFamily(url) {
569
630
  const { baseURL } = getConfiguration();
570
631
  const { protocol } = new URL(url, baseURL);
@@ -597,5 +658,7 @@ export {
597
658
  HttpReader,
598
659
  HttpRangeReader,
599
660
  SplitZipReader,
600
- ERR_HTTP_RANGE
661
+ SplitZipWriter,
662
+ ERR_HTTP_RANGE,
663
+ ERR_ITERATOR_COMPLETED_TOO_SOON
601
664
  };
@@ -56,6 +56,7 @@ const SIGNATURE_LENGTH = 10;
56
56
  const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
57
57
  const UNDEFINED_TYPE = "undefined";
58
58
  const FUNCTION_TYPE = "function";
59
+ // deno-lint-ignore valid-typeof
59
60
  const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
60
61
  const subtle = CRYPTO_API_SUPPORTED && crypto.subtle;
61
62
  const SUBTLE_API_SUPPORTED = CRYPTO_API_SUPPORTED && typeof subtle != UNDEFINED_TYPE;
@@ -132,6 +133,7 @@ class AESDecryptionStream extends TransformStream {
132
133
  class AESEncryptionStream extends TransformStream {
133
134
 
134
135
  constructor(password, strength) {
136
+ // deno-lint-ignore prefer-const
135
137
  let stream;
136
138
  super({
137
139
  start() {
@@ -34,25 +34,72 @@
34
34
  */
35
35
 
36
36
  /* global TransformStream */
37
+ // deno-lint-ignore-file no-this-alias
38
+
39
+ import {
40
+ ERR_INVALID_PASSWORD,
41
+ ERR_INVALID_SIGNATURE,
42
+ InflateStream,
43
+ DeflateStream
44
+ } from "./zip-entry-stream.js";
45
+
46
+ const MESSAGE_EVENT_TYPE = "message";
47
+ const MESSAGE_START = "start";
48
+ const MESSAGE_PULL = "pull";
49
+ const MESSAGE_DATA = "data";
50
+ const MESSAGE_ACK_DATA = "ack";
51
+ const MESSAGE_CLOSE = "close";
52
+ const CODEC_DEFLATE = "deflate";
53
+ const CODEC_INFLATE = "inflate";
54
+
55
+ export {
56
+ CODEC_DEFLATE,
57
+ CODEC_INFLATE,
58
+ MESSAGE_EVENT_TYPE,
59
+ MESSAGE_START,
60
+ MESSAGE_PULL,
61
+ MESSAGE_DATA,
62
+ MESSAGE_ACK_DATA,
63
+ MESSAGE_CLOSE,
64
+ ERR_INVALID_PASSWORD,
65
+ ERR_INVALID_SIGNATURE,
66
+ CodecStream
67
+ };
37
68
 
38
69
  class CodecStream extends TransformStream {
39
70
 
40
- constructor(Codec, options) {
41
- const codec = new Codec(options);
42
- super({
71
+ constructor(options, config) {
72
+ super({});
73
+ const codec = this;
74
+ const { codecType } = options;
75
+ let Stream;
76
+ if (codecType.startsWith(CODEC_DEFLATE)) {
77
+ Stream = DeflateStream;
78
+ } else if (codecType.startsWith(CODEC_INFLATE)) {
79
+ Stream = InflateStream;
80
+ }
81
+ let size = 0;
82
+ const stream = new Stream(options, config);
83
+ const readable = super.readable;
84
+ const transformStream = new TransformStream({
43
85
  transform(chunk, controller) {
44
- controller.enqueue(codec.append(chunk));
45
- },
46
- flush(controller) {
47
- const chunk = codec.flush();
48
- if (chunk) {
86
+ if (chunk && chunk.length) {
87
+ size += chunk.length;
49
88
  controller.enqueue(chunk);
50
89
  }
90
+ },
91
+ flush() {
92
+ const { signature } = stream;
93
+ Object.assign(codec, {
94
+ signature,
95
+ size
96
+ });
97
+ }
98
+ });
99
+ Object.defineProperty(codec, "readable", {
100
+ get() {
101
+ return readable.pipeThrough(stream).pipeThrough(transformStream);
51
102
  }
52
103
  });
53
104
  }
54
- }
55
-
56
- export {
57
- CodecStream
58
- };
105
+ }