windmill-cli 1.739.0 → 1.740.0
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/esm/main.js +354 -39
- package/package.json +1 -1
package/esm/main.js
CHANGED
|
@@ -16784,7 +16784,7 @@ var init_OpenAPI = __esm(() => {
|
|
|
16784
16784
|
PASSWORD: undefined,
|
|
16785
16785
|
TOKEN: getEnv3("WM_TOKEN"),
|
|
16786
16786
|
USERNAME: undefined,
|
|
16787
|
-
VERSION: "1.
|
|
16787
|
+
VERSION: "1.740.0",
|
|
16788
16788
|
WITH_CREDENTIALS: true,
|
|
16789
16789
|
interceptors: {
|
|
16790
16790
|
request: new Interceptors,
|
|
@@ -17157,6 +17157,7 @@ __export(exports_services_gen, {
|
|
|
17157
17157
|
sendMessageToConversation: () => sendMessageToConversation,
|
|
17158
17158
|
searchLogsIndex: () => searchLogsIndex,
|
|
17159
17159
|
searchJobsIndex: () => searchJobsIndex,
|
|
17160
|
+
searchDocs: () => searchDocs,
|
|
17160
17161
|
s3ResourceInfo: () => s3ResourceInfo,
|
|
17161
17162
|
runWaitResultScriptByPathGet: () => runWaitResultScriptByPathGet,
|
|
17162
17163
|
runWaitResultScriptByPath: () => runWaitResultScriptByPath,
|
|
@@ -17213,12 +17214,12 @@ __export(exports_services_gen, {
|
|
|
17213
17214
|
refreshToken: () => refreshToken,
|
|
17214
17215
|
refreshCustomInstanceUserPwd: () => refreshCustomInstanceUserPwd,
|
|
17215
17216
|
rebuildDependencyMap: () => rebuildDependencyMap,
|
|
17217
|
+
readDocsPage: () => readDocsPage,
|
|
17216
17218
|
rawScriptByPathTokened: () => rawScriptByPathTokened,
|
|
17217
17219
|
rawScriptByPath: () => rawScriptByPath,
|
|
17218
17220
|
rawScriptByHash: () => rawScriptByHash,
|
|
17219
17221
|
queryResourceTypes: () => queryResourceTypes,
|
|
17220
17222
|
queryHubScripts: () => queryHubScripts,
|
|
17221
|
-
queryDocumentation: () => queryDocumentation,
|
|
17222
17223
|
pruneVersions: () => pruneVersions,
|
|
17223
17224
|
previewSchedule: () => previewSchedule,
|
|
17224
17225
|
polarsConnectionSettingsV2: () => polarsConnectionSettingsV2,
|
|
@@ -17530,6 +17531,7 @@ __export(exports_services_gen, {
|
|
|
17530
17531
|
getFlowDeploymentStatus: () => getFlowDeploymentStatus,
|
|
17531
17532
|
getFlowDebugInfo: () => getFlowDebugInfo,
|
|
17532
17533
|
getFlowByPath: () => getFlowByPath,
|
|
17534
|
+
getFlowAllLogsStructured: () => getFlowAllLogsStructured,
|
|
17533
17535
|
getFlowAllLogs: () => getFlowAllLogs,
|
|
17534
17536
|
getEmailTrigger: () => getEmailTrigger,
|
|
17535
17537
|
getDraftForUser: () => getDraftForUser,
|
|
@@ -17827,14 +17829,21 @@ var backendVersion = () => {
|
|
|
17827
17829
|
method: "GET",
|
|
17828
17830
|
url: "/ee_license"
|
|
17829
17831
|
});
|
|
17830
|
-
},
|
|
17832
|
+
}, searchDocs = (data3) => {
|
|
17831
17833
|
return request(OpenAPI, {
|
|
17832
|
-
method: "
|
|
17833
|
-
url: "/
|
|
17834
|
-
|
|
17835
|
-
|
|
17836
|
-
|
|
17837
|
-
|
|
17834
|
+
method: "GET",
|
|
17835
|
+
url: "/docs/search",
|
|
17836
|
+
query: {
|
|
17837
|
+
query: data3.query
|
|
17838
|
+
}
|
|
17839
|
+
});
|
|
17840
|
+
}, readDocsPage = (data3) => {
|
|
17841
|
+
return request(OpenAPI, {
|
|
17842
|
+
method: "GET",
|
|
17843
|
+
url: "/docs/page",
|
|
17844
|
+
query: {
|
|
17845
|
+
url: data3.url,
|
|
17846
|
+
section: data3.section
|
|
17838
17847
|
}
|
|
17839
17848
|
});
|
|
17840
17849
|
}, getOpenApiYaml = () => {
|
|
@@ -21770,6 +21779,7 @@ var backendVersion = () => {
|
|
|
21770
21779
|
query: {
|
|
21771
21780
|
include_header: data3.includeHeader,
|
|
21772
21781
|
invisible_to_owner: data3.invisibleToOwner,
|
|
21782
|
+
timeout: data3.timeout,
|
|
21773
21783
|
job_id: data3.jobId
|
|
21774
21784
|
},
|
|
21775
21785
|
body: data3.requestBody,
|
|
@@ -22279,6 +22289,15 @@ var backendVersion = () => {
|
|
|
22279
22289
|
id: data3.id
|
|
22280
22290
|
}
|
|
22281
22291
|
});
|
|
22292
|
+
}, getFlowAllLogsStructured = (data3) => {
|
|
22293
|
+
return request(OpenAPI, {
|
|
22294
|
+
method: "GET",
|
|
22295
|
+
url: "/w/{workspace}/jobs_u/get_flow_all_logs_structured/{id}",
|
|
22296
|
+
path: {
|
|
22297
|
+
workspace: data3.workspace,
|
|
22298
|
+
id: data3.id
|
|
22299
|
+
}
|
|
22300
|
+
});
|
|
22282
22301
|
}, getCompletedJobLogsTail = (data3) => {
|
|
22283
22302
|
return request(OpenAPI, {
|
|
22284
22303
|
method: "GET",
|
|
@@ -25509,7 +25528,7 @@ var init_auth = __esm(async () => {
|
|
|
25509
25528
|
});
|
|
25510
25529
|
|
|
25511
25530
|
// src/core/constants.ts
|
|
25512
|
-
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.
|
|
25531
|
+
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.740.0";
|
|
25513
25532
|
|
|
25514
25533
|
// src/utils/git.ts
|
|
25515
25534
|
var exports_git = {};
|
|
@@ -85751,6 +85770,11 @@ inspect asset-driven pipelines (scripts marked \`// pipeline\`, wired by \`// on
|
|
|
85751
85770
|
- \`--json\` - Output as JSON (for piping to jq)
|
|
85752
85771
|
- \`pipeline show <folder:string>\` - render a pipeline folder's DAG (sources, lineage, subscriptions) in the terminal
|
|
85753
85772
|
- \`--json\` - Output the raw asset graph as JSON
|
|
85773
|
+
- \`pipeline run <folder:string>\` - run a bounded cascade: from a schedule/manual root, fan downstream up to the --to end node(s)
|
|
85774
|
+
- \`--from <script:string>\` - Start script (short name or path). Defaults to the folder's sole schedule/manual root.
|
|
85775
|
+
- \`--to <node:string>\` - End node(s) to stop at — script names/paths or asset URIs (e.g. datatable://main/staged). Repeatable or comma-separated. Omit to run the full downstream.
|
|
85776
|
+
- \`--dry-run\` - Print the topological run plan without executing.
|
|
85777
|
+
- \`--json\` - Output the plan as JSON (for piping to jq).
|
|
85754
85778
|
|
|
85755
85779
|
### protection-rules
|
|
85756
85780
|
|
|
@@ -92589,7 +92613,7 @@ await __promiseAll([
|
|
|
92589
92613
|
async function docs(opts, query) {
|
|
92590
92614
|
await requireLogin(opts);
|
|
92591
92615
|
const workspace = await resolveWorkspace(opts);
|
|
92592
|
-
const url = `${workspace.remote}api/
|
|
92616
|
+
const url = `${workspace.remote}api/docs/search?query=${encodeURIComponent(query)}`;
|
|
92593
92617
|
console.log(colors.bold(`
|
|
92594
92618
|
Searching Windmill docs...
|
|
92595
92619
|
`));
|
|
@@ -92597,55 +92621,36 @@ Searching Windmill docs...
|
|
|
92597
92621
|
let res;
|
|
92598
92622
|
try {
|
|
92599
92623
|
res = await fetch(url, {
|
|
92600
|
-
method: "
|
|
92624
|
+
method: "GET",
|
|
92601
92625
|
headers: {
|
|
92602
|
-
"Content-Type": "application/json",
|
|
92603
92626
|
Authorization: `Bearer ${workspace.token}`,
|
|
92604
92627
|
...extraHeaders
|
|
92605
|
-
}
|
|
92606
|
-
body: JSON.stringify({ query })
|
|
92628
|
+
}
|
|
92607
92629
|
});
|
|
92608
92630
|
} catch (e) {
|
|
92609
92631
|
throw new Error(`Network error connecting to ${workspace.remote}: ${e}`);
|
|
92610
92632
|
}
|
|
92611
92633
|
await detectAuthGatewayChallenge(res, url);
|
|
92612
|
-
if (res.status === 403) {
|
|
92613
|
-
info("Windmill documentation search is an Enterprise Edition feature. Please upgrade to use this command.");
|
|
92614
|
-
return;
|
|
92615
|
-
}
|
|
92616
92634
|
if (!res.ok) {
|
|
92617
92635
|
throw new Error(`Documentation search failed: ${res.status} ${res.statusText}
|
|
92618
92636
|
${await res.text()}`);
|
|
92619
92637
|
}
|
|
92620
92638
|
const data3 = await res.json();
|
|
92621
|
-
const
|
|
92622
|
-
if (
|
|
92623
|
-
|
|
92639
|
+
const items = data3.results ?? [];
|
|
92640
|
+
if (opts.json) {
|
|
92641
|
+
console.log(JSON.stringify(items, null, 2));
|
|
92624
92642
|
return;
|
|
92625
92643
|
}
|
|
92626
|
-
let parsed;
|
|
92627
|
-
try {
|
|
92628
|
-
parsed = JSON.parse(raw);
|
|
92629
|
-
} catch {
|
|
92630
|
-
throw new Error("Failed to parse documentation response.");
|
|
92631
|
-
}
|
|
92632
|
-
const items = parsed.content ?? [];
|
|
92633
92644
|
if (items.length === 0) {
|
|
92634
92645
|
info("No documentation found for this query.");
|
|
92635
92646
|
return;
|
|
92636
92647
|
}
|
|
92637
|
-
if (opts.json) {
|
|
92638
|
-
console.log(JSON.stringify(items, null, 2));
|
|
92639
|
-
return;
|
|
92640
|
-
}
|
|
92641
92648
|
for (const item of items) {
|
|
92642
92649
|
console.log(colors.bold(colors.cyan(`\uD83D\uDCC4 ${item.title}`)));
|
|
92643
92650
|
if (item.url) {
|
|
92644
92651
|
console.log(` ${colors.underline(item.url)}`);
|
|
92645
92652
|
}
|
|
92646
|
-
const
|
|
92647
|
-
if (text) {
|
|
92648
|
-
const snippet = text.length > 500 ? text.slice(0, 500) + "..." : text;
|
|
92653
|
+
for (const snippet of item.snippets ?? []) {
|
|
92649
92654
|
console.log(` ${snippet}`);
|
|
92650
92655
|
}
|
|
92651
92656
|
console.log();
|
|
@@ -94680,6 +94685,191 @@ await __promiseAll([
|
|
|
94680
94685
|
init_auth(),
|
|
94681
94686
|
init_context()
|
|
94682
94687
|
]);
|
|
94688
|
+
|
|
94689
|
+
// src/commands/pipeline/boundedCascade.ts
|
|
94690
|
+
var SCRIPT_PREFIX = "script:";
|
|
94691
|
+
var scriptNodeId = (path23) => `${SCRIPT_PREFIX}${path23}`;
|
|
94692
|
+
var isScriptNode = (id) => id.startsWith(SCRIPT_PREFIX);
|
|
94693
|
+
var scriptPathOf = (id) => id.slice(SCRIPT_PREFIX.length);
|
|
94694
|
+
var assetNodeId = (kind, path23) => `${kind}:${path23}`;
|
|
94695
|
+
var EVENT_TRIGGER_KINDS = new Set([
|
|
94696
|
+
"kafka",
|
|
94697
|
+
"mqtt",
|
|
94698
|
+
"nats",
|
|
94699
|
+
"postgres",
|
|
94700
|
+
"sqs",
|
|
94701
|
+
"gcp",
|
|
94702
|
+
"email"
|
|
94703
|
+
]);
|
|
94704
|
+
function assetUriToNodeId(uri) {
|
|
94705
|
+
const m3 = uri.match(/^([a-z0-9_]+):\/\/(.+)$/i);
|
|
94706
|
+
if (!m3)
|
|
94707
|
+
return;
|
|
94708
|
+
const prefix = m3[1].toLowerCase();
|
|
94709
|
+
const kind = prefix === "s3" ? "s3object" : prefix;
|
|
94710
|
+
return `${kind}:${m3[2]}`;
|
|
94711
|
+
}
|
|
94712
|
+
function addEdge(dag, a2, b2) {
|
|
94713
|
+
if (a2 === b2)
|
|
94714
|
+
return;
|
|
94715
|
+
dag.nodes.add(a2);
|
|
94716
|
+
dag.nodes.add(b2);
|
|
94717
|
+
(dag.down.get(a2) ?? dag.down.set(a2, new Set).get(a2)).add(b2);
|
|
94718
|
+
(dag.up.get(b2) ?? dag.up.set(b2, new Set).get(b2)).add(a2);
|
|
94719
|
+
}
|
|
94720
|
+
function buildLineageDag(g2) {
|
|
94721
|
+
const dag = { down: new Map, up: new Map, nodes: new Set };
|
|
94722
|
+
for (const r2 of g2.runnables ?? []) {
|
|
94723
|
+
if (r2.usage_kind === "script")
|
|
94724
|
+
dag.nodes.add(scriptNodeId(r2.path));
|
|
94725
|
+
}
|
|
94726
|
+
for (const a2 of g2.assets ?? [])
|
|
94727
|
+
dag.nodes.add(assetNodeId(a2.kind, a2.path));
|
|
94728
|
+
for (const e2 of g2.edges ?? []) {
|
|
94729
|
+
if (e2.runnable_kind !== "script")
|
|
94730
|
+
continue;
|
|
94731
|
+
const aid = assetNodeId(e2.asset_kind, e2.asset_path);
|
|
94732
|
+
const access2 = e2.access_type ?? "r";
|
|
94733
|
+
if (access2 === "w" || access2 === "rw") {
|
|
94734
|
+
addEdge(dag, scriptNodeId(e2.runnable_path), aid);
|
|
94735
|
+
} else if (access2 === "r") {
|
|
94736
|
+
addEdge(dag, aid, scriptNodeId(e2.runnable_path));
|
|
94737
|
+
}
|
|
94738
|
+
}
|
|
94739
|
+
for (const t2 of g2.triggers ?? []) {
|
|
94740
|
+
if (t2.trigger_kind !== "asset" || t2.runnable_kind !== "script")
|
|
94741
|
+
continue;
|
|
94742
|
+
const at = t2;
|
|
94743
|
+
addEdge(dag, assetNodeId(at.asset_kind, at.asset_path), scriptNodeId(at.runnable_path));
|
|
94744
|
+
}
|
|
94745
|
+
return dag;
|
|
94746
|
+
}
|
|
94747
|
+
function closure(adj, start) {
|
|
94748
|
+
const seen = new Set;
|
|
94749
|
+
const queue = [start];
|
|
94750
|
+
while (queue.length > 0) {
|
|
94751
|
+
const cur = queue.shift();
|
|
94752
|
+
for (const n2 of adj.get(cur) ?? []) {
|
|
94753
|
+
if (seen.has(n2))
|
|
94754
|
+
continue;
|
|
94755
|
+
seen.add(n2);
|
|
94756
|
+
queue.push(n2);
|
|
94757
|
+
}
|
|
94758
|
+
}
|
|
94759
|
+
seen.delete(start);
|
|
94760
|
+
return seen;
|
|
94761
|
+
}
|
|
94762
|
+
var descendants = (dag, n2) => closure(dag.down, n2);
|
|
94763
|
+
var ancestors = (dag, n2) => closure(dag.up, n2);
|
|
94764
|
+
function boundedSet(dag, start, ends) {
|
|
94765
|
+
const downSet = new Set(descendants(dag, start));
|
|
94766
|
+
downSet.add(start);
|
|
94767
|
+
const reachableEnds = ends.filter((e2) => downSet.has(e2));
|
|
94768
|
+
const droppedEnds = ends.filter((e2) => !downSet.has(e2));
|
|
94769
|
+
if (reachableEnds.length === 0) {
|
|
94770
|
+
return { nodes: new Set([start]), reachableEnds, droppedEnds };
|
|
94771
|
+
}
|
|
94772
|
+
const upClosure = new Set;
|
|
94773
|
+
for (const e2 of reachableEnds) {
|
|
94774
|
+
upClosure.add(e2);
|
|
94775
|
+
for (const a2 of ancestors(dag, e2))
|
|
94776
|
+
upClosure.add(a2);
|
|
94777
|
+
}
|
|
94778
|
+
const nodes = new Set;
|
|
94779
|
+
for (const n2 of downSet)
|
|
94780
|
+
if (upClosure.has(n2))
|
|
94781
|
+
nodes.add(n2);
|
|
94782
|
+
nodes.add(start);
|
|
94783
|
+
return { nodes, reachableEnds, droppedEnds };
|
|
94784
|
+
}
|
|
94785
|
+
function validStarts(g2) {
|
|
94786
|
+
const subscribers = new Set;
|
|
94787
|
+
const scheduleScripts = new Set;
|
|
94788
|
+
const eventScripts = new Set;
|
|
94789
|
+
for (const t2 of g2.triggers ?? []) {
|
|
94790
|
+
if (t2.runnable_kind !== "script")
|
|
94791
|
+
continue;
|
|
94792
|
+
if (t2.trigger_kind === "asset")
|
|
94793
|
+
subscribers.add(t2.runnable_path);
|
|
94794
|
+
else if (t2.trigger_kind === "schedule")
|
|
94795
|
+
scheduleScripts.add(t2.runnable_path);
|
|
94796
|
+
else if (EVENT_TRIGGER_KINDS.has(t2.trigger_kind))
|
|
94797
|
+
eventScripts.add(t2.runnable_path);
|
|
94798
|
+
}
|
|
94799
|
+
const out = new Set;
|
|
94800
|
+
for (const r2 of g2.runnables ?? []) {
|
|
94801
|
+
if (r2.usage_kind !== "script")
|
|
94802
|
+
continue;
|
|
94803
|
+
const p3 = r2.path;
|
|
94804
|
+
if (scheduleScripts.has(p3))
|
|
94805
|
+
out.add(scriptNodeId(p3));
|
|
94806
|
+
else if (!subscribers.has(p3) && !eventScripts.has(p3))
|
|
94807
|
+
out.add(scriptNodeId(p3));
|
|
94808
|
+
}
|
|
94809
|
+
return out;
|
|
94810
|
+
}
|
|
94811
|
+
function scriptsOf(nodes) {
|
|
94812
|
+
const out = [];
|
|
94813
|
+
for (const id of nodes)
|
|
94814
|
+
if (isScriptNode(id))
|
|
94815
|
+
out.push(scriptPathOf(id));
|
|
94816
|
+
return out;
|
|
94817
|
+
}
|
|
94818
|
+
function resolveToken(g2, token) {
|
|
94819
|
+
if (token.includes("://")) {
|
|
94820
|
+
const id = assetUriToNodeId(token);
|
|
94821
|
+
return id && g2.assets.some((a2) => `${a2.kind}:${a2.path}` === id) ? id : undefined;
|
|
94822
|
+
}
|
|
94823
|
+
const scripts = (g2.runnables ?? []).filter((r2) => r2.usage_kind === "script");
|
|
94824
|
+
const exact = scripts.find((r2) => r2.path === token);
|
|
94825
|
+
if (exact)
|
|
94826
|
+
return scriptNodeId(exact.path);
|
|
94827
|
+
const byShort = scripts.filter((r2) => (r2.path.split("/").pop() ?? r2.path) === token);
|
|
94828
|
+
return byShort.length === 1 ? scriptNodeId(byShort[0].path) : undefined;
|
|
94829
|
+
}
|
|
94830
|
+
function topoOrder(g2, scripts) {
|
|
94831
|
+
const dag = buildLineageDag(g2);
|
|
94832
|
+
const down = new Map;
|
|
94833
|
+
const indegree = new Map;
|
|
94834
|
+
for (const s2 of scripts)
|
|
94835
|
+
indegree.set(s2, 0);
|
|
94836
|
+
for (const s2 of scripts) {
|
|
94837
|
+
const sid = scriptNodeId(s2);
|
|
94838
|
+
const oneHop = new Set;
|
|
94839
|
+
for (const asset of dag.down.get(sid) ?? []) {
|
|
94840
|
+
for (const sub of dag.down.get(asset) ?? []) {
|
|
94841
|
+
if (isScriptNode(sub)) {
|
|
94842
|
+
const p3 = scriptPathOf(sub);
|
|
94843
|
+
if (p3 !== s2 && scripts.has(p3))
|
|
94844
|
+
oneHop.add(p3);
|
|
94845
|
+
}
|
|
94846
|
+
}
|
|
94847
|
+
}
|
|
94848
|
+
if (oneHop.size > 0) {
|
|
94849
|
+
down.set(s2, oneHop);
|
|
94850
|
+
for (const p3 of oneHop)
|
|
94851
|
+
indegree.set(p3, (indegree.get(p3) ?? 0) + 1);
|
|
94852
|
+
}
|
|
94853
|
+
}
|
|
94854
|
+
const ready = [...scripts].filter((s2) => (indegree.get(s2) ?? 0) === 0);
|
|
94855
|
+
const remaining = new Map(indegree);
|
|
94856
|
+
const order = [];
|
|
94857
|
+
while (ready.length > 0) {
|
|
94858
|
+
const n2 = ready.shift();
|
|
94859
|
+
order.push(n2);
|
|
94860
|
+
for (const p3 of down.get(n2) ?? []) {
|
|
94861
|
+
const d3 = (remaining.get(p3) ?? 0) - 1;
|
|
94862
|
+
remaining.set(p3, d3);
|
|
94863
|
+
if (d3 === 0)
|
|
94864
|
+
ready.push(p3);
|
|
94865
|
+
}
|
|
94866
|
+
}
|
|
94867
|
+
const orderedSet = new Set(order);
|
|
94868
|
+
const cyclic = [...scripts].filter((s2) => !orderedSet.has(s2));
|
|
94869
|
+
return { order, cyclic };
|
|
94870
|
+
}
|
|
94871
|
+
|
|
94872
|
+
// src/commands/pipeline/pipeline.ts
|
|
94683
94873
|
async function apiGet(path23) {
|
|
94684
94874
|
const response = await fetch(`${OpenAPI.BASE}${path23}`, {
|
|
94685
94875
|
headers: { Authorization: `Bearer ${OpenAPI.TOKEN}` }
|
|
@@ -94838,7 +95028,132 @@ async function show2(opts, folder) {
|
|
|
94838
95028
|
console.log(lines.join(`
|
|
94839
95029
|
`));
|
|
94840
95030
|
}
|
|
94841
|
-
|
|
95031
|
+
async function waitJob(workspace, id) {
|
|
95032
|
+
const MAX_RETRIES = 6000;
|
|
95033
|
+
for (let i = 0;i < MAX_RETRIES; i++) {
|
|
95034
|
+
try {
|
|
95035
|
+
const r2 = await getCompletedJobResultMaybe({
|
|
95036
|
+
workspace,
|
|
95037
|
+
id,
|
|
95038
|
+
getStarted: false
|
|
95039
|
+
});
|
|
95040
|
+
if (r2.completed)
|
|
95041
|
+
return r2.success === true;
|
|
95042
|
+
} catch {}
|
|
95043
|
+
await new Promise((res) => setTimeout(res, 100));
|
|
95044
|
+
}
|
|
95045
|
+
throw new Error(`Timed out waiting for job ${id}`);
|
|
95046
|
+
}
|
|
95047
|
+
async function run5(opts, folder) {
|
|
95048
|
+
if (opts.json)
|
|
95049
|
+
setSilent(true);
|
|
95050
|
+
const workspace = await resolveWorkspace(opts);
|
|
95051
|
+
await requireLogin(opts);
|
|
95052
|
+
const f3 = folder.replace(/^f\//, "").replace(/\/$/, "");
|
|
95053
|
+
const graph = await apiGet(`/w/${workspace.workspaceId}/assets/graph?folder=${encodeURIComponent(f3)}&asset_kinds=${ASSET_KINDS}`);
|
|
95054
|
+
const starts = validStarts(graph);
|
|
95055
|
+
let start;
|
|
95056
|
+
if (opts.from) {
|
|
95057
|
+
const resolved = resolveToken(graph, opts.from);
|
|
95058
|
+
if (!resolved) {
|
|
95059
|
+
const matches = graph.runnables.filter((r2) => r2.usage_kind === "script" && (r2.path.split("/").pop() ?? r2.path) === opts.from);
|
|
95060
|
+
if (matches.length > 1) {
|
|
95061
|
+
throw new Error(`--from '${opts.from}' matches multiple scripts (${matches.map((r2) => r2.path).sort().join(", ")}) — pass the full path.`);
|
|
95062
|
+
}
|
|
95063
|
+
throw new Error(`--from '${opts.from}' matched no script in f/${f3}.`);
|
|
95064
|
+
}
|
|
95065
|
+
if (!starts.has(resolved)) {
|
|
95066
|
+
throw new Error(`--from '${opts.from}' is not a valid bounded-run start. Starts must be schedule-triggered or manual roots; row-backed event triggers (kafka/mqtt/nats/postgres/sqs/gcp/email) fan out per-event and can't be bounded.`);
|
|
95067
|
+
}
|
|
95068
|
+
start = resolved;
|
|
95069
|
+
} else if (starts.size === 1) {
|
|
95070
|
+
start = [...starts][0];
|
|
95071
|
+
} else if (starts.size === 0) {
|
|
95072
|
+
throw new Error(`No schedule or manual root in f/${f3} to start a bounded run from.`);
|
|
95073
|
+
} else {
|
|
95074
|
+
throw new Error(`f/${f3} has ${starts.size} possible starts — pass --from <script>. Candidates: ${scriptsOf(starts).sort().join(", ")}`);
|
|
95075
|
+
}
|
|
95076
|
+
const toTokens = (opts.to ?? []).flatMap((t2) => t2.split(",")).map((t2) => t2.trim()).filter(Boolean);
|
|
95077
|
+
const ends = [];
|
|
95078
|
+
const unresolved = [];
|
|
95079
|
+
for (const tok of toTokens) {
|
|
95080
|
+
const id = resolveToken(graph, tok);
|
|
95081
|
+
if (!id)
|
|
95082
|
+
unresolved.push(tok);
|
|
95083
|
+
else
|
|
95084
|
+
ends.push(id);
|
|
95085
|
+
}
|
|
95086
|
+
if (unresolved.length > 0) {
|
|
95087
|
+
const details = unresolved.map((tok) => {
|
|
95088
|
+
const matches = graph.runnables.filter((r2) => r2.usage_kind === "script" && (r2.path.split("/").pop() ?? r2.path) === tok);
|
|
95089
|
+
return matches.length > 1 ? `'${tok}' (ambiguous: ${matches.map((r2) => r2.path).sort().join(", ")} — use the full path)` : `'${tok}' (no match in f/${f3})`;
|
|
95090
|
+
});
|
|
95091
|
+
throw new Error(`--to could not be resolved: ${details.join("; ")}.`);
|
|
95092
|
+
}
|
|
95093
|
+
const idLabel = (id) => id.startsWith("script:") ? scriptPathOf(id) : id;
|
|
95094
|
+
const dag = buildLineageDag(graph);
|
|
95095
|
+
let selectedScripts;
|
|
95096
|
+
let reachableEnds = [];
|
|
95097
|
+
let droppedEnds = [];
|
|
95098
|
+
if (ends.length === 0) {
|
|
95099
|
+
const all = new Set(descendants(dag, start));
|
|
95100
|
+
all.add(start);
|
|
95101
|
+
selectedScripts = new Set(scriptsOf(all));
|
|
95102
|
+
} else {
|
|
95103
|
+
const res = boundedSet(dag, start, ends);
|
|
95104
|
+
reachableEnds = res.reachableEnds;
|
|
95105
|
+
droppedEnds = res.droppedEnds;
|
|
95106
|
+
for (const d3 of droppedEnds) {
|
|
95107
|
+
warn(`end '${idLabel(d3)}' is not downstream of the start — ignored.`);
|
|
95108
|
+
}
|
|
95109
|
+
selectedScripts = new Set(scriptsOf(res.nodes));
|
|
95110
|
+
}
|
|
95111
|
+
const { order, cyclic } = topoOrder(graph, selectedScripts);
|
|
95112
|
+
if (cyclic.length > 0) {
|
|
95113
|
+
warn(`Skipping ${cyclic.length} script(s) on a dependency cycle: ${cyclic.sort().join(", ")}`);
|
|
95114
|
+
}
|
|
95115
|
+
if (opts.json) {
|
|
95116
|
+
console.log(JSON.stringify({
|
|
95117
|
+
start: scriptPathOf(start),
|
|
95118
|
+
ends: ends.map(idLabel),
|
|
95119
|
+
reachableEnds: reachableEnds.map(idLabel),
|
|
95120
|
+
droppedEnds: droppedEnds.map(idLabel),
|
|
95121
|
+
order,
|
|
95122
|
+
cyclic
|
|
95123
|
+
}));
|
|
95124
|
+
}
|
|
95125
|
+
if (order.length === 0) {
|
|
95126
|
+
if (!opts.json)
|
|
95127
|
+
info("Nothing to run.");
|
|
95128
|
+
return;
|
|
95129
|
+
}
|
|
95130
|
+
if (opts.dryRun) {
|
|
95131
|
+
if (!opts.json) {
|
|
95132
|
+
info(colors.bold(`Bounded run plan — ${order.length} script${order.length === 1 ? "" : "s"}`) + colors.dim(` (from ${shortName(scriptPathOf(start))})`));
|
|
95133
|
+
order.forEach((p3, i) => info(` ${i + 1}. ${p3}`));
|
|
95134
|
+
}
|
|
95135
|
+
return;
|
|
95136
|
+
}
|
|
95137
|
+
for (const path23 of order) {
|
|
95138
|
+
if (!opts.json)
|
|
95139
|
+
info(colors.gray(`▶ running ${path23}…`));
|
|
95140
|
+
const id = await runScriptByPath({
|
|
95141
|
+
workspace: workspace.workspaceId,
|
|
95142
|
+
path: path23,
|
|
95143
|
+
requestBody: { _wmill_skip_asset_dispatch: true }
|
|
95144
|
+
});
|
|
95145
|
+
const ok = await waitJob(workspace.workspaceId, id);
|
|
95146
|
+
if (!ok) {
|
|
95147
|
+
throw new Error(`Bounded run failed at ${path23} (job ${id}).`);
|
|
95148
|
+
}
|
|
95149
|
+
if (!opts.json)
|
|
95150
|
+
info(colors.green(` ✓ ${path23}`));
|
|
95151
|
+
}
|
|
95152
|
+
if (!opts.json) {
|
|
95153
|
+
info(colors.green.bold(`Bounded run complete — ${order.length} script(s) succeeded.`));
|
|
95154
|
+
}
|
|
95155
|
+
}
|
|
95156
|
+
var command41 = new Command().description("inspect asset-driven pipelines (scripts marked `// pipeline`, wired by `// on <spec>` annotations)").command("list", "list pipeline folders in the workspace").option("--json", "Output as JSON (for piping to jq)").action(list18).command("show", "render a pipeline folder's DAG (sources, lineage, subscriptions) in the terminal").arguments("<folder:string>").option("--json", "Output the raw asset graph as JSON").action(show2).command("run", "run a bounded cascade: from a schedule/manual root, fan downstream up to the --to end node(s)").arguments("<folder:string>").option("--from <script:string>", "Start script (short name or path). Defaults to the folder's sole schedule/manual root.").option("--to <node:string>", "End node(s) to stop at — script names/paths or asset URIs (e.g. datatable://main/staged). Repeatable or comma-separated. Omit to run the full downstream.", { collect: true }).option("--dry-run", "Print the topological run plan without executing.").option("--json", "Output the plan as JSON (for piping to jq).").action(run5);
|
|
94842
95157
|
var pipeline_default = command41;
|
|
94843
95158
|
|
|
94844
95159
|
// src/commands/ducklake/ducklake.ts
|
|
@@ -94865,11 +95180,11 @@ async function list19(opts) {
|
|
|
94865
95180
|
new Table2().header(["Name"]).padding(2).border(true).body(names.map((name) => [name])).render();
|
|
94866
95181
|
}
|
|
94867
95182
|
}
|
|
94868
|
-
async function
|
|
95183
|
+
async function run6(opts, sql) {
|
|
94869
95184
|
const name = opts.name ?? DEFAULT_DUCKLAKE_NAME;
|
|
94870
95185
|
await runCatalogQuery(opts, "ducklake", name, sql);
|
|
94871
95186
|
}
|
|
94872
|
-
var command42 = new Command().description("ducklake related commands").command("list", "list all ducklakes in the workspace").option("--json", "Output as JSON (for piping to jq)").action(list19).command("run", "run a SQL query on a ducklake").arguments("<sql:string>").option("-n --name <name:string>", "Ducklake name (default: main)").option("-s --silent", "Output only the final result as JSON. Useful for scripting.").action(
|
|
95187
|
+
var command42 = new Command().description("ducklake related commands").command("list", "list all ducklakes in the workspace").option("--json", "Output as JSON (for piping to jq)").action(list19).command("run", "run a SQL query on a ducklake").arguments("<sql:string>").option("-n --name <name:string>", "Ducklake name (default: main)").option("-s --silent", "Output only the final result as JSON. Useful for scripting.").action(run6);
|
|
94873
95188
|
var ducklake_default = command42;
|
|
94874
95189
|
|
|
94875
95190
|
// src/commands/object-storage/object-storage.ts
|