@cj-tech-master/excelts 4.2.0 → 4.2.1-canary.20260112134913.a3cecdd

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 (317) hide show
  1. package/THIRD_PARTY_NOTICES.md +0 -31
  2. package/dist/browser/index.browser.d.ts +1 -0
  3. package/dist/browser/index.browser.js +12 -0
  4. package/dist/{types/modules/archive → browser/modules/archive/compression}/compress.base.d.ts +1 -0
  5. package/dist/browser/modules/archive/{compress.base.js → compression/compress.base.js} +2 -1
  6. package/dist/{types/modules/archive → browser/modules/archive/compression}/compress.browser.d.ts +10 -8
  7. package/dist/{esm/modules/archive → browser/modules/archive/compression}/compress.browser.js +18 -19
  8. package/dist/browser/modules/archive/{compress.d.ts → compression/compress.d.ts} +2 -2
  9. package/dist/browser/modules/archive/{compress.js → compression/compress.js} +1 -1
  10. package/dist/browser/modules/archive/{crc32.browser.d.ts → compression/crc32.browser.d.ts} +1 -1
  11. package/dist/browser/modules/archive/{crc32.d.ts → compression/crc32.d.ts} +1 -1
  12. package/dist/browser/modules/archive/{crc32.js → compression/crc32.js} +1 -1
  13. package/dist/browser/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
  14. package/dist/browser/modules/archive/{streaming-compress.browser.d.ts → compression/streaming-compress.browser.d.ts} +2 -2
  15. package/dist/browser/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
  16. package/dist/browser/modules/archive/{streaming-compress.d.ts → compression/streaming-compress.d.ts} +2 -2
  17. package/dist/browser/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
  18. package/dist/browser/modules/archive/defaults.d.ts +1 -0
  19. package/dist/browser/modules/archive/defaults.js +6 -3
  20. package/dist/browser/modules/archive/index.base.d.ts +4 -4
  21. package/dist/browser/modules/archive/index.base.js +3 -6
  22. package/dist/browser/modules/archive/index.browser.d.ts +3 -4
  23. package/dist/browser/modules/archive/index.browser.js +3 -7
  24. package/dist/browser/modules/archive/index.d.ts +3 -4
  25. package/dist/browser/modules/archive/index.js +3 -5
  26. package/dist/browser/modules/archive/internal/byte-queue.d.ts +33 -0
  27. package/dist/browser/modules/archive/internal/byte-queue.js +407 -0
  28. package/dist/browser/modules/archive/io/archive-sink.d.ts +8 -0
  29. package/dist/browser/modules/archive/io/archive-sink.js +45 -0
  30. package/dist/browser/modules/archive/io/archive-source.d.ts +6 -0
  31. package/dist/browser/modules/archive/io/archive-source.js +100 -0
  32. package/dist/browser/modules/archive/{extract.d.ts → unzip/extract.d.ts} +2 -2
  33. package/dist/browser/modules/archive/unzip/index.d.ts +40 -0
  34. package/dist/browser/modules/archive/unzip/index.js +164 -0
  35. package/dist/browser/modules/archive/{parse.base.d.ts → unzip/stream.base.d.ts} +58 -3
  36. package/dist/browser/modules/archive/unzip/stream.base.js +1022 -0
  37. package/dist/browser/modules/archive/{parse.browser.d.ts → unzip/stream.browser.d.ts} +1 -1
  38. package/dist/browser/modules/archive/{parse.browser.js → unzip/stream.browser.js} +376 -110
  39. package/dist/browser/modules/archive/{parse.d.ts → unzip/stream.d.ts} +2 -2
  40. package/dist/{esm/modules/archive/parse.js → browser/modules/archive/unzip/stream.js} +7 -6
  41. package/dist/{types/modules/archive → browser/modules/archive/unzip}/zip-parser.d.ts +1 -1
  42. package/dist/{esm/modules/archive → browser/modules/archive/unzip}/zip-parser.js +38 -24
  43. package/dist/browser/modules/archive/utils/async-queue.d.ts +7 -0
  44. package/dist/browser/modules/archive/utils/async-queue.js +103 -0
  45. package/dist/browser/modules/archive/utils/bytes.js +16 -16
  46. package/dist/browser/modules/archive/utils/compressibility.d.ts +10 -0
  47. package/dist/browser/modules/archive/utils/compressibility.js +57 -0
  48. package/dist/browser/modules/archive/utils/parse-buffer.js +21 -23
  49. package/dist/browser/modules/archive/utils/pattern-scanner.d.ts +21 -0
  50. package/dist/browser/modules/archive/utils/pattern-scanner.js +27 -0
  51. package/dist/browser/modules/archive/utils/timestamps.js +62 -1
  52. package/dist/browser/modules/archive/utils/zip-extra-fields.d.ts +1 -1
  53. package/dist/browser/modules/archive/utils/zip-extra-fields.js +26 -14
  54. package/dist/browser/modules/archive/zip/index.d.ts +42 -0
  55. package/dist/browser/modules/archive/zip/index.js +157 -0
  56. package/dist/browser/modules/archive/{streaming-zip.d.ts → zip/stream.d.ts} +28 -5
  57. package/dist/browser/modules/archive/{streaming-zip.js → zip/stream.js} +192 -48
  58. package/dist/browser/modules/archive/zip/zip-bytes.d.ts +73 -0
  59. package/dist/browser/modules/archive/zip/zip-bytes.js +239 -0
  60. package/dist/{esm/modules/archive → browser/modules/archive/zip}/zip-entry-metadata.js +3 -3
  61. package/dist/browser/modules/archive/{zip-records.d.ts → zip-spec/zip-records.d.ts} +20 -0
  62. package/dist/browser/modules/archive/zip-spec/zip-records.js +126 -0
  63. package/dist/browser/modules/excel/form-control.d.ts +2 -0
  64. package/dist/browser/modules/excel/form-control.js +54 -16
  65. package/dist/browser/modules/excel/stream/workbook-reader.browser.js +1 -1
  66. package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
  67. package/dist/browser/modules/excel/stream/workbook-writer.browser.js +1 -1
  68. package/dist/browser/modules/excel/utils/ooxml-validator.d.ts +48 -0
  69. package/dist/browser/modules/excel/utils/ooxml-validator.js +469 -0
  70. package/dist/browser/modules/excel/worksheet.js +5 -2
  71. package/dist/browser/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.d.ts +1 -0
  72. package/dist/browser/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.js +13 -1
  73. package/dist/browser/modules/excel/xlsx/xform/drawing/sp-xform.d.ts +18 -0
  74. package/dist/browser/modules/excel/xlsx/xform/drawing/sp-xform.js +112 -0
  75. package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +6 -1
  76. package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +30 -2
  77. package/dist/browser/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +11 -0
  78. package/dist/browser/modules/excel/xlsx/xform/sheet/page-setup-xform.d.ts +1 -0
  79. package/dist/browser/modules/excel/xlsx/xform/sheet/page-setup-xform.js +16 -2
  80. package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +117 -5
  81. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +3 -6
  82. package/dist/browser/modules/excel/xlsx/xlsx.js +1 -1
  83. package/dist/browser/modules/stream/base-transform.d.ts +3 -0
  84. package/dist/browser/modules/stream/base-transform.js +34 -20
  85. package/dist/browser/modules/stream/buffered-stream.d.ts +2 -12
  86. package/dist/browser/modules/stream/chunked-builder.js +4 -4
  87. package/dist/browser/modules/stream/index.browser.d.ts +13 -19
  88. package/dist/browser/modules/stream/index.browser.js +10 -22
  89. package/dist/browser/modules/stream/index.d.ts +18 -41
  90. package/dist/browser/modules/stream/index.js +15 -44
  91. package/dist/browser/modules/stream/internal/event-utils.d.ts +17 -0
  92. package/dist/browser/modules/stream/internal/event-utils.js +40 -0
  93. package/dist/browser/modules/stream/internal/type-guards.d.ts +9 -0
  94. package/dist/browser/modules/stream/internal/type-guards.js +24 -0
  95. package/dist/browser/modules/stream/pull-stream.d.ts +5 -6
  96. package/dist/browser/modules/stream/pull-stream.js +107 -43
  97. package/dist/browser/modules/stream/shared.d.ts +1 -1
  98. package/dist/browser/modules/stream/shared.js +7 -4
  99. package/dist/browser/modules/stream/streams.browser.d.ts +32 -42
  100. package/dist/browser/modules/stream/streams.browser.js +941 -823
  101. package/dist/browser/modules/stream/streams.d.ts +4 -20
  102. package/dist/browser/modules/stream/streams.js +146 -95
  103. package/dist/browser/modules/stream/utils.js +5 -38
  104. package/dist/cjs/modules/archive/{compress.base.js → compression/compress.base.js} +2 -1
  105. package/dist/cjs/modules/archive/{compress.browser.js → compression/compress.browser.js} +18 -19
  106. package/dist/cjs/modules/archive/{compress.js → compression/compress.js} +1 -1
  107. package/dist/cjs/modules/archive/{crc32.js → compression/crc32.js} +1 -1
  108. package/dist/cjs/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
  109. package/dist/cjs/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
  110. package/dist/cjs/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
  111. package/dist/cjs/modules/archive/defaults.js +7 -4
  112. package/dist/cjs/modules/archive/index.base.js +9 -19
  113. package/dist/cjs/modules/archive/index.browser.js +4 -10
  114. package/dist/cjs/modules/archive/index.js +4 -8
  115. package/dist/cjs/modules/archive/internal/byte-queue.js +411 -0
  116. package/dist/cjs/modules/archive/io/archive-sink.js +49 -0
  117. package/dist/cjs/modules/archive/io/archive-source.js +105 -0
  118. package/dist/cjs/modules/archive/unzip/index.js +170 -0
  119. package/dist/cjs/modules/archive/unzip/stream.base.js +1044 -0
  120. package/dist/cjs/modules/archive/{parse.browser.js → unzip/stream.browser.js} +377 -111
  121. package/dist/cjs/modules/archive/{parse.js → unzip/stream.js} +9 -8
  122. package/dist/cjs/modules/archive/{zip-parser.js → unzip/zip-parser.js} +47 -33
  123. package/dist/cjs/modules/archive/utils/async-queue.js +106 -0
  124. package/dist/cjs/modules/archive/utils/bytes.js +16 -16
  125. package/dist/cjs/modules/archive/utils/compressibility.js +60 -0
  126. package/dist/cjs/modules/archive/utils/parse-buffer.js +21 -23
  127. package/dist/cjs/modules/archive/utils/pattern-scanner.js +31 -0
  128. package/dist/cjs/modules/archive/utils/timestamps.js +64 -3
  129. package/dist/cjs/modules/archive/utils/zip-extra-fields.js +26 -14
  130. package/dist/cjs/modules/archive/zip/index.js +162 -0
  131. package/dist/cjs/modules/archive/{streaming-zip.js → zip/stream.js} +194 -50
  132. package/dist/cjs/modules/archive/zip/zip-bytes.js +242 -0
  133. package/dist/cjs/modules/archive/{zip-entry-metadata.js → zip/zip-entry-metadata.js} +5 -5
  134. package/dist/cjs/modules/archive/zip-spec/zip-records.js +136 -0
  135. package/dist/cjs/modules/excel/form-control.js +54 -16
  136. package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +2 -2
  137. package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +4 -4
  138. package/dist/cjs/modules/excel/utils/ooxml-validator.js +475 -0
  139. package/dist/cjs/modules/excel/worksheet.js +5 -2
  140. package/dist/cjs/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.js +13 -1
  141. package/dist/cjs/modules/excel/xlsx/xform/drawing/sp-xform.js +115 -0
  142. package/dist/cjs/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +30 -2
  143. package/dist/cjs/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +11 -0
  144. package/dist/cjs/modules/excel/xlsx/xform/sheet/page-setup-xform.js +16 -2
  145. package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +117 -5
  146. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +6 -9
  147. package/dist/cjs/modules/excel/xlsx/xlsx.js +2 -2
  148. package/dist/cjs/modules/stream/base-transform.js +34 -20
  149. package/dist/cjs/modules/stream/chunked-builder.js +4 -4
  150. package/dist/cjs/modules/stream/index.browser.js +10 -17
  151. package/dist/cjs/modules/stream/index.js +15 -39
  152. package/dist/cjs/modules/stream/internal/event-utils.js +43 -0
  153. package/dist/cjs/modules/stream/internal/type-guards.js +30 -0
  154. package/dist/cjs/modules/stream/pull-stream.js +107 -43
  155. package/dist/cjs/modules/stream/shared.js +7 -4
  156. package/dist/cjs/modules/stream/streams.browser.js +947 -834
  157. package/dist/cjs/modules/stream/streams.js +156 -107
  158. package/dist/cjs/modules/stream/utils.js +3 -36
  159. package/dist/esm/index.browser.js +12 -0
  160. package/dist/esm/modules/archive/{compress.base.js → compression/compress.base.js} +2 -1
  161. package/dist/{browser/modules/archive → esm/modules/archive/compression}/compress.browser.js +18 -19
  162. package/dist/esm/modules/archive/{compress.js → compression/compress.js} +1 -1
  163. package/dist/esm/modules/archive/{crc32.js → compression/crc32.js} +1 -1
  164. package/dist/esm/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
  165. package/dist/esm/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
  166. package/dist/esm/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
  167. package/dist/esm/modules/archive/defaults.js +6 -3
  168. package/dist/esm/modules/archive/index.base.js +3 -6
  169. package/dist/esm/modules/archive/index.browser.js +3 -7
  170. package/dist/esm/modules/archive/index.js +3 -5
  171. package/dist/esm/modules/archive/internal/byte-queue.js +407 -0
  172. package/dist/esm/modules/archive/io/archive-sink.js +45 -0
  173. package/dist/esm/modules/archive/io/archive-source.js +100 -0
  174. package/dist/esm/modules/archive/unzip/index.js +164 -0
  175. package/dist/esm/modules/archive/unzip/stream.base.js +1022 -0
  176. package/dist/esm/modules/archive/{parse.browser.js → unzip/stream.browser.js} +376 -110
  177. package/dist/{browser/modules/archive/parse.js → esm/modules/archive/unzip/stream.js} +7 -6
  178. package/dist/{browser/modules/archive → esm/modules/archive/unzip}/zip-parser.js +38 -24
  179. package/dist/esm/modules/archive/utils/async-queue.js +103 -0
  180. package/dist/esm/modules/archive/utils/bytes.js +16 -16
  181. package/dist/esm/modules/archive/utils/compressibility.js +57 -0
  182. package/dist/esm/modules/archive/utils/parse-buffer.js +21 -23
  183. package/dist/esm/modules/archive/utils/pattern-scanner.js +27 -0
  184. package/dist/esm/modules/archive/utils/timestamps.js +62 -1
  185. package/dist/esm/modules/archive/utils/zip-extra-fields.js +26 -14
  186. package/dist/esm/modules/archive/zip/index.js +157 -0
  187. package/dist/esm/modules/archive/{streaming-zip.js → zip/stream.js} +192 -48
  188. package/dist/esm/modules/archive/zip/zip-bytes.js +239 -0
  189. package/dist/{browser/modules/archive → esm/modules/archive/zip}/zip-entry-metadata.js +3 -3
  190. package/dist/esm/modules/archive/zip-spec/zip-records.js +126 -0
  191. package/dist/esm/modules/excel/form-control.js +54 -16
  192. package/dist/esm/modules/excel/stream/workbook-reader.browser.js +1 -1
  193. package/dist/esm/modules/excel/stream/workbook-writer.browser.js +1 -1
  194. package/dist/esm/modules/excel/utils/ooxml-validator.js +469 -0
  195. package/dist/esm/modules/excel/worksheet.js +5 -2
  196. package/dist/esm/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.js +13 -1
  197. package/dist/esm/modules/excel/xlsx/xform/drawing/sp-xform.js +112 -0
  198. package/dist/esm/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +30 -2
  199. package/dist/esm/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +11 -0
  200. package/dist/esm/modules/excel/xlsx/xform/sheet/page-setup-xform.js +16 -2
  201. package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +117 -5
  202. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +3 -6
  203. package/dist/esm/modules/excel/xlsx/xlsx.js +1 -1
  204. package/dist/esm/modules/stream/base-transform.js +34 -20
  205. package/dist/esm/modules/stream/chunked-builder.js +4 -4
  206. package/dist/esm/modules/stream/index.browser.js +10 -22
  207. package/dist/esm/modules/stream/index.js +15 -44
  208. package/dist/esm/modules/stream/internal/event-utils.js +40 -0
  209. package/dist/esm/modules/stream/internal/type-guards.js +24 -0
  210. package/dist/esm/modules/stream/pull-stream.js +107 -43
  211. package/dist/esm/modules/stream/shared.js +7 -4
  212. package/dist/esm/modules/stream/streams.browser.js +941 -823
  213. package/dist/esm/modules/stream/streams.js +146 -95
  214. package/dist/esm/modules/stream/utils.js +5 -38
  215. package/dist/iife/THIRD_PARTY_NOTICES.md +81 -0
  216. package/dist/iife/excelts.iife.js +4979 -2800
  217. package/dist/iife/excelts.iife.js.map +1 -1
  218. package/dist/iife/excelts.iife.min.js +103 -31
  219. package/dist/types/index.browser.d.ts +1 -0
  220. package/dist/{browser/modules/archive → types/modules/archive/compression}/compress.base.d.ts +1 -0
  221. package/dist/{browser/modules/archive → types/modules/archive/compression}/compress.browser.d.ts +10 -8
  222. package/dist/types/modules/archive/{streaming-compress.browser.d.ts → compression/streaming-compress.browser.d.ts} +1 -1
  223. package/dist/types/modules/archive/defaults.d.ts +1 -0
  224. package/dist/types/modules/archive/index.base.d.ts +4 -4
  225. package/dist/types/modules/archive/index.browser.d.ts +3 -4
  226. package/dist/types/modules/archive/index.d.ts +3 -4
  227. package/dist/types/modules/archive/internal/byte-queue.d.ts +33 -0
  228. package/dist/types/modules/archive/io/archive-sink.d.ts +8 -0
  229. package/dist/types/modules/archive/io/archive-source.d.ts +6 -0
  230. package/dist/types/modules/archive/unzip/index.d.ts +40 -0
  231. package/dist/types/modules/archive/{parse.base.d.ts → unzip/stream.base.d.ts} +60 -5
  232. package/dist/types/modules/archive/{parse.browser.d.ts → unzip/stream.browser.d.ts} +2 -2
  233. package/dist/types/modules/archive/{parse.d.ts → unzip/stream.d.ts} +3 -3
  234. package/dist/{browser/modules/archive → types/modules/archive/unzip}/zip-parser.d.ts +1 -1
  235. package/dist/types/modules/archive/utils/async-queue.d.ts +7 -0
  236. package/dist/types/modules/archive/utils/compressibility.d.ts +10 -0
  237. package/dist/types/modules/archive/utils/pattern-scanner.d.ts +21 -0
  238. package/dist/types/modules/archive/utils/zip-extra-fields.d.ts +1 -1
  239. package/dist/types/modules/archive/zip/index.d.ts +42 -0
  240. package/dist/types/modules/archive/{streaming-zip.d.ts → zip/stream.d.ts} +29 -6
  241. package/dist/types/modules/archive/zip/zip-bytes.d.ts +73 -0
  242. package/dist/types/modules/archive/{zip-entry-metadata.d.ts → zip/zip-entry-metadata.d.ts} +1 -1
  243. package/dist/types/modules/archive/{zip-records.d.ts → zip-spec/zip-records.d.ts} +20 -0
  244. package/dist/types/modules/excel/form-control.d.ts +2 -0
  245. package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
  246. package/dist/types/modules/excel/utils/ooxml-validator.d.ts +48 -0
  247. package/dist/types/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.d.ts +1 -0
  248. package/dist/types/modules/excel/xlsx/xform/drawing/sp-xform.d.ts +18 -0
  249. package/dist/types/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +6 -1
  250. package/dist/types/modules/excel/xlsx/xform/sheet/page-setup-xform.d.ts +1 -0
  251. package/dist/types/modules/stream/base-transform.d.ts +3 -0
  252. package/dist/types/modules/stream/buffered-stream.d.ts +2 -12
  253. package/dist/types/modules/stream/index.browser.d.ts +13 -19
  254. package/dist/types/modules/stream/index.d.ts +18 -41
  255. package/dist/types/modules/stream/internal/event-utils.d.ts +17 -0
  256. package/dist/types/modules/stream/internal/type-guards.d.ts +9 -0
  257. package/dist/types/modules/stream/pull-stream.d.ts +5 -6
  258. package/dist/types/modules/stream/shared.d.ts +1 -1
  259. package/dist/types/modules/stream/streams.browser.d.ts +32 -42
  260. package/dist/types/modules/stream/streams.d.ts +4 -20
  261. package/package.json +19 -15
  262. package/dist/browser/modules/archive/byte-queue.d.ts +0 -18
  263. package/dist/browser/modules/archive/byte-queue.js +0 -125
  264. package/dist/browser/modules/archive/parse.base.js +0 -610
  265. package/dist/browser/modules/archive/utils/zip-extra.d.ts +0 -18
  266. package/dist/browser/modules/archive/utils/zip-extra.js +0 -68
  267. package/dist/browser/modules/archive/zip-builder.d.ts +0 -117
  268. package/dist/browser/modules/archive/zip-builder.js +0 -292
  269. package/dist/browser/modules/archive/zip-constants.d.ts +0 -18
  270. package/dist/browser/modules/archive/zip-constants.js +0 -23
  271. package/dist/browser/modules/archive/zip-records.js +0 -84
  272. package/dist/cjs/modules/archive/byte-queue.js +0 -129
  273. package/dist/cjs/modules/archive/parse.base.js +0 -632
  274. package/dist/cjs/modules/archive/utils/zip-extra.js +0 -74
  275. package/dist/cjs/modules/archive/zip-builder.js +0 -297
  276. package/dist/cjs/modules/archive/zip-constants.js +0 -26
  277. package/dist/cjs/modules/archive/zip-records.js +0 -90
  278. package/dist/esm/modules/archive/byte-queue.js +0 -125
  279. package/dist/esm/modules/archive/parse.base.js +0 -610
  280. package/dist/esm/modules/archive/utils/zip-extra.js +0 -68
  281. package/dist/esm/modules/archive/zip-builder.js +0 -292
  282. package/dist/esm/modules/archive/zip-constants.js +0 -23
  283. package/dist/esm/modules/archive/zip-records.js +0 -84
  284. package/dist/types/modules/archive/byte-queue.d.ts +0 -18
  285. package/dist/types/modules/archive/utils/zip-extra.d.ts +0 -18
  286. package/dist/types/modules/archive/zip-builder.d.ts +0 -117
  287. package/dist/types/modules/archive/zip-constants.d.ts +0 -18
  288. /package/dist/browser/modules/archive/{crc32.base.d.ts → compression/crc32.base.d.ts} +0 -0
  289. /package/dist/browser/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
  290. /package/dist/browser/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
  291. /package/dist/browser/modules/archive/{deflate-fallback.d.ts → compression/deflate-fallback.d.ts} +0 -0
  292. /package/dist/browser/modules/archive/{streaming-compress.base.d.ts → compression/streaming-compress.base.d.ts} +0 -0
  293. /package/dist/browser/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
  294. /package/dist/browser/modules/archive/{extract.js → unzip/extract.js} +0 -0
  295. /package/dist/browser/modules/archive/{zip-entry-metadata.d.ts → zip/zip-entry-metadata.d.ts} +0 -0
  296. /package/dist/browser/modules/archive/{zip-entry-info.d.ts → zip-spec/zip-entry-info.d.ts} +0 -0
  297. /package/dist/browser/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
  298. /package/dist/cjs/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
  299. /package/dist/cjs/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
  300. /package/dist/cjs/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
  301. /package/dist/cjs/modules/archive/{extract.js → unzip/extract.js} +0 -0
  302. /package/dist/cjs/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
  303. /package/dist/esm/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
  304. /package/dist/esm/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
  305. /package/dist/esm/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
  306. /package/dist/esm/modules/archive/{extract.js → unzip/extract.js} +0 -0
  307. /package/dist/esm/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
  308. /package/dist/{LICENSE → iife/LICENSE} +0 -0
  309. /package/dist/types/modules/archive/{compress.d.ts → compression/compress.d.ts} +0 -0
  310. /package/dist/types/modules/archive/{crc32.base.d.ts → compression/crc32.base.d.ts} +0 -0
  311. /package/dist/types/modules/archive/{crc32.browser.d.ts → compression/crc32.browser.d.ts} +0 -0
  312. /package/dist/types/modules/archive/{crc32.d.ts → compression/crc32.d.ts} +0 -0
  313. /package/dist/types/modules/archive/{deflate-fallback.d.ts → compression/deflate-fallback.d.ts} +0 -0
  314. /package/dist/types/modules/archive/{streaming-compress.base.d.ts → compression/streaming-compress.base.d.ts} +0 -0
  315. /package/dist/types/modules/archive/{streaming-compress.d.ts → compression/streaming-compress.d.ts} +0 -0
  316. /package/dist/types/modules/archive/{extract.d.ts → unzip/extract.d.ts} +0 -0
  317. /package/dist/types/modules/archive/{zip-entry-info.d.ts → zip-spec/zip-entry-info.d.ts} +0 -0
