neozipkit 0.2.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.
Files changed (301) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +410 -186
  3. package/contracts/ABI.txt +889 -0
  4. package/contracts/Bytecode.txt +1 -0
  5. package/contracts/COMPILATION_NOTES.md +59 -0
  6. package/contracts/QUICK_DEPLOY.md +286 -0
  7. package/contracts/README.md +235 -131
  8. package/contracts/VERIFICATION.md +308 -0
  9. package/contracts/deploy-interactive.js +448 -0
  10. package/contracts/deployment-arbitrum-sepolia.json +12 -0
  11. package/contracts/deployment-arbitrum.json +12 -0
  12. package/contracts/deployment-eth-sepolia.json +12 -0
  13. package/contracts/hardhat.config.js +114 -0
  14. package/contracts/package.json +20 -0
  15. package/contracts/scripts/compile-and-extract.js +119 -0
  16. package/contracts/scripts/verify-contract.js +223 -0
  17. package/contracts/src/{NZIP-NFT-Private.sol → NZIP-NFT-v2.0.sol} +66 -151
  18. package/contracts/src/NZIP-NFT.sol +9 -15
  19. package/dist/blockchain/browser/TokenVerifierBrowser.d.ts +67 -0
  20. package/dist/blockchain/browser/TokenVerifierBrowser.d.ts.map +1 -0
  21. package/dist/blockchain/browser/TokenVerifierBrowser.js +313 -0
  22. package/dist/blockchain/browser/TokenVerifierBrowser.js.map +1 -0
  23. package/dist/blockchain/browser/WalletManagerBrowser.d.ts +98 -0
  24. package/dist/blockchain/browser/WalletManagerBrowser.d.ts.map +1 -0
  25. package/dist/blockchain/browser/WalletManagerBrowser.js +434 -0
  26. package/dist/blockchain/browser/WalletManagerBrowser.js.map +1 -0
  27. package/dist/blockchain/browser/ZipkitMinterBrowser.d.ts +58 -0
  28. package/dist/blockchain/browser/ZipkitMinterBrowser.d.ts.map +1 -0
  29. package/dist/blockchain/browser/ZipkitMinterBrowser.js +317 -0
  30. package/dist/blockchain/browser/ZipkitMinterBrowser.js.map +1 -0
  31. package/dist/blockchain/browser/index.d.ts +11 -0
  32. package/dist/blockchain/browser/index.d.ts.map +1 -0
  33. package/dist/blockchain/browser/index.js +16 -0
  34. package/dist/blockchain/browser/index.js.map +1 -0
  35. package/dist/blockchain/core/WalletManager.d.ts +124 -0
  36. package/dist/blockchain/core/WalletManager.d.ts.map +1 -0
  37. package/dist/blockchain/{ZipKitWallet.js → core/WalletManager.js} +157 -177
  38. package/dist/blockchain/core/WalletManager.js.map +1 -0
  39. package/dist/blockchain/{ZipKitMinter.d.ts → core/ZipkitMinter.d.ts} +46 -11
  40. package/dist/blockchain/core/ZipkitMinter.d.ts.map +1 -0
  41. package/dist/blockchain/core/ZipkitMinter.js +548 -0
  42. package/dist/blockchain/core/ZipkitMinter.js.map +1 -0
  43. package/dist/blockchain/{ZipKitOTS.d.ts → core/ZipkitOTS.d.ts} +6 -15
  44. package/dist/blockchain/core/ZipkitOTS.d.ts.map +1 -0
  45. package/dist/blockchain/{ZipKitOTS.js → core/ZipkitOTS.js} +26 -84
  46. package/dist/blockchain/core/ZipkitOTS.js.map +1 -0
  47. package/dist/blockchain/core/ZipkitVerifier.d.ts +177 -0
  48. package/dist/blockchain/core/ZipkitVerifier.d.ts.map +1 -0
  49. package/dist/blockchain/core/ZipkitVerifier.js +632 -0
  50. package/dist/blockchain/core/ZipkitVerifier.js.map +1 -0
  51. package/dist/blockchain/core/contracts.d.ts +83 -0
  52. package/dist/blockchain/core/contracts.d.ts.map +1 -0
  53. package/dist/blockchain/core/contracts.js +341 -0
  54. package/dist/blockchain/core/contracts.js.map +1 -0
  55. package/dist/blockchain/core/index.d.ts +12 -0
  56. package/dist/blockchain/core/index.d.ts.map +1 -0
  57. package/dist/blockchain/core/index.js +59 -0
  58. package/dist/blockchain/core/index.js.map +1 -0
  59. package/dist/blockchain/index.d.ts +11 -7
  60. package/dist/blockchain/index.d.ts.map +1 -0
  61. package/dist/blockchain/index.js +18 -34
  62. package/dist/blockchain/index.js.map +1 -0
  63. package/dist/blockchain/node/WalletManagerNode.d.ts +47 -0
  64. package/dist/blockchain/node/WalletManagerNode.d.ts.map +1 -0
  65. package/dist/blockchain/node/WalletManagerNode.js +203 -0
  66. package/dist/blockchain/node/WalletManagerNode.js.map +1 -0
  67. package/dist/blockchain/node/index.d.ts +12 -0
  68. package/dist/blockchain/node/index.d.ts.map +1 -0
  69. package/dist/blockchain/node/index.js +24 -0
  70. package/dist/blockchain/node/index.js.map +1 -0
  71. package/dist/browser/ZipkitBrowser.d.ts +27 -0
  72. package/dist/browser/ZipkitBrowser.d.ts.map +1 -0
  73. package/dist/browser/{ZipKitBrowser.js → ZipkitBrowser.js} +96 -43
  74. package/dist/browser/ZipkitBrowser.js.map +1 -0
  75. package/dist/browser/index.d.ts +12 -0
  76. package/dist/browser/index.d.ts.map +1 -0
  77. package/dist/browser/index.js +42 -0
  78. package/dist/browser/index.js.map +1 -0
  79. package/dist/browser-esm/index.d.ts +12 -0
  80. package/dist/browser-esm/index.js +59559 -0
  81. package/dist/browser-esm/index.js.map +7 -0
  82. package/dist/browser-umd/index.d.ts +12 -0
  83. package/dist/browser-umd/index.js +59576 -0
  84. package/dist/browser-umd/index.js.map +7 -0
  85. package/dist/browser-umd/index.min.js +63 -0
  86. package/dist/browser.d.ts +8 -14
  87. package/dist/browser.js +13 -28
  88. package/dist/core/ZipCompress.d.ts +99 -0
  89. package/dist/core/ZipCompress.d.ts.map +1 -0
  90. package/dist/core/ZipCompress.js +309 -0
  91. package/dist/core/ZipCompress.js.map +1 -0
  92. package/dist/core/ZipDecompress.d.ts +58 -0
  93. package/dist/core/ZipDecompress.d.ts.map +1 -0
  94. package/dist/core/ZipDecompress.js +172 -0
  95. package/dist/core/ZipDecompress.js.map +1 -0
  96. package/dist/{shared → core}/ZipEntry.d.ts +8 -1
  97. package/dist/core/ZipEntry.d.ts.map +1 -0
  98. package/dist/{shared → core}/ZipEntry.js +225 -82
  99. package/dist/core/ZipEntry.js.map +1 -0
  100. package/dist/core/Zipkit.d.ts +315 -0
  101. package/dist/core/Zipkit.d.ts.map +1 -0
  102. package/dist/core/Zipkit.js +647 -0
  103. package/dist/core/Zipkit.js.map +1 -0
  104. package/dist/core/components/HashCalculator.d.ts +138 -0
  105. package/dist/core/components/HashCalculator.d.ts.map +1 -0
  106. package/dist/core/components/HashCalculator.js +360 -0
  107. package/dist/core/components/HashCalculator.js.map +1 -0
  108. package/dist/core/components/Logger.d.ts +73 -0
  109. package/dist/core/components/Logger.d.ts.map +1 -0
  110. package/dist/core/components/Logger.js +156 -0
  111. package/dist/core/components/Logger.js.map +1 -0
  112. package/dist/core/components/ProgressTracker.d.ts +43 -0
  113. package/dist/core/components/ProgressTracker.d.ts.map +1 -0
  114. package/dist/core/components/ProgressTracker.js +112 -0
  115. package/dist/core/components/ProgressTracker.js.map +1 -0
  116. package/dist/{shared → core}/components/Support.d.ts +1 -0
  117. package/dist/core/components/Support.d.ts.map +1 -0
  118. package/dist/{shared → core}/components/Support.js +1 -0
  119. package/dist/core/components/Support.js.map +1 -0
  120. package/dist/{shared → core}/components/Util.d.ts +7 -2
  121. package/dist/core/components/Util.d.ts.map +1 -0
  122. package/dist/{shared → core}/components/Util.js +14 -34
  123. package/dist/core/components/Util.js.map +1 -0
  124. package/dist/{shared → core}/constants/Errors.d.ts +1 -2
  125. package/dist/core/constants/Errors.d.ts.map +1 -0
  126. package/dist/{shared → core}/constants/Errors.js +1 -3
  127. package/dist/core/constants/Errors.js.map +1 -0
  128. package/dist/{shared → core}/constants/Headers.d.ts +3 -0
  129. package/dist/core/constants/Headers.d.ts.map +1 -0
  130. package/dist/{shared → core}/constants/Headers.js +20 -17
  131. package/dist/core/constants/Headers.js.map +1 -0
  132. package/dist/core/encryption/Manager.d.ts +58 -0
  133. package/dist/core/encryption/Manager.d.ts.map +1 -0
  134. package/dist/core/encryption/Manager.js +121 -0
  135. package/dist/core/encryption/Manager.js.map +1 -0
  136. package/dist/core/encryption/ZipCrypto.d.ts +172 -0
  137. package/dist/core/encryption/ZipCrypto.d.ts.map +1 -0
  138. package/dist/core/encryption/ZipCrypto.js +554 -0
  139. package/dist/core/encryption/ZipCrypto.js.map +1 -0
  140. package/dist/core/encryption/index.d.ts +9 -0
  141. package/dist/core/encryption/index.d.ts.map +1 -0
  142. package/dist/core/encryption/index.js +17 -0
  143. package/dist/core/encryption/index.js.map +1 -0
  144. package/dist/core/encryption/types.d.ts +29 -0
  145. package/dist/core/encryption/types.d.ts.map +1 -0
  146. package/dist/core/encryption/types.js +12 -0
  147. package/dist/core/encryption/types.js.map +1 -0
  148. package/dist/core/index.d.ts +24 -0
  149. package/dist/core/index.d.ts.map +1 -0
  150. package/dist/core/index.js +57 -0
  151. package/dist/core/index.js.map +1 -0
  152. package/dist/core/version.d.ts +5 -0
  153. package/dist/core/version.d.ts.map +1 -0
  154. package/dist/core/version.js +31 -0
  155. package/dist/core/version.js.map +1 -0
  156. package/dist/index.d.ts +8 -18
  157. package/dist/index.d.ts.map +1 -0
  158. package/dist/index.js +29 -35
  159. package/dist/index.js.map +1 -0
  160. package/dist/node/ZipCompressNode.d.ts +123 -0
  161. package/dist/node/ZipCompressNode.d.ts.map +1 -0
  162. package/dist/node/ZipCompressNode.js +576 -0
  163. package/dist/node/ZipCompressNode.js.map +1 -0
  164. package/dist/node/ZipDecompressNode.d.ts +120 -0
  165. package/dist/node/ZipDecompressNode.d.ts.map +1 -0
  166. package/dist/node/ZipDecompressNode.js +461 -0
  167. package/dist/node/ZipDecompressNode.js.map +1 -0
  168. package/dist/node/ZipkitNode.d.ts +406 -0
  169. package/dist/node/ZipkitNode.d.ts.map +1 -0
  170. package/dist/node/ZipkitNode.js +1305 -0
  171. package/dist/node/ZipkitNode.js.map +1 -0
  172. package/dist/node/index.d.ts +26 -0
  173. package/dist/node/index.d.ts.map +1 -0
  174. package/dist/node/index.js +65 -0
  175. package/dist/node/index.js.map +1 -0
  176. package/dist/types/index.d.ts +59 -0
  177. package/dist/types/index.d.ts.map +1 -0
  178. package/dist/types/index.js +36 -1
  179. package/dist/types/index.js.map +1 -0
  180. package/examples/README.md +269 -0
  181. package/examples/blockchain-tokenize.ts +354 -0
  182. package/examples/create-zip.ts +172 -0
  183. package/examples/extract-zip.ts +158 -0
  184. package/examples/list-zip.ts +161 -0
  185. package/examples/test-files/data.json +116 -0
  186. package/examples/test-files/document.md +80 -0
  187. package/examples/test-files/document.txt +2 -0
  188. package/examples/test-files/file1.txt +48 -0
  189. package/examples/test-files/file2.txt +80 -0
  190. package/examples/tsconfig.json +44 -0
  191. package/examples/unzip-token.ts +491 -0
  192. package/examples/verify-tokenized-zip.ts +305 -0
  193. package/examples/zip-token.ts +604 -0
  194. package/package.json +108 -24
  195. package/src/blockchain/README.md +59 -66
  196. package/src/{browser/TokenVerifierBrowser.ts-remove → blockchain/browser/TokenVerifierBrowser.ts} +125 -79
  197. package/src/blockchain/browser/WalletManagerBrowser.ts +486 -0
  198. package/src/blockchain/browser/ZipkitMinterBrowser.ts +400 -0
  199. package/src/blockchain/browser/index.ts +13 -0
  200. package/src/blockchain/{ZipKitWallet.ts → core/WalletManager.ts} +241 -143
  201. package/src/blockchain/core/ZipkitMinter.ts +716 -0
  202. package/src/blockchain/{ZipKitOTS.ts → core/ZipkitOTS.ts} +28 -62
  203. package/src/blockchain/core/ZipkitVerifier.ts +853 -0
  204. package/src/blockchain/core/contracts.ts +370 -0
  205. package/src/blockchain/core/index.ts +71 -0
  206. package/src/blockchain/index.ts +21 -55
  207. package/src/blockchain/node/WalletManagerNode.ts +171 -0
  208. package/src/blockchain/node/index.ts +40 -0
  209. package/src/browser/{ZipKitBrowser.ts → ZipkitBrowser.ts} +104 -41
  210. package/src/browser/index.esm.ts +37 -0
  211. package/src/browser/index.ts +25 -0
  212. package/src/core/ZipCompress.ts +398 -0
  213. package/src/core/ZipDecompress.ts +212 -0
  214. package/src/{shared → core}/ZipEntry.ts +240 -90
  215. package/src/core/Zipkit.ts +794 -0
  216. package/src/core/components/HashCalculator.ts +384 -0
  217. package/src/core/components/Logger.ts +180 -0
  218. package/src/core/components/ProgressTracker.ts +134 -0
  219. package/src/{shared → core}/components/Util.ts +12 -34
  220. package/src/{shared → core}/constants/Errors.ts +0 -4
  221. package/src/{shared → core}/constants/Headers.ts +19 -17
  222. package/src/core/encryption/Manager.ts +137 -0
  223. package/src/core/encryption/ZipCrypto.ts +650 -0
  224. package/src/core/encryption/index.ts +15 -0
  225. package/src/core/encryption/types.ts +33 -0
  226. package/src/core/index.ts +34 -0
  227. package/src/core/version.ts +33 -0
  228. package/src/index.ts +54 -25
  229. package/src/node/ZipCompressNode.ts +632 -0
  230. package/src/node/ZipDecompressNode.ts +508 -0
  231. package/src/node/ZipkitNode.ts +1559 -0
  232. package/src/node/index.ts +69 -0
  233. package/src/types/index.ts +131 -1
  234. package/src/types/modules.d.ts +1 -11
  235. package/src/types/opentimestamps.d.ts +1 -23
  236. package/contracts/INTEGRATION.md +0 -338
  237. package/contracts/NETWORKS.md +0 -156
  238. package/contracts/NZIP-NFT-bytecode.txt +0 -1
  239. package/contracts/constants.ts +0 -952
  240. package/contracts/deploy-bytecode.mjs +0 -94
  241. package/dist/blockchain/CertificateToken.d.ts +0 -48
  242. package/dist/blockchain/CertificateToken.js +0 -386
  243. package/dist/blockchain/ZipKitMinter.js +0 -347
  244. package/dist/blockchain/ZipKitNFT.d.ts +0 -3
  245. package/dist/blockchain/ZipKitNFT.js +0 -7
  246. package/dist/blockchain/ZipKitVerifier.d.ts +0 -69
  247. package/dist/blockchain/ZipKitVerifier.js +0 -289
  248. package/dist/blockchain/ZipKitWallet.d.ts +0 -69
  249. package/dist/blockchain/contracts.d.ts +0 -14
  250. package/dist/blockchain/contracts.js +0 -77
  251. package/dist/blockchain/types.d.ts +0 -47
  252. package/dist/blockchain/types.js +0 -30
  253. package/dist/browser/ZipKitBrowser.d.ts +0 -18
  254. package/dist/browser/ZipKitStampBrowser.d.ts +0 -2
  255. package/dist/browser/ZipKitStampBrowser.js +0 -12
  256. package/dist/browser-index.d.ts +0 -18
  257. package/dist/browser-index.js +0 -57
  258. package/dist/server/ZipKitServer.d.ts +0 -74
  259. package/dist/server/ZipKitServer.js +0 -310
  260. package/dist/shared/ZipKit.d.ts +0 -243
  261. package/dist/shared/ZipKit.js +0 -772
  262. package/dist/shared/components/CertificateOTS.d.ts +0 -15
  263. package/dist/shared/components/CertificateOTS.js +0 -116
  264. package/dist/shared/components/FileSys.d.ts +0 -2
  265. package/dist/shared/components/FileSys.js +0 -113
  266. package/dist/shared/components/HashAccumulator.d.ts +0 -55
  267. package/dist/shared/components/HashAccumulator.js +0 -100
  268. package/dist/shared/components/ZipCrypto.d.ts +0 -3
  269. package/dist/shared/components/ZipCrypto.js +0 -78
  270. package/dist/shared/components/merkleTree.d.ts +0 -66
  271. package/dist/shared/components/merkleTree.js +0 -136
  272. package/dist/shared/types/index.d.ts +0 -21
  273. package/dist/shared/types/index.js +0 -3
  274. package/dist/shared/types.d.ts +0 -33
  275. package/dist/shared/types.js +0 -8
  276. package/dist/shared/version.d.ts +0 -2
  277. package/dist/shared/version.js +0 -6
  278. package/src/blockchain/CertificateToken.ts +0 -444
  279. package/src/blockchain/ZipKitMinter.ts +0 -470
  280. package/src/blockchain/ZipKitNFT.ts +0 -12
  281. package/src/blockchain/ZipKitVerifier.ts +0 -382
  282. package/src/blockchain/contracts.ts +0 -88
  283. package/src/blockchain/types.ts +0 -91
  284. package/src/browser/CertificateGeneratorBrowser.ts-remove +0 -498
  285. package/src/browser/ZipKitStampBrowser.ts +0 -9
  286. package/src/browser-index.ts +0 -36
  287. package/src/server/README.md +0 -25
  288. package/src/server/ZipKitServer.ts +0 -305
  289. package/src/shared/ZipKit.ts +0 -881
  290. package/src/shared/components/CertificateOTS.ts +0 -132
  291. package/src/shared/components/FileSys.ts +0 -87
  292. package/src/shared/components/HashAccumulator.ts +0 -113
  293. package/src/shared/components/ZipCrypto.ts +0 -91
  294. package/src/shared/components/merkleTree.ts +0 -162
  295. package/src/shared/types/index.ts +0 -25
  296. package/src/shared/types/modules.d.ts +0 -22
  297. package/src/shared/types/opentimestamps.d.ts +0 -23
  298. package/src/shared/types.d.ts +0 -8
  299. package/src/shared/types.ts +0 -43
  300. package/src/shared/version.ts +0 -3
  301. /package/src/{shared → core}/components/Support.ts +0 -0
