@sheetxl/runner 0.8.0-beta.1 → 0.8.0-beta.11
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/README.md +16 -4
- package/node/esm/index.mjs +317 -153
- package/package.json +8 -8
- package/types/src/RunDiagnosis.d.ts +33 -0
- package/types/src/Runner.d.ts +7 -9
- package/types/src/Snippet.d.ts +44 -5
- package/types/src/Types.d.ts +58 -4
- package/types/src/index.d.ts +1 -0
package/README.md
CHANGED
|
@@ -19,7 +19,19 @@ npm i -D @sheetxl/runner
|
|
|
19
19
|
## Using the runner
|
|
20
20
|
|
|
21
21
|
``` ts
|
|
22
|
-
export type Runner = (workbook: IWorkbook,
|
|
22
|
+
export type Runner = (workbook: IWorkbook | null, args: ArgV | undefined, options: RunOptions) => Promise<IWorkbook | any | void>;
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The two data inputs are positional — the workbook and the args. Everything else is host wiring and
|
|
26
|
+
lives in `RunOptions`, `target` included.
|
|
27
|
+
|
|
28
|
+
`run` hands back whatever the script returned: a tally, a range, nothing. A returned `IWorkbook` is
|
|
29
|
+
also the workbook the run ended on — the one to write for `--save`/`--out` — so a host that needs it
|
|
30
|
+
reads it off the result:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
const result = await Runner.run(wb, args, { target: 'scripts/transform.ts' });
|
|
34
|
+
const ended = (result as IWorkbook)?.isIWorkbook ? result as IWorkbook : wb;
|
|
23
35
|
```
|
|
24
36
|
|
|
25
37
|
``` ts
|
|
@@ -28,8 +40,8 @@ import { Runner } from '@sheetxl/runner';
|
|
|
28
40
|
|
|
29
41
|
const wb = new Workbook();
|
|
30
42
|
|
|
31
|
-
await Runner.run(wb, '
|
|
32
|
-
|
|
43
|
+
await Runner.run(wb, { raw: ['--region', 'EU'], kv: { region: 'EU' }, _: [] }, {
|
|
44
|
+
target: 'scripts/transform.ts'
|
|
33
45
|
});
|
|
34
46
|
|
|
35
47
|
```
|
|
@@ -46,7 +58,7 @@ import Runner, { type RunContext } from '@sheetxl/runner';
|
|
|
46
58
|
|
|
47
59
|
export default async function main(ctx: RunContext) {
|
|
48
60
|
const { wb, log, args } = ctx;
|
|
49
|
-
wb.
|
|
61
|
+
wb.getWorksheet().getRange('A1').setValue(args.region);
|
|
50
62
|
log('updated value');
|
|
51
63
|
}
|
|
52
64
|
```
|
package/node/esm/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license @sheetxl/runner - SheetXL - Programmatic execution for SheetXL scripts - v0.8.0-beta.
|
|
2
|
+
* @license @sheetxl/runner - SheetXL - Programmatic execution for SheetXL scripts - v0.8.0-beta.11
|
|
3
3
|
*
|
|
4
4
|
* (C) 2026-present SheetXL Inc. & Michael T. Ford
|
|
5
5
|
* License: The license can be found at https://www.sheetxl.com/license.
|
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
import t from "node:path";
|
|
8
8
|
import e from "node:fs";
|
|
9
9
|
import { pathToFileURL as n } from "node:url";
|
|
10
|
-
import { createLogChannels as r } from "@sheetxl/utils";
|
|
10
|
+
import { createLogChannels as r, resolveLogTimeout as s } from "@sheetxl/utils";
|
|
11
11
|
var i = Object.defineProperty;
|
|
12
|
-
function
|
|
12
|
+
function o(e, n = "SHEETXL_IN") {
|
|
13
13
|
if (t.isAbsolute(e)) return e;
|
|
14
14
|
const r = n ? process.env[n] : void 0;
|
|
15
15
|
return t.resolve(r ?? process.cwd(), e);
|
|
16
16
|
}
|
|
17
|
-
var
|
|
17
|
+
var a = ((t, e) => {
|
|
18
18
|
let n = {};
|
|
19
19
|
for (var r in t) i(n, r, {
|
|
20
20
|
get: t[r],
|
|
@@ -22,22 +22,23 @@ var o = ((t, e) => {
|
|
|
22
22
|
});
|
|
23
23
|
return e || i(n, Symbol.toStringTag, { value: "Module" }), n;
|
|
24
24
|
})({
|
|
25
|
-
DEFAULT_DESCRIPTION: () =>
|
|
26
|
-
classify: () =>
|
|
27
|
-
prepare: () =>
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
DEFAULT_DESCRIPTION: () => v,
|
|
26
|
+
classify: () => w,
|
|
27
|
+
prepare: () => T,
|
|
28
|
+
toSnippetOffset: () => b
|
|
29
|
+
}), c = null;
|
|
30
|
+
function l() {
|
|
31
|
+
return c || (c = (async () => {
|
|
31
32
|
try {
|
|
32
33
|
const t = await import("typescript");
|
|
33
34
|
return t.default ?? t;
|
|
34
35
|
} catch {
|
|
35
36
|
return null;
|
|
36
37
|
}
|
|
37
|
-
})()),
|
|
38
|
+
})()), c;
|
|
38
39
|
}
|
|
39
|
-
async function
|
|
40
|
-
const e = await
|
|
40
|
+
async function u(t) {
|
|
41
|
+
const e = await l();
|
|
41
42
|
if (!e) return null;
|
|
42
43
|
const n = e.createSourceFile("snippet.ts", t, e.ScriptTarget.Latest, !1, e.ScriptKind.TS);
|
|
43
44
|
return (n.parseDiagnostics?.length ?? 0) > 0 ? null : {
|
|
@@ -45,154 +46,310 @@ async function l(t) {
|
|
|
45
46
|
sf: n
|
|
46
47
|
};
|
|
47
48
|
}
|
|
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
49
|
function p(t) {
|
|
55
50
|
let e = 0;
|
|
56
51
|
for (let n = 0; n < t.length; n++) "\n" === t[n] && e++;
|
|
57
52
|
return e;
|
|
58
53
|
}
|
|
59
|
-
function d(t, e) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
54
|
+
function d(t, e, n) {
|
|
55
|
+
let r = n.getStart(e);
|
|
56
|
+
for (const s of n.declarationList.declarations) {
|
|
57
|
+
const n = s.initializer;
|
|
58
|
+
if (!n) continue;
|
|
59
|
+
const i = n.getStart(e);
|
|
60
|
+
t.copy(r, i), t.add("await ("), t.copy(i, n.end), t.add(")"), r = n.end;
|
|
61
|
+
}
|
|
62
|
+
t.copy(r, n.end), t.terminate();
|
|
63
|
+
}
|
|
64
|
+
var f = class {
|
|
65
|
+
constructor(t) {
|
|
66
|
+
this._code = t, this.spans = [], this._parts = [], this._length = 0;
|
|
67
|
+
}
|
|
68
|
+
add(t) {
|
|
69
|
+
this._parts.push(t), this._length += t.length;
|
|
70
|
+
}
|
|
71
|
+
copy(t, e) {
|
|
72
|
+
e <= t || (this.spans.push({
|
|
73
|
+
at: this._length,
|
|
74
|
+
from: t,
|
|
75
|
+
length: e - t
|
|
76
|
+
}), this.add(this._code.slice(t, e)));
|
|
77
|
+
}
|
|
78
|
+
terminate() {
|
|
79
|
+
this._parts[this._parts.length - 1]?.endsWith(";") || this.add(";");
|
|
80
|
+
}
|
|
81
|
+
toString() {
|
|
82
|
+
return this._parts.join("");
|
|
83
|
+
}
|
|
84
|
+
}, m = /* @__PURE__ */ new Set([
|
|
85
|
+
"log",
|
|
86
|
+
"warn",
|
|
87
|
+
"error"
|
|
88
|
+
]), h = "await wb?.whenCalculationReady?.(); ";
|
|
89
|
+
function g(t, e) {
|
|
90
|
+
const n = e.statements;
|
|
91
|
+
let r = n.length - 1;
|
|
92
|
+
for (; r >= 0 && n[r].kind === t.SyntaxKind.EmptyStatement;) r--;
|
|
93
|
+
if (r < 0) return null;
|
|
94
|
+
const s = n[r];
|
|
95
|
+
if ((t.isExpressionStatement(s) || t.isExportAssignment(s) && !s.isExportEquals) && ((e) => {
|
|
96
|
+
for (; t.isParenthesizedExpression(e);) e = e.expression;
|
|
97
|
+
return t.isArrowFunction(e) || t.isFunctionExpression(e);
|
|
98
|
+
})(s.expression)) return {
|
|
99
|
+
index: r,
|
|
100
|
+
from: s.expression.getStart(e),
|
|
101
|
+
to: s.expression.end
|
|
102
|
+
};
|
|
103
|
+
if (t.isFunctionDeclaration(s) && s.body) {
|
|
104
|
+
const n = t.getModifiers(s) ?? [], i = n.some((e) => e.kind === t.SyntaxKind.ExportKeyword);
|
|
105
|
+
if (n.some((e) => e.kind === t.SyntaxKind.DefaultKeyword) && !s.name || !i && function(t, e) {
|
|
106
|
+
let n = -1;
|
|
107
|
+
for (let r = 0; r < e.statements.length; r++) {
|
|
108
|
+
const s = e.statements[r];
|
|
109
|
+
if (s.kind !== t.SyntaxKind.EmptyStatement && !t.isImportDeclaration(s) && !t.isImportEqualsDeclaration(s)) {
|
|
110
|
+
if (-1 !== n) return -1;
|
|
111
|
+
n = r;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return n;
|
|
115
|
+
}(t, e) === r) {
|
|
116
|
+
let i = s.getStart(e);
|
|
117
|
+
for (const e of n) e.kind !== t.SyntaxKind.ExportKeyword && e.kind !== t.SyntaxKind.DefaultKeyword || (i = e.end);
|
|
118
|
+
for (; i < s.end && /\s/.test(e.text[i]);) i++;
|
|
119
|
+
return {
|
|
120
|
+
index: r,
|
|
121
|
+
from: i,
|
|
122
|
+
to: s.end
|
|
123
|
+
};
|
|
124
|
+
}
|
|
68
125
|
}
|
|
69
|
-
return
|
|
126
|
+
return null;
|
|
70
127
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
128
|
+
var y = "const __entry: (ctx: SheetXL.IScript.ScriptContext) => unknown = (", x = (t) => `); ${t} = await __entry(ctx);`;
|
|
129
|
+
async function w(t) {
|
|
130
|
+
const e = await u(t);
|
|
131
|
+
if (!e) return function(t) {
|
|
132
|
+
return /^\s*export\s+default\b/m.test(t) || /^\s*export\s*\{[^}]*\bas\s+default\b/m.test(t);
|
|
133
|
+
}(t) ? "script" : "snippet";
|
|
134
|
+
const { ts: n, sf: r } = e;
|
|
135
|
+
return function(t, e) {
|
|
74
136
|
for (const n of e.statements) {
|
|
75
137
|
if (t.isExportAssignment(n) && !n.isExportEquals) return !0;
|
|
76
138
|
if (t.canHaveModifiers(n) && t.getModifiers(n)?.some((e) => e.kind === t.SyntaxKind.DefaultKeyword)) return !0;
|
|
77
139
|
if (t.isExportDeclaration(n) && n.exportClause && t.isNamedExports(n.exportClause) && n.exportClause.elements.some((t) => "default" === t.name.text)) return !0;
|
|
78
140
|
}
|
|
79
141
|
return !1;
|
|
80
|
-
}(
|
|
81
|
-
|
|
82
|
-
|
|
142
|
+
}(n, r) && !function(t, e) {
|
|
143
|
+
const n = g(t, e);
|
|
144
|
+
return !!n && e.statements.every((e, r) => r === n.index || !t.isExportAssignment(e) && !t.isExportDeclaration(e) && !(t.canHaveModifiers(e) && t.getModifiers(e)?.some((e) => e.kind === t.SyntaxKind.ExportKeyword)));
|
|
145
|
+
}(n, r) ? "script" : "snippet";
|
|
83
146
|
}
|
|
84
|
-
var
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
"
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
147
|
+
var S = 3, v = "Run Snippet", E = (t, e, n = [], r) => {
|
|
148
|
+
const s = [
|
|
149
|
+
...n,
|
|
150
|
+
...r ? [r] : [],
|
|
151
|
+
"export default async function __snippet(ctx: SheetXL.IScript.ScriptContext): Promise<void> {",
|
|
152
|
+
" const { wb, log, warn, error, args } = ctx;",
|
|
153
|
+
" let __result: any = undefined;"
|
|
154
|
+
].join("\n") + "\n";
|
|
155
|
+
return {
|
|
156
|
+
source: s + [
|
|
157
|
+
t,
|
|
158
|
+
" ;",
|
|
159
|
+
e,
|
|
160
|
+
"};"
|
|
161
|
+
].join("\n"),
|
|
162
|
+
bodyStart: s.length
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
async function T(t, e) {
|
|
166
|
+
const n = e?.epilogue ?? " return __result;", r = await u(t);
|
|
97
167
|
if (!r) {
|
|
98
|
-
const e = await
|
|
168
|
+
const e = await l() ? void 0 : "TypeScript is unavailable, so this snippet ran without implicit await or a result value. Install the `typescript` peer dependency to restore them.", { source: r, bodyStart: s } = E(t, n);
|
|
99
169
|
return {
|
|
100
|
-
source:
|
|
170
|
+
source: r,
|
|
101
171
|
kind: "verbatim",
|
|
102
|
-
lineOffset:
|
|
172
|
+
lineOffset: S,
|
|
173
|
+
spans: [{
|
|
174
|
+
at: s,
|
|
175
|
+
from: 0,
|
|
176
|
+
length: t.length
|
|
177
|
+
}],
|
|
178
|
+
expectsValue: !1,
|
|
103
179
|
warning: e
|
|
104
180
|
};
|
|
105
181
|
}
|
|
106
|
-
const { ts:
|
|
182
|
+
const { ts: s, sf: i } = r, o = i.statements, a = function(t, e) {
|
|
107
183
|
if (!e.statements[0]) return;
|
|
108
184
|
const n = t.getLeadingCommentRanges(e.text, 0);
|
|
109
185
|
if (n?.length) for (let r = n.length - 1; r >= 0; r--) {
|
|
110
|
-
const
|
|
111
|
-
if (
|
|
112
|
-
const
|
|
113
|
-
if (
|
|
186
|
+
const s = n[r];
|
|
187
|
+
if (s.kind !== t.SyntaxKind.MultiLineCommentTrivia) continue;
|
|
188
|
+
const i = e.text.slice(s.pos, s.end);
|
|
189
|
+
if (i.startsWith("/**")) return i;
|
|
114
190
|
}
|
|
115
|
-
}(
|
|
116
|
-
if (1 === o.length &&
|
|
117
|
-
source:
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
191
|
+
}(s, i), c = a ? p(a) + 1 : 0;
|
|
192
|
+
if (1 === o.length && s.isBlock(o[0])) {
|
|
193
|
+
const { source: r, bodyStart: s } = E(` __result = await (
|
|
194
|
+
${t}\n );`, n, [], a);
|
|
195
|
+
return {
|
|
196
|
+
source: r,
|
|
197
|
+
kind: "expression",
|
|
198
|
+
lineOffset: S + c + 1,
|
|
199
|
+
spans: [{
|
|
200
|
+
at: s + 21,
|
|
201
|
+
from: 0,
|
|
202
|
+
length: t.length
|
|
203
|
+
}],
|
|
204
|
+
expectsValue: !0
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
const { body: w, spans: v, hoisted: T, expectsValue: b } = function(t, e, n) {
|
|
208
|
+
const r = e.text, s = e.statements;
|
|
209
|
+
let i = -1;
|
|
210
|
+
for (let e = s.length - 1; e >= 0; e--) if (s[e].kind !== t.SyntaxKind.EmptyStatement) {
|
|
211
|
+
t.isExpressionStatement(s[e]) && (i = e);
|
|
126
212
|
break;
|
|
127
213
|
}
|
|
128
|
-
const o =
|
|
129
|
-
let
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
a.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
214
|
+
const o = g(t, e);
|
|
215
|
+
let a = !1;
|
|
216
|
+
if (!o && -1 !== i) {
|
|
217
|
+
const e = s[i].expression;
|
|
218
|
+
a = !(t.isCallExpression(e) && t.isIdentifier(e.expression) && m.has(e.expression.text));
|
|
219
|
+
}
|
|
220
|
+
const c = [], l = new f(r);
|
|
221
|
+
let u = 0, w = !1;
|
|
222
|
+
for (let a = 0; a < s.length; a++) {
|
|
223
|
+
const f = s[a], m = f.getStart(e);
|
|
224
|
+
if (l.copy(u, m), u = f.end, t.isImportDeclaration(f) || t.isImportEqualsDeclaration(f)) {
|
|
225
|
+
const t = r.slice(m, f.end);
|
|
226
|
+
c.push({
|
|
227
|
+
text: t,
|
|
228
|
+
from: m
|
|
229
|
+
}), l.add("\n".repeat(p(t)));
|
|
230
|
+
continue;
|
|
143
231
|
}
|
|
232
|
+
w && l.add(h), w = !0, o?.index !== a ? t.isVariableStatement(f) ? d(l, e, f) : t.isExpressionStatement(f) ? (l.add(a === i ? `${n} = await (` : "await ("), l.copy(f.expression.getStart(e), f.expression.end), l.add(");")) : (l.copy(m, f.end), l.terminate()) : (l.add(y), l.copy(o.from, o.to), l.add(x(n)));
|
|
144
233
|
}
|
|
145
|
-
return
|
|
146
|
-
body:
|
|
147
|
-
|
|
234
|
+
return l.copy(u, r.length), {
|
|
235
|
+
body: l.toString(),
|
|
236
|
+
spans: l.spans,
|
|
237
|
+
hoisted: c,
|
|
238
|
+
expectsValue: a
|
|
148
239
|
};
|
|
149
|
-
}(
|
|
240
|
+
}(s, i, "__result"), _ = T.map((t) => t.text), k = T.length > 0 ? p(_.join("\n")) + T.length : 0, { source: D, bodyStart: K } = E(w, n, _, a);
|
|
241
|
+
let R = 0;
|
|
242
|
+
const I = T.map((t) => {
|
|
243
|
+
const e = {
|
|
244
|
+
at: R,
|
|
245
|
+
from: t.from,
|
|
246
|
+
length: t.text.length
|
|
247
|
+
};
|
|
248
|
+
return R += t.text.length + 1, e;
|
|
249
|
+
});
|
|
150
250
|
return {
|
|
151
|
-
source:
|
|
251
|
+
source: D,
|
|
152
252
|
kind: "statements",
|
|
153
|
-
lineOffset:
|
|
253
|
+
lineOffset: S + k + c,
|
|
254
|
+
spans: [...I, ...v.map((t) => ({
|
|
255
|
+
...t,
|
|
256
|
+
at: t.at + K
|
|
257
|
+
}))],
|
|
258
|
+
expectsValue: b
|
|
154
259
|
};
|
|
155
260
|
}
|
|
156
|
-
|
|
261
|
+
function b(t, e) {
|
|
262
|
+
let n = null;
|
|
263
|
+
for (const r of t.spans) {
|
|
264
|
+
if (r.at > e) return null !== n && e < n.at + n.length ? n.from + (e - n.at) : r.from;
|
|
265
|
+
n = r;
|
|
266
|
+
}
|
|
267
|
+
return n ? n.from + Math.min(e - n.at, n.length) : 0;
|
|
268
|
+
}
|
|
269
|
+
var _ = /* @__PURE__ */ new Set(["TS2339", "TS2551"]), k = /* @__PURE__ */ new Set([
|
|
270
|
+
..._,
|
|
271
|
+
"TS2304",
|
|
272
|
+
"TS2552",
|
|
273
|
+
"TS2448",
|
|
274
|
+
"TS2588",
|
|
275
|
+
"TS2531",
|
|
276
|
+
"TS2532",
|
|
277
|
+
"TS2533",
|
|
278
|
+
"TS18047",
|
|
279
|
+
"TS18048",
|
|
280
|
+
"TS18049",
|
|
281
|
+
"TS2349",
|
|
282
|
+
"TS2351",
|
|
283
|
+
"TS2721",
|
|
284
|
+
"TS2722",
|
|
285
|
+
"TS2723"
|
|
286
|
+
]), D = /on type '(never|\{\})'/;
|
|
287
|
+
function K(t) {
|
|
288
|
+
return void 0 === t || "TypeError" === t || "ReferenceError" === t;
|
|
289
|
+
}
|
|
290
|
+
async function R(t, e) {
|
|
291
|
+
try {
|
|
292
|
+
const n = "snippet" === await w(t) ? await T(t) : null;
|
|
293
|
+
if ("undefined" === e && !n?.expectsValue) return [];
|
|
294
|
+
const [{ ScriptCompiler: r }, { getScriptingDeclarations: s }] = await Promise.all([import("@sheetxl/scripting"), import("@sheetxl/sdk")]), { diagnostics: i } = await r.compile({
|
|
295
|
+
source: n?.source ?? t,
|
|
296
|
+
ambientTypes: await s(),
|
|
297
|
+
lenient: !0,
|
|
298
|
+
disableBundle: !0,
|
|
299
|
+
disableSourceMap: !0
|
|
300
|
+
}), o = "threw" === e ? k : _;
|
|
301
|
+
return i.filter((t) => "error" === t.severity && o.has(t.code) && !(_.has(t.code) && D.test(t.message))).map((t) => ({
|
|
302
|
+
...t,
|
|
303
|
+
start: n ? b(n, t.start) : t.start,
|
|
304
|
+
..."undefined" === e ? {
|
|
305
|
+
severity: "warning",
|
|
306
|
+
message: `${t.message} It reads as undefined.`
|
|
307
|
+
} : {}
|
|
308
|
+
}));
|
|
309
|
+
} catch {
|
|
310
|
+
return [];
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
async function I(t, e, n = "Runner timed out") {
|
|
157
314
|
if (!e || e <= 0) return t;
|
|
158
315
|
let r;
|
|
159
|
-
const
|
|
316
|
+
const s = new Promise((t, s) => r = setTimeout(() => s(new Error(n)), e));
|
|
160
317
|
try {
|
|
161
|
-
return await Promise.race([t,
|
|
318
|
+
return await Promise.race([t, s]);
|
|
162
319
|
} finally {
|
|
163
320
|
clearTimeout(r);
|
|
164
321
|
}
|
|
165
322
|
}
|
|
166
|
-
var
|
|
167
|
-
function
|
|
168
|
-
return
|
|
323
|
+
var C = null;
|
|
324
|
+
function $() {
|
|
325
|
+
return C || (C = (async () => {
|
|
169
326
|
const { register: t } = await import("tsx/esm/api");
|
|
170
327
|
t({ tsconfig: !1 });
|
|
171
|
-
})()),
|
|
328
|
+
})()), C;
|
|
172
329
|
}
|
|
173
|
-
var
|
|
174
|
-
function
|
|
175
|
-
return
|
|
176
|
-
const { registerHooks: e, stripTypeScriptTypes: r } = await import("node:module"),
|
|
330
|
+
var L = "data:text/typescript,", M = "data:text/javascript,", W = null;
|
|
331
|
+
function P() {
|
|
332
|
+
return W || (W = (async () => {
|
|
333
|
+
const { registerHooks: e, stripTypeScriptTypes: r } = await import("node:module"), s = r;
|
|
177
334
|
e({
|
|
178
|
-
resolve(e, r,
|
|
179
|
-
const
|
|
180
|
-
if (
|
|
181
|
-
const
|
|
182
|
-
return
|
|
335
|
+
resolve(e, r, s) {
|
|
336
|
+
const i = r.parentURL;
|
|
337
|
+
if (i && (i.startsWith(L) || i.startsWith(M))) {
|
|
338
|
+
const i = n(t.join(process.cwd(), "_inline_.ts")).href;
|
|
339
|
+
return s(e, {
|
|
183
340
|
...r,
|
|
184
|
-
parentURL:
|
|
341
|
+
parentURL: i
|
|
185
342
|
});
|
|
186
343
|
}
|
|
187
|
-
return
|
|
344
|
+
return s(e, r);
|
|
188
345
|
},
|
|
189
346
|
load(t, e, n) {
|
|
190
|
-
if (t.startsWith(
|
|
347
|
+
if (t.startsWith(L)) {
|
|
191
348
|
const e = decodeURIComponent(t.slice(21)), n = process.emitWarning;
|
|
192
349
|
let r;
|
|
193
350
|
process.emitWarning = () => {};
|
|
194
351
|
try {
|
|
195
|
-
r =
|
|
352
|
+
r = s(e, { mode: "transform" });
|
|
196
353
|
} finally {
|
|
197
354
|
process.emitWarning = n;
|
|
198
355
|
}
|
|
@@ -205,25 +362,25 @@ function _() {
|
|
|
205
362
|
return n(t, e);
|
|
206
363
|
}
|
|
207
364
|
});
|
|
208
|
-
})()),
|
|
365
|
+
})()), W;
|
|
209
366
|
}
|
|
210
|
-
async function
|
|
211
|
-
const r = "string" == typeof (
|
|
212
|
-
var
|
|
213
|
-
const
|
|
214
|
-
return ".ts" !==
|
|
367
|
+
async function A(e) {
|
|
368
|
+
const r = "string" == typeof (s = e) ? s.startsWith("file:") ? s : n(t.resolve(process.cwd(), s)).href : s.href;
|
|
369
|
+
var s;
|
|
370
|
+
const i = t.extname(new URL(r).pathname).toLowerCase();
|
|
371
|
+
return ".ts" !== i && ".tsx" !== i || await $(), import(r);
|
|
215
372
|
}
|
|
216
|
-
async function
|
|
217
|
-
const
|
|
218
|
-
debug: (t) =>
|
|
219
|
-
log: (t) =>
|
|
220
|
-
info: (t) =>
|
|
221
|
-
warn: (t) =>
|
|
222
|
-
error: (t) =>
|
|
223
|
-
}, { render:
|
|
373
|
+
async function U(t, e, n) {
|
|
374
|
+
const s = n.notifier ?? (await import("@sheetxl/sdk")).Notifier, i = r({
|
|
375
|
+
debug: (t) => s.debug(t),
|
|
376
|
+
log: (t) => s.log(t),
|
|
377
|
+
info: (t) => s.log(t),
|
|
378
|
+
warn: (t) => s.warn(t),
|
|
379
|
+
error: (t) => s.error(t)
|
|
380
|
+
}, { render: n.render });
|
|
224
381
|
return {
|
|
225
382
|
ctx: {
|
|
226
|
-
args: e
|
|
383
|
+
args: e ?? {
|
|
227
384
|
raw: [],
|
|
228
385
|
kv: {},
|
|
229
386
|
_: []
|
|
@@ -234,56 +391,63 @@ async function k(t, e) {
|
|
|
234
391
|
error: i.error
|
|
235
392
|
},
|
|
236
393
|
channels: i,
|
|
237
|
-
notifier:
|
|
394
|
+
notifier: s
|
|
238
395
|
};
|
|
239
396
|
}
|
|
240
|
-
var
|
|
241
|
-
const
|
|
242
|
-
let
|
|
243
|
-
const
|
|
397
|
+
var j = async (n, r, i) => {
|
|
398
|
+
const o = i.target, a = Array.isArray(o) ? o : [o], c = await Promise.all(a.map((n) => (async (n, r = {}) => {
|
|
399
|
+
let s = null;
|
|
400
|
+
const i = (t, e) => {
|
|
244
401
|
let n = t?.default;
|
|
245
402
|
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
403
|
return n;
|
|
247
404
|
};
|
|
248
|
-
if ("function" == typeof n)
|
|
405
|
+
if ("function" == typeof n) s = n;
|
|
249
406
|
else if ("string" == typeof n || n instanceof URL) {
|
|
250
407
|
let o = null;
|
|
251
|
-
if ("string" != typeof n || /^[a-z]+:\/\//i.test(n)) o = await
|
|
408
|
+
if ("string" != typeof n || /^[a-z]+:\/\//i.test(n)) o = await A(n);
|
|
252
409
|
else {
|
|
253
|
-
const
|
|
254
|
-
if (!e.existsSync(
|
|
255
|
-
e.accessSync(
|
|
410
|
+
const s = t.resolve(r.cwd ?? process.cwd(), n);
|
|
411
|
+
if (!e.existsSync(s)) throw new Error(`Script not found: ${s}`);
|
|
412
|
+
e.accessSync(s, e.constants.R_OK), o = await A(s);
|
|
256
413
|
}
|
|
257
|
-
|
|
414
|
+
s = i(o, String(n));
|
|
258
415
|
} else if ("code" in n) {
|
|
259
416
|
const t = n.filename ?? "inline.ts";
|
|
260
417
|
let e, r = null;
|
|
261
|
-
t.endsWith(".ts") || t.endsWith(".tsx") ? (await
|
|
418
|
+
t.endsWith(".ts") || t.endsWith(".tsx") ? (await $(), await P(), e = `${L}${encodeURIComponent(n.code)}`, r = await import(e)) : (await P(), e = `${M}${encodeURIComponent(n.code)}`, r = await import(e)), s = i(r, t);
|
|
262
419
|
} else {
|
|
263
420
|
if (!("runner" in n)) throw new Error("Invalid run target specified.");
|
|
264
|
-
|
|
421
|
+
s = n.runner;
|
|
265
422
|
}
|
|
266
|
-
return
|
|
267
|
-
})(n, i))),
|
|
268
|
-
let
|
|
269
|
-
const
|
|
270
|
-
for (let t = 0; t <
|
|
271
|
-
const e =
|
|
272
|
-
|
|
273
|
-
const
|
|
274
|
-
let
|
|
423
|
+
return s;
|
|
424
|
+
})(n, i))), l = Date.now();
|
|
425
|
+
let u, p = n, d = null;
|
|
426
|
+
const f = c.length;
|
|
427
|
+
for (let t = 0; t < f; t++) {
|
|
428
|
+
const e = c[t], { ctx: n, channels: o, notifier: a } = await U(p, r, i);
|
|
429
|
+
d = a;
|
|
430
|
+
const l = Date.now();
|
|
431
|
+
let m;
|
|
432
|
+
const h = p, g = (t) => Promise.resolve().then(() => e(t));
|
|
275
433
|
try {
|
|
276
|
-
|
|
434
|
+
m = await I(null !== h ? Promise.resolve(h.doBatch((t, e) => g({
|
|
435
|
+
...n,
|
|
436
|
+
wb: e
|
|
437
|
+
}), "Run Script")) : g(n), i.timeoutMs, "Runner timed out");
|
|
277
438
|
} finally {
|
|
278
|
-
await
|
|
439
|
+
await o.flush({ timeoutMs: s(i.logTimeoutMs) });
|
|
279
440
|
}
|
|
280
|
-
const
|
|
281
|
-
null !=
|
|
441
|
+
const y = Date.now();
|
|
442
|
+
u = m, null != m && m.isIWorkbook && (p = m), a.debug(`Run ${1 === f ? "" : `${t + 1}/${f} `}completed in ${y - l} ms.`);
|
|
282
443
|
}
|
|
283
|
-
if (
|
|
444
|
+
if (f > 1 && d) {
|
|
284
445
|
const t = Date.now();
|
|
285
|
-
|
|
446
|
+
d.debug(`All runs completed in ${t - l} ms.`);
|
|
286
447
|
}
|
|
287
|
-
return
|
|
448
|
+
return u;
|
|
449
|
+
}, O = { run: async (t, e, n) => {
|
|
450
|
+
const { withScriptRuntime: r } = await import("@sheetxl/sdk");
|
|
451
|
+
return r(() => j(t, e, n));
|
|
288
452
|
} };
|
|
289
|
-
export {
|
|
453
|
+
export { a as Snippet, O as default, R as diagnoseRun, K as isExplainable, o as resolvePath };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sheetxl/runner",
|
|
3
3
|
"description": "SheetXL - Programmatic execution for SheetXL scripts",
|
|
4
|
-
"version": "0.8.0-beta.
|
|
4
|
+
"version": "0.8.0-beta.11",
|
|
5
5
|
"license": "SEE LICENSE IN <LICENSE>",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -36,18 +36,18 @@
|
|
|
36
36
|
"runner"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@sheetxl/io": "^0.8.0-beta.
|
|
40
|
-
"@sheetxl/primitives": "^0.8.0-beta.
|
|
41
|
-
"@sheetxl/scripting": "^0.8.0-beta.
|
|
42
|
-
"@sheetxl/sdk": "^0.8.0-beta.
|
|
43
|
-
"@sheetxl/utils": "^0.8.0-beta.
|
|
39
|
+
"@sheetxl/io": "^0.8.0-beta.11",
|
|
40
|
+
"@sheetxl/primitives": "^0.8.0-beta.11",
|
|
41
|
+
"@sheetxl/scripting": "^0.8.0-beta.11",
|
|
42
|
+
"@sheetxl/sdk": "^0.8.0-beta.11",
|
|
43
|
+
"@sheetxl/utils": "^0.8.0-beta.11"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"typescript": "^5.9.0 || ^6.0.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@types/node": "^26.
|
|
50
|
-
"tsx": "^4.23.
|
|
49
|
+
"@types/node": "^26.6.4",
|
|
50
|
+
"tsx": "^4.23.15",
|
|
51
51
|
"typescript": "^5.9.0 || ^6.0.0"
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Diagnostic } from '@sheetxl/scripting';
|
|
2
|
+
/**
|
|
3
|
+
* What a run did that a type check may explain: it threw, or a snippet's final expression came
|
|
4
|
+
* back `undefined`.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* `undefined` is a symptom because the SheetXL API never returns it - `null` is the empty answer.
|
|
8
|
+
* A read that produced `undefined` read something that is not there.
|
|
9
|
+
*/
|
|
10
|
+
export type RunSymptom = 'threw' | 'undefined';
|
|
11
|
+
/**
|
|
12
|
+
* Whether a failure is one a type check can explain, by the error's `name`. A failure with no
|
|
13
|
+
* name (a thrown string, an error that crossed a wire as its message) is checked too.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isExplainable(errorName: string | undefined): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Type-checks the source of a run that has already gone wrong, and returns the findings that can
|
|
18
|
+
* explain it.
|
|
19
|
+
*
|
|
20
|
+
* @remarks
|
|
21
|
+
* A run is never type-checked before it executes: the types are for discovery, not enforcement,
|
|
22
|
+
* and most of what a strict check reports about code written to run once (an unannotated `[]`,
|
|
23
|
+
* `catch (e)`, a field added to `{}`) runs correctly. A failed run leaves nothing behind, so
|
|
24
|
+
* running first costs nothing, and the check is paid only by a run with a symptom.
|
|
25
|
+
*
|
|
26
|
+
* The one implementation behind `sheetxl -e` and the MCP `run` tool, so both answer alike.
|
|
27
|
+
*
|
|
28
|
+
* Positions are in `source` as given - a snippet is checked in its wrapper and mapped back.
|
|
29
|
+
* A `threw` finding is an error; an `undefined` one is a warning, as the run completed.
|
|
30
|
+
* Never throws: a diagnosis that fails must not replace the failure it was diagnosing.
|
|
31
|
+
*/
|
|
32
|
+
export declare function diagnoseRun(source: string, symptom: RunSymptom): Promise<Diagnostic[]>;
|
|
33
|
+
//# sourceMappingURL=RunDiagnosis.d.ts.map
|
package/types/src/Runner.d.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { Runner } from './Types';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Runs the pipeline with the `SheetXL` global installed.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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).
|
|
5
|
+
* @remarks
|
|
6
|
+
* The declarations a script is written against promise `SheetXL.ISheet.Visibility.Hidden` is a
|
|
7
|
+
* VALUE. A compiled macro gets it from the macro runtime; source run here is type-stripped and
|
|
8
|
+
* imported, so nothing would define it. The install spans module LOADING too, not only the call —
|
|
9
|
+
* a script may read an enum at its top level — and is removed however the run ends.
|
|
12
10
|
*/
|
|
13
11
|
export declare const run: Runner;
|
|
14
12
|
declare const _default: {
|
package/types/src/Snippet.d.ts
CHANGED
|
@@ -9,7 +9,16 @@
|
|
|
9
9
|
* contract promises two things a bare paste into an async function does not give them —
|
|
10
10
|
* 1. **implicit await**: nothing in a snippet is ever written `await`, yet a promise-returning
|
|
11
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
|
|
12
|
+
* 2. **the final expression is the result**: exactly like a REPL, or `node -p`;
|
|
13
|
+
* 3. **values are current**: calculation is asynchronous, so a formula set by one statement is
|
|
14
|
+
* settled before the next statement runs — `setFormula('=1+1')` then `getValue()` reads `2`,
|
|
15
|
+
* the way it reads in Excel, rather than the `null` a bare paste would see.
|
|
16
|
+
*
|
|
17
|
+
* **A snippet that is a function is called.** Its value is the function — `async ({ wb }) => …` as
|
|
18
|
+
* the final expression, or a snippet that is only `function main(ctx) { … }` — so it is called with
|
|
19
|
+
* the context, typed as a script's entry would be, and its return is the result. `export default` in
|
|
20
|
+
* front of an arrow or an anonymous function, with nothing else exported, is ceremony for the same
|
|
21
|
+
* thing and runs the same way: the script form is kept for what needs it, a named entry or exports.
|
|
13
22
|
*
|
|
14
23
|
* This is the same problem Node's REPL solves in `lib/internal/repl/await.js`, and it is solved the
|
|
15
24
|
* same way: **parse for real, then rewrite the top-level statements from the AST.** Statement
|
|
@@ -32,9 +41,21 @@
|
|
|
32
41
|
* context parameter) so the identical source compiles on every path: the CLI's type-stripping
|
|
33
42
|
* loader ignores the annotations, and the `ScriptCompiler`'s linter requires them.
|
|
34
43
|
*/
|
|
44
|
+
/**
|
|
45
|
+
* A run of the author's own text inside an emitted source: `length` characters that sit at `at`
|
|
46
|
+
* in the emitted text and came from `from` in the snippet.
|
|
47
|
+
*/
|
|
48
|
+
export interface Span {
|
|
49
|
+
at: number;
|
|
50
|
+
from: number;
|
|
51
|
+
length: number;
|
|
52
|
+
}
|
|
35
53
|
/** How a source will run — see the module remarks for the contract. */
|
|
36
54
|
export type SourceForm = 'script' | 'snippet';
|
|
37
|
-
/**
|
|
55
|
+
/**
|
|
56
|
+
* `script` when the source has a top-level default export; `snippet` otherwise — and when that
|
|
57
|
+
* export is only an entry function (`export default async ({ wb }) => …`), which runs as a snippet.
|
|
58
|
+
*/
|
|
38
59
|
export declare function classify(code: string): Promise<SourceForm>;
|
|
39
60
|
export interface WrapOptions {
|
|
40
61
|
/**
|
|
@@ -55,11 +76,19 @@ export interface Prepared {
|
|
|
55
76
|
*/
|
|
56
77
|
kind: 'expression' | 'statements' | 'verbatim';
|
|
57
78
|
/**
|
|
58
|
-
* Lines of wrapper prologue before the first line of user code
|
|
59
|
-
*
|
|
60
|
-
*
|
|
79
|
+
* Lines of wrapper prologue before the first line of user code. Exact for every kind: the
|
|
80
|
+
* rewrite emits the original trivia, so no line moves. It places LINES only — to point a
|
|
81
|
+
* compiler position back into the snippet, line and column, use {@link toSnippetOffset}.
|
|
61
82
|
*/
|
|
62
83
|
lineOffset: number;
|
|
84
|
+
/** Where the author's text sits within {@link source}, in source order. */
|
|
85
|
+
spans: Span[];
|
|
86
|
+
/**
|
|
87
|
+
* Whether the snippet ends in an expression whose value is its answer — not a statement, not a
|
|
88
|
+
* call to `log`/`warn`/`error`, and not an entry function, which may return nothing as a script
|
|
89
|
+
* may. Such a snippet answering `undefined` read something that is not there.
|
|
90
|
+
*/
|
|
91
|
+
expectsValue: boolean;
|
|
63
92
|
/**
|
|
64
93
|
* Set only when the contract could not be honored — no implicit await, no result. Callers should
|
|
65
94
|
* surface it; a snippet quietly returning `undefined` is worse than one that failed.
|
|
@@ -86,4 +115,14 @@ export declare const DEFAULT_DESCRIPTION = "Run Snippet";
|
|
|
86
115
|
* sidesteps any position mapping — the whole snippet is the expression.
|
|
87
116
|
*/
|
|
88
117
|
export declare function prepare(code: string, options?: WrapOptions): Promise<Prepared>;
|
|
118
|
+
/**
|
|
119
|
+
* Where an offset into a prepared {@link Prepared.source} sits in the snippet the author wrote.
|
|
120
|
+
*
|
|
121
|
+
* @remarks
|
|
122
|
+
* Exact wherever the offset falls in the author's own text, which is where a compiler puts a
|
|
123
|
+
* diagnostic about it. An offset in text the wrapper added has no place in the snippet, so it
|
|
124
|
+
* answers with the nearest thing that does: the author's next character, or the end of their last
|
|
125
|
+
* text when nothing of theirs follows.
|
|
126
|
+
*/
|
|
127
|
+
export declare function toSnippetOffset(prepared: Prepared, offset: number): number;
|
|
89
128
|
//# sourceMappingURL=Snippet.d.ts.map
|
package/types/src/Types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IWorkbook } from '@sheetxl/sdk';
|
|
2
|
-
import { LogRenderer } from '@sheetxl/utils';
|
|
2
|
+
import { LogRenderer, MaybePromise } from '@sheetxl/utils';
|
|
3
3
|
export type Notifier = typeof import('@sheetxl/sdk').Notifier;
|
|
4
4
|
/**
|
|
5
5
|
* Arguments passed after `--` on the CLI (`sheetxl -f <script> [workbook] -- [args...]`).
|
|
@@ -48,6 +48,9 @@ export type RunContext = {
|
|
|
48
48
|
* Variadic and value-taking, like `console.log`: `log('rows:', n)` and `log(range.getStats())`
|
|
49
49
|
* both work. An SDK object renders as its markdown report when the host supplies a renderer
|
|
50
50
|
* (the CLI does); otherwise it falls back to JSON.
|
|
51
|
+
*
|
|
52
|
+
* A promise is awaited and logs as its settled value, so `log(sheet.evaluate(…))` needs no
|
|
53
|
+
* `await`. Output order is still call order.
|
|
51
54
|
*/
|
|
52
55
|
readonly log: (...args: any[]) => void;
|
|
53
56
|
/** Diagnostics: something surprising but survivable. Travels separately from `log` (stderr). */
|
|
@@ -57,8 +60,19 @@ export type RunContext = {
|
|
|
57
60
|
};
|
|
58
61
|
/**
|
|
59
62
|
* The function signature for a script run by the CLI or the MCP `run` tool.
|
|
63
|
+
*
|
|
64
|
+
* @remarks
|
|
65
|
+
* The return value is the run's RESULT, the same contract a snippet's final expression has, so it
|
|
66
|
+
* is deliberately unconstrained — a tally, an `ICellRange`, a `getStats()` object. Returning
|
|
67
|
+
* nothing is normal: a run whose output is its `log` has no answer to hand back.
|
|
68
|
+
*
|
|
69
|
+
* An `IWorkbook` is the one return that is also *structural*: it becomes the workbook the next
|
|
70
|
+
* stage runs against, on top of being the result. Nothing else is inspected — an array is just an
|
|
71
|
+
* array.
|
|
72
|
+
*
|
|
73
|
+
* Sync or async, both real: `function main(ctx): number[]` is as valid as the `async` spelling.
|
|
60
74
|
*/
|
|
61
|
-
export type RunFunction = (ctx: RunContext) =>
|
|
75
|
+
export type RunFunction = (ctx: RunContext) => MaybePromise<IWorkbook | any | void>;
|
|
62
76
|
/**
|
|
63
77
|
* Possible targets for the runner to execute
|
|
64
78
|
*/
|
|
@@ -69,7 +83,17 @@ export type RunTarget = string | URL | {
|
|
|
69
83
|
runner: RunFunction;
|
|
70
84
|
};
|
|
71
85
|
export interface RunOptions {
|
|
72
|
-
|
|
86
|
+
/**
|
|
87
|
+
* What to run — a path, a URL, inline code, or a function.
|
|
88
|
+
*
|
|
89
|
+
* @remarks
|
|
90
|
+
* An array runs as a serial pipeline: each stage gets the workbook the one before it left, and
|
|
91
|
+
* the run answers with the LAST stage's return value. That makes a chain lossy in one corner —
|
|
92
|
+
* an early stage that swapped the workbook is only visible if the last stage hands it back — so
|
|
93
|
+
* a host that needs per-stage reporting calls `run` once per target instead, which is what the
|
|
94
|
+
* CLI does (it owns the error report for the target that failed).
|
|
95
|
+
*/
|
|
96
|
+
target: RunTarget | RunTarget[];
|
|
73
97
|
/** The host's output sink (toasts on a UI host, the console on the CLI). Not exposed to scripts. */
|
|
74
98
|
notifier?: Notifier;
|
|
75
99
|
/**
|
|
@@ -82,6 +106,18 @@ export interface RunOptions {
|
|
|
82
106
|
render?: LogRenderer;
|
|
83
107
|
signal?: AbortSignal;
|
|
84
108
|
timeoutMs?: number;
|
|
109
|
+
/**
|
|
110
|
+
* How long a finished stage waits for what it logged to settle, in milliseconds. `0` waits
|
|
111
|
+
* indefinitely.
|
|
112
|
+
*
|
|
113
|
+
* @remarks
|
|
114
|
+
* `log(promise)` prints what the promise settles to, so a stage is not done until its log is. A
|
|
115
|
+
* value still unsettled when this elapses prints as `[pending]`; nothing is thrown and the rest
|
|
116
|
+
* of the log is kept. Independent of `timeoutMs`, which bounds the script itself.
|
|
117
|
+
*
|
|
118
|
+
* @defaultValue `DEFAULT_LOG_TIMEOUT_MS` (10 seconds)
|
|
119
|
+
*/
|
|
120
|
+
logTimeoutMs?: number;
|
|
85
121
|
cwd?: string;
|
|
86
122
|
ts?: {
|
|
87
123
|
enabled?: boolean;
|
|
@@ -90,6 +126,24 @@ export interface RunOptions {
|
|
|
90
126
|
}
|
|
91
127
|
/**
|
|
92
128
|
* Run any RunFunction with a built in context.
|
|
129
|
+
*
|
|
130
|
+
* @remarks
|
|
131
|
+
* The two data inputs are positional — the workbook the run is against, and the args it was given.
|
|
132
|
+
* Everything else is host wiring and lives in {@link RunOptions}, including `target`, which is why
|
|
133
|
+
* the options are required rather than optional.
|
|
134
|
+
*
|
|
135
|
+
* **Hands back exactly what the entry returned**, undisturbed — see {@link RunFunction}. A host
|
|
136
|
+
* that also needs the workbook the run ended on reads it off that value when it is one:
|
|
137
|
+
*
|
|
138
|
+
* ```ts
|
|
139
|
+
* const result = await run(wb, args, { target: 'transform.ts' });
|
|
140
|
+
* const ended = (result as IWorkbook)?.isIWorkbook ? result as IWorkbook : wb;
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* Always a promise, even for a sync entry: resolving a target loads modules.
|
|
144
|
+
*
|
|
145
|
+
* `args` is spelled `ArgV | undefined` rather than `args?` because TypeScript will not let an
|
|
146
|
+
* optional parameter precede a required one — a run with no args passes `undefined` for it.
|
|
93
147
|
*/
|
|
94
|
-
export type Runner = (workbook: IWorkbook | null,
|
|
148
|
+
export type Runner = (workbook: IWorkbook | null, args: ArgV | undefined, options: RunOptions) => Promise<IWorkbook | any | void>;
|
|
95
149
|
//# sourceMappingURL=Types.d.ts.map
|