@sheetxl/scripting
Version:
Scripting - Scripting engine for Macros and formulas; includes TypeScript and EsBuild.
265 lines (264 loc) • 13.4 kB
JavaScript
import { ScalarType as v } from "@sheetxl/primitives";
import { CommonUtils as ae } from "@sheetxl/utils";
/**
* @license @sheetxl/scripting - Scripting - Scripting engine for Macros and formulas; includes TypeScript and EsBuild. - v0.7.5
*
* (C) 2025-present SheetXL Inc. & Michael T. Ford
* License: The license can be found at https://www.sheetxl.com/license.
*/
let L = null, P = null;
const oe = { compilerOptions: { target: "esnext" } };
async function le(h, x, S = "/script.js", w = "__SHEETXL") {
try {
const $ = await (async function() {
if (L) return L;
if (P) {
if (await P, !L) throw new Error("ESBuild initialization promise resolved, but instance is not available.");
return L;
}
let p, b;
P = new Promise((a, T) => {
p = a, b = T;
});
try {
const { initialize: a } = await import("./CLaQMrnjmIokLq8K.mjs");
return L = await a(), p(), L;
} catch (a) {
throw console.error("Failed to import or initialize esbuild:", a), P = null, b(a), a;
}
})(), A = "@sheetxl/primitives", n = `
export const FormulaContext = globalThis.${w}?.FormulaContext;
export const ScalarType = globalThis.${w}?.ScalarType;
export const Observable = globalThis.${w}?.Observable;
export const IRange = globalThis.${w}?.IRange;
export const FormulaError = globalThis.${w}?.FormulaError;
// Add more exports as needed
`, F = { name: "sheetxl-esbuild-in-memory", setup(p) {
const b = "sheetxl-" + (/* @__PURE__ */ new Date()).getTime();
p.onResolve({ filter: new RegExp(`^(${S.replace("/", "\\/")}|${A})$`) }, (a) => ({ path: a.path, namespace: b })), p.onResolve({ filter: /.*/ }, (a) => {
if (a.namespace !== b) return console.warn(`esbuild: Treating import "${a.path}" as external.`), { path: a.path, external: !0 };
}), p.onLoad({ filter: /.*/, namespace: b }, (a) => {
let T;
if (a.path === S) T = x;
else {
if (a.path !== A) return { errors: [{ text: `Cannot load unknown path in ${b}: ${a.path}` }] };
T = n;
}
return { contents: T, loader: "ts" };
});
} }, f = await $.build({ entryPoints: [S], bundle: !0, write: !1, format: "esm", plugins: [F], sourcemap: "inline", tsconfigRaw: oe, minify: !0, platform: "neutral" });
if (f.outputFiles && f.outputFiles.length > 0) return f.outputFiles[0].text;
throw f.errors && f.errors.length > 0 ? new Error(`esbuild bundling failed: ${f.errors.map((p) => p.text).join(`
`)}`) : new Error("esbuild did not produce an output file.");
} catch ($) {
throw console.error("esbuild bundling process failed:", $), $;
}
}
const se = async () => `
interface FirstTest {
isTrue?: boolean;
}
`, Y = /* @__PURE__ */ new Map([["IReferenceRange", "r"], ["IRange", "l"]]), Z = /* @__PURE__ */ new Map([["IWorkbook", "workbook"], ["ISheet", "sheet"], ["ICellRanges", "ranges"], ["ICellRange", "range"], ["IFormulaContext", "context"]]), q = (h, x) => {
Array.from(x.keys()).forEach((S) => {
const w = x.get(S);
x.set(`${h}.${S}`, w);
});
}, ce = /* @__PURE__ */ new Map([["Scalar", "*"], ["FormulaError.Known", v.Error], ["Date", "Date"], ["JSON", "JSON"]]), de = /* @__PURE__ */ new Map([]), X = "SheetXL";
q(X, Y), q(X, Z), q(X, de);
const ue = /* @__PURE__ */ new Map([["Promise", () => ({ async: !0 })], ["Observable", () => ({ stream: !0 })]]);
let B = null;
async function pe() {
if (B) return B;
try {
return await (await import("./LYfAHJf8uPzK2Nat.mjs")).initialize();
} catch (h) {
throw B = null, h;
} finally {
B = null;
}
}
async function ye(h) {
const x = h?.source ?? null;
if (!x) return null;
const S = (h.disableBundle || h.declarationsOnly) ?? !1, w = [se(), pe()], $ = await Promise.all(w), A = $[0], n = $[1];
let F = "", f = null;
const p = [], b = { allowJs: !0, declaration: !1, sourceMap: !1, inlineSourceMap: !1, inlineSources: !1, isolatedModules: !0, preserveConstEnums: !1, module: 99, noResolve: !0, emitDeclarationOnly: !1, target: n.ScriptTarget.ES2020 }, a = "script", T = `${a}.ts`, _ = "lib.d.ts", H = "global.d.ts", R = { [T]: x, [_]: `
/**
* Represents the completion of an asynchronous operation
*/
interface Promise<T> {
/**
* Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The
* resolved value cannot be modified from the callback.
* @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected).
* @returns A Promise for the completion of the callback.
*/
finally(onfinally?: (() => void) | undefined | null): Promise<T>;
}
`, [H]: A }, ee = { getSourceFile: (e, t, u, m) => n.createSourceFile(e, R[e], n.ScriptTarget.Latest, !0), fileExists: (e) => R[e] !== void 0, readFile: (e) => R[e], writeFile: (e, t) => {
R[e] = t;
}, getCurrentDirectory: () => "./", getCanonicalFileName: (e) => e, useCaseSensitiveFileNames: () => !0, getDefaultLibFileName: (e) => _, getNewLine: () => `
` }, J = n.createProgram([T, H], b, ee), I = J.getTypeChecker(), te = J.getSourceFile(T), W = J.emit();
W.diagnostics.length > 0 && console.warn(W.diagnostics), F = R[`${a}.js`];
const O = (e, t, u, m) => {
if (e) {
if (e.kind === n.SyntaxKind.NumberKeyword) t.scalar = v.Number;
else if (e.kind === n.SyntaxKind.StringKeyword) t.scalar = v.String;
else if (e.kind === n.SyntaxKind.BooleanKeyword) t.scalar = v.Boolean;
else if (e.kind === n.SyntaxKind.UndefinedKeyword || e.kind === n.SyntaxKind.NullKeyword || e.kind === n.SyntaxKind.VoidKeyword) {
if (m) return void k(e, new Error(`'undefined' is not a valid type for input: '${e?.parent?.name?.escapedText}'.`));
t.scalar = v.Null;
} else if (e.kind === n.SyntaxKind.BigIntKeyword) t.scalar = v.Number;
else if (e.kind === n.SyntaxKind.AnyKeyword) t.scalar = v.Null;
else if (e.kind === n.SyntaxKind.ArrayType) {
const o = e.elementType;
if (!o) return void k(e, new Error(`'Array' must be typed: '${e?.parent?.name?.escapedText}'.`));
t.arrayDepth = (t.arrayDepth ?? 0) + 1, O(o, t, u, m);
} else if (e.kind !== n.SyntaxKind.TupleType) {
if (e.kind === n.SyntaxKind.TypeReference) {
const o = e.typeName?.getText?.() ?? null, M = Y.get(o);
let E = !1;
M && (t.range = M, E = !0);
const z = ce.get(o);
if (z && (t.scalar = z), z !== void 0 && (E = !0), m) {
const r = Z.get(o);
if (r) return r;
} else {
const r = ue.get(o);
if (r) {
const l = { ...t, ...r() };
let y = 0;
if (l.async && y++, l.stream && y++, y > 1) return void k(e, new Error(`'${o}' cannot have multiple modifiers: '${e?.parent?.name?.escapedText}'.`));
t = l, E = !0;
}
}
if (!E) return void k("node", new Error(`'${o}' is not a valid type: '${e?.parent?.name?.escapedText}'.`));
const d = e.typeArguments;
if (d) {
if (d.length !== 1) return void k(e, new Error(`'${o}' must be typed with exactly 1 type: '${e?.parent?.name?.escapedText}'.`));
O(d[0], t, u, m);
}
}
}
} else k(e, new Error(`Type is not defined for '${t?.name ?? "return"}'.`));
}, C = [], k = (e, t) => {
C.push(t);
};
if (n.forEachChild(te, (e) => {
if (((t) => (n.getCombinedModifierFlags(t) & n.ModifierFlags.Export) !== 0)(e) && n.isFunctionDeclaration(e)) {
const t = {}, u = { parameters: {} }, m = e?.name?.getText();
try {
t.name = m;
const o = I.getSymbolAtLocation(e.name).getDocumentationComment(I);
if (o && o.length > 0 && o[0].text) {
let d = o[0].text;
d = d.replace(/[\r\n]+/g, "\\n").trim(), u.summary = d;
}
const M = {};
O(e.type, M, t, !1), t.returnType = M;
const E = {};
((d) => (n.getCombinedModifierFlags(d) & n.ModifierFlags.Default) !== 0)(e) && (E.default = !0, f = m), Object.keys(E).length > 0 && (t.behavior = E), t.parameters = [];
const z = /* @__PURE__ */ new Map();
for (let d = 0; d < e.parameters.length; d++) {
const r = e.parameters[d], l = {};
l.name = r.name?.getText();
const y = O(r.type, l, t, !0);
if (y) {
if (t.parameters.length !== 0) {
const D = e?.parent, c = D?.name?.getText();
return void k(e, new Error(`'${t.name}' contexts must be the first parameter: '${c}'.`));
}
t.context = y;
continue;
}
let g;
if ((r.initializer !== void 0 && r.initializer !== null || r.questionToken !== void 0 && r.questionToken !== null) && (l.optional = !0, r.initializer)) try {
g = r.initializer.kind === n.SyntaxKind.StringLiteral ? r.initializer.text : r.initializer.kind === n.SyntaxKind.NumericLiteral ? parseFloat(r.initializer.text) : r.initializer.kind === n.SyntaxKind.TrueKeyword || r.initializer.kind === n.SyntaxKind.FalseKeyword ? r.initializer.kind === n.SyntaxKind.TrueKeyword : r.initializer.kind === n.SyntaxKind.NullKeyword ? null : r.initializer.kind === n.SyntaxKind.ObjectLiteralExpression || r.initializer.kind === n.SyntaxKind.ArrayLiteralExpression ? r.initializer.getText() : r.initializer.getText?.();
} catch (D) {
console.warn(`Couldn't extract default value for parameter '${l.name}'`, D);
}
r.dotDotDotToken && (l.rest = !0), t.parameters.push(l);
const s = { description: "" };
u.parameters[l.name] = s;
const i = I.getSymbolAtLocation(r.name).getDocumentationComment(I);
i && i.length > 0 && i[0].text && (s.description = i[0].text), g !== void 0 && (s.defaultValue = g), z.set(l.name, l);
}
if (e.jsDoc && e.jsDoc.length > 0) {
const d = e.jsDoc;
for (let r = 0; r < d.length; r++) {
const l = d[r]?.tags;
if (l) for (let y = 0; y < l.length; y++) {
const g = l[y];
let s = g?.tagName?.text;
if (!s) continue;
s = s.toLowerCase();
let i = g.comment;
const D = s === "hidden";
if ((typeof i == "string" || D) && (typeof i == "string" && (i = i.replace(/[\r\n]+/g, "\\n").trim()), D || !i || (i = i.split(/\\n/)[0], i && i.length !== 0))) {
if (i && typeof i == "string") {
const c = /\{@link(code|plain)?\s+([^}|]+)(?:\s*\|\s*([^}]+))?\}/g;
let K, N = i, j = [];
for (; (K = c.exec(i)) !== null; ) {
const [U, V, re, Q] = K, ie = [re.trim()];
Q && ie.push(Q.trim());
}
i = N, j.length > 0 && s === "see" && (u.links || (u.links = []), u.links.push(...j));
}
if (s === "name") {
const c = i;
c !== m && (u.name = c);
} else if (s !== "description") {
if (s === "summary") {
const c = i;
c && (u.summary = c);
} else if (s === "param") {
const c = g.name?.text, K = z.get(c);
if (!K) {
C.push(new Error(`Parameter '${c}' not found in function '${m}'.`));
continue;
}
if (g.typeExpression && g.typeExpression.type) try {
const N = g.typeExpression.type;
if (N.kind === n.SyntaxKind.UnionType) {
const j = [];
K.enums = j, N.types.forEach((U) => {
if (U.kind === n.SyntaxKind.LiteralType) {
const V = U.literal.text;
V && j.push(V);
}
});
}
} catch (N) {
console.warn("Error parsing JSDoc type expression:", N);
}
} else if (s === "returns" || s === "return") t.returnType.description = i;
else if (s === "category") u.category = i;
else if (s === "hidden") {
let c = !0;
const K = i?.toLowerCase();
K === "false" ? c = !1 : K !== "true" && (c = i), c !== !1 && (u.hidden = c ?? !0);
}
}
}
}
}
}
Object.keys(t.returnType).length === 0 && delete t.returnType, p.push([t, u]);
} catch (o) {
k(e, new Error(`'${m}': ${o.message}`));
}
}
}), C.length > 0) throw console.warn(C), new Error("There were compilation errors.", { cause: C });
if (p.length === 0) throw new Error("No exported functions.");
const ne = `${ae.uuidV4()}-script`;
try {
S || C.length !== 0 || (F = await le(0, F, a));
} catch {
console.warn("Error bundling script");
}
const G = { functions: p, commitId: ne, source: x, name: "Script", language: "typescript", compiled: F };
return f && (G.autoRun = f), G;
}
export {
ye as compileModule
};