@@ -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
+ }
@@ -0,0 +1,212 @@
1
+ // ======================================
2
+ // ZipDecompress.ts - Decompression 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 } from './constants/Headers';
23
+ import { ZipCrypto } from './encryption/ZipCrypto';
24
+
25
+ export interface DecompressionResult {
26
+ success: boolean;
27
+ data?: Buffer;
28
+ error?: string;
29
+ }
30
+
31
+ export interface DecompressionOptions {
32
+ method: number; // Compression method code (0=stored, 8=deflate, 93=zstd)
33
+ debug?: boolean; // Enable debug logging
34
+ }
35
+
36
+ // Module-level singleton for ZSTD (shared across all instances)
37
+ let zstdCodec: { ZstdSimple: typeof ZstdSimple } | null = null;
38
+
39
+ // Async initialization function for zstd
40
+ async function initZstd(): Promise<{ ZstdSimple: typeof ZstdSimple }> {
41
+ if (!zstdCodec) {
42
+ zstdCodec = await ZstdInit();
43
+ }
44
+ return zstdCodec;
45
+ }
46
+
47
+ /**
48
+ * ZipDecompress - Unified Decompression Module (Internal to Zipkit)
49
+ * Consolidates decompression functionality from ZipCompress
50
+ * Supports deflate, zstd, and stored compression methods with chunked processing
51
+ *
52
+ * This class is internal to Zipkit and should not be used directly.
53
+ * Use Zipkit methods instead.
54
+ */
55
+ class ZipDecompress {
56
+ private zipkit: Zipkit;
57
+ private debug: boolean;
58
+ private zstdCodec: { ZstdSimple: typeof ZstdSimple } | null = null;
59
+
60
+ // Class-level logging control - set to true to enable logging
61
+ private static loggingEnabled: boolean = false;
62
+
63
+ /**
64
+ * Internal logging method - only logs if class logging is enabled
65
+ */
66
+ private log(...args: any[]): void {
67
+ if (ZipDecompress.loggingEnabled) {
68
+ Logger.debug(`[ZipDecompress]`, ...args);
69
+ }
70
+ }
71
+
72
+ constructor(zipkit: Zipkit) {
73
+ this.zipkit = zipkit;
74
+ // Debug disabled by default
75
+ this.debug = false;
76
+ // If logging is enabled, ensure Logger level is set to debug
77
+ if (ZipDecompress.loggingEnabled) {
78
+ Logger.setLevel('debug');
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Extract file data (Buffer-based ZIP only)
84
+ * Public method that validates buffer mode and extracts entry
85
+ *
86
+ * @param entry ZIP entry to extract
87
+ * @param skipHashCheck Skip hash verification (CRC-32 or SHA-256)
88
+ * @returns Promise resolving to extracted data as Buffer, or null if failed
89
+ * @throws Error if not a Buffer-based ZIP
90
+ */
91
+ async extract(entry: ZipEntry, skipHashCheck?: boolean): Promise<Buffer | null> {
92
+ if (!this.zipkit.hasInBuffer()) {
93
+ throw new Error('extract() requires Buffer-based ZIP. Use ZipkitNode.extractToFile() for file-based ZIP or call loadZip() first.');
94
+ }
95
+
96
+ this.log(`extract() called for entry: ${entry.filename}, method: ${entry.cmpMethod}, skipHashCheck: ${skipHashCheck}`);
97
+
98
+ // Lazy ZSTD initialization
99
+ if (entry.cmpMethod === CMP_METHOD.ZSTD && !this.zstdCodec) {
100
+ this.zstdCodec = await initZstd();
101
+ }
102
+
103
+ const buffer = this.zipkit.ensureBuffer();
104
+
105
+ // Decrypt if needed using password on zipkit instance
106
+ let fdata = this.zipkit.parseLocalHeader(entry, buffer);
107
+
108
+ if ((entry as any).isEncrypted && (this.zipkit as any)?.password) {
109
+ this.log(`Starting in-memory decryption for entry: ${entry.filename}`);
110
+
111
+ // Use ZipCrypto's decryptBuffer method which handles all the header parsing and decryption
112
+ const zipCrypto = new ZipCrypto();
113
+
114
+ fdata = zipCrypto.decryptBuffer(entry, buffer, fdata, (this.zipkit as any).password);
115
+
116
+ this.log(`Decryption successful, decrypted compressed data length: ${fdata.length}`);
117
+ }
118
+
119
+ if (fdata.length === 0) {
120
+ return null;
121
+ }
122
+
123
+ // Use the unCompress method
124
+ return this.unCompress(fdata, entry, skipHashCheck);
125
+ }
126
+
127
+
128
+
129
+ /**
130
+ * Inflate data using pako (internal use only)
131
+ */
132
+ private inflate(data: Buffer): Buffer {
133
+ this.log(`inflate() called with ${data.length} bytes`);
134
+ const result = pako.inflateRaw(data);
135
+ return Buffer.from(result.buffer, result.byteOffset, result.byteLength);
136
+ }
137
+
138
+
139
+ /**
140
+ * Synchronous zstd decompress method for in-memory mode
141
+ * ZSTD codec is guaranteed to be initialized via factory method
142
+ * Internal method only
143
+ */
144
+ private zstdDecompressSync(data: Buffer): Buffer {
145
+ this.log(`zstdDecompressSync() called with ${data.length} bytes`);
146
+
147
+ try {
148
+ // Ensure ZSTD is initialized
149
+ if (!this.zstdCodec) {
150
+ throw new Error('ZSTD codec not initialized.');
151
+ }
152
+ const decompressed = this.zstdCodec.ZstdSimple.decompress(data);
153
+ this.log(`ZSTD synchronous decompression successful: ${data.length} bytes -> ${decompressed.length} bytes`);
154
+ return Buffer.from(decompressed);
155
+ } catch (error) {
156
+ this.log(`ZSTD synchronous decompression failed: ${error}`);
157
+ throw new Error(`ZSTD synchronous decompression failed: ${error instanceof Error ? error.message : String(error)}`);
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Uncompress compressed data buffer (synchronous for in-memory mode)
163
+ * Handles decompression and hash verification
164
+ * Internal method only
165
+ */
166
+ private unCompress(
167
+ compressedData: Buffer,
168
+ entry: ZipEntry,
169
+ skipHashCheck?: boolean
170
+ ): Buffer {
171
+ this.log(`unCompress() called for entry: ${entry.filename}, method: ${entry.cmpMethod}, data length: ${compressedData.length}`);
172
+
173
+ if (compressedData.length === 0) {
174
+ return Buffer.alloc(0);
175
+ }
176
+
177
+ let outBuf: Buffer;
178
+ if (entry.cmpMethod === CMP_METHOD.STORED) {
179
+ outBuf = compressedData;
180
+ } else if (entry.cmpMethod === CMP_METHOD.DEFLATED) {
181
+ // Use synchronous inflate for deflate
182
+ outBuf = this.inflate(compressedData);
183
+ } else if (entry.cmpMethod === CMP_METHOD.ZSTD) {
184
+ // Use synchronous ZSTD decompression for in-memory mode
185
+ outBuf = this.zstdDecompressSync(compressedData);
186
+ } else {
187
+ throw new Error(`Unsupported compression method: ${entry.cmpMethod}`);
188
+ }
189
+
190
+ // Verify hash
191
+ if (!skipHashCheck) {
192
+ if (entry.sha256) {
193
+ const isValid = this.zipkit.testSHA256(entry, outBuf);
194
+ if (!isValid) {
195
+ throw new Error(Errors.INVALID_SHA256);
196
+ }
197
+ } else {
198
+ const isValid = this.zipkit.testCRC32(entry, outBuf);
199
+ if (!isValid) {
200
+ throw new Error(Errors.INVALID_CRC);
201
+ }
202
+ }
203
+ }
204
+
205
+ return outBuf;
206
+ }
207
+
208
+
209
+ }
210
+
211
+ // Default export for internal use by Zipkit only
212
+ export default ZipDecompress;