@neoware_inc/neozipkit 0.5.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 (171) hide show
  1. package/README.md +134 -0
  2. package/dist/browser/ZipkitBrowser.d.ts +27 -0
  3. package/dist/browser/ZipkitBrowser.d.ts.map +1 -0
  4. package/dist/browser/ZipkitBrowser.js +303 -0
  5. package/dist/browser/ZipkitBrowser.js.map +1 -0
  6. package/dist/browser/index.d.ts +9 -0
  7. package/dist/browser/index.d.ts.map +1 -0
  8. package/dist/browser/index.esm.d.ts +12 -0
  9. package/dist/browser/index.esm.d.ts.map +1 -0
  10. package/dist/browser/index.esm.js +46 -0
  11. package/dist/browser/index.esm.js.map +1 -0
  12. package/dist/browser/index.js +38 -0
  13. package/dist/browser/index.js.map +1 -0
  14. package/dist/browser-esm/index.d.ts +9 -0
  15. package/dist/browser-esm/index.js +50211 -0
  16. package/dist/browser-esm/index.js.map +7 -0
  17. package/dist/browser-umd/index.d.ts +9 -0
  18. package/dist/browser-umd/index.js +50221 -0
  19. package/dist/browser-umd/index.js.map +7 -0
  20. package/dist/browser-umd/index.min.js +39 -0
  21. package/dist/browser.d.ts +9 -0
  22. package/dist/browser.js +38 -0
  23. package/dist/core/ZipCompress.d.ts +99 -0
  24. package/dist/core/ZipCompress.d.ts.map +1 -0
  25. package/dist/core/ZipCompress.js +287 -0
  26. package/dist/core/ZipCompress.js.map +1 -0
  27. package/dist/core/ZipCopy.d.ts +175 -0
  28. package/dist/core/ZipCopy.d.ts.map +1 -0
  29. package/dist/core/ZipCopy.js +310 -0
  30. package/dist/core/ZipCopy.js.map +1 -0
  31. package/dist/core/ZipDecompress.d.ts +57 -0
  32. package/dist/core/ZipDecompress.d.ts.map +1 -0
  33. package/dist/core/ZipDecompress.js +155 -0
  34. package/dist/core/ZipDecompress.js.map +1 -0
  35. package/dist/core/ZipEntry.d.ts +138 -0
  36. package/dist/core/ZipEntry.d.ts.map +1 -0
  37. package/dist/core/ZipEntry.js +829 -0
  38. package/dist/core/ZipEntry.js.map +1 -0
  39. package/dist/core/Zipkit.d.ts +315 -0
  40. package/dist/core/Zipkit.d.ts.map +1 -0
  41. package/dist/core/Zipkit.js +647 -0
  42. package/dist/core/Zipkit.js.map +1 -0
  43. package/dist/core/ZstdManager.d.ts +56 -0
  44. package/dist/core/ZstdManager.d.ts.map +1 -0
  45. package/dist/core/ZstdManager.js +144 -0
  46. package/dist/core/ZstdManager.js.map +1 -0
  47. package/dist/core/components/HashCalculator.d.ts +138 -0
  48. package/dist/core/components/HashCalculator.d.ts.map +1 -0
  49. package/dist/core/components/HashCalculator.js +360 -0
  50. package/dist/core/components/HashCalculator.js.map +1 -0
  51. package/dist/core/components/Logger.d.ts +73 -0
  52. package/dist/core/components/Logger.d.ts.map +1 -0
  53. package/dist/core/components/Logger.js +156 -0
  54. package/dist/core/components/Logger.js.map +1 -0
  55. package/dist/core/components/ProgressTracker.d.ts +43 -0
  56. package/dist/core/components/ProgressTracker.d.ts.map +1 -0
  57. package/dist/core/components/ProgressTracker.js +112 -0
  58. package/dist/core/components/ProgressTracker.js.map +1 -0
  59. package/dist/core/components/Support.d.ts +64 -0
  60. package/dist/core/components/Support.d.ts.map +1 -0
  61. package/dist/core/components/Support.js +71 -0
  62. package/dist/core/components/Support.js.map +1 -0
  63. package/dist/core/components/Util.d.ts +26 -0
  64. package/dist/core/components/Util.d.ts.map +1 -0
  65. package/dist/core/components/Util.js +95 -0
  66. package/dist/core/components/Util.js.map +1 -0
  67. package/dist/core/constants/Errors.d.ts +52 -0
  68. package/dist/core/constants/Errors.d.ts.map +1 -0
  69. package/dist/core/constants/Errors.js +67 -0
  70. package/dist/core/constants/Errors.js.map +1 -0
  71. package/dist/core/constants/Headers.d.ts +170 -0
  72. package/dist/core/constants/Headers.d.ts.map +1 -0
  73. package/dist/core/constants/Headers.js +194 -0
  74. package/dist/core/constants/Headers.js.map +1 -0
  75. package/dist/core/encryption/Manager.d.ts +58 -0
  76. package/dist/core/encryption/Manager.d.ts.map +1 -0
  77. package/dist/core/encryption/Manager.js +121 -0
  78. package/dist/core/encryption/Manager.js.map +1 -0
  79. package/dist/core/encryption/ZipCrypto.d.ts +172 -0
  80. package/dist/core/encryption/ZipCrypto.d.ts.map +1 -0
  81. package/dist/core/encryption/ZipCrypto.js +554 -0
  82. package/dist/core/encryption/ZipCrypto.js.map +1 -0
  83. package/dist/core/encryption/index.d.ts +9 -0
  84. package/dist/core/encryption/index.d.ts.map +1 -0
  85. package/dist/core/encryption/index.js +17 -0
  86. package/dist/core/encryption/index.js.map +1 -0
  87. package/dist/core/encryption/types.d.ts +29 -0
  88. package/dist/core/encryption/types.d.ts.map +1 -0
  89. package/dist/core/encryption/types.js +12 -0
  90. package/dist/core/encryption/types.js.map +1 -0
  91. package/dist/core/index.d.ts +27 -0
  92. package/dist/core/index.d.ts.map +1 -0
  93. package/dist/core/index.js +59 -0
  94. package/dist/core/index.js.map +1 -0
  95. package/dist/core/version.d.ts +5 -0
  96. package/dist/core/version.d.ts.map +1 -0
  97. package/dist/core/version.js +31 -0
  98. package/dist/core/version.js.map +1 -0
  99. package/dist/index.d.ts +9 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +38 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/node/ZipCompressNode.d.ts +123 -0
  104. package/dist/node/ZipCompressNode.d.ts.map +1 -0
  105. package/dist/node/ZipCompressNode.js +565 -0
  106. package/dist/node/ZipCompressNode.js.map +1 -0
  107. package/dist/node/ZipCopyNode.d.ts +165 -0
  108. package/dist/node/ZipCopyNode.d.ts.map +1 -0
  109. package/dist/node/ZipCopyNode.js +347 -0
  110. package/dist/node/ZipCopyNode.js.map +1 -0
  111. package/dist/node/ZipDecompressNode.d.ts +197 -0
  112. package/dist/node/ZipDecompressNode.d.ts.map +1 -0
  113. package/dist/node/ZipDecompressNode.js +678 -0
  114. package/dist/node/ZipDecompressNode.js.map +1 -0
  115. package/dist/node/ZipkitNode.d.ts +466 -0
  116. package/dist/node/ZipkitNode.d.ts.map +1 -0
  117. package/dist/node/ZipkitNode.js +1426 -0
  118. package/dist/node/ZipkitNode.js.map +1 -0
  119. package/dist/node/index.d.ts +25 -0
  120. package/dist/node/index.d.ts.map +1 -0
  121. package/dist/node/index.js +54 -0
  122. package/dist/node/index.js.map +1 -0
  123. package/dist/types/index.d.ts +45 -0
  124. package/dist/types/index.d.ts.map +1 -0
  125. package/dist/types/index.js +11 -0
  126. package/dist/types/index.js.map +1 -0
  127. package/examples/README.md +261 -0
  128. package/examples/append-data.json +44 -0
  129. package/examples/copy-zip-append.ts +139 -0
  130. package/examples/copy-zip.ts +152 -0
  131. package/examples/create-zip.ts +172 -0
  132. package/examples/extract-zip.ts +118 -0
  133. package/examples/list-zip.ts +161 -0
  134. package/examples/test-files/data.json +116 -0
  135. package/examples/test-files/document.md +80 -0
  136. package/examples/test-files/document.txt +6 -0
  137. package/examples/test-files/file1.txt +48 -0
  138. package/examples/test-files/file2.txt +80 -0
  139. package/examples/tsconfig.json +44 -0
  140. package/package.json +167 -0
  141. package/src/browser/ZipkitBrowser.ts +305 -0
  142. package/src/browser/index.esm.ts +32 -0
  143. package/src/browser/index.ts +19 -0
  144. package/src/core/ZipCompress.ts +370 -0
  145. package/src/core/ZipCopy.ts +434 -0
  146. package/src/core/ZipDecompress.ts +191 -0
  147. package/src/core/ZipEntry.ts +917 -0
  148. package/src/core/Zipkit.ts +794 -0
  149. package/src/core/ZstdManager.ts +165 -0
  150. package/src/core/components/HashCalculator.ts +384 -0
  151. package/src/core/components/Logger.ts +180 -0
  152. package/src/core/components/ProgressTracker.ts +134 -0
  153. package/src/core/components/Support.ts +77 -0
  154. package/src/core/components/Util.ts +91 -0
  155. package/src/core/constants/Errors.ts +78 -0
  156. package/src/core/constants/Headers.ts +205 -0
  157. package/src/core/encryption/Manager.ts +137 -0
  158. package/src/core/encryption/ZipCrypto.ts +650 -0
  159. package/src/core/encryption/index.ts +15 -0
  160. package/src/core/encryption/types.ts +33 -0
  161. package/src/core/index.ts +42 -0
  162. package/src/core/version.ts +33 -0
  163. package/src/index.ts +19 -0
  164. package/src/node/ZipCompressNode.ts +618 -0
  165. package/src/node/ZipCopyNode.ts +437 -0
  166. package/src/node/ZipDecompressNode.ts +793 -0
  167. package/src/node/ZipkitNode.ts +1706 -0
  168. package/src/node/index.ts +40 -0
  169. package/src/types/index.ts +68 -0
  170. package/src/types/modules.d.ts +22 -0
  171. package/src/types/opentimestamps.d.ts +1 -0
