@sheetxl/io
Version:
IO - Import/Export Libraries for SheetXL.
237 lines (236 loc) • 11.9 kB
JavaScript
/**
* @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
};