neozipkit 0.1.1 → 0.3.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 +22 -0
- package/README.md +371 -200
- package/contracts/ABI.txt +889 -0
- package/contracts/Bytecode.txt +1 -0
- package/contracts/COMPILATION_NOTES.md +59 -0
- package/contracts/QUICK_DEPLOY.md +286 -0
- package/contracts/README.md +256 -0
- package/contracts/VERIFICATION.md +308 -0
- package/contracts/deploy-interactive.js +448 -0
- package/contracts/deployment-arbitrum-sepolia.json +12 -0
- package/contracts/deployment-arbitrum.json +12 -0
- package/contracts/deployment-eth-sepolia.json +12 -0
- package/contracts/hardhat.config.js +114 -0
- package/contracts/package.json +20 -0
- package/contracts/scripts/compile-and-extract.js +119 -0
- package/contracts/scripts/verify-contract.js +223 -0
- package/contracts/src/{NZIP-NFT-Private.sol → NZIP-NFT-v2.0.sol} +66 -151
- package/contracts/src/NZIP-NFT.sol +9 -15
- package/dist/{browser → blockchain/browser}/TokenVerifierBrowser.d.ts +11 -20
- package/dist/blockchain/browser/TokenVerifierBrowser.d.ts.map +1 -0
- package/dist/{browser → blockchain/browser}/TokenVerifierBrowser.js +106 -92
- package/dist/blockchain/browser/TokenVerifierBrowser.js.map +1 -0
- package/dist/blockchain/browser/WalletManagerBrowser.d.ts +98 -0
- package/dist/blockchain/browser/WalletManagerBrowser.d.ts.map +1 -0
- package/dist/blockchain/browser/WalletManagerBrowser.js +434 -0
- package/dist/blockchain/browser/WalletManagerBrowser.js.map +1 -0
- package/dist/blockchain/browser/ZipkitMinterBrowser.d.ts +58 -0
- package/dist/blockchain/browser/ZipkitMinterBrowser.d.ts.map +1 -0
- package/dist/blockchain/browser/ZipkitMinterBrowser.js +317 -0
- package/dist/blockchain/browser/ZipkitMinterBrowser.js.map +1 -0
- package/dist/blockchain/browser/index.d.ts +11 -0
- package/dist/blockchain/browser/index.d.ts.map +1 -0
- package/dist/blockchain/browser/index.js +16 -0
- package/dist/blockchain/browser/index.js.map +1 -0
- package/dist/{server/blockchain/WalletAnalyzer.d.ts → blockchain/core/WalletManager.d.ts} +69 -26
- package/dist/blockchain/core/WalletManager.d.ts.map +1 -0
- package/dist/{server/blockchain/WalletAnalyzer.js → blockchain/core/WalletManager.js} +172 -160
- package/dist/blockchain/core/WalletManager.js.map +1 -0
- package/dist/blockchain/core/ZipkitMinter.d.ts +141 -0
- package/dist/blockchain/core/ZipkitMinter.d.ts.map +1 -0
- package/dist/blockchain/core/ZipkitMinter.js +548 -0
- package/dist/blockchain/core/ZipkitMinter.js.map +1 -0
- package/dist/blockchain/core/ZipkitOTS.d.ts +126 -0
- package/dist/blockchain/core/ZipkitOTS.d.ts.map +1 -0
- package/dist/blockchain/core/ZipkitOTS.js +506 -0
- package/dist/blockchain/core/ZipkitOTS.js.map +1 -0
- package/dist/blockchain/core/ZipkitVerifier.d.ts +177 -0
- package/dist/blockchain/core/ZipkitVerifier.d.ts.map +1 -0
- package/dist/blockchain/core/ZipkitVerifier.js +632 -0
- package/dist/blockchain/core/ZipkitVerifier.js.map +1 -0
- package/dist/blockchain/core/contracts.d.ts +83 -0
- package/dist/blockchain/core/contracts.d.ts.map +1 -0
- package/dist/blockchain/core/contracts.js +341 -0
- package/dist/blockchain/core/contracts.js.map +1 -0
- package/dist/blockchain/core/index.d.ts +12 -0
- package/dist/blockchain/core/index.d.ts.map +1 -0
- package/dist/blockchain/core/index.js +59 -0
- package/dist/blockchain/core/index.js.map +1 -0
- package/dist/blockchain/index.d.ts +11 -0
- package/dist/blockchain/index.d.ts.map +1 -0
- package/dist/blockchain/index.js +34 -0
- package/dist/blockchain/index.js.map +1 -0
- package/dist/blockchain/node/WalletManagerNode.d.ts +47 -0
- package/dist/blockchain/node/WalletManagerNode.d.ts.map +1 -0
- package/dist/blockchain/node/WalletManagerNode.js +203 -0
- package/dist/blockchain/node/WalletManagerNode.js.map +1 -0
- package/dist/blockchain/node/index.d.ts +12 -0
- package/dist/blockchain/node/index.d.ts.map +1 -0
- package/dist/blockchain/node/index.js +24 -0
- package/dist/blockchain/node/index.js.map +1 -0
- package/dist/browser/ZipkitBrowser.d.ts +27 -0
- package/dist/browser/ZipkitBrowser.d.ts.map +1 -0
- package/dist/browser/{ZipKitBrowser.js → ZipkitBrowser.js} +96 -43
- package/dist/browser/ZipkitBrowser.js.map +1 -0
- package/dist/browser/index.d.ts +12 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +42 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser-esm/index.d.ts +12 -0
- package/dist/browser-esm/index.js +59559 -0
- package/dist/browser-esm/index.js.map +7 -0
- package/dist/browser-umd/index.d.ts +12 -0
- package/dist/browser-umd/index.js +59576 -0
- package/dist/browser-umd/index.js.map +7 -0
- package/dist/browser-umd/index.min.js +63 -0
- package/dist/browser.d.ts +8 -17
- package/dist/browser.js +13 -29
- package/dist/core/ZipCompress.d.ts +99 -0
- package/dist/core/ZipCompress.d.ts.map +1 -0
- package/dist/core/ZipCompress.js +309 -0
- package/dist/core/ZipCompress.js.map +1 -0
- package/dist/core/ZipDecompress.d.ts +58 -0
- package/dist/core/ZipDecompress.d.ts.map +1 -0
- package/dist/core/ZipDecompress.js +172 -0
- package/dist/core/ZipDecompress.js.map +1 -0
- package/dist/{shared → core}/ZipEntry.d.ts +8 -1
- package/dist/core/ZipEntry.d.ts.map +1 -0
- package/dist/{shared → core}/ZipEntry.js +224 -81
- package/dist/core/ZipEntry.js.map +1 -0
- package/dist/core/Zipkit.d.ts +315 -0
- package/dist/core/Zipkit.d.ts.map +1 -0
- package/dist/core/Zipkit.js +647 -0
- package/dist/core/Zipkit.js.map +1 -0
- package/dist/core/components/HashCalculator.d.ts +138 -0
- package/dist/core/components/HashCalculator.d.ts.map +1 -0
- package/dist/core/components/HashCalculator.js +360 -0
- package/dist/core/components/HashCalculator.js.map +1 -0
- package/dist/core/components/Logger.d.ts +73 -0
- package/dist/core/components/Logger.d.ts.map +1 -0
- package/dist/core/components/Logger.js +156 -0
- package/dist/core/components/Logger.js.map +1 -0
- package/dist/core/components/ProgressTracker.d.ts +43 -0
- package/dist/core/components/ProgressTracker.d.ts.map +1 -0
- package/dist/core/components/ProgressTracker.js +112 -0
- package/dist/core/components/ProgressTracker.js.map +1 -0
- package/dist/{shared → core}/components/Support.d.ts +1 -0
- package/dist/core/components/Support.d.ts.map +1 -0
- package/dist/{shared → core}/components/Support.js +1 -0
- package/dist/core/components/Support.js.map +1 -0
- package/dist/{shared → core}/components/Util.d.ts +7 -2
- package/dist/core/components/Util.d.ts.map +1 -0
- package/dist/{shared → core}/components/Util.js +14 -34
- package/dist/core/components/Util.js.map +1 -0
- package/dist/{shared → core}/constants/Errors.d.ts +1 -2
- package/dist/core/constants/Errors.d.ts.map +1 -0
- package/dist/{shared → core}/constants/Errors.js +1 -3
- package/dist/core/constants/Errors.js.map +1 -0
- package/dist/{shared → core}/constants/Headers.d.ts +3 -0
- package/dist/core/constants/Headers.d.ts.map +1 -0
- package/dist/{shared → core}/constants/Headers.js +20 -17
- package/dist/core/constants/Headers.js.map +1 -0
- package/dist/core/encryption/Manager.d.ts +58 -0
- package/dist/core/encryption/Manager.d.ts.map +1 -0
- package/dist/core/encryption/Manager.js +121 -0
- package/dist/core/encryption/Manager.js.map +1 -0
- package/dist/core/encryption/ZipCrypto.d.ts +172 -0
- package/dist/core/encryption/ZipCrypto.d.ts.map +1 -0
- package/dist/core/encryption/ZipCrypto.js +554 -0
- package/dist/core/encryption/ZipCrypto.js.map +1 -0
- package/dist/core/encryption/index.d.ts +9 -0
- package/dist/core/encryption/index.d.ts.map +1 -0
- package/dist/core/encryption/index.js +17 -0
- package/dist/core/encryption/index.js.map +1 -0
- package/dist/core/encryption/types.d.ts +29 -0
- package/dist/core/encryption/types.d.ts.map +1 -0
- package/dist/core/encryption/types.js +12 -0
- package/dist/core/encryption/types.js.map +1 -0
- package/dist/core/index.d.ts +24 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +57 -0
- package/dist/core/index.js.map +1 -0
- package/dist/{shared → core}/version.d.ts +1 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +31 -0
- package/dist/core/version.js.map +1 -0
- package/dist/index.d.ts +8 -25
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -47
- package/dist/index.js.map +1 -0
- package/dist/node/ZipCompressNode.d.ts +123 -0
- package/dist/node/ZipCompressNode.d.ts.map +1 -0
- package/dist/node/ZipCompressNode.js +576 -0
- package/dist/node/ZipCompressNode.js.map +1 -0
- package/dist/node/ZipDecompressNode.d.ts +120 -0
- package/dist/node/ZipDecompressNode.d.ts.map +1 -0
- package/dist/node/ZipDecompressNode.js +461 -0
- package/dist/node/ZipDecompressNode.js.map +1 -0
- package/dist/node/ZipkitNode.d.ts +406 -0
- package/dist/node/ZipkitNode.d.ts.map +1 -0
- package/dist/node/ZipkitNode.js +1305 -0
- package/dist/node/ZipkitNode.js.map +1 -0
- package/dist/node/index.d.ts +26 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +65 -0
- package/dist/node/index.js.map +1 -0
- package/dist/types/index.d.ts +59 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +36 -1
- package/dist/types/index.js.map +1 -0
- package/examples/README.md +269 -0
- package/examples/blockchain-tokenize.ts +354 -0
- package/examples/create-zip.ts +172 -0
- package/examples/extract-zip.ts +158 -0
- package/examples/list-zip.ts +161 -0
- package/examples/test-files/data.json +116 -0
- package/examples/test-files/document.md +80 -0
- package/examples/test-files/document.txt +2 -0
- package/examples/test-files/file1.txt +48 -0
- package/examples/test-files/file2.txt +80 -0
- package/examples/tsconfig.json +44 -0
- package/examples/unzip-token.ts +6 -3
- package/examples/verify-tokenized-zip.ts +305 -0
- package/package.json +117 -23
- package/src/blockchain/README.md +222 -0
- package/src/{browser → blockchain/browser}/TokenVerifierBrowser.ts +125 -79
- package/src/blockchain/browser/WalletManagerBrowser.ts +486 -0
- package/src/blockchain/browser/ZipkitMinterBrowser.ts +400 -0
- package/src/blockchain/browser/index.ts +13 -0
- package/src/blockchain/core/WalletManager.ts +436 -0
- package/src/blockchain/core/ZipkitMinter.ts +716 -0
- package/src/blockchain/core/ZipkitOTS.ts +588 -0
- package/src/blockchain/core/ZipkitVerifier.ts +853 -0
- package/src/blockchain/core/contracts.ts +370 -0
- package/src/blockchain/core/index.ts +71 -0
- package/src/blockchain/index.ts +27 -0
- package/src/blockchain/node/WalletManagerNode.ts +171 -0
- package/src/blockchain/node/index.ts +40 -0
- package/src/browser/{ZipKitBrowser.ts → ZipkitBrowser.ts} +104 -41
- package/src/browser/index.esm.ts +37 -0
- package/src/browser/index.ts +25 -0
- package/src/core/ZipCompress.ts +398 -0
- package/src/core/ZipDecompress.ts +212 -0
- package/src/{shared → core}/ZipEntry.ts +239 -89
- package/src/core/Zipkit.ts +794 -0
- package/src/core/components/HashCalculator.ts +384 -0
- package/src/core/components/Logger.ts +180 -0
- package/src/core/components/ProgressTracker.ts +134 -0
- package/src/{shared → core}/components/Util.ts +12 -34
- package/src/{shared → core}/constants/Errors.ts +0 -4
- package/src/{shared → core}/constants/Headers.ts +19 -17
- package/src/core/encryption/Manager.ts +137 -0
- package/src/core/encryption/ZipCrypto.ts +650 -0
- package/src/core/encryption/index.ts +15 -0
- package/src/core/encryption/types.ts +33 -0
- package/src/core/index.ts +34 -0
- package/src/core/version.ts +33 -0
- package/src/index.ts +54 -32
- package/src/node/ZipCompressNode.ts +632 -0
- package/src/node/ZipDecompressNode.ts +508 -0
- package/src/node/ZipkitNode.ts +1559 -0
- package/src/node/index.ts +69 -0
- package/src/types/index.ts +131 -1
- package/src/types/opentimestamps.d.ts +1 -23
- package/contracts/Lock.sol +0 -34
- package/contracts/bytecode.txt +0 -1
- package/contracts/compile-contract.js +0 -168
- package/contracts/deploy/deploy-both-contracts.js +0 -286
- package/contracts/deploy/deploy-enhanced-contract.js +0 -197
- package/contracts/deploy/deploy-private-contract.js +0 -190
- package/contracts/deploy/deploy-public-clean.js +0 -1063
- package/contracts/deploy/deploy-public-contract.js +0 -1107
- package/contracts/deployment.config.example.js +0 -25
- package/contracts/remix-compile.js +0 -222
- package/contracts/setup-deployment.js +0 -51
- package/contracts/src/ZipFileNFT-DEPRECATED-6field.sol +0 -260
- package/contracts/src/ZipFileNFT-DEPRECATED-Enhanced.sol +0 -289
- package/dist/browser/CertificateGeneratorBrowser.d.ts +0 -75
- package/dist/browser/CertificateGeneratorBrowser.js +0 -433
- package/dist/browser/ZipKitBrowser.d.ts +0 -18
- package/dist/browser/ZipKitStampBrowser.d.ts +0 -2
- package/dist/browser/ZipKitStampBrowser.js +0 -12
- package/dist/browser-index.d.ts +0 -21
- package/dist/browser-index.js +0 -58
- package/dist/server/blockchain/CertificateToken.d.ts +0 -48
- package/dist/server/blockchain/CertificateToken.js +0 -386
- package/dist/server/blockchain/NFTMinter.d.ts +0 -41
- package/dist/server/blockchain/NFTMinter.js +0 -323
- package/dist/server/blockchain/TokenQuerier.d.ts +0 -31
- package/dist/server/blockchain/TokenQuerier.js +0 -259
- package/dist/server/blockchain/TokenVerifier.d.ts +0 -20
- package/dist/server/blockchain/TokenVerifier.js +0 -395
- package/dist/server/blockchain/WalletFormatter.d.ts +0 -39
- package/dist/server/blockchain/WalletFormatter.js +0 -196
- package/dist/server/blockchain/WalletManager.d.ts +0 -46
- package/dist/server/blockchain/WalletManager.js +0 -294
- package/dist/server/blockchain/ZipMetadata.d.ts +0 -27
- package/dist/server/blockchain/ZipMetadata.js +0 -131
- package/dist/server/blockchain/ZipTokenProcessor.d.ts +0 -44
- package/dist/server/blockchain/ZipTokenProcessor.js +0 -204
- package/dist/server/blockchain/constants.d.ts +0 -102
- package/dist/server/blockchain/constants.js +0 -968
- package/dist/server/blockchain/index.d.ts +0 -9
- package/dist/server/blockchain/index.js +0 -44
- package/dist/server/blockchain/test-certificate.d.ts +0 -8
- package/dist/server/blockchain/test-certificate.js +0 -100
- package/dist/server/blockchain/types.d.ts +0 -69
- package/dist/server/blockchain/types.js +0 -51
- package/dist/server/platform/server/ZipKitServer.d.ts +0 -105
- package/dist/server/platform/server/ZipKitServer.js +0 -437
- package/dist/server/platform/servercomponents/ZipKitOTS.d.ts +0 -91
- package/dist/server/platform/servercomponents/ZipKitOTS.js +0 -271
- package/dist/shared/ZipKit.d.ts +0 -249
- package/dist/shared/ZipKit.js +0 -789
- package/dist/shared/components/CertificateOTS.d.ts +0 -15
- package/dist/shared/components/CertificateOTS.js +0 -116
- package/dist/shared/components/FileSys.d.ts +0 -2
- package/dist/shared/components/FileSys.js +0 -113
- package/dist/shared/components/HashAccumulator.d.ts +0 -55
- package/dist/shared/components/HashAccumulator.js +0 -100
- package/dist/shared/components/ZipCrypto.d.ts +0 -3
- package/dist/shared/components/ZipCrypto.js +0 -78
- package/dist/shared/components/merkleTree.d.ts +0 -66
- package/dist/shared/components/merkleTree.js +0 -136
- package/dist/shared/types/index.d.ts +0 -21
- package/dist/shared/types/index.js +0 -3
- package/dist/shared/types.d.ts +0 -33
- package/dist/shared/types.js +0 -8
- package/dist/shared/version.js +0 -7
- package/src/browser/CertificateGeneratorBrowser.ts +0 -498
- package/src/browser/ZipKitStampBrowser.ts +0 -9
- package/src/browser-index.ts +0 -36
- package/src/server/blockchain/CertificateToken.ts +0 -444
- package/src/server/blockchain/NFTMinter.ts +0 -357
- package/src/server/blockchain/TokenQuerier.ts +0 -287
- package/src/server/blockchain/TokenVerifier.ts +0 -453
- package/src/server/blockchain/WalletAnalyzer.ts +0 -397
- package/src/server/blockchain/WalletFormatter.ts +0 -206
- package/src/server/blockchain/WalletManager.ts +0 -294
- package/src/server/blockchain/ZipMetadata.ts +0 -117
- package/src/server/blockchain/ZipTokenProcessor.ts +0 -234
- package/src/server/blockchain/constants.ts +0 -969
- package/src/server/blockchain/index.ts +0 -42
- package/src/server/blockchain/test-certificate.ts +0 -137
- package/src/server/blockchain/types.ts +0 -134
- package/src/server/platform/server/ZipKitServer.ts +0 -459
- package/src/server/platform/servercomponents/ZipKitOTS.ts +0 -313
- package/src/server/platform/servercomponents/opentimestamps.d.ts +0 -23
- package/src/shared/ZipKit.ts +0 -899
- package/src/shared/components/CertificateOTS.ts +0 -132
- package/src/shared/components/FileSys.ts +0 -87
- package/src/shared/components/HashAccumulator.ts +0 -113
- package/src/shared/components/ZipCrypto.ts +0 -91
- package/src/shared/components/merkleTree.ts +0 -162
- package/src/shared/types/index.ts +0 -25
- package/src/shared/types/modules.d.ts +0 -22
- package/src/shared/types/opentimestamps.d.ts +0 -23
- package/src/shared/types.d.ts +0 -8
- package/src/shared/types.ts +0 -43
- package/src/shared/version.ts +0 -4
- /package/src/{shared → core}/components/Support.ts +0 -0
|
@@ -1,39 +1,41 @@
|
|
|
1
1
|
// ======================================
|
|
2
|
-
//
|
|
2
|
+
// ZipkitBrowser.ts
|
|
3
3
|
// Copyright (c) 2025 NeoWare, Inc. All rights reserved.
|
|
4
4
|
// ======================================
|
|
5
5
|
|
|
6
|
-
import
|
|
7
|
-
import ZipEntry from '../
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import { crc32 } from '../
|
|
13
|
-
import { DATATYPE, getTypeOf } from '../
|
|
14
|
-
import type { FileData } from '../
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export
|
|
6
|
+
import Zipkit, { CompressOptions, CreateZipOptions } from '../core';
|
|
7
|
+
import ZipEntry from '../core/ZipEntry';
|
|
8
|
+
import { ZipCompress } from '../core/ZipCompress';
|
|
9
|
+
import Errors from '../core/constants/Errors';
|
|
10
|
+
import * as Headers from '../core/constants/Headers';
|
|
11
|
+
import { TOKENIZED_METADATA, TIMESTAMP_SUBMITTED, TIMESTAMP_METADATA } from '../core/constants/Headers';
|
|
12
|
+
import { sha256, crc32 } from '../core/encryption/ZipCrypto';
|
|
13
|
+
import { DATATYPE, getTypeOf } from '../core/components/Util';
|
|
14
|
+
import type { FileData } from '../types';
|
|
15
|
+
import HashCalculator from '../core/components/HashCalculator';
|
|
16
|
+
|
|
17
|
+
// Re-export everything from Zipkit
|
|
18
|
+
export * from '../core';
|
|
18
19
|
export { ZipEntry, Errors, Headers, sha256, getTypeOf };
|
|
19
20
|
|
|
20
21
|
// ======================================
|
|
21
|
-
//
|
|
22
|
+
// ZipkitBrowser
|
|
22
23
|
// ======================================
|
|
23
24
|
|
|
24
|
-
export default class
|
|
25
|
+
export default class ZipkitBrowser extends Zipkit {
|
|
25
26
|
constructor() {
|
|
26
27
|
super(); // Call the parent constructor
|
|
27
28
|
|
|
28
|
-
// console.log('
|
|
29
|
-
// console.log('
|
|
30
|
-
// console.log('
|
|
31
|
-
// console.log('
|
|
32
|
-
// console.log('
|
|
29
|
+
// console.log('Zipkit.support.isNode: ', Zipkit.support.isNode);
|
|
30
|
+
// console.log('Zipkit.support.buffer: ', Zipkit.support.buffer);
|
|
31
|
+
// console.log('Zipkit.support.blob: ', Zipkit.support.blob);
|
|
32
|
+
// console.log('Zipkit.support.streams: ', Zipkit.support.streams);
|
|
33
|
+
// console.log('Zipkit.support.fileReader: ', Zipkit.support.fileReader);
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
// --------------------------------------
|
|
36
37
|
// Load a ZIP file from a Blob and return the ZipEntry array
|
|
38
|
+
// Always uses loadZip() to ensure proper initialization
|
|
37
39
|
|
|
38
40
|
async loadZipBlob(data: Blob): Promise<ZipEntry[] | null> {
|
|
39
41
|
if (getTypeOf(data) !== DATATYPE.BLOB) {
|
|
@@ -41,30 +43,34 @@ export default class ZipKitBrowser extends ZipKit {
|
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
return new Promise((resolve, reject) => {
|
|
44
|
-
const _readEntries = (data: Buffer): ZipEntry[] | null => {
|
|
45
|
-
try {
|
|
46
|
-
super.loadZip(data);
|
|
47
|
-
return super.getDirectory();
|
|
48
|
-
} catch (error) {
|
|
49
|
-
reject(error);
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
46
|
const reader = new window.FileReader();
|
|
55
47
|
reader.readAsArrayBuffer(data);
|
|
56
48
|
|
|
57
|
-
reader.onload =
|
|
58
|
-
if (!
|
|
49
|
+
reader.onload = (e: ProgressEvent<FileReader>) => {
|
|
50
|
+
if (!reader.result) {
|
|
59
51
|
reject(new Error('Failed to read file'));
|
|
60
52
|
return;
|
|
61
53
|
}
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
// Convert ArrayBuffer to Buffer
|
|
57
|
+
const buffer = Buffer.from(reader.result as ArrayBuffer);
|
|
58
|
+
|
|
59
|
+
// Always use loadZip() which:
|
|
60
|
+
// 1. Resets ZIP data
|
|
61
|
+
// 2. Stores buffer in this.inBuffer
|
|
62
|
+
// 3. Loads EOCD and parses central directory
|
|
63
|
+
// 4. Stores entries in this.zipEntries
|
|
64
|
+
// 5. Returns the entries
|
|
65
|
+
const entries = super.loadZip(buffer);
|
|
66
|
+
resolve(entries);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
reject(error);
|
|
69
|
+
}
|
|
64
70
|
};
|
|
65
71
|
|
|
66
|
-
reader.onerror =
|
|
67
|
-
reject(
|
|
72
|
+
reader.onerror = () => {
|
|
73
|
+
reject(reader.error || new Error('Failed to read file'));
|
|
68
74
|
};
|
|
69
75
|
});
|
|
70
76
|
}
|
|
@@ -104,7 +110,8 @@ export default class ZipKitBrowser extends ZipKit {
|
|
|
104
110
|
|
|
105
111
|
return new Promise(async (resolve, reject) => {
|
|
106
112
|
const _compressData = async (entry: ZipEntry, data: Buffer, options?: CompressOptions): Promise<Buffer> => {
|
|
107
|
-
|
|
113
|
+
// Use Zipkit wrapper method
|
|
114
|
+
return await this.compressData(entry, data, options);
|
|
108
115
|
};
|
|
109
116
|
|
|
110
117
|
const reader = new window.FileReader();
|
|
@@ -135,7 +142,7 @@ export default class ZipKitBrowser extends ZipKit {
|
|
|
135
142
|
|
|
136
143
|
async extractBlob(entry: ZipEntry, skipHashCheck?: boolean): Promise<Blob | null> {
|
|
137
144
|
try {
|
|
138
|
-
const _outBuf = await
|
|
145
|
+
const _outBuf = await this.extract(entry, skipHashCheck);
|
|
139
146
|
if (!_outBuf) return null;
|
|
140
147
|
|
|
141
148
|
// Convert Buffer to Uint8Array for Blob compatibility
|
|
@@ -170,7 +177,7 @@ export default class ZipKitBrowser extends ZipKit {
|
|
|
170
177
|
entry.isUpdated = true;
|
|
171
178
|
// Don't continue here - let it fall through to special handling below
|
|
172
179
|
} else {
|
|
173
|
-
const inData = super.copyEntry(entry);
|
|
180
|
+
const inData = await super.copyEntry(entry);
|
|
174
181
|
entry.localHdrOffset = offset;
|
|
175
182
|
offset += inData.length;
|
|
176
183
|
buffers.push(inData);
|
|
@@ -186,6 +193,19 @@ export default class ZipKitBrowser extends ZipKit {
|
|
|
186
193
|
|
|
187
194
|
const fileBuffer = await entry.fileData.arrayBuffer();
|
|
188
195
|
|
|
196
|
+
// Special handling for already-compressed entries - use existing compressed data
|
|
197
|
+
if (entry.cmpData && entry.compressedSize && entry.crc) {
|
|
198
|
+
// Entry is already compressed, use the existing compressed data
|
|
199
|
+
const localHdr = entry.createLocalHdr();
|
|
200
|
+
entry.localHdrOffset = offset;
|
|
201
|
+
offset += localHdr.length + entry.cmpData.length;
|
|
202
|
+
|
|
203
|
+
buffers.push(localHdr);
|
|
204
|
+
buffers.push(entry.cmpData);
|
|
205
|
+
_onEntryDone(entry, 'Written (pre-compressed)');
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
|
|
189
209
|
// Special handling for token metadata files - store uncompressed with CRC-32
|
|
190
210
|
if (entry.filename === TOKENIZED_METADATA || entry.filename === TIMESTAMP_SUBMITTED || entry.filename === TIMESTAMP_METADATA) {
|
|
191
211
|
// For token metadata, use STORED compression (no compression)
|
|
@@ -211,7 +231,7 @@ export default class ZipKitBrowser extends ZipKit {
|
|
|
211
231
|
_onEntryDone(entry, 'Stored (metadata)');
|
|
212
232
|
} else {
|
|
213
233
|
// Normal file processing with compression
|
|
214
|
-
const cmpData = await
|
|
234
|
+
const cmpData = await this.compressData(entry, Buffer.from(fileBuffer), cmpOptions);
|
|
215
235
|
const localHdr = entry.createLocalHdr();
|
|
216
236
|
|
|
217
237
|
entry.localHdrOffset = offset;
|
|
@@ -238,5 +258,48 @@ export default class ZipKitBrowser extends ZipKit {
|
|
|
238
258
|
// Convert Buffer to Uint8Array for Blob compatibility
|
|
239
259
|
const uint8Array = new Uint8Array(combinedBuffer);
|
|
240
260
|
return new Blob([uint8Array], { type: 'application/zip' });
|
|
241
|
-
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Checks if a filename is a blockchain metadata file that should be excluded from Merkle Root calculation
|
|
265
|
+
* @param filename - The filename to check
|
|
266
|
+
* @returns boolean - True if the file is a metadata file
|
|
267
|
+
*/
|
|
268
|
+
private isMetadataFile(filename: string): boolean {
|
|
269
|
+
return filename === TIMESTAMP_SUBMITTED ||
|
|
270
|
+
filename === TIMESTAMP_METADATA ||
|
|
271
|
+
filename === TOKENIZED_METADATA;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// --------------------------------------
|
|
275
|
+
// Helper method: Add a file to the ZIP with compression
|
|
276
|
+
// Simplifies the common workflow of creating entry + compressing
|
|
277
|
+
|
|
278
|
+
async addFile(file: FileData, options?: CompressOptions): Promise<ZipEntry> {
|
|
279
|
+
// Create entry
|
|
280
|
+
const entry = this.createZipFileEntry(file);
|
|
281
|
+
|
|
282
|
+
// Compress the file
|
|
283
|
+
// In browser, File objects implement both FileData and Blob interfaces
|
|
284
|
+
// We need to convert FileData to Blob for compressDataBlob
|
|
285
|
+
const fileBlob = file as unknown as Blob;
|
|
286
|
+
const compressedData = await this.compressDataBlob(entry, fileBlob, options);
|
|
287
|
+
entry.cmpData = compressedData;
|
|
288
|
+
|
|
289
|
+
return entry;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// --------------------------------------
|
|
293
|
+
// Verify a ZIP entry by attempting to extract it
|
|
294
|
+
// Returns true if the entry is valid, false otherwise
|
|
295
|
+
|
|
296
|
+
async verifyEntry(entry: ZipEntry, skipHashCheck?: boolean): Promise<boolean> {
|
|
297
|
+
try {
|
|
298
|
+
const blob = await this.extractBlob(entry, skipHashCheck);
|
|
299
|
+
return blob !== null;
|
|
300
|
+
} catch (error) {
|
|
301
|
+
console.error(`Verification failed for ${entry.filename}:`, error);
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
242
305
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// NeoZipkit - Browser ES Module Entry Point
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// This is a clean ES module entry point for browser bundles
|
|
5
|
+
// All exports are named exports for better tree-shaking support
|
|
6
|
+
|
|
7
|
+
// Buffer polyfill for browser
|
|
8
|
+
import { Buffer } from 'buffer';
|
|
9
|
+
if (typeof globalThis !== 'undefined') {
|
|
10
|
+
(globalThis as any).Buffer = Buffer;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Core exports
|
|
14
|
+
export * from '../core';
|
|
15
|
+
|
|
16
|
+
// Browser-specific class
|
|
17
|
+
export { default as ZipkitBrowser } from './ZipkitBrowser';
|
|
18
|
+
|
|
19
|
+
// Re-export ZipEntry as named export for convenience
|
|
20
|
+
export { default as ZipEntry } from '../core/ZipEntry';
|
|
21
|
+
|
|
22
|
+
// Re-export commonly used types and constants
|
|
23
|
+
export type { CompressOptions, CreateZipOptions } from '../core/ZipCompress';
|
|
24
|
+
export type { FileData, TokenMetadata } from '../types';
|
|
25
|
+
export * from '../core/constants/Headers';
|
|
26
|
+
export * from '../core/constants/Errors';
|
|
27
|
+
|
|
28
|
+
// Blockchain exports for browser (if needed)
|
|
29
|
+
export * from '../blockchain/browser';
|
|
30
|
+
export { createTokenVerifier } from '../blockchain/browser';
|
|
31
|
+
|
|
32
|
+
// Platform utilities
|
|
33
|
+
export const PlatformUtils = {
|
|
34
|
+
isBrowser: typeof window !== 'undefined' && typeof document !== 'undefined',
|
|
35
|
+
isNode: typeof process !== 'undefined' && process.versions && process.versions.node,
|
|
36
|
+
};
|
|
37
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// NeoZipkit - Browser-Only Package Exports
|
|
3
|
+
// =============================================================================
|
|
4
|
+
|
|
5
|
+
// Core shared exports (re-exported from core module)
|
|
6
|
+
export * from '../core';
|
|
7
|
+
import Zipkit from '../core';
|
|
8
|
+
export default Zipkit;
|
|
9
|
+
|
|
10
|
+
// Browser-only exports
|
|
11
|
+
export { default as ZipkitBrowser } from './ZipkitBrowser';
|
|
12
|
+
export { TokenMetadata } from '../types';
|
|
13
|
+
|
|
14
|
+
// Blockchain exports for browser
|
|
15
|
+
export * from '../blockchain/browser';
|
|
16
|
+
export { createTokenVerifier } from '../blockchain/browser';
|
|
17
|
+
|
|
18
|
+
// Platform-specific conditional exports
|
|
19
|
+
export const PlatformUtils = {
|
|
20
|
+
// Browser detection
|
|
21
|
+
isBrowser: typeof window !== 'undefined' && typeof document !== 'undefined',
|
|
22
|
+
// Node.js detection
|
|
23
|
+
isNode: typeof process !== 'undefined' && process.versions && process.versions.node,
|
|
24
|
+
};
|
|
25
|
+
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
// ======================================
|
|
2
|
+
// ZipkitCompress.ts - Compression Module
|
|
3
|
+
// Copyright (c) 2025 NeoWare, Inc. All rights reserved.
|
|
4
|
+
// ======================================
|
|
5
|
+
//
|
|
6
|
+
// LOGGING INSTRUCTIONS:
|
|
7
|
+
// ---------------------
|
|
8
|
+
// To enable/disable logging, set loggingEnabled to true/false in the class:
|
|
9
|
+
// private static loggingEnabled: boolean = true; // Enable logging
|
|
10
|
+
// private static loggingEnabled: boolean = false; // Disable logging
|
|
11
|
+
//
|
|
12
|
+
// Logging respects the global Logger level (debug, info, warn, error, silent).
|
|
13
|
+
// Logger level is automatically set to 'debug' when loggingEnabled is true.
|
|
14
|
+
//
|
|
15
|
+
|
|
16
|
+
const pako = require('pako');
|
|
17
|
+
import { ZstdInit, ZstdSimple } from '@oneidentity/zstd-js';
|
|
18
|
+
import Zipkit from './Zipkit';
|
|
19
|
+
import { Logger } from './components/Logger';
|
|
20
|
+
import ZipEntry from './ZipEntry';
|
|
21
|
+
import Errors from './constants/Errors';
|
|
22
|
+
import { CMP_METHOD, GP_FLAG, ENCRYPT_HDR_SIZE } from './constants/Headers';
|
|
23
|
+
import { HashCalculator } from './components/HashCalculator';
|
|
24
|
+
import { ZipCrypto } from './encryption/ZipCrypto';
|
|
25
|
+
|
|
26
|
+
// We'll initialize zstd when needed
|
|
27
|
+
let zstdCodec: { ZstdSimple: typeof ZstdSimple } | null = null;
|
|
28
|
+
|
|
29
|
+
// Async initialization function for zstd
|
|
30
|
+
async function initZstd(): Promise<{ ZstdSimple: typeof ZstdSimple }> {
|
|
31
|
+
if (!zstdCodec) {
|
|
32
|
+
zstdCodec = await ZstdInit();
|
|
33
|
+
}
|
|
34
|
+
return zstdCodec;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Options for compressing files in a ZIP archive
|
|
39
|
+
*/
|
|
40
|
+
export interface CompressOptions {
|
|
41
|
+
level?: number; // Compression level (1-9, 0=store)
|
|
42
|
+
password?: string | null; // Password for encryption
|
|
43
|
+
useSHA256?: boolean; // Whether to calculate SHA256 hash default is false
|
|
44
|
+
useZstd?: boolean; // Whether to use Zstandard compression default is true
|
|
45
|
+
bufferSize?: number; // Override default buffer size
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Callbacks for ZIP file creation process
|
|
50
|
+
* Buffer-based only - no file I/O operations
|
|
51
|
+
*/
|
|
52
|
+
export interface CreateZipOptions {
|
|
53
|
+
onError?: (error: Error) => void; // Called when an error occurs
|
|
54
|
+
onEntryDone?: (entry: ZipEntry, status: string) => void; // Called when entry processing completes
|
|
55
|
+
onOutputBuffer?: (data: Buffer) => Promise<void>; // Called to write output data
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Compression handler for ZIP files
|
|
60
|
+
* Supports Deflate, Zstandard, and Store methods
|
|
61
|
+
*/
|
|
62
|
+
export class ZipCompress {
|
|
63
|
+
private zipkit: Zipkit;
|
|
64
|
+
private debug: boolean;
|
|
65
|
+
|
|
66
|
+
// Class-level logging control - set to true to enable logging
|
|
67
|
+
private static loggingEnabled: boolean = false;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Internal logging method - only logs if class logging is enabled
|
|
71
|
+
*/
|
|
72
|
+
private log(...args: any[]): void {
|
|
73
|
+
if (ZipCompress.loggingEnabled) {
|
|
74
|
+
Logger.debug(`[ZipCompress]`, ...args);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Creates a new ZipCompress instance
|
|
80
|
+
* @param zipkit - Zipkit instance to use for ZIP operations
|
|
81
|
+
*/
|
|
82
|
+
constructor(zipkit: Zipkit) {
|
|
83
|
+
this.zipkit = zipkit;
|
|
84
|
+
// Debug disabled by default (controlled by class-level logging)
|
|
85
|
+
this.debug = false;
|
|
86
|
+
// If logging is enabled, ensure Logger level is set to debug
|
|
87
|
+
if (ZipCompress.loggingEnabled) {
|
|
88
|
+
Logger.setLevel('debug');
|
|
89
|
+
}
|
|
90
|
+
this.log(`ZipCompress initialized`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Compresses data for a ZIP entry (Buffer-based only)
|
|
95
|
+
* @param entry - ZIP entry to compress
|
|
96
|
+
* @param data - Buffer containing data to compress
|
|
97
|
+
* @param options - Compression options
|
|
98
|
+
* @param onOutputBuffer - Optional callback for streaming output
|
|
99
|
+
* @returns Buffer containing compressed data
|
|
100
|
+
*/
|
|
101
|
+
async compressData(entry: ZipEntry, data: Buffer, options?: CompressOptions, onOutputBuffer?: (data: Buffer) => Promise<void>): Promise<Buffer> {
|
|
102
|
+
this.log(`compressData() called for entry: ${entry.filename}`);
|
|
103
|
+
|
|
104
|
+
// Set uncompressed size if not already set
|
|
105
|
+
if (!entry.uncompressedSize || entry.uncompressedSize === 0) {
|
|
106
|
+
entry.uncompressedSize = data.length;
|
|
107
|
+
}
|
|
108
|
+
const totalSize = data.length;
|
|
109
|
+
const bufferSize = options?.bufferSize || this.zipkit.getBufferSize(); // Use Zipkit's bufferSize
|
|
110
|
+
|
|
111
|
+
this.log(`Compressing ${totalSize} bytes for entry: ${entry.filename}`);
|
|
112
|
+
this.log(`Compression options:`, { level: options?.level, useZstd: options?.useZstd, bufferSize });
|
|
113
|
+
|
|
114
|
+
// Determine compression method
|
|
115
|
+
let compressionMethod: number;
|
|
116
|
+
|
|
117
|
+
if (options?.level === 0) {
|
|
118
|
+
compressionMethod = CMP_METHOD.STORED;
|
|
119
|
+
this.log(`Using STORED method (no compression)`);
|
|
120
|
+
} else if (options?.useZstd) {
|
|
121
|
+
// ZSTD fallback to STORED if file too small
|
|
122
|
+
if (totalSize < 100) {
|
|
123
|
+
compressionMethod = CMP_METHOD.STORED;
|
|
124
|
+
this.log(`ZSTD fallback to STORED (file too small: ${totalSize} bytes)`);
|
|
125
|
+
} else {
|
|
126
|
+
compressionMethod = CMP_METHOD.ZSTD;
|
|
127
|
+
this.log(`Using ZSTD method (zstd compression)`);
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
compressionMethod = CMP_METHOD.DEFLATED;
|
|
131
|
+
this.log(`Using DEFLATED method (default compression)`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
entry.cmpMethod = compressionMethod;
|
|
135
|
+
|
|
136
|
+
// Initialize hash calculator
|
|
137
|
+
const needsHashCalculation = (!entry.crc || entry.crc === 0) || (options?.useSHA256 && !entry.sha256);
|
|
138
|
+
const hashCalculator = needsHashCalculation ? new HashCalculator({ useSHA256: options?.useSHA256 && !entry.sha256 || false }) : null;
|
|
139
|
+
|
|
140
|
+
// Calculate hashes if needed
|
|
141
|
+
if (hashCalculator) {
|
|
142
|
+
hashCalculator.update(data);
|
|
143
|
+
if (!entry.crc || entry.crc === 0) {
|
|
144
|
+
entry.crc = hashCalculator.finalizeCRC32();
|
|
145
|
+
}
|
|
146
|
+
if (options?.useSHA256 && !entry.sha256) {
|
|
147
|
+
entry.sha256 = hashCalculator.finalizeSHA256();
|
|
148
|
+
}
|
|
149
|
+
this.log(`Final hashes: CRC32=0x${entry.crc.toString(16).padStart(8, '0')}, SHA256=${entry.sha256 || 'N/A'}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Encrypt if password provided
|
|
153
|
+
if (options?.password) {
|
|
154
|
+
this.log(`Encrypting compressed data for entry: ${entry.filename}`);
|
|
155
|
+
(entry as any).gpFlag = ((entry as any).gpFlag || 0) | GP_FLAG.ENCRYPTED;
|
|
156
|
+
(entry as any).isEncrypted = true;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Compress data based on method
|
|
160
|
+
let compressedData: Buffer;
|
|
161
|
+
const methodName = compressionMethod === CMP_METHOD.ZSTD ? 'ZSTD' : compressionMethod === CMP_METHOD.DEFLATED ? 'DEFLATED' : 'STORED';
|
|
162
|
+
|
|
163
|
+
if (compressionMethod === CMP_METHOD.STORED) {
|
|
164
|
+
compressedData = data;
|
|
165
|
+
} else {
|
|
166
|
+
this.log(`Processing sequence for ${methodName}: [HASH] -> [COMPRESS] -> [OUTPUT]`);
|
|
167
|
+
this.log(`Compressing: method=${methodName}, input=${totalSize} bytes, buffer size=${bufferSize} bytes`);
|
|
168
|
+
this.log(`Calculating hashes: CRC32=${!entry.crc || entry.crc === 0}, SHA256=${options?.useSHA256}`);
|
|
169
|
+
|
|
170
|
+
if (compressionMethod === CMP_METHOD.ZSTD) {
|
|
171
|
+
compressedData = await this.zstdCompress(data, options, bufferSize, entry, onOutputBuffer);
|
|
172
|
+
} else {
|
|
173
|
+
compressedData = await this.deflateCompress(data, options, bufferSize, entry, onOutputBuffer);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Encrypt compressed data if password provided
|
|
178
|
+
if (options?.password) {
|
|
179
|
+
compressedData = this.encryptCompressedData(entry, compressedData, options.password);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
entry.compressedSize = compressedData.length;
|
|
183
|
+
|
|
184
|
+
return compressedData;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Compress data using deflate algorithm with chunked processing
|
|
189
|
+
* @param data - Data to compress (Buffer or chunked reader)
|
|
190
|
+
* @param options - Compression options
|
|
191
|
+
* @param bufferSize - Buffer size for chunked processing
|
|
192
|
+
* @param entry - ZIP entry being compressed
|
|
193
|
+
* @param onOutputBuffer - Optional callback for streaming output
|
|
194
|
+
* @returns Buffer containing compressed data
|
|
195
|
+
*/
|
|
196
|
+
async deflateCompress(
|
|
197
|
+
data: Buffer | { totalSize: number, onReadChunk: (position: number, size: number) => Buffer, onOutChunk: (chunk: Buffer) => void },
|
|
198
|
+
options?: CompressOptions,
|
|
199
|
+
bufferSize?: number,
|
|
200
|
+
entry?: ZipEntry,
|
|
201
|
+
onOutputBuffer?: (data: Buffer) => Promise<void>
|
|
202
|
+
): Promise<Buffer> {
|
|
203
|
+
this.log(`deflateCompress() called - entry: ${entry?.filename ?? 'unknown'}, bufferSize: ${bufferSize}, level: ${options?.level ?? 6}`);
|
|
204
|
+
|
|
205
|
+
const effectiveBufferSize = bufferSize || this.zipkit.getBufferSize();
|
|
206
|
+
const level = options?.level ?? 6;
|
|
207
|
+
|
|
208
|
+
// Handle chunked reader
|
|
209
|
+
if (typeof data === 'object' && 'totalSize' in data && 'onReadChunk' in data) {
|
|
210
|
+
// Chunked reader mode - not implemented in simplified version
|
|
211
|
+
throw new Error('Chunked reader mode not supported in ZipCompress');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// For small data, use synchronous deflate
|
|
215
|
+
if (data.length <= effectiveBufferSize) {
|
|
216
|
+
return this.deflate(data, options);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// For large data, use chunked deflate
|
|
220
|
+
const deflator = new pako.Deflate({ level, raw: true });
|
|
221
|
+
const compressedChunks: Buffer[] = [];
|
|
222
|
+
let totalProcessed = 0;
|
|
223
|
+
let totalCompressedSize = 0;
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
// Process data in chunks
|
|
227
|
+
for (let offset = 0; offset < data.length; offset += effectiveBufferSize) {
|
|
228
|
+
const chunk = data.slice(offset, offset + effectiveBufferSize);
|
|
229
|
+
const isLast = offset + effectiveBufferSize >= data.length;
|
|
230
|
+
|
|
231
|
+
deflator.push(chunk, isLast);
|
|
232
|
+
|
|
233
|
+
// Collect compressed chunks
|
|
234
|
+
if (deflator.result && deflator.result.length > 0) {
|
|
235
|
+
const compressedChunk = Buffer.from(deflator.result);
|
|
236
|
+
compressedChunks.push(compressedChunk);
|
|
237
|
+
totalCompressedSize += compressedChunk.length;
|
|
238
|
+
|
|
239
|
+
// Stream output if callback provided
|
|
240
|
+
if (onOutputBuffer) {
|
|
241
|
+
await onOutputBuffer(compressedChunk);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
totalProcessed += chunk.length;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Calculate compression ratio
|
|
249
|
+
const ratio = totalProcessed > 0 ? Math.round((totalCompressedSize / totalProcessed) * 100) : 0;
|
|
250
|
+
this.log(`Final hashes: CRC32=0x${entry?.crc?.toString(16).padStart(8, '0')}, SHA256=${entry?.sha256 || 'N/A'}`);
|
|
251
|
+
this.log(`Deflate compression complete: ${totalCompressedSize} bytes from ${totalProcessed} bytes (ratio=${ratio}%)`);
|
|
252
|
+
|
|
253
|
+
return Buffer.concat(compressedChunks);
|
|
254
|
+
} catch (e) {
|
|
255
|
+
throw new Error(`Deflate compression failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Compress data using deflate algorithm (synchronous, small buffers only)
|
|
261
|
+
* @param inbuf - Buffer containing data to compress
|
|
262
|
+
* @param options - Compression options
|
|
263
|
+
* @returns Buffer containing compressed data
|
|
264
|
+
*/
|
|
265
|
+
deflate(inbuf: Buffer, options?: CompressOptions): Buffer {
|
|
266
|
+
this.log(`deflate() called with buffer size: ${inbuf.length}, level: ${options?.level ?? 6}`);
|
|
267
|
+
const level = options?.level ?? 6;
|
|
268
|
+
const result = pako.deflateRaw(inbuf, { level });
|
|
269
|
+
const ratio = inbuf.length > 0 ? Math.round((result.length / inbuf.length) * 100) : 0;
|
|
270
|
+
this.log(`Deflate compression complete: ${result.length} bytes from ${inbuf.length} bytes (ratio=${ratio}%)`);
|
|
271
|
+
return Buffer.from(result.buffer, result.byteOffset, result.byteLength);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Compress data using Zstandard (zstd) algorithm
|
|
276
|
+
* @param input - Input data to compress (Buffer or chunked reader)
|
|
277
|
+
* @param options - Compression options
|
|
278
|
+
* @param bufferSize - Buffer size for chunked processing
|
|
279
|
+
* @param entry - ZIP entry being compressed
|
|
280
|
+
* @param onOutputBuffer - Optional callback for streaming output
|
|
281
|
+
* @returns Buffer containing compressed data
|
|
282
|
+
*/
|
|
283
|
+
async zstdCompress(
|
|
284
|
+
input: Buffer | { totalSize: number, readChunk: (position: number, size: number) => Buffer },
|
|
285
|
+
options?: CompressOptions,
|
|
286
|
+
bufferSize?: number,
|
|
287
|
+
entry?: ZipEntry,
|
|
288
|
+
onOutputBuffer?: (data: Buffer) => Promise<void>
|
|
289
|
+
): Promise<Buffer> {
|
|
290
|
+
this.log(`zstdCompress() called - entry: ${entry?.filename ?? 'unknown'}, bufferSize: ${bufferSize}, level: ${options?.level ?? 6}`);
|
|
291
|
+
|
|
292
|
+
const effectiveBufferSize = bufferSize || this.zipkit.getBufferSize();
|
|
293
|
+
const level = options?.level ?? 6;
|
|
294
|
+
|
|
295
|
+
// Handle chunked reader
|
|
296
|
+
if (typeof input === 'object' && 'totalSize' in input && 'readChunk' in input) {
|
|
297
|
+
// Chunked reader mode - not implemented in simplified version
|
|
298
|
+
throw new Error('Chunked reader mode not supported in ZipCompress');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Lazy ZSTD initialization
|
|
302
|
+
const zstdCodec = await initZstd();
|
|
303
|
+
|
|
304
|
+
// Validate input
|
|
305
|
+
if (!input || input.length === 0) {
|
|
306
|
+
throw new Error('ZSTD compression: empty input buffer');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Convert Buffer to Uint8Array for WASM module (same fix as decompression)
|
|
310
|
+
const inputArray = new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
311
|
+
|
|
312
|
+
// For small data, compress in one go
|
|
313
|
+
if (input.length <= effectiveBufferSize) {
|
|
314
|
+
const compressed = zstdCodec.ZstdSimple.compress(inputArray, level);
|
|
315
|
+
const compressedBuffer = Buffer.from(compressed);
|
|
316
|
+
|
|
317
|
+
if (onOutputBuffer) {
|
|
318
|
+
await onOutputBuffer(compressedBuffer);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return compressedBuffer;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// For large data, compress in chunks (ZSTD supports streaming)
|
|
325
|
+
// Note: ZSTD streaming compression is more complex, so for now we compress the whole buffer
|
|
326
|
+
// This could be optimized in the future for true streaming
|
|
327
|
+
const compressed = zstdCodec.ZstdSimple.compress(inputArray, level);
|
|
328
|
+
const compressedBuffer = Buffer.from(compressed);
|
|
329
|
+
|
|
330
|
+
if (onOutputBuffer) {
|
|
331
|
+
await onOutputBuffer(compressedBuffer);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return compressedBuffer;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Encrypt compressed data using PKZIP encryption
|
|
339
|
+
* @param entry - ZIP entry to encrypt
|
|
340
|
+
* @param compressedData - Compressed data to encrypt
|
|
341
|
+
* @param password - Password for encryption
|
|
342
|
+
* @returns Buffer containing encrypted data (includes 12-byte header)
|
|
343
|
+
*/
|
|
344
|
+
encryptCompressedData(entry: ZipEntry, compressedData: Buffer, password: string): Buffer {
|
|
345
|
+
this.log(`encryptCompressedData() called for entry: ${entry.filename}, compressed size: ${compressedData.length}`);
|
|
346
|
+
|
|
347
|
+
const zipCrypto = new ZipCrypto();
|
|
348
|
+
const encryptedData = zipCrypto.encryptBuffer(entry, compressedData, password);
|
|
349
|
+
|
|
350
|
+
this.log(`Encryption complete: ${compressedData.length} bytes compressed -> ${encryptedData.length} bytes encrypted (includes ${ENCRYPT_HDR_SIZE}-byte header)`);
|
|
351
|
+
|
|
352
|
+
return encryptedData;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Compress file data in memory and return ZIP entry information as Buffer
|
|
357
|
+
* @param entry - ZIP entry to compress
|
|
358
|
+
* @param fileData - File data buffer to compress
|
|
359
|
+
* @param cmpOptions - Compression options
|
|
360
|
+
* @returns Buffer containing local header + compressed data
|
|
361
|
+
*/
|
|
362
|
+
async compressFileBuffer(
|
|
363
|
+
entry: ZipEntry,
|
|
364
|
+
fileData: Buffer,
|
|
365
|
+
cmpOptions?: CompressOptions
|
|
366
|
+
): Promise<Buffer> {
|
|
367
|
+
this.log(`compressFileBuffer() called for entry: ${entry.filename}, size: ${fileData.length}`);
|
|
368
|
+
|
|
369
|
+
// Set uncompressed size
|
|
370
|
+
entry.uncompressedSize = fileData.length;
|
|
371
|
+
|
|
372
|
+
// Initialize hash calculator
|
|
373
|
+
const hashCalculator = new HashCalculator({ useSHA256: cmpOptions?.useSHA256 || false });
|
|
374
|
+
hashCalculator.update(fileData);
|
|
375
|
+
|
|
376
|
+
// Set hashes
|
|
377
|
+
entry.crc = hashCalculator.finalizeCRC32();
|
|
378
|
+
if (cmpOptions?.useSHA256) {
|
|
379
|
+
entry.sha256 = hashCalculator.finalizeSHA256();
|
|
380
|
+
this.log(`SHA-256 calculated: ${entry.sha256}`);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Compress data
|
|
384
|
+
const compressedData = await this.compressData(entry, fileData, cmpOptions);
|
|
385
|
+
|
|
386
|
+
// Encrypt if password provided
|
|
387
|
+
if (cmpOptions?.password) {
|
|
388
|
+
this.log(`Encrypting compressed data for entry: ${entry.filename}`);
|
|
389
|
+
(entry as any).gpFlag = ((entry as any).gpFlag || 0) | GP_FLAG.ENCRYPTED;
|
|
390
|
+
(entry as any).isEncrypted = true;
|
|
391
|
+
const zipCrypto = new ZipCrypto();
|
|
392
|
+
const encryptedData = zipCrypto.encryptBuffer(entry, compressedData, cmpOptions.password);
|
|
393
|
+
return encryptedData;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return compressedData;
|
|
397
|
+
}
|
|
398
|
+
}
|