@@ -0,0 +1,42 @@
1
+ import type { ZipTimestampMode } from "@archive/utils/timestamps";
2
+ import { type ArchiveSink } from "@archive/io/archive-sink";
3
+ import { type ArchiveSource } from "@archive/io/archive-source";
4
+ export interface ZipOptions {
5
+ level?: number;
6
+ timestamps?: ZipTimestampMode;
7
+ comment?: string;
8
+ /**
9
+ * Default modification time for entries that don't specify `modTime`.
10
+ *
11
+ * If you need stable output across runs, either pass this explicitly or use `reproducible: true`.
12
+ */
13
+ modTime?: Date;
14
+ /**
15
+ * If true, bias defaults toward reproducible output:
16
+ * - default `modTime` becomes 1980-01-01 00:00:00 (local time)
17
+ * - default `timestamps` becomes "dos" (no UTC extra field)
18
+ */
19
+ reproducible?: boolean;
20
+ /**
21
+ * If true (default), automatically STORE incompressible data.
22
+ * If false, always follow `level` (DEFLATE when level > 0).
23
+ */
24
+ smartStore?: boolean;
25
+ }
26
+ export interface ZipEntryOptions {
27
+ level?: number;
28
+ modTime?: Date;
29
+ comment?: string;
30
+ }
31
+ export declare class ZipArchive {
32
+ private readonly _options;
33
+ private readonly _entries;
34
+ private _sealed;
35
+ constructor(options?: ZipOptions);
36
+ add(name: string, source: ArchiveSource, options?: ZipEntryOptions): this;
37
+ stream(): AsyncIterable<Uint8Array>;
38
+ bytes(): Promise<Uint8Array>;
39
+ bytesSync(): Uint8Array;
40
+ pipeTo(sink: ArchiveSink): Promise<void>;
41
+ }
42
+ export declare function zip(options?: ZipOptions): ZipArchive;
@@ -0,0 +1,157 @@
1
+ import { DEFAULT_ZIP_LEVEL, DEFAULT_ZIP_TIMESTAMPS } from "../defaults.js";
2
+ import { ZipDeflateFile, StreamingZip } from "./stream.js";
3
+ import { createZip, createZipSync } from "./zip-bytes.js";
4
+ import { collect, pipeIterableToSink } from "../io/archive-sink.js";
5
+ import { toAsyncIterable, toUint8Array, toUint8ArraySync } from "../io/archive-source.js";
6
+ import { createAsyncQueue } from "../utils/async-queue.js";
7
+ const REPRODUCIBLE_ZIP_MOD_TIME = new Date(1980, 0, 1, 0, 0, 0);
8
+ export class ZipArchive {
9
+ constructor(options = {}) {
10
+ this._entries = [];
11
+ this._sealed = false;
12
+ const reproducible = options.reproducible ?? false;
13
+ this._options = {
14
+ level: options.level ?? DEFAULT_ZIP_LEVEL,
15
+ timestamps: options.timestamps ?? (reproducible ? "dos" : DEFAULT_ZIP_TIMESTAMPS),
16
+ comment: options.comment,
17
+ modTime: options.modTime ?? (reproducible ? REPRODUCIBLE_ZIP_MOD_TIME : new Date()),
18
+ smartStore: options.smartStore ?? true
19
+ };
20
+ }
21
+ add(name, source, options) {
22
+ if (this._sealed) {
23
+ throw new Error("Cannot add entries after output has started");
24
+ }
25
+ if (!name) {
26
+ throw new Error("Entry name is required");
27
+ }
28
+ this._entries.push({ name, source, options });
29
+ return this;
30
+ }
31
+ stream() {
32
+ this._sealed = true;
33
+ const queue = createAsyncQueue();
34
+ const zip = new StreamingZip((err, data, final) => {
35
+ if (err) {
36
+ queue.fail(err);
37
+ return;
38
+ }
39
+ if (data.length) {
40
+ queue.push(data);
41
+ }
42
+ if (final) {
43
+ queue.close();
44
+ }
45
+ }, { comment: this._options.comment });
46
+ (async () => {
47
+ try {
48
+ for (const entry of this._entries) {
49
+ const level = entry.options?.level ?? this._options.level;
50
+ const file = new ZipDeflateFile(entry.name, {
51
+ level,
52
+ modTime: entry.options?.modTime ?? this._options.modTime,
53
+ timestamps: this._options.timestamps,
54
+ comment: entry.options?.comment,
55
+ smartStore: this._options.smartStore
56
+ });
57
+ zip.add(file);
58
+ // Feed data
59
+ if (entry.source instanceof Uint8Array ||
60
+ entry.source instanceof ArrayBuffer ||
61
+ typeof entry.source === "string" ||
62
+ (typeof Blob !== "undefined" && entry.source instanceof Blob)) {
63
+ const bytes = await toUint8Array(entry.source);
64
+ await file.push(bytes, true);
65
+ }
66
+ else {
67
+ for await (const chunk of toAsyncIterable(entry.source)) {
68
+ await file.push(chunk, false);
69
+ }
70
+ await file.push(new Uint8Array(0), true);
71
+ }
72
+ await file.complete();
73
+ }
74
+ zip.end();
75
+ }
76
+ catch (e) {
77
+ queue.fail(e instanceof Error ? e : new Error(String(e)));
78
+ }
79
+ })();
80
+ return queue.iterable;
81
+ }
82
+ async bytes() {
83
+ this._sealed = true;
84
+ const allSourcesInMemory = this._entries.every(e => e.source instanceof Uint8Array ||
85
+ e.source instanceof ArrayBuffer ||
86
+ typeof e.source === "string" ||
87
+ (typeof Blob !== "undefined" && e.source instanceof Blob));
88
+ const hasBlobSource = this._entries.some(e => typeof Blob !== "undefined" && e.source instanceof Blob);
89
+ // Fast-path: when all sources are already in memory and there are no
90
+ // per-entry compression overrides, use the single-buffer ZIP builder.
91
+ // This avoids the overhead of chunking + collecting from the streaming writer.
92
+ if (allSourcesInMemory) {
93
+ // Prefer the sync builder when possible (Node.js hot path): it avoids
94
+ // async/Promise overhead and uses zlib sync fast paths.
95
+ if (!hasBlobSource) {
96
+ const entries = this._entries.map(e => ({
97
+ name: e.name,
98
+ data: toUint8ArraySync(e.source),
99
+ level: e.options?.level,
100
+ modTime: e.options?.modTime,
101
+ comment: e.options?.comment
102
+ }));
103
+ return createZipSync(entries, {
104
+ level: this._options.level,
105
+ timestamps: this._options.timestamps,
106
+ modTime: this._options.modTime,
107
+ comment: this._options.comment,
108
+ smartStore: this._options.smartStore
109
+ });
110
+ }
111
+ const entries = await Promise.all(this._entries.map(async (e) => ({
112
+ name: e.name,
113
+ data: await toUint8Array(e.source),
114
+ level: e.options?.level,
115
+ modTime: e.options?.modTime,
116
+ comment: e.options?.comment
117
+ })));
118
+ return createZip(entries, {
119
+ level: this._options.level,
120
+ timestamps: this._options.timestamps,
121
+ modTime: this._options.modTime,
122
+ comment: this._options.comment,
123
+ smartStore: this._options.smartStore
124
+ });
125
+ }
126
+ return collect(this.stream());
127
+ }
128
+ bytesSync() {
129
+ this._sealed = true;
130
+ const entries = this._entries.map(e => {
131
+ if (!(e.source instanceof Uint8Array) &&
132
+ !(e.source instanceof ArrayBuffer) &&
133
+ typeof e.source !== "string") {
134
+ throw new Error("bytesSync() only supports Uint8Array/ArrayBuffer/string sources");
135
+ }
136
+ return {
137
+ name: e.name,
138
+ data: toUint8ArraySync(e.source),
139
+ modTime: e.options?.modTime,
140
+ comment: e.options?.comment
141
+ };
142
+ });
143
+ return createZipSync(entries, {
144
+ level: this._options.level,
145
+ timestamps: this._options.timestamps,
146
+ modTime: this._options.modTime,
147
+ comment: this._options.comment,
148
+ smartStore: this._options.smartStore
149
+ });
150
+ }
151
+ async pipeTo(sink) {
152
+ await pipeIterableToSink(this.stream(), sink);
153
+ }
154
+ }
155
+ export function zip(options) {
156
+ return new ZipArchive(options);
157
+ }
@@ -2,17 +2,18 @@
2
2
  * True Streaming ZIP creator - shared implementation.
