@meirblachman/azure-pipelines-visualizer 0.1.13 → 0.1.15

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.
@@ -0,0 +1,1612 @@
1
+ import { jsx as s, jsxs as c, Fragment as et } from "react/jsx-runtime";
2
+ import { useMemo as ze, Component as pt, createContext as ut, useContext as mt, memo as tt, useState as Z, useCallback as fe, useRef as te, useEffect as oe, createElement as ht } from "react";
3
+ import { parseYaml as pe, extractTaskReferences as ft, resolveTaskDocUrl as gt, extractVariableValues as Pe, detectTemplateReferences as Se, extractParameterDefaults as De, buildAdoFileUrl as at, getEffectiveRepoAlias as re, extractDeclaredParameterNames as je, pathHasExpressions as ue, resolveExpressionPath as Ee, resolveTemplateRefPaths as nt, evaluateExpression as _t, resolveTemplateSource as st, parseTemplatePath as vt, resolveAllExpressions as yt, collapsePath as Nt, parseAdoUrl as Pt } from "@apv/core";
4
+ import bt from "@monaco-editor/react";
5
+ import { create as wt } from "zustand";
6
+ import { Handle as He, Position as Ke, getBezierPath as Rt, BaseEdge as Et, EdgeLabelRenderer as xt, MarkerType as xe, useNodesState as kt, useEdgesState as At, ReactFlow as Tt, Background as $t, BackgroundVariant as Ct, Controls as St } from "@xyflow/react";
7
+ import Ye from "@dagrejs/dagre";
8
+ import Dt from "react-dom";
9
+ const Te = wt((t) => ({
10
+ org: "",
11
+ project: "",
12
+ setConnection: (e, a) => t({ org: e, project: a }),
13
+ selectedPipeline: null,
14
+ selectedPipelineLoading: !1,
15
+ selectedPipelineError: null,
16
+ setSelectedPipeline: (e) => t({
17
+ selectedPipeline: e,
18
+ selectedPipelineError: null,
19
+ expandedNodes: /* @__PURE__ */ new Set()
20
+ }),
21
+ setSelectedPipelineLoading: (e) => t({ selectedPipelineLoading: e }),
22
+ setSelectedPipelineError: (e) => t({ selectedPipelineError: e }),
23
+ expandedTemplates: new Map(It()),
24
+ setExpandedTemplate: (e, a) => t((n) => {
25
+ const l = new Map(n.expandedTemplates);
26
+ return l.set(e, a), Ft(l), { expandedTemplates: l };
27
+ }),
28
+ expandedNodes: /* @__PURE__ */ new Set(),
29
+ toggleNode: (e) => t((a) => {
30
+ const n = new Set(a.expandedNodes);
31
+ return n.has(e) ? n.delete(e) : n.add(e), { expandedNodes: n };
32
+ }),
33
+ selectedNodeDetail: null,
34
+ setSelectedNodeDetail: (e) => t({ selectedNodeDetail: e }),
35
+ customTaskDocs: {},
36
+ setCustomTaskDocs: (e) => t({ customTaskDocs: e }),
37
+ taskSchema: /* @__PURE__ */ new Map(),
38
+ setTaskSchema: (e) => t(() => {
39
+ const a = /* @__PURE__ */ new Map();
40
+ for (const n of e)
41
+ a.set(`${n.name}@${n.version}`, n);
42
+ return { taskSchema: a };
43
+ })
44
+ })), ot = "apv-template-cache";
45
+ function It() {
46
+ try {
47
+ const t = localStorage.getItem(ot);
48
+ if (t)
49
+ return JSON.parse(t);
50
+ } catch {
51
+ }
52
+ return [];
53
+ }
54
+ function Ft(t) {
55
+ try {
56
+ const a = Array.from(t.entries()).slice(-100);
57
+ localStorage.setItem(ot, JSON.stringify(a));
58
+ } catch {
59
+ }
60
+ }
61
+ function Lt() {
62
+ const {
63
+ selectedNodeDetail: t,
64
+ customTaskDocs: e,
65
+ taskSchema: a,
66
+ setSelectedNodeDetail: n
67
+ } = Te(), l = ze(() => {
68
+ if (!(t != null && t.yaml)) return [];
69
+ try {
70
+ const o = pe(t.yaml);
71
+ return ft(o ?? {});
72
+ } catch {
73
+ return [];
74
+ }
75
+ }, [t == null ? void 0 : t.yaml]);
76
+ return t ? /* @__PURE__ */ c("div", { className: "detail-panel", children: [
77
+ /* @__PURE__ */ c("div", { className: "detail-panel__header", children: [
78
+ /* @__PURE__ */ c("div", { className: "detail-panel__header-row", children: [
79
+ /* @__PURE__ */ s("h3", { className: "detail-panel__title", children: t.label }),
80
+ /* @__PURE__ */ s(
81
+ "button",
82
+ {
83
+ className: "detail-panel__close",
84
+ onClick: () => n(null),
85
+ "aria-label": "Close detail panel",
86
+ title: "Close",
87
+ children: "✕"
88
+ }
89
+ )
90
+ ] }),
91
+ /* @__PURE__ */ c("div", { className: "detail-panel__path", children: [
92
+ t.filePath,
93
+ t.repoAlias && /* @__PURE__ */ c("span", { className: "detail-panel__repo", children: [
94
+ " ",
95
+ "@",
96
+ t.repoAlias
97
+ ] })
98
+ ] })
99
+ ] }),
100
+ l.length > 0 && /* @__PURE__ */ c("div", { className: "detail-panel__tasks", children: [
101
+ /* @__PURE__ */ c("h4", { className: "detail-panel__section-title", children: [
102
+ "Tasks (",
103
+ l.length,
104
+ ")"
105
+ ] }),
106
+ /* @__PURE__ */ s("ul", { className: "task-list", children: l.map((o) => /* @__PURE__ */ s(
107
+ Ut,
108
+ {
109
+ ref_: o,
110
+ customDocs: e,
111
+ schemaEntry: a.get(o.raw) ?? a.get(`${o.name}@${o.version}`)
112
+ },
113
+ o.raw
114
+ )) })
115
+ ] }),
116
+ /* @__PURE__ */ s("div", { className: "detail-panel__editor", children: /* @__PURE__ */ s(
117
+ bt,
118
+ {
119
+ height: "100%",
120
+ language: "yaml",
121
+ value: t.yaml,
122
+ theme: "vs-dark",
123
+ options: {
124
+ readOnly: !0,
125
+ minimap: { enabled: !1 },
126
+ scrollBeyondLastLine: !1,
127
+ fontSize: 13,
128
+ lineNumbers: "on",
129
+ renderLineHighlight: "none",
130
+ wordWrap: "on",
131
+ padding: { top: 8 }
132
+ }
133
+ }
134
+ ) })
135
+ ] }) : /* @__PURE__ */ s("div", { className: "detail-panel detail-panel--empty", children: /* @__PURE__ */ s("p", { children: "Click a node to view its contents" }) });
136
+ }
137
+ function Ut({
138
+ ref_: t,
139
+ customDocs: e,
140
+ schemaEntry: a
141
+ }) {
142
+ const n = gt(t, e);
143
+ return /* @__PURE__ */ c("li", { className: "task-item", children: [
144
+ /* @__PURE__ */ s("span", { className: "task-item__icon", children: "⚙️" }),
145
+ /* @__PURE__ */ c("div", { className: "task-item__content", children: [
146
+ n ? /* @__PURE__ */ c(
147
+ "a",
148
+ {
149
+ href: n,
150
+ target: "_blank",
151
+ rel: "noopener noreferrer",
152
+ className: "task-item__link",
153
+ title: (a == null ? void 0 : a.description) || `Open docs for ${t.name}`,
154
+ children: [
155
+ t.name,
156
+ /* @__PURE__ */ c("span", { className: "task-item__version", children: [
157
+ "@",
158
+ t.version
159
+ ] }),
160
+ /* @__PURE__ */ s("span", { className: "task-item__external", children: "↗" })
161
+ ]
162
+ }
163
+ ) : /* @__PURE__ */ c("span", { className: "task-item__name", children: [
164
+ t.name,
165
+ /* @__PURE__ */ c("span", { className: "task-item__version", children: [
166
+ "@",
167
+ t.version
168
+ ] })
169
+ ] }),
170
+ (a == null ? void 0 : a.description) && /* @__PURE__ */ s("div", { className: "task-item__description", children: a.description })
171
+ ] })
172
+ ] });
173
+ }
174
+ class Ie extends pt {
175
+ constructor(e) {
176
+ super(e), this.state = { hasError: !1, error: null };
177
+ }
178
+ static getDerivedStateFromError(e) {
179
+ return { hasError: !0, error: e };
180
+ }
181
+ componentDidCatch(e, a) {
182
+ console.error("ErrorBoundary caught:", e, a);
183
+ }
184
+ render() {
185
+ var e;
186
+ return this.state.hasError ? this.props.fallback || /* @__PURE__ */ c("div", { className: "error", children: [
187
+ /* @__PURE__ */ s("h3", { children: "Something went wrong" }),
188
+ /* @__PURE__ */ s("p", { children: (e = this.state.error) == null ? void 0 : e.message }),
189
+ /* @__PURE__ */ s(
190
+ "button",
191
+ {
192
+ onClick: () => this.setState({ hasError: !1, error: null }),
193
+ style: { marginTop: 8, cursor: "pointer" },
194
+ children: "Try again"
195
+ }
196
+ )
197
+ ] }) : this.props.children;
198
+ }
199
+ }
200
+ const rt = ut(null), Vt = rt.Provider;
201
+ function zt() {
202
+ const t = mt(rt);
203
+ if (!t)
204
+ throw new Error(
205
+ "useFileFetch must be used within a FileFetchProvider. Wrap your component tree with <FileFetchProvider value={...}>."
206
+ );
207
+ return t;
208
+ }
209
+ const Xe = 300, Ge = 100;
210
+ function Fe(t, e, a = "TB") {
211
+ const n = new Ye.graphlib.Graph();
212
+ n.setDefaultEdgeLabel(() => ({})), n.setGraph({ rankdir: a, ranksep: 80, nodesep: 40 });
213
+ for (const o of t)
214
+ n.setNode(o.id, { width: Xe, height: Ge });
215
+ for (const o of e)
216
+ n.setEdge(o.source, o.target);
217
+ return Ye.layout(n), { nodes: t.map((o) => {
218
+ const m = n.node(o.id);
219
+ return {
220
+ ...o,
221
+ position: {
222
+ x: m.x - Xe / 2,
223
+ y: m.y - Ge / 2
224
+ }
225
+ };
226
+ }), edges: e };
227
+ }
228
+ function Ot({ data: t }) {
229
+ var m;
230
+ const e = t, [a, n] = Z(!1), l = e.status === "root" ? "file-node--root" : e.status === "expanded" ? "file-node--expanded" : e.status === "loading" ? "file-node--loading" : e.status === "error" ? "file-node--error" : "file-node--collapsed", o = e.repoAlias ? "file-node--cross-repo" : "";
231
+ return /* @__PURE__ */ c("div", { className: `file-node ${l} ${o}`, children: [
232
+ !e.isRoot && /* @__PURE__ */ s(He, { type: "target", position: Ke.Top }),
233
+ /* @__PURE__ */ c("div", { className: "file-node__header", children: [
234
+ /* @__PURE__ */ s("span", { className: "file-node__icon", children: e.isRoot ? "📄" : e.status === "expanded" ? "📋" : e.repoAlias ? "🔗" : "📁" }),
235
+ /* @__PURE__ */ s("span", { className: "file-node__label", title: e.filePath, children: e.label }),
236
+ /* @__PURE__ */ s("span", { className: "file-node__actions", children: e.adoUrl && /* @__PURE__ */ s(
237
+ "a",
238
+ {
239
+ href: e.adoUrl,
240
+ target: "_blank",
241
+ rel: "noopener noreferrer",
242
+ className: "file-node__action-btn",
243
+ title: "Open in Azure DevOps",
244
+ onClick: (P) => P.stopPropagation(),
245
+ children: /* @__PURE__ */ s(Mt, {})
246
+ }
247
+ ) })
248
+ ] }),
249
+ e.repoAlias && /* @__PURE__ */ c(
250
+ "div",
251
+ {
252
+ className: "file-node__repo-row",
253
+ onMouseEnter: () => n(!0),
254
+ onMouseLeave: () => n(!1),
255
+ children: [
256
+ /* @__PURE__ */ c("span", { className: "file-node__repo", children: [
257
+ "@",
258
+ e.repoAlias
259
+ ] }),
260
+ e.repoInfo && a && /* @__PURE__ */ c("div", { className: "file-node__repo-tooltip", children: [
261
+ /* @__PURE__ */ c("div", { className: "file-node__repo-tooltip-row", children: [
262
+ /* @__PURE__ */ s("span", { className: "file-node__repo-tooltip-label", children: "Repo" }),
263
+ /* @__PURE__ */ s("span", { children: e.repoInfo.fullName })
264
+ ] }),
265
+ /* @__PURE__ */ c("div", { className: "file-node__repo-tooltip-row", children: [
266
+ /* @__PURE__ */ s("span", { className: "file-node__repo-tooltip-label", children: "Type" }),
267
+ /* @__PURE__ */ s("span", { children: e.repoInfo.type })
268
+ ] }),
269
+ e.repoInfo.ref && /* @__PURE__ */ c("div", { className: "file-node__repo-tooltip-row", children: [
270
+ /* @__PURE__ */ s("span", { className: "file-node__repo-tooltip-label", children: "Ref" }),
271
+ /* @__PURE__ */ s("span", { children: e.repoInfo.ref })
272
+ ] }),
273
+ e.repoInfo.project && /* @__PURE__ */ c("div", { className: "file-node__repo-tooltip-row", children: [
274
+ /* @__PURE__ */ s("span", { className: "file-node__repo-tooltip-label", children: "Project" }),
275
+ /* @__PURE__ */ s("span", { children: e.repoInfo.project })
276
+ ] })
277
+ ] })
278
+ ]
279
+ }
280
+ ),
281
+ /* @__PURE__ */ c("div", { className: "file-node__meta", children: [
282
+ e.status === "loading" && /* @__PURE__ */ s("span", { className: "file-node__spinner", children: "⏳ Loading..." }),
283
+ e.status === "error" && /* @__PURE__ */ c("span", { className: "file-node__error", title: e.errorMessage, children: [
284
+ "❌ ",
285
+ (m = e.errorMessage) == null ? void 0 : m.slice(0, 80)
286
+ ] }),
287
+ e.status === "collapsed" && /* @__PURE__ */ s("span", { className: "file-node__hint", children: "Click to expand" }),
288
+ e.status === "expanded" && e.templateCount === 0 && !e.isRoot && /* @__PURE__ */ s("span", { className: "file-node__leaf", children: "✓ no nested templates" }),
289
+ (e.status === "root" || e.status === "expanded") && e.templateCount > 0 && /* @__PURE__ */ c("span", { className: "file-node__count", children: [
290
+ e.templateCount,
291
+ " template ref(s)"
292
+ ] })
293
+ ] }),
294
+ /* @__PURE__ */ s(He, { type: "source", position: Ke.Bottom })
295
+ ] });
296
+ }
297
+ function Mt() {
298
+ return /* @__PURE__ */ s(
299
+ "svg",
300
+ {
301
+ width: "14",
302
+ height: "14",
303
+ viewBox: "0 0 18 18",
304
+ className: "file-node__ado-icon",
305
+ "aria-label": "Azure DevOps",
306
+ children: /* @__PURE__ */ s(
307
+ "path",
308
+ {
309
+ d: "M17 4v9.74l-4 3.28-6.2-2.26V17l-3.51-4.59 10.23.8V4.44zm-3.41.49L7.85 1v2.29L2.58 4.84 1 6.87v4.61l2.26 1V6.57z",
310
+ fill: "#3c91e5"
311
+ }
312
+ )
313
+ }
314
+ );
315
+ }
316
+ const Bt = tt(Ot);
317
+ function Le({
318
+ className: t,
319
+ label: e,
320
+ children: a
321
+ }) {
322
+ const [n, l] = Z(!1);
323
+ return /* @__PURE__ */ c(
324
+ "span",
325
+ {
326
+ className: t,
327
+ onMouseEnter: () => l(!0),
328
+ onMouseLeave: () => l(!1),
329
+ children: [
330
+ e,
331
+ n && /* @__PURE__ */ s("div", { className: "template-edge__badge-tooltip", children: a })
332
+ ]
333
+ }
334
+ );
335
+ }
336
+ function Wt({
337
+ id: t,
338
+ sourceX: e,
339
+ sourceY: a,
340
+ targetX: n,
341
+ targetY: l,
342
+ sourcePosition: o,
343
+ targetPosition: m,
344
+ data: P,
345
+ markerEnd: v,
346
+ style: d
347
+ }) {
348
+ var _;
349
+ const r = P, [y, g] = Z(!1), [i, R, S] = Rt({
350
+ sourceX: e,
351
+ sourceY: a,
352
+ sourcePosition: o,
353
+ targetX: n,
354
+ targetY: l,
355
+ targetPosition: m
356
+ }), h = fe(() => g(!0), []), N = fe(() => g(!1), []), b = ((_ = r == null ? void 0 : r.parameterNames) == null ? void 0 : _.length) ?? 0;
357
+ return /* @__PURE__ */ c(et, { children: [
358
+ /* @__PURE__ */ s(Et, { id: t, path: i, markerEnd: v, style: d }),
359
+ /* @__PURE__ */ s(xt, { children: /* @__PURE__ */ c(
360
+ "div",
361
+ {
362
+ className: "template-edge__label-container",
363
+ style: {
364
+ position: "absolute",
365
+ transform: `translate(-50%, -50%) translate(${R}px,${S}px)`,
366
+ pointerEvents: "all"
367
+ },
368
+ children: [
369
+ /* @__PURE__ */ c("div", { className: "template-edge__top-row", children: [
370
+ /* @__PURE__ */ s("span", { className: "template-edge__category", children: r == null ? void 0 : r.edgeLabel }),
371
+ (r == null ? void 0 : r.conditional) && /* @__PURE__ */ c(
372
+ Le,
373
+ {
374
+ className: `template-edge__badge template-edge__badge--conditional${r.conditionResult === !1 ? " template-edge__badge--condition-false" : r.conditionResult === !0 ? " template-edge__badge--condition-true" : ""}`,
375
+ label: r.conditionResult === !1 ? "⊘ false" : r.conditionResult === !0 ? "✓ conditional" : "conditional",
376
+ children: [
377
+ /* @__PURE__ */ s("div", { className: "template-edge__badge-tooltip-title", children: "⚡ Conditional Reference" }),
378
+ /* @__PURE__ */ s("p", { children: r.conditionResult === !0 ? "Condition evaluated to true — this template will be included." : r.conditionResult === !1 ? "Condition evaluated to false — this template will NOT be included in this pipeline run." : "This template is inside a conditional block. The condition could not be fully evaluated." }),
379
+ r.conditionExpression && /* @__PURE__ */ c("div", { className: "template-edge__badge-tooltip-row", children: [
380
+ /* @__PURE__ */ s("span", { className: "template-edge__badge-tooltip-label", children: "Condition" }),
381
+ /* @__PURE__ */ s("code", { children: r.conditionExpression })
382
+ ] }),
383
+ r.conditionResult != null && /* @__PURE__ */ c("div", { className: "template-edge__badge-tooltip-row", children: [
384
+ /* @__PURE__ */ s("span", { className: "template-edge__badge-tooltip-label", children: "Result" }),
385
+ /* @__PURE__ */ s("code", { children: String(r.conditionResult) })
386
+ ] })
387
+ ]
388
+ }
389
+ ),
390
+ (r == null ? void 0 : r.dynamicPath) && r.expressionResolved && /* @__PURE__ */ c(
391
+ Le,
392
+ {
393
+ className: "template-edge__badge template-edge__badge--resolved",
394
+ label: "🔮 resolved",
395
+ children: [
396
+ /* @__PURE__ */ s("div", { className: "template-edge__badge-tooltip-title", children: "🔮 Expression Resolved" }),
397
+ /* @__PURE__ */ s("p", { children: "The template path contained expressions that were successfully evaluated." }),
398
+ /* @__PURE__ */ c("div", { className: "template-edge__badge-tooltip-row", children: [
399
+ /* @__PURE__ */ s("span", { className: "template-edge__badge-tooltip-label", children: "Original" }),
400
+ /* @__PURE__ */ s("code", { children: r.originalPath })
401
+ ] }),
402
+ r.resolvedPath && /* @__PURE__ */ c("div", { className: "template-edge__badge-tooltip-row", children: [
403
+ /* @__PURE__ */ s("span", { className: "template-edge__badge-tooltip-label", children: "Resolved" }),
404
+ /* @__PURE__ */ s("code", { children: r.resolvedPath })
405
+ ] })
406
+ ]
407
+ }
408
+ ),
409
+ (r == null ? void 0 : r.dynamicPath) && !r.expressionResolved && /* @__PURE__ */ c(
410
+ Le,
411
+ {
412
+ className: "template-edge__badge template-edge__badge--unresolved",
413
+ label: "⚠️ dynamic",
414
+ children: [
415
+ /* @__PURE__ */ s("div", { className: "template-edge__badge-tooltip-title", children: "⚠️ Unresolved Expressions" }),
416
+ /* @__PURE__ */ s("p", { children: "The template path contains expressions that could not be evaluated at analysis time." }),
417
+ /* @__PURE__ */ c("div", { className: "template-edge__badge-tooltip-row", children: [
418
+ /* @__PURE__ */ s("span", { className: "template-edge__badge-tooltip-label", children: "Original" }),
419
+ /* @__PURE__ */ s("code", { children: r.originalPath })
420
+ ] }),
421
+ r.resolvedPath && r.resolvedPath !== r.originalPath && /* @__PURE__ */ c("div", { className: "template-edge__badge-tooltip-row", children: [
422
+ /* @__PURE__ */ s("span", { className: "template-edge__badge-tooltip-label", children: "Partial" }),
423
+ /* @__PURE__ */ s("code", { children: r.resolvedPath })
424
+ ] }),
425
+ r.unresolvedExpressions && r.unresolvedExpressions.length > 0 && /* @__PURE__ */ c("div", { className: "template-edge__badge-tooltip-row", children: [
426
+ /* @__PURE__ */ s("span", { className: "template-edge__badge-tooltip-label", children: "Unresolved" }),
427
+ /* @__PURE__ */ s("span", { children: r.unresolvedExpressions.join(", ") })
428
+ ] })
429
+ ]
430
+ }
431
+ )
432
+ ] }),
433
+ b > 0 && /* @__PURE__ */ c(
434
+ "span",
435
+ {
436
+ className: "template-edge__params-badge",
437
+ onMouseEnter: h,
438
+ onMouseLeave: N,
439
+ children: [
440
+ jt(r),
441
+ y && /* @__PURE__ */ s(Ht, { data: r })
442
+ ]
443
+ }
444
+ )
445
+ ]
446
+ }
447
+ ) })
448
+ ] });
449
+ }
450
+ function jt(t) {
451
+ var a;
452
+ const e = ((a = t.parameterNames) == null ? void 0 : a.length) ?? 0;
453
+ return t.totalParameterCount != null ? `${e}/${t.totalParameterCount} params` : `${e} params`;
454
+ }
455
+ function Ht({ data: t }) {
456
+ var a, n;
457
+ const e = (a = t.declaredParameterNames) == null ? void 0 : a.filter(
458
+ (l) => {
459
+ var o;
460
+ return !((o = t.parameterNames) != null && o.includes(l));
461
+ }
462
+ );
463
+ return /* @__PURE__ */ c("div", { className: "template-edge__params-tooltip", children: [
464
+ t.parameterNames && t.parameterNames.length > 0 && /* @__PURE__ */ c("div", { className: "template-edge__params-section", children: [
465
+ /* @__PURE__ */ c("div", { className: "template-edge__params-heading", children: [
466
+ "✓ Passed (",
467
+ t.parameterNames.length,
468
+ ")"
469
+ ] }),
470
+ /* @__PURE__ */ s("ul", { className: "template-edge__params-list", children: t.parameterNames.map((l) => /* @__PURE__ */ s(
471
+ "li",
472
+ {
473
+ className: "template-edge__params-item template-edge__params-item--passed",
474
+ children: l
475
+ },
476
+ l
477
+ )) })
478
+ ] }),
479
+ e && e.length > 0 && /* @__PURE__ */ c("div", { className: "template-edge__params-section", children: [
480
+ /* @__PURE__ */ c("div", { className: "template-edge__params-heading", children: [
481
+ "○ Not passed (",
482
+ e.length,
483
+ ")"
484
+ ] }),
485
+ /* @__PURE__ */ s("ul", { className: "template-edge__params-list", children: e.map((l) => /* @__PURE__ */ s(
486
+ "li",
487
+ {
488
+ className: "template-edge__params-item template-edge__params-item--missing",
489
+ children: l
490
+ },
491
+ l
492
+ )) })
493
+ ] }),
494
+ t.totalParameterCount == null && !((n = t.declaredParameterNames) != null && n.length) && /* @__PURE__ */ s("div", { className: "template-edge__params-hint", children: "Expand node to see all declared params" })
495
+ ] });
496
+ }
497
+ const Kt = tt(Wt), Yt = { fileNode: Bt }, Xt = { templateEdge: Kt }, Gt = {
498
+ animated: !0,
499
+ style: { stroke: "var(--accent)", strokeWidth: 2 },
500
+ markerEnd: { type: xe.ArrowClosed, color: "var(--accent)" }
501
+ };
502
+ function qt() {
503
+ var le, ve;
504
+ const {
505
+ org: t,
506
+ project: e,
507
+ selectedPipeline: a,
508
+ selectedPipelineLoading: n,
509
+ selectedPipelineError: l,
510
+ expandedTemplates: o,
511
+ setExpandedTemplate: m,
512
+ setSelectedNodeDetail: P
513
+ } = Te(), v = zt(), [d, r, y] = kt([]), [g, i, R] = At([]), S = te(null), h = te(null), N = te(""), b = te([]);
514
+ oe(() => {
515
+ b.current = g;
516
+ }, [g]);
517
+ const [_, L] = Z(/* @__PURE__ */ new Set()), x = te(/* @__PURE__ */ new Set()), [k, ae] = Z(!1), $ = ((ve = (le = a == null ? void 0 : a.definition) == null ? void 0 : le.repository) == null ? void 0 : ve.name) ?? "", z = ze(() => {
518
+ if (!(a != null && a.yaml)) return [];
519
+ try {
520
+ const f = pe(a.yaml), p = f == null ? void 0 : f.resources;
521
+ return (p == null ? void 0 : p.repositories) ?? [];
522
+ } catch {
523
+ return [];
524
+ }
525
+ }, [a == null ? void 0 : a.yaml]), H = ze(() => {
526
+ if (!(a != null && a.yaml)) return {};
527
+ try {
528
+ const f = pe(a.yaml);
529
+ return Pe(f ?? {});
530
+ } catch {
531
+ return {};
532
+ }
533
+ }, [a == null ? void 0 : a.yaml]);
534
+ oe(() => {
535
+ var w, F, B, ie, ce, de, ne;
536
+ if (!(a != null && a.yaml)) {
537
+ r([]), i([]);
538
+ return;
539
+ }
540
+ const f = pe(a.yaml), p = ((w = a.definition) == null ? void 0 : w.path) ?? "", u = Se(f ?? {}, { sourcePath: p }), E = ((F = a.definition) == null ? void 0 : F.name) ?? p.split("/").pop() ?? "Pipeline", A = Ae(p), D = De(f ?? {}), C = ((ie = (B = a.definition) == null ? void 0 : B.repository) == null ? void 0 : ie.name) ?? "", W = (ne = (de = (ce = a.definition) == null ? void 0 : ce.repository) == null ? void 0 : de.defaultBranch) == null ? void 0 : ne.replace(
541
+ /^refs\/heads\//,
542
+ ""
543
+ ), I = t && e && C ? at({
544
+ org: t,
545
+ project: e,
546
+ repoName: C,
547
+ filePath: p,
548
+ branch: W
549
+ }) : void 0, Q = {
550
+ id: "root",
551
+ type: "fileNode",
552
+ position: { x: 0, y: 0 },
553
+ data: {
554
+ label: E,
555
+ filePath: p,
556
+ templateCount: u.length,
557
+ status: "root",
558
+ isRoot: !0,
559
+ baseDir: A,
560
+ adoUrl: I
561
+ }
562
+ }, { templateNodes: j, templateEdges: J } = Ue(
563
+ "root",
564
+ u,
565
+ t,
566
+ e,
567
+ $,
568
+ z,
569
+ D,
570
+ void 0,
571
+ // existingNodeIds
572
+ H
573
+ ), Y = [Q, ...j], ee = [...J], { nodes: O, edges: U } = Fe(
574
+ Y,
575
+ ee
576
+ );
577
+ r(O), i(U), x.current = /* @__PURE__ */ new Set();
578
+ }, [a, r, i]);
579
+ const me = te(!1);
580
+ oe(() => {
581
+ if (!k || !S.current || d.length === 0) return;
582
+ const f = `${d.length}:${g.length}`;
583
+ if (f !== N.current)
584
+ return N.current = f, h.current != null && cancelAnimationFrame(h.current), h.current = requestAnimationFrame(() => {
585
+ var p;
586
+ (p = S.current) == null || p.fitView({
587
+ padding: 0.2,
588
+ duration: 300
589
+ }), h.current = null;
590
+ }), () => {
591
+ h.current != null && (cancelAnimationFrame(h.current), h.current = null);
592
+ };
593
+ }, [k, d.length, g.length]), oe(() => {
594
+ if (me.current) return;
595
+ const f = d.filter((p) => {
596
+ const u = p.data;
597
+ if (u.status !== "collapsed" || x.current.has(p.id) || _.has(p.id)) return !1;
598
+ const E = u._conditionResult;
599
+ return !(E === !1 || E === "unknown" && !k);
600
+ });
601
+ if (f.length !== 0) {
602
+ f.sort((p, u) => {
603
+ const E = p.data.templateLocation === "variables" ? 0 : 1, A = u.data.templateLocation === "variables" ? 0 : 1;
604
+ return E - A;
605
+ });
606
+ for (const p of f) {
607
+ const u = p.data;
608
+ u.dynamicPath && !u.expressionResolved || x.current.add(p.id);
609
+ }
610
+ me.current = !0, (async () => {
611
+ for (const p of f) {
612
+ const u = p.data;
613
+ if (!(u.dynamicPath && !u.expressionResolved))
614
+ try {
615
+ const { content: E, actualPath: A } = await Ve(
616
+ t,
617
+ e,
618
+ $,
619
+ u,
620
+ z,
621
+ o,
622
+ m,
623
+ v
624
+ ), D = pe(E) ?? {}, C = u._ref, W = Se(D, {
625
+ contextRepoAlias: re(C ?? {}),
626
+ sourcePath: A
627
+ }), I = je(D);
628
+ if (W.length === 0) {
629
+ const j = u.templateLocation === "variables" ? Pe(D) : void 0, J = j && Object.keys(j).length > 0, Y = /* @__PURE__ */ new Set(), ee = /* @__PURE__ */ new Set(), O = /* @__PURE__ */ new Map();
630
+ if (J)
631
+ for (const U of d) {
632
+ const w = U.data;
633
+ if (w.dynamicPath && !w.expressionResolved) {
634
+ const F = we(
635
+ U,
636
+ j,
637
+ t,
638
+ e,
639
+ $,
640
+ z
641
+ );
642
+ if (F !== U) {
643
+ Y.add(U.id);
644
+ const B = F.data;
645
+ B.repoAlias && ee.add(U.id), O.set(U.id, B.filePath);
646
+ }
647
+ }
648
+ }
649
+ r(
650
+ (U) => U.map((w) => w.id === p.id ? {
651
+ ...w,
652
+ data: {
653
+ ...w.data,
654
+ status: "expanded",
655
+ templateCount: 0,
656
+ totalParameterCount: I.length || void 0,
657
+ declaredParameterNames: I.length ? I : void 0
658
+ }
659
+ } : J && Y.has(w.id) ? we(
660
+ w,
661
+ j,
662
+ t,
663
+ e,
664
+ $,
665
+ z
666
+ ) : w)
667
+ ), Y.size > 0 && i(
668
+ (U) => U.map((w) => {
669
+ if (!Y.has(w.target)) return w;
670
+ const F = w.data;
671
+ if (!(F != null && F.dynamicPath)) return w;
672
+ const B = ee.has(w.target);
673
+ return {
674
+ ...w,
675
+ data: {
676
+ ...F,
677
+ expressionResolved: !0,
678
+ isExternal: B || F.isExternal || void 0,
679
+ resolvedPath: O.get(w.target) ?? F.resolvedPath,
680
+ unresolvedExpressions: void 0
681
+ },
682
+ style: B ? {
683
+ stroke: "var(--badge-resources)",
684
+ strokeWidth: 2,
685
+ strokeDasharray: "6 3"
686
+ } : w.style,
687
+ markerEnd: B ? {
688
+ type: xe.ArrowClosed,
689
+ color: "var(--badge-resources)"
690
+ } : w.markerEnd
691
+ };
692
+ })
693
+ );
694
+ } else if (k) {
695
+ const Q = De(D), j = u._parentParamContext, J = u._accumulatedVariables, Y = C == null ? void 0 : C.parameters, ee = ke(
696
+ Y,
697
+ j,
698
+ J
699
+ ), O = { ...Q, ...ee }, U = Pe(D), w = {
700
+ ...J ?? H,
701
+ ...U
702
+ }, F = u._accumulatedResources, B = qe(D), ie = Je([
703
+ ...F ?? z,
704
+ ...B
705
+ ]);
706
+ await new Promise((M) => setTimeout(M, 0));
707
+ const ce = new Set(d.map((M) => M.id)), { templateNodes: de, templateEdges: ne } = Ue(
708
+ p.id,
709
+ W,
710
+ t,
711
+ e,
712
+ $,
713
+ ie,
714
+ O,
715
+ ce,
716
+ w
717
+ );
718
+ r((M) => {
719
+ const se = new Set(M.map((T) => T.id)), ye = de.filter(
720
+ (T) => !se.has(T.id)
721
+ ), Ne = [...M.map(
722
+ (T) => T.id === p.id ? {
723
+ ...T,
724
+ data: {
725
+ ...T.data,
726
+ status: "expanded",
727
+ templateCount: W.length,
728
+ totalParameterCount: I.length || void 0,
729
+ declaredParameterNames: I.length ? I : void 0
730
+ }
731
+ } : T
732
+ ), ...ye], X = [...I.length ? be(
733
+ b.current,
734
+ p.id,
735
+ I
736
+ ) : b.current, ...ne];
737
+ return Fe(Ne, X).nodes;
738
+ }), i((M) => [...I.length ? be(
739
+ M,
740
+ p.id,
741
+ I
742
+ ) : M, ...ne]), await new Promise((M) => setTimeout(M, 50));
743
+ }
744
+ } catch {
745
+ }
746
+ }
747
+ me.current = !1, k && r((p) => [...p]);
748
+ })();
749
+ }
750
+ }, [
751
+ d,
752
+ t,
753
+ e,
754
+ $,
755
+ z,
756
+ o,
757
+ m,
758
+ _,
759
+ r,
760
+ i,
761
+ k,
762
+ v
763
+ ]);
764
+ const K = fe(
765
+ async (f, p) => {
766
+ const u = p.data;
767
+ if (u.status === "root" && (a != null && a.yaml)) {
768
+ P({
769
+ nodeId: p.id,
770
+ label: u.label,
771
+ filePath: u.filePath,
772
+ yaml: a.yaml
773
+ });
774
+ return;
775
+ }
776
+ if (u.status === "expanded") {
777
+ const E = u._ref, A = re(E ?? {}) || "", D = `${A}:${u.filePath}`, C = u._fallbackPath, W = C ? `${A}:${C}` : void 0, I = o.get(D) ?? (W ? o.get(W) : void 0);
778
+ if (I) {
779
+ P({
780
+ nodeId: p.id,
781
+ label: u.label,
782
+ filePath: u.filePath,
783
+ yaml: I,
784
+ repoAlias: u.repoAlias
785
+ });
786
+ return;
787
+ }
788
+ try {
789
+ const { content: Q } = await Ve(
790
+ t,
791
+ e,
792
+ $,
793
+ u,
794
+ z,
795
+ o,
796
+ m,
797
+ v
798
+ );
799
+ P({
800
+ nodeId: p.id,
801
+ label: u.label,
802
+ filePath: u.filePath,
803
+ yaml: Q,
804
+ repoAlias: u.repoAlias
805
+ });
806
+ } catch {
807
+ }
808
+ return;
809
+ }
810
+ if (u.status === "collapsed" && !_.has(p.id)) {
811
+ L((E) => new Set(E).add(p.id)), r(
812
+ (E) => E.map(
813
+ (A) => A.id === p.id ? { ...A, data: { ...A.data, status: "loading" } } : A
814
+ )
815
+ );
816
+ try {
817
+ const { content: E, actualPath: A } = await Ve(
818
+ t,
819
+ e,
820
+ $,
821
+ u,
822
+ z,
823
+ o,
824
+ m,
825
+ v
826
+ ), D = pe(E) ?? {}, C = u._ref, W = Se(D, {
827
+ contextRepoAlias: re(C ?? {}),
828
+ sourcePath: A
829
+ }), I = De(D), Q = u._parentParamContext, j = u._accumulatedVariables, J = C == null ? void 0 : C.parameters, Y = ke(
830
+ J,
831
+ Q,
832
+ j
833
+ ), ee = { ...I, ...Y }, O = je(D), U = Ae(A), w = Pe(D), F = {
834
+ ...j ?? H,
835
+ ...w
836
+ }, B = u._accumulatedResources, ie = qe(D), ce = Je([
837
+ ...B ?? z,
838
+ ...ie
839
+ ]), de = new Set(d.map((V) => V.id)), { templateNodes: ne, templateEdges: M } = Ue(
840
+ p.id,
841
+ W,
842
+ t,
843
+ e,
844
+ $,
845
+ ce,
846
+ ee,
847
+ de,
848
+ F
849
+ ), se = /* @__PURE__ */ new Set(), ye = /* @__PURE__ */ new Set(), Ce = /* @__PURE__ */ new Map(), Ne = u.templateLocation === "variables" && Object.keys(w).length > 0;
850
+ if (Ne)
851
+ for (const V of d) {
852
+ const X = V.data;
853
+ if (X.dynamicPath && !X.expressionResolved) {
854
+ const T = we(
855
+ V,
856
+ w,
857
+ t,
858
+ e,
859
+ $,
860
+ z
861
+ );
862
+ if (T !== V) {
863
+ se.add(V.id);
864
+ const G = T.data;
865
+ G.repoAlias && ye.add(V.id), Ce.set(V.id, G.filePath);
866
+ }
867
+ }
868
+ }
869
+ r((V) => {
870
+ const X = new Set(V.map((q) => q.id)), T = ne.filter((q) => !X.has(q.id)), he = [...V.map((q) => q.id === p.id ? {
871
+ ...q,
872
+ data: {
873
+ ...q.data,
874
+ status: "expanded",
875
+ templateCount: W.length,
876
+ totalParameterCount: O.length || void 0,
877
+ declaredParameterNames: O.length ? O : void 0
878
+ }
879
+ } : Ne && se.has(q.id) ? we(
880
+ q,
881
+ w,
882
+ t,
883
+ e,
884
+ $,
885
+ z
886
+ ) : q), ...T], dt = [...O.length ? be(
887
+ b.current,
888
+ p.id,
889
+ O
890
+ ) : b.current, ...M];
891
+ return Fe(he, dt).nodes;
892
+ }), i((V) => {
893
+ let X = O.length ? be(
894
+ V,
895
+ p.id,
896
+ O
897
+ ) : V;
898
+ return se.size > 0 && (X = X.map((T) => {
899
+ if (!se.has(T.target)) return T;
900
+ const G = T.data;
901
+ if (!(G != null && G.dynamicPath)) return T;
902
+ const he = ye.has(T.target);
903
+ return {
904
+ ...T,
905
+ data: {
906
+ ...G,
907
+ expressionResolved: !0,
908
+ isExternal: he || G.isExternal || void 0,
909
+ resolvedPath: Ce.get(T.target) ?? G.resolvedPath,
910
+ unresolvedExpressions: void 0
911
+ },
912
+ style: he ? {
913
+ stroke: "var(--badge-resources)",
914
+ strokeWidth: 2,
915
+ strokeDasharray: "6 3"
916
+ } : T.style,
917
+ markerEnd: he ? {
918
+ type: xe.ArrowClosed,
919
+ color: "var(--badge-resources)"
920
+ } : T.markerEnd
921
+ };
922
+ })), [...X, ...M];
923
+ }), P({
924
+ nodeId: p.id,
925
+ label: u.label,
926
+ filePath: u.filePath,
927
+ yaml: E,
928
+ repoAlias: u.repoAlias
929
+ });
930
+ } catch (E) {
931
+ const A = E instanceof Error ? E.message : String(E);
932
+ r(
933
+ (D) => D.map(
934
+ (C) => C.id === p.id ? {
935
+ ...C,
936
+ data: { ...C.data, status: "error", errorMessage: A }
937
+ } : C
938
+ )
939
+ );
940
+ } finally {
941
+ L((E) => {
942
+ const A = new Set(E);
943
+ return A.delete(p.id), A;
944
+ });
945
+ }
946
+ }
947
+ },
948
+ [
949
+ t,
950
+ e,
951
+ $,
952
+ a,
953
+ z,
954
+ o,
955
+ m,
956
+ P,
957
+ _,
958
+ r,
959
+ i,
960
+ v
961
+ ]
962
+ ), $e = fe(() => {
963
+ ae((f) => (f || (x.current = /* @__PURE__ */ new Set(), N.current = ""), !f));
964
+ }, []);
965
+ return n ? /* @__PURE__ */ s("div", { className: "pipeline-tree__empty", children: /* @__PURE__ */ c("div", { className: "loading-indicator", children: [
966
+ /* @__PURE__ */ s("span", { className: "loading-indicator__spinner", children: "⏳" }),
967
+ /* @__PURE__ */ s("span", { children: "Loading pipeline..." })
968
+ ] }) }) : l ? /* @__PURE__ */ s("div", { className: "error", children: l }) : a ? /* @__PURE__ */ c("div", { style: { width: "100%", height: "100%", position: "relative" }, children: [
969
+ /* @__PURE__ */ c(
970
+ Tt,
971
+ {
972
+ nodes: d,
973
+ edges: g,
974
+ onInit: (f) => {
975
+ S.current = f;
976
+ },
977
+ onNodesChange: y,
978
+ onEdgesChange: R,
979
+ onNodeClick: K,
980
+ nodeTypes: Yt,
981
+ edgeTypes: Xt,
982
+ defaultEdgeOptions: Gt,
983
+ fitView: !0,
984
+ fitViewOptions: { padding: 0.2 },
985
+ minZoom: 0.1,
986
+ maxZoom: 2,
987
+ proOptions: { hideAttribution: !0 },
988
+ children: [
989
+ /* @__PURE__ */ s(
990
+ $t,
991
+ {
992
+ variant: Ct.Dots,
993
+ color: "var(--border)",
994
+ gap: 20
995
+ }
996
+ ),
997
+ /* @__PURE__ */ s(St, {})
998
+ ]
999
+ }
1000
+ ),
1001
+ /* @__PURE__ */ c("label", { className: "auto-expand-toggle", children: [
1002
+ /* @__PURE__ */ s(
1003
+ "input",
1004
+ {
1005
+ type: "checkbox",
1006
+ checked: k,
1007
+ onChange: $e
1008
+ }
1009
+ ),
1010
+ /* @__PURE__ */ s("span", { children: "Auto-expand all" })
1011
+ ] })
1012
+ ] }) : /* @__PURE__ */ s("div", { className: "pipeline-tree__empty", children: "Select a pipeline to visualize" });
1013
+ }
1014
+ function be(t, e, a) {
1015
+ return t.map((n) => {
1016
+ if (n.target !== e) return n;
1017
+ const l = n.data ?? {};
1018
+ return {
1019
+ ...n,
1020
+ data: {
1021
+ ...l,
1022
+ totalParameterCount: a.length,
1023
+ declaredParameterNames: a
1024
+ }
1025
+ };
1026
+ });
1027
+ }
1028
+ function ke(t, e, a) {
1029
+ if (!t || !e && !a)
1030
+ return t;
1031
+ const n = {};
1032
+ for (const [l, o] of Object.entries(t))
1033
+ if (typeof o == "string" && ue(o)) {
1034
+ const { result: m, isFullyResolved: P } = yt(o, {
1035
+ parameters: e,
1036
+ variables: a
1037
+ });
1038
+ n[l] = P ? Jt(m) : o;
1039
+ } else o && typeof o == "object" && !Array.isArray(o) ? n[l] = ke(
1040
+ o,
1041
+ e,
1042
+ a
1043
+ ) ?? o : n[l] = o;
1044
+ return n;
1045
+ }
1046
+ function Jt(t) {
1047
+ if (t === "True" || t === "true") return !0;
1048
+ if (t === "False" || t === "false") return !1;
1049
+ if (t === "null") return null;
1050
+ if (t.startsWith("{") && t.endsWith("}") || t.startsWith("[") && t.endsWith("]"))
1051
+ try {
1052
+ return JSON.parse(t);
1053
+ } catch {
1054
+ }
1055
+ return t;
1056
+ }
1057
+ function qe(t) {
1058
+ const e = t.resources;
1059
+ if (!e) return [];
1060
+ const a = e.repositories;
1061
+ return Array.isArray(a) ? a.filter(
1062
+ (n) => n != null && typeof n == "object" && "repository" in n && "name" in n && typeof n.repository == "string" && typeof n.name == "string"
1063
+ ) : [];
1064
+ }
1065
+ function Je(t) {
1066
+ const e = /* @__PURE__ */ new Map();
1067
+ for (const a of t)
1068
+ e.set(a.repository, a);
1069
+ return Array.from(e.values());
1070
+ }
1071
+ function Zt(t, e) {
1072
+ return `tpl::${t || "self"}::${e}`;
1073
+ }
1074
+ function Ue(t, e, a, n, l, o, m, P, v) {
1075
+ const d = /* @__PURE__ */ new Set(), r = [], y = [];
1076
+ for (let g = 0; g < e.length; g++) {
1077
+ const i = e[g];
1078
+ let R = i.normalizedPath, S = !1, h = !0, N, b;
1079
+ if (ue(i.normalizedPath)) {
1080
+ S = !0, N = i.normalizedPath;
1081
+ const f = Ee(
1082
+ i.normalizedPath,
1083
+ m,
1084
+ void 0,
1085
+ v
1086
+ );
1087
+ R = f.resolvedPath, h = f.isFullyResolved, b = f.unresolved.length ? f.unresolved : void 0;
1088
+ }
1089
+ let _ = re(i), L = !1, x = !0;
1090
+ if (_ && ue(_)) {
1091
+ L = !0;
1092
+ const f = Ee(
1093
+ _,
1094
+ m,
1095
+ void 0,
1096
+ v
1097
+ );
1098
+ f.isFullyResolved ? _ = f.resolvedPath : (x = !1, b = [
1099
+ ...b ?? [],
1100
+ ...f.unresolved
1101
+ ]);
1102
+ }
1103
+ const k = S || L, ae = h && x, { primary: $, fallback: z } = nt({
1104
+ ...i,
1105
+ normalizedPath: R,
1106
+ repoAlias: i.repoAlias,
1107
+ sourcePath: i.sourcePath
1108
+ }), H = Zt(_, $);
1109
+ if (d.has(H)) continue;
1110
+ d.add(H);
1111
+ const me = P == null ? void 0 : P.has(H);
1112
+ let K;
1113
+ if (i.conditional && i.conditionExpression)
1114
+ try {
1115
+ const f = _t(i.conditionExpression, {
1116
+ parameters: m,
1117
+ variables: v
1118
+ });
1119
+ typeof f == "boolean" ? K = f : f === void 0 || f === i.conditionExpression ? K = "unknown" : K = !!f;
1120
+ } catch {
1121
+ K = "unknown";
1122
+ }
1123
+ else i.conditional && (K = "unknown");
1124
+ if (K === !1) continue;
1125
+ if (!me) {
1126
+ const f = R.length > 40 ? `...${R.slice(-37)}` : R, { repoInfo: p, adoUrl: u } = lt(
1127
+ i,
1128
+ _,
1129
+ $,
1130
+ a,
1131
+ n,
1132
+ l,
1133
+ o
1134
+ ), E = ke(
1135
+ i.parameters,
1136
+ m,
1137
+ v
1138
+ ), A = _ !== re(i) || E !== i.parameters ? {
1139
+ ...i,
1140
+ repoAlias: _ || i.repoAlias,
1141
+ contextRepoAlias: _ || i.contextRepoAlias,
1142
+ parameters: E
1143
+ } : i;
1144
+ r.push({
1145
+ id: H,
1146
+ type: "fileNode",
1147
+ position: { x: 0, y: 0 },
1148
+ data: {
1149
+ label: f,
1150
+ filePath: $,
1151
+ repoAlias: _,
1152
+ templateCount: 0,
1153
+ status: "collapsed",
1154
+ isRoot: !1,
1155
+ baseDir: Ae($),
1156
+ adoUrl: u,
1157
+ repoInfo: p,
1158
+ templateLocation: i.location,
1159
+ // Dynamic path info for auto-expand to skip unresolved expression paths
1160
+ dynamicPath: k || void 0,
1161
+ expressionResolved: k ? ae : void 0,
1162
+ // Stash the resolved ref for expansion (with resolved repo alias + params)
1163
+ _ref: A,
1164
+ // Stash fallback path for fetch retry (repo-root-relative)
1165
+ _fallbackPath: z,
1166
+ // Stash the parent's parameter context so it can flow down during expansion
1167
+ _parentParamContext: m,
1168
+ // Stash accumulated resources (root + all ancestor template resources)
1169
+ _accumulatedResources: o,
1170
+ // Stash accumulated variables for expression resolution in descendants
1171
+ _accumulatedVariables: v,
1172
+ // Condition evaluation result for conditional refs
1173
+ // true = expand, false = skip, 'unknown' = expand when autoExpandAll
1174
+ _conditionResult: K
1175
+ }
1176
+ });
1177
+ }
1178
+ const $e = i.location === "extends" ? "extends" : i.location === "extends-parameters" ? "extends param" : i.location, le = !!_, ve = i.parameters ? Object.keys(i.parameters) : void 0;
1179
+ y.push({
1180
+ id: `${t}->${H}`,
1181
+ source: t,
1182
+ target: H,
1183
+ type: "templateEdge",
1184
+ data: {
1185
+ edgeLabel: $e,
1186
+ parameterNames: ve,
1187
+ isExternal: le || void 0,
1188
+ conditional: i.conditional || void 0,
1189
+ conditionExpression: i.conditionExpression,
1190
+ conditionResult: K,
1191
+ dynamicPath: k || void 0,
1192
+ expressionResolved: k ? ae : void 0,
1193
+ originalPath: N || (L ? i.rawPath : void 0),
1194
+ resolvedPath: k ? $ : void 0,
1195
+ unresolvedExpressions: b
1196
+ },
1197
+ style: le ? {
1198
+ stroke: "var(--badge-resources)",
1199
+ strokeWidth: 2,
1200
+ strokeDasharray: "6 3"
1201
+ } : void 0,
1202
+ markerEnd: le ? { type: xe.ArrowClosed, color: "var(--badge-resources)" } : void 0
1203
+ });
1204
+ }
1205
+ return { templateNodes: r, templateEdges: y };
1206
+ }
1207
+ async function Ve(t, e, a, n, l, o, m, P) {
1208
+ const v = n._ref;
1209
+ if (!v) throw new Error("No template reference on this node");
1210
+ const d = n.filePath, r = n._fallbackPath, y = re(v), g = `${y || ""}:${d}`, i = o.get(g);
1211
+ if (i) return { content: i, actualPath: d };
1212
+ if (r) {
1213
+ const x = `${y || ""}:${r}`, k = o.get(x);
1214
+ if (k)
1215
+ return { content: k, actualPath: r };
1216
+ }
1217
+ const S = n._accumulatedResources ?? l;
1218
+ let h = e, N = a, b;
1219
+ if (y && S.length) {
1220
+ const x = st(y, S);
1221
+ x ? (h = x.project || e, N = x.repoName, b = x.ref) : N = y;
1222
+ } else y && (N = y);
1223
+ let _, L = d;
1224
+ try {
1225
+ _ = await P(
1226
+ t,
1227
+ h,
1228
+ N,
1229
+ d,
1230
+ b
1231
+ );
1232
+ } catch (x) {
1233
+ if (r)
1234
+ _ = await P(
1235
+ t,
1236
+ h,
1237
+ N,
1238
+ r,
1239
+ b
1240
+ ), L = r;
1241
+ else
1242
+ throw x;
1243
+ }
1244
+ return m(`${y || ""}:${L}`, _.content), { content: _.content, actualPath: L };
1245
+ }
1246
+ function Ae(t) {
1247
+ const e = t.replace(/\\/g, "/"), a = e.lastIndexOf("/");
1248
+ return a > 0 ? e.slice(0, a) : "";
1249
+ }
1250
+ function lt(t, e, a, n, l, o, m) {
1251
+ let P = l, v = o, d, r;
1252
+ if (e && m.length) {
1253
+ const g = st(e, m), i = m.find(
1254
+ (R) => R.repository === e
1255
+ );
1256
+ g ? (P = g.project || l, v = g.repoName, d = g.ref) : v = e, i && (r = {
1257
+ alias: e,
1258
+ fullName: i.name,
1259
+ type: i.type,
1260
+ ref: i.ref,
1261
+ project: g == null ? void 0 : g.project
1262
+ });
1263
+ } else e && (v = e);
1264
+ const y = n && P && v ? at({
1265
+ org: n,
1266
+ project: P,
1267
+ repoName: v,
1268
+ filePath: a,
1269
+ ref: d
1270
+ }) : void 0;
1271
+ return { repoInfo: r, adoUrl: y };
1272
+ }
1273
+ function we(t, e, a, n, l, o) {
1274
+ const m = t.data, v = { ...m._accumulatedVariables ?? {}, ...e }, d = m._ref;
1275
+ if (!d) return t;
1276
+ const r = m._parentParamContext;
1277
+ let y = d.normalizedPath, g = !1, i = !0, R = re(d);
1278
+ if (ue(d.normalizedPath)) {
1279
+ g = !0;
1280
+ const x = Ee(
1281
+ d.normalizedPath,
1282
+ r,
1283
+ void 0,
1284
+ v
1285
+ );
1286
+ if (y = x.resolvedPath, i = x.isFullyResolved, i && !ue(y)) {
1287
+ const k = vt(y);
1288
+ y = k.normalizedPath, k.repoAlias && (R = k.repoAlias);
1289
+ }
1290
+ }
1291
+ if (R && ue(R)) {
1292
+ g = !0;
1293
+ const x = Ee(
1294
+ R,
1295
+ r,
1296
+ void 0,
1297
+ v
1298
+ );
1299
+ x.isFullyResolved ? R = x.resolvedPath : i = !1;
1300
+ }
1301
+ const S = {
1302
+ ...d,
1303
+ normalizedPath: y,
1304
+ repoAlias: R || d.repoAlias,
1305
+ contextRepoAlias: R || d.contextRepoAlias
1306
+ }, { primary: h, fallback: N } = nt({
1307
+ ...S,
1308
+ normalizedPath: y,
1309
+ repoAlias: S.repoAlias,
1310
+ sourcePath: d.sourcePath
1311
+ }), b = y.length > 40 ? `...${y.slice(-37)}` : y, { repoInfo: _, adoUrl: L } = a && n && l && o ? lt(
1312
+ S,
1313
+ R,
1314
+ h,
1315
+ a,
1316
+ n,
1317
+ l,
1318
+ o
1319
+ ) : { repoInfo: void 0, adoUrl: void 0 };
1320
+ return {
1321
+ ...t,
1322
+ data: {
1323
+ ...t.data,
1324
+ label: b,
1325
+ filePath: h,
1326
+ repoAlias: R,
1327
+ baseDir: Ae(h),
1328
+ dynamicPath: g || void 0,
1329
+ expressionResolved: g ? i : void 0,
1330
+ adoUrl: L || t.data.adoUrl,
1331
+ repoInfo: _ || t.data.repoInfo,
1332
+ _ref: S,
1333
+ _accumulatedVariables: v,
1334
+ _fallbackPath: N
1335
+ }
1336
+ };
1337
+ }
1338
+ const Me = "7.1";
1339
+ function Be(t, e) {
1340
+ return `https://dev.azure.com/${encodeURIComponent(t)}/${encodeURIComponent(e)}/_apis`;
1341
+ }
1342
+ function Qt(t) {
1343
+ return t.startsWith("refs/heads/") ? { version: t.slice(11), versionType: "branch" } : t.startsWith("refs/tags/") ? { version: t.slice(10), versionType: "tag" } : /^[0-9a-f]{40}$/i.test(t) ? { version: t, versionType: "commit" } : { version: t, versionType: "branch" };
1344
+ }
1345
+ async function We(t) {
1346
+ const e = await fetch(t, { credentials: "include" });
1347
+ if (!e.ok) {
1348
+ const a = await e.text();
1349
+ throw new Error(`ADO API error (${e.status}): ${a}`);
1350
+ }
1351
+ return e;
1352
+ }
1353
+ async function it(t, e, a, n, l) {
1354
+ const o = n.startsWith("/") ? n : `/${n}`, m = Nt(o);
1355
+ let P = `${Be(t, e)}/git/repositories/${encodeURIComponent(a)}/items?path=${encodeURIComponent(m)}&api-version=${Me}&includeContent=true&$format=text`;
1356
+ if (l) {
1357
+ const d = Qt(l);
1358
+ P += `&versionDescriptor.version=${encodeURIComponent(d.version)}&versionDescriptor.versionType=${d.versionType}`;
1359
+ }
1360
+ return (await We(P)).text();
1361
+ }
1362
+ async function ea(t, e) {
1363
+ const a = `${Be(t, e)}/pipelines?api-version=${Me}`;
1364
+ return (await (await We(a)).json()).value;
1365
+ }
1366
+ async function ta(t, e, a) {
1367
+ var v, d, r, y, g;
1368
+ const n = `${Be(t, e)}/build/definitions/${a}?api-version=${Me}`, o = await (await We(n)).json(), m = {
1369
+ id: o.id,
1370
+ name: o.name,
1371
+ path: ((v = o.process) == null ? void 0 : v.yamlFilename) ?? o.path,
1372
+ repository: {
1373
+ id: (d = o.repository) == null ? void 0 : d.id,
1374
+ name: (r = o.repository) == null ? void 0 : r.name,
1375
+ type: (y = o.repository) == null ? void 0 : y.type,
1376
+ defaultBranch: (g = o.repository) == null ? void 0 : g.defaultBranch
1377
+ }
1378
+ }, P = await it(
1379
+ t,
1380
+ e,
1381
+ m.repository.id,
1382
+ m.path,
1383
+ m.repository.defaultBranch
1384
+ );
1385
+ return { definition: m, yaml: P };
1386
+ }
1387
+ async function aa(t, e, a, n, l) {
1388
+ return { content: await it(t, e, a, n, l), path: n, repoId: a, repoName: a, branch: l || "" };
1389
+ }
1390
+ async function na() {
1391
+ return { customTaskDocs: {} };
1392
+ }
1393
+ async function sa(t) {
1394
+ return { tasks: [], cached: !1 };
1395
+ }
1396
+ const oa = "/api";
1397
+ var Qe;
1398
+ const ge = typeof window < "u" && ((Qe = window.location) == null ? void 0 : Qe.protocol) === "chrome-extension:";
1399
+ async function _e(t) {
1400
+ const e = await fetch(`${oa}${t}`);
1401
+ if (!e.ok) {
1402
+ const a = await e.text();
1403
+ throw new Error(`API error (${e.status}): ${a}`);
1404
+ }
1405
+ return e.json();
1406
+ }
1407
+ function wa(t, e) {
1408
+ return ge ? ea(t, e) : _e(`/${t}/${e}/pipelines`);
1409
+ }
1410
+ function ra(t, e, a) {
1411
+ return ge ? ta(t, e, a) : _e(`/${t}/${e}/pipelines/${a}/yaml`);
1412
+ }
1413
+ function ct(t, e, a, n, l) {
1414
+ if (ge)
1415
+ return aa(t, e, a, n, l);
1416
+ const o = new URLSearchParams({ repo: a, path: n });
1417
+ return l && o.set("branch", l), _e(`/${t}/${e}/file-by-repo-name?${o}`);
1418
+ }
1419
+ function la() {
1420
+ return ge ? na() : _e("/config/task-docs");
1421
+ }
1422
+ function ia(t) {
1423
+ return ge ? sa() : _e(`/${t}/schema/tasks`);
1424
+ }
1425
+ function ca(t) {
1426
+ const {
1427
+ setConnection: e,
1428
+ setSelectedPipeline: a,
1429
+ setSelectedPipelineLoading: n,
1430
+ setSelectedPipelineError: l
1431
+ } = Te(), [o, m] = Z(""), [P, v] = Z(null), [d, r] = Z(!1), y = te(!1);
1432
+ oe(() => {
1433
+ if (y.current) return;
1434
+ y.current = !0;
1435
+ const h = new URLSearchParams(window.location.search), N = t.fileUrl || h.get("url"), b = t.org || h.get("org"), _ = t.project || h.get("project"), L = t.repo || h.get("repo"), x = t.path || h.get("path"), k = t.branch || h.get("branch") || void 0, ae = t.pipelineId ?? (h.get("pipelineId") ? Number(h.get("pipelineId")) : null);
1436
+ if (N)
1437
+ m(N), g(N);
1438
+ else if (b && _ && L && x) {
1439
+ const $ = `https://dev.azure.com/${b}/${_}/_git/${L}?path=${x}${k ? `&version=GB${k}` : ""}`;
1440
+ m($), g($);
1441
+ } else b && _ && ae != null && i(b, _, ae);
1442
+ }, []);
1443
+ const g = async (h) => {
1444
+ const N = Pt(h);
1445
+ if (!N) {
1446
+ v("Invalid Azure DevOps URL");
1447
+ return;
1448
+ }
1449
+ e(N.org, N.project), n(!0), l(null), r(!0);
1450
+ try {
1451
+ const b = await ct(
1452
+ N.org,
1453
+ N.project,
1454
+ N.repoName,
1455
+ N.filePath,
1456
+ N.branch
1457
+ );
1458
+ a({
1459
+ definition: {
1460
+ id: 0,
1461
+ name: N.filePath.split("/").pop() || N.filePath,
1462
+ path: N.filePath,
1463
+ repository: {
1464
+ id: b.repoId,
1465
+ name: b.repoName,
1466
+ type: "git",
1467
+ defaultBranch: b.branch || ""
1468
+ }
1469
+ },
1470
+ yaml: b.content
1471
+ });
1472
+ } catch (b) {
1473
+ l(
1474
+ b instanceof Error ? b.message : String(b)
1475
+ );
1476
+ } finally {
1477
+ n(!1), r(!1);
1478
+ }
1479
+ }, i = async (h, N, b) => {
1480
+ e(h, N), n(!0), l(null);
1481
+ try {
1482
+ const _ = await ra(h, N, b);
1483
+ a(_);
1484
+ } catch (_) {
1485
+ l(
1486
+ _ instanceof Error ? _.message : String(_)
1487
+ );
1488
+ } finally {
1489
+ n(!1);
1490
+ }
1491
+ }, R = async () => {
1492
+ o.trim() && (v(null), await g(o.trim()));
1493
+ };
1494
+ return /* @__PURE__ */ c("div", { className: "pipeline-url-bar", children: [
1495
+ /* @__PURE__ */ s(
1496
+ "input",
1497
+ {
1498
+ type: "text",
1499
+ className: "pipeline-url-bar__input",
1500
+ placeholder: "https://dev.azure.com/{org}/{project}/_git/{repo}?path=/{pipeline}.yml",
1501
+ value: o,
1502
+ onChange: (h) => m(h.target.value),
1503
+ onKeyDown: (h) => {
1504
+ h.key === "Enter" && (h.preventDefault(), R());
1505
+ }
1506
+ }
1507
+ ),
1508
+ /* @__PURE__ */ s(
1509
+ "button",
1510
+ {
1511
+ className: "pipeline-url-bar__btn",
1512
+ onClick: R,
1513
+ disabled: !o.trim() || d,
1514
+ children: d ? "⏳ Loading..." : "Load"
1515
+ }
1516
+ ),
1517
+ P && /* @__PURE__ */ s("div", { className: "pipeline-url-bar__error", children: P })
1518
+ ] });
1519
+ }
1520
+ const da = 280, pa = 900, ua = 420;
1521
+ function ma(t) {
1522
+ const { setCustomTaskDocs: e, setTaskSchema: a, selectedNodeDetail: n, org: l } = Te(), [o, m] = Z(ua), P = te(!1);
1523
+ oe(() => {
1524
+ la().then((d) => e(d.customTaskDocs)).catch(() => {
1525
+ });
1526
+ }, [e]), oe(() => {
1527
+ l && ia(l).then((d) => a(d.tasks)).catch(() => {
1528
+ });
1529
+ }, [l, a]);
1530
+ const v = fe(
1531
+ (d) => {
1532
+ d.preventDefault(), P.current = !0;
1533
+ const r = d.clientX, y = o;
1534
+ document.body.style.cursor = "col-resize", document.body.style.userSelect = "none";
1535
+ const g = (R) => {
1536
+ const S = r - R.clientX, h = Math.min(
1537
+ pa,
1538
+ Math.max(da, y + S)
1539
+ );
1540
+ m(h);
1541
+ }, i = () => {
1542
+ P.current = !1, document.body.style.cursor = "", document.body.style.userSelect = "", window.removeEventListener("mousemove", g), window.removeEventListener("mouseup", i);
1543
+ };
1544
+ window.addEventListener("mousemove", g), window.addEventListener("mouseup", i);
1545
+ },
1546
+ [o]
1547
+ );
1548
+ return /* @__PURE__ */ s(Vt, { value: ct, children: /* @__PURE__ */ c("div", { className: "app", children: [
1549
+ /* @__PURE__ */ c("header", { className: "app__header", children: [
1550
+ /* @__PURE__ */ s("h1", { children: "🔧 Azure Pipelines Visualizer" }),
1551
+ /* @__PURE__ */ s(Ie, { children: /* @__PURE__ */ s(ca, { ...t }) })
1552
+ ] }),
1553
+ /* @__PURE__ */ c("main", { className: "app__main", children: [
1554
+ /* @__PURE__ */ s("section", { className: "app__content", children: /* @__PURE__ */ s(Ie, { children: /* @__PURE__ */ s(qt, {}) }) }),
1555
+ n && /* @__PURE__ */ c(et, { children: [
1556
+ /* @__PURE__ */ s(
1557
+ "div",
1558
+ {
1559
+ className: "app__detail-resize-handle",
1560
+ onMouseDown: v,
1561
+ title: "Drag to resize"
1562
+ }
1563
+ ),
1564
+ /* @__PURE__ */ s("aside", { className: "app__detail", style: { width: o }, children: /* @__PURE__ */ s(Ie, { children: /* @__PURE__ */ s(Lt, {}) }) })
1565
+ ] })
1566
+ ] })
1567
+ ] }) });
1568
+ }
1569
+ var Oe, Re = Dt;
1570
+ if (process.env.NODE_ENV === "production")
1571
+ Oe = Re.createRoot, Re.hydrateRoot;
1572
+ else {
1573
+ var Ze = Re.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
1574
+ Oe = function(t, e) {
1575
+ Ze.usingClientEntryPoint = !0;
1576
+ try {
1577
+ return Re.createRoot(t, e);
1578
+ } finally {
1579
+ Ze.usingClientEntryPoint = !1;
1580
+ }
1581
+ };
1582
+ }
1583
+ function Ra(t, e = {}) {
1584
+ let a = { ...e };
1585
+ const n = Oe(t);
1586
+ function l(o) {
1587
+ n.render(ht(ma, o));
1588
+ }
1589
+ return l(a), {
1590
+ unmount: () => n.unmount(),
1591
+ update: (o) => {
1592
+ a = { ...a, ...o }, l(a);
1593
+ }
1594
+ };
1595
+ }
1596
+ export {
1597
+ ma as App,
1598
+ Lt as DetailPanel,
1599
+ Ie as ErrorBoundary,
1600
+ Bt as FileNode,
1601
+ qt as PipelineDiagram,
1602
+ ca as PipelineSelector,
1603
+ Kt as TemplateEdge,
1604
+ ct as fetchFileByRepoName,
1605
+ ra as fetchPipelineYaml,
1606
+ wa as fetchPipelines,
1607
+ la as fetchTaskDocsConfig,
1608
+ ia as fetchTaskSchema,
1609
+ Fe as getLayoutedElements,
1610
+ Ra as mount,
1611
+ Te as usePipelineStore
1612
+ };