@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
@@ -0,0 +1,165 @@
1
+ import ZipEntry from '../core/ZipEntry';
2
+ import ZipkitNode from './ZipkitNode';
3
+ /**
4
+ * Options for copying ZIP files
5
+ */
6
+ export interface CopyOptions {
7
+ /** Filter function to determine which entries to copy */
8
+ entryFilter?: (entry: ZipEntry) => boolean;
9
+ /** Sort function to reorder entries before copying */
10
+ entrySorter?: (a: ZipEntry, b: ZipEntry) => number;
11
+ /** Whether to preserve the ZIP file comment (default: true) */
12
+ preserveComments?: boolean;
13
+ }
14
+ /**
15
+ * Result of copying a ZIP file
16
+ */
17
+ export interface CopyResult {
18
+ /** Information about copied entries */
19
+ entries: Array<{
20
+ filename: string;
21
+ localHeaderOffset: number;
22
+ compressedSize: number;
23
+ }>;
24
+ /** Offset to the start of the central directory */
25
+ centralDirOffset: number;
26
+ /** Total number of entries copied */
27
+ totalEntries: number;
28
+ }
29
+ /**
30
+ * Result of copying only ZIP entry data (no central directory or EOCD).
31
+ * Use with writeCentralDirectoryAndEOCD after optionally adding more entries
32
+ * to allow building a ZIP that includes both copied and new entries.
33
+ */
34
+ export interface CopyEntriesOnlyResult {
35
+ /** Path to the destination file (entry data only; not yet a valid ZIP) */
36
+ destPath: string;
37
+ /** Offset at which entry data ends; central directory should start here after any new entries are appended */
38
+ dataEndOffset: number;
39
+ /** Copied entries with localHdrOffset set for the destination file */
40
+ copiedEntries: ZipEntry[];
41
+ }
42
+ /**
43
+ * Options for finalizing a ZIP file (writing central directory and EOCD)
44
+ */
45
+ export interface FinalizeZipOptions {
46
+ /** ZIP file comment (default: empty) */
47
+ zipComment?: string;
48
+ }
49
+ /**
50
+ * Efficient ZIP file copying class
51
+ *
52
+ * Uses ZipEntry instances directly to copy entries without decompression/recompression.
53
+ * Supports filtering and reordering entries while maintaining ZIP file validity.
54
+ *
55
+ * Entry data and the central directory / EOCD are separated so you can add files
56
+ * to the copy before finalizing: use copyZipEntriesOnly, append new entries at
57
+ * dataEndOffset, then call writeCentralDirectoryAndEOCD with all entries.
58
+ *
59
+ * @example Full copy (one shot)
60
+ * ```typescript
61
+ * const zipCopy = new ZipCopyNode(new ZipkitNode());
62
+ * const result = await zipCopy.copyZipFile('source.zip', 'dest.zip', {
63
+ * entryFilter: (entry) => !entry.filename.startsWith('.'),
64
+ * entrySorter: (a, b) => a.filename.localeCompare(b.filename)
65
+ * });
66
+ * ```
67
+ *
68
+ * @example Copy then add files before finalizing
69
+ * ```typescript
70
+ * const zipCopy = new ZipCopyNode(new ZipkitNode());
71
+ * const { destPath, dataEndOffset, copiedEntries } = await zipCopy.copyZipEntriesOnly('source.zip', 'dest.zip');
72
+ * // ... append new entries to destPath at dataEndOffset, collect new ZipEntry[] with localHdrOffset set ...
73
+ * const allEntries = [...copiedEntries, ...newEntries];
74
+ * zipCopy.writeCentralDirectoryAndEOCD(destPath, allEntries, { zipComment: '' });
75
+ * ```
76
+ */
77
+ export declare class ZipCopyNode {
78
+ private zipkitNode;
79
+ /**
80
+ * Creates a new ZipCopyNode instance
81
+ * @param zipkitNode - Optional ZipkitNode instance. If not provided, creates a new one.
82
+ */
83
+ constructor(zipkitNode?: ZipkitNode);
84
+ /**
85
+ * Calculate local header size by reading the actual local header
86
+ *
87
+ * Reads the first 30 bytes of the local header to get the exact
88
+ * filename and extra field lengths, ensuring accuracy even when
89
+ * local header differs from central directory.
90
+ *
91
+ * @param sourceFd - File descriptor for source ZIP file
92
+ * @param entry - ZipEntry with localHdrOffset
93
+ * @returns Size of the local header in bytes
94
+ */
95
+ private calculateLocalHeaderSize;
96
+ /**
97
+ * Copy entry bytes directly from source to destination
98
+ *
99
+ * Copies the local header and compressed data as a single operation.
100
+ *
101
+ * Handles various entry types:
102
+ * - Normal entries: [local header][filename][extra][compressed data]
103
+ * - Encrypted entries: compressedSize includes 12-byte encryption header
104
+ * - Data descriptor entries: [local header][filename][extra][data][data descriptor (16 bytes)]
105
+ *
106
+ * For data descriptor entries, the local header has compressed size = 0,
107
+ * but the actual size is in the central directory (entry.compressedSize).
108
+ *
109
+ * @param sourceFd - File descriptor for source ZIP file
110
+ * @param destFd - File descriptor for destination ZIP file
111
+ * @param entry - ZipEntry with source offset information
112
+ * @returns Number of bytes written
113
+ */
114
+ private copyEntryBytes;
115
+ /**
116
+ * Clone a ZipEntry with a new local header offset
117
+ *
118
+ * Creates a new ZipEntry instance with all properties copied from the source,
119
+ * but with an updated localHdrOffset for the destination file.
120
+ *
121
+ * @param entry - Source ZipEntry to clone
122
+ * @param newLocalHdrOffset - New local header offset for the destination
123
+ * @returns New ZipEntry instance with updated offset
124
+ */
125
+ private cloneEntryWithOffset;
126
+ /**
127
+ * Write central directory and End of Central Directory record to an open file descriptor.
128
+ * Used internally by copyZipFile and by writeCentralDirectoryAndEOCD.
129
+ */
130
+ private writeCentralDirectoryAndEOCDToFd;
131
+ /**
132
+ * Copy only ZIP entry data to the destination file (no central directory or EOCD).
133
+ * Use this when you want to add more entries before finalizing. Then call
134
+ * writeCentralDirectoryAndEOCD with all entries (copied + new) to produce a valid ZIP.
135
+ *
136
+ * @param sourceZipPath - Path to source ZIP file
137
+ * @param destZipPath - Path to destination file (will contain only entry data until finalized)
138
+ * @param options - Optional copy options (filtering, sorting)
139
+ * @returns Result with dataEndOffset and copiedEntries for use when adding files and finalizing
140
+ */
141
+ copyZipEntriesOnly(sourceZipPath: string, destZipPath: string, options?: CopyOptions): Promise<CopyEntriesOnlyResult>;
142
+ /**
143
+ * Append central directory and End of Central Directory to a file that already
144
+ * contains ZIP entry data (e.g. from copyZipEntriesOnly plus any newly added entries).
145
+ * Call this after adding files to produce a valid ZIP.
146
+ *
147
+ * @param destZipPath - Path to the partial ZIP file (entry data only)
148
+ * @param entries - All entries in order (copied + any new), each with localHdrOffset set
149
+ * @param options - Optional finalize options (e.g. zipComment)
150
+ */
151
+ writeCentralDirectoryAndEOCD(destZipPath: string, entries: ZipEntry[], options?: FinalizeZipOptions): void;
152
+ /**
153
+ * Copy ZIP file entries efficiently
154
+ *
155
+ * Main method that copies entries from source ZIP to destination ZIP.
156
+ * Uses ZipEntry instances directly to avoid unnecessary parsing.
157
+ *
158
+ * @param sourceZipPath - Path to source ZIP file
159
+ * @param destZipPath - Path to destination ZIP file
160
+ * @param options - Optional copy options (filtering, sorting, etc.)
161
+ * @returns Copy result with entry information
162
+ */
163
+ copyZipFile(sourceZipPath: string, destZipPath: string, options?: CopyOptions): Promise<CopyResult>;
164
+ }
165
+ //# sourceMappingURL=ZipCopyNode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ZipCopyNode.d.ts","sourceRoot":"","sources":["../../src/node/ZipCopyNode.ts"],"names":[],"mappings":"AAUA,OAAO,QAAQ,MAAM,kBAAkB,CAAC;AACxC,OAAO,UAAU,MAAM,cAAc,CAAC;AAGtC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC;IAC3C,sDAAsD;IACtD,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,KAAK,MAAM,CAAC;IACnD,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,uCAAuC;IACvC,OAAO,EAAE,KAAK,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC,CAAC;IACH,mDAAmD;IACnD,gBAAgB,EAAE,MAAM,CAAC;IACzB,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,8GAA8G;IAC9G,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,aAAa,EAAE,QAAQ,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,UAAU,CAAa;IAE/B;;;OAGG;gBACS,UAAU,CAAC,EAAE,UAAU;IAInC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,wBAAwB;IAoBhC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,cAAc;IAiDtB;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IAoD5B;;;OAGG;IACH,OAAO,CAAC,gCAAgC;IA8CxC;;;;;;;;;OASG;IACG,kBAAkB,CACtB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,qBAAqB,CAAC;IAyCjC;;;;;;;;OAQG;IACH,4BAA4B,CAC1B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,QAAQ,EAAE,EACnB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,IAAI;IAeP;;;;;;;;;;OAUG;IACG,WAAW,CACf,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,UAAU,CAAC;CAyBvB"}
@@ -0,0 +1,347 @@
1
+ "use strict";
2
+ // ======================================
3
+ // ZipCopyNode.ts - Efficient ZIP Entry Copying
4
+ // Copyright (c) 2025 NeoWare, Inc. All rights reserved.
5
+ // ======================================
6
+ //
7
+ // Efficient ZIP entry copying using ZipEntry instances directly.
8
+ // Leverages existing offsets and sizes to copy raw bytes without
9
+ // unnecessary parsing and reconstruction.
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || (function () {
27
+ var ownKeys = function(o) {
28
+ ownKeys = Object.getOwnPropertyNames || function (o) {
29
+ var ar = [];
30
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
+ return ar;
32
+ };
33
+ return ownKeys(o);
34
+ };
35
+ return function (mod) {
36
+ if (mod && mod.__esModule) return mod;
37
+ var result = {};
38
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
+ __setModuleDefault(result, mod);
40
+ return result;
41
+ };
42
+ })();
43
+ var __importDefault = (this && this.__importDefault) || function (mod) {
44
+ return (mod && mod.__esModule) ? mod : { "default": mod };
45
+ };
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.ZipCopyNode = void 0;
48
+ const fs = __importStar(require("fs"));
49
+ const ZipEntry_1 = __importDefault(require("../core/ZipEntry"));
50
+ const ZipkitNode_1 = __importDefault(require("./ZipkitNode"));
51
+ const Headers_1 = require("../core/constants/Headers");
52
+ /**
53
+ * Efficient ZIP file copying class
54
+ *
55
+ * Uses ZipEntry instances directly to copy entries without decompression/recompression.
56
+ * Supports filtering and reordering entries while maintaining ZIP file validity.
57
+ *
58
+ * Entry data and the central directory / EOCD are separated so you can add files
59
+ * to the copy before finalizing: use copyZipEntriesOnly, append new entries at
60
+ * dataEndOffset, then call writeCentralDirectoryAndEOCD with all entries.
61
+ *
62
+ * @example Full copy (one shot)
63
+ * ```typescript
64
+ * const zipCopy = new ZipCopyNode(new ZipkitNode());
65
+ * const result = await zipCopy.copyZipFile('source.zip', 'dest.zip', {
66
+ * entryFilter: (entry) => !entry.filename.startsWith('.'),
67
+ * entrySorter: (a, b) => a.filename.localeCompare(b.filename)
68
+ * });
69
+ * ```
70
+ *
71
+ * @example Copy then add files before finalizing
72
+ * ```typescript
73
+ * const zipCopy = new ZipCopyNode(new ZipkitNode());
74
+ * const { destPath, dataEndOffset, copiedEntries } = await zipCopy.copyZipEntriesOnly('source.zip', 'dest.zip');
75
+ * // ... append new entries to destPath at dataEndOffset, collect new ZipEntry[] with localHdrOffset set ...
76
+ * const allEntries = [...copiedEntries, ...newEntries];
77
+ * zipCopy.writeCentralDirectoryAndEOCD(destPath, allEntries, { zipComment: '' });
78
+ * ```
79
+ */
80
+ class ZipCopyNode {
81
+ /**
82
+ * Creates a new ZipCopyNode instance
83
+ * @param zipkitNode - Optional ZipkitNode instance. If not provided, creates a new one.
84
+ */
85
+ constructor(zipkitNode) {
86
+ this.zipkitNode = zipkitNode || new ZipkitNode_1.default();
87
+ }
88
+ /**
89
+ * Calculate local header size by reading the actual local header
90
+ *
91
+ * Reads the first 30 bytes of the local header to get the exact
92
+ * filename and extra field lengths, ensuring accuracy even when
93
+ * local header differs from central directory.
94
+ *
95
+ * @param sourceFd - File descriptor for source ZIP file
96
+ * @param entry - ZipEntry with localHdrOffset
97
+ * @returns Size of the local header in bytes
98
+ */
99
+ calculateLocalHeaderSize(sourceFd, entry) {
100
+ // Read the fixed 30-byte local header
101
+ const headerBuffer = Buffer.alloc(Headers_1.LOCAL_HDR.SIZE);
102
+ fs.readSync(sourceFd, headerBuffer, 0, Headers_1.LOCAL_HDR.SIZE, entry.localHdrOffset);
103
+ // Verify signature
104
+ if (headerBuffer.readUInt32LE(0) !== Headers_1.LOCAL_HDR.SIGNATURE) {
105
+ throw new Error(`Invalid local file header signature for entry ${entry.filename} at offset ${entry.localHdrOffset}`);
106
+ }
107
+ // Read filename and extra field lengths from the actual header
108
+ const filenameLength = headerBuffer.readUInt16LE(Headers_1.LOCAL_HDR.FNAME_LEN);
109
+ const extraFieldLength = headerBuffer.readUInt16LE(Headers_1.LOCAL_HDR.EXTRA_LEN);
110
+ // Calculate total local header size
111
+ return Headers_1.LOCAL_HDR.SIZE + filenameLength + extraFieldLength;
112
+ }
113
+ /**
114
+ * Copy entry bytes directly from source to destination
115
+ *
116
+ * Copies the local header and compressed data as a single operation.
117
+ *
118
+ * Handles various entry types:
119
+ * - Normal entries: [local header][filename][extra][compressed data]
120
+ * - Encrypted entries: compressedSize includes 12-byte encryption header
121
+ * - Data descriptor entries: [local header][filename][extra][data][data descriptor (16 bytes)]
122
+ *
123
+ * For data descriptor entries, the local header has compressed size = 0,
124
+ * but the actual size is in the central directory (entry.compressedSize).
125
+ *
126
+ * @param sourceFd - File descriptor for source ZIP file
127
+ * @param destFd - File descriptor for destination ZIP file
128
+ * @param entry - ZipEntry with source offset information
129
+ * @returns Number of bytes written
130
+ */
131
+ copyEntryBytes(sourceFd, destFd, entry) {
132
+ // Calculate local header size by reading the actual header
133
+ const localHeaderSize = this.calculateLocalHeaderSize(sourceFd, entry);
134
+ // Determine total entry size
135
+ // For data descriptor entries, add 16 bytes for the data descriptor
136
+ const hasDataDescriptor = (entry.bitFlags & Headers_1.GP_FLAG.DATA_DESC) !== 0;
137
+ const totalEntrySize = localHeaderSize + entry.compressedSize + (hasDataDescriptor ? 16 : 0);
138
+ // Read the entire entry (local header + compressed data + data descriptor if present) from source
139
+ const entryBuffer = Buffer.alloc(totalEntrySize);
140
+ const bytesRead = fs.readSync(sourceFd, entryBuffer, 0, totalEntrySize, entry.localHdrOffset);
141
+ if (bytesRead !== totalEntrySize) {
142
+ throw new Error(`Failed to read complete entry for ${entry.filename}: ` +
143
+ `expected ${totalEntrySize} bytes, got ${bytesRead}`);
144
+ }
145
+ // Verify data descriptor signature if present
146
+ if (hasDataDescriptor) {
147
+ const dataDescOffset = localHeaderSize + entry.compressedSize;
148
+ const dataDescSig = entryBuffer.readUInt32LE(dataDescOffset);
149
+ if (dataDescSig !== 0x08074b50) { // DATA_DESCRIPTOR signature
150
+ throw new Error(`Invalid data descriptor signature for entry ${entry.filename} ` +
151
+ `(expected 0x08074b50, got 0x${dataDescSig.toString(16)})`);
152
+ }
153
+ }
154
+ // Write to destination
155
+ const bytesWritten = fs.writeSync(destFd, entryBuffer, 0, totalEntrySize);
156
+ if (bytesWritten !== totalEntrySize) {
157
+ throw new Error(`Failed to write complete entry for ${entry.filename}: ` +
158
+ `expected ${totalEntrySize} bytes, wrote ${bytesWritten}`);
159
+ }
160
+ return bytesWritten;
161
+ }
162
+ /**
163
+ * Clone a ZipEntry with a new local header offset
164
+ *
165
+ * Creates a new ZipEntry instance with all properties copied from the source,
166
+ * but with an updated localHdrOffset for the destination file.
167
+ *
168
+ * @param entry - Source ZipEntry to clone
169
+ * @param newLocalHdrOffset - New local header offset for the destination
170
+ * @returns New ZipEntry instance with updated offset
171
+ */
172
+ cloneEntryWithOffset(entry, newLocalHdrOffset) {
173
+ // Create a new ZipEntry with the same filename and comment
174
+ const cloned = new ZipEntry_1.default(entry.filename, entry.comment || null, entry.debug);
175
+ // Copy all properties
176
+ cloned.verMadeBy = entry.verMadeBy;
177
+ cloned.verExtract = entry.verExtract;
178
+ cloned.bitFlags = entry.bitFlags;
179
+ cloned.cmpMethod = entry.cmpMethod;
180
+ cloned.timeDateDOS = entry.timeDateDOS;
181
+ cloned.crc = entry.crc;
182
+ cloned.compressedSize = entry.compressedSize;
183
+ cloned.uncompressedSize = entry.uncompressedSize;
184
+ cloned.volNumber = entry.volNumber;
185
+ cloned.intFileAttr = entry.intFileAttr;
186
+ cloned.extFileAttr = entry.extFileAttr;
187
+ cloned.localHdrOffset = newLocalHdrOffset; // Update offset
188
+ // Copy extra field if present
189
+ if (entry.extraField) {
190
+ cloned.extraField = Buffer.from(entry.extraField);
191
+ }
192
+ // Copy metadata
193
+ cloned.isEncrypted = entry.isEncrypted;
194
+ cloned.isStrongEncrypt = entry.isStrongEncrypt;
195
+ cloned.isDirectory = entry.isDirectory;
196
+ cloned.isMetaData = entry.isMetaData;
197
+ cloned.isUpdated = entry.isUpdated;
198
+ // Copy platform-specific data
199
+ cloned.platform = entry.platform;
200
+ cloned.universalTime = entry.universalTime;
201
+ cloned.uid = entry.uid;
202
+ cloned.gid = entry.gid;
203
+ cloned.sha256 = entry.sha256;
204
+ // Copy symlink data
205
+ cloned.isSymlink = entry.isSymlink;
206
+ cloned.linkTarget = entry.linkTarget;
207
+ // Copy hardlink data
208
+ cloned.isHardLink = entry.isHardLink;
209
+ cloned.originalEntry = entry.originalEntry;
210
+ cloned.inode = entry.inode;
211
+ return cloned;
212
+ }
213
+ /**
214
+ * Write central directory and End of Central Directory record to an open file descriptor.
215
+ * Used internally by copyZipFile and by writeCentralDirectoryAndEOCD.
216
+ */
217
+ writeCentralDirectoryAndEOCDToFd(destFd, entries, zipComment) {
218
+ const centralDirStartOffset = fs.fstatSync(destFd).size;
219
+ for (const entry of entries) {
220
+ const centralDirBuffer = entry.centralDirEntry();
221
+ fs.writeSync(destFd, centralDirBuffer, 0, centralDirBuffer.length);
222
+ }
223
+ const centralDirEndOffset = fs.fstatSync(destFd).size;
224
+ const centralDirSize = centralDirEndOffset - centralDirStartOffset;
225
+ const commentBytes = Buffer.from(zipComment, 'utf8');
226
+ const commentLength = Math.min(commentBytes.length, 0xFFFF);
227
+ const eocdBuffer = Buffer.alloc(22 + commentLength);
228
+ let pos = 0;
229
+ eocdBuffer.writeUInt32LE(Headers_1.CENTRAL_END.SIGNATURE, pos);
230
+ pos += 4;
231
+ eocdBuffer.writeUInt16LE(0, pos);
232
+ pos += 2;
233
+ eocdBuffer.writeUInt16LE(0, pos);
234
+ pos += 2;
235
+ eocdBuffer.writeUInt16LE(entries.length, pos);
236
+ pos += 2;
237
+ eocdBuffer.writeUInt16LE(entries.length, pos);
238
+ pos += 2;
239
+ eocdBuffer.writeUInt32LE(centralDirSize, pos);
240
+ pos += 4;
241
+ eocdBuffer.writeUInt32LE(centralDirStartOffset, pos);
242
+ pos += 4;
243
+ eocdBuffer.writeUInt16LE(commentLength, pos);
244
+ pos += 2;
245
+ if (commentLength > 0) {
246
+ commentBytes.copy(eocdBuffer, pos, 0, commentLength);
247
+ }
248
+ fs.writeSync(destFd, eocdBuffer, 0, eocdBuffer.length);
249
+ return { centralDirOffset: centralDirStartOffset, centralDirSize };
250
+ }
251
+ /**
252
+ * Copy only ZIP entry data to the destination file (no central directory or EOCD).
253
+ * Use this when you want to add more entries before finalizing. Then call
254
+ * writeCentralDirectoryAndEOCD with all entries (copied + new) to produce a valid ZIP.
255
+ *
256
+ * @param sourceZipPath - Path to source ZIP file
257
+ * @param destZipPath - Path to destination file (will contain only entry data until finalized)
258
+ * @param options - Optional copy options (filtering, sorting)
259
+ * @returns Result with dataEndOffset and copiedEntries for use when adding files and finalizing
260
+ */
261
+ async copyZipEntriesOnly(sourceZipPath, destZipPath, options) {
262
+ const sourceEntries = await this.zipkitNode.loadZipFile(sourceZipPath);
263
+ let entriesToCopy = options?.entryFilter
264
+ ? sourceEntries.filter(options.entryFilter)
265
+ : sourceEntries;
266
+ if (options?.entrySorter) {
267
+ entriesToCopy = [...entriesToCopy].sort(options.entrySorter);
268
+ }
269
+ if (entriesToCopy.length === 0) {
270
+ throw new Error('No entries to copy after filtering');
271
+ }
272
+ const sourceFd = fs.openSync(sourceZipPath, 'r');
273
+ const destFd = fs.openSync(destZipPath, 'w');
274
+ try {
275
+ let destOffset = 0;
276
+ const copiedEntries = [];
277
+ for (const sourceEntry of entriesToCopy) {
278
+ const newLocalHdrOffset = destOffset;
279
+ const bytesWritten = this.copyEntryBytes(sourceFd, destFd, sourceEntry);
280
+ destOffset += bytesWritten;
281
+ const clonedEntry = this.cloneEntryWithOffset(sourceEntry, newLocalHdrOffset);
282
+ copiedEntries.push(clonedEntry);
283
+ }
284
+ return {
285
+ destPath: destZipPath,
286
+ dataEndOffset: destOffset,
287
+ copiedEntries,
288
+ };
289
+ }
290
+ finally {
291
+ fs.closeSync(sourceFd);
292
+ fs.closeSync(destFd);
293
+ }
294
+ }
295
+ /**
296
+ * Append central directory and End of Central Directory to a file that already
297
+ * contains ZIP entry data (e.g. from copyZipEntriesOnly plus any newly added entries).
298
+ * Call this after adding files to produce a valid ZIP.
299
+ *
300
+ * @param destZipPath - Path to the partial ZIP file (entry data only)
301
+ * @param entries - All entries in order (copied + any new), each with localHdrOffset set
302
+ * @param options - Optional finalize options (e.g. zipComment)
303
+ */
304
+ writeCentralDirectoryAndEOCD(destZipPath, entries, options) {
305
+ if (entries.length === 0) {
306
+ throw new Error('At least one entry is required to finalize');
307
+ }
308
+ const zipComment = options?.zipComment ?? '';
309
+ const destFd = fs.openSync(destZipPath, 'a');
310
+ try {
311
+ this.writeCentralDirectoryAndEOCDToFd(destFd, entries, zipComment);
312
+ }
313
+ finally {
314
+ fs.closeSync(destFd);
315
+ }
316
+ }
317
+ /**
318
+ * Copy ZIP file entries efficiently
319
+ *
320
+ * Main method that copies entries from source ZIP to destination ZIP.
321
+ * Uses ZipEntry instances directly to avoid unnecessary parsing.
322
+ *
323
+ * @param sourceZipPath - Path to source ZIP file
324
+ * @param destZipPath - Path to destination ZIP file
325
+ * @param options - Optional copy options (filtering, sorting, etc.)
326
+ * @returns Copy result with entry information
327
+ */
328
+ async copyZipFile(sourceZipPath, destZipPath, options) {
329
+ // Copy only entry data, then write central directory and EOCD (no added entries)
330
+ const { dataEndOffset, copiedEntries } = await this.copyZipEntriesOnly(sourceZipPath, destZipPath, options);
331
+ const zipComment = options?.preserveComments !== false && this.zipkitNode.getZipComment()
332
+ ? this.zipkitNode.getZipComment()
333
+ : '';
334
+ this.writeCentralDirectoryAndEOCD(destZipPath, copiedEntries, { zipComment });
335
+ return {
336
+ entries: copiedEntries.map(entry => ({
337
+ filename: entry.filename,
338
+ localHeaderOffset: entry.localHdrOffset,
339
+ compressedSize: entry.compressedSize,
340
+ })),
341
+ centralDirOffset: dataEndOffset,
342
+ totalEntries: copiedEntries.length,
343
+ };
344
+ }
345
+ }
346
+ exports.ZipCopyNode = ZipCopyNode;
347
+ //# sourceMappingURL=ZipCopyNode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ZipCopyNode.js","sourceRoot":"","sources":["../../src/node/ZipCopyNode.ts"],"names":[],"mappings":"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"}