@cj-tech-master/excelts 4.2.0 → 4.2.1-canary.20260111102127.f808a37
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.
- package/THIRD_PARTY_NOTICES.md +0 -31
- package/dist/browser/index.browser.d.ts +1 -0
- package/dist/browser/index.browser.js +12 -0
- package/dist/{types/modules/archive → browser/modules/archive/compression}/compress.base.d.ts +1 -0
- package/dist/browser/modules/archive/{compress.base.js → compression/compress.base.js} +2 -1
- package/dist/{types/modules/archive → browser/modules/archive/compression}/compress.browser.d.ts +10 -8
- package/dist/{esm/modules/archive → browser/modules/archive/compression}/compress.browser.js +18 -19
- package/dist/browser/modules/archive/{compress.d.ts → compression/compress.d.ts} +2 -2
- package/dist/browser/modules/archive/{compress.js → compression/compress.js} +1 -1
- package/dist/browser/modules/archive/{crc32.browser.d.ts → compression/crc32.browser.d.ts} +1 -1
- package/dist/browser/modules/archive/{crc32.d.ts → compression/crc32.d.ts} +1 -1
- package/dist/browser/modules/archive/{crc32.js → compression/crc32.js} +1 -1
- package/dist/browser/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
- package/dist/browser/modules/archive/{streaming-compress.browser.d.ts → compression/streaming-compress.browser.d.ts} +2 -2
- package/dist/browser/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
- package/dist/browser/modules/archive/{streaming-compress.d.ts → compression/streaming-compress.d.ts} +2 -2
- package/dist/browser/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
- package/dist/browser/modules/archive/defaults.d.ts +1 -0
- package/dist/browser/modules/archive/defaults.js +6 -3
- package/dist/browser/modules/archive/index.base.d.ts +4 -4
- package/dist/browser/modules/archive/index.base.js +3 -6
- package/dist/browser/modules/archive/index.browser.d.ts +3 -4
- package/dist/browser/modules/archive/index.browser.js +3 -7
- package/dist/browser/modules/archive/index.d.ts +3 -4
- package/dist/browser/modules/archive/index.js +3 -5
- package/dist/browser/modules/archive/internal/byte-queue.d.ts +33 -0
- package/dist/browser/modules/archive/internal/byte-queue.js +407 -0
- package/dist/browser/modules/archive/io/archive-sink.d.ts +9 -0
- package/dist/browser/modules/archive/io/archive-sink.js +77 -0
- package/dist/browser/modules/archive/io/archive-source.d.ts +8 -0
- package/dist/browser/modules/archive/io/archive-source.js +107 -0
- package/dist/browser/modules/archive/{extract.d.ts → unzip/extract.d.ts} +2 -2
- package/dist/browser/modules/archive/unzip/index.d.ts +40 -0
- package/dist/browser/modules/archive/unzip/index.js +164 -0
- package/dist/browser/modules/archive/{parse.base.d.ts → unzip/stream.base.d.ts} +58 -3
- package/dist/browser/modules/archive/unzip/stream.base.js +1022 -0
- package/dist/browser/modules/archive/{parse.browser.d.ts → unzip/stream.browser.d.ts} +1 -1
- package/dist/browser/modules/archive/{parse.browser.js → unzip/stream.browser.js} +376 -110
- package/dist/browser/modules/archive/{parse.d.ts → unzip/stream.d.ts} +2 -2
- package/dist/{esm/modules/archive/parse.js → browser/modules/archive/unzip/stream.js} +7 -6
- package/dist/{types/modules/archive → browser/modules/archive/unzip}/zip-parser.d.ts +1 -1
- package/dist/{esm/modules/archive → browser/modules/archive/unzip}/zip-parser.js +38 -24
- package/dist/browser/modules/archive/utils/async-queue.d.ts +7 -0
- package/dist/browser/modules/archive/utils/async-queue.js +103 -0
- package/dist/browser/modules/archive/utils/bytes.js +16 -16
- package/dist/browser/modules/archive/utils/compressibility.d.ts +10 -0
- package/dist/browser/modules/archive/utils/compressibility.js +57 -0
- package/dist/browser/modules/archive/utils/parse-buffer.js +21 -23
- package/dist/browser/modules/archive/utils/pattern-scanner.d.ts +21 -0
- package/dist/browser/modules/archive/utils/pattern-scanner.js +27 -0
- package/dist/browser/modules/archive/utils/timestamps.js +62 -1
- package/dist/browser/modules/archive/utils/zip-extra-fields.d.ts +1 -1
- package/dist/browser/modules/archive/utils/zip-extra-fields.js +26 -14
- package/dist/browser/modules/archive/zip/index.d.ts +42 -0
- package/dist/browser/modules/archive/zip/index.js +157 -0
- package/dist/browser/modules/archive/{streaming-zip.d.ts → zip/stream.d.ts} +28 -5
- package/dist/browser/modules/archive/{streaming-zip.js → zip/stream.js} +192 -48
- package/dist/browser/modules/archive/zip/zip-bytes.d.ts +73 -0
- package/dist/browser/modules/archive/zip/zip-bytes.js +239 -0
- package/dist/{esm/modules/archive → browser/modules/archive/zip}/zip-entry-metadata.js +3 -3
- package/dist/browser/modules/archive/{zip-records.d.ts → zip-spec/zip-records.d.ts} +20 -0
- package/dist/browser/modules/archive/zip-spec/zip-records.js +126 -0
- package/dist/browser/modules/excel/form-control.d.ts +2 -0
- package/dist/browser/modules/excel/form-control.js +54 -16
- package/dist/browser/modules/excel/stream/workbook-reader.browser.js +1 -1
- package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
- package/dist/browser/modules/excel/stream/workbook-writer.browser.js +1 -1
- package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +17 -3
- package/dist/browser/modules/excel/xlsx/xlsx.browser.js +3 -6
- package/dist/browser/modules/excel/xlsx/xlsx.js +1 -1
- package/dist/browser/modules/stream/streams.browser.d.ts +28 -28
- package/dist/browser/modules/stream/streams.browser.js +850 -697
- package/dist/browser/modules/stream/streams.js +140 -58
- package/dist/cjs/modules/archive/{compress.base.js → compression/compress.base.js} +2 -1
- package/dist/cjs/modules/archive/{compress.browser.js → compression/compress.browser.js} +18 -19
- package/dist/cjs/modules/archive/{compress.js → compression/compress.js} +1 -1
- package/dist/cjs/modules/archive/{crc32.js → compression/crc32.js} +1 -1
- package/dist/cjs/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
- package/dist/cjs/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
- package/dist/cjs/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
- package/dist/cjs/modules/archive/defaults.js +7 -4
- package/dist/cjs/modules/archive/index.base.js +9 -19
- package/dist/cjs/modules/archive/index.browser.js +4 -10
- package/dist/cjs/modules/archive/index.js +4 -8
- package/dist/cjs/modules/archive/internal/byte-queue.js +411 -0
- package/dist/cjs/modules/archive/io/archive-sink.js +82 -0
- package/dist/cjs/modules/archive/io/archive-source.js +114 -0
- package/dist/cjs/modules/archive/unzip/index.js +170 -0
- package/dist/cjs/modules/archive/unzip/stream.base.js +1044 -0
- package/dist/cjs/modules/archive/{parse.browser.js → unzip/stream.browser.js} +377 -111
- package/dist/cjs/modules/archive/{parse.js → unzip/stream.js} +9 -8
- package/dist/cjs/modules/archive/{zip-parser.js → unzip/zip-parser.js} +47 -33
- package/dist/cjs/modules/archive/utils/async-queue.js +106 -0
- package/dist/cjs/modules/archive/utils/bytes.js +16 -16
- package/dist/cjs/modules/archive/utils/compressibility.js +60 -0
- package/dist/cjs/modules/archive/utils/parse-buffer.js +21 -23
- package/dist/cjs/modules/archive/utils/pattern-scanner.js +31 -0
- package/dist/cjs/modules/archive/utils/timestamps.js +64 -3
- package/dist/cjs/modules/archive/utils/zip-extra-fields.js +26 -14
- package/dist/cjs/modules/archive/zip/index.js +162 -0
- package/dist/cjs/modules/archive/{streaming-zip.js → zip/stream.js} +194 -50
- package/dist/cjs/modules/archive/zip/zip-bytes.js +242 -0
- package/dist/cjs/modules/archive/{zip-entry-metadata.js → zip/zip-entry-metadata.js} +5 -5
- package/dist/cjs/modules/archive/zip-spec/zip-records.js +136 -0
- package/dist/cjs/modules/excel/form-control.js +54 -16
- package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +2 -2
- package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +4 -4
- package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +17 -3
- package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +6 -9
- package/dist/cjs/modules/excel/xlsx/xlsx.js +2 -2
- package/dist/cjs/modules/stream/streams.browser.js +850 -697
- package/dist/cjs/modules/stream/streams.js +140 -58
- package/dist/esm/index.browser.js +12 -0
- package/dist/esm/modules/archive/{compress.base.js → compression/compress.base.js} +2 -1
- package/dist/{browser/modules/archive → esm/modules/archive/compression}/compress.browser.js +18 -19
- package/dist/esm/modules/archive/{compress.js → compression/compress.js} +1 -1
- package/dist/esm/modules/archive/{crc32.js → compression/crc32.js} +1 -1
- package/dist/esm/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
- package/dist/esm/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
- package/dist/esm/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
- package/dist/esm/modules/archive/defaults.js +6 -3
- package/dist/esm/modules/archive/index.base.js +3 -6
- package/dist/esm/modules/archive/index.browser.js +3 -7
- package/dist/esm/modules/archive/index.js +3 -5
- package/dist/esm/modules/archive/internal/byte-queue.js +407 -0
- package/dist/esm/modules/archive/io/archive-sink.js +77 -0
- package/dist/esm/modules/archive/io/archive-source.js +107 -0
- package/dist/esm/modules/archive/unzip/index.js +164 -0
- package/dist/esm/modules/archive/unzip/stream.base.js +1022 -0
- package/dist/esm/modules/archive/{parse.browser.js → unzip/stream.browser.js} +376 -110
- package/dist/{browser/modules/archive/parse.js → esm/modules/archive/unzip/stream.js} +7 -6
- package/dist/{browser/modules/archive → esm/modules/archive/unzip}/zip-parser.js +38 -24
- package/dist/esm/modules/archive/utils/async-queue.js +103 -0
- package/dist/esm/modules/archive/utils/bytes.js +16 -16
- package/dist/esm/modules/archive/utils/compressibility.js +57 -0
- package/dist/esm/modules/archive/utils/parse-buffer.js +21 -23
- package/dist/esm/modules/archive/utils/pattern-scanner.js +27 -0
- package/dist/esm/modules/archive/utils/timestamps.js +62 -1
- package/dist/esm/modules/archive/utils/zip-extra-fields.js +26 -14
- package/dist/esm/modules/archive/zip/index.js +157 -0
- package/dist/esm/modules/archive/{streaming-zip.js → zip/stream.js} +192 -48
- package/dist/esm/modules/archive/zip/zip-bytes.js +239 -0
- package/dist/{browser/modules/archive → esm/modules/archive/zip}/zip-entry-metadata.js +3 -3
- package/dist/esm/modules/archive/zip-spec/zip-records.js +126 -0
- package/dist/esm/modules/excel/form-control.js +54 -16
- package/dist/esm/modules/excel/stream/workbook-reader.browser.js +1 -1
- package/dist/esm/modules/excel/stream/workbook-writer.browser.js +1 -1
- package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +17 -3
- package/dist/esm/modules/excel/xlsx/xlsx.browser.js +3 -6
- package/dist/esm/modules/excel/xlsx/xlsx.js +1 -1
- package/dist/esm/modules/stream/streams.browser.js +850 -697
- package/dist/esm/modules/stream/streams.js +140 -58
- package/dist/iife/THIRD_PARTY_NOTICES.md +81 -0
- package/dist/iife/excelts.iife.js +4777 -2863
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +103 -31
- package/dist/types/index.browser.d.ts +1 -0
- package/dist/{browser/modules/archive → types/modules/archive/compression}/compress.base.d.ts +1 -0
- package/dist/{browser/modules/archive → types/modules/archive/compression}/compress.browser.d.ts +10 -8
- package/dist/types/modules/archive/{streaming-compress.browser.d.ts → compression/streaming-compress.browser.d.ts} +1 -1
- package/dist/types/modules/archive/defaults.d.ts +1 -0
- package/dist/types/modules/archive/index.base.d.ts +4 -4
- package/dist/types/modules/archive/index.browser.d.ts +3 -4
- package/dist/types/modules/archive/index.d.ts +3 -4
- package/dist/types/modules/archive/internal/byte-queue.d.ts +33 -0
- package/dist/types/modules/archive/io/archive-sink.d.ts +9 -0
- package/dist/types/modules/archive/io/archive-source.d.ts +8 -0
- package/dist/types/modules/archive/unzip/index.d.ts +40 -0
- package/dist/types/modules/archive/{parse.base.d.ts → unzip/stream.base.d.ts} +60 -5
- package/dist/types/modules/archive/{parse.browser.d.ts → unzip/stream.browser.d.ts} +2 -2
- package/dist/types/modules/archive/{parse.d.ts → unzip/stream.d.ts} +3 -3
- package/dist/{browser/modules/archive → types/modules/archive/unzip}/zip-parser.d.ts +1 -1
- package/dist/types/modules/archive/utils/async-queue.d.ts +7 -0
- package/dist/types/modules/archive/utils/compressibility.d.ts +10 -0
- package/dist/types/modules/archive/utils/pattern-scanner.d.ts +21 -0
- package/dist/types/modules/archive/utils/zip-extra-fields.d.ts +1 -1
- package/dist/types/modules/archive/zip/index.d.ts +42 -0
- package/dist/types/modules/archive/{streaming-zip.d.ts → zip/stream.d.ts} +29 -6
- package/dist/types/modules/archive/zip/zip-bytes.d.ts +73 -0
- package/dist/types/modules/archive/{zip-entry-metadata.d.ts → zip/zip-entry-metadata.d.ts} +1 -1
- package/dist/types/modules/archive/{zip-records.d.ts → zip-spec/zip-records.d.ts} +20 -0
- package/dist/types/modules/excel/form-control.d.ts +2 -0
- package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
- package/dist/types/modules/stream/streams.browser.d.ts +28 -28
- package/package.json +10 -6
- package/dist/browser/modules/archive/byte-queue.d.ts +0 -18
- package/dist/browser/modules/archive/byte-queue.js +0 -125
- package/dist/browser/modules/archive/parse.base.js +0 -610
- package/dist/browser/modules/archive/utils/zip-extra.d.ts +0 -18
- package/dist/browser/modules/archive/utils/zip-extra.js +0 -68
- package/dist/browser/modules/archive/zip-builder.d.ts +0 -117
- package/dist/browser/modules/archive/zip-builder.js +0 -292
- package/dist/browser/modules/archive/zip-constants.d.ts +0 -18
- package/dist/browser/modules/archive/zip-constants.js +0 -23
- package/dist/browser/modules/archive/zip-records.js +0 -84
- package/dist/cjs/modules/archive/byte-queue.js +0 -129
- package/dist/cjs/modules/archive/parse.base.js +0 -632
- package/dist/cjs/modules/archive/utils/zip-extra.js +0 -74
- package/dist/cjs/modules/archive/zip-builder.js +0 -297
- package/dist/cjs/modules/archive/zip-constants.js +0 -26
- package/dist/cjs/modules/archive/zip-records.js +0 -90
- package/dist/esm/modules/archive/byte-queue.js +0 -125
- package/dist/esm/modules/archive/parse.base.js +0 -610
- package/dist/esm/modules/archive/utils/zip-extra.js +0 -68
- package/dist/esm/modules/archive/zip-builder.js +0 -292
- package/dist/esm/modules/archive/zip-constants.js +0 -23
- package/dist/esm/modules/archive/zip-records.js +0 -84
- package/dist/types/modules/archive/byte-queue.d.ts +0 -18
- package/dist/types/modules/archive/utils/zip-extra.d.ts +0 -18
- package/dist/types/modules/archive/zip-builder.d.ts +0 -117
- package/dist/types/modules/archive/zip-constants.d.ts +0 -18
- /package/dist/browser/modules/archive/{crc32.base.d.ts → compression/crc32.base.d.ts} +0 -0
- /package/dist/browser/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
- /package/dist/browser/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
- /package/dist/browser/modules/archive/{deflate-fallback.d.ts → compression/deflate-fallback.d.ts} +0 -0
- /package/dist/browser/modules/archive/{streaming-compress.base.d.ts → compression/streaming-compress.base.d.ts} +0 -0
- /package/dist/browser/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
- /package/dist/browser/modules/archive/{extract.js → unzip/extract.js} +0 -0
- /package/dist/browser/modules/archive/{zip-entry-metadata.d.ts → zip/zip-entry-metadata.d.ts} +0 -0
- /package/dist/browser/modules/archive/{zip-entry-info.d.ts → zip-spec/zip-entry-info.d.ts} +0 -0
- /package/dist/browser/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
- /package/dist/cjs/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
- /package/dist/cjs/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
- /package/dist/cjs/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
- /package/dist/cjs/modules/archive/{extract.js → unzip/extract.js} +0 -0
- /package/dist/cjs/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
- /package/dist/esm/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
- /package/dist/esm/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
- /package/dist/esm/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
- /package/dist/esm/modules/archive/{extract.js → unzip/extract.js} +0 -0
- /package/dist/esm/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
- /package/dist/{LICENSE → iife/LICENSE} +0 -0
- /package/dist/types/modules/archive/{compress.d.ts → compression/compress.d.ts} +0 -0
- /package/dist/types/modules/archive/{crc32.base.d.ts → compression/crc32.base.d.ts} +0 -0
- /package/dist/types/modules/archive/{crc32.browser.d.ts → compression/crc32.browser.d.ts} +0 -0
- /package/dist/types/modules/archive/{crc32.d.ts → compression/crc32.d.ts} +0 -0
- /package/dist/types/modules/archive/{deflate-fallback.d.ts → compression/deflate-fallback.d.ts} +0 -0
- /package/dist/types/modules/archive/{streaming-compress.base.d.ts → compression/streaming-compress.base.d.ts} +0 -0
- /package/dist/types/modules/archive/{streaming-compress.d.ts → compression/streaming-compress.d.ts} +0 -0
- /package/dist/types/modules/archive/{extract.d.ts → unzip/extract.d.ts} +0 -0
- /package/dist/types/modules/archive/{zip-entry-info.d.ts → zip-spec/zip-entry-info.d.ts} +0 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { DEFAULT_ZIP_LEVEL, DEFAULT_ZIP_TIMESTAMPS } from "../defaults.js";
|
|
2
|
+
import { ZipDeflateFile, StreamingZip } from "./stream.js";
|
|
3
|
+
import { createZip, createZipSync } from "./zip-bytes.js";
|
|
4
|
+
import { collect, pipeIterableToSink } from "../io/archive-sink.js";
|
|
5
|
+
import { toAsyncIterable, toUint8Array, toUint8ArraySync } from "../io/archive-source.js";
|
|
6
|
+
import { createAsyncQueue } from "../utils/async-queue.js";
|
|
7
|
+
const REPRODUCIBLE_ZIP_MOD_TIME = new Date(1980, 0, 1, 0, 0, 0);
|
|
8
|
+
export class ZipArchive {
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this._entries = [];
|
|
11
|
+
this._sealed = false;
|
|
12
|
+
const reproducible = options.reproducible ?? false;
|
|
13
|
+
this._options = {
|
|
14
|
+
level: options.level ?? DEFAULT_ZIP_LEVEL,
|
|
15
|
+
timestamps: options.timestamps ?? (reproducible ? "dos" : DEFAULT_ZIP_TIMESTAMPS),
|
|
16
|
+
comment: options.comment,
|
|
17
|
+
modTime: options.modTime ?? (reproducible ? REPRODUCIBLE_ZIP_MOD_TIME : new Date()),
|
|
18
|
+
smartStore: options.smartStore ?? true
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
add(name, source, options) {
|
|
22
|
+
if (this._sealed) {
|
|
23
|
+
throw new Error("Cannot add entries after output has started");
|
|
24
|
+
}
|
|
25
|
+
if (!name) {
|
|
26
|
+
throw new Error("Entry name is required");
|
|
27
|
+
}
|
|
28
|
+
this._entries.push({ name, source, options });
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
stream() {
|
|
32
|
+
this._sealed = true;
|
|
33
|
+
const queue = createAsyncQueue();
|
|
34
|
+
const zip = new StreamingZip((err, data, final) => {
|
|
35
|
+
if (err) {
|
|
36
|
+
queue.fail(err);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (data.length) {
|
|
40
|
+
queue.push(data);
|
|
41
|
+
}
|
|
42
|
+
if (final) {
|
|
43
|
+
queue.close();
|
|
44
|
+
}
|
|
45
|
+
}, { comment: this._options.comment });
|
|
46
|
+
(async () => {
|
|
47
|
+
try {
|
|
48
|
+
for (const entry of this._entries) {
|
|
49
|
+
const level = entry.options?.level ?? this._options.level;
|
|
50
|
+
const file = new ZipDeflateFile(entry.name, {
|
|
51
|
+
level,
|
|
52
|
+
modTime: entry.options?.modTime ?? this._options.modTime,
|
|
53
|
+
timestamps: this._options.timestamps,
|
|
54
|
+
comment: entry.options?.comment,
|
|
55
|
+
smartStore: this._options.smartStore
|
|
56
|
+
});
|
|
57
|
+
zip.add(file);
|
|
58
|
+
// Feed data
|
|
59
|
+
if (entry.source instanceof Uint8Array ||
|
|
60
|
+
entry.source instanceof ArrayBuffer ||
|
|
61
|
+
typeof entry.source === "string" ||
|
|
62
|
+
(typeof Blob !== "undefined" && entry.source instanceof Blob)) {
|
|
63
|
+
const bytes = await toUint8Array(entry.source);
|
|
64
|
+
await file.push(bytes, true);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
for await (const chunk of toAsyncIterable(entry.source)) {
|
|
68
|
+
await file.push(chunk, false);
|
|
69
|
+
}
|
|
70
|
+
await file.push(new Uint8Array(0), true);
|
|
71
|
+
}
|
|
72
|
+
await file.complete();
|
|
73
|
+
}
|
|
74
|
+
zip.end();
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
queue.fail(e instanceof Error ? e : new Error(String(e)));
|
|
78
|
+
}
|
|
79
|
+
})();
|
|
80
|
+
return queue.iterable;
|
|
81
|
+
}
|
|
82
|
+
async bytes() {
|
|
83
|
+
this._sealed = true;
|
|
84
|
+
const allSourcesInMemory = this._entries.every(e => e.source instanceof Uint8Array ||
|
|
85
|
+
e.source instanceof ArrayBuffer ||
|
|
86
|
+
typeof e.source === "string" ||
|
|
87
|
+
(typeof Blob !== "undefined" && e.source instanceof Blob));
|
|
88
|
+
const hasBlobSource = this._entries.some(e => typeof Blob !== "undefined" && e.source instanceof Blob);
|
|
89
|
+
// Fast-path: when all sources are already in memory and there are no
|
|
90
|
+
// per-entry compression overrides, use the single-buffer ZIP builder.
|
|
91
|
+
// This avoids the overhead of chunking + collecting from the streaming writer.
|
|
92
|
+
if (allSourcesInMemory) {
|
|
93
|
+
// Prefer the sync builder when possible (Node.js hot path): it avoids
|
|
94
|
+
// async/Promise overhead and uses zlib sync fast paths.
|
|
95
|
+
if (!hasBlobSource) {
|
|
96
|
+
const entries = this._entries.map(e => ({
|
|
97
|
+
name: e.name,
|
|
98
|
+
data: toUint8ArraySync(e.source),
|
|
99
|
+
level: e.options?.level,
|
|
100
|
+
modTime: e.options?.modTime,
|
|
101
|
+
comment: e.options?.comment
|
|
102
|
+
}));
|
|
103
|
+
return createZipSync(entries, {
|
|
104
|
+
level: this._options.level,
|
|
105
|
+
timestamps: this._options.timestamps,
|
|
106
|
+
modTime: this._options.modTime,
|
|
107
|
+
comment: this._options.comment,
|
|
108
|
+
smartStore: this._options.smartStore
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
const entries = await Promise.all(this._entries.map(async (e) => ({
|
|
112
|
+
name: e.name,
|
|
113
|
+
data: await toUint8Array(e.source),
|
|
114
|
+
level: e.options?.level,
|
|
115
|
+
modTime: e.options?.modTime,
|
|
116
|
+
comment: e.options?.comment
|
|
117
|
+
})));
|
|
118
|
+
return createZip(entries, {
|
|
119
|
+
level: this._options.level,
|
|
120
|
+
timestamps: this._options.timestamps,
|
|
121
|
+
modTime: this._options.modTime,
|
|
122
|
+
comment: this._options.comment,
|
|
123
|
+
smartStore: this._options.smartStore
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
return collect(this.stream());
|
|
127
|
+
}
|
|
128
|
+
bytesSync() {
|
|
129
|
+
this._sealed = true;
|
|
130
|
+
const entries = this._entries.map(e => {
|
|
131
|
+
if (!(e.source instanceof Uint8Array) &&
|
|
132
|
+
!(e.source instanceof ArrayBuffer) &&
|
|
133
|
+
typeof e.source !== "string") {
|
|
134
|
+
throw new Error("bytesSync() only supports Uint8Array/ArrayBuffer/string sources");
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
name: e.name,
|
|
138
|
+
data: toUint8ArraySync(e.source),
|
|
139
|
+
modTime: e.options?.modTime,
|
|
140
|
+
comment: e.options?.comment
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
return createZipSync(entries, {
|
|
144
|
+
level: this._options.level,
|
|
145
|
+
timestamps: this._options.timestamps,
|
|
146
|
+
modTime: this._options.modTime,
|
|
147
|
+
comment: this._options.comment,
|
|
148
|
+
smartStore: this._options.smartStore
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
async pipeTo(sink) {
|
|
152
|
+
await pipeIterableToSink(this.stream(), sink);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
export function zip(options) {
|
|
156
|
+
return new ZipArchive(options);
|
|
157
|
+
}
|
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
* True Streaming ZIP creator - shared implementation.
|
|
3
3
|
*
|
|
4
4
|
* This module is intentionally platform-agnostic.
|
|
5
|
-
* - In Node builds it uses `./crc32` + `./streaming-compress` (zlib-backed).
|
|
5
|
+
* - In Node builds it uses `./compression/crc32` + `./compression/streaming-compress` (zlib-backed).
|
|
6
6
|
* - In browser builds the bundler aliases those imports to their browser variants.
|
|
7
7
|
*/
|
|
8
|
-
import { crc32Update, crc32Finalize } from "
|
|
9
|
-
import { createDeflateStream } from "
|
|
10
|
-
import { DEFAULT_ZIP_LEVEL, DEFAULT_ZIP_TIMESTAMPS } from "
|
|
11
|
-
import { buildZipEntryMetadata } from "./zip-entry-metadata.js";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
8
|
+
import { crc32Update, crc32Finalize } from "../compression/crc32.js";
|
|
9
|
+
import { createDeflateStream } from "../compression/streaming-compress.js";
|
|
10
|
+
import { DEFAULT_ZIP_LEVEL, DEFAULT_ZIP_TIMESTAMPS } from "../defaults.js";
|
|
11
|
+
import { buildZipEntryMetadata, resolveZipCompressionMethod } from "./zip-entry-metadata.js";
|
|
12
|
+
import { decodeUtf8, encodeUtf8 } from "../utils/text.js";
|
|
13
|
+
import { isProbablyIncompressible } from "../utils/compressibility.js";
|
|
14
|
+
import { buildCentralDirectoryHeader, buildDataDescriptor, buildEndOfCentralDirectory, buildLocalFileHeader, VERSION_MADE_BY, VERSION_NEEDED } from "../zip-spec/zip-records.js";
|
|
14
15
|
/**
|
|
15
16
|
* True Streaming ZIP File - compresses chunk by chunk
|
|
16
17
|
*/
|
|
@@ -23,9 +24,15 @@ export class ZipDeflateFile {
|
|
|
23
24
|
this._finalized = false;
|
|
24
25
|
this._headerEmitted = false;
|
|
25
26
|
this._ondata = null;
|
|
27
|
+
this._onerror = null;
|
|
26
28
|
this._centralDirEntryInfo = null;
|
|
27
29
|
this._pendingEnd = false;
|
|
28
30
|
this._emittedDataDescriptor = false;
|
|
31
|
+
this._localHeader = null;
|
|
32
|
+
// Smart STORE: delay method selection until we sample data.
|
|
33
|
+
this._deflateWanted = null;
|
|
34
|
+
this._pendingChunks = [];
|
|
35
|
+
this._sampleLen = 0;
|
|
29
36
|
// Promise resolution for completion (including data descriptor)
|
|
30
37
|
this._completeResolve = null;
|
|
31
38
|
this._completeReject = null;
|
|
@@ -34,46 +41,70 @@ export class ZipDeflateFile {
|
|
|
34
41
|
// Queue for incoming data before ondata is set
|
|
35
42
|
this._dataQueue = [];
|
|
36
43
|
this._finalQueued = false;
|
|
44
|
+
// Serialize push() calls so callers don't need to await to preserve ordering.
|
|
45
|
+
this._pushChain = Promise.resolve();
|
|
37
46
|
this.name = name;
|
|
38
47
|
const modTime = options?.modTime ?? new Date();
|
|
39
48
|
this._modTime = modTime;
|
|
40
49
|
this.level = options?.level ?? DEFAULT_ZIP_LEVEL;
|
|
50
|
+
this._smartStore = options?.smartStore ?? true;
|
|
51
|
+
this._sampleBuffer = this._smartStore ? new Uint8Array(64 * 1024) : new Uint8Array(0);
|
|
41
52
|
const metadata = buildZipEntryMetadata({
|
|
42
53
|
name,
|
|
43
|
-
comment: "",
|
|
54
|
+
comment: options?.comment ?? "",
|
|
44
55
|
modTime,
|
|
45
56
|
timestamps: options?.timestamps ?? DEFAULT_ZIP_TIMESTAMPS,
|
|
46
57
|
useDataDescriptor: true,
|
|
47
|
-
deflate:
|
|
58
|
+
deflate: false
|
|
48
59
|
});
|
|
49
60
|
this.nameBytes = metadata.nameBytes;
|
|
61
|
+
this.commentBytes = metadata.commentBytes;
|
|
50
62
|
this.dosTime = metadata.dosTime;
|
|
51
63
|
this.dosDate = metadata.dosDate;
|
|
52
64
|
this.extraField = metadata.extraField;
|
|
53
65
|
this._flags = metadata.flags;
|
|
54
66
|
this._compressionMethod = metadata.compressionMethod;
|
|
55
|
-
//
|
|
56
|
-
if (this.
|
|
57
|
-
|
|
58
|
-
this.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this._enqueueData(chunk, false);
|
|
65
|
-
});
|
|
66
|
-
// Handle end - emit data descriptor
|
|
67
|
-
// IMPORTANT: Only use 'end' event, NOT 'finish'!
|
|
68
|
-
// Node.js zlib emits events in order: finish -> data -> end
|
|
69
|
-
this._deflate.on("end", () => {
|
|
70
|
-
if (this._pendingEnd && !this._emittedDataDescriptor) {
|
|
71
|
-
this._emittedDataDescriptor = true;
|
|
72
|
-
this._emitDataDescriptor();
|
|
73
|
-
}
|
|
74
|
-
});
|
|
67
|
+
// If smart store is disabled, decide method upfront and keep true streaming semantics.
|
|
68
|
+
if (!this._smartStore) {
|
|
69
|
+
const deflate = this.level > 0;
|
|
70
|
+
this._deflateWanted = deflate;
|
|
71
|
+
this._compressionMethod = this._buildCompressionMethod(deflate);
|
|
72
|
+
if (deflate) {
|
|
73
|
+
this._initDeflateStream();
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
75
76
|
}
|
|
76
|
-
|
|
77
|
+
// Level 0: always STORE.
|
|
78
|
+
if (this.level === 0) {
|
|
79
|
+
this._deflateWanted = false;
|
|
80
|
+
this._compressionMethod = this._buildCompressionMethod(false);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
_buildCompressionMethod(deflate) {
|
|
84
|
+
return resolveZipCompressionMethod(deflate);
|
|
85
|
+
}
|
|
86
|
+
_initDeflateStream() {
|
|
87
|
+
if (this._deflate) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this._deflate = createDeflateStream({ level: this.level });
|
|
91
|
+
this._deflate.on("error", (err) => {
|
|
92
|
+
this._rejectComplete(err);
|
|
93
|
+
});
|
|
94
|
+
// Handle compressed output - this is true streaming!
|
|
95
|
+
this._deflate.on("data", (chunk) => {
|
|
96
|
+
this._compressedSize += chunk.length;
|
|
97
|
+
this._enqueueData(chunk, false);
|
|
98
|
+
});
|
|
99
|
+
// Handle end - emit data descriptor
|
|
100
|
+
// IMPORTANT: Only use 'end' event, NOT 'finish'!
|
|
101
|
+
// Node.js zlib emits events in order: finish -> data -> end
|
|
102
|
+
this._deflate.on("end", () => {
|
|
103
|
+
if (this._pendingEnd && !this._emittedDataDescriptor) {
|
|
104
|
+
this._emittedDataDescriptor = true;
|
|
105
|
+
this._emitDataDescriptor();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
77
108
|
}
|
|
78
109
|
_buildLocalHeader() {
|
|
79
110
|
// CRC + sizes are written via data descriptor for true streaming.
|
|
@@ -90,6 +121,63 @@ export class ZipDeflateFile {
|
|
|
90
121
|
versionNeeded: VERSION_NEEDED
|
|
91
122
|
});
|
|
92
123
|
}
|
|
124
|
+
_accumulateSample(data) {
|
|
125
|
+
if (this._deflateWanted !== null) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (this._sampleLen >= this._sampleBuffer.length) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const take = Math.min(this._sampleBuffer.length - this._sampleLen, data.length);
|
|
132
|
+
if (take <= 0) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this._sampleBuffer.set(data.subarray(0, take), this._sampleLen);
|
|
136
|
+
this._sampleLen += take;
|
|
137
|
+
}
|
|
138
|
+
_shouldDecide(final) {
|
|
139
|
+
if (this._deflateWanted !== null) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
return final || this._sampleLen >= 16 * 1024;
|
|
143
|
+
}
|
|
144
|
+
_decideCompressionIfNeeded(final) {
|
|
145
|
+
if (this._deflateWanted !== null) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
// Match non-streaming builder semantics: empty files never need DEFLATE.
|
|
149
|
+
if (final && this._sampleLen === 0) {
|
|
150
|
+
this._deflateWanted = false;
|
|
151
|
+
this._compressionMethod = this._buildCompressionMethod(false);
|
|
152
|
+
this._localHeader = null;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
// Default to DEFLATE unless heuristic says STORE.
|
|
156
|
+
const sample = this._sampleBuffer.subarray(0, this._sampleLen);
|
|
157
|
+
const store = isProbablyIncompressible(sample);
|
|
158
|
+
this._deflateWanted = !store;
|
|
159
|
+
this._compressionMethod = this._buildCompressionMethod(this._deflateWanted);
|
|
160
|
+
this._localHeader = null;
|
|
161
|
+
if (this._deflateWanted) {
|
|
162
|
+
this._initDeflateStream();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
_emitHeaderIfNeeded() {
|
|
166
|
+
if (this._headerEmitted) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
this._emitHeader();
|
|
170
|
+
this._headerEmitted = true;
|
|
171
|
+
}
|
|
172
|
+
async _flushPendingChunks() {
|
|
173
|
+
if (this._pendingChunks.length === 0) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
for (const chunk of this._pendingChunks) {
|
|
177
|
+
await this._writeData(chunk);
|
|
178
|
+
}
|
|
179
|
+
this._pendingChunks = [];
|
|
180
|
+
}
|
|
93
181
|
_enqueueData(data, final) {
|
|
94
182
|
if (this._ondata) {
|
|
95
183
|
this._ondata(data, final);
|
|
@@ -121,13 +209,29 @@ export class ZipDeflateFile {
|
|
|
121
209
|
// Flush any queued data
|
|
122
210
|
this._flushQueue();
|
|
123
211
|
}
|
|
212
|
+
get onerror() {
|
|
213
|
+
return this._onerror ?? undefined;
|
|
214
|
+
}
|
|
215
|
+
set onerror(cb) {
|
|
216
|
+
this._onerror = cb;
|
|
217
|
+
// If an error already occurred, surface it immediately.
|
|
218
|
+
if (this._completeError) {
|
|
219
|
+
cb(this._completeError);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
124
222
|
_resolveComplete() {
|
|
125
223
|
if (this._completeResolve) {
|
|
126
224
|
this._completeResolve();
|
|
127
225
|
}
|
|
128
226
|
}
|
|
129
227
|
_rejectComplete(err) {
|
|
228
|
+
if (this._completeError) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
130
231
|
this._completeError = err;
|
|
232
|
+
if (this._onerror) {
|
|
233
|
+
this._onerror(err);
|
|
234
|
+
}
|
|
131
235
|
if (this._completeReject) {
|
|
132
236
|
this._completeReject(err);
|
|
133
237
|
}
|
|
@@ -153,13 +257,6 @@ export class ZipDeflateFile {
|
|
|
153
257
|
}
|
|
154
258
|
promise.then(() => callback()).catch(err => callback(err));
|
|
155
259
|
}
|
|
156
|
-
_emitHeaderIfNeeded() {
|
|
157
|
-
if (this._headerEmitted) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
this._emitHeader();
|
|
161
|
-
this._headerEmitted = true;
|
|
162
|
-
}
|
|
163
260
|
_writeData(data) {
|
|
164
261
|
if (data.length === 0) {
|
|
165
262
|
return Promise.resolve();
|
|
@@ -217,27 +314,60 @@ export class ZipDeflateFile {
|
|
|
217
314
|
this._emitDataDescriptor();
|
|
218
315
|
return completePromise;
|
|
219
316
|
}
|
|
220
|
-
|
|
221
|
-
* Push data - immediately compresses and outputs
|
|
222
|
-
* Returns a Promise that resolves when the write is complete.
|
|
223
|
-
* If final=true, it resolves after the data descriptor is emitted.
|
|
224
|
-
*/
|
|
225
|
-
push(data, final = false, callback) {
|
|
317
|
+
_pushUnchained(data, final, callback) {
|
|
226
318
|
if (this._finalized) {
|
|
227
319
|
const promise = Promise.reject(new Error("Cannot push to finalized ZipDeflateFile"));
|
|
228
320
|
this._tapCallback(promise, callback);
|
|
229
321
|
return promise;
|
|
230
322
|
}
|
|
323
|
+
if (this._deflateWanted === null) {
|
|
324
|
+
this._accumulateSample(data);
|
|
325
|
+
if (!this._shouldDecide(final)) {
|
|
326
|
+
if (data.length > 0) {
|
|
327
|
+
this._pendingChunks.push(data);
|
|
328
|
+
}
|
|
329
|
+
const promise = Promise.resolve();
|
|
330
|
+
this._tapCallback(promise, callback);
|
|
331
|
+
return promise;
|
|
332
|
+
}
|
|
333
|
+
this._decideCompressionIfNeeded(final);
|
|
334
|
+
this._emitHeaderIfNeeded();
|
|
335
|
+
const hadPendingChunks = this._pendingChunks.length > 0;
|
|
336
|
+
const flushPromise = this._flushPendingChunks();
|
|
337
|
+
let writePromise = flushPromise;
|
|
338
|
+
if (data.length > 0) {
|
|
339
|
+
writePromise = hadPendingChunks
|
|
340
|
+
? flushPromise.then(() => this._writeData(data))
|
|
341
|
+
: this._writeData(data);
|
|
342
|
+
}
|
|
343
|
+
const promise = final ? this._finalizeAfterWrite(writePromise) : writePromise;
|
|
344
|
+
this._tapCallback(promise, callback);
|
|
345
|
+
return promise;
|
|
346
|
+
}
|
|
231
347
|
this._emitHeaderIfNeeded();
|
|
232
348
|
const writePromise = this._writeData(data);
|
|
233
349
|
const promise = final ? this._finalizeAfterWrite(writePromise) : writePromise;
|
|
234
350
|
this._tapCallback(promise, callback);
|
|
235
351
|
return promise;
|
|
236
352
|
}
|
|
353
|
+
/**
|
|
354
|
+
* Push data - immediately compresses and outputs
|
|
355
|
+
* Returns a Promise that resolves when the write is complete.
|
|
356
|
+
* If final=true, it resolves after the data descriptor is emitted.
|
|
357
|
+
*/
|
|
358
|
+
push(data, final = false, callback) {
|
|
359
|
+
const promise = (this._pushChain = this._pushChain.then(() => this._pushUnchained(data, final, callback)));
|
|
360
|
+
// Prevent unhandled rejection when callers intentionally ignore the Promise.
|
|
361
|
+
promise.catch(() => { });
|
|
362
|
+
return promise;
|
|
363
|
+
}
|
|
237
364
|
/**
|
|
238
365
|
* Emit local file header with Data Descriptor flag
|
|
239
366
|
*/
|
|
240
367
|
_emitHeader() {
|
|
368
|
+
if (!this._localHeader) {
|
|
369
|
+
this._localHeader = this._buildLocalHeader();
|
|
370
|
+
}
|
|
241
371
|
this._enqueueData(this._localHeader, false);
|
|
242
372
|
}
|
|
243
373
|
/**
|
|
@@ -250,6 +380,7 @@ export class ZipDeflateFile {
|
|
|
250
380
|
this._centralDirEntryInfo = {
|
|
251
381
|
name: this.nameBytes,
|
|
252
382
|
extraField: this.extraField,
|
|
383
|
+
comment: this.commentBytes,
|
|
253
384
|
flags: this._flags,
|
|
254
385
|
crc: crcValue,
|
|
255
386
|
compressedSize: this._compressedSize,
|
|
@@ -288,7 +419,7 @@ export class ZipDeflateFile {
|
|
|
288
419
|
crc32: this._centralDirEntryInfo.crc,
|
|
289
420
|
lastModified: this._modTime,
|
|
290
421
|
localHeaderOffset: this._centralDirEntryInfo.offset,
|
|
291
|
-
comment:
|
|
422
|
+
comment: decodeUtf8(this._centralDirEntryInfo.comment),
|
|
292
423
|
externalAttributes: 0,
|
|
293
424
|
isEncrypted: false
|
|
294
425
|
};
|
|
@@ -305,7 +436,7 @@ export class ZipDeflateFile {
|
|
|
305
436
|
* Streaming ZIP Creator - processes files sequentially
|
|
306
437
|
*/
|
|
307
438
|
export class StreamingZip {
|
|
308
|
-
constructor(callback) {
|
|
439
|
+
constructor(callback, options) {
|
|
309
440
|
this.entries = [];
|
|
310
441
|
this.currentOffset = 0;
|
|
311
442
|
this.ended = false;
|
|
@@ -315,10 +446,12 @@ export class StreamingZip {
|
|
|
315
446
|
this.fileQueueIndex = 0;
|
|
316
447
|
this.activeFile = null;
|
|
317
448
|
this.callback = callback;
|
|
449
|
+
// Avoid per-instance TextEncoder allocations.
|
|
450
|
+
this.zipComment = options?.comment ? encodeUtf8(options.comment) : new Uint8Array(0);
|
|
318
451
|
}
|
|
319
452
|
add(file) {
|
|
320
453
|
if (this.ended) {
|
|
321
|
-
throw new Error("Cannot add files after calling end()");
|
|
454
|
+
throw new Error("Cannot add files after calling end() ");
|
|
322
455
|
}
|
|
323
456
|
this.fileQueue.push(file);
|
|
324
457
|
// If no active file, process this one
|
|
@@ -341,7 +474,18 @@ export class StreamingZip {
|
|
|
341
474
|
const file = this.fileQueue[this.fileQueueIndex++];
|
|
342
475
|
this.activeFile = file;
|
|
343
476
|
const startOffset = this.currentOffset;
|
|
477
|
+
const empty = new Uint8Array(0);
|
|
478
|
+
file.onerror = (err) => {
|
|
479
|
+
if (this.ended) {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
this.ended = true;
|
|
483
|
+
this.callback(err, empty, true);
|
|
484
|
+
};
|
|
344
485
|
file.ondata = (data, final) => {
|
|
486
|
+
if (this.ended) {
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
345
489
|
this.currentOffset += data.length;
|
|
346
490
|
this.callback(null, data, false);
|
|
347
491
|
if (final) {
|
|
@@ -367,7 +511,7 @@ export class StreamingZip {
|
|
|
367
511
|
const header = buildCentralDirectoryHeader({
|
|
368
512
|
fileName: entry.name,
|
|
369
513
|
extraField: entry.extraField,
|
|
370
|
-
comment: empty,
|
|
514
|
+
comment: entry.comment ?? empty,
|
|
371
515
|
flags: entry.flags,
|
|
372
516
|
compressionMethod: entry.compressionMethod,
|
|
373
517
|
dosTime: entry.dosTime,
|
|
@@ -386,7 +530,7 @@ export class StreamingZip {
|
|
|
386
530
|
entryCount: this.entries.length,
|
|
387
531
|
centralDirSize,
|
|
388
532
|
centralDirOffset,
|
|
389
|
-
comment:
|
|
533
|
+
comment: this.zipComment
|
|
390
534
|
});
|
|
391
535
|
this.callback(null, eocd, true);
|
|
392
536
|
}
|