windmill-cli 1.738.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 +362 -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,
|
|
@@ -17428,6 +17429,7 @@ __export(exports_services_gen, {
|
|
|
17428
17429
|
getSharedUiVersion: () => getSharedUiVersion,
|
|
17429
17430
|
getSharedUi: () => getSharedUi,
|
|
17430
17431
|
getSettings: () => getSettings,
|
|
17432
|
+
getSessionWorkspaceStatus: () => getSessionWorkspaceStatus,
|
|
17431
17433
|
getSecondaryStorageNames: () => getSecondaryStorageNames,
|
|
17432
17434
|
getScriptLatestVersion: () => getScriptLatestVersion,
|
|
17433
17435
|
getScriptHistoryByPath: () => getScriptHistoryByPath,
|
|
@@ -17529,6 +17531,7 @@ __export(exports_services_gen, {
|
|
|
17529
17531
|
getFlowDeploymentStatus: () => getFlowDeploymentStatus,
|
|
17530
17532
|
getFlowDebugInfo: () => getFlowDebugInfo,
|
|
17531
17533
|
getFlowByPath: () => getFlowByPath,
|
|
17534
|
+
getFlowAllLogsStructured: () => getFlowAllLogsStructured,
|
|
17532
17535
|
getFlowAllLogs: () => getFlowAllLogs,
|
|
17533
17536
|
getEmailTrigger: () => getEmailTrigger,
|
|
17534
17537
|
getDraftForUser: () => getDraftForUser,
|
|
@@ -17826,14 +17829,21 @@ var backendVersion = () => {
|
|
|
17826
17829
|
method: "GET",
|
|
17827
17830
|
url: "/ee_license"
|
|
17828
17831
|
});
|
|
17829
|
-
},
|
|
17832
|
+
}, searchDocs = (data3) => {
|
|
17830
17833
|
return request(OpenAPI, {
|
|
17831
|
-
method: "
|
|
17832
|
-
url: "/
|
|
17833
|
-
|
|
17834
|
-
|
|
17835
|
-
|
|
17836
|
-
|
|
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
|
|
17837
17847
|
}
|
|
17838
17848
|
});
|
|
17839
17849
|
}, getOpenApiYaml = () => {
|
|
@@ -18120,6 +18130,13 @@ var backendVersion = () => {
|
|
|
18120
18130
|
method: "GET",
|
|
18121
18131
|
url: "/workspaces/users"
|
|
18122
18132
|
});
|
|
18133
|
+
}, getSessionWorkspaceStatus = (data3) => {
|
|
18134
|
+
return request(OpenAPI, {
|
|
18135
|
+
method: "POST",
|
|
18136
|
+
url: "/workspaces/session_workspace_status",
|
|
18137
|
+
body: data3.requestBody,
|
|
18138
|
+
mediaType: "application/json"
|
|
18139
|
+
});
|
|
18123
18140
|
}, getWorkspaceAsSuperAdmin = (data3) => {
|
|
18124
18141
|
return request(OpenAPI, {
|
|
18125
18142
|
method: "GET",
|
|
@@ -21762,6 +21779,7 @@ var backendVersion = () => {
|
|
|
21762
21779
|
query: {
|
|
21763
21780
|
include_header: data3.includeHeader,
|
|
21764
21781
|
invisible_to_owner: data3.invisibleToOwner,
|
|
21782
|
+
timeout: data3.timeout,
|
|
21765
21783
|
job_id: data3.jobId
|
|
21766
21784
|
},
|
|
21767
21785
|
body: data3.requestBody,
|
|
@@ -22271,6 +22289,15 @@ var backendVersion = () => {
|
|
|
22271
22289
|
id: data3.id
|
|
22272
22290
|
}
|
|
22273
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
|
+
});
|
|
22274
22301
|
}, getCompletedJobLogsTail = (data3) => {
|
|
22275
22302
|
return request(OpenAPI, {
|
|
22276
22303
|
method: "GET",
|
|
@@ -25501,7 +25528,7 @@ var init_auth = __esm(async () => {
|
|
|
25501
25528
|
});
|
|
25502
25529
|
|
|
25503
25530
|
// src/core/constants.ts
|
|
25504
|
-
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.
|
|
25531
|
+
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.740.0";
|
|
25505
25532
|
|
|
25506
25533
|
// src/utils/git.ts
|
|
25507
25534
|
var exports_git = {};
|
|
@@ -85743,6 +85770,11 @@ inspect asset-driven pipelines (scripts marked \`// pipeline\`, wired by \`// on
|
|
|
85743
85770
|
- \`--json\` - Output as JSON (for piping to jq)
|
|
85744
85771
|
- \`pipeline show <folder:string>\` - render a pipeline folder's DAG (sources, lineage, subscriptions) in the terminal
|
|
85745
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).
|
|
85746
85778
|
|
|
85747
85779
|
### protection-rules
|
|
85748
85780
|
|
|
@@ -92581,7 +92613,7 @@ await __promiseAll([
|
|
|
92581
92613
|
async function docs(opts, query) {
|
|
92582
92614
|
await requireLogin(opts);
|
|
92583
92615
|
const workspace = await resolveWorkspace(opts);
|
|
92584
|
-
const url = `${workspace.remote}api/
|
|
92616
|
+
const url = `${workspace.remote}api/docs/search?query=${encodeURIComponent(query)}`;
|
|
92585
92617
|
console.log(colors.bold(`
|
|
92586
92618
|
Searching Windmill docs...
|
|
92587
92619
|
`));
|
|
@@ -92589,55 +92621,36 @@ Searching Windmill docs...
|
|
|
92589
92621
|
let res;
|
|
92590
92622
|
try {
|
|
92591
92623
|
res = await fetch(url, {
|
|
92592
|
-
method: "
|
|
92624
|
+
method: "GET",
|
|
92593
92625
|
headers: {
|
|
92594
|
-
"Content-Type": "application/json",
|
|
92595
92626
|
Authorization: `Bearer ${workspace.token}`,
|
|
92596
92627
|
...extraHeaders
|
|
92597
|
-
}
|
|
92598
|
-
body: JSON.stringify({ query })
|
|
92628
|
+
}
|
|
92599
92629
|
});
|
|
92600
92630
|
} catch (e) {
|
|
92601
92631
|
throw new Error(`Network error connecting to ${workspace.remote}: ${e}`);
|
|
92602
92632
|
}
|
|
92603
92633
|
await detectAuthGatewayChallenge(res, url);
|
|
92604
|
-
if (res.status === 403) {
|
|
92605
|
-
info("Windmill documentation search is an Enterprise Edition feature. Please upgrade to use this command.");
|
|
92606
|
-
return;
|
|
92607
|
-
}
|
|
92608
92634
|
if (!res.ok) {
|
|
92609
92635
|
throw new Error(`Documentation search failed: ${res.status} ${res.statusText}
|
|
92610
92636
|
${await res.text()}`);
|
|
92611
92637
|
}
|
|
92612
92638
|
const data3 = await res.json();
|
|
92613
|
-
const
|
|
92614
|
-
if (
|
|
92615
|
-
|
|
92639
|
+
const items = data3.results ?? [];
|
|
92640
|
+
if (opts.json) {
|
|
92641
|
+
console.log(JSON.stringify(items, null, 2));
|
|
92616
92642
|
return;
|
|
92617
92643
|
}
|
|
92618
|
-
let parsed;
|
|
92619
|
-
try {
|
|
92620
|
-
parsed = JSON.parse(raw);
|
|
92621
|
-
} catch {
|
|
92622
|
-
throw new Error("Failed to parse documentation response.");
|
|
92623
|
-
}
|
|
92624
|
-
const items = parsed.content ?? [];
|
|
92625
92644
|
if (items.length === 0) {
|
|
92626
92645
|
info("No documentation found for this query.");
|
|
92627
92646
|
return;
|
|
92628
92647
|
}
|
|
92629
|
-
if (opts.json) {
|
|
92630
|
-
console.log(JSON.stringify(items, null, 2));
|
|
92631
|
-
return;
|
|
92632
|
-
}
|
|
92633
92648
|
for (const item of items) {
|
|
92634
92649
|
console.log(colors.bold(colors.cyan(`\uD83D\uDCC4 ${item.title}`)));
|
|
92635
92650
|
if (item.url) {
|
|
92636
92651
|
console.log(` ${colors.underline(item.url)}`);
|
|
92637
92652
|
}
|
|
92638
|
-
const
|
|
92639
|
-
if (text) {
|
|
92640
|
-
const snippet = text.length > 500 ? text.slice(0, 500) + "..." : text;
|
|
92653
|
+
for (const snippet of item.snippets ?? []) {
|
|
92641
92654
|
console.log(` ${snippet}`);
|
|
92642
92655
|
}
|
|
92643
92656
|
console.log();
|
|
@@ -94672,6 +94685,191 @@ await __promiseAll([
|
|
|
94672
94685
|
init_auth(),
|
|
94673
94686
|
init_context()
|
|
94674
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
|
|
94675
94873
|
async function apiGet(path23) {
|
|
94676
94874
|
const response = await fetch(`${OpenAPI.BASE}${path23}`, {
|
|
94677
94875
|
headers: { Authorization: `Bearer ${OpenAPI.TOKEN}` }
|
|
@@ -94830,7 +95028,132 @@ async function show2(opts, folder) {
|
|
|
94830
95028
|
console.log(lines.join(`
|
|
94831
95029
|
`));
|
|
94832
95030
|
}
|
|
94833
|
-
|
|
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);
|
|
94834
95157
|
var pipeline_default = command41;
|
|
94835
95158
|
|
|
94836
95159
|
// src/commands/ducklake/ducklake.ts
|
|
@@ -94857,11 +95180,11 @@ async function list19(opts) {
|
|
|
94857
95180
|
new Table2().header(["Name"]).padding(2).border(true).body(names.map((name) => [name])).render();
|
|
94858
95181
|
}
|
|
94859
95182
|
}
|
|
94860
|
-
async function
|
|
95183
|
+
async function run6(opts, sql) {
|
|
94861
95184
|
const name = opts.name ?? DEFAULT_DUCKLAKE_NAME;
|
|
94862
95185
|
await runCatalogQuery(opts, "ducklake", name, sql);
|
|
94863
95186
|
}
|
|
94864
|
-
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);
|
|
94865
95188
|
var ducklake_default = command42;
|
|
94866
95189
|
|
|
94867
95190
|
// src/commands/object-storage/object-storage.ts
|