@office-kit/xlsx 0.13.0 → 0.14.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 (34) hide show
  1. package/dist/io.mjs +2 -2
  2. package/dist/iterparse-zWV-5vc6.mjs +164 -0
  3. package/dist/iterparse-zWV-5vc6.mjs.map +1 -0
  4. package/dist/{load-CJdGh50R.mjs → load-B16H5A3S.mjs} +3 -3
  5. package/dist/{load-CJdGh50R.mjs.map → load-B16H5A3S.mjs.map} +1 -1
  6. package/dist/node.mjs +8 -4
  7. package/dist/node.mjs.map +1 -1
  8. package/dist/{reader-BNaUTVCy.mjs → reader-DHMxLBQV.mjs} +81 -26
  9. package/dist/reader-DHMxLBQV.mjs.map +1 -0
  10. package/dist/{save-CjarR7Rp.mjs → save-I6GjvO1k.mjs} +83 -43
  11. package/dist/save-I6GjvO1k.mjs.map +1 -0
  12. package/dist/streaming.mjs +154 -60
  13. package/dist/streaming.mjs.map +1 -1
  14. package/dist/{stylesheet-writer-D7Uug85X.mjs → stylesheet-writer-BCS6PzWU.mjs} +66 -62
  15. package/dist/stylesheet-writer-BCS6PzWU.mjs.map +1 -0
  16. package/dist/utf8-OAkCDG5g.mjs +21 -0
  17. package/dist/utf8-OAkCDG5g.mjs.map +1 -0
  18. package/dist/worksheet/writer.d.ts +23 -4
  19. package/dist/{writer-Z7cF_CBk.mjs → writer-C38RBZCy.mjs} +2 -2
  20. package/dist/writer-C38RBZCy.mjs.map +1 -0
  21. package/dist/xml.mjs +2 -1
  22. package/dist/xml.mjs.map +1 -1
  23. package/dist/zip/decompression-guard.d.ts +22 -6
  24. package/dist/zip/inflate-cache.d.ts +22 -0
  25. package/dist/zip/reader.d.ts +11 -6
  26. package/dist/zip/writer.d.ts +6 -2
  27. package/dist/zip.mjs +2 -2
  28. package/package.json +1 -1
  29. package/dist/reader-BNaUTVCy.mjs.map +0 -1
  30. package/dist/save-CjarR7Rp.mjs.map +0 -1
  31. package/dist/stylesheet-writer-D7Uug85X.mjs.map +0 -1
  32. package/dist/utf8-Tn3nzyik.mjs +0 -143
  33. package/dist/utf8-Tn3nzyik.mjs.map +0 -1
  34. package/dist/writer-Z7cF_CBk.mjs.map +0 -1