package/package.json ADDED
@@ -0,0 +1,167 @@
1
+ {
2
+ "name": "@neoware_inc/neozipkit",
3
+ "version": "0.5.0",
4
+ "packageManager": "yarn@4.12.0",
5
+ "description": "NeoZipKit - Advanced ZIP file creation, compression, and encryption",
6
+ "main": "index.js",
7
+ "types": "index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "browser": {
11
+ "types": "./dist/browser.d.ts",
12
+ "default": "./dist/browser.js"
13
+ },
14
+ "node": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.js"
20
+ },
21
+ "./browser": {
22
+ "types": "./dist/browser.d.ts",
23
+ "default": "./dist/browser.js"
24
+ },
25
+ "./browser/*": {
26
+ "types": "./dist/browser/*.d.ts",
27
+ "default": "./dist/browser/*.js"
28
+ },
29
+ "./browser-esm": {
30
+ "types": "./dist/browser-esm/index.d.ts",
31
+ "import": "./dist/browser-esm/index.js"
32
+ },
33
+ "./browser-umd": {
34
+ "types": "./dist/browser-umd/index.d.ts",
35
+ "import": "./dist/browser-umd/index.js",
36
+ "require": "./dist/browser-umd/index.js"
37
+ },
38
+ "./node": {
39
+ "types": "./dist/node/index.d.ts",
40
+ "import": "./dist/node/index.js",
41
+ "require": "./dist/node/index.js",
42
+ "default": "./dist/node/index.js"
43
+ },
44
+ "./node/*": {
45
+ "types": "./dist/node/*.d.ts",
46
+ "default": "./dist/node/*.js"
47
+ },
48
+ "./node/platform/*": {
49
+ "types": "./dist/node/platform/*.d.ts",
50
+ "default": "./dist/node/platform/*.js"
51
+ },
52
+ "./shared": {
53
+ "types": "./dist/shared/index.d.ts",
54
+ "default": "./dist/shared/index.js"
55
+ },
56
+ "./shared/*": {
57
+ "types": "./dist/shared/*.d.ts",
58
+ "default": "./dist/shared/*.js"
59
+ },
60
+ "./shared/components/*": {
61
+ "types": "./dist/shared/components/*.d.ts",
62
+ "default": "./dist/shared/components/*.js"
63
+ },
64
+ "./shared/constants/*": {
65
+ "types": "./dist/shared/constants/*.d.ts",
66
+ "default": "./dist/shared/constants/*.js"
67
+ },
68
+ "./src": {
69
+ "types": "./src/index.ts",
70
+ "default": "./src/index.ts"
71
+ },
72
+ "./src/*": {
73
+ "types": "./src/*.ts",
74
+ "default": "./src/*.ts"
75
+ },
76
+ "./src/node": {
77
+ "types": "./src/node/index.ts",
78
+ "default": "./src/node/index.ts"
79
+ },
80
+ "./src/node/*": {
81
+ "types": "./src/node/*.ts",
82
+ "default": "./src/node/*.ts"
83
+ },
84
+ "./src/components/*": {
85
+ "types": "./src/components/*.ts",
86
+ "default": "./src/components/*.ts"
87
+ }
88
+ },
89
+ "files": [
90
+ "dist/",
91
+ "src/",
92
+ "examples/",
93
+ "README.md"
94
+ ],
95
+ "scripts": {
96
+ "clean": "node scripts/clean.js",
97
+ "compile": "tsc",
98
+ "create-browser-entry": "node scripts/create-browser-entry.js",
99
+ "build": "npm run clean && npm run compile && npm run create-browser-entry && npm run build:browser",
100
+ "build:browser": "npm run build:browser:esm && npm run build:browser:umd",
101
+ "build:browser:esm": "node scripts/build-browser-bundle.js --esm",
102
+ "build:browser:umd": "node scripts/build-browser-bundle.js --umd",
103
+ "watch": "tsc --watch",
104
+ "dev:clean": "node scripts/dev-clean.js",
105
+ "dev:compile": "tsc --project tsconfig.dev.json",
106
+ "dev:create-browser-entry": "node scripts/dev-create-browser-entry.js",
107
+ "dev:build": "npm run dev:clean && npm run dev:compile && npm run dev:create-browser-entry",
108
+ "dev:watch": "tsc --project tsconfig.dev.json --watch",
109
+ "build:auto": "node scripts/auto-build.js",
110
+ "build:ci": "node scripts/check-branch.js && npm run clean && npm run compile && npm run create-browser-entry",
111
+ "test": "yarn exec jest",
112
+ "test:unit": "yarn exec jest tests/unit",
113
+ "test:examples": "yarn exec ts-node scripts/test-examples.ts",
114
+ "test:all": "npm run test:unit && npm run test:examples",
115
+ "test:watch": "yarn exec jest --watch",
116
+ "test:coverage": "yarn exec jest --coverage",
117
+ "audit": "yarn npm audit",
118
+ "example:create-zip": "npx ts-node examples/create-zip.ts",
119
+ "example:extract-zip": "npx ts-node examples/extract-zip.ts",
120
+ "example:list-zip": "npx ts-node examples/list-zip.ts",
121
+ "example:copy-zip": "npx ts-node examples/copy-zip.ts",
122
+ "release": "node scripts/ensure-npm-auth.js && yarn build && npm publish --access public",
123
+ "release:login": "npm login",
124
+ "version": "node scripts/update-version.js",
125
+ "version:set": "node scripts/update-version.js",
126
+ "version:patch": "node scripts/update-version.js patch",
127
+ "version:minor": "node scripts/update-version.js minor",
128
+ "version:major": "node scripts/update-version.js major"
129
+ },
130
+ "keywords": [
131
+ "zip",
132
+ "archive",
133
+ "verification",
134
+ "crypto",
135
+ "compression",
136
+ "encryption"
137
+ ],
138
+ "author": "NeoWare, Inc.",
139
+ "repository": {
140
+ "type": "git",
141
+ "url": "git+https://github.com/NeoWareInc/neozipkit.git"
142
+ },
143
+ "bugs": {
144
+ "url": "https://github.com/NeoWareInc/neozipkit/issues"
145
+ },
146
+ "homepage": "https://github.com/NeoWareInc/neozipkit#readme",
147
+ "license": "MIT",
148
+ "devDependencies": {
149
+ "@jest/core": "29.7.0",
150
+ "@jest/test-sequencer": "29.7.0",
151
+ "@types/jest": "29.5.12",
152
+ "@types/node": "^24.3.1",
153
+ "@types/pako": "^2.0.3",
154
+ "@types/uuid": "^9.0.0",
155
+ "esbuild": "^0.25.0",
156
+ "jest": "29.7.0",
157
+ "minimatch": "^10.2.1",
158
+ "ts-jest": "29.1.2",
159
+ "typescript": "^5.0.0"
160
+ },
161
+ "dependencies": {
162
+ "@oneidentity/zstd-js": "^1.0.3",
163
+ "buffer": "^6.0.3",
164
+ "pako": "^2.1.0",
165
+ "uuid": "^9.0.0"
166
+ }
167
+ }
@@ -0,0 +1,305 @@
1
+ // ======================================
2
+ // ZipkitBrowser.ts
3
+ // Copyright (c) 2025 NeoWare, Inc. All rights reserved.
4
+ // ======================================
5
+
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';
19
+ export { ZipEntry, Errors, Headers, sha256, getTypeOf };
20
+
21
+ // ======================================
22
+ // ZipkitBrowser
23
+ // ======================================
24
+
25
+ export default class ZipkitBrowser extends Zipkit {
26
+ constructor() {
27
+ super(); // Call the parent constructor
28
+
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);
34
+ }
35
+
36
+ // --------------------------------------
37
+ // Load a ZIP file from a Blob and return the ZipEntry array
38
+ // Always uses loadZip() to ensure proper initialization
39
+
40
+ async loadZipBlob(data: Blob): Promise<ZipEntry[] | null> {
41
+ if (getTypeOf(data) !== DATATYPE.BLOB) {
42
+ throw new Error(Errors.DATATYPE_UNSUPPORTED);
43
+ }
44
+
45
+ return new Promise((resolve, reject) => {
46
+ const reader = new window.FileReader();
47
+ reader.readAsArrayBuffer(data);
48
+
49
+ reader.onload = (e: ProgressEvent<FileReader>) => {
50
+ if (!reader.result) {
51
+ reject(new Error('Failed to read file'));
52
+ return;
53
+ }
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
+ }
70
+ };
71
+
72
+ reader.onerror = () => {
73
+ reject(reader.error || new Error('Failed to read file'));
74
+ };
75
+ });
76
+ }
77
+
78
+ // --------------------------------------
79
+ // Create a ZipEntry for a File object
80
+
81
+ createZipFileEntry(file: FileData): ZipEntry {
82
+ const entry = super.createZipEntry(file.name);
83
+ entry.fileData = file;
84
+ entry.uncompressedSize = file.size;
85
+
86
+ const fileDate = new Date(file.lastModified);
87
+ entry.timeDateDOS = entry.setDateTime(fileDate);
88
+ entry.cmpMethod = Headers.CMP_METHOD.DEFLATED;
89
+
90
+ return entry;
91
+ }
92
+
93
+ // --------------------------------------
94
+ // Calculate the SHA256 hash of a File object
95
+
96
+ async hashFile(file: FileData): Promise<string> {
97
+ const arrayBuffer = await file.arrayBuffer();
98
+ const buffer = Buffer.from(arrayBuffer);
99
+ return sha256(buffer);
100
+ }
101
+
102
+ // --------------------------------------
103
+ // Compress the data and return the compressed data buffer
104
+ // Set the ZipEntry compressSize and CRC32 values
105
+
106
+ async compressDataBlob(entry: ZipEntry, data: Blob, options?: CompressOptions): Promise<Buffer> {
107
+ if (getTypeOf(data) !== DATATYPE.BLOB) {
108
+ throw new Error(Errors.DATATYPE_UNSUPPORTED);
109
+ }
110
+
111
+ return new Promise(async (resolve, reject) => {
112
+ const _compressData = async (entry: ZipEntry, data: Buffer, options?: CompressOptions): Promise<Buffer> => {
113
+ // Use Zipkit wrapper method
114
+ return await this.compressData(entry, data, options);
115
+ };
116
+
117
+ const reader = new window.FileReader();
118
+ reader.readAsArrayBuffer(data);
119
+
120
+ reader.onload = async function(this: FileReader, e: ProgressEvent<FileReader>) {
121
+ if (!this.result) {
122
+ reject(new Error('Failed to read file'));
123
+ return;
124
+ }
125
+ try {
126
+ const _inBuf = Buffer.from(this.result as ArrayBuffer);
127
+ const result = await _compressData(entry, _inBuf, options);
128
+ resolve(result);
129
+ } catch (error) {
130
+ reject(error);
131
+ }
132
+ };
133
+
134
+ reader.onerror = function(this: FileReader, e: ProgressEvent<FileReader>) {
135
+ reject(this.error || new Error('Failed to read file'));
136
+ };
137
+ });
138
+ }
139
+
140
+ // --------------------------------------
141
+ // Extract a Blob from a ZipEntry
142
+
143
+ async extractBlob(entry: ZipEntry, skipHashCheck?: boolean): Promise<Blob | null> {
144
+ try {
145
+ const _outBuf = await this.extract(entry, skipHashCheck);
146
+ if (!_outBuf) return null;
147
+
148
+ // Convert Buffer to Uint8Array for Blob compatibility
149
+ const uint8Array = new Uint8Array(_outBuf);
150
+ return new Blob([uint8Array], { type: 'application/octet-stream' });
151
+ } catch (error) {
152
+ throw error;
153
+ }
154
+ }
155
+
156
+ // --------------------------------------
157
+ // Create a ZIP file in memory and return a Blob
158
+
159
+ async createZipBlob(cmpOptions?: CompressOptions, options?: CreateZipOptions): Promise<Blob | null> {
160
+ const _onError = options?.onError || (() => {});
161
+ const _onEntryDone = options?.onEntryDone || (() => {});
162
+
163
+ const zipEntries = super.getDirectory();
164
+ if (!zipEntries) {
165
+ _onError(new Error(Errors.NO_FILES));
166
+ return null;
167
+ }
168
+
169
+ let offset = 0;
170
+ const buffers: Buffer[] = [];
171
+
172
+ for (const entry of zipEntries) {
173
+ if (!entry.isUpdated) {
174
+ // Check for META-INF metadata files even in copy mode
175
+ if (entry.filename === TOKENIZED_METADATA || entry.filename === TIMESTAMP_SUBMITTED || entry.filename === TIMESTAMP_METADATA) {
176
+ // Force this entry to be processed with special handling instead of copied
177
+ entry.isUpdated = true;
178
+ // Don't continue here - let it fall through to special handling below
179
+ } else {
180
+ const inData = await super.copyEntry(entry);
181
+ entry.localHdrOffset = offset;
182
+ offset += inData.length;
183
+ buffers.push(inData);
184
+ _onEntryDone(entry, 'Copied');
185
+ continue;
186
+ }
187
+ }
188
+
189
+ if (!entry.fileData) {
190
+ _onError(new Error(Errors.FILE_NOT_FOUND));
191
+ return null;
192
+ }
193
+
194
+ const fileBuffer = await entry.fileData.arrayBuffer();
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
+
209
+ // Special handling for META-INF metadata files - store uncompressed with CRC-32
210
+ if (entry.filename === TOKENIZED_METADATA || entry.filename === TIMESTAMP_SUBMITTED || entry.filename === TIMESTAMP_METADATA) {
211
+ // For metadata files, use STORED compression (no compression)
212
+ const buffer = Buffer.from(fileBuffer);
213
+
214
+ // Calculate CRC-32 for the metadata file (not SHA-256 to avoid Merkle Root interference)
215
+ entry.crc = crc32(buffer);
216
+
217
+ // Set up entry for STORED compression
218
+ entry.cmpMethod = 0; // STORED
219
+ entry.compressedSize = buffer.length;
220
+ entry.uncompressedSize = buffer.length;
221
+
222
+ // Do NOT set SHA-256 hash for metadata files to avoid Merkle Root calculation
223
+ // entry.sha256 should remain undefined for metadata files
224
+
225
+ const localHdr = entry.createLocalHdr();
226
+ entry.localHdrOffset = offset;
227
+ offset += localHdr.length + buffer.length;
228
+
229
+ buffers.push(localHdr);
230
+ buffers.push(buffer);
231
+ _onEntryDone(entry, 'Stored (metadata)');
232
+ } else {
233
+ // Normal file processing with compression
234
+ const cmpData = await this.compressData(entry, Buffer.from(fileBuffer), cmpOptions);
235
+ const localHdr = entry.createLocalHdr();
236
+
237
+ entry.localHdrOffset = offset;
238
+ offset += localHdr.length + cmpData.length;
239
+
240
+ buffers.push(localHdr);
241
+ buffers.push(cmpData);
242
+ _onEntryDone(entry, 'Written');
243
+ }
244
+ }
245
+
246
+ const centralDirOffset = offset;
247
+ for (const entry of zipEntries) {
248
+ const centralDirEntry = entry.centralDirEntry();
249
+ offset += centralDirEntry.length;
250
+ buffers.push(centralDirEntry);
251
+ }
252
+
253
+ const centralDirSize = offset - centralDirOffset;
254
+ const ceBuf = super.centralEndHdr(centralDirSize, centralDirOffset);
255
+ buffers.push(ceBuf);
256
+
257
+ const combinedBuffer = Buffer.concat(buffers);
258
+ // Convert Buffer to Uint8Array for Blob compatibility
259
+ const uint8Array = new Uint8Array(combinedBuffer);
260
+ return new Blob([uint8Array], { type: 'application/zip' });
261
+ }
262
+
263
+ /**
264
+ * Checks if a filename is a metadata file (META-INF) 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
+ }
305
+ }
@@ -0,0 +1,32 @@
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 } from '../types';
25
+ export * from '../core/constants/Headers';
26
+ export * from '../core/constants/Errors';
27
+
28
+ // Platform utilities
29
+ export const PlatformUtils = {
30
+ isBrowser: typeof window !== 'undefined' && typeof document !== 'undefined',
31
+ isNode: typeof process !== 'undefined' && process.versions && process.versions.node,
32
+ };
@@ -0,0 +1,19 @@
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
+
13
+ // Platform-specific conditional exports
14
+ export const PlatformUtils = {
15
+ // Browser detection
16
+ isBrowser: typeof window !== 'undefined' && typeof document !== 'undefined',
17
+ // Node.js detection
18
+ isNode: typeof process !== 'undefined' && process.versions && process.versions.node,
19
+ };