3
3
  *
4
4
  * This module is intentionally platform-agnostic.
5
- * - In Node builds it uses `./crc32` + `./streaming-compress` (zlib-backed).
5
+ * - In Node builds it uses `./compression/crc32` + `./compression/streaming-compress` (zlib-backed).
6
6
  * - In browser builds the bundler aliases those imports to their browser variants.
7
7
  */
8
8
  import type { ZipTimestampMode } from "@archive/utils/timestamps";
9
- import type { ZipEntryInfo as UnzipZipEntryInfo } from "@archive/zip-entry-info";
9
+ import type { ZipEntryInfo as UnzipZipEntryInfo } from "@archive/zip-spec/zip-entry-info";
10
10
  /**
11
11
  * Internal entry info for central directory
12
12
  */
13
13
  interface ZipEntryInfo {
14
14
  name: Uint8Array;
15
15
  extraField: Uint8Array;
16
+ comment: Uint8Array;
16
17
  flags: number;
17
18
  crc: number;
18
19
  compressedSize: number;
@@ -34,43 +35,62 @@ export declare class ZipDeflateFile {
34
35
  private _finalized;
35
36
  private _headerEmitted;
36
37
  private _ondata;
38
+ private _onerror;
37
39
  private _centralDirEntryInfo;
38
40
  private _pendingEnd;
39
41
  private _emittedDataDescriptor;
40
42
  private _localHeader;
43
+ private _deflateWanted;
44
+ private _pendingChunks;
45
+ private _sampleBuffer;
46
+ private _sampleLen;
47
+ private _smartStore;
41
48
  private _completeResolve;
42
49
  private _completeReject;
43
50
  private _completePromise;
44
51
  private _completeError;
45
52
  private _dataQueue;
46
53
  private _finalQueued;
54
+ private _pushChain;
47
55
  readonly name: string;
48
56
  readonly level: number;
49
57
  readonly nameBytes: Uint8Array;
58
+ readonly commentBytes: Uint8Array;
50
59
  readonly dosTime: number;
51
60
  readonly dosDate: number;
52
61
  readonly extraField: Uint8Array;
53
62
  private readonly _flags;
54
- private readonly _compressionMethod;
63
+ private _compressionMethod;
55
64
  private readonly _modTime;
56
65
  constructor(name: string, options?: {
57
66
  level?: number;
58
67
  modTime?: Date;
59
68
  timestamps?: ZipTimestampMode;
69
+ comment?: string;
70
+ smartStore?: boolean;
60
71
  });
72
+ private _buildCompressionMethod;
73
+ private _initDeflateStream;
61
74
  private _buildLocalHeader;
75
+ private _accumulateSample;
76
+ private _shouldDecide;
77
+ private _decideCompressionIfNeeded;
78
+ private _emitHeaderIfNeeded;
79
+ private _flushPendingChunks;
62
80
  private _enqueueData;
63
81
  private _flushQueue;
64
82
  get ondata(): ((data: Uint8Array, final: boolean) => void) | undefined;
65
83
  set ondata(cb: (data: Uint8Array, final: boolean) => void);
84
+ get onerror(): ((err: Error) => void) | undefined;
85
+ set onerror(cb: (err: Error) => void);
66
86
  private _resolveComplete;
67
87
  private _rejectComplete;
68
88
  private _ensureCompletePromise;
69
89
  private _tapCallback;
70
- private _emitHeaderIfNeeded;
71
90
  private _writeData;
72
91
  private _endDeflateAndWait;
73
92
  private _finalizeAfterWrite;
93
+ private _pushUnchained;
74
94
  /**
75
95
  * Push data - immediately compresses and outputs
76
96
  * Returns a Promise that resolves when the write is complete.
@@ -108,10 +128,13 @@ export declare class StreamingZip {
108
128
  private currentOffset;
109
129
  private ended;
110
130
  private endPending;
131
+ private zipComment;
111
132
  private fileQueue;
112
133
  private fileQueueIndex;
113
134
  private activeFile;
114
- constructor(callback: (err: Error | null, data: Uint8Array, final: boolean) => void);
135
+ constructor(callback: (err: Error | null, data: Uint8Array, final: boolean) => void, options?: {
136
+ comment?: string;
137
+ });
115
138
  add(file: ZipDeflateFile): void;
116
139
  private _processNextFile;
117
140
  private _finalize;
@@ -2,15 +2,16 @@
2
2
  * True Streaming ZIP creator - shared implementation.
3
3
  *
4
4
  * This module is intentionally platform-agnostic.
5
- * - In Node builds it uses `./crc32` + `./streaming-compress` (zlib-backed).
5
+ * - In Node builds it uses `./compression/crc32` + `./compression/streaming-compress` (zlib-backed).
6
6
  * - In browser builds the bundler aliases those imports to their browser variants.
7
7
  */
8
- import { crc32Update, crc32Finalize } from "./crc32.browser.js";
9
- import { createDeflateStream } from "./streaming-compress.browser.js";
10
- import { DEFAULT_ZIP_LEVEL, DEFAULT_ZIP_TIMESTAMPS } from "./defaults.js";
11
- import { buildZipEntryMetadata } from "./zip-entry-metadata.js";
12
- import { buildCentralDirectoryHeader, buildDataDescriptor, buildEndOfCentralDirectory, buildLocalFileHeader } from "./zip-records.js";
13
- import { VERSION_MADE_BY, VERSION_NEEDED } from "./zip-constants.js";
8
+ import { crc32Update, crc32Finalize } from "../compression/crc32.browser.js";
9
+ import { createDeflateStream } from "../compression/streaming-compress.browser.js";
10
+ import { DEFAULT_ZIP_LEVEL, DEFAULT_ZIP_TIMESTAMPS } from "../defaults.js";
11
+ import { buildZipEntryMetadata, resolveZipCompressionMethod } from "./zip-entry-metadata.js";
12
+ import { decodeUtf8, encodeUtf8 } from "../utils/text.js";
13
+ import { isProbablyIncompressible } from "../utils/compressibility.js";
14
+ import { buildCentralDirectoryHeader, buildDataDescriptor, buildEndOfCentralDirectory, buildLocalFileHeader, VERSION_MADE_BY, VERSION_NEEDED } from "../zip-spec/zip-records.js";
14
15
  /**
15
16
  * True Streaming ZIP File - compresses chunk by chunk
16
17
  */
@@ -23,9 +24,15 @@ export class ZipDeflateFile {
23
24
  this._finalized = false;
24
25
  this._headerEmitted = false;
25
26
  this._ondata = null;
27
+ this._onerror = null;
26
28
  this._centralDirEntryInfo = null;
27
29
  this._pendingEnd = false;
28
30
  this._emittedDataDescriptor = false;
31
+ this._localHeader = null;
32
+ // Smart STORE: delay method selection until we sample data.
33
+ this._deflateWanted = null;
34
+ this._pendingChunks = [];
35
+ this._sampleLen = 0;
29
36
  // Promise resolution for completion (including data descriptor)
30
37
  this._completeResolve = null;
31
38
  this._completeReject = null;
@@ -34,46 +41,70 @@ export class ZipDeflateFile {
34
41
  // Queue for incoming data before ondata is set
35
42
  this._dataQueue = [];
36
43
  this._finalQueued = false;
44
+ // Serialize push() calls so callers don't need to await to preserve ordering.
45
+ this._pushChain = Promise.resolve();
37
46
  this.name = name;
38
47
  const modTime = options?.modTime ?? new Date();
39
48
  this._modTime = modTime;
40
49
  this.level = options?.level ?? DEFAULT_ZIP_LEVEL;
50
+ this._smartStore = options?.smartStore ?? true;
51
+ this._sampleBuffer = this._smartStore ? new Uint8Array(64 * 1024) : new Uint8Array(0);
41
52
  const metadata = buildZipEntryMetadata({
42
53
  name,
43
- comment: "",
54
+ comment: options?.comment ?? "",
44
55
  modTime,
45
56
  timestamps: options?.timestamps ?? DEFAULT_ZIP_TIMESTAMPS,
46
57
  useDataDescriptor: true,
47
- deflate: this.level > 0
58
+ deflate: false
48
59
  });
49
60
  this.nameBytes = metadata.nameBytes;
61
+ this.commentBytes = metadata.commentBytes;
50
62
  this.dosTime = metadata.dosTime;
51
63
  this.dosDate = metadata.dosDate;
52
64
  this.extraField = metadata.extraField;
53
65
  this._flags = metadata.flags;
54
66
  this._compressionMethod = metadata.compressionMethod;
55
- // Create deflate stream for compression
56
- if (this.level > 0) {
57
- this._deflate = createDeflateStream({ level: this.level });
58
- this._deflate.on("error", (err) => {
59
- this._rejectComplete(err);
60
- });
61
- // Handle compressed output - this is true streaming!
62
- this._deflate.on("data", (chunk) => {
63
- this._compressedSize += chunk.length;
64
- this._enqueueData(chunk, false);
65
- });
66
- // Handle end - emit data descriptor
67
- // IMPORTANT: Only use 'end' event, NOT 'finish'!
68
- // Node.js zlib emits events in order: finish -> data -> end
69
- this._deflate.on("end", () => {
70
- if (this._pendingEnd && !this._emittedDataDescriptor) {
71
- this._emittedDataDescriptor = true;
72
- this._emitDataDescriptor();
73
- }
74
- });
67
+ // If smart store is disabled, decide method upfront and keep true streaming semantics.
68
+ if (!this._smartStore) {
69
+ const deflate = this.level > 0;
70
+ this._deflateWanted = deflate;
71
+ this._compressionMethod = this._buildCompressionMethod(deflate);
72
+ if (deflate) {
73
+ this._initDeflateStream();
74
+ }
75
+ return;
75
76
  }
76
- this._localHeader = this._buildLocalHeader();
77
+ // Level 0: always STORE.
78
+ if (this.level === 0) {
79
+ this._deflateWanted = false;
80
+ this._compressionMethod = this._buildCompressionMethod(false);
81
+ }
82
+ }
83
+ _buildCompressionMethod(deflate) {
84
+ return resolveZipCompressionMethod(deflate);
85
+ }
86
+ _initDeflateStream() {
87
+ if (this._deflate) {
88
+ return;
89
+ }
90
+ this._deflate = createDeflateStream({ level: this.level });
91
+ this._deflate.on("error", (err) => {
92
+ this._rejectComplete(err);
93
+ });
94
+ // Handle compressed output - this is true streaming!
95
+ this._deflate.on("data", (chunk) => {
96
+ this._compressedSize += chunk.length;
97
+ this._enqueueData(chunk, false);
98
+ });
99
+ // Handle end - emit data descriptor
100
+ // IMPORTANT: Only use 'end' event, NOT 'finish'!
101
+ // Node.js zlib emits events in order: finish -> data -> end
102
+ this._deflate.on("end", () => {
103
+ if (this._pendingEnd && !this._emittedDataDescriptor) {
104
+ this._emittedDataDescriptor = true;
105
+ this._emitDataDescriptor();
106
+ }
107
+ });
77
108
  }
78
109
  _buildLocalHeader() {
79
110
  // CRC + sizes are written via data descriptor for true streaming.
@@ -90,6 +121,63 @@ export class ZipDeflateFile {
90
121
  versionNeeded: VERSION_NEEDED
91
122
  });
92
123
  }
124
+ _accumulateSample(data) {
125
+ if (this._deflateWanted !== null) {
126
+ return;
127
+ }
128
+ if (this._sampleLen >= this._sampleBuffer.length) {
129
+ return;
130
+ }
131
+ const take = Math.min(this._sampleBuffer.length - this._sampleLen, data.length);
132
+ if (take <= 0) {
133
+ return;
134
+ }
135
+ this._sampleBuffer.set(data.subarray(0, take), this._sampleLen);
136
+ this._sampleLen += take;
137
+ }
138
+ _shouldDecide(final) {
139
+ if (this._deflateWanted !== null) {
140
+ return false;
141
+ }
142
+ return final || this._sampleLen >= 16 * 1024;
143
+ }
144
+ _decideCompressionIfNeeded(final) {
145
+ if (this._deflateWanted !== null) {
146
+ return;
147
+ }
148
+ // Match non-streaming builder semantics: empty files never need DEFLATE.
149
+ if (final && this._sampleLen === 0) {
150
+ this._deflateWanted = false;
151
+ this._compressionMethod = this._buildCompressionMethod(false);
152
+ this._localHeader = null;
153
+ return;
154
+ }
155
+ // Default to DEFLATE unless heuristic says STORE.
156
+ const sample = this._sampleBuffer.subarray(0, this._sampleLen);
157
+ const store = isProbablyIncompressible(sample);
158
+ this._deflateWanted = !store;
159
+ this._compressionMethod = this._buildCompressionMethod(this._deflateWanted);
160
+ this._localHeader = null;
161
+ if (this._deflateWanted) {
162
+ this._initDeflateStream();
163
+ }
164
+ }
165
+ _emitHeaderIfNeeded() {
166
+ if (this._headerEmitted) {
167
+ return;
168
+ }
169
+ this._emitHeader();
170
+ this._headerEmitted = true;
171
+ }
172
+ async _flushPendingChunks() {
173
+ if (this._pendingChunks.length === 0) {
174
+ return;
175
+ }
176
+ for (const chunk of this._pendingChunks) {
177
+ await this._writeData(chunk);
178
+ }
179
+ this._pendingChunks = [];
180
+ }
93
181
  _enqueueData(data, final) {
94
182
  if (this._ondata) {
95
183
  this._ondata(data, final);
@@ -121,13 +209,29 @@ export class ZipDeflateFile {
121
209
  // Flush any queued data
122
210
  this._flushQueue();
123
211
  }
212
+ get onerror() {
213
+ return this._onerror ?? undefined;
214
+ }
215
+ set onerror(cb) {
216
+ this._onerror = cb;
217
+ // If an error already occurred, surface it immediately.
218
+ if (this._completeError) {
219
+ cb(this._completeError);
220
+ }
221
+ }
124
222
  _resolveComplete() {
125
223
  if (this._completeResolve) {
126
224
  this._completeResolve();
127
225
  }
128
226
  }
129
227
  _rejectComplete(err) {
228
+ if (this._completeError) {
229
+ return;
230
+ }
130
231
  this._completeError = err;
232
+ if (this._onerror) {
233
+ this._onerror(err);
234
+ }
131
235
  if (this._completeReject) {
132
236
  this._completeReject(err);
133
237
  }
@@ -153,13 +257,6 @@ export class ZipDeflateFile {
153
257
  }
154
258
  promise.then(() => callback()).catch(err => callback(err));
155
259
  }
156
- _emitHeaderIfNeeded() {
157
- if (this._headerEmitted) {
158
- return;
159
- }
160
- this._emitHeader();
161
- this._headerEmitted = true;
162
- }
163
260
  _writeData(data) {
164
261
  if (data.length === 0) {
165
262
  return Promise.resolve();
@@ -217,27 +314,60 @@ export class ZipDeflateFile {
217
314
  this._emitDataDescriptor();
218
315
  return completePromise;
219
316
  }
220
- /**
221
- * Push data - immediately compresses and outputs
222
- * Returns a Promise that resolves when the write is complete.
223
- * If final=true, it resolves after the data descriptor is emitted.
224
- */
225
- push(data, final = false, callback) {
317
+ _pushUnchained(data, final, callback) {
226
318
  if (this._finalized) {
227
319
  const promise = Promise.reject(new Error("Cannot push to finalized ZipDeflateFile"));
228
320
  this._tapCallback(promise, callback);
229
321
  return promise;
230
322
  }
323
+ if (this._deflateWanted === null) {
324
+ this._accumulateSample(data);
325
+ if (!this._shouldDecide(final)) {
326
+ if (data.length > 0) {
327
+ this._pendingChunks.push(data);
328
+ }
329
+ const promise = Promise.resolve();
330
+ this._tapCallback(promise, callback);
331
+ return promise;
332
+ }
333
+ this._decideCompressionIfNeeded(final);
334
+ this._emitHeaderIfNeeded();
335
+ const hadPendingChunks = this._pendingChunks.length > 0;
336
+ const flushPromise = this._flushPendingChunks();
337
+ let writePromise = flushPromise;
338
+ if (data.length > 0) {
339
+ writePromise = hadPendingChunks
340
+ ? flushPromise.then(() => this._writeData(data))
341
+ : this._writeData(data);
342
+ }
343
+ const promise = final ? this._finalizeAfterWrite(writePromise) : writePromise;
344
+ this._tapCallback(promise, callback);
345
+ return promise;
346
+ }
231
347
  this._emitHeaderIfNeeded();
232
348
  const writePromise = this._writeData(data);
233
349
  const promise = final ? this._finalizeAfterWrite(writePromise) : writePromise;
234
350
  this._tapCallback(promise, callback);
235
351
  return promise;
236
352
  }
353
+ /**
354
+ * Push data - immediately compresses and outputs
355
+ * Returns a Promise that resolves when the write is complete.
356
+ * If final=true, it resolves after the data descriptor is emitted.
357
+ */
358
+ push(data, final = false, callback) {
359
+ const promise = (this._pushChain = this._pushChain.then(() => this._pushUnchained(data, final, callback)));
360
+ // Prevent unhandled rejection when callers intentionally ignore the Promise.
361
+ promise.catch(() => { });
362
+ return promise;
363
+ }
237
364
  /**
238
365
  * Emit local file header with Data Descriptor flag
239
366
  */
240
367
  _emitHeader() {
368
+ if (!this._localHeader) {
369
+ this._localHeader = this._buildLocalHeader();
370
+ }
241
371
  this._enqueueData(this._localHeader, false);
242
372
  }
243
373
  /**
@@ -250,6 +380,7 @@ export class ZipDeflateFile {
250
380
  this._centralDirEntryInfo = {
251
381
  name: this.nameBytes,
252
382
  extraField: this.extraField,
383
+ comment: this.commentBytes,
253
384
  flags: this._flags,
254
385
  crc: crcValue,
255
386
  compressedSize: this._compressedSize,
@@ -288,7 +419,7 @@ export class ZipDeflateFile {
288
419
  crc32: this._centralDirEntryInfo.crc,
289
420
  lastModified: this._modTime,
290
421
  localHeaderOffset: this._centralDirEntryInfo.offset,
291
- comment: "",
422
+ comment: decodeUtf8(this._centralDirEntryInfo.comment),
292
423
  externalAttributes: 0,
293
424
  isEncrypted: false
294
425
  };
@@ -305,7 +436,7 @@ export class ZipDeflateFile {
305
436
  * Streaming ZIP Creator - processes files sequentially
306
437
  */
307
438
  export class StreamingZip {
308
- constructor(callback) {
439
+ constructor(callback, options) {
309
440
  this.entries = [];
310
441
  this.currentOffset = 0;
311
442
  this.ended = false;
@@ -315,10 +446,12 @@ export class StreamingZip {
315
446
  this.fileQueueIndex = 0;
316
447
  this.activeFile = null;
317
448
  this.callback = callback;
449
+ // Avoid per-instance TextEncoder allocations.
450
+ this.zipComment = options?.comment ? encodeUtf8(options.comment) : new Uint8Array(0);
318
451
  }
319
452
  add(file) {
320
453
  if (this.ended) {
321
- throw new Error("Cannot add files after calling end()");
454
+ throw new Error("Cannot add files after calling end() ");
322
455
  }
323
456
  this.fileQueue.push(file);
324
457
  // If no active file, process this one
@@ -341,7 +474,18 @@ export class StreamingZip {
341
474
  const file = this.fileQueue[this.fileQueueIndex++];
342
475
  this.activeFile = file;
343
476
  const startOffset = this.currentOffset;
477
+ const empty = new Uint8Array(0);
478
+ file.onerror = (err) => {
479
+ if (this.ended) {
480
+ return;
481
+ }
482
+ this.ended = true;
483
+ this.callback(err, empty, true);
484
+ };
344
485
  file.ondata = (data, final) => {
486
+ if (this.ended) {
487
+ return;
488
+ }
345
489
  this.currentOffset += data.length;
346
490
  this.callback(null, data, false);
347
491
  if (final) {
@@ -367,7 +511,7 @@ export class StreamingZip {
367
511
  const header = buildCentralDirectoryHeader({
368
512
  fileName: entry.name,
369
513
  extraField: entry.extraField,
370
- comment: empty,
514
+ comment: entry.comment ?? empty,
371
515
  flags: entry.flags,
372
516
  compressionMethod: entry.compressionMethod,
373
517
  dosTime: entry.dosTime,
@@ -386,7 +530,7 @@ export class StreamingZip {
386
530
  entryCount: this.entries.length,
387
531
  centralDirSize,
388
532
  centralDirOffset,
389
- comment: empty
533
+ comment: this.zipComment
390
534
  });
391
535
  this.callback(null, eocd, true);
392
536
  }