@sheetxl/io
Version:
IO - Import/Export Libraries for SheetXL.
232 lines (231 loc) • 11.7 kB
JavaScript
/**
* @license @sheetxl/io - IO - Import/Export Libraries for SheetXL. - v0.7.27
*
* (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", "json"], isDefault: true, handler: async (e2, t2) => (await import("./VUIjKANo4QVIKBlI.mjs")).readBufferSXL(e2, t2) }, { key: "CSV", description: "Comma Delimited", mimeType: "text/csv", exts: ["csv"], handler: async (e2, t2) => (await import("./CxZwQdVNPX28b1YR.mjs")).readBufferCSV(e2, t2) }, { key: "Excel", description: "Excel Workbook", mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", exts: ["xlsx", "xls", "xlsm"], handler: async (e2, t2) => (await import("./Bl-w2fv5_elyht4Z.mjs").then((e3) => e3.H)).readBufferXLSX(e2, t2) }], a = [{ key: "SheetXL", mimeType: "application/vnd.sheetxl.sheet", description: "SheetXL", exts: ["sxl", "json"], isDefault: true, async handler(e2, t2) {
"json" === t2?.format && (t2 = { compress: false, ...t2 });
return (await import("./VUIjKANo4QVIKBlI.mjs")).writeBufferSXL(e2, t2);
} }, { key: "CSV", mimeType: "text/csv", description: "Comma Delimited", exts: ["csv"], handler: async (e2, t2) => (await import("./CxZwQdVNPX28b1YR.mjs")).writeBufferCSV(e2, t2) }, { key: "Excel", mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", description: "Excel Workbook", exts: ["xlsx"], tags: ["SheetJS Pro"], handler: async (e2, t2) => (await import("./Bl-w2fv5_elyht4Z.mjs").then((e3) => e3.H)).writeBufferXLSX(e2, t2) }];
class s {
constructor(e2 = o, t2 = a) {
this._readFormats = [], this._writeFormats = [], this._readFormats = Object.freeze([...e2]), this._writeFormats = Object.freeze([...t2]);
}
async getReadFormats(e2) {
return e2 ? this._filterFormats(e2, this._readFormats) : [...this._readFormats];
}
async getWriteFormats(e2) {
return this._writeFormats ? e2 ? this._filterFormats(e2, this._writeFormats) : [...this._writeFormats] : [];
}
async writeArrayBuffer(e2, t2) {
const r2 = (await this.getWriteFormats({ search: t2?.format ?? "slx" }))[0];
return this._writeArrayBuffer(e2, r2, t2);
}
async read(r2) {
if (!r2) throw new Error("'options' must be provided for read.");
let o2 = r2.source;
if (!o2) throw new Error("'options.source' must be provided for read.");
let a2, s2 = r2.name, i2 = r2.format;
!i2 && s2 && (a2 = t.getFileNameExtension(s2)), "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.");
const f2 = this, c2 = async (e2, t2, o3) => {
if (!e2 && !t2) throw new Error("Either format or file extension must be provided to determine read type.");
const a3 = (await f2.getReadFormats({ search: e2, ext: t2 }))[0];
if (!a3) throw new Error(`No read format available for '${r2.format ?? t2}' input.`);
delete (r2 = { ...r2, ...r2?.typedCreateWorkbookOptions?.[a3.key] }).typedCreateWorkbookOptions;
const i3 = s2 ?? o3 ?? `read-${n2}`;
r2.createWorkbookOptions = { ...r2.createWorkbookOptions || {}, name: i3 }, void 0 !== r2.readonly && (r2.createWorkbookOptions = { readonly: r2.readonly, ...r2.createWorkbookOptions }, delete r2.readonly);
const c3 = r2?.progress?.onStart;
return c3 && await Promise.resolve(c3({ format: a3, name: i3 })), a3;
}, l = async (e2, t2, r3) => {
const o3 = await Promise.resolve(e2), a3 = await this._readArrayBuffer(o3, t2, r3);
return r3?.progress?.onComplete?.(), a3;
};
switch (n2) {
case "file": {
const e2 = o2, a3 = e2?.name;
let s3 = "";
a3 && (s3 = `${t.getBaseName(a3)}`);
const n3 = await c2(i2, t.getFileNameExtension(a3), s3);
return l(e2.arrayBuffer(), n3, r2);
}
case "blob": {
const e2 = await c2(i2, a2);
return l(o2.arrayBuffer(), e2, r2);
}
case "base64": {
const t2 = await c2(i2, a2);
let s3;
if (o2 && "object" == typeof o2 && "base64" in o2) s3 = o2.base64;
else if ("string" == typeof o2 && o2.startsWith("data:")) {
const [, e2] = o2.split(",");
s3 = e2;
} else s3 = o2;
return l(e.base64ToArrayBuffer(s3), t2, r2);
}
case "fetch": {
let e2, s3, n3 = null;
if ("string" == typeof o2) n3 = o2;
else {
if (!o2 || "object" != typeof o2 || !("input" in o2)) throw new Error("Invalid fetch source provided.");
{
const t2 = o2;
n3 = t2.input, e2 = t2.init, s3 = t2.timeout;
}
}
const f3 = s3 || 3e4, m = new AbortController(), d = setTimeout(() => m.abort(), f3), u = "string" == typeof n3 ? n3 : n3.toString(), p = a2 || t.getFileNameExtension(u), h = await c2(i2, p, t.getBaseName(u, true));
try {
const t2 = await fetch(n3, { ...e2, signal: m.signal });
if (clearTimeout(d), !t2.ok) throw new Error(`Failed to fetch: ${t2.status} ${t2.statusText}`);
const o3 = await t2.arrayBuffer();
if (!o3) throw new Error(`Unable to fetched content: ${u}`);
return l(o3, h, r2);
} catch (e3) {
if (clearTimeout(d), "AbortError" === e3.name) throw new Error(`Fetch timeout after ${f3}ms: ${u}`);
throw e3;
}
}
case "buffer":
return l(o2, await c2(i2, a2), r2);
case "stream": {
const e2 = await c2(i2, a2), t2 = o2.getReader(), s3 = [];
let n3 = 0;
try {
for (; ; ) {
const { done: e3, value: r3 } = await t2.read();
if (e3) break;
s3.push(r3), n3 += r3.length;
}
} finally {
t2.releaseLock();
}
const f3 = new ArrayBuffer(n3), m = new Uint8Array(f3);
let d = 0;
for (const e3 of s3) m.set(e3, d), d += e3.length;
return l(f3, e2, r2);
}
default:
throw new Error(`Unsupported source type: ${n2}`);
}
}
async writeFile(e2, r2, o2) {
if (!e2) throw new Error("File name must be provided.");
if (!r2) throw new Error("Workbook must be provided.");
if (!r2.isIWorkbook) throw new Error("Invalid workbook model provided. Must be an instance of IWorkbook.");
const a2 = t.getFileNameExtension(e2).toLowerCase();
a2 && (e2 = e2.slice(0, e2.length - a2.length - 1));
const s2 = (await this.getWriteFormats({ search: o2?.format, ext: a2 }))[0];
if (!s2) throw new Error(`Unable to determine write type for '${e2}'.`);
const i2 = e2 + "." + (a2 || s2.exts[0]);
let n2 = null;
try {
n2 = await this._writeArrayBuffer(r2, s2, o2);
} 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);
})(i2, n2);
} catch (e3) {
throw new Error("Unable to write file.", { cause: e3 });
}
return o2?.progress?.onComplete?.(), true;
}
async registerReadFormat(e2) {
this._registerFormatType(e2, this._readFormats);
}
async registerWriteFormat(e2) {
this._registerFormatType(e2, this._writeFormats);
}
async _registerFormatType(e2, t2) {
if (!e2) throw new Error("format must be provided.");
}
_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" : "undefined" != typeof Blob && e2 instanceof Blob ? "blob" : e2 instanceof ArrayBuffer || ArrayBuffer.isView(e2) ? "buffer" : "undefined" != typeof ReadableStream && e2 instanceof ReadableStream ? "stream" : null;
}
_filterFormats(e2, t2, r2) {
if (!e2 || 0 === Object.keys(e2).length) {
if (!r2) return [...t2];
e2 = { ext: r2 };
}
const o2 = e2.search?.toLocaleLowerCase();
return t2.filter((t3) => {
if (o2) {
const e3 = t3.key.toLocaleLowerCase().includes(o2), r3 = !!t3.exts && t3.exts.some((e4) => e4.toLocaleLowerCase().includes(o2)), a3 = !!t3.mimeType && t3.mimeType.toLocaleLowerCase().includes(o2), s2 = !!t3.tags && t3.tags.some((e4) => e4.toLocaleLowerCase().includes(o2)), i2 = !!t3.description && t3.description.toLocaleLowerCase().includes(o2);
if (!(e3 || r3 || a3 || s2 || i2)) return false;
}
const a2 = e2.ext || r2;
if (a2) {
const e3 = a2.toLocaleLowerCase();
if (!t3.exts.some((t4) => t4.toLocaleLowerCase() === e3)) return false;
}
if (e2.mimeType && t3.mimeType !== e2.mimeType) return false;
if (e2.key && t3.key.toLocaleLowerCase() !== e2.key.toLocaleLowerCase()) return false;
if (void 0 !== e2.isDefault && t3.isDefault !== e2.isDefault) return false;
if (e2.tags) {
const r3 = t3.tags || [];
if (!("string" == typeof e2.tags ? [e2.tags] : e2.tags).every((e3) => r3.includes(e3))) return false;
}
return true;
});
}
async _writeArrayBuffer(e2, t2, r2) {
if (!t2) throw new Error(`Invalid write type for '${t2}'.`);
try {
const o2 = t2.handler;
if (!o2) throw new Error(`Unable to resolve handler for type: ${t2.description ?? t2}.`);
return o2(e2, r2);
} catch (e3) {
throw new Error(`Unable to load handler for '${t2}.'`, { cause: e3 });
}
}
async _readArrayBuffer(e2, t2, r2 = null) {
if (!e2) throw new Error("ArrayBuffer must be specified.");
if (!t2) throw new Error("format must be specified.");
const o2 = t2.handler;
if (!o2) throw new Error(`Unable to resolve handler for format type: ${t2?.description ?? t2}.`);
let a2;
try {
a2 = await o2(e2, r2);
} catch (e3) {
throw new Error("Unable to read", { cause: e3 });
}
return a2;
}
}
const i = new s(), n = /^(con|prn|aux|nul|com\d|lpt\d)$/i, f = /[<>:"/\\|?*\u0000-\u001F]/g, c = Object.freeze(Object.defineProperty({ __proto__: null, MAX_WORKBOOK_NAME_SIZE: 96, WINDOW_FILENAME_CHAR_RESERVED_REGEX: f, WINDOW_FILENAME_RESERVED_REGEX: n, isValidWindowsFilename: (e2) => !(!e2 || e2.length > 255) && (!f.test(e2) && !n.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 {
s as DefaultWorkbookIO,
c as IOUtils,
i as WorkbookIO
};