@@ -1,143 +0,0 @@
1
- import { o as OpenXmlSchemaError } from "./exceptions-D-CFwxgm.mjs";
2
- import { jt as qname } from "./tree-BX-sRRVp.mjs";
3
- import { SaxesParser } from "saxes";
4
- //#region src/xml/iterparse.ts
5
- const DOCTYPE_RE = /<!DOCTYPE\b/;
6
- const ENTITY_RE = /<!ENTITY\b/;
7
- const checkDoctype = (text) => {
8
- if (DOCTYPE_RE.test(text)) throw new OpenXmlSchemaError("DTD declarations are not permitted in OOXML payloads");
9
- if (ENTITY_RE.test(text)) throw new OpenXmlSchemaError("Entity declarations are not permitted in OOXML payloads");
10
- };
11
- const isReadableStream = (v) => {
12
- return typeof v === "object" && v !== null && typeof v.getReader === "function";
13
- };
14
- const decoder = () => new TextDecoder("utf-8", { fatal: false });
15
- const buildAttrsClark = (attrs) => {
16
- const out = {};
17
- for (const [, info] of Object.entries(attrs)) {
18
- if (info.prefix === "xmlns" || info.prefix === "" && info.local === "xmlns") continue;
19
- const key = qname(info.uri, info.local);
20
- out[key] = info.value;
21
- }
22
- return out;
23
- };
24
- /**
25
- * Parse the input as a stream of SAX events. Element / attribute names are
26
- * returned in Clark notation (`{ns}local`).
27
- */
28
- async function* iterParse(input) {
29
- const parser = new SaxesParser({
30
- xmlns: true,
31
- fragment: false
32
- });
33
- let queue = [];
34
- let head = 0;
35
- let pending;
36
- parser.on("error", (err) => {
37
- pending = err;
38
- });
39
- parser.on("doctype", () => {
40
- pending = new OpenXmlSchemaError("DTD declarations are not permitted in OOXML payloads");
41
- });
42
- parser.on("opentag", (node) => {
43
- queue.push({
44
- kind: "start",
45
- name: qname(node.uri, node.local),
46
- attrs: buildAttrsClark(node.attributes)
47
- });
48
- });
49
- parser.on("closetag", (node) => {
50
- queue.push({
51
- kind: "end",
52
- name: qname(node.uri, node.local)
53
- });
54
- });
55
- parser.on("text", (text) => {
56
- if (text.length > 0) queue.push({
57
- kind: "text",
58
- text
59
- });
60
- });
61
- const drain = function* () {
62
- for (;;) {
63
- const ev = head < queue.length ? queue[head] : void 0;
64
- if (ev === void 0) {
65
- queue = [];
66
- head = 0;
67
- return;
68
- }
69
- head++;
70
- yield ev;
71
- }
72
- };
73
- const feed = (chunk) => {
74
- parser.write(chunk);
75
- if (pending !== void 0) throw pending;
76
- };
77
- if (typeof input === "string") {
78
- checkDoctype(input);
79
- feed(input);
80
- } else if (input instanceof Uint8Array) {
81
- const text = decoder().decode(input);
82
- checkDoctype(text);
83
- feed(text);
84
- yield* drain();
85
- } else if (isReadableStream(input)) {
86
- const reader = input.getReader();
87
- const td = decoder();
88
- let firstChunkChecked = false;
89
- let firstChunkBuffer = "";
90
- while (true) {
91
- const { done, value } = await reader.read();
92
- if (done) break;
93
- const chunk = td.decode(value, { stream: true });
94
- if (!firstChunkChecked) {
95
- firstChunkBuffer += chunk;
96
- if (firstChunkBuffer.length >= 256) {
97
- checkDoctype(firstChunkBuffer);
98
- firstChunkChecked = true;
99
- feed(firstChunkBuffer);
100
- yield* drain();
101
- }
102
- } else {
103
- feed(chunk);
104
- yield* drain();
105
- }
106
- }
107
- const tail = td.decode();
108
- if (!firstChunkChecked) {
109
- const all = firstChunkBuffer + tail;
110
- checkDoctype(all);
111
- feed(all);
112
- yield* drain();
113
- } else if (tail.length > 0) {
114
- feed(tail);
115
- yield* drain();
116
- }
117
- } else throw new OpenXmlSchemaError("iterParse: unsupported input type");
118
- parser.close();
119
- if (pending !== void 0) throw pending;
120
- yield* drain();
121
- }
122
- //#endregion
123
- //#region src/utils/utf8.ts
124
- function utf8ByteLength(s) {
125
- let n = 0;
126
- for (let i = 0; i < s.length; i++) {
127
- const c = s.charCodeAt(i);
128
- if (c < 128) n += 1;
129
- else if (c < 2048) n += 2;
130
- else if (c >= 55296 && c <= 56319) {
131
- const next = i + 1 < s.length ? s.charCodeAt(i + 1) : 0;
132
- if (next >= 56320 && next <= 57343) {
133
- n += 4;
134
- i++;
135
- } else n += 3;
136
- } else n += 3;
137
- }
138
- return n;
139
- }
140
- //#endregion
141
- export { iterParse as n, utf8ByteLength as t };
142
-
143
- //# sourceMappingURL=utf8-Tn3nzyik.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utf8-Tn3nzyik.mjs","names":[],"sources":["../src/xml/iterparse.ts","../src/utils/utf8.ts"],"sourcesContent":["// SAX iterator over OOXML XML payloads. Wraps `saxes` (XMLNS-aware) and yields\n// a flat stream of {start | end | text} events with names already converted to\n// Clark notation (`{ns}local`) — same shape as the DOM parser produces for\n// static XmlNode trees, so consumers can switch between bulk and streaming\n// reads without retouching name comparison.\n//\n// Phase 1 §3 acceptance: 1 k–row sheetData walked end-to-end with cell counts\n// matching the source. The phase-4 read-only worksheet drives real-world use;\n// this layer just produces the events.\n//\n// DOCTYPE / external entity declarations are forbidden. saxes does not expand\n// external entities, but a prescan also rejects DTDs in non-streaming inputs.\n// Streaming inputs are checked on the first chunk before being fed to the\n// parser.\n\nimport { SaxesParser } from 'saxes';\nimport { OpenXmlSchemaError } from '../utils/exceptions.js';\nimport { qname } from './namespaces.js';\n\nexport type SaxEvent =\n | { kind: 'start'; name: string; attrs: Record<string, string> }\n | { kind: 'end'; name: string }\n | { kind: 'text'; text: string };\n\n/**\n * Streamable input: `Uint8Array`, plain string, or a Web `ReadableStream` of\n * `Uint8Array` chunks (produced by xlsx zip entries via fflate, fetch, file\n * streams, etc.).\n */\nexport type SaxInput = Uint8Array | string | ReadableStream<Uint8Array>;\n\nconst DOCTYPE_RE = /<!DOCTYPE\\b/;\nconst ENTITY_RE = /<!ENTITY\\b/;\n\nconst checkDoctype = (text: string): void => {\n if (DOCTYPE_RE.test(text)) {\n throw new OpenXmlSchemaError('DTD declarations are not permitted in OOXML payloads');\n }\n if (ENTITY_RE.test(text)) {\n throw new OpenXmlSchemaError('Entity declarations are not permitted in OOXML payloads');\n }\n};\n\nconst isReadableStream = (v: unknown): v is ReadableStream<Uint8Array> => {\n return typeof v === 'object' && v !== null && typeof (v as ReadableStream).getReader === 'function';\n};\n\nconst decoder = (): TextDecoder => new TextDecoder('utf-8', { fatal: false });\n\ninterface SaxesOpenTag {\n name: string;\n uri: string;\n local: string;\n prefix: string;\n attributes: Record<string, { value: string; uri: string; local: string; prefix: string }>;\n isSelfClosing?: boolean;\n}\n\ninterface SaxesCloseTag {\n name: string;\n uri: string;\n local: string;\n prefix: string;\n}\n\nconst buildAttrsClark = (attrs: SaxesOpenTag['attributes']): Record<string, string> => {\n const out: Record<string, string> = {};\n for (const [, info] of Object.entries(attrs)) {\n // saxes already resolved the namespace when xmlns: true is set; raw xmlns /\n // xmlns:* declarations have prefix='xmlns' (or local==='xmlns' when\n // default) and we drop those — they're rebuilt by the serializer.\n if (info.prefix === 'xmlns' || (info.prefix === '' && info.local === 'xmlns')) continue;\n const key = qname(info.uri, info.local);\n out[key] = info.value;\n }\n return out;\n};\n\n/**\n * Parse the input as a stream of SAX events. Element / attribute names are\n * returned in Clark notation (`{ns}local`).\n */\nexport async function* iterParse(input: SaxInput): AsyncIterableIterator<SaxEvent> {\n // Set up the parser. xmlns: true gives us resolved {uri, local, prefix} on\n // every open / close tag and on every attribute.\n const parser = new SaxesParser({ xmlns: true, fragment: false });\n\n // Head-pointer ring instead of Array#shift: each saxes write() can produce\n // hundreds of events in a single synchronous batch (a `<row>` with dozens of\n // cells flushes one opentag + one text + one closetag per cell). `shift()`\n // is O(n) per element in V8, so a single-batch drain of N events would be\n // O(N²) before iteration. The head advances on yield; the queue is reset\n // (head + length) once it drains so memory stays bounded.\n let queue: SaxEvent[] = [];\n let head = 0;\n let pending: Error | undefined;\n\n parser.on('error', (err: Error) => {\n pending = err;\n });\n parser.on('doctype', () => {\n pending = new OpenXmlSchemaError('DTD declarations are not permitted in OOXML payloads');\n });\n parser.on('opentag', (node: SaxesOpenTag) => {\n queue.push({ kind: 'start', name: qname(node.uri, node.local), attrs: buildAttrsClark(node.attributes) });\n });\n parser.on('closetag', (node: SaxesCloseTag) => {\n queue.push({ kind: 'end', name: qname(node.uri, node.local) });\n });\n parser.on('text', (text: string) => {\n if (text.length > 0) queue.push({ kind: 'text', text });\n });\n\n const drain = function* (): IterableIterator<SaxEvent> {\n for (;;) {\n const ev = head < queue.length ? queue[head] : undefined;\n if (ev === undefined) {\n // Reset rather than grow forever; the next batch starts at index 0.\n queue = [];\n head = 0;\n return;\n }\n head++;\n yield ev;\n }\n };\n\n const feed = (chunk: string): void => {\n parser.write(chunk);\n if (pending !== undefined) throw pending;\n };\n\n if (typeof input === 'string') {\n checkDoctype(input);\n feed(input);\n } else if (input instanceof Uint8Array) {\n const text = decoder().decode(input);\n checkDoctype(text);\n feed(text);\n yield* drain();\n } else if (isReadableStream(input)) {\n const reader = input.getReader();\n const td = decoder();\n let firstChunkChecked = false;\n let firstChunkBuffer = '';\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const chunk = td.decode(value, { stream: true });\n if (!firstChunkChecked) {\n // We need to see enough of the prologue to be sure no DOCTYPE is\n // hiding. Buffer until we have ~256 chars; if the stream ends before\n // we reach the threshold the tail handler below runs `checkDoctype`\n // on the accumulated prologue. (The previous `|| done` here was dead:\n // a true `done` short-circuits at the top of the loop.)\n firstChunkBuffer += chunk;\n if (firstChunkBuffer.length >= 256) {\n checkDoctype(firstChunkBuffer);\n firstChunkChecked = true;\n feed(firstChunkBuffer);\n yield* drain();\n }\n } else {\n feed(chunk);\n yield* drain();\n }\n }\n // Stream ended; flush decoder + any buffered prologue.\n const tail = td.decode();\n if (!firstChunkChecked) {\n const all = firstChunkBuffer + tail;\n checkDoctype(all);\n feed(all);\n yield* drain();\n } else if (tail.length > 0) {\n feed(tail);\n yield* drain();\n }\n } else {\n throw new OpenXmlSchemaError('iterParse: unsupported input type');\n }\n\n parser.close();\n if (pending !== undefined) throw pending;\n yield* drain();\n}\n","// Fast UTF-8 byte-length scan. Used by streaming writers to decide when their\n// pending string buffer should be encoded + flushed.\n//\n// `s.length` returns UTF-16 code units, which undercounts BMP characters above\n// U+007F (1 code unit, 2 UTF-8 bytes for U+0080–U+07FF, 3 bytes for the rest\n// of the BMP). For CJK-heavy payloads the discrepancy is ~3× — large enough\n// to push a \"64 KB\" flush threshold to 192 KB of resident text. We scan the\n// string once and account for each codepoint instead of running a full\n// TextEncoder, which would also have to materialise the byte buffer we don't\n// need yet.\nexport function utf8ByteLength(s: string): number {\n let n = 0;\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i);\n if (c < 0x80) {\n n += 1;\n } else if (c < 0x800) {\n n += 2;\n } else if (c >= 0xd800 && c <= 0xdbff) {\n // High surrogate. Only consume the next code unit when it actually\n // is a low surrogate — an unpaired high surrogate (followed by a\n // BMP char or by EOS) would otherwise swallow the next code unit\n // and undercount the string. TextEncoder replaces a lone high\n // surrogate with U+FFFD (3 bytes), so use 3 here too. A paired\n // surrogate encodes one 4-byte codepoint.\n const next = i + 1 < s.length ? s.charCodeAt(i + 1) : 0;\n if (next >= 0xdc00 && next <= 0xdfff) {\n n += 4;\n i++;\n } else {\n n += 3;\n }\n } else {\n // Includes unpaired low surrogates (0xDC00-0xDFFF), which encode as\n // U+FFFD = 3 UTF-8 bytes through TextEncoder.\n n += 3;\n }\n }\n return n;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"writer-Z7cF_CBk.mjs","names":["ZIP32_MAX_ENTRIES"],"sources":["../src/zip/zip64-patch.ts","../src/zip/writer.ts"],"sourcesContent":["// ZIP64 post-processing for archives whose entry count exceeds the\n// 16-bit ZIP32 cap (65535). fflate's `Zip` writer always emits a\n// plain ZIP32 EOCD; for archives with more entries we keep its\n// per-entry LFH/CDH layout (correct as long as no individual size or\n// offset overflows 32 bits) and splice in a ZIP64 End-of-Central-\n// Directory record + locator before the EOCD, then patch the EOCD's\n// entry-count fields with the 0xFFFF sentinel that signals \"consult\n// the ZIP64 record for the real values\".\n//\n// The input is fflate's *final* chunk — the trailing [CD | EOCD] block\n// it emits in one ondata callback when `Zip.end()` is called. The\n// preceding entry-data chunks have already been streamed to the sink,\n// so we operate on the final chunk in isolation. The global EOCD\n// offset (needed for the ZIP64 locator) is derivable from cd_offset +\n// cd_size carried in the EOCD itself, so no external bookkeeping is\n// required.\n//\n// Out of scope: per-entry sizes or central-directory offsets > 4 GiB.\n// xlsx archives don't approach those limits in practice; we throw a\n// clear error if we detect overflow there.\n\nimport { OpenXmlIoError, OpenXmlNotImplementedError } from '../utils/exceptions.js';\n\nconst ZIP32_MAX_ENTRIES = 0xffff;\nconst ZIP32_MAX_U32 = 0xffffffff;\nconst SIG_EOCD = 0x06054b50;\nconst SIG_ZIP64_EOCD = 0x06064b50;\nconst SIG_ZIP64_EOCD_LOCATOR = 0x07064b50;\n\nconst ZIP64_EOCD_SIZE = 56;\nconst ZIP64_LOCATOR_SIZE = 20;\n\nconst u16 = (b: Uint8Array, o: number): number => (b[o] ?? 0) | ((b[o + 1] ?? 0) << 8);\n\nconst u32 = (b: Uint8Array, o: number): number => {\n const v0 = b[o] ?? 0;\n const v1 = b[o + 1] ?? 0;\n const v2 = b[o + 2] ?? 0;\n const v3 = b[o + 3] ?? 0;\n return (v0 | (v1 << 8) | (v2 << 16) | (v3 << 24)) >>> 0;\n};\n\nconst writeU16 = (b: Uint8Array, o: number, v: number): void => {\n b[o] = v & 0xff;\n b[o + 1] = (v >>> 8) & 0xff;\n};\n\nconst writeU32 = (b: Uint8Array, o: number, v: number): void => {\n b[o] = v & 0xff;\n b[o + 1] = (v >>> 8) & 0xff;\n b[o + 2] = (v >>> 16) & 0xff;\n b[o + 3] = (v >>> 24) & 0xff;\n};\n\nconst writeU64 = (b: Uint8Array, o: number, v: number): void => {\n // JS Number safely represents integers up to 2^53 - 1, well beyond\n // anything we'd ever emit here. Split via Math.floor + modulo to\n // avoid bit-shift truncation at 32 bits.\n const lo = v >>> 0;\n const hi = Math.floor(v / 0x100000000) >>> 0;\n writeU32(b, o, lo);\n writeU32(b, o + 4, hi);\n};\n\nconst findEocdOffset = (bytes: Uint8Array): number => {\n // EOCD is min 22 bytes and may be followed by up to 65535 bytes of\n // archive comment. Scan backwards from the latest possible position.\n const minOffset = Math.max(0, bytes.length - (22 + 0xffff));\n for (let p = bytes.length - 22; p >= minOffset; p--) {\n if (u32(bytes, p) === SIG_EOCD) {\n const commentLen = u16(bytes, p + 20);\n if (p + 22 + commentLen === bytes.length) return p;\n }\n }\n throw new OpenXmlIoError('zip64-patch: no End-of-Central-Directory signature found');\n};\n\n/**\n * Splice ZIP64 EOCD record + locator into fflate's final chunk and\n * patch the trailing EOCD entry-count fields with the 0xFFFF sentinel.\n *\n * `finalChunk` must be the [CD | EOCD] block fflate emits as its last\n * ondata callback (everything before it is per-entry LFH/data/DD that\n * we leave untouched). Returns a new chunk; the input is not mutated.\n *\n * Assumes per-entry sizes and central-directory offset fit in 32 bits;\n * throws if not (xlsx archives never approach those limits).\n */\nexport function applyZip64EntryCountPatch(finalChunk: Uint8Array, totalEntries: number): Uint8Array {\n if (totalEntries <= ZIP32_MAX_ENTRIES) return finalChunk;\n\n const eocdOffset = findEocdOffset(finalChunk);\n\n const cdSize = u32(finalChunk, eocdOffset + 12);\n const cdOffset = u32(finalChunk, eocdOffset + 16);\n const commentLen = u16(finalChunk, eocdOffset + 20);\n\n if (cdSize === ZIP32_MAX_U32 || cdOffset === ZIP32_MAX_U32) {\n throw new OpenXmlNotImplementedError(\n 'zip64-patch: archive size or central-directory offset exceeds 4 GiB; full ZIP64 size support is not implemented (xlsx in practice stays well under 4 GiB).',\n );\n }\n\n // Where the EOCD starts in the *global* archive (before our patch).\n // CD precedes EOCD with no gap, so global EOCD offset is just\n // cd_offset + cd_size — the locator points here.\n const globalEocdOffset = cdOffset + cdSize;\n\n const eocdLen = 22 + commentLen;\n const newChunkLen = eocdOffset + ZIP64_EOCD_SIZE + ZIP64_LOCATOR_SIZE + eocdLen;\n const out = new Uint8Array(newChunkLen);\n\n // Original CD bytes (everything before the EOCD).\n out.set(finalChunk.subarray(0, eocdOffset), 0);\n\n // ZIP64 EOCD record (56 bytes total).\n const zip64Eocd = out.subarray(eocdOffset, eocdOffset + ZIP64_EOCD_SIZE);\n writeU32(zip64Eocd, 0, SIG_ZIP64_EOCD);\n // size_of_zip64_eocd = total_size - 12 (size field excludes signature + this field itself)\n writeU64(zip64Eocd, 4, ZIP64_EOCD_SIZE - 12);\n writeU16(zip64Eocd, 12, 45); // version made by (4.5 — first ZIP64 spec)\n writeU16(zip64Eocd, 14, 45); // version needed\n writeU32(zip64Eocd, 16, 0); // disk_number\n writeU32(zip64Eocd, 20, 0); // disk_with_cd\n writeU64(zip64Eocd, 24, totalEntries); // entries_on_this_disk\n writeU64(zip64Eocd, 32, totalEntries); // total_entries\n writeU64(zip64Eocd, 40, cdSize); // cd_size\n writeU64(zip64Eocd, 48, cdOffset); // cd_offset\n\n // ZIP64 EOCD locator (20 bytes).\n const locOffset = eocdOffset + ZIP64_EOCD_SIZE;\n const locator = out.subarray(locOffset, locOffset + ZIP64_LOCATOR_SIZE);\n writeU32(locator, 0, SIG_ZIP64_EOCD_LOCATOR);\n writeU32(locator, 4, 0); // disk_with_zip64_eocd\n writeU64(locator, 8, globalEocdOffset);\n writeU32(locator, 16, 1); // total_disks\n\n // New EOCD: copy original then patch entry counts to the 0xFFFF\n // sentinel. (fflate writes the low 16 bits of the true count there,\n // which confuses readers that don't first look for the ZIP64 record.)\n const newEocdOffset = locOffset + ZIP64_LOCATOR_SIZE;\n out.set(finalChunk.subarray(eocdOffset, eocdOffset + eocdLen), newEocdOffset);\n writeU16(out, newEocdOffset + 8, ZIP32_MAX_ENTRIES);\n writeU16(out, newEocdOffset + 10, ZIP32_MAX_ENTRIES);\n\n return out;\n}\n","// ZIP write layer. Streaming-deflate via fflate's `Zip` + per-entry\n// `ZipDeflate` / `ZipPassThrough` so the writer never holds the whole archive\n// in memory. Each addEntry pushes its bytes through the deflate stream and the\n// resulting ZIP chunks land on the sink one at a time — the buffered\n// `toBytes()` sink concatenates them on finish, while a streaming sink can\n// flush them as they arrive.\n//\n// ZIP64 (entry count > 65535): fflate's `Zip` emits a plain ZIP32 EOCD in all\n// cases, so on finalize we splice in a ZIP64 EOCD record + locator when needed\n// via `applyZip64EntryCountPatch`. That keeps the per-entry LFH/CDH layout\n// fflate produces and only rewrites the trailing records.\n//\n// Scope: this covers the entry-count-overflow case (the limit xlsx archives\n// realistically hit — `tens of millions of cells` → tens of thousands of\n// worksheet entries via the streaming writer). Per-entry compressed/uncompressed\n// sizes and the central-directory offset must still fit in 32 bits (≤ 4 GiB\n// each); a single >4 GiB entry would need full ZIP64 size support and\n// `applyZip64EntryCountPatch` throws `OpenXmlNotImplementedError` if we ever\n// detect that. xlsx workbooks don't approach that limit in practice, but the\n// constraint is real — surface it in your own size estimates.\n\nimport { Zip, ZipDeflate, ZipPassThrough } from 'fflate';\nimport type { XlsxSink } from '../io/sink.js';\nimport { OpenXmlIoError } from '../utils/exceptions.js';\nimport { applyZip64EntryCountPatch } from './zip64-patch.js';\n\nconst ZIP32_MAX_ENTRIES = 0xffff;\nconst LOCAL_TIMESTAMP_OFFSET = 10;\nconst CENTRAL_TIMESTAMP_OFFSET = 12;\nconst CENTRAL_HEADER_SIZE = 46;\nconst CENTRAL_NAME_LENGTH_OFFSET = 28;\nconst CENTRAL_EXTRA_LENGTH_OFFSET = 30;\nconst CENTRAL_COMMENT_LENGTH_OFFSET = 32;\n\n/** Deflate effort: 0 skips compression, 9 is the slowest and smallest. */\nexport type CompressionLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;\n\n/** Supported year range of the fflate ZIP backend. */\nconst MIN_ZIP_YEAR = 1980;\nconst MAX_ZIP_YEAR = 2099;\n\nexport interface ZipWriterOptions {\n /**\n * Last-modified timestamp stamped into every entry's local header and\n * central-directory record. ZIP has no \"no timestamp\" encoding, so fflate\n * defaults each entry to the wall clock and two archives built from\n * identical input differ in bytes. Pin this to get reproducible output for\n * golden-file tests or content-addressed caching.\n *\n * Recorded as the date's UTC wall time, to a two-second resolution, with the\n * year required to fall in 1980-2099. The DOS field carries no timezone, so\n * writing local components would leave the bytes depending on the writer's\n * `TZ`, which is the opposite of what pinning a stamp is for.\n */\n mtime?: Date;\n /** Deflate level handed to fflate. Defaults to fflate's own 6. */\n compressionLevel?: CompressionLevel;\n}\n\nexport interface ZipWriter {\n /**\n * Stage an entry. Bytes are pushed through fflate's `ZipDeflate` /\n * `ZipPassThrough` stream synchronously, so the deflated chunks land on the\n * sink as the call runs (no per-entry buffering — see the streaming-behaviour\n * test in `tests/phase-1/zip/writer.test.ts`). Streams (`ReadableStream`)\n * are not accepted today; pass an already-materialised entry, or use\n * {@link addStreamingEntry} for chunked writes.\n *\n * `compress` defaults to `true`. Pass `false` for already-compressed payloads\n * (PNG/JPEG/zip-as-binary content like vbaProject.bin) so we don't pay\n * deflate costs for no gain.\n */\n addEntry(path: string, bytes: Uint8Array | ReadableStream<Uint8Array>, opts?: { compress?: boolean }): Promise<void>;\n\n /**\n * Open a streaming entry. Returns a writer the caller can `write()` chunks to\n * and `end()` to seal the entry. Each chunk pushes through the same fflate\n * `ZipDeflate` / `ZipPassThrough` machinery as `addEntry`, so peak memory\n * stays at one chunk + deflate scratch even for multi-GB worksheets.\n *\n * Sequencing: only one streaming entry may be open at a time — `addEntry` and\n * a second `addStreamingEntry` both throw until the current entry's `end()`\n * resolves.\n */\n addStreamingEntry(path: string, opts?: { compress?: boolean }): StreamingEntryWriter;\n\n /**\n * Build the central directory and flush all bytes through the sink.\n * Idempotent; subsequent calls resolve to the same payload.\n */\n finalize(): Promise<Uint8Array>;\n\n /**\n * Release the sink and underlying writer without producing a valid archive.\n * Use this from a surrounding catch block when serialization fails part-way\n * through — without it, streaming sinks (`toFile` / `toWritable`) keep their\n * file descriptors / writables open and the half-written xlsx looks valid on\n * disk. Idempotent; safe to call after `finalize()`.\n */\n abort(cause?: unknown): void;\n}\n\n/** Writer handle for a single streaming entry. */\nexport interface StreamingEntryWriter {\n /** Push a chunk of bytes (already-encoded). Throws after `end()`. */\n write(chunk: Uint8Array): void;\n /** Seal the entry. Subsequent `write()` throws. Idempotent. */\n end(): Promise<void>;\n}\n\n/** Encode UTC components directly: local dates cannot represent a DST gap. */\nconst toZipStamp = (mtime: Date): number => {\n const ms = mtime.getTime();\n if (Number.isNaN(ms)) {\n throw new OpenXmlIoError('createZipWriter: mtime is an invalid Date');\n }\n const year = mtime.getUTCFullYear();\n if (year < MIN_ZIP_YEAR || year > MAX_ZIP_YEAR) {\n throw new OpenXmlIoError(\n `createZipWriter: mtime ${mtime.toISOString()} is outside the supported ZIP timestamp range (${MIN_ZIP_YEAR}-${MAX_ZIP_YEAR})`,\n );\n }\n return ((year - MIN_ZIP_YEAR) << 25)\n | ((mtime.getUTCMonth() + 1) << 21)\n | (mtime.getUTCDate() << 16)\n | (mtime.getUTCHours() << 11)\n | (mtime.getUTCMinutes() << 5)\n | (mtime.getUTCSeconds() >> 1);\n};\n\n/**\n * fflate looks the level up in a table and falls back to 6 for anything off\n * the end, so an out-of-range level would quietly produce default output. The\n * union type catches that for TypeScript callers; this catches it for the rest.\n */\nconst validateCompressionLevel = (level: number): void => {\n if (!Number.isInteger(level) || level < 0 || level > 9) {\n throw new OpenXmlIoError(`createZipWriter: compressionLevel must be an integer in [0, 9]; got ${level}`);\n }\n};\n\n/**\n * ZIP writer backed by fflate's streaming `Zip` class. Entries are pushed\n * through `ZipDeflate` / `ZipPassThrough` streams as they arrive, so peak\n * memory stays at the size of the in-flight entry plus the output buffer rather\n * than the full archive.\n *\n * The sink contract is `toBytes()`, but that name is historical: the sink is\n * driven by a chunked `write(chunk)` API that fans bytes out as they arrive.\n * The buffered Node/browser sinks (`toBuffer`, `toBlob`, `toArrayBuffer`)\n * concatenate the chunks for a single-shot result; streaming sinks\n * (`toFile`, `toWritable`) forward each chunk to disk / the wrapped writable\n * without ever holding the full archive resident. Either kind plugs in here.\n */\nexport function createZipWriter(sink: XlsxSink, opts: ZipWriterOptions = {}): ZipWriter {\n // Both options are checked before the sink is opened: a bad one otherwise\n // surfaces from fflate half-way through the first entry, by which time a file\n // sink holds a partial archive.\n if (opts.compressionLevel !== undefined) validateCompressionLevel(opts.compressionLevel);\n const stamp = opts.mtime === undefined ? undefined : toZipStamp(opts.mtime);\n const writer = sink.toBytes();\n const deflateOpts = opts.compressionLevel === undefined ? undefined : { level: opts.compressionLevel };\n let pendingLocalHeader = false;\n // fflate clones mtime and reads local getters, so even a Date subclass cannot\n // represent UTC times in a local DST gap. Give it a safe placeholder and patch\n // only its header chunks below; payload chunks must never be signature-scanned.\n const newEntry = (path: string, compress: boolean): ZipDeflate | ZipPassThrough => {\n const file = compress ? new ZipDeflate(path, deflateOpts) : new ZipPassThrough(path);\n if (stamp !== undefined) {\n file.mtime = new Date(2000, 0, 1);\n pendingLocalHeader = true;\n }\n return file;\n };\n let finalised: Promise<Uint8Array> | undefined;\n let endCalled = false;\n const seen = new Set<string>();\n const errors: Error[] = [];\n // fflate emits the [CD | EOCD] block in a single ondata call with\n // `final=true`. We capture only that chunk so we can apply the ZIP64 patch on\n // finalize; all preceding entry-data chunks stream straight to the sink to\n // preserve the writer's incremental flushing contract.\n let finalChunk: Uint8Array | undefined;\n let zipFinishResolve: (() => void) | undefined;\n const zipFinishPromise = new Promise<void>((resolve) => {\n zipFinishResolve = resolve;\n });\n\n const zip = new Zip((err, chunk, final) => {\n if (err) {\n errors.push(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n // ZipDeflate emits an empty trailer chunk on the final callback even when\n // there are no bytes; guard against pushing an undefined chunk.\n if (chunk && chunk.byteLength > 0) {\n if (stamp !== undefined && (final || pendingLocalHeader)) {\n const view = new DataView(chunk.buffer, chunk.byteOffset, chunk.byteLength);\n if (final) {\n // fflate emits the complete central directory plus EOCD as one chunk.\n let offset = 0;\n for (let i = 0; i < seen.size; i++) {\n view.setUint32(offset + CENTRAL_TIMESTAMP_OFFSET, stamp, true);\n offset += CENTRAL_HEADER_SIZE + view.getUint16(offset + CENTRAL_NAME_LENGTH_OFFSET, true)\n + view.getUint16(offset + CENTRAL_EXTRA_LENGTH_OFFSET, true)\n + view.getUint16(offset + CENTRAL_COMMENT_LENGTH_OFFSET, true);\n }\n } else if (pendingLocalHeader) {\n // With one entry open at a time, its first chunk is the local header.\n view.setUint32(LOCAL_TIMESTAMP_OFFSET, stamp, true);\n pendingLocalHeader = false;\n }\n }\n if (final) {\n // Buffer the trailing CD + EOCD block; written after possible patch.\n finalChunk = chunk;\n } else {\n writer.write(chunk);\n }\n }\n if (final && zipFinishResolve) {\n zipFinishResolve();\n zipFinishResolve = undefined;\n }\n });\n\n let streamingOpen = false;\n\n const guardAdd = (path: string): void => {\n if (finalised !== undefined) {\n throw new OpenXmlIoError('createZipWriter: addEntry after finalize');\n }\n if (streamingOpen) {\n throw new OpenXmlIoError('createZipWriter: a streaming entry is still open — call end() first');\n }\n if (seen.has(path)) {\n throw new OpenXmlIoError(`createZipWriter: duplicate entry \"${path}\"`);\n }\n };\n\n return {\n async addEntry(path, bytes, entryOpts) {\n if (!(bytes instanceof Uint8Array)) {\n throw new OpenXmlIoError(\n 'createZipWriter: ReadableStream entries are not yet supported (deferred to streaming writer)',\n );\n }\n guardAdd(path);\n seen.add(path);\n const file = newEntry(path, entryOpts?.compress ?? true);\n try {\n zip.add(file);\n file.push(bytes, /* final */ true);\n } catch (cause) {\n throw new OpenXmlIoError(`createZipWriter: failed to add entry \"${path}\"`, { cause });\n }\n if (errors.length > 0) {\n throw new OpenXmlIoError('createZipWriter: stream error during addEntry', { cause: errors[0] });\n }\n },\n\n addStreamingEntry(path, entryOpts) {\n guardAdd(path);\n seen.add(path);\n streamingOpen = true;\n const file = newEntry(path, entryOpts?.compress ?? true);\n try {\n zip.add(file);\n } catch (cause) {\n streamingOpen = false;\n throw new OpenXmlIoError(`createZipWriter: failed to open streaming entry \"${path}\"`, { cause });\n }\n let ended = false;\n return {\n write(chunk: Uint8Array): void {\n if (ended) throw new OpenXmlIoError(`createZipWriter: write after end on \"${path}\"`);\n if (!(chunk instanceof Uint8Array)) {\n throw new OpenXmlIoError(`createZipWriter: streaming entry \"${path}\" chunk is not a Uint8Array`);\n }\n if (chunk.byteLength === 0) return;\n try {\n file.push(chunk, /* final */ false);\n } catch (cause) {\n throw new OpenXmlIoError(`createZipWriter: failed to push chunk on \"${path}\"`, { cause });\n }\n if (errors.length > 0) {\n throw new OpenXmlIoError('createZipWriter: stream error during write', { cause: errors[0] });\n }\n },\n async end(): Promise<void> {\n if (ended) return;\n ended = true;\n try {\n file.push(new Uint8Array(0), /* final */ true);\n } catch (cause) {\n throw new OpenXmlIoError(`createZipWriter: failed to end streaming entry \"${path}\"`, { cause });\n }\n streamingOpen = false;\n if (errors.length > 0) {\n throw new OpenXmlIoError('createZipWriter: stream error during end', { cause: errors[0] });\n }\n },\n };\n },\n\n async finalize() {\n if (finalised !== undefined) return finalised;\n if (streamingOpen) {\n throw new OpenXmlIoError('createZipWriter: cannot finalize while a streaming entry is open');\n }\n finalised = (async () => {\n try {\n if (!endCalled) {\n zip.end();\n endCalled = true;\n }\n } catch (cause) {\n throw new OpenXmlIoError('createZipWriter: failed to finalize zip archive', { cause });\n }\n await zipFinishPromise;\n if (errors.length > 0) {\n throw new OpenXmlIoError('createZipWriter: stream error during finalize', { cause: errors[0] });\n }\n\n // Apply the ZIP64 patch to fflate's [CD | EOCD] tail when the entry\n // count exceeds ZIP32's 16-bit cap, then flush the (possibly patched)\n // tail to the sink.\n if (finalChunk) {\n const patched =\n seen.size > ZIP32_MAX_ENTRIES\n ? applyZip64EntryCountPatch(finalChunk, seen.size)\n : finalChunk;\n writer.write(patched);\n }\n return writer.finish();\n })();\n return finalised;\n },\n\n abort(cause?: unknown): void {\n if (finalised !== undefined) return;\n // Mark finalised so any subsequent addEntry / finalize short-circuits.\n finalised = Promise.resolve(new Uint8Array(0));\n // Drop fflate's listener — we don't care about further `ondata` callbacks.\n if (zipFinishResolve) {\n zipFinishResolve();\n zipFinishResolve = undefined;\n }\n writer.abort?.(cause);\n },\n };\n}\n"],"mappings":"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"}