@sheetxl/runner 0.7.23-beta.1
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.
- package/LICENSE.md +11 -0
- package/README.md +66 -0
- package/licenses/dependencies.txt +1 -0
- package/node/esm/index.mjs +289 -0
- package/package.json +53 -0
- package/types/index.d.ts +6 -0
- package/types/src/RunUtils.d.ts +13 -0
- package/types/src/RunUtils.d.ts.map +1 -0
- package/types/src/Runner.d.ts +18 -0
- package/types/src/Runner.d.ts.map +1 -0
- package/types/src/Snippet.d.ts +89 -0
- package/types/src/Snippet.d.ts.map +1 -0
- package/types/src/Types.d.ts +95 -0
- package/types/src/Types.d.ts.map +1 -0
- package/types/src/index.d.ts +5 -0
- package/types/src/index.d.ts.map +1 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Repository Licensing
|
|
2
|
+
|
|
3
|
+
SheetXL contains a mix of open-source and commercially licensed packages. Each package is individually licensed and contains its own license file.
|
|
4
|
+
|
|
5
|
+
For the specific terms and conditions applicable to a package, please see the `LICENSE.md` file located in that package's root directory.
|
|
6
|
+
|
|
7
|
+
Generally, packages intended for public distribution (such as CLIs, adapters, and vanilla wrappers) are licensed under the MIT license. All other core packages are proprietary and require a commercial license for use.
|
|
8
|
+
|
|
9
|
+
For more details on commercial licensing, please visit our website:
|
|
10
|
+
|
|
11
|
+
https://www.sheetxl.com/docs/guides/licensing-pricing
|
package/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# SheetXL CLI
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://www.sheetxl.com" target="_blank">
|
|
5
|
+
<img src="https://www.sheetxl.com/logo-text.svg" alt="SheetXL Logo" width="180" />
|
|
6
|
+
</a>
|
|
7
|
+
</p>
|
|
8
|
+
# @sheetxl/runner
|
|
9
|
+
|
|
10
|
+
The `SheetXL` runner library enables simple execution of predefined scripts for updating
|
|
11
|
+
workbooks.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm i -D @sheetxl/runner
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Using the runner
|
|
20
|
+
|
|
21
|
+
``` ts
|
|
22
|
+
export type Runner = (workbook: IWorkbook, target: RunTarget | RunTarget[], options?: RunOptions) => Promise<void>;
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
``` ts
|
|
26
|
+
import { Workbook } from '@sheetxl/sdk';
|
|
27
|
+
import { Runner } from '@sheetxl/runner';
|
|
28
|
+
|
|
29
|
+
const wb = new Workbook();
|
|
30
|
+
|
|
31
|
+
await Runner.run(wb, 'scripts/transform.ts', {
|
|
32
|
+
args: ['region=EU']
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Example Runner Script
|
|
38
|
+
|
|
39
|
+
This is a basic runner script. Runners scripts are designed to update a workbook
|
|
40
|
+
the load/saving is handled by the runner.
|
|
41
|
+
|
|
42
|
+
This examples reads the region argument and updates the first cell.
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import Runner, { type RunContext } from '@sheetxl/runner';
|
|
46
|
+
|
|
47
|
+
export default async function main(ctx: RunContext) {
|
|
48
|
+
const { wb, log, args } = ctx;
|
|
49
|
+
wb.getSelectedSheet().getRange('A1').setValue(args.region);
|
|
50
|
+
log('updated value');
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 🔗 Learn More
|
|
55
|
+
|
|
56
|
+
Whether you're ready to build, need help, or just want to see more examples, here's where to go next.
|
|
57
|
+
|
|
58
|
+
* 💬 **[Join our Discord Community](https://discord.gg/NTKdwUgK9p)** - Get help and connect with the team.
|
|
59
|
+
* ⭐ **[Star us on GitHub](https://github.com/sheetxl/sheetxl)** - If you like SheetXL give us a star ⭐ and help others find us!
|
|
60
|
+
* 📘 **[Developer Docs](https://www.sheetxl.com/docs)** - Guides and tutorials.
|
|
61
|
+
* 🔌 **[API Reference](https://api.sheetxl.com)** - Detailed documentation for all packages.
|
|
62
|
+
* 👀 **[Live Demo Gallery](https://www.sheetxl.com/demos)** - A showcase of interactive examples.
|
|
63
|
+
* 🖼️ **[Storybook](https://storybook.sheetxl.com)** - Explore and test individual UI components.
|
|
64
|
+
* 🌐 **[Website](https://www.sheetxl.com)** - Our Website.
|
|
65
|
+
|
|
66
|
+
---
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
No third parties dependencies
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license @sheetxl/runner - SheetXL - Programmatic execution for SheetXL scripts - v0.7.23-beta.1
|
|
3
|
+
*
|
|
4
|
+
* (C) 2026-present SheetXL Inc. & Michael T. Ford
|
|
5
|
+
* License: The license can be found at https://www.sheetxl.com/license.
|
|
6
|
+
*/
|
|
7
|
+
import t from "node:path";
|
|
8
|
+
import e from "node:fs";
|
|
9
|
+
import { pathToFileURL as n } from "node:url";
|
|
10
|
+
import { createLogChannels as r } from "@sheetxl/utils";
|
|
11
|
+
var i = Object.defineProperty;
|
|
12
|
+
function s(e, n = "SHEETXL_IN") {
|
|
13
|
+
if (t.isAbsolute(e)) return e;
|
|
14
|
+
const r = n ? process.env[n] : void 0;
|
|
15
|
+
return t.resolve(r ?? process.cwd(), e);
|
|
16
|
+
}
|
|
17
|
+
var o = ((t, e) => {
|
|
18
|
+
let n = {};
|
|
19
|
+
for (var r in t) i(n, r, {
|
|
20
|
+
get: t[r],
|
|
21
|
+
enumerable: !0
|
|
22
|
+
});
|
|
23
|
+
return e || i(n, Symbol.toStringTag, { value: "Module" }), n;
|
|
24
|
+
})({
|
|
25
|
+
DEFAULT_DESCRIPTION: () => g,
|
|
26
|
+
classify: () => m,
|
|
27
|
+
prepare: () => y
|
|
28
|
+
}), a = null;
|
|
29
|
+
function c() {
|
|
30
|
+
return a || (a = (async () => {
|
|
31
|
+
try {
|
|
32
|
+
const t = await import("typescript");
|
|
33
|
+
return t.default ?? t;
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
})()), a;
|
|
38
|
+
}
|
|
39
|
+
async function l(t) {
|
|
40
|
+
const e = await c();
|
|
41
|
+
if (!e) return null;
|
|
42
|
+
const n = e.createSourceFile("snippet.ts", t, e.ScriptTarget.Latest, !1, e.ScriptKind.TS);
|
|
43
|
+
return (n.parseDiagnostics?.length ?? 0) > 0 ? null : {
|
|
44
|
+
ts: e,
|
|
45
|
+
sf: n
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function u(t, e) {
|
|
49
|
+
return t.text.slice(e.getStart(t), e.end);
|
|
50
|
+
}
|
|
51
|
+
function f(t) {
|
|
52
|
+
return t.endsWith(";") ? t : `${t};`;
|
|
53
|
+
}
|
|
54
|
+
function p(t) {
|
|
55
|
+
let e = 0;
|
|
56
|
+
for (let n = 0; n < t.length; n++) "\n" === t[n] && e++;
|
|
57
|
+
return e;
|
|
58
|
+
}
|
|
59
|
+
function d(t, e) {
|
|
60
|
+
const n = e.getStart(t);
|
|
61
|
+
let r = t.text.slice(n, e.end);
|
|
62
|
+
const i = e.declarationList.declarations;
|
|
63
|
+
for (let e = i.length - 1; e >= 0; e--) {
|
|
64
|
+
const s = i[e].initializer;
|
|
65
|
+
if (!s) continue;
|
|
66
|
+
const o = s.getStart(t) - n, a = s.end - n;
|
|
67
|
+
r = `${r.slice(0, o)}await (${r.slice(o, a)})${r.slice(a)}`;
|
|
68
|
+
}
|
|
69
|
+
return f(r);
|
|
70
|
+
}
|
|
71
|
+
async function m(t) {
|
|
72
|
+
const e = await l(t);
|
|
73
|
+
return e ? function(t, e) {
|
|
74
|
+
for (const n of e.statements) {
|
|
75
|
+
if (t.isExportAssignment(n) && !n.isExportEquals) return !0;
|
|
76
|
+
if (t.canHaveModifiers(n) && t.getModifiers(n)?.some((e) => e.kind === t.SyntaxKind.DefaultKeyword)) return !0;
|
|
77
|
+
if (t.isExportDeclaration(n) && n.exportClause && t.isNamedExports(n.exportClause) && n.exportClause.elements.some((t) => "default" === t.name.text)) return !0;
|
|
78
|
+
}
|
|
79
|
+
return !1;
|
|
80
|
+
}(e.ts, e.sf) ? "script" : "snippet" : function(t) {
|
|
81
|
+
return /^\s*export\s+default\b/m.test(t) || /^\s*export\s*\{[^}]*\bas\s+default\b/m.test(t);
|
|
82
|
+
}(t) ? "script" : "snippet";
|
|
83
|
+
}
|
|
84
|
+
var w = 3, g = "Run Snippet", h = (t, e, n = [], r) => [
|
|
85
|
+
...n,
|
|
86
|
+
...r ? [r] : [],
|
|
87
|
+
"export default async function __snippet(ctx: SheetXL.IScript.ScriptContext): Promise<void> {",
|
|
88
|
+
" const { wb, log, warn, error, args } = ctx as any;",
|
|
89
|
+
" let __result: any = undefined;",
|
|
90
|
+
t,
|
|
91
|
+
" ;",
|
|
92
|
+
e,
|
|
93
|
+
"};"
|
|
94
|
+
].join("\n");
|
|
95
|
+
async function y(t, e) {
|
|
96
|
+
const n = e?.epilogue ?? " return __result;", r = await l(t);
|
|
97
|
+
if (!r) {
|
|
98
|
+
const e = await c() ? void 0 : "TypeScript is unavailable, so this snippet ran without implicit await or a result value. Install the `typescript` peer dependency to restore them.";
|
|
99
|
+
return {
|
|
100
|
+
source: h(t, n),
|
|
101
|
+
kind: "verbatim",
|
|
102
|
+
lineOffset: w,
|
|
103
|
+
warning: e
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const { ts: i, sf: s } = r, o = s.statements, a = function(t, e) {
|
|
107
|
+
if (!e.statements[0]) return;
|
|
108
|
+
const n = t.getLeadingCommentRanges(e.text, 0);
|
|
109
|
+
if (n?.length) for (let r = n.length - 1; r >= 0; r--) {
|
|
110
|
+
const i = n[r];
|
|
111
|
+
if (i.kind !== t.SyntaxKind.MultiLineCommentTrivia) continue;
|
|
112
|
+
const s = e.text.slice(i.pos, i.end);
|
|
113
|
+
if (s.startsWith("/**")) return s;
|
|
114
|
+
}
|
|
115
|
+
}(i, s), m = a ? p(a) + 1 : 0;
|
|
116
|
+
if (1 === o.length && i.isBlock(o[0])) return {
|
|
117
|
+
source: h(` __result = await (\n${t}\n );`, n, [], a),
|
|
118
|
+
kind: "expression",
|
|
119
|
+
lineOffset: w + m + 1
|
|
120
|
+
};
|
|
121
|
+
const { body: g, hoisted: y } = function(t, e, n) {
|
|
122
|
+
const r = e.text, i = e.statements;
|
|
123
|
+
let s = -1;
|
|
124
|
+
for (let e = i.length - 1; e >= 0; e--) if (i[e].kind !== t.SyntaxKind.EmptyStatement) {
|
|
125
|
+
t.isExpressionStatement(i[e]) && (s = e);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
const o = [], a = [];
|
|
129
|
+
let c = 0;
|
|
130
|
+
for (let l = 0; l < i.length; l++) {
|
|
131
|
+
const m = i[l], w = m.getStart(e);
|
|
132
|
+
a.push(r.slice(c, w)), c = m.end;
|
|
133
|
+
const g = r.slice(w, m.end);
|
|
134
|
+
if (t.isImportDeclaration(m) || t.isImportEqualsDeclaration(m)) o.push(g), a.push("\n".repeat(p(g)));
|
|
135
|
+
else if (t.isVariableStatement(m)) a.push(d(e, m));
|
|
136
|
+
else {
|
|
137
|
+
if (t.isExpressionStatement(m)) {
|
|
138
|
+
const t = u(e, m.expression);
|
|
139
|
+
a.push(l === s ? `${n} = await (${t});` : `await (${t});`);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
a.push(f(g));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return a.push(r.slice(c)), {
|
|
146
|
+
body: a.join(""),
|
|
147
|
+
hoisted: o
|
|
148
|
+
};
|
|
149
|
+
}(i, s, "__result"), x = y.length > 0 ? p(y.join("\n")) + y.length : 0;
|
|
150
|
+
return {
|
|
151
|
+
source: h(g, n, y, a),
|
|
152
|
+
kind: "statements",
|
|
153
|
+
lineOffset: w + x + m
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
async function x(t, e, n = "Runner timed out") {
|
|
157
|
+
if (!e || e <= 0) return t;
|
|
158
|
+
let r;
|
|
159
|
+
const i = new Promise((t, i) => r = setTimeout(() => i(new Error(n)), e));
|
|
160
|
+
try {
|
|
161
|
+
return await Promise.race([t, i]);
|
|
162
|
+
} finally {
|
|
163
|
+
clearTimeout(r);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
var S = null;
|
|
167
|
+
function v() {
|
|
168
|
+
return S || (S = (async () => {
|
|
169
|
+
const { register: t } = await import("tsx/esm/api");
|
|
170
|
+
t({ tsconfig: !1 });
|
|
171
|
+
})()), S;
|
|
172
|
+
}
|
|
173
|
+
var b = "data:text/typescript,", $ = "data:text/javascript,", E = null;
|
|
174
|
+
function _() {
|
|
175
|
+
return E || (E = (async () => {
|
|
176
|
+
const { registerHooks: e, stripTypeScriptTypes: r } = await import("node:module"), i = r;
|
|
177
|
+
e({
|
|
178
|
+
resolve(e, r, i) {
|
|
179
|
+
const s = r.parentURL;
|
|
180
|
+
if (s && (s.startsWith(b) || s.startsWith($))) {
|
|
181
|
+
const s = n(t.join(process.cwd(), "_inline_.ts")).href;
|
|
182
|
+
return i(e, {
|
|
183
|
+
...r,
|
|
184
|
+
parentURL: s
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return i(e, r);
|
|
188
|
+
},
|
|
189
|
+
load(t, e, n) {
|
|
190
|
+
if (t.startsWith(b)) {
|
|
191
|
+
const e = decodeURIComponent(t.slice(21)), n = process.emitWarning;
|
|
192
|
+
let r;
|
|
193
|
+
process.emitWarning = () => {};
|
|
194
|
+
try {
|
|
195
|
+
r = i(e, { mode: "transform" });
|
|
196
|
+
} finally {
|
|
197
|
+
process.emitWarning = n;
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
format: "module",
|
|
201
|
+
source: r,
|
|
202
|
+
shortCircuit: !0
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return n(t, e);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
})()), E;
|
|
209
|
+
}
|
|
210
|
+
async function R(e) {
|
|
211
|
+
const r = "string" == typeof (i = e) ? i.startsWith("file:") ? i : n(t.resolve(process.cwd(), i)).href : i.href;
|
|
212
|
+
var i;
|
|
213
|
+
const s = t.extname(new URL(r).pathname).toLowerCase();
|
|
214
|
+
return ".ts" !== s && ".tsx" !== s || await v(), import(r);
|
|
215
|
+
}
|
|
216
|
+
async function k(t, e) {
|
|
217
|
+
const n = e.notifier ?? (await import("@sheetxl/sdk")).Notifier, i = r({
|
|
218
|
+
debug: (t) => n.debug(t),
|
|
219
|
+
log: (t) => n.log(t),
|
|
220
|
+
info: (t) => n.log(t),
|
|
221
|
+
warn: (t) => n.warn(t),
|
|
222
|
+
error: (t) => n.error(t)
|
|
223
|
+
}, { render: e.render });
|
|
224
|
+
return {
|
|
225
|
+
ctx: {
|
|
226
|
+
args: e.args ?? {
|
|
227
|
+
raw: [],
|
|
228
|
+
kv: {},
|
|
229
|
+
_: []
|
|
230
|
+
},
|
|
231
|
+
wb: t,
|
|
232
|
+
log: i.log,
|
|
233
|
+
warn: i.warn,
|
|
234
|
+
error: i.error
|
|
235
|
+
},
|
|
236
|
+
channels: i,
|
|
237
|
+
notifier: n
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
var C = { run: async (n, r, i = {}) => {
|
|
241
|
+
const s = Array.isArray(r) ? r : [r], o = await Promise.all(s.map((n) => (async (n, r = {}) => {
|
|
242
|
+
let i = null;
|
|
243
|
+
const s = (t, e) => {
|
|
244
|
+
let n = t?.default;
|
|
245
|
+
if (n && "function" != typeof n && "function" == typeof n.default && (n = n.default), "function" != typeof n) throw new Error(`Script '${e}' has no runnable entry: export a default function, e.g. \`export default function main(ctx) { … }\`.`);
|
|
246
|
+
return n;
|
|
247
|
+
};
|
|
248
|
+
if ("function" == typeof n) i = n;
|
|
249
|
+
else if ("string" == typeof n || n instanceof URL) {
|
|
250
|
+
let o = null;
|
|
251
|
+
if ("string" != typeof n || /^[a-z]+:\/\//i.test(n)) o = await R(n);
|
|
252
|
+
else {
|
|
253
|
+
const i = t.resolve(r.cwd ?? process.cwd(), n);
|
|
254
|
+
if (!e.existsSync(i)) throw new Error(`Script not found: ${i}`);
|
|
255
|
+
e.accessSync(i, e.constants.R_OK), o = await R(i);
|
|
256
|
+
}
|
|
257
|
+
i = s(o, String(n));
|
|
258
|
+
} else if ("code" in n) {
|
|
259
|
+
const t = n.filename ?? "inline.ts";
|
|
260
|
+
let e, r = null;
|
|
261
|
+
t.endsWith(".ts") || t.endsWith(".tsx") ? (await v(), await _(), e = `${b}${encodeURIComponent(n.code)}`, r = await import(e)) : (await _(), e = `${$}${encodeURIComponent(n.code)}`, r = await import(e)), i = s(r, t);
|
|
262
|
+
} else {
|
|
263
|
+
if (!("runner" in n)) throw new Error("Invalid run target specified.");
|
|
264
|
+
i = n.runner;
|
|
265
|
+
}
|
|
266
|
+
return i;
|
|
267
|
+
})(n, i))), a = Date.now();
|
|
268
|
+
let c = n, l = null;
|
|
269
|
+
const u = o.length;
|
|
270
|
+
for (let t = 0; t < u; t++) {
|
|
271
|
+
const e = o[t], { ctx: n, channels: r, notifier: s } = await k(c, i);
|
|
272
|
+
l = s;
|
|
273
|
+
const a = Date.now();
|
|
274
|
+
let f;
|
|
275
|
+
try {
|
|
276
|
+
f = await x(Promise.resolve().then(() => e(n)), i.timeoutMs, "Runner timed out");
|
|
277
|
+
} finally {
|
|
278
|
+
await r.flush();
|
|
279
|
+
}
|
|
280
|
+
const p = Date.now();
|
|
281
|
+
null != f && f.isIWorkbook && (c = f), s.debug(`Run ${1 === u ? "" : `${t + 1}/${u} `}completed in ${p - a} ms.`);
|
|
282
|
+
}
|
|
283
|
+
if (u > 1 && l) {
|
|
284
|
+
const t = Date.now();
|
|
285
|
+
l.debug(`All runs completed in ${t - a} ms.`);
|
|
286
|
+
}
|
|
287
|
+
return c ?? void 0;
|
|
288
|
+
} };
|
|
289
|
+
export { o as Snippet, C as default, s as resolvePath };
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sheetxl/runner",
|
|
3
|
+
"description": "SheetXL - Programmatic execution for SheetXL scripts",
|
|
4
|
+
"version": "0.7.23-beta.1",
|
|
5
|
+
"license": "SEE LICENSE IN <LICENSE>",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./types/index.d.ts",
|
|
10
|
+
"node": "./node/esm/index.mjs",
|
|
11
|
+
"import": "./node/esm/index.mjs"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"types": "./types/index.d.ts",
|
|
15
|
+
"module": "./node/esm/index.mjs",
|
|
16
|
+
"sideEffects": false,
|
|
17
|
+
"engineStrict": true,
|
|
18
|
+
"homepage": "https://sheetxl.com",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/sheetxl/sheetxl.git"
|
|
22
|
+
},
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/sheetxl/sheetxl/issues"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"sheetxl",
|
|
28
|
+
"spreadsheet",
|
|
29
|
+
"javascript",
|
|
30
|
+
"typescript",
|
|
31
|
+
"data wrangling",
|
|
32
|
+
"automation",
|
|
33
|
+
"scripting",
|
|
34
|
+
"excel",
|
|
35
|
+
"xlsx",
|
|
36
|
+
"runner"
|
|
37
|
+
],
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@sheetxl/io": "^0.7.23-beta.1",
|
|
40
|
+
"@sheetxl/primitives": "^0.7.23-beta.1",
|
|
41
|
+
"@sheetxl/scripting": "^0.7.23-beta.1",
|
|
42
|
+
"@sheetxl/sdk": "^0.7.23-beta.1",
|
|
43
|
+
"@sheetxl/utils": "^0.7.23-beta.1"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"typescript": "^5.9.0 || ^6.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^26.1.2",
|
|
50
|
+
"tsx": "^4.23.1",
|
|
51
|
+
"typescript": "^5.9.0 || ^6.0.0"
|
|
52
|
+
}
|
|
53
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a file path against an optional env-variable base directory.
|
|
3
|
+
*
|
|
4
|
+
* Resolution order:
|
|
5
|
+
* 1. Absolute path → returned as-is.
|
|
6
|
+
* 2. Relative path + env var set → resolved against `process.env[envVar]`.
|
|
7
|
+
* 3. Relative path, no env var → resolved against CWD.
|
|
8
|
+
*
|
|
9
|
+
* No existence checks are performed — this mirrors `path.resolve` semantics.
|
|
10
|
+
* The caller is responsible for handling missing files or non-existent directories.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolvePath(raw: string, envVar?: string): string;
|
|
13
|
+
//# sourceMappingURL=RunUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RunUtils.d.ts","sourceRoot":"","sources":["../../../src/RunUtils.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAqB,GAAG,MAAM,CAI9E"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Runner } from './Types';
|
|
2
|
+
/** Core: run targets as a serial pipeline, each receiving the current workbook.
|
|
3
|
+
*
|
|
4
|
+
* Pipeline semantics:
|
|
5
|
+
* - Targets run **serially** in order, never in parallel.
|
|
6
|
+
* - Each target receives a fresh `RunContext` built with the **current** workbook.
|
|
7
|
+
* - If a target returns an `IWorkbook`, that becomes the workbook for all subsequent targets.
|
|
8
|
+
* - `args` are shared across all targets — they represent pipeline-level configuration,
|
|
9
|
+
* not per-step input. This follows the standard Unix convention where environment
|
|
10
|
+
* variables / flags are visible to every process in a pipeline.
|
|
11
|
+
* - Returns the final workbook (which may differ from the one passed in).
|
|
12
|
+
*/
|
|
13
|
+
export declare const run: Runner;
|
|
14
|
+
declare const _default: {
|
|
15
|
+
run: Runner;
|
|
16
|
+
};
|
|
17
|
+
export default _default;
|
|
18
|
+
//# sourceMappingURL=Runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Runner.d.ts","sourceRoot":"","sources":["../../../src/Runner.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,KAAK,MAAM,EACZ,MAAM,SAAS,CAAC;AAyOjB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,GAAG,EAAE,MAyDjB,CAAA;;;;AAED,wBAEE"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snippet classification and source transforms — shared by every transport that accepts inline
|
|
3
|
+
* code (`sheetxl -e` / stdin on the CLI, the `run` tool's `code`/`path` on MCP).
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* **What the source means is decided by the code itself, not by how it arrived.** A module with a
|
|
7
|
+
* top-level default export is a *script*: it is handed the run context and its return value is the
|
|
8
|
+
* result. Anything else is a *snippet*: the author writes what they would type at a prompt, and the
|
|
9
|
+
* contract promises two things a bare paste into an async function does not give them —
|
|
10
|
+
* 1. **implicit await**: nothing in a snippet is ever written `await`, yet a promise-returning
|
|
11
|
+
* statement must have settled before the next one runs;
|
|
12
|
+
* 2. **the final expression is the result**: exactly like a REPL, or `node -p`.
|
|
13
|
+
*
|
|
14
|
+
* This is the same problem Node's REPL solves in `lib/internal/repl/await.js`, and it is solved the
|
|
15
|
+
* same way: **parse for real, then rewrite the top-level statements from the AST.** Statement
|
|
16
|
+
* boundaries, declarator lists, binding patterns, ASI, comments, regex-vs-division and template
|
|
17
|
+
* nesting are all a parser's job, and every one of them is a bug when they are a scanner's instead.
|
|
18
|
+
* The one place we deliberately diverge from the REPL is the await: Node makes the author write it,
|
|
19
|
+
* and a snippet's author never does.
|
|
20
|
+
*
|
|
21
|
+
* Because the source is TypeScript, the parser is TypeScript's — `createSourceFile`, parse-only, no
|
|
22
|
+
* `Program`. It is the same module the `ScriptCompiler` links, so the transform and the linter can
|
|
23
|
+
* never disagree about what a snippet means, and a transport that already compiles (MCP) pays
|
|
24
|
+
* nothing for it: the module is loaded once per process and cached.
|
|
25
|
+
*
|
|
26
|
+
* **Nothing here degrades silently.** The transform is deterministic: either the snippet parsed, in
|
|
27
|
+
* which case it is rewritten exactly once, or it did not, in which case it is wrapped verbatim so
|
|
28
|
+
* the loader that runs it reports the authoritative syntax error against real positions. A snippet
|
|
29
|
+
* is never quietly run with the contract switched off.
|
|
30
|
+
*
|
|
31
|
+
* The generated wrapper is deliberately the *validated* macro shape (named default export, typed
|
|
32
|
+
* context parameter) so the identical source compiles on every path: the CLI's type-stripping
|
|
33
|
+
* loader ignores the annotations, and the `ScriptCompiler`'s linter requires them.
|
|
34
|
+
*/
|
|
35
|
+
/** How a source will run — see the module remarks for the contract. */
|
|
36
|
+
export type SourceForm = 'script' | 'snippet';
|
|
37
|
+
/** `script` when the source has a top-level default export; `snippet` otherwise. */
|
|
38
|
+
export declare function classify(code: string): Promise<SourceForm>;
|
|
39
|
+
export interface WrapOptions {
|
|
40
|
+
/**
|
|
41
|
+
* Statements emitted after the body, before the closing brace. Sees `__result` (the final
|
|
42
|
+
* expression's value) and the destructured context (`wb`, `log`, …). Defaults to
|
|
43
|
+
* `return __result;` — the script-contract shape, where the return value is the run's result.
|
|
44
|
+
*/
|
|
45
|
+
epilogue?: string;
|
|
46
|
+
}
|
|
47
|
+
/** A snippet wrapped as a run-function module, ready to compile or load. */
|
|
48
|
+
export interface Prepared {
|
|
49
|
+
/** The complete wrapper module source. */
|
|
50
|
+
source: string;
|
|
51
|
+
/**
|
|
52
|
+
* Which transform produced it: the statement-level rewrite (implicit await, final expression is
|
|
53
|
+
* the result), a single parenthesized expression, or the snippet verbatim — which means neither
|
|
54
|
+
* promise was kept and {@link warning} says why.
|
|
55
|
+
*/
|
|
56
|
+
kind: 'expression' | 'statements' | 'verbatim';
|
|
57
|
+
/**
|
|
58
|
+
* Lines of wrapper prologue before the first line of user code — subtract from a compiler
|
|
59
|
+
* diagnostic's line to point back into the snippet. Exact for every kind: the rewrite emits the
|
|
60
|
+
* original trivia, so no line moves.
|
|
61
|
+
*/
|
|
62
|
+
lineOffset: number;
|
|
63
|
+
/**
|
|
64
|
+
* Set only when the contract could not be honored — no implicit await, no result. Callers should
|
|
65
|
+
* surface it; a snippet quietly returning `undefined` is worse than one that failed.
|
|
66
|
+
*/
|
|
67
|
+
warning?: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The label a host should fall back to for an unnamed snippet run.
|
|
71
|
+
*
|
|
72
|
+
* @remarks
|
|
73
|
+
* Exported rather than emitted as the wrapper's own JSDoc, which is the author's slot and must stay
|
|
74
|
+
* empty when the author left it empty — see {@link leadingDoc}. A caller passes this as the SDK's
|
|
75
|
+
* `RunOptions.defaultDescription`, the floor *below* a documented entry's summary. Deliberately not
|
|
76
|
+
* "inline snippet": nothing is being inlined anywhere, code is being run.
|
|
77
|
+
*/
|
|
78
|
+
export declare const DEFAULT_DESCRIPTION = "Run Snippet";
|
|
79
|
+
/**
|
|
80
|
+
* The wrapper module for a snippet — one deterministic transform, never a ladder.
|
|
81
|
+
*
|
|
82
|
+
* @remarks
|
|
83
|
+
* A snippet that is nothing but `{ … }` parses as a *block*, exactly as it would at a Node REPL
|
|
84
|
+
* prompt, so `-e '{ name: s.getName() }'` would otherwise run as a labelled statement and produce
|
|
85
|
+
* nothing. The REPL recovers by re-reading such input parenthesized; so does this, which also
|
|
86
|
+
* sidesteps any position mapping — the whole snippet is the expression.
|
|
87
|
+
*/
|
|
88
|
+
export declare function prepare(code: string, options?: WrapOptions): Promise<Prepared>;
|
|
89
|
+
//# sourceMappingURL=Snippet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Snippet.d.ts","sourceRoot":"","sources":["../../../src/Snippet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAoKH,uEAAuE;AACvE,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAmC9C,oFAAoF;AACpF,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAKhE;AAID,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,4EAA4E;AAC5E,MAAM,WAAW,QAAQ;IACvB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,IAAI,EAAE,YAAY,GAAG,YAAY,GAAG,UAAU,CAAC;IAC/C;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAQD;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AA8DjD;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkCpF"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { IWorkbook } from '@sheetxl/sdk';
|
|
2
|
+
import { LogRenderer } from '@sheetxl/utils';
|
|
3
|
+
export type Notifier = typeof import('@sheetxl/sdk').Notifier;
|
|
4
|
+
/**
|
|
5
|
+
* Arguments passed after `--` on the CLI (`sheetxl -f <script> [workbook] -- [args...]`).
|
|
6
|
+
*
|
|
7
|
+
* Parsing rules:
|
|
8
|
+
* - Long flags: `--key=value` or `--key value`
|
|
9
|
+
* - Short flags: `-k value` or `-v`
|
|
10
|
+
* - Positionals: tokens not starting with `-` (appear in `_.`)
|
|
11
|
+
* - Optional: we also accept `-long=value` as a long flag.
|
|
12
|
+
* - Repeated flags: last one wins (no arrays).
|
|
13
|
+
* - Types: values are strings or booleans; scripts can coerce as needed.
|
|
14
|
+
*/
|
|
15
|
+
export type ArgV = {
|
|
16
|
+
/** Tail as typed by the user (everything after <script>). */
|
|
17
|
+
raw: string[];
|
|
18
|
+
/** Parsed flags (long/short) with string or boolean values. */
|
|
19
|
+
kv: Record<string, string | boolean>;
|
|
20
|
+
/** Positional args (order preserved). */
|
|
21
|
+
_: string[];
|
|
22
|
+
} & {
|
|
23
|
+
/**
|
|
24
|
+
* Named flags, also spread onto the object itself — `args.region` and `args.kv.region` are the
|
|
25
|
+
* same value. This is what makes `args` read identically on the CLI and on MCP (where it is the
|
|
26
|
+
* caller's JSON object). `raw`/`kv`/`_` win on a collision.
|
|
27
|
+
*/
|
|
28
|
+
[name: string]: any;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* The run context — the five members every run sees, on every transport, and the implicit globals
|
|
32
|
+
* of an inline snippet: `wb`, `log`, `warn`, `error`, `args`. Nothing else (in particular, no
|
|
33
|
+
* `console`): a script needing the SDK's module surface imports it like any other module.
|
|
34
|
+
*/
|
|
35
|
+
export type RunContext = {
|
|
36
|
+
/**
|
|
37
|
+
* All tail args after the script
|
|
38
|
+
*/
|
|
39
|
+
readonly args: ArgV;
|
|
40
|
+
/**
|
|
41
|
+
* The workbook the run is against — from `--in`, or `null` when there is none.
|
|
42
|
+
*/
|
|
43
|
+
readonly wb: IWorkbook | null;
|
|
44
|
+
/**
|
|
45
|
+
* The reporting channel — findings and results.
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* Variadic and value-taking, like `console.log`: `log('rows:', n)` and `log(range.getStats())`
|
|
49
|
+
* both work. An SDK object renders as its markdown report when the host supplies a renderer
|
|
50
|
+
* (the CLI does); otherwise it falls back to JSON.
|
|
51
|
+
*/
|
|
52
|
+
readonly log: (...args: any[]) => void;
|
|
53
|
+
/** Diagnostics: something surprising but survivable. Travels separately from `log` (stderr). */
|
|
54
|
+
readonly warn: (...args: any[]) => void;
|
|
55
|
+
/** Diagnostics: something wrong. Travels separately from `log` (stderr). */
|
|
56
|
+
readonly error: (...args: any[]) => void;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* The function signature for a script run by the CLI or the MCP `run` tool.
|
|
60
|
+
*/
|
|
61
|
+
export type RunFunction = (ctx: RunContext) => Promise<void | IWorkbook>;
|
|
62
|
+
/**
|
|
63
|
+
* Possible targets for the runner to execute
|
|
64
|
+
*/
|
|
65
|
+
export type RunTarget = string | URL | {
|
|
66
|
+
code: string;
|
|
67
|
+
filename?: string;
|
|
68
|
+
} | {
|
|
69
|
+
runner: RunFunction;
|
|
70
|
+
};
|
|
71
|
+
export interface RunOptions {
|
|
72
|
+
args?: ArgV;
|
|
73
|
+
/** The host's output sink (toasts on a UI host, the console on the CLI). Not exposed to scripts. */
|
|
74
|
+
notifier?: Notifier;
|
|
75
|
+
/**
|
|
76
|
+
* Renders an SDK object logged by the script as its markdown report.
|
|
77
|
+
*
|
|
78
|
+
* @remarks
|
|
79
|
+
* Injected because the renderer registry lives in `@sheetxl/query`. The CLI passes a closure
|
|
80
|
+
* over `renderMarkdown` and its workbook; without it, logged objects fall back to JSON.
|
|
81
|
+
*/
|
|
82
|
+
render?: LogRenderer;
|
|
83
|
+
signal?: AbortSignal;
|
|
84
|
+
timeoutMs?: number;
|
|
85
|
+
cwd?: string;
|
|
86
|
+
ts?: {
|
|
87
|
+
enabled?: boolean;
|
|
88
|
+
cacheDir?: string;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Run any RunFunction with a built in context.
|
|
93
|
+
*/
|
|
94
|
+
export type Runner = (workbook: IWorkbook | null, target: RunTarget | RunTarget[], options?: RunOptions) => Promise<void | IWorkbook>;
|
|
95
|
+
//# sourceMappingURL=Types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Types.d.ts","sourceRoot":"","sources":["../../../src/Types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,cAAc,cAAc,EAAE,QAAQ,CAAC;AAE9D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,IAAI,GAAG;IACjB,6DAA6D;IAC7D,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,+DAA+D;IAC/D,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;IACrC,yCAAyC;IACzC,CAAC,EAAE,MAAM,EAAE,CAAC;CACb,GAAG;IACF;;;;OAIG;IACH,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC;CACrB,CAAC;AAGF;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI,CAAC;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACvC,gGAAgG;IAChG,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACxC,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;CAM1C,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,GAAG,GACH;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC;AAE5B,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,oGAAoG;IACpG,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,CACnB,QAAQ,EAAE,SAAS,GAAG,IAAI,EAC1B,MAAM,EAAE,SAAS,GAAG,SAAS,EAAE,EAC/B,OAAO,CAAC,EAAE,UAAU,KACjB,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,OAAO,KAAK,OAAO,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
|