zip-writer 1.1.2 → 2.0.0
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/README.md +112 -132
- package/dist/index.d.ts +30 -57
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +141 -131
- package/dist/index.js.map +1 -1
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +20 -0
- package/dist/utils.js.map +1 -1
- package/dist/write-central-directory.d.ts +2 -2
- package/dist/write-central-directory.d.ts.map +1 -1
- package/dist/write-central-directory.js +5 -9
- package/dist/write-central-directory.js.map +1 -1
- package/dist/write-entry.d.ts +2 -17
- package/dist/write-entry.d.ts.map +1 -1
- package/dist/write-entry.js +4 -95
- package/dist/write-entry.js.map +1 -1
- package/package.json +26 -5
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# zip-writable
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/zip-writer)
|
|
4
|
+
[](https://github.com/gmaclennan/zip-writer/actions/workflows/test.yml)
|
|
5
|
+
[](https://bundlejs.com/?q=zip-writer%401.1.2&treeshake=%5B*%5D)
|
|
6
|
+
|
|
3
7
|
A modern streaming ZIP archive writer for JavaScript that uses the
|
|
4
8
|
[Web Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API)
|
|
5
9
|
and
|
|
@@ -7,12 +11,17 @@ and
|
|
|
7
11
|
|
|
8
12
|
## Features
|
|
9
13
|
|
|
10
|
-
- **Streaming API** - Write ZIP archives
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
- **Streaming API** - Write ZIP archives without buffering entries our the
|
|
15
|
+
output zip into memory
|
|
16
|
+
- **Browser & Node.js** - Works in both environments with the same API
|
|
17
|
+
- **Small bundle size** - ~3KB minified and gzipped
|
|
18
|
+
- **Minimal dependencies** - Only depends on
|
|
19
|
+
[p-mutex](https://www.npmjs.com/package/p-mutex) for mutex locking (adds ~390
|
|
20
|
+
bytes)
|
|
13
21
|
- **ZIP64 support** - Automatic handling of large files and archives
|
|
14
|
-
- **
|
|
15
|
-
|
|
22
|
+
- **Editable Central Directory** - Reorder, rename, or remove entries before
|
|
23
|
+
finalizing
|
|
24
|
+
- **100% test coverage** - Output validated against standard ZIP tools
|
|
16
25
|
|
|
17
26
|
## Installation
|
|
18
27
|
|
|
@@ -31,13 +40,16 @@ const zipWriter = new ZipWriter();
|
|
|
31
40
|
zipWriter.readable.pipeTo(writableStream);
|
|
32
41
|
|
|
33
42
|
// Add entries to the ZIP
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
const data = new TextEncoder().encode("Hello, World!");
|
|
44
|
+
const info = await zipWriter.addEntry({
|
|
45
|
+
readable: new ReadableStream({
|
|
46
|
+
start(controller) {
|
|
47
|
+
controller.enqueue(data);
|
|
48
|
+
controller.close();
|
|
49
|
+
},
|
|
50
|
+
}),
|
|
51
|
+
name: "hello.txt",
|
|
52
|
+
});
|
|
41
53
|
console.log(info);
|
|
42
54
|
|
|
43
55
|
// Finalize the ZIP archive
|
|
@@ -83,93 +95,66 @@ return new Response(zipWriter.readable, {
|
|
|
83
95
|
});
|
|
84
96
|
```
|
|
85
97
|
|
|
86
|
-
##### `entries:
|
|
98
|
+
##### `entries(): Promise<EntryInfo[]>`
|
|
87
99
|
|
|
88
|
-
|
|
89
|
-
metadata like size, CRC32,
|
|
100
|
+
Returns a promise that resolves to an array of all entries that have been
|
|
101
|
+
written to the archive. Each entry contains metadata like size, CRC32,
|
|
102
|
+
compression info, etc.
|
|
90
103
|
|
|
91
104
|
#### Methods
|
|
92
105
|
|
|
93
|
-
##### `
|
|
94
|
-
|
|
95
|
-
Convenience method to add a buffer as an entry to the zip archive. Returns a
|
|
96
|
-
promise that resolves to the entry info once written. For more efficient
|
|
97
|
-
streaming writes, use `createEntryStream()`.
|
|
98
|
-
|
|
99
|
-
**Parameters:**
|
|
100
|
-
|
|
101
|
-
- `data: Uint8Array` - Entry data to write
|
|
102
|
-
- `options.name: string` - Entry name including internal path (required)
|
|
103
|
-
- `options.comment?: string` - Entry comment
|
|
104
|
-
- `options.date?: Date` - Entry date (defaults to current date)
|
|
105
|
-
- `options.mode?: number` - Entry permissions (Unix-style mode)
|
|
106
|
-
- `options.store?: boolean` - Set to `true` to disable compression (defaults to
|
|
107
|
-
`false`, using DEFLATE compression)
|
|
108
|
-
|
|
109
|
-
**Example:**
|
|
110
|
-
|
|
111
|
-
```ts
|
|
112
|
-
const data = new TextEncoder().encode("Hello, World!");
|
|
113
|
-
const entryInfo = await zipWriter.createEntry(data, { name: "hello.txt" });
|
|
114
|
-
console.log(entryInfo);
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
##### `createEntryStream(options: EntryOptions): EntryWriter`
|
|
106
|
+
##### `addEntry(entry: Entry): Promise<EntryInfo>`
|
|
118
107
|
|
|
119
|
-
|
|
120
|
-
|
|
108
|
+
Add an entry to the ZIP archive. Returns a promise that resolves to the entry
|
|
109
|
+
info once written.
|
|
121
110
|
|
|
122
111
|
**Parameters:**
|
|
123
112
|
|
|
124
|
-
- `
|
|
125
|
-
|
|
126
|
-
- `
|
|
127
|
-
- `
|
|
128
|
-
- `
|
|
113
|
+
- `entry.readable: ReadableStream<ArrayBufferView>` - Readable stream of entry
|
|
114
|
+
data
|
|
115
|
+
- `entry.name: string` - Entry name including internal path (required)
|
|
116
|
+
- `entry.comment?: string` - Entry comment
|
|
117
|
+
- `entry.date?: Date` - Entry date (defaults to current date)
|
|
118
|
+
- `entry.mode?: number` - Entry permissions (Unix-style mode)
|
|
119
|
+
- `entry.store?: boolean` - Set to `true` to disable compression (defaults to
|
|
129
120
|
`false`, using DEFLATE compression)
|
|
130
121
|
|
|
131
122
|
**Examples:**
|
|
132
123
|
|
|
133
124
|
```ts
|
|
134
|
-
//
|
|
135
|
-
const entry = zipWriter.createEntryStream({ name: "readme.txt" });
|
|
136
|
-
const writer = entry.writable.getWriter();
|
|
137
|
-
await writer.write(new TextEncoder().encode("Hello!"));
|
|
138
|
-
await writer.close();
|
|
139
|
-
|
|
140
|
-
// Stream a fetch response
|
|
125
|
+
// Stream from a fetch response
|
|
141
126
|
const response = await fetch(imageUrl);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
127
|
+
await zipWriter.addEntry({
|
|
128
|
+
readable: response.body,
|
|
129
|
+
name: "images/photo.jpg",
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Stream from a Uint8Array
|
|
133
|
+
const data = new TextEncoder().encode("Hello, World!");
|
|
134
|
+
await zipWriter.addEntry({
|
|
135
|
+
readable: new ReadableStream({
|
|
136
|
+
start(controller) {
|
|
137
|
+
controller.enqueue(data);
|
|
138
|
+
controller.close();
|
|
139
|
+
},
|
|
140
|
+
}),
|
|
141
|
+
name: "hello.txt",
|
|
142
|
+
});
|
|
145
143
|
|
|
146
144
|
// With custom date and permissions
|
|
147
|
-
zipWriter.
|
|
145
|
+
await zipWriter.addEntry({
|
|
146
|
+
readable: scriptStream,
|
|
148
147
|
name: "script.sh",
|
|
149
148
|
date: new Date("2024-01-01"),
|
|
150
149
|
mode: 0o755, // executable
|
|
151
|
-
})
|
|
150
|
+
});
|
|
152
151
|
|
|
153
152
|
// Disable compression for already-compressed files
|
|
154
|
-
zipWriter.
|
|
153
|
+
await zipWriter.addEntry({
|
|
154
|
+
readable: videoStream,
|
|
155
155
|
name: "video.mp4",
|
|
156
156
|
store: true, // no compression
|
|
157
|
-
})
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
##### `onceQueueEmpty(): Promise<void>`
|
|
161
|
-
|
|
162
|
-
Wait until all currently queued entries have been written. Useful when you need
|
|
163
|
-
to ensure entries are complete before continuing.
|
|
164
|
-
|
|
165
|
-
```ts
|
|
166
|
-
// Add multiple entries
|
|
167
|
-
zipWriter.createEntryStream({ name: "file1.txt" }).writable;
|
|
168
|
-
zipWriter.createEntryStream({ name: "file2.txt" }).writable;
|
|
169
|
-
|
|
170
|
-
// Wait for all to complete
|
|
171
|
-
await zipWriter.onceQueueEmpty();
|
|
172
|
-
console.log(`Wrote ${zipWriter.entries.length} entries`);
|
|
157
|
+
});
|
|
173
158
|
```
|
|
174
159
|
|
|
175
160
|
##### `finalize(options?): Promise<{ zip64: boolean, uncompressedEntriesSize: bigint, compressedEntriesSize: bigint, fileSize: bigint }>`
|
|
@@ -205,11 +190,8 @@ console.log(
|
|
|
205
190
|
**Example with entries option:**
|
|
206
191
|
|
|
207
192
|
```ts
|
|
208
|
-
// Wait for all entries to be written
|
|
209
|
-
await zipWriter.onceQueueEmpty();
|
|
210
|
-
|
|
211
193
|
// Get current entries and modify them
|
|
212
|
-
const entries =
|
|
194
|
+
const entries = await zipWriter.entries();
|
|
213
195
|
|
|
214
196
|
// Remove an entry
|
|
215
197
|
const filtered = entries.filter((e) => e.name !== "temp.txt");
|
|
@@ -227,37 +209,11 @@ const sorted = [...entries].sort((a, b) => a.name.localeCompare(b.name));
|
|
|
227
209
|
await zipWriter.finalize({ entries: sorted });
|
|
228
210
|
```
|
|
229
211
|
|
|
230
|
-
### `
|
|
231
|
-
|
|
232
|
-
Returned by `ZipWriter.createEntryStream()`. Provides a writable stream to write
|
|
233
|
-
entry data.
|
|
212
|
+
### `EntryInfo`
|
|
234
213
|
|
|
235
|
-
|
|
214
|
+
Returned by `ZipWriter.addEntry()`. Contains metadata about a written entry.
|
|
236
215
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
The writable stream to write entry data to. Close this stream when done writing.
|
|
240
|
-
|
|
241
|
-
```ts
|
|
242
|
-
const entryWriter = zipWriter.createEntryStream({ name: "data.txt" });
|
|
243
|
-
|
|
244
|
-
// Using a writer
|
|
245
|
-
const writer = entryWriter.writable.getWriter();
|
|
246
|
-
await writer.write(new TextEncoder().encode("chunk 1"));
|
|
247
|
-
await writer.write(new TextEncoder().encode("chunk 2"));
|
|
248
|
-
await writer.close();
|
|
249
|
-
|
|
250
|
-
// Using pipeTo
|
|
251
|
-
someReadableStream.pipeTo(entryWriter.writable);
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
#### Methods
|
|
255
|
-
|
|
256
|
-
##### `getEntryInfo(): Promise<EntryInfo>`
|
|
257
|
-
|
|
258
|
-
Get entry info. Resolves once all data has been written to the ZIP stream.
|
|
259
|
-
|
|
260
|
-
**Returns `EntryInfo`:**
|
|
216
|
+
**Properties:**
|
|
261
217
|
|
|
262
218
|
- `name: string` - Entry name
|
|
263
219
|
- `comment?: string` - Entry comment
|
|
@@ -270,11 +226,13 @@ Get entry info. Resolves once all data has been written to the ZIP stream.
|
|
|
270
226
|
- `compressedSize: bigint | number` - Compressed size in bytes
|
|
271
227
|
- `zip64: boolean` - Whether this entry uses ZIP64 format
|
|
272
228
|
|
|
273
|
-
|
|
274
|
-
const entryWriter = zipWriter.createEntryStream({ name: "test.txt" });
|
|
275
|
-
await someStream.pipeTo(entryWriter.writable);
|
|
229
|
+
**Example:**
|
|
276
230
|
|
|
277
|
-
|
|
231
|
+
```ts
|
|
232
|
+
const info = await zipWriter.addEntry({
|
|
233
|
+
readable: dataStream,
|
|
234
|
+
name: "test.txt",
|
|
235
|
+
});
|
|
278
236
|
console.log(
|
|
279
237
|
`Wrote ${info.name}: ${info.uncompressedSize} bytes (compressed to ${info.compressedSize})`,
|
|
280
238
|
);
|
|
@@ -294,24 +252,41 @@ async function createZip() {
|
|
|
294
252
|
const fileStream = Writable.toWeb(createWriteStream("output.zip"));
|
|
295
253
|
zipWriter.readable.pipeTo(fileStream);
|
|
296
254
|
|
|
297
|
-
// Add a text file
|
|
255
|
+
// Add a text file
|
|
298
256
|
const data1 = new TextEncoder().encode("This is a readme");
|
|
299
|
-
await zipWriter.
|
|
300
|
-
|
|
301
|
-
|
|
257
|
+
await zipWriter.addEntry({
|
|
258
|
+
readable: new ReadableStream({
|
|
259
|
+
start(controller) {
|
|
260
|
+
controller.enqueue(data1);
|
|
261
|
+
controller.close();
|
|
262
|
+
},
|
|
263
|
+
}),
|
|
264
|
+
name: "readme.txt",
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// Add files from URLs
|
|
302
268
|
const imageResponse = await fetch("https://example.com/image.png");
|
|
303
|
-
await
|
|
304
|
-
|
|
305
|
-
|
|
269
|
+
await zipWriter.addEntry({
|
|
270
|
+
readable: imageResponse.body,
|
|
271
|
+
name: "images/photo.png",
|
|
272
|
+
});
|
|
306
273
|
|
|
307
|
-
// Add a JSON file
|
|
274
|
+
// Add a JSON file
|
|
308
275
|
const data = { hello: "world" };
|
|
309
276
|
const jsonData = new TextEncoder().encode(JSON.stringify(data, null, 2));
|
|
310
|
-
await zipWriter.
|
|
277
|
+
await zipWriter.addEntry({
|
|
278
|
+
readable: new ReadableStream({
|
|
279
|
+
start(controller) {
|
|
280
|
+
controller.enqueue(jsonData);
|
|
281
|
+
controller.close();
|
|
282
|
+
},
|
|
283
|
+
}),
|
|
284
|
+
name: "data.json",
|
|
285
|
+
});
|
|
311
286
|
|
|
312
287
|
// Wait for all entries and check results
|
|
313
|
-
await zipWriter.
|
|
314
|
-
console.log(`Added ${
|
|
288
|
+
const entries = await zipWriter.entries();
|
|
289
|
+
console.log(`Added ${entries.length} entries`);
|
|
315
290
|
|
|
316
291
|
// Finalize the archive
|
|
317
292
|
const result = await zipWriter.finalize();
|
|
@@ -329,9 +304,16 @@ const zipWriter = new ZipWriter();
|
|
|
329
304
|
|
|
330
305
|
// Add entries...
|
|
331
306
|
const data = new TextEncoder().encode("Hello");
|
|
332
|
-
zipWriter
|
|
333
|
-
|
|
334
|
-
|
|
307
|
+
await zipWriter.addEntry({
|
|
308
|
+
readable: new ReadableStream({
|
|
309
|
+
start(controller) {
|
|
310
|
+
controller.enqueue(data);
|
|
311
|
+
controller.close();
|
|
312
|
+
},
|
|
313
|
+
}),
|
|
314
|
+
name: "file.txt",
|
|
315
|
+
});
|
|
316
|
+
await zipWriter.finalize();
|
|
335
317
|
|
|
336
318
|
// Create download link
|
|
337
319
|
const blob = await new Response(zipWriter.readable).blob();
|
|
@@ -410,17 +392,15 @@ No special configuration is needed - it's handled automatically.
|
|
|
410
392
|
|
|
411
393
|
```ts
|
|
412
394
|
try {
|
|
413
|
-
|
|
414
|
-
await someStream.pipeTo(entryWriter.writable);
|
|
415
|
-
await entryWriter.getEntryInfo();
|
|
395
|
+
await zipWriter.addEntry({ readable: someStream, name: "test.txt" });
|
|
416
396
|
} catch (error) {
|
|
417
397
|
console.error("Failed to write entry:", error);
|
|
418
398
|
// The ZIP stream is aborted on error - cannot add more entries
|
|
419
399
|
}
|
|
420
400
|
```
|
|
421
401
|
|
|
422
|
-
Once an error occurs during entry writing, the ZIP stream is
|
|
423
|
-
cannot be recovered. You must create a new `ZipWriter` instance.
|
|
402
|
+
Once an error occurs during entry writing, the ZIP stream is in the errored
|
|
403
|
+
state and cannot be recovered. You must create a new `ZipWriter` instance.
|
|
424
404
|
|
|
425
405
|
## License
|
|
426
406
|
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,17 @@ export interface EntryOptions {
|
|
|
10
10
|
/** Compression method to `STORE` (defaults to `DEFLATE`) */
|
|
11
11
|
store?: boolean;
|
|
12
12
|
}
|
|
13
|
-
export interface
|
|
13
|
+
export interface EntryOptionsInternal extends EntryOptions {
|
|
14
|
+
/** Encoded entry name */
|
|
15
|
+
nameBytes: Uint8Array;
|
|
16
|
+
/** Encoded entry comment */
|
|
17
|
+
commentBytes: Uint8Array;
|
|
18
|
+
}
|
|
19
|
+
export interface Entry extends EntryOptions {
|
|
20
|
+
/** Readable stream of entry data */
|
|
21
|
+
readable: ReadableStream<ArrayBufferView<ArrayBufferLike>>;
|
|
22
|
+
}
|
|
23
|
+
export interface EntryInfoZip64 extends EntryOptionsInternal {
|
|
14
24
|
/** Byte offset of the local file header within the ZIP archive */
|
|
15
25
|
startOffset: bigint;
|
|
16
26
|
/** CRC32 checksum of the uncompressed data */
|
|
@@ -22,10 +32,22 @@ export interface EntryInfoZip64 extends EntryOptions {
|
|
|
22
32
|
/** Entry information is in ZIP64 format */
|
|
23
33
|
zip64: true;
|
|
24
34
|
}
|
|
35
|
+
export interface ZipInfo {
|
|
36
|
+
/** Does the archive use ZIP64 format? */
|
|
37
|
+
zip64: boolean;
|
|
38
|
+
/** Total uncompressed size of all entries */
|
|
39
|
+
uncompressedEntriesSize: bigint;
|
|
40
|
+
/** Total compressed size of all entries */
|
|
41
|
+
compressedEntriesSize: bigint;
|
|
42
|
+
/** Total size of the ZIP file */
|
|
43
|
+
fileSize: bigint;
|
|
44
|
+
}
|
|
25
45
|
export type EntryInfoStandard = {
|
|
26
46
|
[K in keyof EntryInfoZip64]: EntryInfoZip64[K] extends bigint ? number : K extends "zip64" ? false : EntryInfoZip64[K];
|
|
27
47
|
};
|
|
28
|
-
export type
|
|
48
|
+
export type EntryInfoInternal = EntryInfoZip64 | EntryInfoStandard;
|
|
49
|
+
type OmitUnion<T, U extends keyof T> = T extends U ? never : Omit<T, U>;
|
|
50
|
+
export type EntryInfo = OmitUnion<EntryInfoInternal, "nameBytes" | "commentBytes">;
|
|
29
51
|
export declare class ZipWriter<TIsZip64 extends boolean = false> {
|
|
30
52
|
#private;
|
|
31
53
|
/**
|
|
@@ -35,29 +57,10 @@ export declare class ZipWriter<TIsZip64 extends boolean = false> {
|
|
|
35
57
|
crc32?: (data: Uint8Array<ArrayBuffer>, value?: number) => number;
|
|
36
58
|
});
|
|
37
59
|
get readable(): ReadableStream<ArrayBufferView<ArrayBufferLike>>;
|
|
38
|
-
get entries(): ReadonlyArray<Readonly<EntryInfo>>;
|
|
39
60
|
/**
|
|
40
|
-
*
|
|
61
|
+
* Get an array of entry information for all entries added so far to the ZIP archive.
|
|
41
62
|
*/
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Convenience wrapper around `createEntryStream` to write all data at once.
|
|
45
|
-
* Use `createEntryStream` for more efficient streaming writes. Calls to
|
|
46
|
-
* createEntry() will be queued internally and each will resolve once it's
|
|
47
|
-
* written to the archive.
|
|
48
|
-
*
|
|
49
|
-
* @example
|
|
50
|
-
* ```ts
|
|
51
|
-
* const data = new TextEncoder().encode("Hello, World!");
|
|
52
|
-
* const entryInfo = await zipWriter.createEntry(data, { name: "hello.txt" });
|
|
53
|
-
* console.log(entryInfo);
|
|
54
|
-
* ```
|
|
55
|
-
*
|
|
56
|
-
* @param data Entry data
|
|
57
|
-
* @param options Entry filename, comment, compression method, etc.
|
|
58
|
-
* @returns Entry information once the entry has been written.
|
|
59
|
-
*/
|
|
60
|
-
createEntry(data: Uint8Array<ArrayBuffer>, options: EntryOptions): Promise<EntryInfo>;
|
|
63
|
+
entries(): Promise<EntryInfo[]>;
|
|
61
64
|
/**
|
|
62
65
|
* Create a new entry in the Zip archive. Use the returned
|
|
63
66
|
* entryWriter.writable to write data to the entry. You can await
|
|
@@ -84,7 +87,7 @@ export declare class ZipWriter<TIsZip64 extends boolean = false> {
|
|
|
84
87
|
*
|
|
85
88
|
* @param options Entry options
|
|
86
89
|
*/
|
|
87
|
-
|
|
90
|
+
addEntry({ readable, ...entryOptions }: Entry): Promise<EntryInfo>;
|
|
88
91
|
/**
|
|
89
92
|
* Finalize the ZIP archive by writing the central directory and end of
|
|
90
93
|
* central directory records. You may not add any more entries after calling
|
|
@@ -100,39 +103,9 @@ export declare class ZipWriter<TIsZip64 extends boolean = false> {
|
|
|
100
103
|
*
|
|
101
104
|
* @returns Information about the finalized archive.
|
|
102
105
|
*/
|
|
103
|
-
finalize({ entries
|
|
104
|
-
entries?:
|
|
105
|
-
}): Promise<
|
|
106
|
-
/** Does the archive use ZIP64 format? */
|
|
107
|
-
zip64: boolean;
|
|
108
|
-
/** Total uncompressed size of all entries */
|
|
109
|
-
uncompressedEntriesSize: bigint;
|
|
110
|
-
/** Total compressed size of all entries */
|
|
111
|
-
compressedEntriesSize: bigint;
|
|
112
|
-
/** Total size of the ZIP file */
|
|
113
|
-
fileSize: bigint;
|
|
114
|
-
}>;
|
|
115
|
-
}
|
|
116
|
-
declare class EntryWriter {
|
|
117
|
-
#private;
|
|
118
|
-
/**
|
|
119
|
-
* @param enqueueAndPipe Function that enqueues the entry data readable, pipes it to the Zip stream, and returns a promise that resolves to the entry info once done.
|
|
120
|
-
*/
|
|
121
|
-
constructor(enqueueAndPipe: (readable: ReadableStream<Uint8Array<ArrayBuffer>>) => Promise<EntryInfo>);
|
|
122
|
-
/**
|
|
123
|
-
* Writable stream to write entry data to.
|
|
124
|
-
*
|
|
125
|
-
* @example
|
|
126
|
-
* ```ts
|
|
127
|
-
* ReadableStream.from([new TextEncoder().encode("Hello, World!")])
|
|
128
|
-
* .pipeTo(entryWriter.writable);
|
|
129
|
-
* ```
|
|
130
|
-
*/
|
|
131
|
-
get writable(): WritableStream<Uint8Array<ArrayBuffer>>;
|
|
132
|
-
/**
|
|
133
|
-
* Get entry info. Resolves once all data has been written to the Zip stream.
|
|
134
|
-
*/
|
|
135
|
-
getEntryInfo(): Promise<EntryInfo>;
|
|
106
|
+
finalize({ entries }?: {
|
|
107
|
+
entries?: EntryInfo[];
|
|
108
|
+
}): Promise<ZipInfo>;
|
|
136
109
|
}
|
|
137
110
|
export {};
|
|
138
111
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD,yBAAyB;IACzB,SAAS,EAAE,UAAU,CAAC;IACtB,4BAA4B;IAC5B,YAAY,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,KAAM,SAAQ,YAAY;IACzC,oCAAoC;IACpC,QAAQ,EAAE,cAAc,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,cAAe,SAAQ,oBAAoB;IAC1D,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,+BAA+B;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,KAAK,EAAE,IAAI,CAAC;CACb;AAED,MAAM,WAAW,OAAO;IACtB,yCAAyC;IACzC,KAAK,EAAE,OAAO,CAAC;IACf,6CAA6C;IAC7C,uBAAuB,EAAE,MAAM,CAAC;IAChC,2CAA2C;IAC3C,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,iBAAiB,GAAG;KAC7B,CAAC,IAAI,MAAM,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC,SAAS,MAAM,GACzD,MAAM,GACN,CAAC,SAAS,OAAO,GACf,KAAK,GACL,cAAc,CAAC,CAAC,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,iBAAiB,CAAC;AAEnE,KAAK,SAAS,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAExE,MAAM,MAAM,SAAS,GAAG,SAAS,CAC/B,iBAAiB,EACjB,WAAW,GAAG,cAAc,CAC7B,CAAC;AAIF,qBAAa,SAAS,CAAC,QAAQ,SAAS,OAAO,GAAG,KAAK;;IAoBrD;;OAEG;gBACS,EACV,KAAoB,GACrB,GAAE;QACD,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;KAC9D;IAIN,IAAI,QAAQ,qDAEX;IAED;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAS/B;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,QAAQ,CAAC,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC;IAmKlE;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAE;QAAE,OAAO,CAAC,EAAE,SAAS,EAAE,CAAA;KAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAgFxE"}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getDataDescriptorStandard, getDataDescriptorZip64, getLocalFileHeader, } from "./write-entry.js";
|
|
2
2
|
import { getCDFH, getEOCDZip64, getEOCDStandard, } from "./write-central-directory.js";
|
|
3
3
|
import { ZIP64_LIMIT } from "./constants.js";
|
|
4
|
-
import { noop } from "./utils.js";
|
|
4
|
+
import { noop, validateEntryOptions } from "./utils.js";
|
|
5
5
|
import { crc32 as crc32Default } from "#crc32";
|
|
6
|
+
import Mutex from "p-mutex";
|
|
6
7
|
const BUFFER_SIZE = 16 * 1024; // 16 KB
|
|
7
8
|
const bufferedQueue = new ByteLengthQueuingStrategy({
|
|
8
9
|
highWaterMark: BUFFER_SIZE,
|
|
9
10
|
});
|
|
11
|
+
const textEncoder = new TextEncoder();
|
|
10
12
|
export class ZipWriter {
|
|
11
13
|
#offset = BigInt(0);
|
|
12
14
|
#zipStream = new TransformStream({
|
|
@@ -21,10 +23,9 @@ export class ZipWriter {
|
|
|
21
23
|
// block the zip writing.
|
|
22
24
|
bufferedQueue);
|
|
23
25
|
#entries = [];
|
|
24
|
-
#queued = Promise.resolve();
|
|
25
|
-
#entryCount = 0;
|
|
26
|
-
#finalized = false;
|
|
27
26
|
#crc32;
|
|
27
|
+
#mutex = new Mutex();
|
|
28
|
+
#finalized = false;
|
|
28
29
|
/**
|
|
29
30
|
* @param crc Optional CRC32 function to use. Defaults to zlib.crc32 on Node and a pure JS implementation in browsers.
|
|
30
31
|
*/
|
|
@@ -34,44 +35,14 @@ export class ZipWriter {
|
|
|
34
35
|
get readable() {
|
|
35
36
|
return this.#zipStream.readable;
|
|
36
37
|
}
|
|
37
|
-
get entries() {
|
|
38
|
-
return this.#entries;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Wait until all currently queued entries have been written.
|
|
42
|
-
*/
|
|
43
|
-
async onceQueueEmpty() {
|
|
44
|
-
while (this.#entries.length < this.#entryCount) {
|
|
45
|
-
await this.#queued;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
38
|
/**
|
|
49
|
-
*
|
|
50
|
-
* Use `createEntryStream` for more efficient streaming writes. Calls to
|
|
51
|
-
* createEntry() will be queued internally and each will resolve once it's
|
|
52
|
-
* written to the archive.
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* ```ts
|
|
56
|
-
* const data = new TextEncoder().encode("Hello, World!");
|
|
57
|
-
* const entryInfo = await zipWriter.createEntry(data, { name: "hello.txt" });
|
|
58
|
-
* console.log(entryInfo);
|
|
59
|
-
* ```
|
|
60
|
-
*
|
|
61
|
-
* @param data Entry data
|
|
62
|
-
* @param options Entry filename, comment, compression method, etc.
|
|
63
|
-
* @returns Entry information once the entry has been written.
|
|
39
|
+
* Get an array of entry information for all entries added so far to the ZIP archive.
|
|
64
40
|
*/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
finally {
|
|
72
|
-
await writer.close();
|
|
73
|
-
}
|
|
74
|
-
return entryWriter.getEntryInfo();
|
|
41
|
+
entries() {
|
|
42
|
+
return this.#mutex.withLock(() => this.#entries.map((entry) => {
|
|
43
|
+
const { nameBytes, commentBytes, ...publicEntryInfo } = entry;
|
|
44
|
+
return publicEntryInfo;
|
|
45
|
+
}));
|
|
75
46
|
}
|
|
76
47
|
/**
|
|
77
48
|
* Create a new entry in the Zip archive. Use the returned
|
|
@@ -99,56 +70,118 @@ export class ZipWriter {
|
|
|
99
70
|
*
|
|
100
71
|
* @param options Entry options
|
|
101
72
|
*/
|
|
102
|
-
|
|
73
|
+
addEntry({ readable, ...entryOptions }) {
|
|
103
74
|
if (this.#finalized) {
|
|
104
75
|
throw new TypeError("Cannot add entry after finalize() has been called");
|
|
105
76
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
// Wait for previous entry to complete
|
|
121
|
-
await prevQueued;
|
|
122
|
-
const writer = this.#zipStream.writable.getWriter();
|
|
123
|
-
const reader = readable.getReader();
|
|
77
|
+
// Encode now to catch range errors synchronously
|
|
78
|
+
const entryOptionsInternal = {
|
|
79
|
+
...entryOptions,
|
|
80
|
+
nameBytes: textEncoder.encode(entryOptions.name),
|
|
81
|
+
commentBytes: entryOptions.comment
|
|
82
|
+
? textEncoder.encode(entryOptions.comment)
|
|
83
|
+
: new Uint8Array(),
|
|
84
|
+
};
|
|
85
|
+
validateEntryOptions(entryOptionsInternal);
|
|
86
|
+
const entryInfoPromise = this.#mutex.withLock(async () => {
|
|
87
|
+
// -- Write local file header --
|
|
88
|
+
let writer = this.#zipStream.writable.getWriter();
|
|
89
|
+
await writer.ready;
|
|
90
|
+
const startOffset = this.#offset;
|
|
124
91
|
try {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
startOffset: this.#offset,
|
|
131
|
-
});
|
|
132
|
-
this.#entries.push(entryInfo);
|
|
133
|
-
entryDone();
|
|
134
|
-
return entryInfo;
|
|
92
|
+
// This is in a try...catch because if writing the local file header
|
|
93
|
+
// fails, we want to abort the output zip readable stream.
|
|
94
|
+
await writer.write(getLocalFileHeader(entryOptionsInternal));
|
|
95
|
+
// Await all data has been written before we releaseLock and read the offset
|
|
96
|
+
await writer.ready;
|
|
135
97
|
}
|
|
136
98
|
catch (err) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
//
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
99
|
+
// Let the readable size know we are no longer consuming data
|
|
100
|
+
/* istanbul ignore next -- @preserve */
|
|
101
|
+
readable.cancel(err);
|
|
102
|
+
// Put the zip stream writable into an error state, which will propogate
|
|
103
|
+
// to the readable side and anything consuming it
|
|
104
|
+
/* istanbul ignore next -- @preserve */
|
|
105
|
+
await writer.abort(err);
|
|
106
|
+
/* istanbul ignore next -- @preserve */
|
|
107
|
+
writer.releaseLock();
|
|
108
|
+
/* istanbul ignore next -- @preserve */
|
|
145
109
|
throw err;
|
|
146
110
|
}
|
|
147
|
-
|
|
148
|
-
|
|
111
|
+
writer.releaseLock();
|
|
112
|
+
const fileStartOffset = this.#offset;
|
|
113
|
+
// -- Write file data --
|
|
114
|
+
let uncompressedSize = BigInt(0);
|
|
115
|
+
let checksum = 0;
|
|
116
|
+
const crcAndSizeStream = new TransformStream({
|
|
117
|
+
transform: async (chunk, controller) => {
|
|
118
|
+
const byteLength = BigInt(chunk.byteLength);
|
|
119
|
+
uncompressedSize += byteLength;
|
|
120
|
+
checksum = this.#crc32(chunk, checksum);
|
|
121
|
+
controller.enqueue(chunk);
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
const compressionStream = entryOptions.store
|
|
125
|
+
? new TransformStream()
|
|
126
|
+
: new CompressionStream("deflate-raw");
|
|
127
|
+
await readable
|
|
128
|
+
.pipeThrough(crcAndSizeStream)
|
|
129
|
+
.pipeThrough(compressionStream)
|
|
130
|
+
.pipeTo(this.#zipStream.writable, { preventClose: true });
|
|
131
|
+
// -- Write data descriptor --
|
|
132
|
+
writer = this.#zipStream.writable.getWriter();
|
|
133
|
+
// Await here to ensure all data has been written, so we know this.#offset is accurate
|
|
134
|
+
await writer.ready;
|
|
135
|
+
const compressedSize = this.#offset - fileStartOffset;
|
|
136
|
+
const needsZip64 = uncompressedSize > ZIP64_LIMIT ||
|
|
137
|
+
compressedSize > ZIP64_LIMIT ||
|
|
138
|
+
startOffset > ZIP64_LIMIT;
|
|
139
|
+
let entryInfo;
|
|
140
|
+
try {
|
|
141
|
+
// This is in a try...catch because writing the data descriptor could fail,
|
|
142
|
+
// and we want to abort the output zip readable stream if that happens.
|
|
143
|
+
if (needsZip64) {
|
|
144
|
+
entryInfo = {
|
|
145
|
+
...entryOptionsInternal,
|
|
146
|
+
startOffset,
|
|
147
|
+
crc32: checksum,
|
|
148
|
+
uncompressedSize,
|
|
149
|
+
compressedSize,
|
|
150
|
+
zip64: true,
|
|
151
|
+
};
|
|
152
|
+
await writer.write(getDataDescriptorZip64(entryInfo));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
entryInfo = {
|
|
156
|
+
...entryOptionsInternal,
|
|
157
|
+
startOffset: Number(startOffset),
|
|
158
|
+
crc32: checksum,
|
|
159
|
+
uncompressedSize: Number(uncompressedSize),
|
|
160
|
+
compressedSize: Number(compressedSize),
|
|
161
|
+
zip64: false,
|
|
162
|
+
};
|
|
163
|
+
await writer.write(getDataDescriptorStandard(entryInfo));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
/* istanbul ignore next -- @preserve */
|
|
168
|
+
await writer.abort(err);
|
|
169
|
+
/* istanbul ignore next -- @preserve */
|
|
149
170
|
writer.releaseLock();
|
|
171
|
+
// The readable has already been fully consumed at this point, so no need to cancel it
|
|
172
|
+
/* istanbul ignore next -- @preserve */
|
|
173
|
+
throw err;
|
|
150
174
|
}
|
|
175
|
+
writer.releaseLock();
|
|
176
|
+
this.#entries.push(entryInfo);
|
|
177
|
+
// Clone to avoid mutation affecting our internal state
|
|
178
|
+
const { nameBytes, commentBytes, ...publicEntryInfo } = entryInfo;
|
|
179
|
+
return publicEntryInfo;
|
|
151
180
|
});
|
|
181
|
+
// Avoid an uncaught rejection if the user doesn't await entryInfoPromise
|
|
182
|
+
// - error handling can be done on the readable stream
|
|
183
|
+
entryInfoPromise.catch(noop);
|
|
184
|
+
return entryInfoPromise;
|
|
152
185
|
}
|
|
153
186
|
/**
|
|
154
187
|
* Set the entries of the Zip archive. This can be used to reorder,
|
|
@@ -179,7 +212,13 @@ export class ZipWriter {
|
|
|
179
212
|
throw new Error(`Cannot set entries: entry at offset ${entry.startOffset} has different compressed size`);
|
|
180
213
|
}
|
|
181
214
|
}
|
|
182
|
-
this.#entries = entries.map((entry) => ({
|
|
215
|
+
this.#entries = entries.map((entry) => ({
|
|
216
|
+
...entry,
|
|
217
|
+
nameBytes: textEncoder.encode(entry.name),
|
|
218
|
+
commentBytes: entry.comment
|
|
219
|
+
? textEncoder.encode(entry.comment)
|
|
220
|
+
: new Uint8Array(0),
|
|
221
|
+
}));
|
|
183
222
|
}
|
|
184
223
|
/**
|
|
185
224
|
* Finalize the ZIP archive by writing the central directory and end of
|
|
@@ -196,23 +235,27 @@ export class ZipWriter {
|
|
|
196
235
|
*
|
|
197
236
|
* @returns Information about the finalized archive.
|
|
198
237
|
*/
|
|
199
|
-
|
|
238
|
+
finalize({ entries } = {}) {
|
|
200
239
|
if (this.#finalized) {
|
|
201
240
|
throw new TypeError("finalize() has already been called");
|
|
202
241
|
}
|
|
203
242
|
this.#finalized = true;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
243
|
+
const zipInfoPromise = this.#mutex.withLock(async () => {
|
|
244
|
+
if (entries) {
|
|
245
|
+
try {
|
|
246
|
+
this.#setEntries(entries);
|
|
247
|
+
}
|
|
248
|
+
catch (err) {
|
|
249
|
+
// If setting entries fails, we still want to finalize the zip stream
|
|
250
|
+
// so that consumers don't hang waiting for data that will never come.
|
|
251
|
+
this.#zipStream.writable.abort(err);
|
|
252
|
+
throw err;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
213
255
|
// Write central directory headers for all entries
|
|
214
|
-
const centralDirectoryStart = this.#offset;
|
|
215
256
|
const writer = this.#zipStream.writable.getWriter();
|
|
257
|
+
await writer.ready;
|
|
258
|
+
const centralDirectoryStart = this.#offset;
|
|
216
259
|
try {
|
|
217
260
|
let entryUsesZip64 = false;
|
|
218
261
|
let uncompressedEntriesSize = BigInt(0);
|
|
@@ -223,8 +266,10 @@ export class ZipWriter {
|
|
|
223
266
|
}
|
|
224
267
|
uncompressedEntriesSize += BigInt(entry.uncompressedSize);
|
|
225
268
|
compressedEntriesSize += BigInt(entry.compressedSize);
|
|
269
|
+
await writer.ready;
|
|
226
270
|
await writer.write(getCDFH(entry));
|
|
227
271
|
}
|
|
272
|
+
await writer.ready;
|
|
228
273
|
const centralDirectorySize = this.#offset - centralDirectoryStart;
|
|
229
274
|
// Determine if the archive needs ZIP64 based on entries or central directory
|
|
230
275
|
const eocdNeedsZip64 = this.#entries.length > 0xffff ||
|
|
@@ -238,7 +283,6 @@ export class ZipWriter {
|
|
|
238
283
|
eocd = getEOCDStandard(this.#entries.length, Number(centralDirectoryStart), Number(centralDirectorySize));
|
|
239
284
|
}
|
|
240
285
|
await writer.write(eocd);
|
|
241
|
-
// Close the zip stream
|
|
242
286
|
await writer.close();
|
|
243
287
|
return {
|
|
244
288
|
zip64: eocdNeedsZip64 || entryUsesZip64,
|
|
@@ -254,45 +298,11 @@ export class ZipWriter {
|
|
|
254
298
|
finally {
|
|
255
299
|
writer.releaseLock();
|
|
256
300
|
}
|
|
257
|
-
})();
|
|
258
|
-
finalizePromise.catch(noop); // prevent unhandled rejection
|
|
259
|
-
return finalizePromise;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
class EntryWriter {
|
|
263
|
-
#entryStream = new TransformStream(undefined, bufferedQueue, bufferedQueue);
|
|
264
|
-
#written;
|
|
265
|
-
/**
|
|
266
|
-
* @param enqueueAndPipe Function that enqueues the entry data readable, pipes it to the Zip stream, and returns a promise that resolves to the entry info once done.
|
|
267
|
-
*/
|
|
268
|
-
constructor(enqueueAndPipe) {
|
|
269
|
-
// We could try to pass the zipstream writable to EntryWriter, but then
|
|
270
|
-
// EntryWriter would not know when the entry has finished writing, and would
|
|
271
|
-
// not have a way to get the entry info.
|
|
272
|
-
this.#written = enqueueAndPipe(this.#entryStream.readable);
|
|
273
|
-
// abort the writable quickly if there is an error, and ensure we don't
|
|
274
|
-
// throw an uncaught error.
|
|
275
|
-
this.#written.catch((reason) => {
|
|
276
|
-
this.#entryStream.writable.abort(reason);
|
|
277
301
|
});
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
* @example
|
|
283
|
-
* ```ts
|
|
284
|
-
* ReadableStream.from([new TextEncoder().encode("Hello, World!")])
|
|
285
|
-
* .pipeTo(entryWriter.writable);
|
|
286
|
-
* ```
|
|
287
|
-
*/
|
|
288
|
-
get writable() {
|
|
289
|
-
return this.#entryStream.writable;
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Get entry info. Resolves once all data has been written to the Zip stream.
|
|
293
|
-
*/
|
|
294
|
-
async getEntryInfo() {
|
|
295
|
-
return this.#written;
|
|
302
|
+
// Avoid an uncaught rejection if the user doesn't await finalize() - error
|
|
303
|
+
// handling can be done on the readable stream
|
|
304
|
+
zipInfoPromise.catch(noop);
|
|
305
|
+
return zipInfoPromise;
|
|
296
306
|
}
|
|
297
307
|
}
|
|
298
308
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
export declare function getDosTime(date: Date): number;
|
|
2
2
|
export declare function getDosDate(date: Date): number;
|
|
3
3
|
export declare function noop(): void;
|
|
4
|
+
/**
|
|
5
|
+
* Validates EntryOptions to ensure they are within the limits of our encoding.
|
|
6
|
+
* Throws an error if any field exceeds the maximum allowed size.
|
|
7
|
+
*/
|
|
8
|
+
export declare function validateEntryOptions({ nameBytes, commentBytes, mode, }: {
|
|
9
|
+
nameBytes: Uint8Array;
|
|
10
|
+
commentBytes: Uint8Array;
|
|
11
|
+
mode?: number;
|
|
12
|
+
}): void;
|
|
4
13
|
type DataViewValue<T extends keyof typeof OFFSETS = keyof typeof OFFSETS> = T extends "setBigUint64" ? [T, bigint, boolean] : [T, number, boolean];
|
|
5
14
|
export declare const UINT16 = "setUint16";
|
|
6
15
|
export declare const UINT32 = "setUint32";
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAM7C;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAM7C;AAED,wBAAgB,IAAI,SAAK;AAEzB,KAAK,aAAa,CAAC,CAAC,SAAS,MAAM,OAAO,OAAO,GAAG,MAAM,OAAO,OAAO,IACtE,CAAC,SAAS,cAAc,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAEzE,eAAO,MAAM,MAAM,cAAc,CAAC;AAClC,eAAO,MAAM,MAAM,cAAc,CAAC;AAClC,eAAO,MAAM,MAAM,iBAAiB,CAAC;AAGrC,QAAA,MAAM,OAAO;;;;CAImB,CAAC;AAEjC,wBAAgB,aAAa,CAC3B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,aAAa,EAAE,EACvB,MAAM,GAAE,MAAU,GACjB,MAAM,CAOR"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAM7C;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAM7C;AAED,wBAAgB,IAAI,SAAK;AAEzB;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,SAAS,EACT,YAAY,EACZ,IAAI,GACL,EAAE;IACD,SAAS,EAAE,UAAU,CAAC;IACtB,YAAY,EAAE,UAAU,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,IAAI,CAuBP;AAED,KAAK,aAAa,CAAC,CAAC,SAAS,MAAM,OAAO,OAAO,GAAG,MAAM,OAAO,OAAO,IACtE,CAAC,SAAS,cAAc,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAEzE,eAAO,MAAM,MAAM,cAAc,CAAC;AAClC,eAAO,MAAM,MAAM,cAAc,CAAC;AAClC,eAAO,MAAM,MAAM,iBAAiB,CAAC;AAGrC,QAAA,MAAM,OAAO;;;;CAImB,CAAC;AAEjC,wBAAgB,aAAa,CAC3B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,aAAa,EAAE,EACvB,MAAM,GAAE,MAAU,GACjB,MAAM,CAOR"}
|
package/dist/utils.js
CHANGED
|
@@ -9,6 +9,26 @@ export function getDosDate(date) {
|
|
|
9
9
|
date.getDate());
|
|
10
10
|
}
|
|
11
11
|
export function noop() { }
|
|
12
|
+
/**
|
|
13
|
+
* Validates EntryOptions to ensure they are within the limits of our encoding.
|
|
14
|
+
* Throws an error if any field exceeds the maximum allowed size.
|
|
15
|
+
*/
|
|
16
|
+
export function validateEntryOptions({ nameBytes, commentBytes, mode, }) {
|
|
17
|
+
// Validate name
|
|
18
|
+
if (nameBytes.length > 0xffff) {
|
|
19
|
+
throw new RangeError(`File name exceeds maximum length of 65535 bytes (got ${nameBytes.length} bytes)`);
|
|
20
|
+
}
|
|
21
|
+
// Validate comment
|
|
22
|
+
if (commentBytes.length > 0xffff) {
|
|
23
|
+
throw new RangeError(`File comment exceeds maximum length of 65535 bytes (got ${commentBytes.length} bytes)`);
|
|
24
|
+
}
|
|
25
|
+
// Validate mode (Unix file mode is 16 bits, stored in upper 16 bits of external attributes)
|
|
26
|
+
if (mode !== undefined) {
|
|
27
|
+
if (!Number.isInteger(mode) || mode < 0 || mode > 0xffff) {
|
|
28
|
+
throw new RangeError(`File mode must be an integer between 0 and 65535 (got ${mode})`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
12
32
|
export const UINT16 = "setUint16";
|
|
13
33
|
export const UINT32 = "setUint32";
|
|
14
34
|
export const UINT64 = "setBigUint64";
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,IAAU;IACnC,OAAO,CACL,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;QACvB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACxB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CACzB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAU;IACnC,OAAO,CACL,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,OAAO,EAAE,CACf,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI,KAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,IAAU;IACnC,OAAO,CACL,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;QACvB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACxB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CACzB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAU;IACnC,OAAO,CACL,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,OAAO,EAAE,CACf,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI,KAAI,CAAC;AAEzB;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,EACnC,SAAS,EACT,YAAY,EACZ,IAAI,GAKL;IACC,gBAAgB;IAChB,IAAI,SAAS,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;QAC9B,MAAM,IAAI,UAAU,CAClB,wDAAwD,SAAS,CAAC,MAAM,SAAS,CAClF,CAAC;IACJ,CAAC;IAED,mBAAmB;IACnB,IAAI,YAAY,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;QACjC,MAAM,IAAI,UAAU,CAClB,2DAA2D,YAAY,CAAC,MAAM,SAAS,CACxF,CAAC;IACJ,CAAC;IAED,4FAA4F;IAC5F,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,MAAM,EAAE,CAAC;YACzD,MAAM,IAAI,UAAU,CAClB,yDAAyD,IAAI,GAAG,CACjE,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAKD,MAAM,CAAC,MAAM,MAAM,GAAG,WAAW,CAAC;AAClC,MAAM,CAAC,MAAM,MAAM,GAAG,WAAW,CAAC;AAClC,MAAM,CAAC,MAAM,MAAM,GAAG,cAAc,CAAC;AAGrC,MAAM,OAAO,GAAG;IACd,SAAS,EAAE,CAAC;IACZ,SAAS,EAAE,CAAC;IACZ,YAAY,EAAE,CAAC;CACe,CAAC;AAEjC,MAAM,UAAU,aAAa,CAC3B,IAAc,EACd,MAAuB,EACvB,SAAiB,CAAC;IAElB,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,IAAI,MAAM,EAAE,CAAC;QACnD,mBAAmB;QACnB,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;QAC1C,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EntryInfoInternal } from "./index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Generate the Central Directory File Header for the given entry info.
|
|
4
4
|
*/
|
|
5
|
-
export declare function getCDFH(entryInfo:
|
|
5
|
+
export declare function getCDFH(entryInfo: EntryInfoInternal): Uint8Array<ArrayBuffer>;
|
|
6
6
|
/**
|
|
7
7
|
* Generate the End of Central Directory record with zip64 support.
|
|
8
8
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-central-directory.d.ts","sourceRoot":"","sources":["../src/write-central-directory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"write-central-directory.d.ts","sourceRoot":"","sources":["../src/write-central-directory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EAGlB,MAAM,YAAY,CAAC;AAgCpB;;GAEG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,iBAAiB,GAAG,UAAU,CAAC,WAAW,CAAC,CAM7E;AAuJD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,EACpB,sBAAsB,EAAE,MAAM,EAC9B,oBAAoB,EAAE,MAAM,GAC3B,UAAU,CAAC,WAAW,CAAC,CAwBzB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,EACpB,sBAAsB,EAAE,MAAM,EAC9B,oBAAoB,EAAE,MAAM,GAC3B,UAAU,CAAC,WAAW,CAAC,CA6DzB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CENTRAL_DIRECTORY_SIGNATURE, END_OF_CENTRAL_DIR_SIGNATURE, ZIP64_END_OF_CENTRAL_DIR_SIGNATURE, ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE, VERSION_MADE_BY, VERSION_NEEDED_STANDARD, VERSION_NEEDED_ZIP64, GENERAL_PURPOSE_FLAGS, COMPRESSION_METHOD_STORE, COMPRESSION_METHOD_DEFLATE, ZIP64_LIMIT, CENTRAL_DIRECTORY_HEADER_SIZE, EOCD_SIZE, EOCD64_SIZE, EOCD64_LOCATOR_SIZE, BIG_ENDIAN, LITTLE_ENDIAN, } from "./constants.js";
|
|
2
|
-
import { getDosTime, getDosDate, writeDataView, UINT16, UINT32, UINT64, } from "./utils.js";
|
|
2
|
+
import { getDosTime, getDosDate, writeDataView, UINT16, UINT32, UINT64, validateEntryOptions, } from "./utils.js";
|
|
3
3
|
const textEncoder = new TextEncoder();
|
|
4
4
|
/**
|
|
5
5
|
* Generate the Central Directory File Header for the given entry info.
|
|
@@ -13,10 +13,8 @@ export function getCDFH(entryInfo) {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
function getCDFHStandard(entryInfo) {
|
|
16
|
-
const nameBytes =
|
|
17
|
-
|
|
18
|
-
? textEncoder.encode(entryInfo.comment)
|
|
19
|
-
: new Uint8Array(0);
|
|
16
|
+
const { nameBytes, commentBytes } = entryInfo;
|
|
17
|
+
validateEntryOptions(entryInfo);
|
|
20
18
|
const headerSize = CENTRAL_DIRECTORY_HEADER_SIZE + nameBytes.length + commentBytes.length;
|
|
21
19
|
const header = new Uint8Array(headerSize);
|
|
22
20
|
const view = new DataView(header.buffer);
|
|
@@ -70,10 +68,8 @@ function getCDFHStandard(entryInfo) {
|
|
|
70
68
|
return header;
|
|
71
69
|
}
|
|
72
70
|
function getCDFHZip64(entryInfo) {
|
|
73
|
-
const nameBytes =
|
|
74
|
-
|
|
75
|
-
? textEncoder.encode(entryInfo.comment)
|
|
76
|
-
: new Uint8Array(0);
|
|
71
|
+
const { nameBytes, commentBytes } = entryInfo;
|
|
72
|
+
validateEntryOptions(entryInfo);
|
|
77
73
|
// Extra field for ZIP64
|
|
78
74
|
const extraField = new Uint8Array(28); // ZIP64 extra field
|
|
79
75
|
const extraView = new DataView(extraField.buffer);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-central-directory.js","sourceRoot":"","sources":["../src/write-central-directory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"write-central-directory.js","sourceRoot":"","sources":["../src/write-central-directory.ts"],"names":[],"mappings":"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"}
|
package/dist/write-entry.d.ts
CHANGED
|
@@ -1,20 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
* Write a zip entry to the given writer from the given reader.
|
|
4
|
-
*/
|
|
5
|
-
export declare function writeZipEntry({ writer, reader, entryOptions, startOffset, crc32, }: {
|
|
6
|
-
/** Writer for the zip archive */
|
|
7
|
-
writer: WritableStreamDefaultWriter<Uint8Array<ArrayBuffer>>;
|
|
8
|
-
/** Reader for the entry data */
|
|
9
|
-
reader: ReadableStreamDefaultReader<Uint8Array<ArrayBuffer>>;
|
|
10
|
-
/** Options for the zip entry */
|
|
11
|
-
entryOptions: EntryOptions;
|
|
12
|
-
/** Offset in the zip archive where this entry starts */
|
|
13
|
-
startOffset: bigint;
|
|
14
|
-
/** CRC32 function to use */
|
|
15
|
-
crc32: (data: Uint8Array<ArrayBuffer>, value?: number) => number;
|
|
16
|
-
}): Promise<EntryInfoZip64 | EntryInfoStandard>;
|
|
17
|
-
export declare function getLocalFileHeader(options: EntryOptions): Uint8Array<ArrayBuffer>;
|
|
1
|
+
import type { EntryOptionsInternal } from "./index.js";
|
|
2
|
+
export declare function getLocalFileHeader(options: EntryOptionsInternal): Uint8Array<ArrayBuffer>;
|
|
18
3
|
export declare function getDataDescriptorStandard(entryInfo: {
|
|
19
4
|
uncompressedSize: number;
|
|
20
5
|
compressedSize: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-entry.d.ts","sourceRoot":"","sources":["../src/write-entry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"write-entry.d.ts","sourceRoot":"","sources":["../src/write-entry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAuBvD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,oBAAoB,GAC5B,UAAU,CAAC,WAAW,CAAC,CAoCzB;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE;IACnD,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,UAAU,CAAC,WAAW,CAAC,CAgB1B;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE;IAChD,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,UAAU,CAAC,WAAW,CAAC,CAgB1B"}
|
package/dist/write-entry.js
CHANGED
|
@@ -1,98 +1,7 @@
|
|
|
1
|
-
import { LOCAL_FILE_HEADER_SIGNATURE, DATA_DESCRIPTOR_SIGNATURE, VERSION_NEEDED_STANDARD, GENERAL_PURPOSE_FLAGS, COMPRESSION_METHOD_STORE, COMPRESSION_METHOD_DEFLATE, LOCAL_FILE_HEADER_SIZE,
|
|
1
|
+
import { LOCAL_FILE_HEADER_SIGNATURE, DATA_DESCRIPTOR_SIGNATURE, VERSION_NEEDED_STANDARD, GENERAL_PURPOSE_FLAGS, COMPRESSION_METHOD_STORE, COMPRESSION_METHOD_DEFLATE, LOCAL_FILE_HEADER_SIZE, DATA_DESCRIPTOR_SIZE, DATA_DESCRIPTOR_SIZE_ZIP64, LITTLE_ENDIAN, BIG_ENDIAN, } from "./constants.js";
|
|
2
2
|
import { getDosTime, getDosDate, writeDataView, UINT16, UINT32, UINT64, } from "./utils.js";
|
|
3
|
-
const textEncoder = new TextEncoder();
|
|
4
|
-
/**
|
|
5
|
-
* Write a zip entry to the given writer from the given reader.
|
|
6
|
-
*/
|
|
7
|
-
export async function writeZipEntry({ writer, reader, entryOptions, startOffset, crc32, }) {
|
|
8
|
-
let uncompressedSize = BigInt(0);
|
|
9
|
-
let compressedSize = BigInt(0);
|
|
10
|
-
let checksum = 0;
|
|
11
|
-
await writer.write(getLocalFileHeader(entryOptions));
|
|
12
|
-
if (entryOptions.store) {
|
|
13
|
-
// Store mode: no compression, direct copy
|
|
14
|
-
while (true) {
|
|
15
|
-
const { value, done } = await reader.read();
|
|
16
|
-
if (done)
|
|
17
|
-
break;
|
|
18
|
-
const byteLength = BigInt(value.byteLength);
|
|
19
|
-
uncompressedSize += byteLength;
|
|
20
|
-
compressedSize += byteLength;
|
|
21
|
-
checksum = crc32(value, checksum);
|
|
22
|
-
await writer.write(value);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
// Deflate mode: manual reader/writer loops to minimize overhead
|
|
27
|
-
const compressionStream = new CompressionStream("deflate-raw");
|
|
28
|
-
const compressionWriter = compressionStream.writable.getWriter();
|
|
29
|
-
const compressionReader = compressionStream.readable.getReader();
|
|
30
|
-
const writePromise = (async () => {
|
|
31
|
-
try {
|
|
32
|
-
while (true) {
|
|
33
|
-
const { value, done } = await reader.read();
|
|
34
|
-
if (done)
|
|
35
|
-
break;
|
|
36
|
-
uncompressedSize += BigInt(value.byteLength);
|
|
37
|
-
checksum = crc32(value, checksum);
|
|
38
|
-
await compressionWriter.write(value);
|
|
39
|
-
}
|
|
40
|
-
await compressionWriter.close();
|
|
41
|
-
}
|
|
42
|
-
catch (err) {
|
|
43
|
-
await compressionWriter.abort(err);
|
|
44
|
-
throw err;
|
|
45
|
-
}
|
|
46
|
-
})();
|
|
47
|
-
const readPromise = (async () => {
|
|
48
|
-
try {
|
|
49
|
-
while (true) {
|
|
50
|
-
const { value, done } = await compressionReader.read();
|
|
51
|
-
if (done)
|
|
52
|
-
break;
|
|
53
|
-
compressedSize += BigInt(value.byteLength);
|
|
54
|
-
await writer.write(value);
|
|
55
|
-
}
|
|
56
|
-
compressionReader.releaseLock();
|
|
57
|
-
}
|
|
58
|
-
catch (err) {
|
|
59
|
-
await compressionReader.cancel(err);
|
|
60
|
-
throw err;
|
|
61
|
-
}
|
|
62
|
-
})();
|
|
63
|
-
await Promise.all([writePromise, readPromise]);
|
|
64
|
-
}
|
|
65
|
-
const needsZip64 = uncompressedSize > ZIP64_LIMIT ||
|
|
66
|
-
compressedSize > ZIP64_LIMIT ||
|
|
67
|
-
startOffset > ZIP64_LIMIT;
|
|
68
|
-
if (needsZip64) {
|
|
69
|
-
const entryInfo = {
|
|
70
|
-
...entryOptions,
|
|
71
|
-
startOffset,
|
|
72
|
-
crc32: checksum,
|
|
73
|
-
uncompressedSize,
|
|
74
|
-
compressedSize,
|
|
75
|
-
zip64: true,
|
|
76
|
-
};
|
|
77
|
-
await writer.write(getDataDescriptorZip64(entryInfo));
|
|
78
|
-
return entryInfo;
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
const entryInfo = {
|
|
82
|
-
...entryOptions,
|
|
83
|
-
startOffset: Number(startOffset),
|
|
84
|
-
crc32: checksum,
|
|
85
|
-
uncompressedSize: Number(uncompressedSize),
|
|
86
|
-
compressedSize: Number(compressedSize),
|
|
87
|
-
zip64: false,
|
|
88
|
-
};
|
|
89
|
-
await writer.write(getDataDescriptorStandard(entryInfo));
|
|
90
|
-
return entryInfo;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
3
|
export function getLocalFileHeader(options) {
|
|
94
|
-
const
|
|
95
|
-
const headerSize = LOCAL_FILE_HEADER_SIZE + nameBytes.length;
|
|
4
|
+
const headerSize = LOCAL_FILE_HEADER_SIZE + options.nameBytes.length;
|
|
96
5
|
const header = new Uint8Array(headerSize);
|
|
97
6
|
const view = new DataView(header.buffer);
|
|
98
7
|
const date = options.date || new Date();
|
|
@@ -118,12 +27,12 @@ export function getLocalFileHeader(options) {
|
|
|
118
27
|
// Uncompressed size (0 when using data descriptor)
|
|
119
28
|
[UINT32, 0, LITTLE_ENDIAN],
|
|
120
29
|
// File name length
|
|
121
|
-
[UINT16, nameBytes.length, LITTLE_ENDIAN],
|
|
30
|
+
[UINT16, options.nameBytes.length, LITTLE_ENDIAN],
|
|
122
31
|
// Extra field length
|
|
123
32
|
[UINT16, 0, LITTLE_ENDIAN],
|
|
124
33
|
]);
|
|
125
34
|
// File name
|
|
126
|
-
header.set(nameBytes, offset);
|
|
35
|
+
header.set(options.nameBytes, offset);
|
|
127
36
|
return header;
|
|
128
37
|
}
|
|
129
38
|
export function getDataDescriptorStandard(entryInfo) {
|
package/dist/write-entry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-entry.js","sourceRoot":"","sources":["../src/write-entry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"write-entry.js","sourceRoot":"","sources":["../src/write-entry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zip-writer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"exports": {
|
|
5
5
|
".": {
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -21,16 +21,25 @@
|
|
|
21
21
|
"test:lint": "eslint .",
|
|
22
22
|
"test:vitest": "vitest",
|
|
23
23
|
"bench": "vitest bench",
|
|
24
|
+
"coverage": "vitest run --coverage",
|
|
24
25
|
"format": "prettier --write .",
|
|
25
26
|
"prepack": "rimraf dist && tsc"
|
|
26
27
|
},
|
|
27
28
|
"files": [
|
|
28
29
|
"dist"
|
|
29
30
|
],
|
|
30
|
-
"keywords": [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
"keywords": [
|
|
32
|
+
"zip",
|
|
33
|
+
"archive",
|
|
34
|
+
"streaming",
|
|
35
|
+
"web streams",
|
|
36
|
+
"compression streams",
|
|
37
|
+
"javascript",
|
|
38
|
+
"typescript"
|
|
39
|
+
],
|
|
40
|
+
"author": "Gregor MacLennan <gmaclennan@gmail.com>",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"description": "A modern streaming ZIP archive writer for JavaScript that uses the Web Streams API and Compression Streams API.",
|
|
34
43
|
"devDependencies": {
|
|
35
44
|
"@node-rs/crc32": "^1.10.6",
|
|
36
45
|
"@types/archiver": "^7.0.0",
|
|
@@ -38,6 +47,7 @@
|
|
|
38
47
|
"@types/yauzl-promise": "^4.0.1",
|
|
39
48
|
"@vitest/browser": "^4.0.7",
|
|
40
49
|
"@vitest/browser-playwright": "^4.0.7",
|
|
50
|
+
"@vitest/coverage-istanbul": "^4.0.7",
|
|
41
51
|
"@zip.js/zip.js": "^2.8.8",
|
|
42
52
|
"archiver": "^7.0.1",
|
|
43
53
|
"eslint": "^9.39.1",
|
|
@@ -57,5 +67,16 @@
|
|
|
57
67
|
"lint-staged": {
|
|
58
68
|
"*.js": "eslint --cache --fix",
|
|
59
69
|
"*.{js,css,md}": "prettier --write"
|
|
70
|
+
},
|
|
71
|
+
"repository": {
|
|
72
|
+
"type": "git",
|
|
73
|
+
"url": "git+https://github.com/gmaclennan/zip-writer.git"
|
|
74
|
+
},
|
|
75
|
+
"bugs": {
|
|
76
|
+
"url": "https://github.com/gmaclennan/zip-writer/issues"
|
|
77
|
+
},
|
|
78
|
+
"homepage": "https://github.com/gmaclennan/zip-writer#readme",
|
|
79
|
+
"dependencies": {
|
|
80
|
+
"p-mutex": "^1.0.0"
|
|
60
81
|
}
|
|
61
82
|
}
|