@gyng/remote-zip 1.0.0 → 1.0.1
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 +9 -20
- package/lib/cjs/index.js +1 -6
- package/lib/cjs/index.js.map +4 -4
- package/lib/esm/index.mjs +1 -6
- package/lib/esm/index.mjs.map +4 -4
- package/lib/types/crypto.d.mts +39 -0
- package/lib/types/zip.d.mts +12 -6
- package/lib/types/zip.d.ts +11 -5
- package/package.json +47 -55
|
@@ -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>;
|
package/lib/types/zip.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { crc32 } from "./crypto";
|
|
1
|
+
export { crc32 } from "./crypto.mjs";
|
|
2
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";
|
|
3
|
+
export type RemoteZipErrorCode = "UNKNOWN" | "CONTENT_LENGTH_MISSING" | "INVALID_CONTENT_LENGTH" | "HTTP_ERROR" | "RANGE_NOT_SUPPORTED" | "RANGE_RESPONSE_MISMATCH" | "EOCD_NOT_FOUND" | "UNSUPPORTED_ZIP64" | "UNSUPPORTED_ENCRYPTION" | "FILE_NOT_FOUND" | "LOCAL_HEADER_PARSE_FAILED" | "CENTRAL_DIRECTORY_OUT_OF_BOUNDS" | "INVALID_ARCHIVE" | "TRUNCATED_ENTRY" | "UNSUPPORTED_COMPRESSION" | "UNSUPPORTED_MULTI_DISK" | "DECOMPRESSION_LIMIT_EXCEEDED" | "CRC_MISMATCH" | "WRONG_PASSWORD" | "DECRYPTION_FAILED";
|
|
4
4
|
export declare class RemoteZipError extends Error {
|
|
5
5
|
/** Machine-readable error code, for programmatic handling without matching on `message`. */
|
|
6
6
|
code: RemoteZipErrorCode;
|
|
@@ -273,7 +273,7 @@ export declare class RemoteZip {
|
|
|
273
273
|
/** Passed to fetch when performing a HTTP GET request for the file */
|
|
274
274
|
method: string;
|
|
275
275
|
/** Passed to fetch when performing a HTTP GET request for the file. */
|
|
276
|
-
credentials
|
|
276
|
+
credentials?: "include" | "omit" | "same-origin";
|
|
277
277
|
} & Pick<RemoteZipRequestOptions, "redirect" | "signal" | "timeoutMs" | "requestInit">);
|
|
278
278
|
/** Build a fetch RequestInit from this instance's network options. */
|
|
279
279
|
private requestInitFor;
|
|
@@ -305,7 +305,7 @@ export declare class RemoteZip {
|
|
|
305
305
|
* @param options.verifyCrc If set, verify the decompressed output against the
|
|
306
306
|
* entry's CRC-32 and throw a {@link RemoteZipError} (`CRC_MISMATCH`) on mismatch.
|
|
307
307
|
* @returns Inflated (uncompressed) bytes of the requested file
|
|
308
|
-
* @throws
|
|
308
|
+
* @throws {@link RemoteZipError} if it fails to parse, fetch, or exceeds limits
|
|
309
309
|
*/
|
|
310
310
|
fetch(path: string, additionalHeaders?: Headers, options?: EntryDecodeOptions): Promise<Uint8Array>;
|
|
311
311
|
/**
|
|
@@ -333,6 +333,7 @@ export declare class RemoteZip {
|
|
|
333
333
|
* {@link fetchStream}.
|
|
334
334
|
*/
|
|
335
335
|
private fetchEntryResponse;
|
|
336
|
+
private fetchRange;
|
|
336
337
|
}
|
|
337
338
|
/**
|
|
338
339
|
* Network options shared by every request a {@link RemoteZip} / {@link RemoteZipPointer}
|
|
@@ -403,8 +404,8 @@ export declare class RemoteZipPointer {
|
|
|
403
404
|
/**
|
|
404
405
|
* Gets metadata about the ZIP file and constructs an initialised `RemoteZip`.
|
|
405
406
|
*
|
|
406
|
-
* @returns An initialised
|
|
407
|
-
* @throws
|
|
407
|
+
* @returns An initialised {@link RemoteZip}
|
|
408
|
+
* @throws {@link RemoteZipError} if it fails to parse or fetch
|
|
408
409
|
*/
|
|
409
410
|
populate(): Promise<RemoteZip>;
|
|
410
411
|
private fetchEndOfCentralDirectory;
|
|
@@ -428,13 +429,18 @@ export declare const parseZipDatetime: (zipDate: number, zipTime: number) => str
|
|
|
428
429
|
export declare const isZip64: (eocd: EndOfCentralDirectory) => boolean;
|
|
429
430
|
/** Effective central-directory location from a ZIP64 End Of Central Directory record. */
|
|
430
431
|
export interface Zip64EndOfCentralDirectory {
|
|
432
|
+
diskNumber: number;
|
|
433
|
+
cdDisk: number;
|
|
434
|
+
centralDirectoryDiskRecordCount: number;
|
|
431
435
|
centralDirectoryRecordCount: number;
|
|
432
436
|
centralDirectoryByteSize: number;
|
|
433
437
|
centralDirectoryByteOffset: number;
|
|
434
438
|
}
|
|
435
439
|
/** Locate the ZIP64 EOCD locator in a tail buffer and return the ZIP64 EOCD offset. */
|
|
436
440
|
export declare const parseZip64EOCDLocator: (buffer: ArrayBuffer) => {
|
|
441
|
+
diskWithZip64EOCD: number;
|
|
437
442
|
zip64EOCDOffset: number;
|
|
443
|
+
totalDisks: number;
|
|
438
444
|
} | null;
|
|
439
445
|
/** Parse a ZIP64 End Of Central Directory record (the real CD offset/size/count). */
|
|
440
446
|
export declare const parseZip64EOCD: (buffer: ArrayBuffer) => Zip64EndOfCentralDirectory | null;
|
package/lib/types/zip.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { crc32 } from "./crypto";
|
|
2
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";
|
|
3
|
+
export type RemoteZipErrorCode = "UNKNOWN" | "CONTENT_LENGTH_MISSING" | "INVALID_CONTENT_LENGTH" | "HTTP_ERROR" | "RANGE_NOT_SUPPORTED" | "RANGE_RESPONSE_MISMATCH" | "EOCD_NOT_FOUND" | "UNSUPPORTED_ZIP64" | "UNSUPPORTED_ENCRYPTION" | "FILE_NOT_FOUND" | "LOCAL_HEADER_PARSE_FAILED" | "CENTRAL_DIRECTORY_OUT_OF_BOUNDS" | "INVALID_ARCHIVE" | "TRUNCATED_ENTRY" | "UNSUPPORTED_COMPRESSION" | "UNSUPPORTED_MULTI_DISK" | "DECOMPRESSION_LIMIT_EXCEEDED" | "CRC_MISMATCH" | "WRONG_PASSWORD" | "DECRYPTION_FAILED";
|
|
4
4
|
export declare class RemoteZipError extends Error {
|
|
5
5
|
/** Machine-readable error code, for programmatic handling without matching on `message`. */
|
|
6
6
|
code: RemoteZipErrorCode;
|
|
@@ -273,7 +273,7 @@ export declare class RemoteZip {
|
|
|
273
273
|
/** Passed to fetch when performing a HTTP GET request for the file */
|
|
274
274
|
method: string;
|
|
275
275
|
/** Passed to fetch when performing a HTTP GET request for the file. */
|
|
276
|
-
credentials
|
|
276
|
+
credentials?: "include" | "omit" | "same-origin";
|
|
277
277
|
} & Pick<RemoteZipRequestOptions, "redirect" | "signal" | "timeoutMs" | "requestInit">);
|
|
278
278
|
/** Build a fetch RequestInit from this instance's network options. */
|
|
279
279
|
private requestInitFor;
|
|
@@ -305,7 +305,7 @@ export declare class RemoteZip {
|
|
|
305
305
|
* @param options.verifyCrc If set, verify the decompressed output against the
|
|
306
306
|
* entry's CRC-32 and throw a {@link RemoteZipError} (`CRC_MISMATCH`) on mismatch.
|
|
307
307
|
* @returns Inflated (uncompressed) bytes of the requested file
|
|
308
|
-
* @throws
|
|
308
|
+
* @throws {@link RemoteZipError} if it fails to parse, fetch, or exceeds limits
|
|
309
309
|
*/
|
|
310
310
|
fetch(path: string, additionalHeaders?: Headers, options?: EntryDecodeOptions): Promise<Uint8Array>;
|
|
311
311
|
/**
|
|
@@ -333,6 +333,7 @@ export declare class RemoteZip {
|
|
|
333
333
|
* {@link fetchStream}.
|
|
334
334
|
*/
|
|
335
335
|
private fetchEntryResponse;
|
|
336
|
+
private fetchRange;
|
|
336
337
|
}
|
|
337
338
|
/**
|
|
338
339
|
* Network options shared by every request a {@link RemoteZip} / {@link RemoteZipPointer}
|
|
@@ -403,8 +404,8 @@ export declare class RemoteZipPointer {
|
|
|
403
404
|
/**
|
|
404
405
|
* Gets metadata about the ZIP file and constructs an initialised `RemoteZip`.
|
|
405
406
|
*
|
|
406
|
-
* @returns An initialised
|
|
407
|
-
* @throws
|
|
407
|
+
* @returns An initialised {@link RemoteZip}
|
|
408
|
+
* @throws {@link RemoteZipError} if it fails to parse or fetch
|
|
408
409
|
*/
|
|
409
410
|
populate(): Promise<RemoteZip>;
|
|
410
411
|
private fetchEndOfCentralDirectory;
|
|
@@ -428,13 +429,18 @@ export declare const parseZipDatetime: (zipDate: number, zipTime: number) => str
|
|
|
428
429
|
export declare const isZip64: (eocd: EndOfCentralDirectory) => boolean;
|
|
429
430
|
/** Effective central-directory location from a ZIP64 End Of Central Directory record. */
|
|
430
431
|
export interface Zip64EndOfCentralDirectory {
|
|
432
|
+
diskNumber: number;
|
|
433
|
+
cdDisk: number;
|
|
434
|
+
centralDirectoryDiskRecordCount: number;
|
|
431
435
|
centralDirectoryRecordCount: number;
|
|
432
436
|
centralDirectoryByteSize: number;
|
|
433
437
|
centralDirectoryByteOffset: number;
|
|
434
438
|
}
|
|
435
439
|
/** Locate the ZIP64 EOCD locator in a tail buffer and return the ZIP64 EOCD offset. */
|
|
436
440
|
export declare const parseZip64EOCDLocator: (buffer: ArrayBuffer) => {
|
|
441
|
+
diskWithZip64EOCD: number;
|
|
437
442
|
zip64EOCDOffset: number;
|
|
443
|
+
totalDisks: number;
|
|
438
444
|
} | null;
|
|
439
445
|
/** Parse a ZIP64 End Of Central Directory record (the real CD offset/size/count). */
|
|
440
446
|
export declare const parseZip64EOCD: (buffer: ArrayBuffer) => Zip64EndOfCentralDirectory | null;
|
package/package.json
CHANGED
|
@@ -1,45 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gyng/remote-zip",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Fetch file listings and individual files from a remote ZIP archive over HTTP Range requests, without downloading the whole archive.",
|
|
5
|
-
"type": "commonjs",
|
|
6
|
-
"main": "lib/cjs/index.js",
|
|
7
|
-
"module": "lib/esm/index.mjs",
|
|
8
|
-
"types": "lib/types/index.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"import": {
|
|
12
|
-
"types": "./lib/types/index.d.mts",
|
|
13
|
-
"default": "./lib/esm/index.mjs"
|
|
14
|
-
},
|
|
15
|
-
"require": {
|
|
16
|
-
"types": "./lib/types/index.d.ts",
|
|
17
|
-
"default": "./lib/cjs/index.js"
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
"./package.json": "./package.json"
|
|
21
|
-
},
|
|
22
|
-
"sideEffects": false,
|
|
23
|
-
"author": "Ng Guoyou <gyng@users.noreply.github.com>",
|
|
24
|
-
"license": "(MIT OR Apache-2.0)",
|
|
25
5
|
"keywords": [
|
|
26
|
-
"
|
|
27
|
-
"
|
|
6
|
+
"browser",
|
|
7
|
+
"central-directory",
|
|
8
|
+
"fetch",
|
|
28
9
|
"http",
|
|
29
10
|
"range",
|
|
30
|
-
"
|
|
11
|
+
"remote",
|
|
31
12
|
"stream",
|
|
32
|
-
"
|
|
33
|
-
"browser"
|
|
13
|
+
"zip"
|
|
34
14
|
],
|
|
35
15
|
"homepage": "https://github.com/gyng/remote-zip#readme",
|
|
36
16
|
"bugs": {
|
|
37
17
|
"url": "https://github.com/gyng/remote-zip/issues"
|
|
38
18
|
},
|
|
39
|
-
"
|
|
40
|
-
|
|
19
|
+
"license": "(MIT OR Apache-2.0)",
|
|
20
|
+
"author": "Ng Guoyou <gyng@users.noreply.github.com>",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/gyng/remote-zip.git"
|
|
41
24
|
},
|
|
42
|
-
"packageManager": "npm@11.11.0",
|
|
43
25
|
"files": [
|
|
44
26
|
"LICENSE-MIT",
|
|
45
27
|
"LICENSE-APACHE",
|
|
@@ -47,45 +29,55 @@
|
|
|
47
29
|
"package.json",
|
|
48
30
|
"lib/**"
|
|
49
31
|
],
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
32
|
+
"type": "commonjs",
|
|
33
|
+
"sideEffects": false,
|
|
34
|
+
"main": "lib/cjs/index.js",
|
|
35
|
+
"module": "lib/esm/index.mjs",
|
|
36
|
+
"types": "lib/types/index.d.ts",
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"import": {
|
|
40
|
+
"types": "./lib/types/index.d.mts",
|
|
41
|
+
"default": "./lib/esm/index.mjs"
|
|
42
|
+
},
|
|
43
|
+
"require": {
|
|
44
|
+
"types": "./lib/types/index.d.ts",
|
|
45
|
+
"default": "./lib/cjs/index.js"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"./package.json": "./package.json"
|
|
53
49
|
},
|
|
54
50
|
"scripts": {
|
|
55
51
|
"build": "rm -rf lib/* && npm run ts-types && node ./esbuild.mjs",
|
|
56
52
|
"d": "WATCH=1 npm run build",
|
|
57
|
-
"doc:gen": "
|
|
53
|
+
"doc:gen": "npm --prefix tools/typedoc run generate",
|
|
58
54
|
"doc:site": "npm run build && npm run doc:gen && node ./scripts/build-site.mjs",
|
|
59
|
-
"lint:
|
|
60
|
-
"lint
|
|
61
|
-
"lint:fix": "npm run lint:prettier:fix && npm run lint:eslint:fix",
|
|
62
|
-
"lint:prettier:fix": "prettier --write .",
|
|
63
|
-
"lint:prettier": "prettier --check .",
|
|
64
|
-
"lint": "npm run lint:prettier && npm run lint:eslint",
|
|
55
|
+
"lint:fix": "oxfmt . && oxlint --type-aware --import-plugin --vitest-plugin --fix .",
|
|
56
|
+
"lint": "oxfmt --check . && oxlint --type-aware --import-plugin --vitest-plugin .",
|
|
65
57
|
"t:watch": "vitest",
|
|
66
58
|
"t": "npm test",
|
|
67
59
|
"test:coverage": "vitest run --coverage",
|
|
60
|
+
"test:package": "npm run build && node ./scripts/test-package.mjs",
|
|
68
61
|
"test": "vitest run",
|
|
69
62
|
"ts-types": "tsc -p tsconfig.build.json",
|
|
70
63
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
71
64
|
"prepublishOnly": "npm run build"
|
|
72
65
|
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"pako": "^3.0.1"
|
|
68
|
+
},
|
|
73
69
|
"devDependencies": {
|
|
74
|
-
"@
|
|
75
|
-
"@
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"prettier": "^3.8.3",
|
|
83
|
-
"typedoc": "^0.28.19",
|
|
84
|
-
"typescript": "~6.0",
|
|
85
|
-
"typescript-eslint": "^8.61.0",
|
|
86
|
-
"vitest": "^4.1.0"
|
|
70
|
+
"@types/node": "^26.1.1",
|
|
71
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
72
|
+
"esbuild": "^0.28.1",
|
|
73
|
+
"oxfmt": "^0.58.0",
|
|
74
|
+
"oxlint": "^1.73.0",
|
|
75
|
+
"oxlint-tsgolint": "^0.24.0",
|
|
76
|
+
"typescript": "~7.0.2",
|
|
77
|
+
"vitest": "^4.1.10"
|
|
87
78
|
},
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
}
|
|
79
|
+
"engines": {
|
|
80
|
+
"node": ">=22"
|
|
81
|
+
},
|
|
82
|
+
"packageManager": "npm@11.11.0"
|
|
91
83
|
}
|