UNPKG

@sheetxl/io

Version:

IO - Import/Export Libraries for SheetXL.

237 lines (236 loc) 11.9 kB
/** * @license @sheetxl/io - IO - Import/Export Libraries for SheetXL. - v0.7.5 * * (C) 2025-present SheetXL Inc. & Michael T. Ford * License: The license can be found at https://www.sheetxl.com/license. */ import { BufferUtils as e } from "@sheetxl/utils"; import { TextUtils as t } from "@sheetxl/sdk"; import r from "path"; const o = [{ key: "SheetXL", description: "SheetXL", mimeType: ".sxl", exts: ["sxl"], isDefault: true, handler: async (e2, t2) => (await import("./A1Gl-9PqHjVs_JL5.mjs")).fromBufferJSON(e2, t2) }, { key: "CSV", description: "Comma Delimited", mimeType: "text/csv", exts: ["csv"], handler: async (e2, t2) => (await import("./Bf9iMmIXENzdyJ9a.mjs")).fromBufferCSV(e2, t2) }, { key: "Excel", description: "Excel Workbook", mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", exts: ["xlsx", "xls", "xlsm"], handler: async (e2, t2) => (await import("./CaMMfYYKHYs03fiz.mjs").then((e3) => e3.i)).fromBufferXLSX(e2, t2) }], i = [{ key: "SheetXL", mimeType: "application/vnd.sheetxl.sheet", description: "SheetXL", ext: "sxl", isDefault: true, handler: async (e2, t2) => (await import("./A1Gl-9PqHjVs_JL5.mjs")).toBufferJSON(e2, t2) }, { key: "CSV", mimeType: "text/csv", description: "Comma Delimited", ext: "csv", handler: async (e2, t2) => (await import("./Bf9iMmIXENzdyJ9a.mjs")).toBufferCSV(e2, t2) }, { key: "Excel", mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", description: "Excel Workbook", ext: "xlsx", tags: ["SheetJS Pro"], handler: async (e2, t2) => (await import("./CaMMfYYKHYs03fiz.mjs").then((e3) => e3.i)).toBufferXLSX(e2, t2) }]; class a { constructor(e2 = o, t2 = i) { this._readFormatTypes = [], this._writeFormatType = [], this._readFormatTypes = Object.freeze([...e2]), this._writeFormatType = Object.freeze([...t2]); } _detectImportSourceType(e2) { return e2 && "object" == typeof e2 && "base64" in e2 ? "base64" : e2 && "object" == typeof e2 && "input" in e2 ? "fetch" : "string" == typeof e2 ? e2.startsWith("data:") ? "base64" : (e2.startsWith("http://") || e2.startsWith("https://") || e2.startsWith("/") || e2.startsWith("./") || e2.startsWith("../"), "fetch") : "undefined" != typeof File && e2 instanceof File ? "file" : e2 instanceof ArrayBuffer || ArrayBuffer.isView(e2) ? "buffer" : "undefined" != typeof ReadableStream && e2 instanceof ReadableStream ? "stream" : null; } getReadFormats() { return this._readFormatTypes; } getWriteFormats() { return this._writeFormatType; } getReadFormatTypeForKey(e2) { return this._readFormatTypes.find((t2) => t2.key.includes(e2)) ?? null; } getReadFormatTypeForExt(e2) { return e2 ? (e2 = e2.toLowerCase(), this._readFormatTypes.find((t2) => t2.exts.includes(e2)) ?? null) : null; } getReadFormatTypeForMimeType(e2) { return this._readFormatTypes.find((t2) => t2.mimeType === e2) ?? null; } getWriteFormatTypeForExt(e2) { return e2 ? (e2 = e2.toLowerCase(), this._writeFormatType.find((t2) => t2.ext === e2) ?? null) : null; } getWriteFormatType(e2) { if (!e2) return null; e2 = e2.toLowerCase(); let t2 = this._writeFormatType.find((t3) => t3.ext === e2) ?? null; return t2 || (t2 = this._writeFormatType.find((t3) => t3.key.toLowerCase() === e2) ?? null, t2 || (this._writeFormatType.find((t3) => t3.mimeType.toLowerCase() === e2) ?? null)); } getAllReadFormatTypeAsString() { const e2 = [], t2 = this._readFormatTypes.length; for (let r2 = 0; r2 < t2; r2++) e2.push(this._readFormatTypes[r2].mimeType); return e2; } async toArrayBuffer(e2, t2, r2) { const o2 = this.getWriteFormatType(t2); if (!o2) throw new Error(`Invalid export type for '${t2}'.`); try { const i2 = o2.handler; if (!i2) throw new Error(`Unable to resolve handler for type: ${o2.description ?? t2}.`); return i2(e2, r2); } catch (e3) { throw new Error(`Unable to load handler for '${t2}.'`, { cause: e3 }); } } async _fromArrayBuffer(e2, t2, r2 = null) { let o2 = this.getReadFormatTypeForKey(t2) ?? this.getReadFormatTypeForExt(t2) ?? this.getReadFormatTypeForMimeType(t2); if (!e2 || !o2) { if (!e2) throw new Error("ArrayBuffer must be specified."); if (!t2) throw new Error("formatKey must be specified."); } const i2 = o2.handler; if (!i2) throw new Error(`Unable to resolve handler for type: ${o2?.description ?? t2}.`); const a2 = { ...r2, ...r2?.typedCreateWorkbookOptions?.[t2] }; let n2; delete a2.typedCreateWorkbookOptions; try { n2 = await i2(e2, a2); } catch (e3) { throw new Error("Unable to import", { cause: e3 }); } return n2; } async read(r2) { if (!r2) throw new Error("'options' must be provided for load."); let o2 = r2.source; if (!o2) throw new Error("'options.source' must be provided for load."); const i2 = r2.name; let a2 = r2.formatType; !a2 && i2 && (a2 = t.getFileNameExtension(i2)), "function" == typeof o2 && (o2 = o2()), o2 && "object" == typeof o2 && "function" == typeof o2.then && (o2 = await Promise.resolve(o2)); const n2 = this._detectImportSourceType(o2); if (!n2) throw new Error("Unable to detect source type from provided input."); switch (n2) { case "file": { const e2 = o2; return await this._fromFile(e2, r2); } case "base64": { let t2; if (o2 && "object" == typeof o2 && "base64" in o2) t2 = o2.base64; else if ("string" == typeof o2 && o2.startsWith("data:")) { const [, e2] = o2.split(","); t2 = e2; } else t2 = o2; const n3 = e.base64ToArrayBuffer(t2), s2 = this.getReadFormatTypeForExt(a2) || this._readFormatTypes[0]; if (!s2) throw new Error("No import type available for base64 input."); return { workbook: await this._fromArrayBuffer(n3, s2.key, r2), title: i2 || "imported-file", formatType: s2 }; } case "fetch": { let e2, n3, s2 = null; if ("string" == typeof o2) s2 = o2; else { if (!o2 || "object" != typeof o2 || !("input" in o2)) throw new Error("Invalid fetch source provided."); { const t2 = o2; s2 = t2.input, e2 = t2.init, n3 = t2.timeout; } } const f2 = n3 || 3e4, l2 = new AbortController(), m2 = setTimeout(() => l2.abort(), f2), p = "string" == typeof s2 ? s2 : s2.toString(), c = a2 || t.getFileNameExtension(p), y = this.getReadFormatTypeForExt(c) || this._readFormatTypes[0]; try { const o3 = await fetch(s2, { ...e2, signal: l2.signal }); if (clearTimeout(m2), !o3.ok) throw new Error(`Failed to fetch: ${o3.status} ${o3.statusText}`); const a3 = await o3.arrayBuffer(); if (!y) throw new Error(`Unable to determine import type for fetched content: ${p}`); return { workbook: await this._fromArrayBuffer(a3, y.key, r2), title: i2 || t.getBaseName(p, true) || "fetched-file", formatType: y }; } catch (e3) { if (clearTimeout(m2), "AbortError" === e3.name) throw new Error(`Fetch timeout after ${f2}ms: ${p}`); throw e3; } } case "buffer": { const e2 = o2, t2 = this.getReadFormatTypeForExt(a2) || this._readFormatTypes[0]; if (!t2) throw new Error("No import type available for buffer input."); return { workbook: await this._fromArrayBuffer(e2, t2.key, r2), title: i2 || "buffer-file", formatType: t2 }; } case "stream": { const e2 = o2.getReader(), t2 = []; let n3 = 0; try { for (; ; ) { const { done: r3, value: o3 } = await e2.read(); if (r3) break; t2.push(o3), n3 += o3.length; } } finally { e2.releaseLock(); } const s2 = new ArrayBuffer(n3), f2 = new Uint8Array(s2); let l2 = 0; for (const e3 of t2) f2.set(e3, l2), l2 += e3.length; const m2 = this.getReadFormatTypeForExt(a2) || this._readFormatTypes[0]; if (!m2) throw new Error("No import type available for stream input."); return { workbook: await this._fromArrayBuffer(s2, m2.key, r2), title: i2 || "stream-file", formatType: m2 }; } default: throw new Error(`Unsupported source type: ${n2}`); } } async _fromFile(e2, r2 = null) { let o2 = null; try { let i2 = ""; e2?.name && (i2 = `${t.getBaseName(e2.name)}`); const a2 = this.getReadFormatTypeForExt(t.getFileNameExtension(e2?.name)); if (!a2) throw new Error(`Unknown file type: ${t.getFileNameExtension(e2?.name) ?? e2?.name ?? "(empty)"}.`); const s2 = await e2.arrayBuffer(), f2 = { name: i2, ...r2, ...r2?.typedCreateWorkbookOptions?.[a2.key] }; delete f2.typedCreateWorkbookOptions; const l2 = a2.handler; if (!l2) throw new Error(`Unable to resolve handler for type: ${a2?.description ?? t.getFileNameExtension(e2?.name) ?? e2?.name ?? "(empty)"}.`); const m2 = await l2(s2, f2); o2 = new n(e2, m2, i2, a2); } catch (e3) { throw e3; } return o2; } async writeFile(e2, r2, o2) { if (!r2 || !e2) throw new Error("Workbook model or file name must be provided."); if (!r2.isIWorkbook) throw new Error("Invalid workbook model provided. Must be an instance of IWorkbook."); const i2 = t.getFileNameExtension(e2); i2 && (e2 = e2.slice(0, e2.length - i2.length - 1)); let a2 = null; o2?.formatType && (a2 = this.getWriteFormatType(o2.formatType)); const n2 = this.getWriteFormats(), s2 = n2.length; for (let e3 = 0; !a2 && e3 < s2; e3++) (n2[e3].ext === i2 || !i2 && n2[e3].isDefault) && (a2 = n2[e3]); if (!a2) throw new Error(`Unable to determine export type for '${e2}'.`); const f2 = e2 + "." + a2.ext; let l2 = null; try { l2 = await this.toArrayBuffer(r2, a2.key); } catch (e3) { throw "string" == typeof e3 ? new Error(e3) : e3; } try { await (async (e3, t2) => { const r3 = await import( /* @vite-ignore */ /* webpackIgnore: true */ "fs/promises" ), o3 = Buffer.from(t2); await r3.writeFile(e3, o3); })(f2, l2); } catch (e3) { throw new Error("Unable to write file.", { cause: e3 }); } return true; } } class n { constructor(e2, t2, r2, o2) { this.file = e2, this.workbook = t2, this.title = r2, this.formatType = o2; } get [Symbol.toStringTag]() { return "[WorkbookHandle]"; } toString() { return `'${this.file.name}' ${this.file.size} (${this.formatType.description})`; } } const s = new a(), f = /^(con|prn|aux|nul|com\d|lpt\d)$/i, l = /[<>:"/\\|?*\u0000-\u001F]/g, m = Object.freeze(Object.defineProperty({ __proto__: null, MAX_WORKBOOK_NAME_SIZE: 96, WINDOW_FILENAME_CHAR_RESERVED_REGEX: l, WINDOW_FILENAME_RESERVED_REGEX: f, isValidWindowsFilename: (e2) => !(!e2 || e2.length > 255) && (!l.test(e2) && !f.test(e2) && ("." !== e2 && ".." !== e2)), relativePath: (e2, t2) => { try { return new URL(t2), t2; } catch { } if (t2.startsWith("/") || /^[a-zA-Z]:/.test(t2)) return t2; if ("undefined" == typeof window || void 0 === window.document) { if ("undefined" != typeof require && "undefined" != typeof process) return r.resolve(e2, t2); throw new Error("Unsupported environment"); } try { let r2 = e2.startsWith("http") ? e2 : `file:///${e2.replace(/\\/g, "/")}`; r2.endsWith("/") || (r2 += "/"); return new URL(t2, r2).href; } catch { const r2 = document.createElement("a"); let o2 = e2; return o2.endsWith("/") || (o2 += "/"), r2.href = new URL(t2, o2).href, r2.href; } } }, Symbol.toStringTag, { value: "Module" })); export { a as DefaultWorkbookIO, m as IOUtils, s as WorkbookIO };