@buun_group/plotwork-mcp 0.1.0-beta.6 → 0.1.0-beta.7

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/plotwork-mcp.mjs CHANGED
@@ -51,7 +51,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
51
51
  var package_default;
52
52
  var init_package = __esm({
53
53
  "package.json"() {
54
- package_default = { version: "0.1.0-beta.6" };
54
+ package_default = { version: "0.1.0-beta.7" };
55
55
  }
56
56
  });
57
57
 
@@ -643,7 +643,7 @@ var init_view_links = __esm({
643
643
  };
644
644
  CLI_RELEASE = {
645
645
  packageName: "@buun_group/plotwork",
646
- version: "0.1.0-beta.7",
646
+ version: "0.1.0-beta.8",
647
647
  onNpm: true
648
648
  };
649
649
  }
@@ -662,7 +662,7 @@ var init_mcp_release = __esm({
662
662
  "use strict";
663
663
  MCP_RELEASE = {
664
664
  packageName: "@buun_group/plotwork-mcp",
665
- version: "0.1.0-beta.5"
665
+ version: "0.1.0-beta.6"
666
666
  };
667
667
  }
668
668
  });
@@ -6944,7 +6944,11 @@ var init_guide = __esm({
6944
6944
  helm: { reads: "The output of helm template, or a chart folder (Chart.yaml, charts/, Chart.lock, values.yaml).", draws: "flow as kubernetes framed by release and chart, or a flow of charts and their dependencies", options: "none." },
6945
6945
  kustomize: { reads: "The output of kustomize build, or a folder of kustomization.yaml files with what they list.", draws: "flow as kubernetes, or a flow of overlays, bases, and components", options: "none." },
6946
6946
  backstage: { reads: "Backstage catalog descriptors (catalog-info.yaml), one file or a folder.", draws: "flow of components, APIs, and resources in systems and domains", options: "groupBy owner: frame by the owning group instead." },
6947
+ structurizr: { reads: "A Structurizr workspace: its DSL (workspace.dsl, with !identifiers hierarchical) or its JSON export.", draws: "c4 of one view: the containers of the first system that has some, or the view the workspace defines first", options: "view context, container, or component; root: the system or container, by identifier or name." },
6948
+ asyncapi: { reads: "AsyncAPI 2.x or 3.x documents in YAML or JSON; send one application's, or a folder of them in files.", draws: "flow of applications and channels in their brokers' frames, an arrow for each send or receive labelled with its messages", options: "none." },
6947
6949
  "github-actions": { reads: "A GitHub Actions workflow file.", draws: "flow of the trigger, the jobs in needs order, and their steps", options: "none." },
6950
+ "gitlab-ci": { reads: "A .gitlab-ci.yml; extends and hidden jobs are resolved, include: is not fetched.", draws: "flow of stages as frames in order, jobs by needs or stage after stage, dashed when manual or by rules, triggers to downstream pipelines", options: "none." },
6951
+ "azure-pipelines": { reads: "An azure-pipelines.yml: stages, jobs, and deployment jobs, or a file of only jobs or steps; templates are not fetched.", draws: "flow of stages as frames, jobs by dependsOn at both levels, deployments with their environment", options: "none." },
6948
6952
  csv: { reads: "A CSV, TSV, or semicolon-separated table.", draws: "the chart its shape suits: xychart, pie, sankey, treemap, or matrix", options: "chart: auto or one of those." },
6949
6953
  json: { reads: "Records, rows, a name to number object, or nested objects of numbers.", draws: "the same charts as csv", options: "chart." },
6950
6954
  tree: { reads: "tree output, a list of paths, or an indented outline.", draws: "tree", options: "none." },
@@ -6958,8 +6962,8 @@ var IMPORT_FORMATS, IMPORT_VIEWS, IMPORT_CHARTS, IMPORT_GROUP_BY, NO_STATS;
6958
6962
  var init_types2 = __esm({
6959
6963
  "../../packages/diagrams/src/importers/types.ts"() {
6960
6964
  "use strict";
6961
- IMPORT_FORMATS = ["sql", "prisma", "drizzle", "openapi", "terraform", "terraform-plan", "bicep", "arm", "pulumi", "cloudformation", "cdk", "compose", "kubernetes", "helm", "kustomize", "backstage", "github-actions", "csv", "json", "tree", "git-log"];
6962
- IMPORT_VIEWS = ["endpoints", "map", "sequence", "git", "timeline"];
6965
+ IMPORT_FORMATS = ["sql", "prisma", "drizzle", "openapi", "terraform", "terraform-plan", "bicep", "arm", "pulumi", "cloudformation", "cdk", "compose", "kubernetes", "helm", "kustomize", "backstage", "structurizr", "asyncapi", "github-actions", "gitlab-ci", "azure-pipelines", "csv", "json", "tree", "git-log"];
6966
+ IMPORT_VIEWS = ["endpoints", "map", "sequence", "git", "timeline", "context", "container", "component"];
6963
6967
  IMPORT_CHARTS = ["auto", "xychart", "pie", "sankey", "treemap", "matrix"];
6964
6968
  IMPORT_GROUP_BY = ["module", "network", "file", "owner"];
6965
6969
  NO_STATS = { items: 0, links: 0, groups: 0, dropped: 0 };
@@ -7023,7 +7027,8 @@ var init_looks = __esm({
7023
7027
  system: { caption: "Software System", frame: "dashed", icon: null },
7024
7028
  container: { caption: "Container", frame: "dashed", icon: null },
7025
7029
  enterprise: { caption: "Enterprise", frame: "dashed", icon: null },
7026
- deployment: { caption: "Deployment Node", frame: "solid", icon: "lucide:server" }
7030
+ deployment: { caption: "Deployment Node", frame: "solid", icon: "lucide:server" },
7031
+ group: { caption: "Group", frame: "dashed", icon: null }
7027
7032
  };
7028
7033
  }
7029
7034
  });
@@ -102504,13 +102509,13 @@ var init_stretch = __esm({
102504
102509
  function tryRoutes(scene, changes) {
102505
102510
  const old = changes.map(({ edge }) => ({ edge, points: edge.points, label: edge.label, hits: intrusions(scene, edge, edge.points, edge.label) }));
102506
102511
  const crossingsOf2 = (edge) => scene.edges.reduce((sum, other) => other === edge ? sum : sum + crossingsNear(edge.points, other.points), 0);
102507
- const runsOf5 = (edge) => scene.edges.reduce((sum, other) => other === edge ? sum : sum + sharedRuns(edge.points, other.points), 0);
102508
- const before = changes.reduce((sum, { edge }) => ({ crossings: sum.crossings + crossingsOf2(edge), runs: sum.runs + runsOf5(edge), bends: sum.bends + bends(edge.points) }), { crossings: 0, runs: 0, bends: 0 });
102512
+ const runsOf6 = (edge) => scene.edges.reduce((sum, other) => other === edge ? sum : sum + sharedRuns(edge.points, other.points), 0);
102513
+ const before = changes.reduce((sum, { edge }) => ({ crossings: sum.crossings + crossingsOf2(edge), runs: sum.runs + runsOf6(edge), bends: sum.bends + bends(edge.points) }), { crossings: 0, runs: 0, bends: 0 });
102509
102514
  for (const change of changes) {
102510
102515
  change.edge.points = change.points;
102511
102516
  change.edge.label = change.label;
102512
102517
  }
102513
- const after = changes.reduce((sum, { edge }) => ({ crossings: sum.crossings + crossingsOf2(edge), runs: sum.runs + runsOf5(edge), bends: sum.bends + bends(edge.points) }), { crossings: 0, runs: 0, bends: 0 });
102518
+ const after = changes.reduce((sum, { edge }) => ({ crossings: sum.crossings + crossingsOf2(edge), runs: sum.runs + runsOf6(edge), bends: sum.bends + bends(edge.points) }), { crossings: 0, runs: 0, bends: 0 });
102514
102519
  const isClean = old.every(({ edge, hits }) => isSubset(intrusions(scene, edge, edge.points, edge.label), hits)) && after.crossings <= before.crossings && after.runs <= before.runs && after.bends <= before.bends;
102515
102520
  if (isClean) return true;
102516
102521
  for (const { edge, points, label } of old) {
@@ -105226,7 +105231,7 @@ var init_words = __esm({
105226
105231
  C4_VIEWS = ["context", "container", "component", "deployment", "dynamic"];
105227
105232
  DEFAULT_VIEW = "container";
105228
105233
  C4_ELEMENT_WORDS = ["person", "system", "container", "component", "db"];
105229
- C4_BOUNDARY_KINDS = ["system", "container", "enterprise", "deployment"];
105234
+ C4_BOUNDARY_KINDS = ["system", "container", "enterprise", "deployment", "group"];
105230
105235
  DEFAULT_BOUNDARY_KIND = "system";
105231
105236
  C4_HEADER_OPTIONS = ["view", "direction", "desc", "icons"];
105232
105237
  C4_ELEMENT_OPTIONS = ["desc", "tech", "external", "icon", "tone"];
@@ -105351,7 +105356,7 @@ function resolveRelationships(state) {
105351
105356
  const elementIds = new Set(state.elements.map((element) => element.id));
105352
105357
  const boundaryIds = new Set(state.boundaries.map((boundary) => boundary.id));
105353
105358
  const names8 = [...elementIds];
105354
- const resolved = [];
105359
+ const resolved2 = [];
105355
105360
  let suggested = 0;
105356
105361
  for (const pending of state.pending) {
105357
105362
  const missing = [pending.from, pending.to].filter((end) => !elementIds.has(end.text));
@@ -105362,19 +105367,19 @@ function resolveRelationships(state) {
105362
105367
  state.report.push(errorAt(DIAGNOSTIC_CODES.unknownNode, message2, spanOf2(end), `${guess}Declare it first with: container ${end.text} "Name"`));
105363
105368
  }
105364
105369
  if (missing.length > 0) continue;
105365
- resolved.push({
105366
- id: toEdgeId(resolved.length),
105370
+ resolved2.push({
105371
+ id: toEdgeId(resolved2.length),
105367
105372
  from: toNodeId(pending.from.text),
105368
105373
  to: toNodeId(pending.to.text),
105369
105374
  label: pending.label,
105370
105375
  tech: pending.tech,
105371
105376
  line: pending.arrow.line,
105372
105377
  heads: pending.arrow.heads,
105373
- ...state.view === "dynamic" ? { step: DEFAULT_FIRST_STEP + resolved.length } : {},
105378
+ ...state.view === "dynamic" ? { step: DEFAULT_FIRST_STEP + resolved2.length } : {},
105374
105379
  at: pending.at
105375
105380
  });
105376
105381
  }
105377
- return resolved;
105382
+ return resolved2;
105378
105383
  }
105379
105384
  function dispatch(line3, state, scopes) {
105380
105385
  const cursor = new TokenCursor(line3.tokens);
@@ -106393,7 +106398,7 @@ function c4Vocabulary() {
106393
106398
  example: 'container api "API Application" tech="Spring Boot" desc="Serves the banking data as JSON."'
106394
106399
  },
106395
106400
  {
106396
- syntax: 'boundary <id> "Name" kind=system|container|enterprise|deployment tech="<technology>" {',
106401
+ syntax: 'boundary <id> "Name" kind=system|container|enterprise|deployment|group tech="<technology>" {',
106397
106402
  meaning: "Opens a boundary: a frame with its name and a caption such as [Software System] in a corner tab, around the elements written inside it. Boundaries nest, up to four deep, and close with } on a line of its own. A deployment boundary is a solid frame with a server icon, and tech= is its technology, such as Ubuntu 22.04.",
106398
106403
  example: 'boundary bank "Internet Banking System" kind=system {'
106399
106404
  },
@@ -108974,15 +108979,15 @@ function resolveRelation(pending, state, ids, known3, index2) {
108974
108979
  }
108975
108980
  function resolveNotes(state) {
108976
108981
  const ids = state.classes.map((node3) => node3.id);
108977
- const resolved = [];
108982
+ const resolved2 = [];
108978
108983
  for (const note of state.notes) {
108979
108984
  if (note.target !== null && !ids.includes(note.target.text)) {
108980
108985
  state.report.push(errorAt(DIAGNOSTIC_CODES.unknownNode, `Unknown class "${note.target.text}"`, note.target, `${didYouMean(note.target.text, ids)} A note belongs to a class: note on Order : "text"`));
108981
108986
  continue;
108982
108987
  }
108983
- resolved.push({ id: `note${resolved.length}`, text: note.text, target: note.target === null ? null : toNodeId(note.target.text), at: note.at });
108988
+ resolved2.push({ id: `note${resolved2.length}`, text: note.text, target: note.target === null ? null : toNodeId(note.target.text), at: note.at });
108984
108989
  }
108985
- return resolved;
108990
+ return resolved2;
108986
108991
  }
108987
108992
  function parseClass(lines, report3) {
108988
108993
  const state = {
@@ -109017,8 +109022,8 @@ function parseClass(lines, report3) {
109017
109022
  const ids = state.classes.map((node3) => node3.id);
109018
109023
  const known3 = new Set(ids);
109019
109024
  for (const pending of state.relations) {
109020
- const resolved = resolveRelation(pending, state, ids, known3, relations.length);
109021
- if (resolved !== null) relations.push(resolved);
109025
+ const resolved2 = resolveRelation(pending, state, ids, known3, relations.length);
109026
+ if (resolved2 !== null) relations.push(resolved2);
109022
109027
  }
109023
109028
  return {
109024
109029
  kind: "class",
@@ -110654,7 +110659,7 @@ function isRefused(member, at3, overlay, seen, state, parents) {
110654
110659
  function resolveOverlays(state) {
110655
110660
  const parents = parentsOf2(state);
110656
110661
  const claimedBy = /* @__PURE__ */ new Map();
110657
- const resolved = [];
110662
+ const resolved2 = [];
110658
110663
  for (const overlay of state.overlays) {
110659
110664
  const seen = /* @__PURE__ */ new Set();
110660
110665
  let isSound = true;
@@ -110678,9 +110683,9 @@ function resolveOverlays(state) {
110678
110683
  if (!isSound) continue;
110679
110684
  for (const member of overlay.members) claimedBy.set(member, overlay.id);
110680
110685
  const { memberAt: _memberAt, ...rest } = overlay;
110681
- resolved.push(rest);
110686
+ resolved2.push(rest);
110682
110687
  }
110683
- return resolved;
110688
+ return resolved2;
110684
110689
  }
110685
110690
  var init_overlay_resolve = __esm({
110686
110691
  "../../packages/diagrams/src/parse/overlay-resolve.ts"() {
@@ -110734,7 +110739,7 @@ function closeScope3(line3, state, scopes) {
110734
110739
  function resolveEdges(state) {
110735
110740
  const nodeIds = state.nodes.map((node3) => node3.id);
110736
110741
  const known3 = new Set(nodeIds);
110737
- const resolved = [];
110742
+ const resolved2 = [];
110738
110743
  for (const edge of state.edges) {
110739
110744
  const missing = [
110740
110745
  { id: edge.from, token: edge.fromToken },
@@ -110746,8 +110751,8 @@ function resolveEdges(state) {
110746
110751
  state.report.push(errorAt(DIAGNOSTIC_CODES.unknownNode, `Unknown node "${end.id}"`, end.token, hint2));
110747
110752
  }
110748
110753
  if (missing.length === 0) {
110749
- resolved.push({
110750
- id: toEdgeId(resolved.length),
110754
+ resolved2.push({
110755
+ id: toEdgeId(resolved2.length),
110751
110756
  from: toNodeId(edge.from),
110752
110757
  to: toNodeId(edge.to),
110753
110758
  label: edge.label,
@@ -110760,7 +110765,7 @@ function resolveEdges(state) {
110760
110765
  });
110761
110766
  }
110762
110767
  }
110763
- return resolved;
110768
+ return resolved2;
110764
110769
  }
110765
110770
  function parseFlow(lines, report3) {
110766
110771
  const state = {
@@ -112649,19 +112654,19 @@ function resolve(declaration) {
112649
112654
  if (fill !== null && tone === null) leftOut.unshift(`fill ${fill} has no tone`);
112650
112655
  return { tone, fill, leftOut };
112651
112656
  }
112652
- function report2(state, declaration, resolved, subject, isApplied) {
112657
+ function report2(state, declaration, resolved2, subject, isApplied) {
112653
112658
  const { reporter } = state.ctx;
112654
- const leftOut = [...resolved.leftOut];
112655
- if (resolved.tone !== null && resolved.fill !== null && isApplied) {
112659
+ const leftOut = [...resolved2.leftOut];
112660
+ if (resolved2.tone !== null && resolved2.fill !== null && isApplied) {
112656
112661
  reporter.add(
112657
112662
  DIAGNOSTIC_CODES.mermaidMappedToNearest,
112658
112663
  declaration.span,
112659
- `The fill ${resolved.fill} of ${subject} became the tone ${resolved.tone}.`,
112664
+ `The fill ${resolved2.fill} of ${subject} became the tone ${resolved2.tone}.`,
112660
112665
  "Check that the tone says what it means. The theme draws it in light and dark.",
112661
112666
  "fill-tone"
112662
112667
  );
112663
- } else if (resolved.tone !== null && resolved.fill !== null) {
112664
- leftOut.unshift(`fill ${resolved.fill} has no node or subgraph to colour`);
112668
+ } else if (resolved2.tone !== null && resolved2.fill !== null) {
112669
+ leftOut.unshift(`fill ${resolved2.fill} has no node or subgraph to colour`);
112665
112670
  }
112666
112671
  if (leftOut.length > 0) reporter.dropped("styleLeftOut", declaration.span, leftOut.join(", "));
112667
112672
  }
@@ -112669,9 +112674,9 @@ function applyStyles(state) {
112669
112674
  const { builder, ctx } = state;
112670
112675
  const classTones = /* @__PURE__ */ new Map();
112671
112676
  for (const declaration of state.classDefs) {
112672
- const resolved = resolve(declaration);
112673
- if (resolved.tone !== null) for (const name2 of declaration.targets) classTones.set(name2, resolved.tone);
112674
- report2(state, declaration, resolved, `the class ${declaration.targets.map((name2) => `"${name2}"`).join(", ")}`, resolved.tone !== null);
112677
+ const resolved2 = resolve(declaration);
112678
+ if (resolved2.tone !== null) for (const name2 of declaration.targets) classTones.set(name2, resolved2.tone);
112679
+ report2(state, declaration, resolved2, `the class ${declaration.targets.map((name2) => `"${name2}"`).join(", ")}`, resolved2.tone !== null);
112675
112680
  }
112676
112681
  for (const node3 of builder.nodes) {
112677
112682
  for (const name2 of node3.classes) {
@@ -112680,9 +112685,9 @@ function applyStyles(state) {
112680
112685
  }
112681
112686
  }
112682
112687
  for (const declaration of state.styles) {
112683
- const resolved = resolve(declaration);
112684
- const applied = resolved.tone === null ? [] : declaration.targets.filter((target) => builder.setTone(target, resolved.tone));
112685
- report2(state, declaration, resolved, `the style of ${declaration.targets.map((target) => `"${target}"`).join(", ")}`, applied.length > 0);
112688
+ const resolved2 = resolve(declaration);
112689
+ const applied = resolved2.tone === null ? [] : declaration.targets.filter((target) => builder.setTone(target, resolved2.tone));
112690
+ report2(state, declaration, resolved2, `the style of ${declaration.targets.map((target) => `"${target}"`).join(", ")}`, applied.length > 0);
112686
112691
  }
112687
112692
  for (const use of state.classUses) {
112688
112693
  if (!classTones.has(use.name)) ctx.reporter.dropped("classAssign", use.span, use.name);
@@ -114278,7 +114283,7 @@ function resolveWindows(ir, calendar, ctx) {
114278
114283
  if (target === void 0) return fail2(task, `${what} "${key}", which is not a task of this chart.`, hint2);
114279
114284
  return windowOf(target, ir.tasks.indexOf(target)) ?? fail2(task, `${what} "${key}", which cannot be placed.`, "Fix that task first, or give this one a start date.");
114280
114285
  };
114281
- const startOf3 = (task, index2) => {
114286
+ const startOf4 = (task, index2) => {
114282
114287
  if (task.start.kind === "date") return task.start.day;
114283
114288
  if (task.start.kind === "previous") {
114284
114289
  const previous = ir.tasks[index2 - 1];
@@ -114289,7 +114294,7 @@ function resolveWindows(ir, calendar, ctx) {
114289
114294
  return ends.length === 0 || ends.includes(null) ? null : Math.max(...ends.map((day) => day ?? 0));
114290
114295
  };
114291
114296
  const place2 = (task, index2) => {
114292
- const wanted2 = startOf3(task, index2);
114297
+ const wanted2 = startOf4(task, index2);
114293
114298
  if (wanted2 === null) return null;
114294
114299
  const start2 = task.start.kind === "date" || !calendar.isActive ? wanted2 : nextWorkingDay(calendar, wanted2);
114295
114300
  const { end } = task;
@@ -119403,7 +119408,7 @@ function close(line3, state) {
119403
119408
  function resolveLinks(state) {
119404
119409
  const ids = state.layers.flatMap((layer2) => layer2.blocks.map((block) => block.id));
119405
119410
  const inAside = new Set(state.asides.flatMap((aside) => aside.blocks.map((block) => block.id)));
119406
- const resolved = [];
119411
+ const resolved2 = [];
119407
119412
  for (const link2 of state.links) {
119408
119413
  const missing = [link2.from, link2.to].filter((end) => !ids.includes(end.text));
119409
119414
  for (const end of missing) {
@@ -119412,9 +119417,9 @@ function resolveLinks(state) {
119412
119417
  }
119413
119418
  if (missing.length > 0) continue;
119414
119419
  if (link2.from.text === link2.to.text) syntax(state, `The block "${link2.from.text}" cannot link to itself`, link2.to, "Link two different blocks.");
119415
- else resolved.push({ from: link2.from.text, to: link2.to.text, label: link2.label, line: link2.line, heads: link2.heads });
119420
+ else resolved2.push({ from: link2.from.text, to: link2.to.text, label: link2.label, line: link2.line, heads: link2.heads });
119416
119421
  }
119417
- return resolved;
119422
+ return resolved2;
119418
119423
  }
119419
119424
  function parseLayers(lines, report3) {
119420
119425
  const state = { title: null, description: null, direction: "down", showCounts: false, layers: [], asides: [], links: [], open: [], declared: /* @__PURE__ */ new Map(), report: report3 };
@@ -127198,14 +127203,14 @@ function resolveEnd(token, tables, report3) {
127198
127203
  return { table: table2, column: columnName2 };
127199
127204
  }
127200
127205
  function resolveRelations(state) {
127201
- const resolved = [];
127206
+ const resolved2 = [];
127202
127207
  for (const pending of state.relations) {
127203
127208
  const from = resolveEnd(pending.from, state.tables, state.report);
127204
127209
  const to = resolveEnd(pending.to, state.tables, state.report);
127205
127210
  if (from === null || to === null) continue;
127206
127211
  const fromColumn = from.table.columns.find((column) => column.name === from.column);
127207
- resolved.push({
127208
- id: toEdgeId(resolved.length),
127212
+ resolved2.push({
127213
+ id: toEdgeId(resolved2.length),
127209
127214
  fromTable: toTableId(from.table.id),
127210
127215
  fromColumn: from.column,
127211
127216
  toTable: toTableId(to.table.id),
@@ -127214,7 +127219,7 @@ function resolveRelations(state) {
127214
127219
  cardinality: fromColumn?.isPrimaryKey === true || fromColumn?.isUnique === true ? "one-to-one" : "many-to-one"
127215
127220
  });
127216
127221
  }
127217
- return resolved;
127222
+ return resolved2;
127218
127223
  }
127219
127224
  function parseSchema(lines, report3) {
127220
127225
  const state = { title: null, description: null, tables: [], relations: [], openTable: null, declared: /* @__PURE__ */ new Map(), report: report3 };
@@ -131287,7 +131292,7 @@ function lineage(id, byId) {
131287
131292
  }
131288
131293
  function resolveTransitions(state, byId) {
131289
131294
  const names8 = state.nodes.filter((node3) => node3.kind === "state" || node3.kind === "composite" || node3.kind === "choice" || node3.kind === "fork" || node3.kind === "join" || node3.kind === "history").map((node3) => node3.id);
131290
- const resolved = [];
131295
+ const resolved2 = [];
131291
131296
  let suggested = 0;
131292
131297
  for (const pending of state.transitions) {
131293
131298
  const missing = [
@@ -131310,9 +131315,9 @@ function resolveTransitions(state, byId) {
131310
131315
  continue;
131311
131316
  }
131312
131317
  const parts = pending.label === null ? { event: null, guard: null, action: null } : splitLabel(pending.label);
131313
- resolved.push({ id: `t${resolved.length}`, from: pending.from, to: pending.to, label: pending.label, ...parts, at: pending.at });
131318
+ resolved2.push({ id: `t${resolved2.length}`, from: pending.from, to: pending.to, label: pending.label, ...parts, at: pending.at });
131314
131319
  }
131315
- return resolved;
131320
+ return resolved2;
131316
131321
  }
131317
131322
  function resolveNotes2(state, byId) {
131318
131323
  const names8 = state.nodes.filter((node3) => node3.kind === "state" || node3.kind === "composite" || node3.kind === "choice").map((node3) => node3.id);
@@ -132593,7 +132598,7 @@ function parseFlow2(cursor, p, line3) {
132593
132598
  }
132594
132599
  function resolveFlows(p) {
132595
132600
  const names8 = p.items.map((item) => item.id);
132596
- const resolved = [];
132601
+ const resolved2 = [];
132597
132602
  let suggested = 0;
132598
132603
  for (const pending of p.pending) {
132599
132604
  const missing = [pending.from, pending.to].filter((end) => !names8.includes(end.text));
@@ -132608,9 +132613,9 @@ function resolveFlows(p) {
132608
132613
  continue;
132609
132614
  }
132610
132615
  const parts = pending.label === null ? { event: null, guard: null, action: null } : splitLabel(pending.label);
132611
- resolved.push({ id: `f${resolved.length}`, from: pending.from.text, to: pending.to.text, label: pending.label, ...parts, line: pending.line, ...pending.step === void 0 ? {} : { step: pending.step }, at: pending.at });
132616
+ resolved2.push({ id: `f${resolved2.length}`, from: pending.from.text, to: pending.to.text, label: pending.label, ...parts, line: pending.line, ...pending.step === void 0 ? {} : { step: pending.step }, at: pending.at });
132612
132617
  }
132613
- return resolved;
132618
+ return resolved2;
132614
132619
  }
132615
132620
  function dispatch11(line3, p, scope) {
132616
132621
  const cursor = new TokenCursor(line3.tokens);
@@ -143355,7 +143360,7 @@ var init_schemas = __esm({
143355
143360
  }
143356
143361
  return propValues;
143357
143362
  });
143358
- const isObject5 = isObject;
143363
+ const isObject6 = isObject;
143359
143364
  const catchall = def.catchall;
143360
143365
  let value;
143361
143366
  const memo3 = globalConfig.memoizer;
@@ -143363,7 +143368,7 @@ var init_schemas = __esm({
143363
143368
  inst._zod.parse = (payload, ctx) => {
143364
143369
  value ?? (value = _normalized.value);
143365
143370
  const input2 = payload.value;
143366
- if (!isObject5(input2)) {
143371
+ if (!isObject6(input2)) {
143367
143372
  payload.issues.push({
143368
143373
  expected: "object",
143369
143374
  code: "invalid_type",
@@ -143499,7 +143504,7 @@ var init_schemas = __esm({
143499
143504
  return doc.compile();
143500
143505
  };
143501
143506
  let fastpass;
143502
- const isObject5 = isObject;
143507
+ const isObject6 = isObject;
143503
143508
  const jit = !globalConfig.jitless;
143504
143509
  const allowsEval2 = allowsEval;
143505
143510
  const fastEnabled = jit && allowsEval2.value;
@@ -143508,7 +143513,7 @@ var init_schemas = __esm({
143508
143513
  inst._zod.parse = (payload, ctx) => {
143509
143514
  value ?? (value = _normalized.value);
143510
143515
  const input2 = payload.value;
143511
- if (!isObject5(input2)) {
143516
+ if (!isObject6(input2)) {
143512
143517
  payload.issues.push({
143513
143518
  expected: "object",
143514
143519
  code: "invalid_type",
@@ -159272,8 +159277,8 @@ function convertBaseSchema(schema, ctx) {
159272
159277
  });
159273
159278
  }
159274
159279
  ctx.processing.add(refPath);
159275
- const resolved = resolveRef(refPath, ctx);
159276
- const zodSchema2 = convertSchema(resolved, ctx);
159280
+ const resolved2 = resolveRef(refPath, ctx);
159281
+ const zodSchema2 = convertSchema(resolved2, ctx);
159277
159282
  ctx.refs.set(refPath, zodSchema2);
159278
159283
  ctx.processing.delete(refPath);
159279
159284
  return zodSchema2;
@@ -161646,9 +161651,9 @@ async function runSync(document2, settings, ops, cache, limit) {
161646
161651
  const render = async (written3, id) => {
161647
161652
  const source = applyDefaults(written3, settings.defaults).source;
161648
161653
  if (calls.length >= limit) {
161649
- const capped = calls.length >= settings.countLimit ? "count" : "bytes";
161650
- calls.push({ id, source, detail: null, capped });
161651
- return { diagnostics: capped === "count" ? CAPPED_BY_COUNT : CAPPED_BY_BYTES };
161654
+ const capped2 = calls.length >= settings.countLimit ? "count" : "bytes";
161655
+ calls.push({ id, source, detail: null, capped: capped2 });
161656
+ return { diagnostics: capped2 === "count" ? CAPPED_BY_COUNT : CAPPED_BY_BYTES };
161652
161657
  }
161653
161658
  const key = `${id}\0${source}`;
161654
161659
  let detail = cache.get(key);
@@ -171949,9 +171954,9 @@ var init_ajvProvider_CEoC_sr = __esm({
171949
171954
  }
171950
171955
  function resolve5(baseURI, relativeURI, options3) {
171951
171956
  const schemelessOptions = options3 ? Object.assign({ scheme: "null" }, options3) : { scheme: "null" };
171952
- const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
171957
+ const resolved2 = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
171953
171958
  schemelessOptions.skipEscape = true;
171954
- return serialize(resolved, schemelessOptions);
171959
+ return serialize(resolved2, schemelessOptions);
171955
171960
  }
171956
171961
  function resolveComponent(base, relative, options3, skipNormalization) {
171957
171962
  const target = {};
@@ -178123,7 +178128,7 @@ var init_sources = __esm({
178123
178128
  tags: external_exports.array(external_exports.string().min(1).max(200)).max(200).optional().describe("openapi: the tags to read."),
178124
178129
  groupBy: external_exports.enum(IMPORT_GROUP_BY).optional().describe("terraform, bicep, arm, pulumi, cloudformation, cdk: module (the default) frames each module's resources and nests them by what they name; network nests by what they name alone; file (terraform) frames them by their .tf file; owner (backstage) frames a catalog by the group that owns each entity."),
178125
178130
  varFiles: external_exports.array(repositoryPath).max(20).optional().describe("terraform: the variables files to apply, as -var-file would; bicep: the .bicepparam file; arm: the parameters file; pulumi: the Pulumi.<stack>.yaml file."),
178126
- root: repositoryPath.optional().describe("terraform, bicep, pulumi, cloudformation, cdk: the root module, deployment, program, template, or stack to draw when the files hold several, such as envs/prod; each is a part of its own when left out.")
178131
+ root: repositoryPath.optional().describe("terraform, bicep, pulumi, cloudformation, cdk: the root module, deployment, program, template, or stack to draw when the files hold several, such as envs/prod; each is a part of its own when left out. structurizr: the system or container the view is about.")
178127
178132
  }).meta({ id: "SourceOptions", description: "The reader options of one source, as import_source takes them." });
178128
178133
  SourcePublishSchema = external_exports.strictObject({
178129
178134
  alias: external_exports.string().min(1).max(60).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "An alias is lower-case words joined by single hyphens, such as checkout-flow").optional().describe("A stable link of a personal key: one address that always shows the latest version."),
@@ -178139,7 +178144,7 @@ var init_sources = __esm({
178139
178144
  from: external_exports.union([pattern2, external_exports.array(pattern2).min(1).max(GENERATE.maxPatterns)]).describe("The files to read: one pattern or a list."),
178140
178145
  format: external_exports.enum(IMPORT_FORMATS).describe("The format of the files, as import_source reads them."),
178141
178146
  out: outPath.describe("The diagram to write: a .diagram file, or a Markdown file and the id of a ```diagram id=<id> fence in it."),
178142
- view: external_exports.enum(IMPORT_VIEWS).optional().describe("openapi: endpoints, map, or sequence; git-log: git or timeline."),
178147
+ view: external_exports.enum(IMPORT_VIEWS).optional().describe("openapi: endpoints, map, or sequence; git-log: git or timeline; structurizr: context, container, or component."),
178143
178148
  title: external_exports.string().min(1).max(120).optional().describe("The title of the diagram; the reader takes one from the files when left out."),
178144
178149
  options: SourceOptionsSchema.optional(),
178145
178150
  overrides: repositoryPath.refine((path) => path.endsWith(".json"), { message: "An overrides file is a .json file" }).optional().describe("The overrides file, applied after every import. Left out: the out path with .overrides.json in place of .diagram, or <file>.<fence id>.overrides.json beside a Markdown file."),
@@ -183291,6 +183296,8 @@ var init_detect = __esm({
183291
183296
  { format: "cdk", test: (text3) => /"?aws:cdk:path"?\s*:/.test(text3) || /"artifacts"\s*:/.test(text3) && /"aws:cloudformation:stack"/.test(text3) },
183292
183297
  { format: "cloudformation", test: (text3) => /^\s*"?AWSTemplateFormatVersion"?\s*:/m.test(text3) || /^Transform\s*:\s*AWS::Serverless/m.test(text3) || /^\s*"?Resources"?\s*:/m.test(text3) && /"?Type"?\s*:\s*["']?AWS::[A-Za-z0-9]+::/.test(text3) },
183293
183298
  { format: "backstage", test: (text3) => /^apiVersion\s*:\s*["']?backstage\.io\//m.test(text3) },
183299
+ { format: "asyncapi", test: (text3) => /^\s*["']?asyncapi["']?\s*:\s*["']?[23]\./m.test(text3) },
183300
+ { format: "structurizr", test: (text3) => /^\s*workspace\b[^\n{]*\{/m.test(text3) && /^\s*model\s*\{/m.test(text3) || /^\s*\{/.test(text3) && /"model"\s*:\s*\{/.test(text3) && /"(?:softwareSystems|people)"\s*:\s*\[/.test(text3) },
183294
183301
  // A kustomization, or what kustomize build makes of one: a generated ConfigMap or Secret whose name ends in its hash.
183295
183302
  { format: "kustomize", test: (text3) => isKustomization(text3) || /^kind\s*:\s*(?:ConfigMap|Secret)\s*$/m.test(text3) && /^\s+name\s*:\s*[\w.-]+-(?=[^-\s]*\d)[b-df-hj-np-tv-z0-9]{10}\s*$/m.test(text3) },
183296
183303
  { format: "helm", test: (text3) => /^\s*apiVersion\s*:/m.test(text3) && /^\s*kind\s*:\s*\w+/m.test(text3) && (/^# Source: [^\n]*\/templates\//m.test(text3) || /^\s*helm\.sh\/chart\s*:/m.test(text3)) || isChartFile(text3) },
@@ -183306,9 +183313,13 @@ var init_detect = __esm({
183306
183313
  NAMES = [
183307
183314
  { format: "compose", words: /\b(?:docker[- ]compose|compose (?:file|yaml|yml|stack))\b/i },
183308
183315
  { format: "backstage", words: /\b(?:backstage|catalog-info(?:\.yaml)?|software catalog)\b/i },
183316
+ { format: "asyncapi", words: /\b(?:asyncapi|async api)\b/i },
183317
+ { format: "structurizr", words: /\b(?:structurizr|workspace\.dsl|c4 (?:model|workspace))\b/i },
183309
183318
  { format: "kustomize", words: /\b(?:kustomize|kustomization(?:\.yaml)?)\b/i },
183310
183319
  { format: "helm", words: /\b(?:helm (?:charts?|template|release)|chart\.yaml)\b/i },
183311
183320
  { format: "kubernetes", words: /\b(?:kubernetes|k8s)\b/i },
183321
+ { format: "gitlab-ci", words: /(?:\.gitlab-ci\.ya?ml\b|\bgitlab(?:[- ]ci| pipelines?| ci\/cd)\b)/i },
183322
+ { format: "azure-pipelines", words: /(?:\bazure-pipelines\.ya?ml\b|\bazure (?:devops )?pipelines?\b)/i },
183312
183323
  { format: "github-actions", words: /\b(?:github actions?|workflow (?:file|yaml|yml)|ci workflow)\b/i },
183313
183324
  { format: "terraform-plan", words: /\b(?:terraform|tofu) (?:plan|state|show -json)\b|\bplan\.json\b/i },
183314
183325
  { format: "terraform", words: /\b(?:terraform|opentofu|hcl|\.tf files?)\b/i },
@@ -183326,7 +183337,7 @@ var init_detect = __esm({
183326
183337
  { format: "json", words: /\bjson (?:data|file|records|export)\b/i },
183327
183338
  { format: "tree", words: /\b(?:tree output|folder (?:structure|tree|listing)|directory (?:tree|listing))\b/i }
183328
183339
  ];
183329
- SURE_FROM_DATA = /* @__PURE__ */ new Set(["sql", "prisma", "drizzle", "openapi", "terraform", "terraform-plan", "bicep", "arm", "pulumi", "cloudformation", "cdk", "compose", "kubernetes", "helm", "kustomize", "backstage", "github-actions", "git-log"]);
183340
+ SURE_FROM_DATA = /* @__PURE__ */ new Set(["sql", "prisma", "drizzle", "openapi", "terraform", "terraform-plan", "bicep", "arm", "pulumi", "cloudformation", "cdk", "compose", "kubernetes", "helm", "kustomize", "backstage", "structurizr", "asyncapi", "github-actions", "git-log"]);
183330
183341
  }
183331
183342
  });
183332
183343
 
@@ -183638,8 +183649,8 @@ function rawValue(resource, name2) {
183638
183649
  return resource.block.attributes.find((attribute2) => attribute2.name === name2)?.raw ?? null;
183639
183650
  }
183640
183651
  function tagName(resource) {
183641
- const resolved = resource.values.get("tags.Name");
183642
- if (resolved !== void 0 && !resolved.includes("{")) return resolved;
183652
+ const resolved2 = resource.values.get("tags.Name");
183653
+ if (resolved2 !== void 0 && !resolved2.includes("{")) return resolved2;
183643
183654
  const tags = rawValue(resource, "tags");
183644
183655
  if (tags === null) return null;
183645
183656
  const match = /\bName\s*=\s*"((?:[^"\\$\n]|\\.)*)"/.exec(tags);
@@ -186358,13 +186369,13 @@ function expression(value, depth) {
186358
186369
  }
186359
186370
  function body5(object2, depth, lines) {
186360
186371
  for (const [key, value] of Object.entries(object2)) {
186361
- const isObject5 = (item) => typeof item === "object" && item !== null && !Array.isArray(item);
186372
+ const isObject6 = (item) => typeof item === "object" && item !== null && !Array.isArray(item);
186362
186373
  if (key === "locals" || key === "tags" || key === "labels" || key === "app_settings" || key === "default" || depth > MAX_DEPTH9) lines.push(`${keyOf2(key)} = ${expression(value, depth)}`);
186363
- else if (isObject5(value)) {
186374
+ else if (isObject6(value)) {
186364
186375
  lines.push(`${keyOf2(key)} {`);
186365
186376
  body5(value, depth + 1, lines);
186366
186377
  lines.push("}");
186367
- } else if (Array.isArray(value) && value.length > 0 && value.every(isObject5)) {
186378
+ } else if (Array.isArray(value) && value.length > 0 && value.every(isObject6)) {
186368
186379
  for (const item of value) {
186369
186380
  lines.push(`${keyOf2(key)} {`);
186370
186381
  body5(item, depth + 1, lines);
@@ -186975,9 +186986,9 @@ var init_evaluate = __esm({
186975
186986
  }
186976
186987
  case "replace": {
186977
186988
  const [value, search, replacement] = args();
186978
- const [known3, find, put] = [value instanceof Partial ? value.name : text3(value), text3(search), text3(replacement)];
186979
- if (known3 === null || find === null || put === null || find === "") return value ?? null;
186980
- const out = known3.split(find).join(put);
186989
+ const [known3, find2, put] = [value instanceof Partial ? value.name : text3(value), text3(search), text3(replacement)];
186990
+ if (known3 === null || find2 === null || put === null || find2 === "") return value ?? null;
186991
+ const out = known3.split(find2).join(put);
186981
186992
  return value instanceof Partial ? new Partial(out) : out;
186982
186993
  }
186983
186994
  case "take":
@@ -188815,8 +188826,537 @@ var init_arm = __esm({
188815
188826
  }
188816
188827
  });
188817
188828
 
188829
+ // ../../packages/diagrams/src/importers/asyncapi/document.ts
188830
+ function nodeOf2(value, depth = 0) {
188831
+ const at3 = { line: 1, column: 1 };
188832
+ if (depth > MAX_DEPTH13 || value === null || value === void 0) return { kind: "scalar", value: "", quoted: false, isNull: true, ...at3 };
188833
+ if (Array.isArray(value)) return { kind: "seq", items: value.map((item) => nodeOf2(item, depth + 1)), ...at3 };
188834
+ if (typeof value === "object") return { kind: "map", entries: Object.entries(value).map(([key, entry2]) => ({ key, value: nodeOf2(entry2, depth + 1), ...at3 })), ...at3 };
188835
+ return { kind: "scalar", value: String(value), quoted: typeof value === "string", isNull: false, ...at3 };
188836
+ }
188837
+ function readDocument(text3) {
188838
+ if (/^\s*\{/.test(text3)) {
188839
+ try {
188840
+ return { root: nodeOf2(JSON.parse(text3)), problem: null };
188841
+ } catch (error62) {
188842
+ return { root: null, problem: { line: 1, column: 1, message: `The JSON cannot be read: ${error62 instanceof Error ? error62.message : "it is not valid"}.`, hint: "Fix the JSON, often a missing or extra comma or quote." } };
188843
+ }
188844
+ }
188845
+ const read = parseYaml(text3);
188846
+ if (read.error !== null) return { root: null, problem: { ...read.error, message: `The YAML cannot be read: ${read.error.message}` } };
188847
+ return { root: read.documents.find((document2) => document2.root !== null)?.root ?? null, problem: null };
188848
+ }
188849
+ function pointerPart(part) {
188850
+ const plain3 = part.replace(/~1/g, "/").replace(/~0/g, "~");
188851
+ try {
188852
+ return decodeURIComponent(plain3);
188853
+ } catch {
188854
+ return plain3;
188855
+ }
188856
+ }
188857
+ function nameOfRef(ref) {
188858
+ const path = ref.slice(ref.indexOf("#") + 1);
188859
+ const last = path.split("/").filter((part) => part !== "").pop() ?? ref;
188860
+ return pointerPart(last);
188861
+ }
188862
+ function deref(root, node3) {
188863
+ let at3 = node3;
188864
+ for (let hop = 0; hop < MAX_HOPS; hop += 1) {
188865
+ const ref = refOf(at3);
188866
+ if (ref === null || !ref.startsWith("#/")) return at3;
188867
+ let target = root;
188868
+ for (const part of ref.slice(2).split("/")) target = get(target, pointerPart(part));
188869
+ if (target === void 0) return at3;
188870
+ at3 = target;
188871
+ }
188872
+ return at3;
188873
+ }
188874
+ var MAX_HOPS, MAX_DEPTH13, refOf;
188875
+ var init_document2 = __esm({
188876
+ "../../packages/diagrams/src/importers/asyncapi/document.ts"() {
188877
+ "use strict";
188878
+ init_yaml();
188879
+ MAX_HOPS = 10;
188880
+ MAX_DEPTH13 = 64;
188881
+ refOf = (node3) => {
188882
+ const ref = get(node3, "$ref");
188883
+ return ref?.kind === "scalar" ? ref.value : null;
188884
+ };
188885
+ }
188886
+ });
188887
+
188888
+ // ../../packages/diagrams/src/importers/asyncapi/spec.ts
188889
+ function messageName(root, node3, fallback) {
188890
+ const ref = refOf(node3);
188891
+ const message2 = deref(root, node3);
188892
+ return text(get(message2, "name")) ?? text(get(message2, "title")) ?? text(get(message2, "messageId")) ?? fallback ?? (ref === null ? null : nameOfRef(ref));
188893
+ }
188894
+ function messagesOf2(root, operation) {
188895
+ const message2 = get(operation, "message");
188896
+ const resolved2 = deref(root, message2);
188897
+ const choices = items(get(resolved2, "oneOf"));
188898
+ const list = choices.length > 0 ? choices : message2 === void 0 ? [] : [message2];
188899
+ return list.map((node3) => messageName(root, node3, null)).filter((name2) => name2 !== null);
188900
+ }
188901
+ function serversOf(root) {
188902
+ return entries(get(root, "servers")).map((entry2) => {
188903
+ const server = deref(root, entry2.value);
188904
+ const host = text(get(server, "host")) ?? text(get(server, "url"));
188905
+ return { name: entry2.key, protocol: (text(get(server, "protocol")) ?? "").toLowerCase(), host, line: entry2.line, column: entry2.column };
188906
+ });
188907
+ }
188908
+ function channelServers(root, channel) {
188909
+ return items(get(channel, "servers")).map((node3) => text(node3) ?? (refOf(node3) === null ? null : nameOfRef(refOf(node3) ?? ""))).filter((name2) => name2 !== null);
188910
+ }
188911
+ function readVersion2(root) {
188912
+ const channels = [];
188913
+ const operations = [];
188914
+ for (const entry2 of entries(get(root, "channels"))) {
188915
+ const channel = deref(root, entry2.value);
188916
+ channels.push({ id: entry2.key, address: entry2.key, description: text(get(channel, "description")), servers: channelServers(root, channel), line: entry2.line, column: entry2.column });
188917
+ for (const [key, direction] of [["subscribe", "send"], ["publish", "receive"]]) {
188918
+ const operation = get(channel, key);
188919
+ if (operation === void 0) continue;
188920
+ const at3 = channel?.kind === "map" ? channel.entries.find((candidate2) => candidate2.key === key) : void 0;
188921
+ operations.push({ id: text(get(operation, "operationId")) ?? `${key} ${entry2.key}`, channel: entry2.key, direction, messages: messagesOf2(root, operation), line: at3?.line ?? entry2.line, column: at3?.column ?? entry2.column });
188922
+ }
188923
+ }
188924
+ return { channels, operations, unresolved: [] };
188925
+ }
188926
+ function readVersion3(root) {
188927
+ const channels = [];
188928
+ const messagesOfChannel = /* @__PURE__ */ new Map();
188929
+ for (const entry2 of entries(get(root, "channels"))) {
188930
+ const channel = deref(root, entry2.value);
188931
+ channels.push({ id: entry2.key, address: text(get(channel, "address")) ?? entry2.key, description: text(get(channel, "description")) ?? text(get(channel, "summary")), servers: channelServers(root, channel), line: entry2.line, column: entry2.column });
188932
+ messagesOfChannel.set(
188933
+ entry2.key,
188934
+ entries(get(channel, "messages")).map((message2) => messageName(root, message2.value, message2.key)).filter((name2) => name2 !== null)
188935
+ );
188936
+ }
188937
+ const operations = [];
188938
+ const unresolved = [];
188939
+ for (const entry2 of entries(get(root, "operations"))) {
188940
+ const operation = deref(root, entry2.value);
188941
+ const action = text(get(operation, "action"));
188942
+ const ref = refOf(get(operation, "channel"));
188943
+ const channel = ref === null ? null : ref.startsWith("#/channels/") ? nameOfRef(ref) : null;
188944
+ if (channel === null || !messagesOfChannel.has(channel)) {
188945
+ unresolved.push({ name: ref ?? entry2.key, line: entry2.line, column: entry2.column });
188946
+ continue;
188947
+ }
188948
+ if (action !== "send" && action !== "receive") continue;
188949
+ const listed2 = items(get(operation, "messages")).map((node3) => {
188950
+ const target = refOf(node3);
188951
+ const key = target === null ? null : nameOfRef(target);
188952
+ return messageName(root, node3, null) ?? key;
188953
+ }).filter((name2) => name2 !== null);
188954
+ operations.push({ id: entry2.key, channel, direction: action, messages: listed2.length > 0 ? listed2 : messagesOfChannel.get(channel) ?? [], line: entry2.line, column: entry2.column });
188955
+ }
188956
+ return { channels, operations, unresolved };
188957
+ }
188958
+ function majorOf(root) {
188959
+ const version2 = text(get(root, "asyncapi"));
188960
+ if (version2 === null) return null;
188961
+ return version2.startsWith("2.") ? 2 : version2.startsWith("3.") ? 3 : null;
188962
+ }
188963
+ function readApplication(root, major) {
188964
+ const info = get(root, "info");
188965
+ const read = major === 2 ? readVersion2(root) : readVersion3(root);
188966
+ return { title: text(get(info, "title")) ?? "Application", version: text(get(root, "asyncapi")) ?? "", appVersion: text(get(info, "version")), major, servers: serversOf(root), ...read };
188967
+ }
188968
+ var init_spec = __esm({
188969
+ "../../packages/diagrams/src/importers/asyncapi/spec.ts"() {
188970
+ "use strict";
188971
+ init_yaml();
188972
+ init_document2();
188973
+ }
188974
+ });
188975
+
188976
+ // ../../packages/diagrams/src/importers/asyncapi/index.ts
188977
+ function familyOf2(protocol) {
188978
+ if (protocol.startsWith("kafka")) return "kafka";
188979
+ if (protocol.startsWith("amqp")) return "amqp";
188980
+ if (protocol.includes("mqtt")) return "mqtt";
188981
+ if (protocol === "wss") return "ws";
188982
+ if (protocol === "https") return "http";
188983
+ return protocol === "" ? "broker" : protocol;
188984
+ }
188985
+ function messagesLabel(messages) {
188986
+ const unique2 = [...new Set(messages.map((message2) => cleanText(message2)))];
188987
+ if (unique2.length === 0) return null;
188988
+ return unique2.length <= 2 ? unique2.join(", ") : `${unique2[0]} and ${unique2.length - 1} more`;
188989
+ }
188990
+ function readAsyncApi(text3, context) {
188991
+ const index2 = new LineIndex(text3);
188992
+ const files = context.files.map((file2, position) => ({ path: file2.path, start: file2.start, text: text3.slice(file2.start, context.files[position + 1]?.start ?? text3.length) }));
188993
+ const at3 = (file2, line3, column) => index2.span(file2.start + file2.text.split("\n").slice(0, line3 - 1).join("\n").length + (line3 > 1 ? 1 : 0) + column - 1);
188994
+ const applications = [];
188995
+ for (const file2 of files) {
188996
+ const read = readDocument(file2.text);
188997
+ const name2 = cleanText(file2.path, "The file");
188998
+ if (read.problem !== null || read.root === null) {
188999
+ const problem = read.problem ?? { line: 1, column: 1, message: "The file is empty.", hint: "Send an AsyncAPI document." };
189000
+ context.report.add(files.length === 1 ? DIAGNOSTIC_CODES.importUnreadable : DIAGNOSTIC_CODES.importSkipped, at3(file2, problem.line, problem.column), `${files.length === 1 ? "" : `${name2} is not drawn: `}${problem.message}`, problem.hint);
189001
+ if (files.length === 1) return null;
189002
+ continue;
189003
+ }
189004
+ const major = majorOf(read.root);
189005
+ if (major === null) {
189006
+ const said = read.root.kind === "map" && read.root.entries.some((entry2) => entry2.key === "asyncapi") ? "is of an AsyncAPI version this reader does not read" : "has no asyncapi: field, so it is not an AsyncAPI document";
189007
+ if (files.length > 1) context.report.add(DIAGNOSTIC_CODES.importSkipped, at3(file2, 1, 1), `${name2} ${said}, and is not drawn.`, "Send AsyncAPI 2.x or 3.x documents; convert a 1.x document with the AsyncAPI converter.");
189008
+ else context.report.add(DIAGNOSTIC_CODES.importNoShape, START, `The text ${said}.`, "Send an AsyncAPI 2.x or 3.x document, which starts with asyncapi: and a version.");
189009
+ continue;
189010
+ }
189011
+ applications.push({ app: readApplication(read.root, major), file: file2 });
189012
+ }
189013
+ if (applications.length === 0) {
189014
+ if (files.length > 1) context.report.add(DIAGNOSTIC_CODES.importNoShape, START, "None of the files is an AsyncAPI document.", "Send AsyncAPI 2.x or 3.x documents, each starting with asyncapi: and a version.");
189015
+ return null;
189016
+ }
189017
+ const nodes = [];
189018
+ const groups = [];
189019
+ const edges = [];
189020
+ const arrows = /* @__PURE__ */ new Map();
189021
+ const channelBox = /* @__PURE__ */ new Map();
189022
+ const brokerHosts = /* @__PURE__ */ new Map();
189023
+ const brokerServers = /* @__PURE__ */ new Map();
189024
+ let operations = 0;
189025
+ for (const { app, file: file2 } of applications) {
189026
+ for (const problem of app.unresolved) context.report.add(DIAGNOSTIC_CODES.importUnresolved, at3(file2, problem.line, problem.column), `The operation names a channel the document does not hold: ${cleanText(problem.name)}, so no arrow is drawn for it.`, "Point channel at an entry of channels, such as $ref: '#/channels/orderPlaced'.");
189027
+ const appKey = `app:${app.title}`;
189028
+ if (!nodes.some((node3) => node3.key === appKey)) nodes.push({ key: appKey, type: "service", label: cleanText(app.title), sub: app.appVersion === null ? null : `Version ${cleanText(app.appVersion)}`, idHint: app.title.toLowerCase() });
189029
+ const serverFamily = new Map(app.servers.map((server) => [server.name, familyOf2(server.protocol)]));
189030
+ for (const server of app.servers) {
189031
+ const family = familyOf2(server.protocol);
189032
+ brokerServers.set(family, [...brokerServers.get(family) ?? [], server]);
189033
+ if (server.host !== null) brokerHosts.set(family, (brokerHosts.get(family) ?? /* @__PURE__ */ new Set()).add(server.host));
189034
+ }
189035
+ for (const channel of app.channels) {
189036
+ const families = new Set((channel.servers.length > 0 ? channel.servers : app.servers.map((server) => server.name)).map((name2) => serverFamily.get(name2)).filter((family2) => family2 !== void 0));
189037
+ const family = families.size === 1 ? [...families][0] : void 0;
189038
+ const key = `channel:${channel.address}`;
189039
+ const existing = channelBox.get(key);
189040
+ if (existing === void 0) {
189041
+ const box = { key, type: "queue", label: cleanText(channel.address), sub: channel.description === null ? null : cleanText(channel.description), group: family === void 0 ? null : `broker:${family}`, idHint: channel.address };
189042
+ channelBox.set(key, box);
189043
+ nodes.push(box);
189044
+ }
189045
+ }
189046
+ for (const operation of app.operations) {
189047
+ const channel = app.channels.find((candidate2) => candidate2.id === operation.channel);
189048
+ if (channel === void 0) continue;
189049
+ const channelKey = `channel:${channel.address}`;
189050
+ operations += 1;
189051
+ const [from, to] = operation.direction === "send" ? [appKey, channelKey] : [channelKey, appKey];
189052
+ const pair2 = `${from}\0${to}`;
189053
+ arrows.set(pair2, { from, to, messages: [...arrows.get(pair2)?.messages ?? [], ...operation.messages] });
189054
+ }
189055
+ }
189056
+ for (const arrow of arrows.values()) edges.push({ from: arrow.from, to: arrow.to, label: messagesLabel(arrow.messages) });
189057
+ const usedFamilies = new Set(nodes.map((node3) => node3.group).filter((group2) => group2 !== null && group2 !== void 0));
189058
+ for (const family of [...brokerServers.keys()]) {
189059
+ const key = `broker:${family}`;
189060
+ if (!usedFamilies.has(key)) continue;
189061
+ const broker = BROKERS[family];
189062
+ const hosts = [...brokerHosts.get(family) ?? []];
189063
+ const servers = brokerServers.get(family) ?? [];
189064
+ const named = servers.map((server) => iconForName(`${server.name} ${server.host ?? ""}`, "queue")).find((icon) => icon?.startsWith("simple:") === true) ?? null;
189065
+ const where = hosts.length === 0 ? null : hosts.length === 1 ? hosts[0] ?? null : `${hosts.length} hosts`;
189066
+ groups.push({ key, label: broker?.label ?? `${family.toUpperCase()} broker`, type: "messaging", icon: broker?.icon ?? named, sub: where === null ? null : cleanText(where), idHint: family });
189067
+ }
189068
+ const unused = [...brokerServers.entries()].filter(([family]) => !usedFamilies.has(`broker:${family}`)).flatMap(([, servers]) => servers);
189069
+ if (unused.length > 0) {
189070
+ const first = unused[0];
189071
+ const file2 = applications.find(({ app }) => app.servers.includes(first))?.file ?? files[0];
189072
+ context.report.add(DIAGNOSTIC_CODES.importSkipped, at3(file2, first.line, first.column), `${countOf2(unused.length, "server")} carr${unused.length === 1 ? "ies" : "y"} no channel that is drawn in a frame, so ${unused.length === 1 ? "it is" : "they are"} not drawn: ${unused.slice(0, 3).map((server) => cleanText(server.name)).join(", ")}.`, "Name the servers of each channel with servers:, so each channel sits in the frame of its broker.");
189073
+ }
189074
+ const sends = (key) => edges.some((edge) => edge.from === key);
189075
+ const receives = (key) => edges.some((edge) => edge.to === key);
189076
+ const rank = (node3) => node3.type === "queue" ? 1 : sends(node3.key) && !receives(node3.key) ? 0 : !sends(node3.key) && receives(node3.key) ? 2 : 1;
189077
+ const ordered = [...nodes].sort((a, b) => rank(a) - rank(b));
189078
+ const one = applications.length === 1 ? applications[0]?.app : void 0;
189079
+ const channels = channelBox.size;
189080
+ return writeFlow(
189081
+ {
189082
+ title: context.title ?? (one === void 0 ? "Event flows" : cleanText(one.title)),
189083
+ desc: one === void 0 ? `${countOf2(applications.length, "application")} and the ${countOf2(channels, "channel")} where they meet: an arrow into a channel sends to it, an arrow out of one receives from it, labelled with the messages. Imported from AsyncAPI.` : `What ${cleanText(one.title)} sends and receives on ${countOf2(channels, "channel")}: an arrow into a channel sends to it, an arrow out of one receives from it, labelled with the messages. Imported from AsyncAPI ${cleanText(one.version)}.`,
189084
+ direction: "right",
189085
+ nodes: ordered,
189086
+ groups,
189087
+ edges,
189088
+ noun: "channels",
189089
+ advice: one === void 0 ? "Check that each channel has the same address in every file that uses it, so producers and consumers meet on one box." : "Import the AsyncAPI documents of the other applications with this one, as files, to see who sends and who receives on each channel.",
189090
+ coverage: { noun: "channels and operations", total: channels + operations, drawn: channels + operations, summarised: 0 }
189091
+ },
189092
+ context.report
189093
+ );
189094
+ }
189095
+ var BROKERS, asyncapiImporter;
189096
+ var init_asyncapi = __esm({
189097
+ "../../packages/diagrams/src/importers/asyncapi/index.ts"() {
189098
+ "use strict";
189099
+ init_core();
189100
+ init_shared2();
189101
+ init_document2();
189102
+ init_spec();
189103
+ BROKERS = {
189104
+ kafka: { label: "Kafka", icon: "simple:apachekafka" },
189105
+ amqp: { label: "AMQP broker", icon: null },
189106
+ mqtt: { label: "MQTT broker", icon: null },
189107
+ nats: { label: "NATS", icon: null },
189108
+ redis: { label: "Redis", icon: "simple:redis" },
189109
+ pulsar: { label: "Pulsar", icon: "simple:apachepulsar" },
189110
+ sns: { label: "Amazon SNS", icon: "aws:sns" },
189111
+ sqs: { label: "Amazon SQS", icon: "aws:sqs" },
189112
+ googlepubsub: { label: "Google Pub/Sub", icon: "gcp:pubsub" },
189113
+ ibmmq: { label: "IBM MQ", icon: null },
189114
+ jms: { label: "JMS broker", icon: null },
189115
+ solace: { label: "Solace", icon: null },
189116
+ stomp: { label: "STOMP broker", icon: null },
189117
+ ws: { label: "WebSocket", icon: null },
189118
+ http: { label: "HTTP", icon: null },
189119
+ anypointmq: { label: "Anypoint MQ", icon: null },
189120
+ mercure: { label: "Mercure", icon: null }
189121
+ };
189122
+ asyncapiImporter = { format: "asyncapi", kinds: ["flow"], joins: "\n", extensions: [".yaml", ".yml", ".json"], read: readAsyncApi };
189123
+ }
189124
+ });
189125
+
189126
+ // ../../packages/diagrams/src/importers/azure-pipelines/pipeline.ts
189127
+ function dependsOnOf2(node3) {
189128
+ const value = get(node3, "dependsOn");
189129
+ if (value === void 0) return null;
189130
+ return items(value).map((item) => text(item)).filter((name2) => name2 !== null && name2 !== "");
189131
+ }
189132
+ function stepLabel(step) {
189133
+ const named = text(get(step, "displayName")) ?? text(get(step, "name"));
189134
+ if (named !== null) return named;
189135
+ const task = text(get(step, "task"));
189136
+ if (task !== null) return task.split("@")[0] ?? task;
189137
+ const checkout = text(get(step, "checkout"));
189138
+ if (checkout !== null) return checkout === "none" ? "No checkout" : `Check out ${checkout}`;
189139
+ for (const key of ["script", "bash", "pwsh", "powershell"]) {
189140
+ const script = text(get(step, key));
189141
+ if (script === null) continue;
189142
+ const first = script.split("\n").map((line3) => line3.trim()).find((line3) => line3 !== "" && !line3.startsWith("#")) ?? "Run a script";
189143
+ if (first.length <= MAX_STEP_LABEL) return first;
189144
+ const cut = first.slice(0, MAX_STEP_LABEL);
189145
+ return cut.lastIndexOf(" ") > 12 ? cut.slice(0, cut.lastIndexOf(" ")) : cut;
189146
+ }
189147
+ for (const key of ["download", "publish", "getPackage", "restoreCache", "reviewApp"]) if (get(step, key) !== void 0) return `${key.charAt(0).toUpperCase()}${key.slice(1)} ${text(get(step, key)) ?? ""}`.trim();
189148
+ return "Step";
189149
+ }
189150
+ function stepsOf(list, templates) {
189151
+ const out = [];
189152
+ for (const step of items(list)) {
189153
+ const template = text(get(step, "template"));
189154
+ if (template !== null) templates.push({ path: template, line: step.line, column: step.column });
189155
+ else if (step.kind === "map") out.push({ label: cleanText(stepLabel(step), "Step"), line: step.line, column: step.column });
189156
+ }
189157
+ return out;
189158
+ }
189159
+ function poolOf(node3, fallback) {
189160
+ const pool = get(node3, "pool");
189161
+ if (pool === void 0) return fallback;
189162
+ return text(pool) ?? text(get(pool, "vmImage")) ?? text(get(pool, "name")) ?? fallback;
189163
+ }
189164
+ function deploymentSteps(job, templates) {
189165
+ const strategy = get(job, "strategy");
189166
+ return entries(strategy).flatMap((kind) => entries(kind.value).flatMap((hook) => (hook.key === "on" ? entries(hook.value).map((when) => when.value) : [hook.value]).flatMap((phase) => stepsOf(get(phase, "steps"), templates))));
189167
+ }
189168
+ function jobsOf(list, pool, templates) {
189169
+ const out = [];
189170
+ for (const job of items(list)) {
189171
+ const template = text(get(job, "template"));
189172
+ if (template !== null) {
189173
+ templates.push({ path: template, line: job.line, column: job.column });
189174
+ continue;
189175
+ }
189176
+ const deployment = text(get(job, "deployment"));
189177
+ const name2 = deployment ?? text(get(job, "job"));
189178
+ if (name2 === null) continue;
189179
+ const strategy = get(job, "strategy");
189180
+ const matrix = entries(get(strategy, "matrix")).length;
189181
+ const parallel = Number(text(get(strategy, "parallel")));
189182
+ const environment = get(job, "environment");
189183
+ out.push({
189184
+ name: name2,
189185
+ label: cleanText(text(get(job, "displayName")) ?? name2, name2),
189186
+ dependsOn: dependsOnOf2(job),
189187
+ conditional: get(job, "condition") !== void 0,
189188
+ environment: deployment === null ? null : text(environment) ?? text(get(environment, "name")),
189189
+ pool: poolOf(job, pool),
189190
+ runs: matrix > 1 ? matrix : Number.isInteger(parallel) && parallel > 1 ? parallel : 1,
189191
+ matrix: matrix > 1,
189192
+ steps: deployment === null ? stepsOf(get(job, "steps"), templates) : deploymentSteps(job, templates),
189193
+ line: job.line,
189194
+ column: job.column
189195
+ });
189196
+ }
189197
+ return out;
189198
+ }
189199
+ function readPipeline(root) {
189200
+ const templates = [];
189201
+ const extended2 = text(get(get(root, "extends"), "template"));
189202
+ if (extended2 !== null) {
189203
+ const at3 = root.kind === "map" ? root.entries.find((entry2) => entry2.key === "extends") : void 0;
189204
+ templates.push({ path: extended2, line: at3?.line ?? 1, column: at3?.column ?? 1 });
189205
+ }
189206
+ const pool = poolOf(root, null);
189207
+ if (get(root, "stages") !== void 0) {
189208
+ const stages = [];
189209
+ for (const stage of items(get(root, "stages"))) {
189210
+ const template = text(get(stage, "template"));
189211
+ if (template !== null) {
189212
+ templates.push({ path: template, line: stage.line, column: stage.column });
189213
+ continue;
189214
+ }
189215
+ const name2 = text(get(stage, "stage"));
189216
+ if (name2 === null) continue;
189217
+ stages.push({ name: name2, label: cleanText(text(get(stage, "displayName")) ?? name2, name2), dependsOn: dependsOnOf2(stage), conditional: get(stage, "condition") !== void 0, jobs: jobsOf(get(stage, "jobs"), poolOf(stage, pool), templates), line: stage.line, column: stage.column });
189218
+ }
189219
+ return { stages, shape: "stages", templates };
189220
+ }
189221
+ if (get(root, "jobs") !== void 0) return { stages: [{ name: "", label: "", dependsOn: [], conditional: false, jobs: jobsOf(get(root, "jobs"), pool, templates), line: 1, column: 1 }], shape: "jobs", templates };
189222
+ const steps = stepsOf(get(root, "steps"), templates);
189223
+ const job = { name: "Job", label: "Job", dependsOn: null, conditional: false, environment: null, pool, runs: 1, matrix: false, steps, line: 1, column: 1 };
189224
+ return { stages: steps.length === 0 ? [] : [{ name: "", label: "", dependsOn: [], conditional: false, jobs: [job], line: 1, column: 1 }], shape: "steps", templates };
189225
+ }
189226
+ var MAX_STEP_LABEL;
189227
+ var init_pipeline = __esm({
189228
+ "../../packages/diagrams/src/importers/azure-pipelines/pipeline.ts"() {
189229
+ "use strict";
189230
+ init_shared2();
189231
+ init_yaml();
189232
+ MAX_STEP_LABEL = 48;
189233
+ }
189234
+ });
189235
+
189236
+ // ../../packages/diagrams/src/importers/azure-pipelines/index.ts
189237
+ function subOf(job, stage) {
189238
+ const parts = [
189239
+ job.conditional || stage.conditional ? "when its condition holds" : null,
189240
+ job.runs > 1 ? `${job.runs} ${job.matrix ? "matrix" : "parallel"} runs` : null,
189241
+ job.environment === null ? null : `deploys to ${job.environment}`,
189242
+ job.pool,
189243
+ job.steps.length === 0 ? null : countOf2(job.steps.length, "step")
189244
+ ].filter((part) => part !== null);
189245
+ return parts.length === 0 ? null : cleanText(parts.join(", "));
189246
+ }
189247
+ function readAzurePipelines(source, context) {
189248
+ const read = parseYaml(source);
189249
+ if (read.error !== null) {
189250
+ context.report.add(DIAGNOSTIC_CODES.importUnreadable, spanAt3(read.error.line, read.error.column), read.error.message, read.error.hint);
189251
+ return null;
189252
+ }
189253
+ const root = read.documents.find((document2) => document2.root?.kind === "map")?.root ?? null;
189254
+ const pipeline = root === null ? null : readPipeline(root);
189255
+ const firstTemplate = pipeline?.templates[0];
189256
+ if (pipeline !== null && firstTemplate !== void 0) {
189257
+ const paths = [...new Set(pipeline.templates.map((template) => cleanText(template.path)))];
189258
+ context.report.add(DIAGNOSTIC_CODES.importSkipped, spanAt3(firstTemplate.line, firstTemplate.column), `${countOf2(paths.length, "template")} ${paths.length === 1 ? "is" : "are"} not fetched, so what ${paths.length === 1 ? "it adds is" : "they add is"} not drawn: ${paths.slice(0, 3).join(", ")}.`, "Import the template files too, or draw this file knowing their stages, jobs, and steps are missing.");
189259
+ }
189260
+ if (pipeline === null || pipeline.stages.every((stage) => stage.jobs.length === 0)) {
189261
+ context.report.add(DIAGNOSTIC_CODES.importNoShape, START, "The file has no stages, jobs, or steps of its own.", "Send an azure-pipelines.yml with stages:, jobs:, or steps:.");
189262
+ return null;
189263
+ }
189264
+ const stages = pipeline.stages.filter((stage) => stage.jobs.length > 0);
189265
+ const nodes = [{ key: START_KEY, type: "terminal", label: "Pipeline starts" }];
189266
+ const groups = [];
189267
+ const edges = [];
189268
+ const unresolved = [];
189269
+ if (pipeline.shape === "steps") {
189270
+ const job = stages[0]?.jobs[0];
189271
+ job.steps.forEach((step, index2) => nodes.push({ key: `step:${index2}`, type: "step", label: step.label, idHint: `step_${index2 + 1}` }));
189272
+ job.steps.forEach((_step, index2) => edges.push({ from: index2 === 0 ? START_KEY : `step:${index2 - 1}`, to: `step:${index2}` }));
189273
+ return writeFlow(
189274
+ {
189275
+ title: context.title ?? "Azure pipeline",
189276
+ desc: `The ${countOf2(job.steps.length, "step")} of an Azure pipeline of one job${job.pool === null ? "" : ` on ${cleanText(job.pool)}`}, in order. Imported from Azure Pipelines.`,
189277
+ direction: "down",
189278
+ nodes,
189279
+ groups,
189280
+ edges,
189281
+ noun: "steps",
189282
+ coverage: { noun: "steps", total: job.steps.length, drawn: job.steps.length, summarised: 0 },
189283
+ advice: "Give each step a displayName, so the picture says what it does."
189284
+ },
189285
+ context.report
189286
+ );
189287
+ }
189288
+ const keyOf5 = (stage, job) => pipeline.shape === "jobs" ? `job:${job.name}` : `job:${stage.name}.${job.name}`;
189289
+ const stageNames = new Set(pipeline.stages.map((stage) => stage.name));
189290
+ for (const stage of stages) {
189291
+ if (pipeline.shape === "stages") groups.push({ key: `stage:${stage.name}`, label: stage.label, type: "ci-cd", idHint: `stage_${hintOf(stage.name)}` });
189292
+ for (const job of stage.jobs) nodes.push({ key: keyOf5(stage, job), type: "step", label: job.label, sub: subOf(job, stage), group: pipeline.shape === "stages" ? `stage:${stage.name}` : null, idHint: hintOf(job.name) });
189293
+ }
189294
+ const inStage = (stage, job) => (job.dependsOn ?? []).filter((name2) => stage.jobs.some((other) => other.name === name2));
189295
+ const firstJobs = (stage) => stage.jobs.filter((job) => inStage(stage, job).length === 0);
189296
+ const lastJobs = (stage) => stage.jobs.filter((job) => !stage.jobs.some((other) => inStage(stage, other).includes(job.name)));
189297
+ stages.forEach((stage, index2) => {
189298
+ const dashed = (job) => job.conditional || stage.conditional ? "-->" : void 0;
189299
+ const link2 = (from, job) => {
189300
+ const arrow = dashed(job);
189301
+ edges.push({ from, to: keyOf5(stage, job), ...arrow === void 0 ? {} : { arrow } });
189302
+ };
189303
+ const before = stage.dependsOn === null ? index2 === 0 ? [] : [stages[index2 - 1]] : stage.dependsOn.flatMap((name2) => {
189304
+ const found = stages.find((other) => other.name === name2);
189305
+ if (found === void 0 && !stageNames.has(name2)) unresolved.push({ name: `stage ${name2}`, line: stage.line, column: stage.column });
189306
+ return found === void 0 ? [] : [found];
189307
+ });
189308
+ for (const job of stage.jobs) {
189309
+ for (const name2 of job.dependsOn ?? []) {
189310
+ if (stage.jobs.some((other) => other.name === name2)) link2(keyOf5(stage, stage.jobs.find((other) => other.name === name2)), job);
189311
+ else unresolved.push({ name: `job ${name2}`, line: job.line, column: job.column });
189312
+ }
189313
+ }
189314
+ for (const job of firstJobs(stage)) {
189315
+ if (before.length === 0) link2(START_KEY, job);
189316
+ for (const previous of before) for (const last of lastJobs(previous)) link2(keyOf5(previous, last), job);
189317
+ }
189318
+ });
189319
+ const first = unresolved[0];
189320
+ if (first !== void 0) {
189321
+ context.report.add(DIAGNOSTIC_CODES.importUnresolved, spanAt3(first.line, first.column), `${countOf2(unresolved.length, "dependsOn")} name${unresolved.length === 1 ? "s" : ""} what the file does not hold, so no arrow is drawn for ${unresolved.length === 1 ? "it" : "them"}: ${unresolved.slice(0, 3).map((entry2) => cleanText(entry2.name)).join(", ")}.`, "Fix the name in dependsOn, or import the template that defines it.");
189322
+ }
189323
+ const jobs = stages.reduce((sum, stage) => sum + stage.jobs.length, 0);
189324
+ const deployments = stages.reduce((sum, stage) => sum + stage.jobs.filter((job) => job.environment !== null).length, 0);
189325
+ return writeFlow(
189326
+ {
189327
+ title: context.title ?? "Azure pipeline",
189328
+ desc: `${countOf2(jobs, "job")}${pipeline.shape === "stages" ? ` in ${countOf2(stages.length, "stage")}` : ""}${deployments === 0 ? "" : `, ${deployments} of which ${deployments === 1 ? "deploys" : "deploy"} to an environment`}, in the order dependsOn sets. A dashed arrow reaches a job that runs only when its condition holds. Imported from Azure Pipelines.`,
189329
+ direction: "down",
189330
+ nodes,
189331
+ groups,
189332
+ edges,
189333
+ noun: "jobs",
189334
+ capSpan: (key) => {
189335
+ const job = stages.flatMap((stage) => stage.jobs.map((entry2) => ({ key: keyOf5(stage, entry2), entry: entry2 }))).find((candidate2) => candidate2.key === key)?.entry;
189336
+ return spanAt3(job?.line ?? 1, job?.column ?? 1);
189337
+ },
189338
+ coverage: { noun: "jobs", total: jobs, drawn: jobs, summarised: 0 },
189339
+ advice: "Give each stage and job a displayName, so the picture says what it does."
189340
+ },
189341
+ context.report
189342
+ );
189343
+ }
189344
+ var hintOf, START_KEY, azurePipelinesImporter;
189345
+ var init_azure_pipelines = __esm({
189346
+ "../../packages/diagrams/src/importers/azure-pipelines/index.ts"() {
189347
+ "use strict";
189348
+ init_core();
189349
+ init_shared2();
189350
+ init_yaml();
189351
+ init_pipeline();
189352
+ hintOf = (name2) => name2.replace(/([a-z0-9])([A-Z][a-z])/g, "$1_$2").toLowerCase();
189353
+ START_KEY = "pipeline";
189354
+ azurePipelinesImporter = { format: "azure-pipelines", kinds: ["flow"], joins: null, extensions: [], read: readAzurePipelines };
189355
+ }
189356
+ });
189357
+
188818
189358
  // ../../packages/diagrams/src/importers/backstage/entities.ts
188819
- function refOf(written3, fallbackKind, namespace) {
189359
+ function refOf2(written3, fallbackKind, namespace) {
188820
189360
  const colon = written3.indexOf(":");
188821
189361
  const kind = colon === -1 ? fallbackKind : written3.slice(0, colon).toLowerCase();
188822
189362
  const rest = colon === -1 ? written3 : written3.slice(colon + 1);
@@ -188833,9 +189373,9 @@ function readEntity2(root) {
188833
189373
  const spec = get(root, "spec");
188834
189374
  const one = (key, fallback) => {
188835
189375
  const value = text(get(spec, key));
188836
- return value === null || value === "" ? null : refOf(value, fallback, namespace);
189376
+ return value === null || value === "" ? null : refOf2(value, fallback, namespace);
188837
189377
  };
188838
- const many = (key, fallback) => names5(get(spec, key)).map((value) => refOf(value, fallback, namespace));
189378
+ const many = (key, fallback) => names5(get(spec, key)).map((value) => refOf2(value, fallback, namespace));
188839
189379
  return {
188840
189380
  kind,
188841
189381
  ref: `${kind.toLowerCase()}:${namespace}/${name2}`,
@@ -188856,14 +189396,14 @@ function readEntity2(root) {
188856
189396
  column: root.column
188857
189397
  };
188858
189398
  }
188859
- var DRAWN_KINDS2, QUIET_KINDS2, nameOfRef;
189399
+ var DRAWN_KINDS2, QUIET_KINDS2, nameOfRef2;
188860
189400
  var init_entities = __esm({
188861
189401
  "../../packages/diagrams/src/importers/backstage/entities.ts"() {
188862
189402
  "use strict";
188863
189403
  init_yaml();
188864
189404
  DRAWN_KINDS2 = ["Domain", "System", "Component", "API", "Resource", "Group", "User"];
188865
189405
  QUIET_KINDS2 = /* @__PURE__ */ new Set(["Location"]);
188866
- nameOfRef = (ref) => ref.slice(ref.lastIndexOf("/") + 1);
189406
+ nameOfRef2 = (ref) => ref.slice(ref.lastIndexOf("/") + 1);
188867
189407
  }
188868
189408
  });
188869
189409
 
@@ -188877,7 +189417,7 @@ function brandOf(...texts) {
188877
189417
  }
188878
189418
  function boxOf3(entity, byOwner) {
188879
189419
  const type = (entity.type ?? "").toLowerCase();
188880
- const said = (words3) => cleanText([words3, entity.lifecycle === null || entity.lifecycle === "production" ? null : entity.lifecycle, byOwner || entity.owner === null ? null : `owned by ${nameOfRef(entity.owner)}`].filter((part) => part !== null).join(", "));
189420
+ const said = (words3) => cleanText([words3, entity.lifecycle === null || entity.lifecycle === "production" ? null : entity.lifecycle, byOwner || entity.owner === null ? null : `owned by ${nameOfRef2(entity.owner)}`].filter((part) => part !== null).join(", "));
188881
189421
  const label = entity.title ?? entity.name;
188882
189422
  if (entity.kind === "API") return { type: "gateway", label, sub: said(`${API_NAMES[type] ?? entity.type ?? ""} API`.trim()), icon: API_ICONS[type] ?? "lucide:plug", idHint: entity.name };
188883
189423
  if (entity.kind === "Resource") {
@@ -188924,15 +189464,15 @@ function readBackstage(textIn, context) {
188924
189464
  }
188925
189465
  for (const entity of boxes2) if (entity.owner !== null && byRef.get(entity.owner)?.kind === "Group") frameOf3.set(entity.ref, entity.owner);
188926
189466
  } else {
188927
- for (const domain2 of entities.filter((entity) => entity.kind === "Domain")) groups.push({ key: domain2.ref, label: domain2.title ?? domain2.name, sub: cleanText(`Domain${domain2.owner === null ? "" : `, owned by ${nameOfRef(domain2.owner)}`}`), icon: "lucide:map", idHint: domain2.name });
188928
- for (const system of entities.filter((entity) => entity.kind === "System")) groups.push({ key: system.ref, label: system.title ?? system.name, sub: cleanText(`System${system.owner === null ? "" : `, owned by ${nameOfRef(system.owner)}`}`), icon: "lucide:boxes", parent: system.domain !== null && byRef.has(system.domain) ? system.domain : null, idHint: system.name });
189467
+ for (const domain2 of entities.filter((entity) => entity.kind === "Domain")) groups.push({ key: domain2.ref, label: domain2.title ?? domain2.name, sub: cleanText(`Domain${domain2.owner === null ? "" : `, owned by ${nameOfRef2(domain2.owner)}`}`), icon: "lucide:map", idHint: domain2.name });
189468
+ for (const system of entities.filter((entity) => entity.kind === "System")) groups.push({ key: system.ref, label: system.title ?? system.name, sub: cleanText(`System${system.owner === null ? "" : `, owned by ${nameOfRef2(system.owner)}`}`), icon: "lucide:boxes", parent: system.domain !== null && byRef.has(system.domain) ? system.domain : null, idHint: system.name });
188929
189469
  for (const entity of boxes2) if (entity.system !== null && byRef.get(entity.system)?.kind === "System") frameOf3.set(entity.ref, entity.system);
188930
189470
  }
188931
189471
  const order = { Component: 0, API: 1, Resource: 2 };
188932
189472
  const ordered = [...boxes2].sort((a, b) => order[a.kind] - order[b.kind]);
188933
189473
  const nodes = ordered.map((entity) => {
188934
189474
  const box = boxOf3(entity, byOwner);
188935
- const system = byOwner && entity.system !== null ? `, in ${nameOfRef(entity.system)}` : "";
189475
+ const system = byOwner && entity.system !== null ? `, in ${nameOfRef2(entity.system)}` : "";
188936
189476
  return { key: entity.ref, ...box, sub: box.sub === null || box.sub === void 0 ? null : cleanText(`${box.sub}${system}`), group: frameOf3.get(entity.ref) ?? null };
188937
189477
  });
188938
189478
  const drawn = new Set(nodes.map((node3) => node3.key));
@@ -189225,14 +189765,14 @@ function templateItems(template, offsetOf) {
189225
189765
  }
189226
189766
  return { items: items2, empty };
189227
189767
  }
189228
- var MAX_DEPTH13, PSEUDO, entryOf, scalarOf, itemsOf, subNames, Template;
189768
+ var MAX_DEPTH14, PSEUDO, entryOf, scalarOf, itemsOf, subNames, Template;
189229
189769
  var init_template = __esm({
189230
189770
  "../../packages/diagrams/src/importers/cloudformation/template.ts"() {
189231
189771
  "use strict";
189232
189772
  init_attributes();
189233
189773
  init_type_names();
189234
189774
  init_value();
189235
- MAX_DEPTH13 = 16;
189775
+ MAX_DEPTH14 = 16;
189236
189776
  PSEUDO = {
189237
189777
  "AWS::Region": "region",
189238
189778
  "AWS::AccountId": "account",
@@ -189264,7 +189804,7 @@ var init_template = __esm({
189264
189804
  conditionMemo = /* @__PURE__ */ new Map();
189265
189805
  /** The value of a node as far as the template's defaults give it. */
189266
189806
  evaluate(node3, depth = 0) {
189267
- if (node3 === void 0 || depth > MAX_DEPTH13) return new Unknown("value");
189807
+ if (node3 === void 0 || depth > MAX_DEPTH14) return new Unknown("value");
189268
189808
  const intrinsic = intrinsicOf(node3);
189269
189809
  if (intrinsic !== null) return this.call(intrinsic, depth);
189270
189810
  if (node3.kind === "scalar") return node3.isNull ? null : node3.value;
@@ -189372,7 +189912,7 @@ var init_template = __esm({
189372
189912
  }
189373
189913
  /** The resources a node names: `Ref`, `GetAtt`, and `${ }` of `Sub`, and only the branch an `If` takes when its condition is known. */
189374
189914
  refs(node3, depth = 0) {
189375
- if (node3 === void 0 || depth > MAX_DEPTH13) return [];
189915
+ if (node3 === void 0 || depth > MAX_DEPTH14) return [];
189376
189916
  const intrinsic = intrinsicOf(node3);
189377
189917
  if (intrinsic !== null) {
189378
189918
  const argument = intrinsic.argument;
@@ -189409,7 +189949,7 @@ var init_template = __esm({
189409
189949
  }
189410
189950
  /** Every reference a node holds, by the keys that lead to it. */
189411
189951
  refsByPath(node3, path, out, depth = 0) {
189412
- if (node3 === void 0 || depth > MAX_DEPTH13) return;
189952
+ if (node3 === void 0 || depth > MAX_DEPTH14) return;
189413
189953
  if (intrinsicOf(node3) === null && node3.kind === "map") {
189414
189954
  for (const entry2 of node3.entries) this.refsByPath(entry2.value, [...path, entry2.key], out, depth + 1);
189415
189955
  return;
@@ -189426,17 +189966,17 @@ var init_template = __esm({
189426
189966
  });
189427
189967
 
189428
189968
  // ../../packages/diagrams/src/importers/cloudformation/index.ts
189429
- function nodeOf2(value, depth = 0) {
189969
+ function nodeOf3(value, depth = 0) {
189430
189970
  const at3 = { line: 1, column: 1 };
189431
189971
  if (depth > 64 || value === null || value === void 0) return { kind: "scalar", value: "", quoted: false, isNull: true, ...at3 };
189432
- if (Array.isArray(value)) return { kind: "seq", items: value.map((item) => nodeOf2(item, depth + 1)), ...at3 };
189433
- if (typeof value === "object") return { kind: "map", entries: Object.entries(value).map(([key, entry2]) => ({ key, value: nodeOf2(entry2, depth + 1), ...at3 })), ...at3 };
189972
+ if (Array.isArray(value)) return { kind: "seq", items: value.map((item) => nodeOf3(item, depth + 1)), ...at3 };
189973
+ if (typeof value === "object") return { kind: "map", entries: Object.entries(value).map(([key, entry2]) => ({ key, value: nodeOf3(entry2, depth + 1), ...at3 })), ...at3 };
189434
189974
  return { kind: "scalar", value: String(value), quoted: typeof value === "string", isNull: false, ...at3 };
189435
189975
  }
189436
189976
  function readFile(text3) {
189437
189977
  if (/^\s*\{/.test(text3)) {
189438
189978
  try {
189439
- return { root: nodeOf2(JSON.parse(text3)), problem: null };
189979
+ return { root: nodeOf3(JSON.parse(text3)), problem: null };
189440
189980
  } catch (error62) {
189441
189981
  return { root: null, problem: { line: 1, column: 1, message: `The template is not JSON: ${error62 instanceof Error ? error62.message : "it cannot be read"}.`, hint: "Send the template as CloudFormation writes it, in JSON or YAML." } };
189442
189982
  }
@@ -189669,7 +190209,7 @@ function readable(segment, stack) {
189669
190209
  const at3 = stack.length >= 3 ? own2.indexOf(stack) : -1;
189670
190210
  return (at3 > 0 ? own2.slice(0, at3) : own2) || segment;
189671
190211
  }
189672
- function frameModules2(tree, classes, startOf3) {
190212
+ function frameModules2(tree, classes, startOf4) {
189673
190213
  const scopes = /* @__PURE__ */ new Map();
189674
190214
  const used = /* @__PURE__ */ new Set();
189675
190215
  const modules = [];
@@ -189684,7 +190224,7 @@ function frameModules2(tree, classes, startOf3) {
189684
190224
  const kind = tree.frames.get(path) ?? "Construct";
189685
190225
  const fqn = classes.get(path) ?? "";
189686
190226
  const own2 = /^(?:aws-cdk-lib|@aws-cdk\/[^.]+)\./.test(fqn) && !/\.(?:Stack|NestedStack|Stage)$/.test(fqn) ? fqn.split(".").pop() ?? "" : "";
189687
- modules.push({ scope, name: path, label: id, instance: null, source: own2, start: startOf3(path), noun: kind });
190227
+ modules.push({ scope, name: path, label: id, instance: null, source: own2, start: startOf4(path), noun: kind });
189688
190228
  }
189689
190229
  return { modules, scopes };
189690
190230
  }
@@ -189849,7 +190389,7 @@ function readCdk(joined2, context) {
189849
190389
  }
189850
190390
  let hops = 0;
189851
190391
  const refsOf = (read, node3) => {
189852
- if (node3 === void 0 || hops >= MAX_HOPS) return [];
190392
+ if (node3 === void 0 || hops >= MAX_HOPS2) return [];
189853
190393
  hops += 1;
189854
190394
  try {
189855
190395
  return read.model.refs(node3).map((ref) => read.names.get(ref) ?? ref);
@@ -189915,12 +190455,12 @@ function readCdk(joined2, context) {
189915
190455
  const maker = makers.get(item.name) ?? null;
189916
190456
  if ((labelCount.get(item.label) ?? 0) > 1 && maker !== null && !item.label.startsWith(`${maker}_`)) items2[position] = { ...item, label: `${maker}_${item.label}` };
189917
190457
  }
189918
- const startOf3 = (path) => {
190458
+ const startOf4 = (path) => {
189919
190459
  const owner = reads.find((read) => read.template.stackPath === path) ?? reads.find((read) => read.template.topPath === path.split("/")[0]);
189920
190460
  const at3 = owner === void 0 ? -1 : owner.template.file.text.indexOf(`"${path}/`);
189921
190461
  return owner === void 0 ? 0 : owner.template.file.start + Math.max(0, at3);
189922
190462
  };
189923
- const { modules, scopes } = frameModules2(tree, assembly.classes, startOf3);
190463
+ const { modules, scopes } = frameModules2(tree, assembly.classes, startOf4);
189924
190464
  const scoped = items2.map((item) => {
189925
190465
  const frames = placements.get(item.name) ?? [];
189926
190466
  const innermost = frames[frames.length - 1];
@@ -189950,7 +190490,7 @@ function readCdk(joined2, context) {
189950
190490
  framing: "construct"
189951
190491
  });
189952
190492
  }
189953
- var LISTED9, MAX_HOPS, METADATA_TYPE, withoutHash, cdkImporter;
190493
+ var LISTED9, MAX_HOPS2, METADATA_TYPE, withoutHash, cdkImporter;
189954
190494
  var init_cdk = __esm({
189955
190495
  "../../packages/diagrams/src/importers/cdk/index.ts"() {
189956
190496
  "use strict";
@@ -189964,7 +190504,7 @@ var init_cdk = __esm({
189964
190504
  init_assembly();
189965
190505
  init_constructs();
189966
190506
  LISTED9 = 3;
189967
- MAX_HOPS = 8;
190507
+ MAX_HOPS2 = 8;
189968
190508
  METADATA_TYPE = "AWS::CDK::Metadata";
189969
190509
  withoutHash = (logical) => logical.replace(/[0-9A-F]{8}$/, "") || logical;
189970
190510
  cdkImporter = { format: "cdk", kinds: ["flow"], joins: "\n", extensions: [".json", ".yaml", ".yml", ".out"], read: readCdk };
@@ -190119,17 +190659,17 @@ var init_services2 = __esm({
190119
190659
  });
190120
190660
 
190121
190661
  // ../../packages/diagrams/src/importers/compose/index.ts
190122
- function subOf(service) {
190662
+ function subOf2(service) {
190123
190663
  const runs = service.image ?? (service.build === null ? null : `build ${service.build}`);
190124
190664
  const ports = service.ports.length === 0 ? null : `${service.ports.length === 1 ? "port" : "ports"} ${service.ports.join(", ")}`;
190125
190665
  const replicas = service.replicas === null || service.replicas === "1" ? null : `${service.replicas} replicas`;
190126
190666
  const parts = [runs, ports, replicas].filter((part) => part !== null);
190127
190667
  return parts.length === 0 ? null : parts.join(", ");
190128
190668
  }
190129
- function nodeOf3(service, group2) {
190669
+ function nodeOf4(service, group2) {
190130
190670
  const look = (service.image === null ? null : imageLook(service.image)) ?? imageLook(service.name);
190131
190671
  const type = look?.type ?? "service";
190132
- return { key: `service:${service.name}`, type, label: service.name, sub: subOf(service), icon: look?.icon ?? iconForName(service.name, type), group: group2, idHint: service.name };
190672
+ return { key: `service:${service.name}`, type, label: service.name, sub: subOf2(service), icon: look?.icon ?? iconForName(service.name, type), group: group2, idHint: service.name };
190133
190673
  }
190134
190674
  function groupsOf(services, networks) {
190135
190675
  const home = /* @__PURE__ */ new Map();
@@ -190187,7 +190727,7 @@ function readCompose(source, context) {
190187
190727
  const mounted = new Set(services.flatMap((service) => service.volumes));
190188
190728
  const volumes = declared(root, "volumes").filter((volume) => mounted.has(volume));
190189
190729
  const nodes = [
190190
- ...services.map((service) => nodeOf3(service, home.get(service.name) ?? null)),
190730
+ ...services.map((service) => nodeOf4(service, home.get(service.name) ?? null)),
190191
190731
  ...volumes.map((volume) => ({ key: `volume:${volume}`, type: "storage", label: volume, sub: "Named volume", idHint: `${volume}_volume` }))
190192
190732
  ];
190193
190733
  const name2 = text(get(root, "name"));
@@ -191942,8 +192482,8 @@ function actionLabel(uses) {
191942
192482
  }
191943
192483
  function commandLabel(run3) {
191944
192484
  const first = run3.split("\n").map((line3) => line3.trim()).find((line3) => line3 !== "" && !line3.startsWith("#")) ?? "Run a script";
191945
- if (first.length <= MAX_STEP_LABEL) return first;
191946
- const cut = first.slice(0, MAX_STEP_LABEL);
192485
+ if (first.length <= MAX_STEP_LABEL2) return first;
192486
+ const cut = first.slice(0, MAX_STEP_LABEL2);
191947
192487
  const space = cut.lastIndexOf(" ");
191948
192488
  return space > 12 ? cut.slice(0, space) : cut;
191949
192489
  }
@@ -192015,13 +192555,13 @@ function triggerOf(root) {
192015
192555
  const short3 = `${words2.map((word2) => word2.short).join(" or ")}${more}`;
192016
192556
  return { label: cleanText(`${short3.charAt(0).toUpperCase()}${short3.slice(1)}`), sentence: cleanText(`${words2.map((word2) => word2.long).join(" or ")}${more}`) };
192017
192557
  }
192018
- var MAX_STEP_LABEL, ACTION_ICONS, COMMAND_ICONS;
192558
+ var MAX_STEP_LABEL2, ACTION_ICONS, COMMAND_ICONS;
192019
192559
  var init_workflow = __esm({
192020
192560
  "../../packages/diagrams/src/importers/github-actions/workflow.ts"() {
192021
192561
  "use strict";
192022
192562
  init_shared2();
192023
192563
  init_yaml();
192024
- MAX_STEP_LABEL = 48;
192564
+ MAX_STEP_LABEL2 = 48;
192025
192565
  ACTION_ICONS = {
192026
192566
  "actions/checkout": "lucide:git-branch",
192027
192567
  "actions/setup-node": "simple:nodedotjs",
@@ -192111,31 +192651,31 @@ function readWorkflow(source, context) {
192111
192651
  return null;
192112
192652
  }
192113
192653
  const ids = new Set(jobs.map((job) => job.id));
192114
- const resolved = jobs.map((job) => {
192654
+ const resolved2 = jobs.map((job) => {
192115
192655
  const missing = job.needs.filter((need) => !ids.has(need));
192116
192656
  for (const need of missing) context.report.add(DIAGNOSTIC_CODES.importUnresolved, spanAt3(job.line, job.column, job.id.length), `Job ${job.id} needs ${need}, which is not a job of this workflow.`, "Fix the name in needs:, or add the job.");
192117
192657
  return missing.length === 0 ? job : { ...job, needs: job.needs.filter((need) => ids.has(need)) };
192118
192658
  });
192119
- const expanded = fitsSteps(resolved);
192120
- const drawn = expanded ? stepBoxes(resolved) : { ...jobBoxes(resolved), groups: [] };
192659
+ const expanded = fitsSteps(resolved2);
192660
+ const drawn = expanded ? stepBoxes(resolved2) : { ...jobBoxes(resolved2), groups: [] };
192121
192661
  const trigger = triggerOf(root);
192122
192662
  const firstOf = (job) => expanded ? job.steps.length === 0 ? `job:${job.id}` : `step:${job.id}:0` : `job:${job.id}`;
192123
- const starts = resolved.filter((job) => job.needs.length === 0).map((job) => ({ from: TRIGGER, to: firstOf(job) }));
192663
+ const starts = resolved2.filter((job) => job.needs.length === 0).map((job) => ({ from: TRIGGER, to: firstOf(job) }));
192124
192664
  const name2 = text(get(root, "name"));
192125
- const depth = depthOf5(resolved);
192126
- const steps = resolved.reduce((sum, job) => sum + job.steps.length, 0);
192665
+ const depth = depthOf5(resolved2);
192666
+ const steps = resolved2.reduce((sum, job) => sum + job.steps.length, 0);
192127
192667
  const coverage = expanded ? { noun: "steps", total: drawn.nodes.length, drawn: drawn.nodes.length, summarised: 0 } : { noun: "steps", total: steps, drawn: 0, summarised: steps };
192128
192668
  return writeFlow(
192129
192669
  {
192130
192670
  title: context.title ?? name2 ?? "GitHub Actions workflow",
192131
- desc: `${countOf2(resolved.length, "job")}${expanded ? " and their steps" : ""} of ${name2 === null ? "a GitHub Actions workflow" : `the ${name2} workflow`}, started by ${trigger === null ? "its trigger" : trigger.sentence}, in the order their needs set, imported from GitHub Actions.`,
192671
+ desc: `${countOf2(resolved2.length, "job")}${expanded ? " and their steps" : ""} of ${name2 === null ? "a GitHub Actions workflow" : `the ${name2} workflow`}, started by ${trigger === null ? "its trigger" : trigger.sentence}, in the order their needs set, imported from GitHub Actions.`,
192132
192672
  direction: expanded || depth > 4 ? "down" : "right",
192133
192673
  nodes: [{ key: TRIGGER, type: "terminal", label: trigger?.label ?? "Workflow starts" }, ...drawn.nodes],
192134
192674
  groups: drawn.groups,
192135
192675
  edges: [...starts, ...drawn.edges],
192136
192676
  noun: expanded ? "steps" : "jobs",
192137
192677
  capSpan: (key) => {
192138
- const job = resolved.find((candidate2) => key === `job:${candidate2.id}`);
192678
+ const job = resolved2.find((candidate2) => key === `job:${candidate2.id}`);
192139
192679
  return spanAt3(job?.line ?? 1, job?.column ?? 1);
192140
192680
  },
192141
192681
  coverage,
@@ -192159,6 +192699,213 @@ var init_github_actions = __esm({
192159
192699
  }
192160
192700
  });
192161
192701
 
192702
+ // ../../packages/diagrams/src/importers/gitlab-ci/pipeline.ts
192703
+ function resolved(name2, byName, missing, depth = 0) {
192704
+ const own2 = byName.get(name2);
192705
+ const out = /* @__PURE__ */ new Map();
192706
+ if (own2 === void 0 || depth > MAX_EXTENDS) return out;
192707
+ for (const parent of names5(get(own2, "extends"))) {
192708
+ if (!byName.has(parent)) {
192709
+ if (!missing.includes(parent)) missing.push(parent);
192710
+ continue;
192711
+ }
192712
+ for (const [key, value] of resolved(parent, byName, missing, depth + 1)) out.set(key, value);
192713
+ }
192714
+ for (const entry2 of entries(own2)) if (entry2.key !== "extends") out.set(entry2.key, entry2.value);
192715
+ return out;
192716
+ }
192717
+ function runsOf5(parallel) {
192718
+ const count3 = Number(text(parallel));
192719
+ if (Number.isInteger(count3) && count3 > 1) return { runs: count3, matrix: false };
192720
+ const matrix = items(get(parallel, "matrix"));
192721
+ if (matrix.length === 0) return { runs: 1, matrix: false };
192722
+ const runs = matrix.reduce((sum, entry2) => sum + entries(entry2).reduce((product, variable) => product * Math.max(1, items(variable.value).length), 1), 0);
192723
+ return { runs, matrix: true };
192724
+ }
192725
+ function startOf3(keys) {
192726
+ const when = text(keys.get("when"));
192727
+ if (when === "manual") return "manual";
192728
+ if (when === "delayed") return "delayed";
192729
+ if (when === "on_failure") return "on_failure";
192730
+ const rules = items(keys.get("rules"));
192731
+ if (rules.some((rule) => text(get(rule, "when")) === "manual")) return "manual";
192732
+ if (rules.length > 0) return "rules";
192733
+ if (keys.has("only") || keys.has("except")) return "only";
192734
+ return "always";
192735
+ }
192736
+ function triggerOf2(node3) {
192737
+ if (node3 === void 0) return null;
192738
+ const project2 = text(node3) ?? text(get(node3, "project"));
192739
+ if (project2 !== null) return { label: project2, child: false };
192740
+ const include = get(node3, "include");
192741
+ const file2 = text(include) ?? items(include).map((entry2) => text(entry2) ?? text(get(entry2, "local")) ?? text(get(entry2, "file")) ?? text(get(entry2, "template")) ?? text(get(entry2, "artifact"))).find((value) => value !== null) ?? null;
192742
+ return { label: file2 ?? "Child pipeline", child: true };
192743
+ }
192744
+ function includesOf(root) {
192745
+ const include = get(root, "include");
192746
+ return items(include).map((entry2) => {
192747
+ const said = text(entry2) ?? (text(get(entry2, "project")) === null ? null : `${text(get(entry2, "project"))}: ${names5(get(entry2, "file")).join(", ")}`) ?? text(get(entry2, "local")) ?? text(get(entry2, "remote")) ?? text(get(entry2, "template")) ?? text(get(entry2, "component")) ?? "an include";
192748
+ return { said: cleanText(said), line: entry2.line, column: entry2.column };
192749
+ });
192750
+ }
192751
+ function readPipeline2(root) {
192752
+ const byName = /* @__PURE__ */ new Map();
192753
+ for (const entry2 of entries(root)) if (entry2.value.kind === "map") byName.set(entry2.key, entry2.value);
192754
+ const written3 = names5(get(root, "stages"));
192755
+ const defaults = get(root, "default");
192756
+ const fallbackImage = text(get(defaults, "image")) ?? text(get(get(defaults, "image"), "name")) ?? text(get(root, "image")) ?? text(get(get(root, "image"), "name"));
192757
+ const jobs = [];
192758
+ for (const entry2 of entries(root)) {
192759
+ if (entry2.key.startsWith(".") || GLOBAL_KEYS.has(entry2.key) || entry2.value.kind !== "map") continue;
192760
+ const missing = [];
192761
+ const keys = resolved(entry2.key, byName, missing);
192762
+ const needsNode = keys.get("needs");
192763
+ const needs2 = needsNode === void 0 ? null : items(needsNode).map((need) => text(need) ?? (get(need, "pipeline") === void 0 && get(need, "project") === void 0 ? text(get(need, "job")) : null)).filter((need) => need !== null);
192764
+ const image = text(keys.get("image")) ?? text(get(keys.get("image"), "name")) ?? fallbackImage;
192765
+ const environment = text(keys.get("environment")) ?? text(get(keys.get("environment"), "name"));
192766
+ const allow = keys.get("allow_failure");
192767
+ jobs.push({
192768
+ name: entry2.key,
192769
+ stage: text(keys.get("stage")) ?? "test",
192770
+ needs: needs2,
192771
+ start: startOf3(keys),
192772
+ image: image === null ? null : image.split("/").pop() ?? image,
192773
+ ...runsOf5(keys.get("parallel")),
192774
+ environment,
192775
+ trigger: triggerOf2(keys.get("trigger")),
192776
+ allowFailure: text(allow) === "true" || allow?.kind === "map",
192777
+ missingExtends: missing,
192778
+ line: entry2.line,
192779
+ column: entry2.column
192780
+ });
192781
+ }
192782
+ return { stages: written3.length > 0 ? written3 : [...DEFAULT_STAGES], stagesWritten: written3.length > 0, jobs, includes: includesOf(root) };
192783
+ }
192784
+ var DEFAULT_STAGES, GLOBAL_KEYS, MAX_EXTENDS;
192785
+ var init_pipeline2 = __esm({
192786
+ "../../packages/diagrams/src/importers/gitlab-ci/pipeline.ts"() {
192787
+ "use strict";
192788
+ init_shared2();
192789
+ init_yaml();
192790
+ DEFAULT_STAGES = [".pre", "build", "test", "deploy", ".post"];
192791
+ GLOBAL_KEYS = /* @__PURE__ */ new Set(["default", "include", "stages", "variables", "workflow", "image", "services", "cache", "before_script", "after_script", "types", "spec"]);
192792
+ MAX_EXTENDS = 11;
192793
+ }
192794
+ });
192795
+
192796
+ // ../../packages/diagrams/src/importers/gitlab-ci/index.ts
192797
+ function subOf3(job) {
192798
+ const parts = [
192799
+ START_WORDS[job.start],
192800
+ job.runs > 1 ? `${job.runs} ${job.matrix ? "matrix" : "parallel"} runs` : null,
192801
+ job.environment === null ? null : `deploys to ${job.environment}`,
192802
+ job.image,
192803
+ job.allowFailure ? "may fail" : null
192804
+ ].filter((part) => part !== null);
192805
+ return parts.length === 0 ? null : cleanText(parts.join(", "));
192806
+ }
192807
+ function readGitlabCi(source, context) {
192808
+ const read = parseYaml(source);
192809
+ if (read.error !== null) {
192810
+ context.report.add(DIAGNOSTIC_CODES.importUnreadable, spanAt3(read.error.line, read.error.column), read.error.message, read.error.hint);
192811
+ return null;
192812
+ }
192813
+ const root = [...read.documents].reverse().find((document2) => document2.root?.kind === "map")?.root ?? null;
192814
+ const pipeline = root === null ? null : readPipeline2(root);
192815
+ if (pipeline === null || pipeline.jobs.length === 0) {
192816
+ const includes = pipeline?.includes.length ?? 0;
192817
+ context.report.add(DIAGNOSTIC_CODES.importNoShape, START, includes > 0 ? "The file has no jobs of its own; they come from what it includes, which is not fetched." : "The file has no jobs.", includes > 0 ? "Import the included files, or a .gitlab-ci.yml with jobs." : "Send a .gitlab-ci.yml with at least one job, a key with a script or a trigger.");
192818
+ return null;
192819
+ }
192820
+ const firstInclude = pipeline.includes[0];
192821
+ if (firstInclude !== void 0) {
192822
+ context.report.add(DIAGNOSTIC_CODES.importSkipped, spanAt3(firstInclude.line, firstInclude.column), `${countOf2(pipeline.includes.length, "include")} ${pipeline.includes.length === 1 ? "is" : "are"} not fetched, so the jobs ${pipeline.includes.length === 1 ? "it adds are" : "they add are"} not drawn: ${pipeline.includes.slice(0, 3).map((include) => include.said).join(", ")}.`, "Import the included files too, or draw this file alone knowing those jobs are missing.");
192823
+ }
192824
+ const names8 = new Set(pipeline.jobs.map((job) => job.name));
192825
+ const missingExtends = pipeline.jobs.filter((job) => job.missingExtends.length > 0);
192826
+ const firstMissing = missingExtends[0];
192827
+ if (firstMissing !== void 0) {
192828
+ const parents = [...new Set(missingExtends.flatMap((job) => job.missingExtends))];
192829
+ context.report.add(DIAGNOSTIC_CODES.importUnresolved, spanAt3(firstMissing.line, firstMissing.column, firstMissing.name.length), `${countOf2(missingExtends.length, "job")} extend${missingExtends.length === 1 ? "s" : ""} ${parents.length === 1 ? "a job" : "jobs"} the file does not hold, so what ${parents.length === 1 ? "it sets is" : "they set is"} not read: ${parents.slice(0, 3).map((name2) => cleanText(name2)).join(", ")}.`, "They often come from an include; import the file that defines them with this one.");
192830
+ }
192831
+ const stages = pipeline.stages.filter((stage) => pipeline.jobs.some((job) => job.stage === stage));
192832
+ const unknown2 = [...new Set(pipeline.jobs.map((job) => job.stage).filter((stage) => !pipeline.stages.includes(stage)))];
192833
+ const firstUnknown = pipeline.jobs.find((job) => unknown2.includes(job.stage));
192834
+ if (firstUnknown !== void 0) {
192835
+ context.report.add(DIAGNOSTIC_CODES.importUnresolved, spanAt3(firstUnknown.line, firstUnknown.column, firstUnknown.name.length), `${countOf2(unknown2.length, "stage")} ${unknown2.length === 1 ? "is" : "are"} used by jobs but not listed in stages, so ${unknown2.length === 1 ? "it is" : "they are"} drawn last: ${unknown2.slice(0, 3).map((stage) => cleanText(stage)).join(", ")}.`, "List every stage in stages:, in the order they run.");
192836
+ }
192837
+ const ordered = [...stages, ...unknown2];
192838
+ const jobsOf2 = (stage) => pipeline.jobs.filter((job) => job.stage === stage);
192839
+ const nodes = [{ key: START_KEY2, type: "terminal", label: "Pipeline starts" }];
192840
+ const groups = [];
192841
+ const edges = [];
192842
+ const unresolvedNeeds = [];
192843
+ for (const stage of ordered) {
192844
+ groups.push({ key: `stage:${stage}`, label: cleanText(stage), type: "ci-cd", idHint: `stage_${stage.replace(/^\./, "")}` });
192845
+ for (const job of jobsOf2(stage)) {
192846
+ nodes.push({ key: `job:${job.name}`, type: "step", label: cleanText(job.name), sub: subOf3(job), icon: job.image === null ? null : imageLook(job.image)?.icon ?? null, group: `stage:${stage}`, idHint: job.name });
192847
+ if (job.trigger !== null) {
192848
+ nodes.push({ key: `trigger:${job.name}`, type: "external", label: cleanText(job.trigger.label), sub: job.trigger.child ? "Child pipeline" : "Downstream pipeline", icon: "simple:gitlab", idHint: `${job.name}_pipeline` });
192849
+ edges.push({ from: `job:${job.name}`, to: `trigger:${job.name}`, label: "triggers" });
192850
+ }
192851
+ }
192852
+ }
192853
+ for (const job of pipeline.jobs) {
192854
+ const arrow = job.start === "always" ? void 0 : "-->";
192855
+ const into = (from) => {
192856
+ edges.push({ from, to: `job:${job.name}`, ...arrow === void 0 ? {} : { arrow } });
192857
+ };
192858
+ if (job.needs !== null) {
192859
+ for (const need of job.needs) {
192860
+ if (names8.has(need)) into(`job:${need}`);
192861
+ else unresolvedNeeds.push({ job, need });
192862
+ }
192863
+ if (job.needs.filter((need) => names8.has(need)).length === 0) into(START_KEY2);
192864
+ continue;
192865
+ }
192866
+ const before = ordered.slice(0, ordered.indexOf(job.stage)).reverse().find((stage) => jobsOf2(stage).length > 0);
192867
+ if (before === void 0) into(START_KEY2);
192868
+ else for (const previous of jobsOf2(before)) into(`job:${previous.name}`);
192869
+ }
192870
+ const firstNeed = unresolvedNeeds[0];
192871
+ if (firstNeed !== void 0) {
192872
+ context.report.add(DIAGNOSTIC_CODES.importUnresolved, spanAt3(firstNeed.job.line, firstNeed.job.column, firstNeed.job.name.length), `${countOf2(unresolvedNeeds.length, "need")} name${unresolvedNeeds.length === 1 ? "s a job" : " jobs"} the file does not hold, so no arrow is drawn for ${unresolvedNeeds.length === 1 ? "it" : "them"}: ${unresolvedNeeds.slice(0, 3).map((entry2) => `${cleanText(entry2.job.name)} needs ${cleanText(entry2.need)}`).join(", ")}.`, "Fix the name in needs:, or import the file that defines the job.");
192873
+ }
192874
+ const triggers = pipeline.jobs.filter((job) => job.trigger !== null).length;
192875
+ return writeFlow(
192876
+ {
192877
+ title: context.title ?? "GitLab CI/CD pipeline",
192878
+ desc: `${countOf2(pipeline.jobs.length, "job")} in ${countOf2(ordered.length, "stage")}${triggers === 0 ? "" : `, ${triggers} of which ${triggers === 1 ? "starts" : "start"} another pipeline`}, in the order they run: by needs, or stage after stage. A dashed arrow reaches a job that runs by hand or by its rules. Imported from GitLab CI/CD.`,
192879
+ // Stages run down the page: across, even three stages of a few jobs are wider than a column.
192880
+ direction: "down",
192881
+ nodes,
192882
+ groups,
192883
+ edges,
192884
+ noun: "jobs",
192885
+ capSpan: (key) => {
192886
+ const job = pipeline.jobs.find((candidate2) => key === `job:${candidate2.name}`);
192887
+ return spanAt3(job?.line ?? 1, job?.column ?? 1);
192888
+ },
192889
+ coverage: { noun: "jobs", total: pipeline.jobs.length, drawn: pipeline.jobs.length, summarised: 0 },
192890
+ advice: pipeline.stagesWritten ? "Add needs: to jobs that do not wait for a whole stage, so the picture shows what really runs in parallel." : "List the stages in stages:, so the picture shows them in the order they run."
192891
+ },
192892
+ context.report
192893
+ );
192894
+ }
192895
+ var START_KEY2, START_WORDS, gitlabCiImporter;
192896
+ var init_gitlab_ci = __esm({
192897
+ "../../packages/diagrams/src/importers/gitlab-ci/index.ts"() {
192898
+ "use strict";
192899
+ init_core();
192900
+ init_shared2();
192901
+ init_yaml();
192902
+ init_pipeline2();
192903
+ START_KEY2 = "pipeline";
192904
+ START_WORDS = { always: null, manual: "manual", rules: "when its rules match", only: "only on some refs", delayed: "delayed", on_failure: "on failure" };
192905
+ gitlabCiImporter = { format: "gitlab-ci", kinds: ["flow"], joins: null, extensions: [], read: readGitlabCi };
192906
+ }
192907
+ });
192908
+
192162
192909
  // ../../packages/diagrams/src/importers/json/locate.ts
192163
192910
  function stringEnd3(text3, start2) {
192164
192911
  for (let index2 = start2 + 1; index2 < text3.length; index2 += 1) {
@@ -192483,7 +193230,7 @@ function withoutSchemaBodies(text3) {
192483
193230
  }
192484
193231
  return lines.join("\n");
192485
193232
  }
192486
- function readDocument(text3, report3) {
193233
+ function readDocument2(text3, report3) {
192487
193234
  const index2 = new LineIndex(text3);
192488
193235
  if (text3.trimStart().startsWith("{")) {
192489
193236
  try {
@@ -192503,7 +193250,7 @@ function readDocument(text3, report3) {
192503
193250
  return root === void 0 || root === null ? null : plain2(root);
192504
193251
  }
192505
193252
  var UNREAD_SECTIONS;
192506
- var init_document2 = __esm({
193253
+ var init_document3 = __esm({
192507
193254
  "../../packages/diagrams/src/importers/openapi/document.ts"() {
192508
193255
  "use strict";
192509
193256
  init_core();
@@ -192860,7 +193607,7 @@ var METHODS;
192860
193607
  var init_operations = __esm({
192861
193608
  "../../packages/diagrams/src/importers/openapi/operations.ts"() {
192862
193609
  "use strict";
192863
- init_document2();
193610
+ init_document3();
192864
193611
  METHODS = ["get", "post", "put", "patch", "delete", "head", "options", "trace"];
192865
193612
  }
192866
193613
  });
@@ -192964,7 +193711,7 @@ function readOpenApi(text3, context) {
192964
193711
  report3.add(DIAGNOSTIC_CODES.importNotFound, START, `An OpenAPI document has no "${asked}" view.`, 'Set options.view to "endpoints" for an access matrix, "map" for the endpoints by tag, or "sequence" for one operation.');
192965
193712
  return null;
192966
193713
  }
192967
- const document2 = readDocument(text3, report3);
193714
+ const document2 = readDocument2(text3, report3);
192968
193715
  if (document2 === null) return null;
192969
193716
  if (!isOpenApi3(document2)) {
192970
193717
  report3.add(DIAGNOSTIC_CODES.importNoShape, START, "The document has no openapi: 3.x field, so it is not an OpenAPI 3 document.", "Send an OpenAPI 3.0 or 3.1 document. A Swagger 2.0 file can be converted with the swagger2openapi tool first.");
@@ -193011,7 +193758,7 @@ var init_openapi = __esm({
193011
193758
  "use strict";
193012
193759
  init_core();
193013
193760
  init_shared2();
193014
- init_document2();
193761
+ init_document3();
193015
193762
  init_endpoints();
193016
193763
  init_map();
193017
193764
  init_operations();
@@ -193303,19 +194050,19 @@ function piecesOf4(value) {
193303
194050
  }
193304
194051
  return out;
193305
194052
  }
193306
- var MAX_DEPTH14, Program;
194053
+ var MAX_DEPTH15, Program;
193307
194054
  var init_program = __esm({
193308
194055
  "../../packages/diagrams/src/importers/pulumi/program.ts"() {
193309
194056
  "use strict";
193310
194057
  init_value();
193311
194058
  init_yaml();
193312
194059
  init_item();
193313
- MAX_DEPTH14 = 16;
194060
+ MAX_DEPTH15 = 16;
193314
194061
  Program = class {
193315
- constructor(root, config2, stack, project) {
194062
+ constructor(root, config2, stack, project2) {
193316
194063
  this.config = config2;
193317
194064
  this.stack = stack;
193318
- this.project = project;
194065
+ this.project = project2;
193319
194066
  this.resources = entries(get(root, "resources")).filter((entry2) => entry2.value.kind === "map").map((entry2) => ({ name: entry2.key, node: entry2.value, line: entry2.line, column: entry2.column }));
193320
194067
  this.variables = new Map(entries(get(root, "variables")).map((entry2) => [entry2.key, entry2.value]));
193321
194068
  const defaults = /* @__PURE__ */ new Map();
@@ -193338,7 +194085,7 @@ var init_program = __esm({
193338
194085
  }
193339
194086
  /** The value of a node as far as the program and the stack give it. */
193340
194087
  evaluate(node3, depth = 0) {
193341
- if (node3 === void 0 || depth > MAX_DEPTH14) return new Unknown("value");
194088
+ if (node3 === void 0 || depth > MAX_DEPTH15) return new Unknown("value");
193342
194089
  if (node3.kind === "scalar") {
193343
194090
  if (node3.isNull) return null;
193344
194091
  if (!node3.value.includes("${")) return node3.value;
@@ -193423,7 +194170,7 @@ var init_program = __esm({
193423
194170
  }
193424
194171
  /** The resources a node names, through the variables it uses. */
193425
194172
  refs(node3, depth = 0) {
193426
- if (node3 === void 0 || depth > MAX_DEPTH14) return [];
194173
+ if (node3 === void 0 || depth > MAX_DEPTH15) return [];
193427
194174
  if (node3.kind === "scalar") {
193428
194175
  if (!node3.value.includes("${")) return [];
193429
194176
  return piecesOf4(node3.value).flatMap((piece) => {
@@ -193446,7 +194193,7 @@ var init_program = __esm({
193446
194193
  }
193447
194194
  /** Every reference a node holds, by the keys that lead to it. */
193448
194195
  refsByPath(node3, path, out, depth) {
193449
- if (node3 === void 0 || depth > MAX_DEPTH14) return;
194196
+ if (node3 === void 0 || depth > MAX_DEPTH15) return;
193450
194197
  if (node3.kind === "map" && !(node3.entries.length === 1 && node3.entries[0]?.key.startsWith("fn::"))) {
193451
194198
  for (const entry2 of node3.entries) this.refsByPath(entry2.value, [...path, entry2.key], out, depth + 1);
193452
194199
  return;
@@ -194244,6 +194991,718 @@ var init_sql = __esm({
194244
194991
  }
194245
194992
  });
194246
194993
 
194994
+ // ../../packages/diagrams/src/importers/structurizr/tokens.ts
194995
+ function tokensOf(line3) {
194996
+ const tokens = [];
194997
+ let index2 = 0;
194998
+ while (index2 < line3.length) {
194999
+ const char = line3.charAt(index2);
195000
+ if (char === " " || char === " ") {
195001
+ index2 += 1;
195002
+ continue;
195003
+ }
195004
+ if (char === '"') {
195005
+ let value = "";
195006
+ let at3 = index2 + 1;
195007
+ for (; at3 < line3.length && line3.charAt(at3) !== '"'; at3 += 1) {
195008
+ if (line3.charAt(at3) === "\\" && at3 + 1 < line3.length) at3 += 1;
195009
+ value += line3.charAt(at3);
195010
+ }
195011
+ tokens.push({ text: value, quoted: true, column: index2 + 1 });
195012
+ index2 = at3 + 1;
195013
+ continue;
195014
+ }
195015
+ if (char === "#" || line3.startsWith("//", index2)) break;
195016
+ let end = index2;
195017
+ while (end < line3.length && !' "'.includes(line3.charAt(end))) end += 1;
195018
+ const word2 = line3.slice(index2, end);
195019
+ let start2 = 0;
195020
+ for (let at3 = 0; at3 < word2.length; at3 += 1) {
195021
+ const single = word2.charAt(at3) === "{" || word2.charAt(at3) === "}" || word2.charAt(at3) === "=";
195022
+ const arrow = word2.startsWith("->", at3);
195023
+ if (!single && !arrow) continue;
195024
+ if (at3 > start2) tokens.push({ text: word2.slice(start2, at3), quoted: false, column: index2 + start2 + 1 });
195025
+ const size = arrow ? 2 : 1;
195026
+ tokens.push({ text: word2.slice(at3, at3 + size), quoted: false, column: index2 + at3 + 1 });
195027
+ start2 = at3 + size;
195028
+ at3 += size - 1;
195029
+ }
195030
+ if (start2 < word2.length) tokens.push({ text: word2.slice(start2), quoted: false, column: index2 + start2 + 1 });
195031
+ index2 = end;
195032
+ }
195033
+ return tokens;
195034
+ }
195035
+ function statementsOf2(text3) {
195036
+ const lines = text3.split("\n");
195037
+ const out = [];
195038
+ let inComment = false;
195039
+ let pending = null;
195040
+ for (let index2 = 0; index2 < lines.length && out.length < MAX_STATEMENTS; index2 += 1) {
195041
+ let line3 = lines[index2] ?? "";
195042
+ if (inComment) {
195043
+ const close2 = line3.indexOf("*/");
195044
+ if (close2 === -1) continue;
195045
+ line3 = " ".repeat(close2 + 2) + line3.slice(close2 + 2);
195046
+ inComment = false;
195047
+ }
195048
+ const trimmed4 = line3.trim();
195049
+ if (trimmed4.startsWith("/*")) {
195050
+ const close2 = line3.indexOf("*/", line3.indexOf("/*") + 2);
195051
+ if (close2 === -1) {
195052
+ inComment = true;
195053
+ continue;
195054
+ }
195055
+ line3 = " ".repeat(close2 + 2) + line3.slice(close2 + 2);
195056
+ }
195057
+ if (line3.trimEnd().endsWith("\\")) {
195058
+ const head = line3.trimEnd().slice(0, -1);
195059
+ pending = pending === null ? { text: head, line: index2 + 1 } : { text: `${pending.text} ${head.trim()}`, line: pending.line };
195060
+ continue;
195061
+ }
195062
+ const whole2 = pending === null ? { text: line3, line: index2 + 1 } : { text: `${pending.text} ${line3.trim()}`, line: pending.line };
195063
+ pending = null;
195064
+ const tokens = tokensOf(whole2.text);
195065
+ if (tokens.length === 0) continue;
195066
+ const open2 = tokens.findIndex((token) => !token.quoted && token.text === "{");
195067
+ const last = tokens[tokens.length - 1];
195068
+ if (open2 !== -1 && open2 < tokens.length - 1 && last !== void 0 && !last.quoted && last.text === "}") {
195069
+ out.push({ tokens: tokens.slice(0, open2 + 1), line: whole2.line });
195070
+ if (open2 + 1 < tokens.length - 1) out.push({ tokens: tokens.slice(open2 + 1, -1), line: whole2.line });
195071
+ out.push({ tokens: [last], line: whole2.line });
195072
+ continue;
195073
+ }
195074
+ out.push({ tokens, line: whole2.line });
195075
+ }
195076
+ return out;
195077
+ }
195078
+ var MAX_STATEMENTS;
195079
+ var init_tokens4 = __esm({
195080
+ "../../packages/diagrams/src/importers/structurizr/tokens.ts"() {
195081
+ "use strict";
195082
+ MAX_STATEMENTS = 5e4;
195083
+ }
195084
+ });
195085
+
195086
+ // ../../packages/diagrams/src/importers/structurizr/dsl.ts
195087
+ function readDsl(text3) {
195088
+ const statements = statementsOf2(text3);
195089
+ const elements = [];
195090
+ const byKey = /* @__PURE__ */ new Map();
195091
+ const groups = [];
195092
+ const relationships = [];
195093
+ const views = [];
195094
+ const cylinderTags = [];
195095
+ const skipped = [];
195096
+ const constants = /* @__PURE__ */ new Map();
195097
+ const stack = [];
195098
+ let hierarchical = false;
195099
+ let name2 = null;
195100
+ let description = null;
195101
+ const skip = (what, at3, hint2) => {
195102
+ if (!skipped.some((entry2) => entry2.what === what)) skipped.push({ what, line: at3.line, column: at3.column, hint: hint2 });
195103
+ };
195104
+ const expand2 = (value) => value.includes("${") ? value.replace(/\$\{([A-Za-z0-9_-]{1,64})\}/g, (whole2, key) => constants.get(key) ?? whole2) : value;
195105
+ const currentElement = () => {
195106
+ for (let index2 = stack.length - 1; index2 >= 0; index2 -= 1) {
195107
+ const frame = stack[index2];
195108
+ if (frame?.type === "element") return frame.key;
195109
+ }
195110
+ return null;
195111
+ };
195112
+ const currentGroup = () => {
195113
+ for (let index2 = stack.length - 1; index2 >= 0; index2 -= 1) {
195114
+ const frame = stack[index2];
195115
+ if (frame?.type === "group") return frame.key;
195116
+ if (frame?.type === "element") return null;
195117
+ }
195118
+ return null;
195119
+ };
195120
+ const resolve5 = (reference, scope) => {
195121
+ if (reference === "this") return scope;
195122
+ const lower = reference.toLowerCase();
195123
+ if (hierarchical) {
195124
+ for (let at3 = scope; at3 !== null; at3 = byKey.get(at3.toLowerCase())?.parent ?? null) {
195125
+ const found = byKey.get(`${at3.toLowerCase()}.${lower}`);
195126
+ if (found !== void 0) return found.key;
195127
+ }
195128
+ }
195129
+ return byKey.get(lower)?.key ?? null;
195130
+ };
195131
+ const addElement = (statement, identifier, kind, args) => {
195132
+ const parent = currentElement();
195133
+ const parentDraft = parent === null ? void 0 : byKey.get(parent.toLowerCase());
195134
+ const label = args[0]?.text ?? kind;
195135
+ const named = parentDraft === void 0 ? label : `${parentDraft.key}/${label}`;
195136
+ const key = identifier === null ? named : hierarchical && parentDraft !== void 0 ? `${parentDraft.key}.${identifier}` : identifier;
195137
+ const hasTech = kind === "container" || kind === "component";
195138
+ const tags = tagsOf2(args.slice(hasTech ? 3 : 2));
195139
+ const draft = {
195140
+ key,
195141
+ kind,
195142
+ name: label,
195143
+ description: args[1]?.text === "" ? null : args[1]?.text ?? null,
195144
+ technology: hasTech && args[2] !== void 0 && args[2].text !== "" ? args[2].text : null,
195145
+ tags,
195146
+ parent: parentDraft?.key ?? null,
195147
+ group: currentGroup(),
195148
+ external: tags.some((tag) => tag.toLowerCase() === "external"),
195149
+ line: statement.line,
195150
+ column: statement.tokens[0]?.column ?? 1
195151
+ };
195152
+ if (!byKey.has(key.toLowerCase())) {
195153
+ elements.push(draft);
195154
+ byKey.set(key.toLowerCase(), draft);
195155
+ }
195156
+ return { type: "element", key: byKey.get(key.toLowerCase())?.key ?? key };
195157
+ };
195158
+ const readModelStatement = (statement, words2) => {
195159
+ const first = words2[0];
195160
+ if (first === void 0) return { type: "skip" };
195161
+ const keyword = first.text.toLowerCase();
195162
+ const scope = currentElement();
195163
+ if (!first.quoted && keyword === "!identifiers") {
195164
+ hierarchical = words2[1]?.text.toLowerCase() === "hierarchical";
195165
+ return { type: "skip" };
195166
+ }
195167
+ if (!first.quoted && (keyword === "!element" || keyword === "!ref")) {
195168
+ const key = resolve5(words2[1]?.text ?? "", scope);
195169
+ if (key === null) {
195170
+ skip(`!element ${words2[1]?.text ?? ""}`, { line: statement.line, column: first.column }, "The element it extends is not in the files sent; send the workspace that defines it.");
195171
+ return { type: "skip" };
195172
+ }
195173
+ return { type: "element", key };
195174
+ }
195175
+ const assigned = words2[1]?.text === "=" && !words2[1].quoted;
195176
+ const rest = assigned ? words2.slice(2) : words2;
195177
+ const arrow = rest.findIndex((token) => !token.quoted && token.text === "->");
195178
+ if (arrow === 0 || arrow === 1) {
195179
+ const from = arrow === 0 ? "this" : rest[0]?.text ?? "";
195180
+ const to = rest[arrow + 1];
195181
+ if (to === void 0 || arrow === 0 && scope === null) {
195182
+ skip("A relationship with no source", { line: statement.line, column: first.column }, "Write the relationship as source -> destination, or inside the block of its source.");
195183
+ return { type: "skip" };
195184
+ }
195185
+ const args = rest.slice(arrow + 2);
195186
+ relationships.push({ from, to: to.text, scope, description: args[0]?.text === "" ? null : args[0]?.text ?? null, technology: args[1]?.text === "" ? null : args[1]?.text ?? null, tags: tagsOf2(args.slice(2)), line: statement.line, column: first.column });
195187
+ return { type: "relationship", index: relationships.length - 1 };
195188
+ }
195189
+ const word2 = (rest[0]?.text ?? "").toLowerCase();
195190
+ const kind = rest[0]?.quoted === true ? void 0 : ELEMENT_WORDS[word2];
195191
+ if (kind !== void 0) return addElement(statement, assigned ? first.text : null, kind, rest.slice(1));
195192
+ if (word2 === "group" || word2 === "enterprise") {
195193
+ const label = rest[1]?.text ?? (word2 === "enterprise" ? "Enterprise" : "Group");
195194
+ const parent = currentGroup();
195195
+ const key = parent !== null ? `${parent}/${label}` : scope !== null ? `${scope}/${label}` : label;
195196
+ if (!groups.some((group2) => group2.key === key)) groups.push({ key, name: label, parent, enterprise: word2 === "enterprise", line: statement.line });
195197
+ return { type: "group", key };
195198
+ }
195199
+ if (DEPLOYMENT_WORDS.has(word2)) {
195200
+ skip("Deployment environments", { line: statement.line, column: first.column }, "The picture shows the system context, container, or component level; a deployment view is not drawn.");
195201
+ return { type: "skip" };
195202
+ }
195203
+ if (word2 === "element") {
195204
+ skip("Custom elements", { line: statement.line, column: first.column }, "Only people, software systems, containers, and components are drawn.");
195205
+ return { type: "skip" };
195206
+ }
195207
+ if (scope !== null && (word2 === "description" || word2 === "technology" || word2 === "tags" || word2 === "tag")) {
195208
+ const draft = byKey.get(scope.toLowerCase());
195209
+ const value = rest[1]?.text ?? "";
195210
+ if (draft !== void 0 && word2 === "description") draft.description = value === "" ? null : value;
195211
+ if (draft !== void 0 && word2 === "technology") draft.technology = value === "" ? null : value;
195212
+ if (draft !== void 0 && (word2 === "tags" || word2 === "tag")) {
195213
+ draft.tags = [...draft.tags, ...tagsOf2(rest.slice(1))];
195214
+ draft.external ||= draft.tags.some((tag) => tag.toLowerCase() === "external");
195215
+ }
195216
+ return { type: "skip" };
195217
+ }
195218
+ if (scope !== null && word2 === "location") {
195219
+ const draft = byKey.get(scope.toLowerCase());
195220
+ if (draft !== void 0 && rest[1]?.text.toLowerCase() === "external") draft.external = true;
195221
+ return { type: "skip" };
195222
+ }
195223
+ if (word2 === "!include") skip(`!include ${rest[1]?.text ?? ""}`, { line: statement.line, column: first.column }, "Included files are not fetched; send the workspace with the included text in place.");
195224
+ return { type: "skip" };
195225
+ };
195226
+ for (const statement of statements) {
195227
+ const tokens = statement.tokens.map((token) => ({ ...token, text: expand2(token.text) }));
195228
+ const first = tokens[0];
195229
+ if (first === void 0) continue;
195230
+ if (!first.quoted && first.text === "}") {
195231
+ stack.pop();
195232
+ continue;
195233
+ }
195234
+ const last = tokens[tokens.length - 1];
195235
+ const opens = last !== void 0 && !last.quoted && last.text === "{";
195236
+ const words2 = opens ? tokens.slice(0, -1) : tokens;
195237
+ const keyword = first.quoted ? "" : first.text.toLowerCase();
195238
+ const frame = stack[stack.length - 1];
195239
+ let next = { type: "skip" };
195240
+ if (keyword === "!const" || keyword === "!constant" || keyword === "!var") {
195241
+ const key = words2[1]?.text;
195242
+ if (key !== void 0) constants.set(key, words2[2]?.text ?? "");
195243
+ } else if (frame === void 0) {
195244
+ if (keyword === "workspace") {
195245
+ if (words2[1]?.text.toLowerCase() === "extends" && !words2[1].quoted) skip("workspace extends", { line: statement.line, column: first.column }, "The workspace it extends is not fetched; send the base workspace, or one that holds the whole model.");
195246
+ else {
195247
+ name2 = words2[1]?.text ?? null;
195248
+ description = words2[2]?.text ?? null;
195249
+ }
195250
+ next = { type: "workspace" };
195251
+ }
195252
+ } else if (frame.type === "workspace") {
195253
+ if (keyword === "model") next = { type: "model" };
195254
+ else if (keyword === "views") next = { type: "views" };
195255
+ else if (keyword === "name") name2 = words2[1]?.text ?? name2;
195256
+ else if (keyword === "description") description = words2[1]?.text ?? description;
195257
+ else if (keyword === "!identifiers") hierarchical = words2[1]?.text.toLowerCase() === "hierarchical";
195258
+ else if (keyword === "!include") skip(`!include ${words2[1]?.text ?? ""}`, { line: statement.line, column: first.column }, "Included files are not fetched; send the workspace with the included text in place.");
195259
+ } else if (frame.type === "model" || frame.type === "element" || frame.type === "group") {
195260
+ next = readModelStatement(statement, words2);
195261
+ } else if (frame.type === "relationship") {
195262
+ const relationship = relationships[frame.index];
195263
+ if (relationship !== void 0 && (keyword === "tags" || keyword === "tag")) relationship.tags.push(...tagsOf2(words2.slice(1)));
195264
+ if (relationship !== void 0 && keyword === "description") relationship.description = words2[1]?.text ?? relationship.description;
195265
+ if (relationship !== void 0 && keyword === "technology") relationship.technology = words2[1]?.text ?? relationship.technology;
195266
+ } else if (frame.type === "views") {
195267
+ const level2 = VIEW_WORDS2[keyword];
195268
+ if (level2 !== void 0 && words2[1] !== void 0) {
195269
+ views.push({ level: level2, scope: words2[1].text, title: null, direction: null, line: statement.line, column: words2[1].column });
195270
+ next = { type: "view", index: views.length - 1 };
195271
+ } else if (keyword === "styles") next = { type: "styles" };
195272
+ } else if (frame.type === "view") {
195273
+ const view = views[frame.index];
195274
+ if (view !== void 0 && keyword === "title") view.title = words2[1]?.text ?? null;
195275
+ if (view !== void 0 && keyword === "autolayout") view.direction = /^(?:lr|rl)$/i.test(words2[1]?.text ?? "") ? "right" : "down";
195276
+ } else if (frame.type === "styles") {
195277
+ if (keyword === "element" && words2[1] !== void 0) next = { type: "style", tag: words2[1].text };
195278
+ } else if (frame.type === "style") {
195279
+ if (keyword === "shape" && words2[1]?.text.toLowerCase() === "cylinder") cylinderTags.push(frame.tag);
195280
+ }
195281
+ if (opens) stack.push(next);
195282
+ }
195283
+ const unresolved = [];
195284
+ const resolved2 = [];
195285
+ for (const relationship of relationships) {
195286
+ const from = resolve5(relationship.from, relationship.scope);
195287
+ const to = resolve5(relationship.to, relationship.scope);
195288
+ for (const [written3, key] of [[relationship.from, from], [relationship.to, to]]) if (key === null) unresolved.push({ name: written3, line: relationship.line, column: relationship.column });
195289
+ if (from !== null && to !== null) resolved2.push({ from, to, description: relationship.description, technology: relationship.technology, tags: relationship.tags, line: relationship.line, column: relationship.column });
195290
+ }
195291
+ const modelViews = [];
195292
+ for (const view of views) {
195293
+ const scope = resolve5(view.scope, null);
195294
+ if (scope === null) unresolved.push({ name: view.scope, line: view.line, column: view.column });
195295
+ else modelViews.push({ level: view.level, scope, title: view.title, direction: view.direction, line: view.line });
195296
+ }
195297
+ return { workspace: { name: name2, description, elements, relationships: resolved2, groups, views: modelViews, cylinderTags, skipped }, unresolved };
195298
+ }
195299
+ var ELEMENT_WORDS, VIEW_WORDS2, DEPLOYMENT_WORDS, tagsOf2;
195300
+ var init_dsl = __esm({
195301
+ "../../packages/diagrams/src/importers/structurizr/dsl.ts"() {
195302
+ "use strict";
195303
+ init_tokens4();
195304
+ ELEMENT_WORDS = { person: "person", softwaresystem: "system", container: "container", component: "component" };
195305
+ VIEW_WORDS2 = { systemcontext: "context", container: "container", component: "component" };
195306
+ DEPLOYMENT_WORDS = /* @__PURE__ */ new Set(["deploymentenvironment", "deploymentnode", "infrastructurenode", "softwaresysteminstance", "containerinstance", "deploymentgroup"]);
195307
+ tagsOf2 = (tokens) => tokens.flatMap((token) => token.text.split(",")).map((tag) => tag.trim()).filter((tag) => tag !== "");
195308
+ }
195309
+ });
195310
+
195311
+ // ../../packages/diagrams/src/importers/structurizr/json.ts
195312
+ function isWorkspaceJson(value) {
195313
+ return isObject4(value) && isObject4(value["model"]) && (Array.isArray(value["model"]["softwareSystems"]) || Array.isArray(value["model"]["people"]));
195314
+ }
195315
+ function readWorkspaceJson(json2) {
195316
+ const model = isObject4(json2["model"]) ? json2["model"] : {};
195317
+ const elements = [];
195318
+ const keyOfId = /* @__PURE__ */ new Map();
195319
+ const groups = [];
195320
+ const rawRelationships = [];
195321
+ const add2 = (entry2, kind, parent) => {
195322
+ const name2 = textOf7(entry2["name"]) ?? kind;
195323
+ const properties = isObject4(entry2["properties"]) ? entry2["properties"] : {};
195324
+ const identifier = textOf7(properties["structurizr.dsl.identifier"]);
195325
+ const tags = tagsOf3(entry2["tags"]);
195326
+ const group2 = textOf7(entry2["group"]);
195327
+ if (group2 !== null && !groups.some((existing) => existing.key === group2)) groups.push({ key: group2, name: group2, parent: null, enterprise: false, line: 1 });
195328
+ const element = {
195329
+ key: identifier ?? (parent === null ? name2 : `${parent.key}/${name2}`),
195330
+ kind,
195331
+ name: name2,
195332
+ description: textOf7(entry2["description"]),
195333
+ technology: kind === "container" || kind === "component" ? textOf7(entry2["technology"]) : null,
195334
+ tags,
195335
+ parent: parent?.key ?? null,
195336
+ group: group2,
195337
+ external: textOf7(entry2["location"])?.toLowerCase() === "external" || tags.some((tag) => tag.toLowerCase() === "external"),
195338
+ line: 1,
195339
+ column: 1
195340
+ };
195341
+ elements.push(element);
195342
+ const id = textOf7(entry2["id"]);
195343
+ if (id !== null) keyOfId.set(id, element.key);
195344
+ rawRelationships.push(...listOf4(entry2["relationships"]));
195345
+ return element;
195346
+ };
195347
+ for (const person of listOf4(model["people"])) add2(person, "person", null);
195348
+ for (const system of listOf4(model["softwareSystems"])) {
195349
+ const parent = add2(system, "system", null);
195350
+ for (const container of listOf4(system["containers"])) {
195351
+ const holder = add2(container, "container", parent);
195352
+ for (const component of listOf4(container["components"])) add2(component, "component", holder);
195353
+ }
195354
+ }
195355
+ const relationships = [];
195356
+ for (const relationship of rawRelationships) {
195357
+ if (relationship["linkedRelationshipId"] !== void 0) continue;
195358
+ const from = keyOfId.get(textOf7(relationship["sourceId"]) ?? "");
195359
+ const to = keyOfId.get(textOf7(relationship["destinationId"]) ?? "");
195360
+ if (from === void 0 || to === void 0) continue;
195361
+ relationships.push({ from, to, description: textOf7(relationship["description"]), technology: textOf7(relationship["technology"]), tags: tagsOf3(relationship["tags"]), line: 1, column: 1 });
195362
+ }
195363
+ const viewsJson = isObject4(json2["views"]) ? json2["views"] : {};
195364
+ const views = [];
195365
+ const lists = [
195366
+ ["systemContextViews", "context", "softwareSystemId"],
195367
+ ["containerViews", "container", "softwareSystemId"],
195368
+ ["componentViews", "component", "containerId"]
195369
+ ];
195370
+ for (const [list, level2, field] of lists) {
195371
+ for (const view of listOf4(viewsJson[list])) {
195372
+ const scope = keyOfId.get(textOf7(view[field]) ?? "");
195373
+ const rank = isObject4(view["automaticLayout"]) ? textOf7(view["automaticLayout"]["rankDirection"]) : null;
195374
+ if (scope !== void 0) views.push({ level: level2, scope, title: textOf7(view["title"]), direction: rank === null ? null : /^(?:LeftRight|RightLeft)$/i.test(rank) ? "right" : "down", line: 1 });
195375
+ }
195376
+ }
195377
+ const configuration = isObject4(viewsJson["configuration"]) ? viewsJson["configuration"] : {};
195378
+ const styles = isObject4(configuration["styles"]) ? configuration["styles"] : {};
195379
+ const cylinderTags = listOf4(styles["elements"]).filter((style) => textOf7(style["shape"])?.toLowerCase() === "cylinder").map((style) => textOf7(style["tag"]) ?? "").filter((tag) => tag !== "");
195380
+ return { name: textOf7(json2["name"]), description: textOf7(json2["description"]), elements, relationships, groups, views, cylinderTags, skipped: [] };
195381
+ }
195382
+ var isObject4, listOf4, textOf7, DEFAULT_TAGS, tagsOf3;
195383
+ var init_json2 = __esm({
195384
+ "../../packages/diagrams/src/importers/structurizr/json.ts"() {
195385
+ "use strict";
195386
+ isObject4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
195387
+ listOf4 = (value) => Array.isArray(value) ? value.filter(isObject4) : [];
195388
+ textOf7 = (value) => typeof value === "string" && value.trim() !== "" ? value : typeof value === "number" ? String(value) : null;
195389
+ DEFAULT_TAGS = /* @__PURE__ */ new Set(["element", "person", "software system", "container", "component", "relationship"]);
195390
+ tagsOf3 = (value) => (textOf7(value) ?? "").split(",").map((tag) => tag.trim()).filter((tag) => tag !== "" && !DEFAULT_TAGS.has(tag.toLowerCase()));
195391
+ }
195392
+ });
195393
+
195394
+ // ../../packages/diagrams/src/importers/structurizr/view.ts
195395
+ function find(workspace, name2) {
195396
+ const lower = name2.toLowerCase();
195397
+ return workspace.elements.find((element) => element.key.toLowerCase() === lower) ?? workspace.elements.find((element) => element.name.toLowerCase() === lower);
195398
+ }
195399
+ function chooseView(workspace, level2, root) {
195400
+ const named = root === null ? null : find(workspace, root) ?? null;
195401
+ if (root !== null && named === null) return { view: null, missing: root };
195402
+ const systems = workspace.elements.filter((element) => element.kind === "system");
195403
+ const withChildren = (kind) => workspace.elements.find((element) => element.kind === kind && childrenOf(workspace, element.key).length > 0);
195404
+ const systemOf = (element) => {
195405
+ let at3 = element;
195406
+ for (let depth = 0; at3.parent !== null && depth < 3; depth += 1) at3 = workspace.elements.find((candidate2) => candidate2.key === at3.parent) ?? at3;
195407
+ return at3;
195408
+ };
195409
+ if (level2 === null && named === null) {
195410
+ const defined2 = workspace.views[0];
195411
+ const scope = defined2 === void 0 ? void 0 : workspace.elements.find((element) => element.key === defined2.scope);
195412
+ if (defined2 !== void 0 && scope !== void 0) return { view: { level: defined2.level, scope, title: defined2.title, direction: defined2.direction }, missing: null };
195413
+ const system2 = withChildren("system");
195414
+ if (system2 !== void 0) return { view: { level: "container", scope: system2, title: null, direction: null }, missing: null };
195415
+ const first = systems[0];
195416
+ return { view: first === void 0 ? null : { level: "context", scope: first, title: null, direction: null }, missing: null };
195417
+ }
195418
+ const wanted2 = level2 ?? (named?.kind === "container" || named?.kind === "component" ? "component" : named !== null && childrenOf(workspace, named.key).length > 0 ? "container" : "context");
195419
+ const defined = (scope) => workspace.views.find((view) => view.level === wanted2 && view.scope === scope.key);
195420
+ if (wanted2 === "component") {
195421
+ const container = named === null ? withChildren("container") : named.kind === "component" ? workspace.elements.find((element) => element.key === named.parent) : named.kind === "container" ? named : childrenOf(workspace, named.key).find((child) => childrenOf(workspace, child.key).length > 0) ?? childrenOf(workspace, named.key)[0];
195422
+ return { view: container === void 0 ? null : { level: "component", scope: container, title: defined(container)?.title ?? null, direction: defined(container)?.direction ?? null }, missing: null };
195423
+ }
195424
+ const system = named === null ? wanted2 === "container" ? withChildren("system") ?? systems[0] : withChildren("system") ?? systems[0] : named.kind === "person" ? void 0 : systemOf(named);
195425
+ return { view: system === void 0 ? null : { level: wanted2, scope: system, title: defined(system)?.title ?? null, direction: defined(system)?.direction ?? null }, missing: null };
195426
+ }
195427
+ function hiddenWords(workspace, element) {
195428
+ const containers = childrenOf(workspace, element.key);
195429
+ const components = containers.flatMap((child) => childrenOf(workspace, child.key));
195430
+ const parts = [
195431
+ containers.length === 0 ? null : `${containers.length} ${element.kind === "container" ? containers.length === 1 ? "component" : "components" : containers.length === 1 ? "container" : "containers"}`,
195432
+ components.length === 0 ? null : `${components.length} ${components.length === 1 ? "component" : "components"}`
195433
+ ].filter((part) => part !== null);
195434
+ return { count: containers.length + components.length, words: parts.join(" and ") };
195435
+ }
195436
+ function project(workspace, view) {
195437
+ const byKey = new Map(workspace.elements.map((element) => [element.key, element]));
195438
+ const ancestors = (element) => {
195439
+ const out = [];
195440
+ for (let at3 = element.parent === null ? void 0 : byKey.get(element.parent); at3 !== void 0 && out.length < 3; at3 = at3.parent === null ? void 0 : byKey.get(at3.parent)) out.push(at3);
195441
+ return out;
195442
+ };
195443
+ const within = (element, holder) => element.key === holder.key || ancestors(element).some((ancestor) => ancestor.key === holder.key);
195444
+ const top = (element) => ancestors(element).pop() ?? element;
195445
+ const scope = view.scope;
195446
+ const system = top(scope);
195447
+ const inner = view.level === "context" ? [scope] : childrenOf(workspace, scope.key);
195448
+ const innerKeys = new Set(inner.map((element) => element.key));
195449
+ const innerOf2 = (element) => [element, ...ancestors(element)].find((candidate2) => innerKeys.has(candidate2.key)) ?? null;
195450
+ const outerOf = (element) => {
195451
+ if (view.level === "component" && within(element, system) && !within(element, scope)) return [element, ...ancestors(element)].find((candidate2) => candidate2.kind === "container") ?? null;
195452
+ if (within(element, system)) return null;
195453
+ return top(element);
195454
+ };
195455
+ const shown = new Map(inner.map((element) => [element.key, element]));
195456
+ const lines = [];
195457
+ const seen = /* @__PURE__ */ new Set();
195458
+ for (const relationship of workspace.relationships) {
195459
+ const fromElement = byKey.get(relationship.from);
195460
+ const toElement = byKey.get(relationship.to);
195461
+ if (fromElement === void 0 || toElement === void 0) continue;
195462
+ const fromInner = innerOf2(fromElement);
195463
+ const toInner = innerOf2(toElement);
195464
+ if (fromInner === null && toInner === null) continue;
195465
+ const from = fromInner ?? outerOf(fromElement);
195466
+ const to = toInner ?? outerOf(toElement);
195467
+ if (from === null || to === null || from.key === to.key) continue;
195468
+ shown.set(from.key, from);
195469
+ shown.set(to.key, to);
195470
+ const pair2 = `${from.key}\0${to.key}`;
195471
+ if (seen.has(pair2)) continue;
195472
+ seen.add(pair2);
195473
+ lines.push({ from: from.key, to: to.key, relationship });
195474
+ }
195475
+ for (const relationship of workspace.relationships) {
195476
+ const fromElement = byKey.get(relationship.from);
195477
+ const toElement = byKey.get(relationship.to);
195478
+ if (fromElement === void 0 || toElement === void 0 || innerOf2(fromElement) !== null || innerOf2(toElement) !== null) continue;
195479
+ const from = outerOf(fromElement);
195480
+ const to = outerOf(toElement);
195481
+ if (from === null || to === null || from.key === to.key || !shown.has(from.key) || !shown.has(to.key)) continue;
195482
+ const pair2 = `${from.key}\0${to.key}`;
195483
+ if (seen.has(pair2)) continue;
195484
+ seen.add(pair2);
195485
+ lines.push({ from: from.key, to: to.key, relationship });
195486
+ }
195487
+ const boundaries = [];
195488
+ const groupBoundary = (groupKey, holder) => {
195489
+ const group2 = groupKey === null ? void 0 : workspace.groups.find((entry2) => entry2.key === groupKey);
195490
+ if (group2 === void 0) return holder;
195491
+ const parent = groupBoundary(group2.parent, holder);
195492
+ const key = `group:${group2.key}`;
195493
+ if (!boundaries.some((boundary) => boundary.key === key)) boundaries.push({ key, name: group2.name, kind: group2.enterprise ? "enterprise" : "group", parent, tech: null, element: null });
195494
+ return key;
195495
+ };
195496
+ let scopeBoundary = null;
195497
+ if (view.level === "component") {
195498
+ boundaries.push({ key: system.key, name: system.name, kind: "system", parent: groupBoundary(system.group, null), tech: null, element: system });
195499
+ boundaries.push({ key: scope.key, name: scope.name, kind: "container", parent: system.key, tech: scope.technology, element: scope });
195500
+ scopeBoundary = scope.key;
195501
+ } else if (view.level === "container") {
195502
+ boundaries.push({ key: scope.key, name: scope.name, kind: "system", parent: groupBoundary(scope.group, null), tech: null, element: scope });
195503
+ scopeBoundary = scope.key;
195504
+ }
195505
+ const enterprise = workspace.groups.some((group2) => group2.enterprise);
195506
+ const inEnterprise = (element) => {
195507
+ let group2 = workspace.groups.find((entry2) => entry2.key === top(element).group);
195508
+ for (let depth = 0; group2 !== void 0 && depth < workspace.groups.length; depth += 1) {
195509
+ if (group2.enterprise) return true;
195510
+ group2 = workspace.groups.find((entry2) => entry2.key === group2?.parent);
195511
+ }
195512
+ return false;
195513
+ };
195514
+ const order = (element) => innerKeys.has(element.key) ? 1 : element.kind === "person" ? 0 : 2;
195515
+ const placed = [...shown.values()].sort((a, b) => order(a) - order(b) || workspace.elements.indexOf(a) - workspace.elements.indexOf(b)).map((element) => {
195516
+ const holder = innerKeys.has(element.key) && view.level !== "context" ? scopeBoundary : view.level === "component" && within(element, system) ? system.key : null;
195517
+ const hidden = hiddenWords(workspace, element);
195518
+ return { element, boundary: groupBoundary(element.group, holder), external: element.external || element.kind === "system" && element.key !== system.key && (enterprise ? !inEnterprise(element) : true), hidden: hidden.count, hiddenWords: hidden.words };
195519
+ });
195520
+ const depthOf7 = (key) => {
195521
+ let depth = 0;
195522
+ for (let at3 = key; at3 !== null && depth <= boundaries.length; depth += 1) at3 = boundaries.find((boundary) => boundary.key === at3)?.parent ?? null;
195523
+ return depth;
195524
+ };
195525
+ const kept2 = (key) => {
195526
+ let at3 = key;
195527
+ while (at3 !== null && depthOf7(at3) > MAX_DEPTH16) at3 = boundaries.find((boundary) => boundary.key === at3)?.parent ?? null;
195528
+ return at3;
195529
+ };
195530
+ const elements = placed.map((entry2) => ({ ...entry2, boundary: kept2(entry2.boundary) }));
195531
+ const used = new Set(elements.map((entry2) => entry2.boundary));
195532
+ for (let changed = true, round2 = 0; changed && round2 <= boundaries.length; round2 += 1) {
195533
+ changed = false;
195534
+ for (const boundary of boundaries) if (used.has(boundary.key) && boundary.parent !== null && !used.has(boundary.parent)) {
195535
+ used.add(boundary.parent);
195536
+ changed = true;
195537
+ }
195538
+ }
195539
+ const shownBoundaries = boundaries.filter((boundary) => depthOf7(boundary.key) <= MAX_DEPTH16 && (boundary.element !== null || used.has(boundary.key)));
195540
+ const drawn = /* @__PURE__ */ new Set([...elements.map((entry2) => entry2.element.key), ...shownBoundaries.flatMap((boundary) => boundary.element === null ? [] : [boundary.element.key])]);
195541
+ const summarisedBy = (element) => ancestors(element).some((ancestor) => shown.has(ancestor.key));
195542
+ const summarised = workspace.elements.filter((element) => !drawn.has(element.key) && summarisedBy(element)).length;
195543
+ const omitted = workspace.elements.filter((element) => !drawn.has(element.key) && !summarisedBy(element));
195544
+ return { elements, boundaries: shownBoundaries, relationships: lines, summarised, omitted };
195545
+ }
195546
+ var MAX_DEPTH16, childrenOf;
195547
+ var init_view = __esm({
195548
+ "../../packages/diagrams/src/importers/structurizr/view.ts"() {
195549
+ "use strict";
195550
+ MAX_DEPTH16 = 4;
195551
+ childrenOf = (workspace, key) => workspace.elements.filter((element) => element.parent === key);
195552
+ }
195553
+ });
195554
+
195555
+ // ../../packages/diagrams/src/importers/structurizr/index.ts
195556
+ function isDatabase(element, workspace) {
195557
+ if (element.kind !== "container" && element.kind !== "component") return false;
195558
+ const tags = element.tags.map((tag) => tag.toLowerCase());
195559
+ return tags.includes("database") || workspace.cylinderTags.some((tag) => tags.includes(tag.toLowerCase())) || element.technology !== null && DATABASE_WORDS.test(element.technology);
195560
+ }
195561
+ function readWorkspace(text3, context) {
195562
+ if (/^\s*\{/.test(text3)) {
195563
+ let json2;
195564
+ try {
195565
+ json2 = JSON.parse(text3);
195566
+ } catch (error62) {
195567
+ context.report.add(DIAGNOSTIC_CODES.importUnreadable, START, `The text is not JSON: ${error62 instanceof Error ? error62.message : "it cannot be read"}.`, "Send the workspace as Structurizr exports it (workspace.json), or its DSL (workspace.dsl).");
195568
+ return null;
195569
+ }
195570
+ if (!isWorkspaceJson(json2)) {
195571
+ context.report.add(DIAGNOSTIC_CODES.importNoShape, START, "The JSON has no model of people or software systems, so it is not a Structurizr workspace.", "Send workspace.json as Structurizr exports it, or the workspace DSL.");
195572
+ return null;
195573
+ }
195574
+ return { workspace: readWorkspaceJson(json2), unresolved: [] };
195575
+ }
195576
+ return readDsl(text3);
195577
+ }
195578
+ function writeC4(workspace, view, shown, title, desc) {
195579
+ const ids = new IdAllocator();
195580
+ const hint2 = (element) => element.key.includes("/") ? element.name : element.key.split(".").pop() ?? element.name;
195581
+ for (const boundary of shown.boundaries) if (boundary.element !== null) ids.idFor(`b:${boundary.key}`, hint2(boundary.element));
195582
+ for (const entry2 of shown.elements) ids.idFor(`e:${entry2.element.key}`, hint2(entry2.element));
195583
+ for (const boundary of shown.boundaries) if (boundary.element === null) ids.idFor(`b:${boundary.key}`, boundary.name.toLowerCase());
195584
+ const lines = new SourceLines();
195585
+ lines.add(`c4 ${quote(title)}${options2({ view: view.level, direction: view.direction, desc })}`);
195586
+ const elementLine2 = (entry2, depth) => {
195587
+ const { element } = entry2;
195588
+ const type = isDatabase(element, workspace) ? "db" : element.kind;
195589
+ const text3 = [element.description === null ? null : cleanText(element.description), entry2.hidden === 0 ? null : `Holds ${entry2.hiddenWords}.`].filter((part) => part !== null).join(" ");
195590
+ lines.add(`${type} ${ids.idFor(`e:${element.key}`)} ${quote(cleanText(element.name))}${options2({ tech: element.technology === null ? null : cleanText(element.technology), desc: text3, external: entry2.external ? "on" : null }, ["tech", "desc"])}`, depth);
195591
+ };
195592
+ const writeBoundary = (boundary, depth) => {
195593
+ lines.gap();
195594
+ lines.add(`boundary ${ids.idFor(`b:${boundary.key}`)} ${quote(cleanText(boundary.name))}${options2({ kind: boundary.kind, tech: boundary.tech === null ? null : cleanText(boundary.tech) }, ["tech"])} {`, depth);
195595
+ for (const entry2 of shown.elements) if (entry2.boundary === boundary.key) elementLine2(entry2, depth + 1);
195596
+ for (const child of shown.boundaries) if (child.parent === boundary.key) writeBoundary(child, depth + 1);
195597
+ lines.add("}", depth);
195598
+ };
195599
+ lines.gap();
195600
+ const people = shown.elements.filter((entry2) => entry2.boundary === null && entry2.element.kind === "person");
195601
+ for (const entry2 of people) elementLine2(entry2, 0);
195602
+ for (const boundary of shown.boundaries) if (boundary.parent === null) writeBoundary(boundary, 0);
195603
+ lines.gap();
195604
+ for (const entry2 of shown.elements) if (entry2.boundary === null && entry2.element.kind !== "person") elementLine2(entry2, 0);
195605
+ lines.gap();
195606
+ const kindOf3 = new Map(shown.elements.map((entry2) => [entry2.element.key, entry2.element.kind]));
195607
+ const ordered = [...shown.relationships].sort((a, b) => Number(kindOf3.get(a.from) !== "person") - Number(kindOf3.get(b.from) !== "person"));
195608
+ for (const line3 of ordered) {
195609
+ const { relationship } = line3;
195610
+ const async = relationship.tags.some((tag) => /^async(?:hronous)?$/i.test(tag));
195611
+ const label = relationship.description === null ? "" : ` : ${quote(cleanText(relationship.description))}${options2({ tech: relationship.technology === null ? null : cleanText(relationship.technology) }, ["tech"])}`;
195612
+ lines.add(`${ids.idFor(`e:${line3.from}`)} ${async ? "-->" : "->"} ${ids.idFor(`e:${line3.to}`)}${label}`);
195613
+ }
195614
+ return { source: lines.toString(), ids: { ...ids.mapped("b:"), ...ids.mapped("e:") }, links: shown.relationships.length };
195615
+ }
195616
+ function capped(shown, context) {
195617
+ const elements = shown.elements.slice(0, C4_BUDGET.maxElements);
195618
+ const keys = new Set(elements.map((entry2) => entry2.element.key));
195619
+ const relationships = shown.relationships.filter((line3) => keys.has(line3.from) && keys.has(line3.to)).slice(0, C4_BUDGET.maxRelationships);
195620
+ const leftElements = shown.elements.length - elements.length;
195621
+ const leftLines = shown.relationships.length - relationships.length;
195622
+ if (leftElements + leftLines > 0) {
195623
+ const first = shown.elements[C4_BUDGET.maxElements]?.element;
195624
+ context.report.add(
195625
+ DIAGNOSTIC_CODES.importDropped,
195626
+ first === void 0 ? START : spanAt3(first.line, first.column),
195627
+ `${[leftElements === 0 ? null : countOf2(leftElements, "element"), leftLines === 0 ? null : countOf2(leftLines, "relationship")].filter((part) => part !== null).join(" and ")} past what one C4 picture holds ${leftElements + leftLines === 1 ? "was" : "were"} left out.`,
195628
+ "Draw a smaller view: one container with options.view component, or one system with options.root."
195629
+ );
195630
+ }
195631
+ return { ...shown, elements, relationships, omitted: [...shown.omitted, ...shown.elements.slice(C4_BUDGET.maxElements).map((entry2) => entry2.element)] };
195632
+ }
195633
+ function readStructurizr(text3, context) {
195634
+ const read = readWorkspace(text3, context);
195635
+ if (read === null) return null;
195636
+ const { workspace, unresolved } = read;
195637
+ if (workspace.elements.length === 0) {
195638
+ context.report.add(DIAGNOSTIC_CODES.importNoShape, START, "The workspace has no people, software systems, containers, or components.", 'Send a workspace with a model block, such as workspace { model { user = person "User" } }.');
195639
+ return null;
195640
+ }
195641
+ for (const skipped of workspace.skipped) context.report.add(DIAGNOSTIC_CODES.importSkipped, spanAt3(skipped.line, skipped.column), `${cleanText(skipped.what)} ${skipped.what.startsWith("!") || skipped.what.startsWith("workspace") ? "is" : "are"} not drawn.`, skipped.hint);
195642
+ const firstUnresolved = unresolved[0];
195643
+ if (firstUnresolved !== void 0) {
195644
+ context.report.add(DIAGNOSTIC_CODES.importUnresolved, spanAt3(firstUnresolved.line, firstUnresolved.column), `${countOf2(unresolved.length, "reference")} name${unresolved.length === 1 ? "s" : ""} no element of the model: ${[...new Set(unresolved.map((entry2) => entry2.name))].slice(0, 3).map((name2) => cleanText(name2)).join(", ")}.`, "Check the identifier; with !identifiers hierarchical, an element inside another is named by its path, such as shop.api.");
195645
+ }
195646
+ const requested = context.options.view;
195647
+ const level2 = requested !== void 0 && LEVELS.includes(requested) ? requested : null;
195648
+ const chosen = chooseView(workspace, level2, context.options.root ?? null);
195649
+ if (chosen.missing !== null) {
195650
+ context.report.add(DIAGNOSTIC_CODES.importNotFound, START, `No element of the workspace is named ${cleanText(chosen.missing)}.`, `Set options.root to the identifier or name of a software system or container, such as ${workspace.elements.find((element) => element.kind === "system")?.key ?? "shop"}.`);
195651
+ return null;
195652
+ }
195653
+ if (chosen.view === null) {
195654
+ context.report.add(DIAGNOSTIC_CODES.importNoShape, START, level2 === "component" ? "No container of the workspace has components." : "The workspace has no software system to draw a view of.", "Add a softwareSystem to the model, or choose another level with options.view.");
195655
+ return null;
195656
+ }
195657
+ const view = chosen.view;
195658
+ const shown = capped(project(workspace, view), context);
195659
+ const omitted = shown.omitted;
195660
+ const firstOmitted = omitted[0];
195661
+ if (firstOmitted !== void 0) {
195662
+ context.report.add(
195663
+ DIAGNOSTIC_CODES.importSkipped,
195664
+ spanAt3(firstOmitted.line, firstOmitted.column),
195665
+ `${countOf2(omitted.length, "element")} ${omitted.length === 1 ? "is" : "are"} not in the ${LEVEL_WORDS[view.level].title} view of ${cleanText(view.scope.name)}: ${omitted.slice(0, 3).map((element) => cleanText(element.key)).join(", ")}.`,
195666
+ "An element is drawn when a relationship joins it to what the view is about. Choose another view with options.view (context, container, or component) and options.root."
195667
+ );
195668
+ }
195669
+ const scopeName = cleanText(view.scope.name);
195670
+ const title = context.title ?? (view.title === null ? `${scopeName}: ${LEVEL_WORDS[view.level].title}` : cleanText(view.title));
195671
+ const what = view.level === "context" ? `${scopeName} ${LEVEL_WORDS.context.sentence}` : `${LEVEL_WORDS[view.level].sentence} ${scopeName} and what they talk to`;
195672
+ const desc = `${what.charAt(0).toUpperCase()}${what.slice(1)}, imported from the Structurizr workspace${workspace.name === null ? "" : ` ${cleanText(workspace.name)}`}.`;
195673
+ const written3 = writeC4(workspace, view, shown, title, desc);
195674
+ const drawn = shown.elements.length + shown.boundaries.filter((boundary) => boundary.element !== null).length;
195675
+ const others = workspace.views.length > 1 ? ` The workspace defines ${countOf2(workspace.views.length, "view")}; draw another with options.view and options.root.` : "";
195676
+ return {
195677
+ kind: "c4",
195678
+ source: written3.source,
195679
+ stats: { items: shown.elements.length, links: written3.links, groups: shown.boundaries.length, dropped: omitted.length },
195680
+ advice: `Check that each element has a description and each relationship a technology, so the cards and lines say what they do.${others}`,
195681
+ coverage: { noun: "elements", total: workspace.elements.length, drawn, summarised: shown.summarised },
195682
+ ids: written3.ids
195683
+ };
195684
+ }
195685
+ var DATABASE_WORDS, LEVELS, LEVEL_WORDS, structurizrImporter;
195686
+ var init_structurizr = __esm({
195687
+ "../../packages/diagrams/src/importers/structurizr/index.ts"() {
195688
+ "use strict";
195689
+ init_core();
195690
+ init_limits();
195691
+ init_shared2();
195692
+ init_dsl();
195693
+ init_json2();
195694
+ init_view();
195695
+ DATABASE_WORDS = /\b(?:database|postgres(?:ql)?|mysql|mariadb|oracle|sql server|sqlite|mongodb|dynamodb|cassandra|cosmos ?db|couchdb|neo4j|elasticsearch|opensearch|clickhouse|snowflake|bigquery|redshift)\b/i;
195696
+ LEVELS = ["context", "container", "component"];
195697
+ LEVEL_WORDS = {
195698
+ context: { title: "system context", sentence: "and the people and systems around it" },
195699
+ container: { title: "containers", sentence: "the containers of" },
195700
+ component: { title: "components", sentence: "the components of" }
195701
+ };
195702
+ structurizrImporter = { format: "structurizr", kinds: ["c4"], joins: null, extensions: [".dsl", ".json"], read: readStructurizr };
195703
+ }
195704
+ });
195705
+
194247
195706
  // ../../packages/diagrams/src/importers/terraform-plan/document.ts
194248
195707
  function moduleOfAddress(address, type, mode) {
194249
195708
  const own2 = `${mode === "data" ? "data." : ""}${type}.`;
@@ -194251,7 +195710,7 @@ function moduleOfAddress(address, type, mode) {
194251
195710
  return at3 <= 0 ? "" : address.slice(0, at3 - 1);
194252
195711
  }
194253
195712
  function resourceOf3(raw, module) {
194254
- if (!isObject4(raw) || typeof raw["address"] !== "string" || typeof raw["type"] !== "string" || typeof raw["name"] !== "string") return null;
195713
+ if (!isObject5(raw) || typeof raw["address"] !== "string" || typeof raw["type"] !== "string" || typeof raw["name"] !== "string") return null;
194255
195714
  const mode = raw["mode"] === "data" ? "data" : "managed";
194256
195715
  const index2 = typeof raw["index"] === "string" || typeof raw["index"] === "number" ? raw["index"] : null;
194257
195716
  return {
@@ -194261,13 +195720,13 @@ function resourceOf3(raw, module) {
194261
195720
  name: raw["name"],
194262
195721
  index: index2,
194263
195722
  module: module === "" ? moduleOfAddress(raw["address"], raw["type"], mode) : module,
194264
- values: isObject4(raw["values"]) ? raw["values"] : {},
194265
- sensitive: isObject4(raw["sensitive_values"]) ? raw["sensitive_values"] : {},
195723
+ values: isObject5(raw["values"]) ? raw["values"] : {},
195724
+ sensitive: isObject5(raw["sensitive_values"]) ? raw["sensitive_values"] : {},
194266
195725
  dependsOn: strings2(raw["depends_on"])
194267
195726
  };
194268
195727
  }
194269
195728
  function moduleResources(raw, depth = 0) {
194270
- if (!isObject4(raw) || depth > MAX_MODULE_DEPTH2) return [];
195729
+ if (!isObject5(raw) || depth > MAX_MODULE_DEPTH2) return [];
194271
195730
  const address = typeof raw["address"] === "string" ? raw["address"] : "";
194272
195731
  const own2 = (Array.isArray(raw["resources"]) ? raw["resources"] : []).map((entry2) => resourceOf3(entry2, address)).filter((entry2) => entry2 !== null);
194273
195732
  const children = Array.isArray(raw["child_modules"]) ? raw["child_modules"].flatMap((child) => moduleResources(child, depth + 1)) : [];
@@ -194275,9 +195734,9 @@ function moduleResources(raw, depth = 0) {
194275
195734
  }
194276
195735
  function variablesOf(raw, sensitive) {
194277
195736
  const out = /* @__PURE__ */ new Map();
194278
- if (!isObject4(raw)) return out;
195737
+ if (!isObject5(raw)) return out;
194279
195738
  for (const [name2, entry2] of Object.entries(raw)) {
194280
- if (sensitive.has(name2) || !isObject4(entry2)) continue;
195739
+ if (sensitive.has(name2) || !isObject5(entry2)) continue;
194281
195740
  const value = entry2["value"];
194282
195741
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") out.set(name2, String(value));
194283
195742
  }
@@ -194286,28 +195745,28 @@ function variablesOf(raw, sensitive) {
194286
195745
  function sensitiveVariables(configuration) {
194287
195746
  const out = /* @__PURE__ */ new Set();
194288
195747
  const root = configuration === null ? null : configuration["root_module"];
194289
- const variables = isObject4(root) && isObject4(root["variables"]) ? root["variables"] : {};
194290
- for (const [name2, entry2] of Object.entries(variables)) if (isObject4(entry2) && entry2["sensitive"] === true) out.add(name2);
195748
+ const variables = isObject5(root) && isObject5(root["variables"]) ? root["variables"] : {};
195749
+ for (const [name2, entry2] of Object.entries(variables)) if (isObject5(entry2) && entry2["sensitive"] === true) out.add(name2);
194291
195750
  return out;
194292
195751
  }
194293
195752
  function changesOf(raw) {
194294
195753
  const out = /* @__PURE__ */ new Map();
194295
195754
  if (!Array.isArray(raw)) return out;
194296
195755
  for (const entry2 of raw) {
194297
- if (!isObject4(entry2) || typeof entry2["address"] !== "string" || !isObject4(entry2["change"])) continue;
195756
+ if (!isObject5(entry2) || typeof entry2["address"] !== "string" || !isObject5(entry2["change"])) continue;
194298
195757
  const change = entry2["change"];
194299
- out.set(entry2["address"], { actions: strings2(change["actions"]), previous: typeof entry2["previous_address"] === "string" ? entry2["previous_address"] : null, before: isObject4(change["before"]) ? change["before"] : null });
195758
+ out.set(entry2["address"], { actions: strings2(change["actions"]), previous: typeof entry2["previous_address"] === "string" ? entry2["previous_address"] : null, before: isObject5(change["before"]) ? change["before"] : null });
194300
195759
  }
194301
195760
  return out;
194302
195761
  }
194303
195762
  function readPlanDocument(json2) {
194304
- if (!isObject4(json2)) return null;
194305
- const configuration = isObject4(json2["configuration"]) ? json2["configuration"] : null;
194306
- const providers = configuration !== null && isObject4(configuration["provider_config"]) ? configuration["provider_config"] : {};
195763
+ if (!isObject5(json2)) return null;
195764
+ const configuration = isObject5(json2["configuration"]) ? json2["configuration"] : null;
195765
+ const providers = configuration !== null && isObject5(configuration["provider_config"]) ? configuration["provider_config"] : {};
194307
195766
  const variables = variablesOf(json2["variables"], sensitiveVariables(configuration));
194308
- if (isObject4(json2["planned_values"]) || Array.isArray(json2["resource_changes"])) {
194309
- const planned = isObject4(json2["planned_values"]) ? moduleResources(json2["planned_values"]["root_module"]) : [];
194310
- const prior = isObject4(json2["prior_state"]) && isObject4(json2["prior_state"]["values"]) ? moduleResources(json2["prior_state"]["values"]["root_module"]) : [];
195767
+ if (isObject5(json2["planned_values"]) || Array.isArray(json2["resource_changes"])) {
195768
+ const planned = isObject5(json2["planned_values"]) ? moduleResources(json2["planned_values"]["root_module"]) : [];
195769
+ const prior = isObject5(json2["prior_state"]) && isObject5(json2["prior_state"]["values"]) ? moduleResources(json2["prior_state"]["values"]["root_module"]) : [];
194311
195770
  const changes = changesOf(json2["resource_changes"]);
194312
195771
  const kept2 = new Set(planned.map((resource) => resource.address));
194313
195772
  const data = prior.filter((resource) => resource.mode === "data" && !kept2.has(resource.address));
@@ -194320,11 +195779,11 @@ function readPlanDocument(json2) {
194320
195779
  }
194321
195780
  const drift = /* @__PURE__ */ new Set();
194322
195781
  if (Array.isArray(json2["resource_drift"])) {
194323
- for (const entry2 of json2["resource_drift"]) if (isObject4(entry2) && typeof entry2["address"] === "string") drift.add(entry2["address"]);
195782
+ for (const entry2 of json2["resource_drift"]) if (isObject5(entry2) && typeof entry2["address"] === "string") drift.add(entry2["address"]);
194324
195783
  }
194325
195784
  return { kind: "plan", resources: [...planned, ...data], destroyed, changes, drift, configuration, providers, variables };
194326
195785
  }
194327
- if (isObject4(json2["values"]) && isObject4(json2["values"]["root_module"])) {
195786
+ if (isObject5(json2["values"]) && isObject5(json2["values"]["root_module"])) {
194328
195787
  return { kind: "state", resources: moduleResources(json2["values"]["root_module"]), destroyed: [], changes: /* @__PURE__ */ new Map(), drift: /* @__PURE__ */ new Set(), configuration, providers, variables };
194329
195788
  }
194330
195789
  if (Array.isArray(json2["resources"]) && typeof json2["version"] === "number") return { kind: "state", resources: rawStateResources(json2["resources"]), destroyed: [], changes: /* @__PURE__ */ new Map(), drift: /* @__PURE__ */ new Set(), configuration: null, providers: {}, variables: /* @__PURE__ */ new Map() };
@@ -194333,12 +195792,12 @@ function readPlanDocument(json2) {
194333
195792
  function rawStateResources(raw) {
194334
195793
  const out = [];
194335
195794
  for (const block of raw) {
194336
- if (!isObject4(block) || typeof block["type"] !== "string" || typeof block["name"] !== "string" || !Array.isArray(block["instances"])) continue;
195795
+ if (!isObject5(block) || typeof block["type"] !== "string" || typeof block["name"] !== "string" || !Array.isArray(block["instances"])) continue;
194337
195796
  const module = typeof block["module"] === "string" ? block["module"] : "";
194338
195797
  const mode = block["mode"] === "data" ? "data" : "managed";
194339
195798
  const base = `${module === "" ? "" : `${module}.`}${mode === "data" ? "data." : ""}${block["type"]}.${block["name"]}`;
194340
195799
  for (const instance of block["instances"]) {
194341
- if (!isObject4(instance)) continue;
195800
+ if (!isObject5(instance)) continue;
194342
195801
  const key = instance["index_key"];
194343
195802
  const index2 = typeof key === "string" || typeof key === "number" ? key : null;
194344
195803
  const address = `${base}${index2 === null ? "" : typeof index2 === "number" ? `[${index2}]` : `[${JSON.stringify(index2)}]`}`;
@@ -194346,20 +195805,20 @@ function rawStateResources(raw) {
194346
195805
  if (Array.isArray(instance["sensitive_attributes"])) {
194347
195806
  for (const path of instance["sensitive_attributes"]) {
194348
195807
  const first = Array.isArray(path) ? path[0] : null;
194349
- if (isObject4(first) && typeof first["value"] === "string") sensitive[first["value"]] = true;
195808
+ if (isObject5(first) && typeof first["value"] === "string") sensitive[first["value"]] = true;
194350
195809
  }
194351
195810
  }
194352
- out.push({ address, mode, type: block["type"], name: block["name"], index: index2, module, values: isObject4(instance["attributes"]) ? instance["attributes"] : {}, sensitive, dependsOn: strings2(instance["dependencies"]) });
195811
+ out.push({ address, mode, type: block["type"], name: block["name"], index: index2, module, values: isObject5(instance["attributes"]) ? instance["attributes"] : {}, sensitive, dependsOn: strings2(instance["dependencies"]) });
194353
195812
  }
194354
195813
  }
194355
195814
  return out;
194356
195815
  }
194357
- var MAX_MODULE_DEPTH2, isObject4, strings2, destroys;
194358
- var init_document3 = __esm({
195816
+ var MAX_MODULE_DEPTH2, isObject5, strings2, destroys;
195817
+ var init_document4 = __esm({
194359
195818
  "../../packages/diagrams/src/importers/terraform-plan/document.ts"() {
194360
195819
  "use strict";
194361
195820
  MAX_MODULE_DEPTH2 = 16;
194362
- isObject4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
195821
+ isObject5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
194363
195822
  strings2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
194364
195823
  destroys = (change) => change !== void 0 && change.actions.length === 1 && change.actions[0] === "delete";
194365
195824
  }
@@ -194367,14 +195826,14 @@ var init_document3 = __esm({
194367
195826
 
194368
195827
  // ../../packages/diagrams/src/importers/terraform-plan/references.ts
194369
195828
  function attributesOf3(expressions, depth = 0) {
194370
- if (!isObject4(expressions) || depth > MAX_NESTING) return [];
195829
+ if (!isObject5(expressions) || depth > MAX_NESTING) return [];
194371
195830
  const out = [];
194372
195831
  for (const [name2, value] of Object.entries(expressions)) {
194373
- if (isObject4(value) && ("references" in value || "constant_value" in value)) {
195832
+ if (isObject5(value) && ("references" in value || "constant_value" in value)) {
194374
195833
  const refs = strings3(value["references"]);
194375
195834
  out.push({ name: name2, refs: refs.filter((ref) => !SAME_INSTANCE.has(ref)), paired: refs.some((ref) => SAME_INSTANCE.has(ref)) });
194376
195835
  } else if (Array.isArray(value)) for (const block of value) out.push(...attributesOf3(block, depth + 1));
194377
- else if (isObject4(value)) out.push(...attributesOf3(value, depth + 1));
195836
+ else if (isObject5(value)) out.push(...attributesOf3(value, depth + 1));
194378
195837
  }
194379
195838
  return out;
194380
195839
  }
@@ -194399,13 +195858,13 @@ function parentOf3(module) {
194399
195858
  const at3 = module.lastIndexOf(".module.");
194400
195859
  return at3 === -1 ? "" : module.slice(0, at3);
194401
195860
  }
194402
- var MAX_DEPTH15, MAX_NESTING, TYPE2, SAME_INSTANCE, strings3, Configuration;
195861
+ var MAX_DEPTH17, MAX_NESTING, TYPE2, SAME_INSTANCE, strings3, Configuration;
194403
195862
  var init_references2 = __esm({
194404
195863
  "../../packages/diagrams/src/importers/terraform-plan/references.ts"() {
194405
195864
  "use strict";
194406
195865
  init_address();
194407
- init_document3();
194408
- MAX_DEPTH15 = 8;
195866
+ init_document4();
195867
+ MAX_DEPTH17 = 8;
194409
195868
  MAX_NESTING = 8;
194410
195869
  TYPE2 = /^[a-z][a-z0-9]*_[a-z0-9_]+$/;
194411
195870
  SAME_INSTANCE = /* @__PURE__ */ new Set(["each.key", "each.value", "count.index"]);
@@ -194421,11 +195880,11 @@ var init_references2 = __esm({
194421
195880
  moduleAt(address) {
194422
195881
  let module = this.root;
194423
195882
  for (const call of callsOf2(address)) {
194424
- const calls = isObject4(module) && isObject4(module["module_calls"]) ? module["module_calls"] : null;
195883
+ const calls = isObject5(module) && isObject5(module["module_calls"]) ? module["module_calls"] : null;
194425
195884
  const entry2 = calls === null ? null : calls[call.name];
194426
- module = isObject4(entry2) ? entry2["module"] : null;
195885
+ module = isObject5(entry2) ? entry2["module"] : null;
194427
195886
  }
194428
- return isObject4(module) ? module : null;
195887
+ return isObject5(module) ? module : null;
194429
195888
  }
194430
195889
  /** The call of a module instance, as its parent's configuration writes it: its source, version, and the values it passes. */
194431
195890
  callAt(address) {
@@ -194433,20 +195892,20 @@ var init_references2 = __esm({
194433
195892
  const last = calls[calls.length - 1];
194434
195893
  if (last === void 0) return null;
194435
195894
  const parent = this.moduleAt(parentOf3(address));
194436
- const entry2 = parent !== null && isObject4(parent["module_calls"]) ? parent["module_calls"][last.name] : null;
194437
- return isObject4(entry2) ? entry2 : null;
195895
+ const entry2 = parent !== null && isObject5(parent["module_calls"]) ? parent["module_calls"][last.name] : null;
195896
+ return isObject5(entry2) ? entry2 : null;
194438
195897
  }
194439
195898
  /** The configured block of a resource, by the module instance it is in and its address inside the module. */
194440
195899
  resourceAt(module, local2) {
194441
195900
  const config2 = this.moduleAt(module);
194442
195901
  const list = config2 !== null && Array.isArray(config2["resources"]) ? config2["resources"] : [];
194443
- const found = list.find((entry2) => isObject4(entry2) && entry2["address"] === local2);
195902
+ const found = list.find((entry2) => isObject5(entry2) && entry2["address"] === local2);
194444
195903
  if (found === void 0) return null;
194445
195904
  return { attributes: attributesOf3(found["expressions"]), dependsOn: strings3(found["depends_on"]), providerKey: typeof found["provider_config_key"] === "string" ? found["provider_config_key"] : null };
194446
195905
  }
194447
195906
  /** What a reference written in a module instance names, followed through module outputs and the variables its call passes. */
194448
195907
  resolve(ref, module, depth = 0) {
194449
- if (depth > MAX_DEPTH15) return [];
195908
+ if (depth > MAX_DEPTH17) return [];
194450
195909
  const steps = references(ref)[0] ?? [];
194451
195910
  const [first, second, third, fourth] = steps;
194452
195911
  const name2 = (step) => step?.kind === "name" ? step.text : null;
@@ -194471,9 +195930,9 @@ var init_references2 = __esm({
194471
195930
  const out = [];
194472
195931
  for (const instance of chosen) {
194473
195932
  const config2 = this.moduleAt(instance);
194474
- const outputs = config2 !== null && isObject4(config2["outputs"]) ? config2["outputs"] : {};
195933
+ const outputs = config2 !== null && isObject5(config2["outputs"]) ? config2["outputs"] : {};
194475
195934
  const entry2 = outputs[output2];
194476
- const expression2 = isObject4(entry2) && isObject4(entry2["expression"]) ? entry2["expression"] : null;
195935
+ const expression2 = isObject5(entry2) && isObject5(entry2["expression"]) ? entry2["expression"] : null;
194477
195936
  for (const inner of strings3(expression2?.["references"])) out.push(...this.resolve(inner, instance, depth + 1));
194478
195937
  }
194479
195938
  return out;
@@ -194482,9 +195941,9 @@ var init_references2 = __esm({
194482
195941
  variable(module, variable, depth) {
194483
195942
  if (module === "") return [{ kind: "var", name: variable }];
194484
195943
  const call = this.callAt(module);
194485
- const expressions = call !== null && isObject4(call["expressions"]) ? call["expressions"] : {};
195944
+ const expressions = call !== null && isObject5(call["expressions"]) ? call["expressions"] : {};
194486
195945
  const passed = expressions[variable];
194487
- const refs = isObject4(passed) ? strings3(passed["references"]).filter((ref) => !SAME_INSTANCE.has(ref)) : [];
195946
+ const refs = isObject5(passed) ? strings3(passed["references"]).filter((ref) => !SAME_INSTANCE.has(ref)) : [];
194488
195947
  return refs.flatMap((ref) => this.resolve(ref, parentOf3(module), depth + 1));
194489
195948
  }
194490
195949
  };
@@ -194493,7 +195952,7 @@ var init_references2 = __esm({
194493
195952
 
194494
195953
  // ../../packages/diagrams/src/importers/terraform-plan/resources.ts
194495
195954
  function rawOf(value) {
194496
- if (isObject4(value)) {
195955
+ if (isObject5(value)) {
194497
195956
  const entries2 = Object.entries(value).filter((entry2) => typeof entry2[1] === "string");
194498
195957
  return `{ ${entries2.map(([key, entry2]) => `${key} = ${JSON.stringify(entry2)}`).join(", ")} }`;
194499
195958
  }
@@ -194507,7 +195966,7 @@ function valuesOf2(resource) {
194507
195966
  }
194508
195967
  const tags = resource.values["tags"];
194509
195968
  const hidden = resource.sensitive["tags"];
194510
- if (isObject4(tags) && typeof tags["Name"] === "string" && !(isObject4(hidden) && hidden["Name"] === true) && hidden !== true) out.set("tags.Name", tags["Name"]);
195969
+ if (isObject5(tags) && typeof tags["Name"] === "string" && !(isObject5(hidden) && hidden["Name"] === true) && hidden !== true) out.set("tags.Name", tags["Name"]);
194511
195970
  return out;
194512
195971
  }
194513
195972
  function blockOf2(resource, values, start2) {
@@ -194525,7 +195984,7 @@ function stringsOf(values, sensitive) {
194525
195984
  if (out.length >= MAX_VALUES || depth > MAX_VALUE_DEPTH || hidden === true) return;
194526
195985
  if (typeof value === "string") out.push({ name: name2, value });
194527
195986
  else if (Array.isArray(value)) value.forEach((item, index2) => walk(item, name2, Array.isArray(hidden) ? hidden[index2] : void 0, depth + 1));
194528
- else if (isObject4(value)) for (const [key, entry2] of Object.entries(value)) walk(entry2, key, isObject4(hidden) ? hidden[key] : void 0, depth + 1);
195987
+ else if (isObject5(value)) for (const [key, entry2] of Object.entries(value)) walk(entry2, key, isObject5(hidden) ? hidden[key] : void 0, depth + 1);
194529
195988
  };
194530
195989
  for (const [name2, value] of Object.entries(values)) if (!OWN_IDS.has(name2) && !SKIPPED2.has(name2) && name2 !== "tags") walk(value, name2, sensitive[name2], 0);
194531
195990
  return out;
@@ -194546,7 +196005,7 @@ function planResources(document2, text3) {
194546
196005
  if (byBase.has(same)) alias.set(baseOf(resource), same);
194547
196006
  }
194548
196007
  const instances = [...new Set(all.map((resource) => resource.module).filter((module) => module !== "").flatMap((module) => callsOf2(module).map((_call, index2, calls) => calls.slice(0, index2 + 1).map((call) => `module.${call.name}${call.suffix}`).join("."))))];
194549
- const configuration = new Configuration(document2.configuration === null ? null : isObject4(document2.configuration["root_module"]) ? document2.configuration["root_module"] : null, instances);
196008
+ const configuration = new Configuration(document2.configuration === null ? null : isObject5(document2.configuration["root_module"]) ? document2.configuration["root_module"] : null, instances);
194550
196009
  const expand2 = (target, own2, paired) => {
194551
196010
  if (target.kind !== "item") return [];
194552
196011
  const base = alias.get(target.address) ?? target.address;
@@ -194688,7 +196147,7 @@ var init_resources2 = __esm({
194688
196147
  init_generic();
194689
196148
  init_graph4();
194690
196149
  init_resources();
194691
- init_document3();
196150
+ init_document4();
194692
196151
  init_references2();
194693
196152
  MAX_VALUE_DEPTH = 6;
194694
196153
  MAX_VALUES = 400;
@@ -194719,19 +196178,19 @@ function importedOf(json2) {
194719
196178
  const out = /* @__PURE__ */ new Set();
194720
196179
  const changes = json2["resource_changes"];
194721
196180
  if (Array.isArray(changes)) {
194722
- for (const entry2 of changes) if (isObject4(entry2) && isObject4(entry2["change"]) && entry2["change"]["importing"] !== void 0 && typeof entry2["address"] === "string") out.add(entry2["address"]);
196181
+ for (const entry2 of changes) if (isObject5(entry2) && isObject5(entry2["change"]) && entry2["change"]["importing"] !== void 0 && typeof entry2["address"] === "string") out.add(entry2["address"]);
194723
196182
  }
194724
196183
  return out;
194725
196184
  }
194726
196185
  function accountsOf(document2, types) {
194727
196186
  const out = /* @__PURE__ */ new Map();
194728
196187
  for (const entry2 of Object.values(document2.providers)) {
194729
- if (!isObject4(entry2) || typeof entry2["name"] !== "string") continue;
196188
+ if (!isObject5(entry2) || typeof entry2["name"] !== "string") continue;
194730
196189
  const cloud = providerOf2(`${entry2["name"]}_x`);
194731
196190
  if (cloud === null || out.get(cloud) !== void 0) continue;
194732
- const expressions = isObject4(entry2["expressions"]) ? entry2["expressions"] : {};
194733
- const project = isObject4(expressions["project"]) ? expressions["project"]["constant_value"] : void 0;
194734
- out.set(cloud, cloud === "gcp" && typeof project === "string" ? project : null);
196191
+ const expressions = isObject5(entry2["expressions"]) ? entry2["expressions"] : {};
196192
+ const project2 = isObject5(expressions["project"]) ? expressions["project"]["constant_value"] : void 0;
196193
+ out.set(cloud, cloud === "gcp" && typeof project2 === "string" ? project2 : null);
194735
196194
  }
194736
196195
  for (const type of types) {
194737
196196
  const cloud = providerOf2(type);
@@ -194743,9 +196202,9 @@ function regionsOf2(document2) {
194743
196202
  const out = /* @__PURE__ */ new Map();
194744
196203
  const byProvider = /* @__PURE__ */ new Map();
194745
196204
  for (const [key, entry2] of Object.entries(document2.providers)) {
194746
- if (!isObject4(entry2) || typeof entry2["name"] !== "string" || key.includes(":")) continue;
194747
- const expressions = isObject4(entry2["expressions"]) ? entry2["expressions"] : {};
194748
- const region = isObject4(expressions["region"]) ? expressions["region"]["constant_value"] : void 0;
196205
+ if (!isObject5(entry2) || typeof entry2["name"] !== "string" || key.includes(":")) continue;
196206
+ const expressions = isObject5(entry2["expressions"]) ? entry2["expressions"] : {};
196207
+ const region = isObject5(expressions["region"]) ? expressions["region"]["constant_value"] : void 0;
194749
196208
  if (typeof region !== "string" || region === "") continue;
194750
196209
  out.set(key, region);
194751
196210
  byProvider.set(entry2["name"], /* @__PURE__ */ new Set([...byProvider.get(entry2["name"]) ?? [], region]));
@@ -194778,7 +196237,7 @@ function readTerraformPlan(text3, context) {
194778
196237
  return null;
194779
196238
  }
194780
196239
  const document2 = readPlanDocument(json2);
194781
- if (document2 === null || !isObject4(json2)) {
196240
+ if (document2 === null || !isObject5(json2)) {
194782
196241
  context.report.add(DIAGNOSTIC_CODES.importNoShape, START, "The JSON is neither a plan (planned_values and resource_changes) nor a state (values.root_module).", "Run terraform plan -out=plan.out, then send the output of terraform show -json plan.out; or send terraform show -json for the state.");
194783
196242
  return null;
194784
196243
  }
@@ -194846,7 +196305,7 @@ var init_terraform_plan = __esm({
194846
196305
  init_labels();
194847
196306
  init_resources();
194848
196307
  init_values2();
194849
- init_document3();
196308
+ init_document4();
194850
196309
  init_resources2();
194851
196310
  CHANGES = {
194852
196311
  create: { tone: "green", word: "create", said: "one marked + is created", mark: "create" },
@@ -195162,6 +196621,8 @@ var init_registry4 = __esm({
195162
196621
  "../../packages/diagrams/src/importers/registry.ts"() {
195163
196622
  "use strict";
195164
196623
  init_arm();
196624
+ init_asyncapi();
196625
+ init_azure_pipelines();
195165
196626
  init_backstage();
195166
196627
  init_bicep();
195167
196628
  init_cdk();
@@ -195172,6 +196633,7 @@ var init_registry4 = __esm({
195172
196633
  init_git_log();
195173
196634
  init_helm();
195174
196635
  init_github_actions();
196636
+ init_gitlab_ci();
195175
196637
  init_json();
195176
196638
  init_kubernetes();
195177
196639
  init_kustomize();
@@ -195179,6 +196641,7 @@ var init_registry4 = __esm({
195179
196641
  init_prisma();
195180
196642
  init_pulumi();
195181
196643
  init_sql();
196644
+ init_structurizr();
195182
196645
  init_terraform();
195183
196646
  init_terraform_plan();
195184
196647
  init_tree5();
@@ -195199,7 +196662,11 @@ var init_registry4 = __esm({
195199
196662
  helm: helmImporter,
195200
196663
  kustomize: kustomizeImporter,
195201
196664
  backstage: backstageImporter,
196665
+ structurizr: structurizrImporter,
196666
+ asyncapi: asyncapiImporter,
195202
196667
  "github-actions": githubActionsImporter,
196668
+ "gitlab-ci": gitlabCiImporter,
196669
+ "azure-pipelines": azurePipelinesImporter,
195203
196670
  csv: csvImporter,
195204
196671
  json: jsonImporter,
195205
196672
  tree: treeImporter,
@@ -197086,7 +198553,7 @@ function wordsOf5(text3) {
197086
198553
  function cleanLabel2(text3) {
197087
198554
  return text3.replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/[`*_~"\\]/g, "").replace(/[\u0000-\u001f\u007f]/g, " ").replace(/\s+/g, " ").trim();
197088
198555
  }
197089
- function stepLabel(text3) {
198556
+ function stepLabel2(text3) {
197090
198557
  const clean = cleanLabel2(text3).replace(/[.;]$/, "");
197091
198558
  const capital2 = `${clean.charAt(0).toUpperCase()}${clean.slice(1)}`;
197092
198559
  if (capital2.length <= ONE_LINE) return { label: capital2, sub: null };
@@ -197097,7 +198564,7 @@ function stepLabel(text3) {
197097
198564
  return { label: capital2, sub: null };
197098
198565
  }
197099
198566
  function stepText2(text3) {
197100
- const { label, sub } = stepLabel(text3);
198567
+ const { label, sub } = stepLabel2(text3);
197101
198568
  return sub === null ? `"${label}"` : `"${label}" sub="${sub}"`;
197102
198569
  }
197103
198570
  function withDescription(source, description) {
@@ -197969,7 +199436,7 @@ function partType(name2) {
197969
199436
  function linkedFlow(material, title) {
197970
199437
  const ids = idMaker("part");
197971
199438
  const nodes = /* @__PURE__ */ new Map();
197972
- const nodeOf4 = (label) => {
199439
+ const nodeOf5 = (label) => {
197973
199440
  const key = label.toLowerCase();
197974
199441
  const known3 = nodes.get(key);
197975
199442
  if (known3 !== void 0 && /^[a-z]/.test(known3.label) && /^[A-Z]/.test(label)) known3.label = label;
@@ -197978,7 +199445,7 @@ function linkedFlow(material, title) {
197978
199445
  nodes.set(key, node3);
197979
199446
  return node3.id;
197980
199447
  };
197981
- const links = material.relations.slice(0, MOST * 2).map((relation2) => ({ from: nodeOf4(relation2.from), to: nodeOf4(relation2.to), verb: relation2.verb }));
199448
+ const links = material.relations.slice(0, MOST * 2).map((relation2) => ({ from: nodeOf5(relation2.from), to: nodeOf5(relation2.to), verb: relation2.verb }));
197982
199449
  const edges = links.map((link2) => `${link2.from} -> ${link2.to} : ${quoted4(link2.verb)}`);
197983
199450
  return sourceOf(`flow ${quoted4(title)} direction=${directionFor(longestChain2(links))}`, [
197984
199451
  ...[...nodes.values()].map((node3) => `node ${node3.id} ${partType(node3.label)} ${quoted4(node3.label)}${iconOption(node3.label)}`),
@@ -197998,7 +199465,7 @@ function longestChain2(links) {
197998
199465
  };
197999
199466
  return Math.max(0, ...links.map((link2) => walk(link2.from, /* @__PURE__ */ new Set([link2.from]))));
198000
199467
  }
198001
- function stepsOf(material) {
199468
+ function stepsOf2(material) {
198002
199469
  const pairs = material.labelled.filter((line3) => cleanLabel2(line3.text) !== "");
198003
199470
  const repeated = new Set(pairs.map((line3) => line3.label.toLowerCase())).size < pairs.length;
198004
199471
  if (pairs.length >= 2 && repeated || pairs.length >= 3) return pairs.slice(0, MOST).map((pair2) => ({ label: pair2.label, text: pair2.text }));
@@ -198109,7 +199576,7 @@ var init_systems = __esm({
198109
199576
  },
198110
199577
  swimlane: (material, title) => {
198111
199578
  const ids = idMaker("step");
198112
- const steps = stepsOf(material);
199579
+ const steps = stepsOf2(material);
198113
199580
  const laneNames = distinctLabels(steps.map((step) => step.label)).slice(0, 6);
198114
199581
  const placed = steps.map((step) => ({ lane: laneNames.findIndex((name2) => name2.toLowerCase() === cleanLabel2(step.label).toLowerCase()), label: cleanLabel2(step.text) })).filter((step) => step.lane >= 0).map((step) => ({ ...step, id: ids(step.label) }));
198115
199582
  const begin = ids("Start");
@@ -198889,7 +200356,7 @@ var init_draw_for_view = __esm({
198889
200356
  });
198890
200357
 
198891
200358
  // ../../packages/diagrams/src/view/index.ts
198892
- var init_view = __esm({
200359
+ var init_view2 = __esm({
198893
200360
  "../../packages/diagrams/src/view/index.ts"() {
198894
200361
  "use strict";
198895
200362
  init_fragment();
@@ -198974,7 +200441,7 @@ var init_view_link = __esm({
198974
200441
  init_constants();
198975
200442
  init_apply_defaults();
198976
200443
  init_schema4();
198977
- init_view();
200444
+ init_view2();
198978
200445
  SOURCE_OF = {
198979
200446
  draw_diagram: (args, answer) => answer["valid"] === true ? args["source"] : null,
198980
200447
  draw_from_pattern: (_args, answer) => answer["valid"] === true ? answer["source"] : null,
@@ -199379,7 +200846,7 @@ var init_server_info = __esm({
199379
200846
  `Draws ${joinWords(kindNouns(), "and")} diagrams from a small line-oriented text language.`,
199380
200847
  "Prefer the workflow tools: each does the work of several single tools in one call.",
199381
200848
  "When you are unsure which kind of diagram fits, call suggest_diagram with the request in plain words and any data: it ranks the kinds and gives a starter that parses; for a whole document, plan_document_diagrams returns the sections a picture would help, each with a starter.",
199382
- "When the diagram should come from a file the person has (SQL, Prisma, or Drizzle models, an OpenAPI document, Terraform, Bicep, ARM, Pulumi, CloudFormation, or the CDK, docker-compose, Kubernetes manifests, Helm, Kustomize, a Backstage catalog, a GitHub Actions workflow, CSV or JSON data, a folder listing, or a git log), call import_source with its text and format: it builds the whole diagram from the file in one call, and its diagnostics say what was left out get_diagram_syntax with topic import-formats says what each format reads.",
200849
+ "When the diagram should come from a file the person has (SQL, Prisma, or Drizzle models, an OpenAPI document, Terraform, Bicep, ARM, Pulumi, CloudFormation, or the CDK, docker-compose, Kubernetes manifests, Helm, Kustomize, a Backstage catalog, a Structurizr workspace, AsyncAPI documents, a GitHub Actions workflow, a GitLab CI/CD or Azure Pipelines pipeline, CSV or JSON data, a folder listing, or a git log), call import_source with its text and format: it builds the whole diagram from the file in one call, and its diagnostics say what was left out get_diagram_syntax with topic import-formats says what each format reads.",
199383
200850
  "For a request to draw a common architecture, such as a three-tier network, a serverless API, a container platform, or a queue with workers, call find_pattern first with the request in plain words; when a pattern fits, call draw_from_pattern with its id, a provider flavour (neutral, aws, azure, or gcp), and slot values that rename its parts, or get_pattern to read and edit its source, and when nothing fits, write the diagram from scratch with draw_diagram.",
199384
200851
  "Call get_diagram_syntax once with no kind to read the shared language, and again with kind set to the kind you draw for its statements, limits, and example.",
199385
200852
  'Write the source and call draw_diagram: it returns every error with line, column, and hint and draws nothing until the source is valid, so fix every error and call again; once valid it returns the warnings, an outline to check the meaning, and the SVG for light and dark. The pictures are most of the answer and you cannot look at them, so pass svg "never" to check a diagram, and draw only when you will save, show, or publish the pictures; when a drawing is too big to read in one answer the SVG is left out, picturesOmitted says so, and svg "always" forces it.',
@@ -199763,7 +201230,7 @@ var init_create_server = __esm({
199763
201230
  "use strict";
199764
201231
  init_dist();
199765
201232
  init_tools();
199766
- init_view();
201233
+ init_view2();
199767
201234
  init_activity();
199768
201235
  init_audit();
199769
201236
  init_engine_runner();
@@ -200227,7 +201694,7 @@ var VIEWER_URL_VARIABLE;
200227
201694
  var init_viewer_address = __esm({
200228
201695
  "src/viewer-address.ts"() {
200229
201696
  "use strict";
200230
- init_view();
201697
+ init_view2();
200231
201698
  VIEWER_URL_VARIABLE = "PLOTWORK_VIEWER_URL";
200232
201699
  }
200233
201700
  });