@gyng/remote-zip 0.2.5 → 1.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/LICENSE-APACHE +201 -0
- package/{LICENSE → LICENSE-MIT} +1 -1
- package/README.md +82 -23
- package/lib/cjs/index.js +7 -0
- package/lib/cjs/index.js.map +7 -0
- package/lib/esm/index.mjs +7 -0
- package/lib/esm/index.mjs.map +7 -0
- package/lib/types/crypto.d.ts +39 -0
- package/lib/types/index.d.mts +1 -0
- package/lib/types/zip.d.mts +453 -0
- package/lib/types/zip.d.ts +133 -10
- package/package.json +70 -36
- package/lib/types/zip.test.d.ts +0 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Incremental CRC-32, for verifying decompressed output (including streaming). */
|
|
2
|
+
export declare class Crc32 {
|
|
3
|
+
private state;
|
|
4
|
+
update(bytes: Uint8Array): void;
|
|
5
|
+
digest(): number;
|
|
6
|
+
}
|
|
7
|
+
/** Compute the CRC-32 of `bytes` (the ZIP/IEEE variant). */
|
|
8
|
+
export declare const crc32: (bytes: Uint8Array) => number;
|
|
9
|
+
/** Test seam: raw AES block encryption (FIPS-197), used to validate the core. */
|
|
10
|
+
export declare const aesEncryptBlockRaw: (key: Uint8Array, block: Uint8Array) => Uint8Array;
|
|
11
|
+
/**
|
|
12
|
+
* Decrypt traditional-ZipCrypto bytes (the 12-byte encryption header is consumed
|
|
13
|
+
* and stripped). Returns the compressed plaintext and the header's check byte.
|
|
14
|
+
*/
|
|
15
|
+
export declare const decryptZipCrypto: (data: Uint8Array, password: Uint8Array) => {
|
|
16
|
+
plaintext: Uint8Array;
|
|
17
|
+
checkByte: number;
|
|
18
|
+
};
|
|
19
|
+
/** Encrypt for ZipCrypto (used by tests to build fixtures). */
|
|
20
|
+
export declare const encryptZipCrypto: (plaintext: Uint8Array, password: Uint8Array, header: Uint8Array) => Uint8Array;
|
|
21
|
+
/** Parse the WinZip AES extra field (id 0x9901): strength + actual method. */
|
|
22
|
+
export declare const parseAesExtra: (extra: ArrayBuffer) => {
|
|
23
|
+
strength: number;
|
|
24
|
+
actualMethod: number;
|
|
25
|
+
} | null;
|
|
26
|
+
/** Reasons a WinZip AES decryption can fail (mapped to RemoteZipError codes). */
|
|
27
|
+
export type AesDecryptError = "WRONG_PASSWORD" | "BAD_MAC" | "UNSUPPORTED";
|
|
28
|
+
export declare class CryptoError extends Error {
|
|
29
|
+
reason: AesDecryptError;
|
|
30
|
+
constructor(reason: AesDecryptError);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Decrypt a WinZip AES entry payload (salt || pwVerify || ciphertext || mac).
|
|
34
|
+
* Verifies the password-check bytes and the authentication code, then returns
|
|
35
|
+
* the still-compressed plaintext.
|
|
36
|
+
*/
|
|
37
|
+
export declare const decryptWinzipAes: (data: Uint8Array, password: Uint8Array, strength: number) => Promise<Uint8Array>;
|
|
38
|
+
/** Encrypt a WinZip AES payload (used by tests to build fixtures). */
|
|
39
|
+
export declare const encryptWinzipAes: (plaintext: Uint8Array, password: Uint8Array, strength: number, salt: Uint8Array) => Promise<Uint8Array>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./zip.mjs";
|
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
export { crc32 } from "./crypto";
|
|
2
|
+
/** Machine-readable discriminant for {@link RemoteZipError}. */
|
|
3
|
+
export type RemoteZipErrorCode = "UNKNOWN" | "CONTENT_LENGTH_MISSING" | "HTTP_ERROR" | "EOCD_NOT_FOUND" | "UNSUPPORTED_ZIP64" | "UNSUPPORTED_ENCRYPTION" | "FILE_NOT_FOUND" | "LOCAL_HEADER_PARSE_FAILED" | "CENTRAL_DIRECTORY_OUT_OF_BOUNDS" | "DECOMPRESSION_LIMIT_EXCEEDED" | "CRC_MISMATCH" | "WRONG_PASSWORD" | "DECRYPTION_FAILED";
|
|
4
|
+
export declare class RemoteZipError extends Error {
|
|
5
|
+
/** Machine-readable error code, for programmatic handling without matching on `message`. */
|
|
6
|
+
code: RemoteZipErrorCode;
|
|
7
|
+
constructor(message: string, code?: RemoteZipErrorCode);
|
|
8
|
+
}
|
|
9
|
+
/** Per-call options for {@link RemoteZip.fetch} / {@link RemoteZip.fetchStream}. */
|
|
10
|
+
export interface EntryDecodeOptions {
|
|
11
|
+
/** If set, decompression aborts and throws once output would exceed this many bytes. */
|
|
12
|
+
maxUncompressedSize?: number;
|
|
13
|
+
/** Aborts this request (in addition to any instance-level signal). */
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
/** Per-request timeout in milliseconds. */
|
|
16
|
+
timeoutMs?: number;
|
|
17
|
+
/** If set, verify the decompressed output against the entry's CRC-32. */
|
|
18
|
+
verifyCrc?: boolean;
|
|
19
|
+
/** Password for an encrypted entry (traditional ZipCrypto or WinZip AES). */
|
|
20
|
+
password?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface EndOfCentralDirectory {
|
|
23
|
+
meta: Record<string, unknown>;
|
|
24
|
+
data: {
|
|
25
|
+
/** End of central directory signature = 0x06054b50 */
|
|
26
|
+
signature: ArrayBuffer;
|
|
27
|
+
/** Number of this disk (or 0xffff for ZIP64) */
|
|
28
|
+
diskNumber: number;
|
|
29
|
+
/** Disk where central directory starts (or 0xffff for ZIP64) */
|
|
30
|
+
cdDisk: number;
|
|
31
|
+
/** Number of central directory records on this disk (or 0xffff for ZIP64) */
|
|
32
|
+
centralDirectoryDiskNumber: number;
|
|
33
|
+
/** Number of central directory records on this disk (or 0xffff for ZIP64) */
|
|
34
|
+
centralDirectoryRecordCount: number;
|
|
35
|
+
/** Size of central directory (bytes) (or 0xffffffff for ZIP64) */
|
|
36
|
+
centralDirectoryByteSize: number;
|
|
37
|
+
/** Offset of start of central directory, relative to start of archive (or 0xffffffff for ZIP64) */
|
|
38
|
+
centralDirectoryByteOffset: number;
|
|
39
|
+
/** Comment */
|
|
40
|
+
comment: string;
|
|
41
|
+
/** Comment length (n) */
|
|
42
|
+
commentLength: number;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export interface CentralDirectoryRecord {
|
|
46
|
+
meta: {
|
|
47
|
+
/** Length of the entire record */
|
|
48
|
+
length: number;
|
|
49
|
+
};
|
|
50
|
+
data: {
|
|
51
|
+
/** Central directory file header signature = 0x02014b50 */
|
|
52
|
+
signature: ArrayBuffer;
|
|
53
|
+
/** Version of the program this ZIP was made by.
|
|
54
|
+
*
|
|
55
|
+
* Upper byte:
|
|
56
|
+
* - 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)
|
|
57
|
+
* - 1 - Amiga
|
|
58
|
+
* - 2 - OpenVMS
|
|
59
|
+
* - 3 - UNIX
|
|
60
|
+
* - 4 - VM/CMS
|
|
61
|
+
* - 5 - Atari ST
|
|
62
|
+
* - 6 - OS/2 H.P.F.S.
|
|
63
|
+
* - 7 - Macintosh
|
|
64
|
+
* - 8 - Z-System
|
|
65
|
+
* - 9 - CP/M
|
|
66
|
+
* - 10 - Windows NTFS
|
|
67
|
+
* - 11 - MVS (OS/390 - Z/OS)
|
|
68
|
+
* - 12 - VSE
|
|
69
|
+
* - 13 - Acorn Risc
|
|
70
|
+
* - 14 - VFAT
|
|
71
|
+
* - 15 - alternate MVS
|
|
72
|
+
* - 16 - BeOS
|
|
73
|
+
* - 17 - Tandem
|
|
74
|
+
* - 18 - OS/400
|
|
75
|
+
* - 19 - OS/X (Darwin)
|
|
76
|
+
* - 20 - 255: Unused
|
|
77
|
+
*/
|
|
78
|
+
versionMadeBy: number;
|
|
79
|
+
/** Version needed to extract (minimum) */
|
|
80
|
+
versionToExtract: number;
|
|
81
|
+
/** General purpose bit flag
|
|
82
|
+
*
|
|
83
|
+
* - Bit 00: encrypted file
|
|
84
|
+
* - Bit 01: compression option
|
|
85
|
+
* - Bit 02: compression option
|
|
86
|
+
* - Bit 03: data descriptor
|
|
87
|
+
* - Bit 04: enhanced deflation
|
|
88
|
+
* - Bit 05: compressed patched data
|
|
89
|
+
* - Bit 06: strong encryption
|
|
90
|
+
* - Bit 07-10: unused
|
|
91
|
+
* - Bit 11: language encoding
|
|
92
|
+
* - Bit 12: reserved
|
|
93
|
+
* - Bit 13: mask header values
|
|
94
|
+
* - Bit 14-15: reserved
|
|
95
|
+
*/
|
|
96
|
+
generalPurposeBitFlag: number;
|
|
97
|
+
/** Compression method; e.g. none = 0, DEFLATE = 8 (or "\0x08\0x00")
|
|
98
|
+
*
|
|
99
|
+
* - 00: no compression
|
|
100
|
+
* - 01: shrunk
|
|
101
|
+
* - 02: reduced with compression factor 1
|
|
102
|
+
* - 03: reduced with compression factor 2
|
|
103
|
+
* - 04: reduced with compression factor 3
|
|
104
|
+
* - 05: reduced with compression factor 4
|
|
105
|
+
* - 06: imploded
|
|
106
|
+
* - 07: reserved
|
|
107
|
+
* - 08: deflated
|
|
108
|
+
* - 09: enhanced deflated
|
|
109
|
+
* - 10: PKWare DCL imploded
|
|
110
|
+
* - 11: reserved
|
|
111
|
+
* - 12: compressed using BZIP2
|
|
112
|
+
* - 13: reserved
|
|
113
|
+
* - 14: LZMA
|
|
114
|
+
* - 15-17: reserved
|
|
115
|
+
* - 18: compressed using IBM TERSE
|
|
116
|
+
* - 19: IBM LZ77 z
|
|
117
|
+
* - 98: PPMd version I, Rev 1
|
|
118
|
+
*/
|
|
119
|
+
compressionMethod: number;
|
|
120
|
+
/** File last modification time (DOS) */
|
|
121
|
+
lastModifiedTime: number;
|
|
122
|
+
/** File last modification date (DOS) */
|
|
123
|
+
lastModifiedDate: number;
|
|
124
|
+
/** CRC-32 of uncompressed data
|
|
125
|
+
* Value computed over file data by CRC-32 algorithm with
|
|
126
|
+
* 'magic number' 0xdebb20e3 (little endian)
|
|
127
|
+
*/
|
|
128
|
+
crc32: number;
|
|
129
|
+
/** Compressed size (or 0xffffffff for ZIP64) */
|
|
130
|
+
compressedSize: number;
|
|
131
|
+
/** Uncompressed size (or 0xffffffff for ZIP64) */
|
|
132
|
+
uncompressedSize: number;
|
|
133
|
+
/** File name length (n) */
|
|
134
|
+
filenameLength: number;
|
|
135
|
+
/** Extra field length (m) */
|
|
136
|
+
extraFieldLength: number;
|
|
137
|
+
/** File comment length (k) */
|
|
138
|
+
fileCommentLength: number;
|
|
139
|
+
/** Disk number where file starts */
|
|
140
|
+
startingDiskNumber: number;
|
|
141
|
+
/** Internal file attributes
|
|
142
|
+
*
|
|
143
|
+
* Bit 0: apparent ASCII/text file
|
|
144
|
+
* Bit 1: reserved
|
|
145
|
+
* Bit 2: control field records precede logical records
|
|
146
|
+
* Bits 3-16: unused
|
|
147
|
+
*/
|
|
148
|
+
internalFileAttributes: number;
|
|
149
|
+
/** External file attributes (host-system dependent) */
|
|
150
|
+
externalFileAttributes: number;
|
|
151
|
+
/** Relative offset of local file header.
|
|
152
|
+
* This is the number of bytes between the start of the first
|
|
153
|
+
* disk on which the file occurs, and the start of the local file
|
|
154
|
+
* header. This allows software reading the central directory to
|
|
155
|
+
* locate the position of the file inside the ZIP file. */
|
|
156
|
+
localFileHeaderRelativeOffset: number;
|
|
157
|
+
/** File name */
|
|
158
|
+
filename: string;
|
|
159
|
+
/** Extra field
|
|
160
|
+
*
|
|
161
|
+
* Used to store additional information. The field consistes of a sequence of
|
|
162
|
+
* header and data pairs, where the header has a 2 byte identifier and a 2 byte data size field.
|
|
163
|
+
*/
|
|
164
|
+
extraField: ArrayBuffer;
|
|
165
|
+
/** File comment */
|
|
166
|
+
fileComment: string;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
export interface LocalFileHeader {
|
|
170
|
+
meta: {
|
|
171
|
+
compressedData: ArrayBuffer;
|
|
172
|
+
/** If the bit at offset 3 (0x08) of the general-purpose flags field is set,
|
|
173
|
+
* then the CRC-32 and file sizes are not known when the header is written.
|
|
174
|
+
* The fields in the local header are filled with zero, and the CRC-32 and size are
|
|
175
|
+
* appended in a 12-byte structure (optionally preceded by a 4-byte signature) immediately
|
|
176
|
+
* after the compressed data */
|
|
177
|
+
dataDescriptor?: {
|
|
178
|
+
/** Optional data descriptor signature = 0x08074b50 */
|
|
179
|
+
optionalSignature?: ArrayBuffer;
|
|
180
|
+
/** CRC-32 of uncompressed data */
|
|
181
|
+
crc32: number;
|
|
182
|
+
/** Compressed size */
|
|
183
|
+
compressedSize: number;
|
|
184
|
+
/** Uncompressed size */
|
|
185
|
+
uncompressedSize: number;
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
data: {
|
|
189
|
+
/** Local file header signature = 0x04034b50 (PK♥♦ or "PK\3\4") */
|
|
190
|
+
signature: ArrayBuffer;
|
|
191
|
+
/** Version needed to extract (minimum) */
|
|
192
|
+
versionToExtract: number;
|
|
193
|
+
/** General purpose bit flag */
|
|
194
|
+
generalPurposeBitFlag: number;
|
|
195
|
+
/** Compression method; e.g. none = 0, DEFLATE = 8 (or "\0x08\0x00") */
|
|
196
|
+
compressionMethod: number;
|
|
197
|
+
/** File last modification time (DOS format) */
|
|
198
|
+
lastModifiedTime: number;
|
|
199
|
+
/** File last modification date (DOS format) */
|
|
200
|
+
lastModifiedDate: number;
|
|
201
|
+
/** CRC-32 of uncompressed data
|
|
202
|
+
* Value computed over file data by CRC-32 algorithm with
|
|
203
|
+
* 'magic number' 0xdebb20e3 (little endian)
|
|
204
|
+
*/
|
|
205
|
+
crc32: number;
|
|
206
|
+
/** Compressed size (or 0xffffffff for ZIP64) */
|
|
207
|
+
compressedSize: number;
|
|
208
|
+
/** Uncompressed size (or 0xffffffff for ZIP64) */
|
|
209
|
+
uncompressedSize: number;
|
|
210
|
+
/** File name length (n) */
|
|
211
|
+
filenameLength: number;
|
|
212
|
+
/** Extra field length (m) */
|
|
213
|
+
extraFieldLength: number;
|
|
214
|
+
/** File name */
|
|
215
|
+
filename: string;
|
|
216
|
+
/** Extra field */
|
|
217
|
+
extraField: ArrayBuffer;
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* A friendly representation of a file inside a ZIP archive
|
|
222
|
+
*/
|
|
223
|
+
export interface RemoteZipFile {
|
|
224
|
+
/** Full path of the file inside the archive */
|
|
225
|
+
filename: string;
|
|
226
|
+
/** Size in bytes */
|
|
227
|
+
size: number;
|
|
228
|
+
/** ISO timestamp without timezone (ZIP/DOS does not preserve timezones) */
|
|
229
|
+
modified: string;
|
|
230
|
+
/** File attributes of host system */
|
|
231
|
+
attributes: number;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* An initialised object representating a remote ZIP archive.
|
|
235
|
+
*
|
|
236
|
+
* Best constructed from a `RemoteZipPointer`.
|
|
237
|
+
*
|
|
238
|
+
* ```ts
|
|
239
|
+
* import { RemoteZipPointer } from "remote-zip";
|
|
240
|
+
*
|
|
241
|
+
* const url = new URL("http://www.example.com/test.zip");
|
|
242
|
+
* const remoteZip = await new RemoteZipPointer({ url }).populate();
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
export declare class RemoteZip {
|
|
246
|
+
/** Size of the remote ZIP archive in bytes */
|
|
247
|
+
contentLength: number;
|
|
248
|
+
/** URL of the remote ZIP archive */
|
|
249
|
+
url: URL;
|
|
250
|
+
/** Records representing the files in the remote ZIP archive */
|
|
251
|
+
centralDirectoryRecords: CentralDirectoryRecord[];
|
|
252
|
+
/** Metadata of the remote ZIP archive */
|
|
253
|
+
endOfCentralDirectory: EndOfCentralDirectory | null;
|
|
254
|
+
/** HTTP method used to fetch files from the remote ZIP archive */
|
|
255
|
+
method: string;
|
|
256
|
+
/** Credentials passed to `fetch` when retrieving files. Defaults to `same-origin`. */
|
|
257
|
+
credentials: "include" | "omit" | "same-origin";
|
|
258
|
+
/** Redirect mode passed to `fetch`. Defaults to `"follow"`. */
|
|
259
|
+
redirect?: RequestRedirect;
|
|
260
|
+
/** Signal that aborts in-flight requests. */
|
|
261
|
+
signal?: AbortSignal;
|
|
262
|
+
/** Per-request timeout in milliseconds. */
|
|
263
|
+
timeoutMs?: number;
|
|
264
|
+
/** Extra RequestInit merged into every `fetch`. */
|
|
265
|
+
requestInit?: RequestInit;
|
|
266
|
+
constructor({ contentLength, url, centralDirectoryRecords, endOfCentralDirectory, method, credentials, redirect, signal, timeoutMs, requestInit, }: {
|
|
267
|
+
/** Length of the remote ZIP archive in bytes */
|
|
268
|
+
contentLength: number;
|
|
269
|
+
/** Passed to fetch when performing a HTTP GET request for the file */
|
|
270
|
+
url: URL;
|
|
271
|
+
centralDirectoryRecords: CentralDirectoryRecord[];
|
|
272
|
+
endOfCentralDirectory: EndOfCentralDirectory | null;
|
|
273
|
+
/** Passed to fetch when performing a HTTP GET request for the file */
|
|
274
|
+
method: string;
|
|
275
|
+
/** Passed to fetch when performing a HTTP GET request for the file. */
|
|
276
|
+
credentials: "include" | "omit" | "same-origin";
|
|
277
|
+
} & Pick<RemoteZipRequestOptions, "redirect" | "signal" | "timeoutMs" | "requestInit">);
|
|
278
|
+
/** Build a fetch RequestInit from this instance's network options. */
|
|
279
|
+
private requestInitFor;
|
|
280
|
+
/**
|
|
281
|
+
* Get a formatted file listing of the remote ZIP archive.
|
|
282
|
+
*
|
|
283
|
+
* @returns List of files in the remote ZIP archive.
|
|
284
|
+
*
|
|
285
|
+
* ```ts
|
|
286
|
+
* import { RemoteZipPointer } from "remote-zip";
|
|
287
|
+
*
|
|
288
|
+
* const url = new URL("http://www.example.com/test.zip");
|
|
289
|
+
* const remoteZip = await new RemoteZipPointer({ url }).populate();
|
|
290
|
+
* const files = remoteZip.files();
|
|
291
|
+
* // files = [{ attributes: 1107099648, filename: "text.txt", modified: "2021-06-17T12:28:02", size: 14 }]
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
files(): RemoteZipFile[];
|
|
295
|
+
/**
|
|
296
|
+
* Gets a single uncompressed file in the remote ZIP archive.
|
|
297
|
+
*
|
|
298
|
+
* @param path Path of the file in the remote ZIP archive
|
|
299
|
+
* @param additionalHeaders Additional headers, if any, to be passed to the `fetch` request
|
|
300
|
+
* @param options.maxUncompressedSize If set, inflation aborts and throws once the
|
|
301
|
+
* decompressed output would exceed this many bytes. Set this when handling
|
|
302
|
+
* untrusted archives to guard against decompression bombs.
|
|
303
|
+
* @param options.signal Aborts this request (in addition to any instance-level signal).
|
|
304
|
+
* @param options.timeoutMs Per-request timeout for this fetch.
|
|
305
|
+
* @param options.verifyCrc If set, verify the decompressed output against the
|
|
306
|
+
* entry's CRC-32 and throw a {@link RemoteZipError} (`CRC_MISMATCH`) on mismatch.
|
|
307
|
+
* @returns Inflated (uncompressed) bytes of the requested file
|
|
308
|
+
* @throws [RemoteZipError](RemoteZipError) if it fails to parse, fetch, or exceeds limits
|
|
309
|
+
*/
|
|
310
|
+
fetch(path: string, additionalHeaders?: Headers, options?: EntryDecodeOptions): Promise<Uint8Array>;
|
|
311
|
+
/**
|
|
312
|
+
* Decrypt (if needed), decompress, and CRC-verify one entry's bytes. Shared by
|
|
313
|
+
* {@link fetch} and the encrypted path of {@link fetchStream}.
|
|
314
|
+
*/
|
|
315
|
+
private decodeEntry;
|
|
316
|
+
/**
|
|
317
|
+
* Like {@link fetch}, but returns a `ReadableStream` of the uncompressed bytes
|
|
318
|
+
* so large entries can be processed incrementally without buffering the whole
|
|
319
|
+
* file. `maxUncompressedSize` is enforced mid-stream (the stream errors with a
|
|
320
|
+
* {@link RemoteZipError} once exceeded).
|
|
321
|
+
*
|
|
322
|
+
* ```ts
|
|
323
|
+
* const stream = await remoteZip.fetchStream("big.bin");
|
|
324
|
+
* for await (const chunk of stream) {
|
|
325
|
+
* // process each chunk
|
|
326
|
+
* }
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
fetchStream(path: string, additionalHeaders?: Headers, options?: EntryDecodeOptions): Promise<ReadableStream<Uint8Array>>;
|
|
330
|
+
/**
|
|
331
|
+
* Find an entry, reject encrypted ones, and issue the Range request that covers
|
|
332
|
+
* its local file header + compressed data. Shared by {@link fetch} and
|
|
333
|
+
* {@link fetchStream}.
|
|
334
|
+
*/
|
|
335
|
+
private fetchEntryResponse;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Network options shared by every request a {@link RemoteZip} / {@link RemoteZipPointer}
|
|
339
|
+
* makes. All are optional with sensible defaults.
|
|
340
|
+
*/
|
|
341
|
+
export interface RemoteZipRequestOptions {
|
|
342
|
+
/** HTTP method for the Range GET requests. The metadata probe is always a HEAD. Defaults to `"GET"`. */
|
|
343
|
+
method?: string;
|
|
344
|
+
/** Passed to `fetch`. Defaults to `"same-origin"`. */
|
|
345
|
+
credentials?: "include" | "omit" | "same-origin";
|
|
346
|
+
/**
|
|
347
|
+
* Passed to `fetch`. Defaults to `"follow"`. Use `"manual"` or `"error"` to avoid
|
|
348
|
+
* leaking `Authorization`/cookies cross-origin when a server responds with a redirect.
|
|
349
|
+
*/
|
|
350
|
+
redirect?: RequestRedirect;
|
|
351
|
+
/** Aborts in-flight requests when this signal fires. */
|
|
352
|
+
signal?: AbortSignal;
|
|
353
|
+
/** Per-request timeout in milliseconds; combined with `signal` via `AbortSignal.any`. */
|
|
354
|
+
timeoutMs?: number;
|
|
355
|
+
/** Escape hatch merged into every `fetch` RequestInit (lowest precedence — the options above win). */
|
|
356
|
+
requestInit?: RequestInit;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* An uninitialised pointer to a remote ZIP file.
|
|
360
|
+
*
|
|
361
|
+
* No network requests are sent until `populate()` is called.
|
|
362
|
+
*
|
|
363
|
+
* ```ts
|
|
364
|
+
* const url = new URL("http://www.example.com/test.zip");
|
|
365
|
+
* const remoteZip = await new RemoteZipPointer({ url }).populate();
|
|
366
|
+
* const fileListing = remoteZip.files(); // RemoteZipFile[]
|
|
367
|
+
* const uncompressedBytes = await remoteZip.fetch("test.txt"); // Uint8Array
|
|
368
|
+
* ```
|
|
369
|
+
*/
|
|
370
|
+
export declare class RemoteZipPointer {
|
|
371
|
+
/** URL of the remote ZIP archive */
|
|
372
|
+
url: URL;
|
|
373
|
+
/** URL used when performing the HTTP HEAD request to fetch ZIP metadata */
|
|
374
|
+
headUrl: URL;
|
|
375
|
+
/** Additional headers, if any, passed to `fetch` when calling `url` or `headUrl` */
|
|
376
|
+
additionalHeaders?: Headers;
|
|
377
|
+
/** HTTP method used to fetch ZIP metadata (the initial HEAD request is always sent) */
|
|
378
|
+
method: string;
|
|
379
|
+
/** Credentials passed to `fetch` when retrieving files. Defaults to `same-origin`. */
|
|
380
|
+
credentials: "include" | "omit" | "same-origin";
|
|
381
|
+
/** Redirect mode passed to `fetch`. Defaults to `"follow"`. */
|
|
382
|
+
redirect?: RequestRedirect;
|
|
383
|
+
/** Signal that aborts in-flight requests. */
|
|
384
|
+
signal?: AbortSignal;
|
|
385
|
+
/** Per-request timeout in milliseconds. */
|
|
386
|
+
timeoutMs?: number;
|
|
387
|
+
/** Extra RequestInit merged into every `fetch`. */
|
|
388
|
+
requestInit?: RequestInit;
|
|
389
|
+
constructor({ url, headUrl, additionalHeaders, method, credentials, redirect, signal, timeoutMs, requestInit, }: {
|
|
390
|
+
/** URL for GET requests */
|
|
391
|
+
url: URL;
|
|
392
|
+
/** Passed to fetch when performing a HTTP GET request for the file */
|
|
393
|
+
additionalHeaders?: Headers;
|
|
394
|
+
/** Passed to fetch when performing a HTTP GET request for the file */
|
|
395
|
+
method?: string;
|
|
396
|
+
/** Passed to fetch when performing a HTTP GET request for the file */
|
|
397
|
+
credentials?: "include" | "omit" | "same-origin";
|
|
398
|
+
/** URL for HEAD request. Defaults to `url`. This can, for example, differ from `url` if you are using a signed URL for S3. */
|
|
399
|
+
headUrl?: URL;
|
|
400
|
+
} & Pick<RemoteZipRequestOptions, "redirect" | "signal" | "timeoutMs" | "requestInit">);
|
|
401
|
+
/** Build a fetch RequestInit from this pointer's network options. */
|
|
402
|
+
private requestInitFor;
|
|
403
|
+
/**
|
|
404
|
+
* Gets metadata about the ZIP file and constructs an initialised `RemoteZip`.
|
|
405
|
+
*
|
|
406
|
+
* @returns An initialised [RemoteZip](RemoteZip)
|
|
407
|
+
* @throws [RemoteZipError](RemoteZipError) if it fails to parse or fetch
|
|
408
|
+
*/
|
|
409
|
+
populate(): Promise<RemoteZip>;
|
|
410
|
+
private fetchEndOfCentralDirectory;
|
|
411
|
+
private fetchZip64EOCD;
|
|
412
|
+
private fetchCentralDirectoryRecords;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Parses DOS datetime into an ISO string without timezone.
|
|
416
|
+
*
|
|
417
|
+
* @param zipDate DOS date format
|
|
418
|
+
* @param zipTime DOS time format
|
|
419
|
+
* @returns An ISO datetime without timezone. Defaults to `"1980-01-01T00:00:00"` if the datetime is invalid
|
|
420
|
+
* @see https://github.com/Stuk/jszip/blob/112fcdb9953c6b9a2744afee451d73029f7cd2f8/lib/reader/DataReader.js#L105
|
|
421
|
+
*/
|
|
422
|
+
export declare const parseZipDatetime: (zipDate: number, zipTime: number) => string;
|
|
423
|
+
/**
|
|
424
|
+
* Detects whether an EOCD record points at ZIP64 structures this library does
|
|
425
|
+
* not parse yet. Any ZIP64 sentinel value (`0xffff` for 16-bit fields,
|
|
426
|
+
* `0xffffffff` for 32-bit fields) means the real value lives in a ZIP64 EOCD.
|
|
427
|
+
*/
|
|
428
|
+
export declare const isZip64: (eocd: EndOfCentralDirectory) => boolean;
|
|
429
|
+
/** Effective central-directory location from a ZIP64 End Of Central Directory record. */
|
|
430
|
+
export interface Zip64EndOfCentralDirectory {
|
|
431
|
+
centralDirectoryRecordCount: number;
|
|
432
|
+
centralDirectoryByteSize: number;
|
|
433
|
+
centralDirectoryByteOffset: number;
|
|
434
|
+
}
|
|
435
|
+
/** Locate the ZIP64 EOCD locator in a tail buffer and return the ZIP64 EOCD offset. */
|
|
436
|
+
export declare const parseZip64EOCDLocator: (buffer: ArrayBuffer) => {
|
|
437
|
+
zip64EOCDOffset: number;
|
|
438
|
+
} | null;
|
|
439
|
+
/** Parse a ZIP64 End Of Central Directory record (the real CD offset/size/count). */
|
|
440
|
+
export declare const parseZip64EOCD: (buffer: ArrayBuffer) => Zip64EndOfCentralDirectory | null;
|
|
441
|
+
/**
|
|
442
|
+
* Decode a ZIP filename/comment. ZIP entries use CP437 unless general-purpose
|
|
443
|
+
* bit 11 marks the field as UTF-8; ASCII is identical in both.
|
|
444
|
+
*/
|
|
445
|
+
export declare const decodeZipString: (bytes: ArrayBuffer, utf8: boolean) => string;
|
|
446
|
+
export declare const parseAllCDs: (buffer: ArrayBuffer) => CentralDirectoryRecord[];
|
|
447
|
+
export declare const parseOneCD: (buffer: ArrayBuffer) => CentralDirectoryRecord | null;
|
|
448
|
+
export declare const parseOneEOCD: (buffer: ArrayBuffer) => EndOfCentralDirectory | null;
|
|
449
|
+
export declare const parseOneLocalFile: (buffer: ArrayBuffer,
|
|
450
|
+
/** Sometimes, the local header does not have the compressed size and a data descriptor is used after the compressed data.
|
|
451
|
+
* If provided, will be used if the local header indicates a data descriptor block.
|
|
452
|
+
* It is used to find the correct offset for the data descriptor. */
|
|
453
|
+
compressedSizeOverride?: number) => LocalFileHeader | null;
|