likec4 1.48.0 → 1.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +11 -1
  2. package/__app__/src/likec4.js +5595 -4127
  3. package/__app__/src/routes/index.js +3 -153
  4. package/__app__/src/routes/projects.js +21 -1087
  5. package/__app__/src/routes/single.js +1221 -16
  6. package/__app__/src/style.css +1 -1
  7. package/__app__/src/vendors.js +3507 -894
  8. package/__app__/src/webcomponent.js +1 -1
  9. package/config/schema.json +155 -143
  10. package/dist/THIRD-PARTY-LICENSES.md +1739 -0
  11. package/dist/_chunks/GraphvizBinaryAdapter.mjs +72 -0
  12. package/dist/_chunks/filenames.mjs +14 -0
  13. package/dist/_chunks/index.d.mts +224 -129
  14. package/dist/_chunks/index2.d.mts +2033 -1908
  15. package/dist/_chunks/libs/@chevrotain/gast.mjs +1 -3969
  16. package/dist/_chunks/libs/@chevrotain/regexp-to-ast.mjs +9 -785
  17. package/dist/_chunks/libs/@chevrotain/utils.mjs +1 -37
  18. package/dist/_chunks/libs/@hono/mcp.mjs +34 -0
  19. package/dist/_chunks/libs/@hono/node-server.mjs +1 -436
  20. package/dist/_chunks/libs/@logtape/logtape.d.mts +741 -0
  21. package/dist/_chunks/libs/@logtape/logtape.mjs +6 -1354
  22. package/dist/_chunks/libs/@lume/kiwi.mjs +1 -1355
  23. package/dist/_chunks/libs/@modelcontextprotocol/sdk.d.mts +14 -14
  24. package/dist/_chunks/libs/@modelcontextprotocol/sdk.mjs +12 -25105
  25. package/dist/_chunks/libs/@msgpack/msgpack.mjs +1 -1503
  26. package/dist/_chunks/libs/@nanostores/react.mjs +1 -30
  27. package/dist/_chunks/libs/@smithy/util-base64.mjs +1 -100
  28. package/dist/_chunks/libs/ajv.mjs +1 -777
  29. package/dist/_chunks/libs/atomically.mjs +1 -362
  30. package/dist/_chunks/libs/birpc.mjs +1 -201
  31. package/dist/_chunks/libs/chevrotain-allstar.mjs +2 -850
  32. package/dist/_chunks/libs/chevrotain.mjs +55 -6229
  33. package/dist/_chunks/libs/conf.mjs +1 -2258
  34. package/dist/_chunks/libs/defu.mjs +1 -42
  35. package/dist/_chunks/libs/esm-env.mjs +1 -5
  36. package/dist/_chunks/libs/eventemitter3.mjs +1 -243
  37. package/dist/_chunks/libs/fast-equals.mjs +1 -446
  38. package/dist/_chunks/libs/find-up-simple.mjs +1 -24
  39. package/dist/_chunks/libs/get-port.mjs +1 -107
  40. package/dist/_chunks/libs/is-docker.mjs +1 -26
  41. package/dist/_chunks/libs/is-error-instance.mjs +1 -26
  42. package/dist/_chunks/libs/is-inside-container.mjs +1 -20
  43. package/dist/_chunks/libs/is-plain-obj.mjs +1 -9
  44. package/dist/_chunks/libs/isexe.mjs +1 -127
  45. package/dist/_chunks/libs/json5.mjs +14 -959
  46. package/dist/_chunks/libs/khroma.mjs +1 -605
  47. package/dist/_chunks/libs/ky.mjs +2 -807
  48. package/dist/_chunks/libs/langium.d.mts +2880 -2844
  49. package/dist/_chunks/libs/langium.mjs +32 -20351
  50. package/dist/_chunks/libs/merge-error-cause.mjs +2 -746
  51. package/dist/_chunks/libs/nanostores.mjs +1 -198
  52. package/dist/_chunks/libs/p-limit.mjs +1 -120
  53. package/dist/_chunks/libs/p-queue.mjs +1 -449
  54. package/dist/_chunks/libs/package-manager-detector.mjs +1 -559
  55. package/dist/_chunks/libs/package-up.mjs +1 -10
  56. package/dist/_chunks/libs/parse-ms.mjs +1 -36
  57. package/dist/_chunks/libs/pathe.mjs +1 -0
  58. package/dist/_chunks/libs/picomatch.mjs +1 -1673
  59. package/dist/_chunks/libs/pretty-ms.mjs +1 -80
  60. package/dist/_chunks/libs/remeda.mjs +1 -690
  61. package/dist/_chunks/libs/safe-stringify.mjs +1 -21
  62. package/dist/_chunks/libs/strip-indent.mjs +1 -15
  63. package/dist/_chunks/libs/tinyrainbow.mjs +1 -88
  64. package/dist/_chunks/libs/ts-graphviz.mjs +4 -725
  65. package/dist/_chunks/libs/ufo.mjs +1 -240
  66. package/dist/_chunks/libs/which.mjs +1 -84
  67. package/dist/_chunks/libs/word-wrap.mjs +12 -43
  68. package/dist/_chunks/node.mjs +481 -0
  69. package/dist/_chunks/plugin.mjs +98 -772
  70. package/dist/_chunks/rolldown-runtime.mjs +1 -48
  71. package/dist/_chunks/sequence-view.mjs +1 -575
  72. package/dist/cli/index.mjs +127 -1846
  73. package/dist/config/index.d.mts +2 -2
  74. package/dist/config/index.mjs +1 -6
  75. package/dist/index.d.mts +148 -7
  76. package/dist/index.mjs +1 -21
  77. package/dist/model/builder.mjs +1 -3
  78. package/dist/model/index.d.mts +57 -3
  79. package/dist/model/index.mjs +1 -5
  80. package/dist/vite-plugin/index.d.mts +4 -3
  81. package/dist/vite-plugin/index.mjs +1 -22
  82. package/dist/vite-plugin/internal.d.mts +5 -5
  83. package/dist/vite-plugin/internal.mjs +1 -68
  84. package/package.json +60 -41
  85. package/react/{index.d.ts → index.d.mts} +112 -70
  86. package/react/{index.js → index.mjs} +21361 -22064
  87. package/react/package.json +2 -5
  88. package/vite-plugin-modules.d.ts +5 -5
  89. package/dist/_chunks/LikeC4.d.mts +0 -121
  90. package/dist/_chunks/LikeC4.mjs +0 -202
  91. package/dist/_chunks/config-app.prod.d.mts +0 -18
  92. package/dist/_chunks/config-app.prod.mjs +0 -188
  93. package/dist/_chunks/config-webcomponent.prod.mjs +0 -71
  94. package/dist/_chunks/define-config.mjs +0 -409
  95. package/dist/_chunks/index3.d.mts +0 -60
  96. package/dist/_chunks/index4.d.mts +0 -1
  97. package/dist/_chunks/libs/@smithy/is-array-buffer.mjs +0 -10
  98. package/dist/_chunks/libs/hono.mjs +0 -1829
  99. package/dist/_chunks/libs/nanoid.mjs +0 -29
  100. package/dist/_chunks/model.mjs +0 -12
  101. package/dist/_chunks/module.d.mts +0 -71
  102. package/dist/_chunks/module.mjs +0 -18657
  103. package/dist/_chunks/vite-build.mjs +0 -69
  104. package/dist/_chunks/vite-dev.mjs +0 -79
  105. package/dist/_chunks/vite-preview.mjs +0 -27
  106. package/dist/language/module.d.mts +0 -5
  107. package/dist/language/module.mjs +0 -20
  108. package/dist/vite/vite-build.d.mts +0 -26
  109. package/dist/vite/vite-build.mjs +0 -27
  110. package/dist/vite/vite-dev.d.mts +0 -34
  111. package/dist/vite/vite-dev.mjs +0 -29
  112. package/dist/vite/vite-preview.d.mts +0 -20
  113. package/dist/vite/vite-preview.mjs +0 -26
@@ -1,350 +1,24 @@
1
- import { s as __toESM } from "./rolldown-runtime.mjs";
2
- import { a as expandToNode, i as toString, n as CompositeGeneratorNode, r as NL, t as joinToNode } from "./libs/langium.mjs";
3
- import { B as n$2, S as e, U as n, h as t$3, j as t$5, m as t, o as t$2, q as t$1, r as n$1, u as t$4, v as e$2, w as e$1 } from "./libs/remeda.mjs";
4
- import { t as u } from "./libs/tinyrainbow.mjs";
5
- import { t as require_lib } from "./libs/json5.mjs";
6
- import { o as joinURL } from "./libs/ufo.mjs";
7
- import { t as LikeC4 } from "./LikeC4.mjs";
8
- import { t as createBirpc } from "./libs/birpc.mjs";
9
- import { RichText } from "@likec4/core/types";
10
- import { invariant, isNonEmptyArray, nonexhaustive } from "@likec4/core";
11
- import { compareNatural } from "@likec4/core/utils";
12
-
13
- //#region src/vite-plugin/rpc/calcAdhocView.ts
14
- async function calcAdhocView({ logger, likec4 }, data) {
15
- logger.info([
16
- u.green("adhoc:view"),
17
- u.dim("project:"),
18
- data.projectId
19
- ].join(" "));
20
- const view = await likec4.views.adhocView(data.predicates, data.projectId);
21
- logger.info([u.green("adhoc:view"), "✅"].join(" "));
22
- return view;
23
- }
24
-
25
- //#endregion
26
- //#region src/vite-plugin/rpc/sendError.ts
27
- function sendError(server, { name, error }) {
28
- const lines = error.split("\n");
29
- const test = /^\s+at\s+/;
30
- let stackBeginAt = lines.findIndex((l) => test.test(l));
31
- if (stackBeginAt === -1) stackBeginAt = lines.length;
32
- server.hot.send({
33
- type: "error",
34
- err: {
35
- message: lines.slice(0, stackBeginAt).join("\n"),
36
- stack: lines.slice(stackBeginAt).join("\n"),
37
- name: name ?? "LikeC4PluginError",
38
- plugin: "vite-plugin-likec4"
39
- }
40
- });
41
- }
42
-
43
- //#endregion
44
- //#region src/vite-plugin/rpc/updateView.ts
45
- async function updateView({ logger, likec4 }, data) {
46
- logger.info([
47
- u.green("view:onChange"),
48
- u.dim("project") + ":",
49
- data.projectId,
50
- u.dim("view") + ":",
51
- data.viewId,
52
- u.dim("change") + ":",
53
- data.change.op
54
- ].join(" "));
55
- const result = await likec4.editor.applyChange(data);
56
- if (!result.success) {
57
- logger.error(`Failed to apply view change:\n${result.error}`);
58
- const err = new Error(result.error);
59
- err.stack = result.error;
60
- throw err;
61
- }
62
- logger.info([u.green("view:onChange"), "✅"].join(" "));
63
- }
64
-
65
- //#endregion
66
- //#region src/vite-plugin/rpc/rpc.ts
67
- function enablePluginRPC(params) {
68
- let lastError = null;
69
- const server = params.server;
70
- createBirpc({
71
- updateView: (data) => updateView(params, data),
72
- calcAdhocView: (data) => calcAdhocView(params, data)
73
- }, {
74
- on: (fn) => server.hot.on("likec4:rpc", fn),
75
- post: (data) => server.hot.send("likec4:rpc", data),
76
- onFunctionError: (error, functionName) => {
77
- params.logger.error(`RPC error in ${functionName}`, { error });
78
- const errorString = error.stack ?? error.message;
79
- try {
80
- if (lastError !== errorString) {
81
- lastError = errorString;
82
- sendError(server, {
83
- name: error.name,
84
- error: errorString
85
- });
86
- }
87
- } catch (e) {
88
- params.logger.error(`Failed to send error to client`, { error: e });
89
- }
90
- }
91
- });
92
- }
93
-
94
- //#endregion
95
- //#region ../generators/src/d2/generate-d2.ts
96
- const capitalizeFirstLetter$2 = (value) => value.charAt(0).toLocaleUpperCase() + value.slice(1);
97
- const fqnName$2 = (nodeId) => nodeId.split(".").map(capitalizeFirstLetter$2).join("");
98
- const nodeName$2 = (node) => {
99
- return fqnName$2(node.parent ? node.id.slice(node.parent.length + 1) : node.id);
100
- };
101
- const d2direction = ({ autoLayout }) => {
102
- switch (autoLayout.direction) {
103
- case "TB": return "down";
104
- case "BT": return "up";
105
- case "LR": return "right";
106
- case "RL": return "left";
107
- }
108
- };
109
- const d2shape = ({ shape }) => {
110
- switch (shape) {
111
- case "queue":
112
- case "cylinder":
113
- case "rectangle":
114
- case "document": return shape;
115
- case "person": return "c4-person";
116
- case "storage": return "stored_data";
117
- case "bucket":
118
- case "mobile":
119
- case "browser": return "rectangle";
120
- }
121
- };
122
- function generateD2(viewmodel) {
123
- const view = viewmodel.$view;
124
- const { nodes, edges } = view;
125
- const names = /* @__PURE__ */ new Map();
126
- const printNode = (node, parentName) => {
127
- const name = nodeName$2(node);
128
- const fqnName = (parentName ? parentName + "." : "") + name;
129
- names.set(node.id, fqnName);
130
- const label = JSON.stringify(node.title);
131
- const shape = d2shape(node);
132
- return new CompositeGeneratorNode().append(name, ": {", NL).indent({
133
- indentedChildren: (indent) => indent.append("label: ", label, NL).appendIf(shape !== "rectangle", "shape: ", shape, NL).appendIf(node.children.length > 0, NL, joinToNode(nodes.filter((n) => n.parent === node.id), (n) => printNode(n, fqnName))),
134
- indentation: 2
135
- }).append("}", NL);
136
- };
137
- const printEdge = (edge) => {
138
- return new CompositeGeneratorNode().append(names.get(edge.source), " -> ", names.get(edge.target)).append((out) => edge.label && out.append(": ", JSON.stringify(edge.label)));
139
- };
140
- return toString(new CompositeGeneratorNode().append("direction: ", d2direction(view), NL, NL).append(joinToNode(nodes.filter((n) => e(n.parent)), (n) => printNode(n), { appendNewLineIfNotEmpty: true })).appendIf(edges.length > 0, NL, joinToNode(edges, (e) => printEdge(e), { appendNewLineIfNotEmpty: true })));
141
- }
142
-
143
- //#endregion
144
- //#region ../generators/src/mmd/generate-mmd.ts
145
- const capitalizeFirstLetter$1 = (value) => value.charAt(0).toLocaleUpperCase() + value.slice(1);
146
- const fqnName$1 = (nodeId) => nodeId.split(".").map(capitalizeFirstLetter$1).join("");
147
- const nodeName$1 = (node) => {
148
- return fqnName$1(node.parent ? node.id.slice(node.parent.length + 1) : node.id);
149
- };
150
- const toSingleQuotes = (str) => str.replace(/\\?"/g, `'`);
151
- const mmdshape = ({ shape, title }) => {
152
- const label = `label: ${JSON.stringify(title)}`;
153
- switch (shape) {
154
- case "queue": return `@{ shape: horizontal-cylinder, ${label} }`;
155
- case "person": return `@{ icon: "fa:user", shape: rounded, ${label} }`;
156
- case "storage": return `@{ shape: disk, ${label} }`;
157
- case "cylinder": return `@{ shape: cylinder, ${label} }`;
158
- case "mobile":
159
- case "browser": return `@{ shape: rounded, ${label} }`;
160
- case "bucket": return `@{ shape: trap-t, ${label} }`;
161
- case "rectangle": return `@{ shape: rectangle, ${label} }`;
162
- case "document": return `@{ shape: doc, ${label} }`;
163
- default: nonexhaustive(shape);
164
- }
165
- };
166
- function generateMermaid(viewmodel) {
167
- const view = viewmodel.$view;
168
- const { nodes, edges } = view;
169
- const names = /* @__PURE__ */ new Map();
170
- const printNode = (node, parentName) => {
171
- const name = nodeName$1(node);
172
- const fqnName = (parentName ? parentName + "." : "") + name;
173
- names.set(node.id, fqnName);
174
- const baseNode = new CompositeGeneratorNode();
175
- if (node.children.length > 0) {
176
- const label = toSingleQuotes(node.title);
177
- baseNode.append("subgraph ", fqnName, "[\"`", label, "`\"]", NL).indent({
178
- indentedChildren: [joinToNode(nodes.filter((n) => n.parent === node.id), (n) => printNode(n, fqnName), { appendNewLineIfNotEmpty: true })],
179
- indentation: 2
180
- }).append("end", NL);
181
- } else baseNode.append(fqnName, mmdshape(node));
182
- return baseNode;
183
- };
184
- const printEdge = (edge) => {
185
- return new CompositeGeneratorNode().append(names.get(edge.source), " -.", edge.label ? " \"`" + toSingleQuotes(edge.label) + "`\" .-" : "-", "> ", names.get(edge.target));
186
- };
187
- return toString(new CompositeGeneratorNode().append("---", NL, `title: ${JSON.stringify(toSingleQuotes(viewmodel.titleOrId))}`, NL, "---", NL).append("graph ", view.autoLayout.direction, NL).indent({
188
- indentedChildren: (indent) => {
189
- indent.append(joinToNode(nodes.filter((n) => e(n.parent)), (n) => printNode(n), { appendNewLineIfNotEmpty: true })).appendIf(edges.length > 0, joinToNode(edges, (e) => printEdge(e), { appendNewLineIfNotEmpty: true }));
190
- },
191
- indentation: 2
192
- }));
193
- }
194
-
195
- //#endregion
196
- //#region ../generators/src/puml/generate-puml.ts
197
- const capitalizeFirstLetter = (value) => value.charAt(0).toLocaleUpperCase() + value.slice(1);
198
- const fqnName = (nodeId) => {
199
- return nodeId.split(/[.-]/).map(capitalizeFirstLetter).join("");
200
- };
201
- const nodeName = (node) => {
202
- return fqnName(node.parent ? node.id.slice(node.parent.length + 1) : node.id);
203
- };
204
- const pumlColor = (color, customColorProvider, defaultColor = "#3b82f6") => {
205
- if (color) return customColorProvider(color) ?? defaultColor;
206
- return defaultColor;
207
- };
208
- const pumlDirection = ({ autoLayout }) => {
209
- switch (autoLayout.direction) {
210
- case "TB": return "top to bottom";
211
- case "BT":
212
- console.warn("Bottom to top direction is not supported. Defaulting to top to bottom.");
213
- return "top to bottom";
214
- case "LR": return "left to right";
215
- case "RL":
216
- console.warn("Right to left direction is not supported. Defaulting to left to right.");
217
- return "left to right";
218
- }
219
- };
220
- const pumlShape = ({ shape }) => {
221
- switch (shape) {
222
- case "queue":
223
- case "rectangle":
224
- case "person": return shape;
225
- case "storage":
226
- case "cylinder": return "database";
227
- case "document":
228
- case "mobile":
229
- case "bucket":
230
- case "browser": return "rectangle";
231
- default: nonexhaustive(shape);
232
- }
233
- };
234
- const escapeLabel = (label) => e$1(label) ? null : JSON.stringify(label).slice(1, -1).replace(/\\"/g, "\"");
235
- function generatePuml(viewmodel) {
236
- const view = viewmodel.$view;
237
- const colors = viewmodel.$model.$styles.theme.colors;
238
- const { nodes, edges } = view;
239
- const elemntColorProvider = (key) => (colorKey) => colorKey in colors ? colors[colorKey].elements[key] : void 0;
240
- const relationshipsColorProvider = (key) => (colorKey) => colorKey in colors ? colors[colorKey].relationships[key] : void 0;
241
- const names = /* @__PURE__ */ new Map();
242
- const printHeader = () => {
243
- return new CompositeGeneratorNode().append("title \"", viewmodel.titleOrId, "\"", NL).append(pumlDirection(view), " direction", NL);
244
- };
245
- const printTheme = () => {
246
- return new CompositeGeneratorNode().append("hide stereotype", NL).append("skinparam ranksep ", "60", NL).append("skinparam nodesep ", "30", NL).append("skinparam {", NL).indent({
247
- indentedChildren: (indent) => indent.append("arrowFontSize ", "10", NL).append("defaultTextAlignment ", "center", NL).append("wrapWidth ", "200", NL).append("maxMessageSize ", "100", NL).append("shadowing ", "false", NL),
248
- indentation: 2
249
- }).append("}", NL);
250
- };
251
- const printStereotypes = (node) => {
252
- const shape = pumlShape(node);
253
- const fqn = fqnName(node.id);
254
- return new CompositeGeneratorNode().append("skinparam ", shape, "<<", fqn, ">>", "{", NL).indent({
255
- indentedChildren: (indent) => indent.append("BackgroundColor ", pumlColor(node.color, elemntColorProvider("fill")), NL).append("FontColor ", pumlColor(node.color, elemntColorProvider("hiContrast"), "#FFFFFF"), NL).append("BorderColor ", pumlColor(node.color, elemntColorProvider("stroke")), NL),
256
- indentation: 2
257
- }).append("}", NL);
258
- };
259
- const printNode = (node) => {
260
- const shape = pumlShape(node);
261
- const fqn = fqnName(node.id);
262
- const label = escapeLabel(node.title) || nodeName(node);
263
- const tech = escapeLabel(node.technology);
264
- names.set(node.id, fqn);
265
- const description = RichText.from(node.description);
266
- return new CompositeGeneratorNode().append(shape, " ").append("\"").append("==", label).appendIf(!!tech, `\\n<size:10>[`, tech, "]</size>").appendIf(description.nonEmpty, `\\n\\n`, escapeLabel(description.text)).append("\"", " <<", fqn, ">> ", "as ", fqn, NL);
267
- };
268
- const printBoundary = (node) => {
269
- const label = escapeLabel(node.title) || nodeName(node);
270
- const fqn = fqnName(node.id);
271
- names.set(node.id, fqn);
272
- return new CompositeGeneratorNode().append("rectangle \"", label, "\" <<", fqn, ">> as ", fqn, " {", NL).indent({
273
- indentedChildren: (indent) => indent.append("skinparam ", "RectangleBorderColor<<", fqn, ">> ", pumlColor(node.color, elemntColorProvider("fill")), NL).append("skinparam ", "RectangleFontColor<<", fqn, ">> ", pumlColor(node.color, elemntColorProvider("fill")), NL).append("skinparam ", "RectangleBorderStyle<<", fqn, ">> ", "dashed", NL, NL).append(joinToNode(nodes.filter((n) => n.parent === node.id), (c) => c.children.length > 0 ? printBoundary(c) : printNode(c))),
274
- indentation: 2
275
- }).append("}", NL);
276
- };
277
- const printEdge = (edge) => {
278
- const tech = edge.technology || "";
279
- const label = edge.label || tech;
280
- const color = pumlColor(edge.color, relationshipsColorProvider("line"), "#777777");
281
- const withColor = (text) => `<color:${color}>${text.replaceAll("\"", `'`)}`;
282
- const out = new CompositeGeneratorNode().append(names.get(edge.source), " .[", color, ",thickness=2].> ", names.get(edge.target));
283
- if (label || tech) {
284
- out.append(" : ", label.split("\n").map((l) => e$1(l) ? l : withColor(l)).join("\\n"));
285
- if (tech && tech !== label) out.append("\\n<size:8>[", withColor(tech), "]</size>");
286
- }
287
- return out.append(NL);
288
- };
289
- return toString(new CompositeGeneratorNode().append("@startuml", NL).append(printHeader(), NL).append(printTheme(), NL).append(joinToNode(nodes.filter((n) => n.children.length == 0), (n) => printStereotypes(n), { appendNewLineIfNotEmpty: true })).append(joinToNode(nodes.filter((n) => e(n.parent)), (n) => n.children.length > 0 ? printBoundary(n) : printNode(n), { appendNewLineIfNotEmpty: true })).appendIf(edges.length > 0, NL, joinToNode(edges, (e) => printEdge(e), { appendNewLineIfNotEmpty: true })).append(`@enduml`, NL));
290
- }
291
-
292
- //#endregion
293
- //#region src/vite-plugin/virtuals/_shared.ts
294
- function generateMatches(moduleId, extension = ".js") {
295
- return {
296
- matches: (id) => {
297
- let { module, projectId } = id.match(/^likec4:plugin\/(?<projectId>.+)\/(?<module>.+)$/)?.groups ?? id.match(/^likec4:(?<module>.+)\/(?<projectId>.+)$/)?.groups ?? {};
298
- if (!module || !projectId) return null;
299
- if (module.endsWith(extension)) module = module.slice(0, -extension.length);
300
- if (module === moduleId) return projectId;
301
- return null;
302
- },
303
- virtualId: (projectId) => joinURL(`likec4:plugin`, projectId, moduleId) + extension
304
- };
305
- }
306
- const charMap = {
307
- "<": "\\u003C",
308
- ">": "\\u003E",
309
- "/": "\\u002F",
310
- "\\": "\\\\",
311
- "\b": "\\b",
312
- "\f": "\\f",
313
- "\n": "\\n",
314
- "\r": "\\r",
315
- " ": "\\t",
316
- "\0": "\\0",
317
- "\u2028": "\\u2028",
318
- "\u2029": "\\u2029"
319
- };
320
- function escapeUnsafeChars(str) {
321
- return str.replace(/[<>\b\f\n\r\t\0\u2028\u2029\\]/g, (x) => charMap[x]);
322
- }
323
- function generateCombinedProjects(moduleId, fnName) {
324
- return {
325
- id: `likec4:${moduleId}`,
326
- virtualId: `likec4:plugin/${moduleId}.js`,
327
- async load({ logger, projects }) {
328
- logger.info(u.dim(`generating likec4:${moduleId}`));
329
- return `
330
- export let ${fnName}Fn = {
331
- ${projects.map(({ id }) => {
332
- const pkg = escapeUnsafeChars(JSON.stringify(joinURL(`likec4:${moduleId}`, id)));
333
- return ` ${JSON.stringify(id)}: () => import(${pkg})`;
334
- }).join(",\n")}
1
+ import{t as createBirpc}from"./libs/birpc.mjs";import{E as e,F as t$5,K as n,O as e$1,S as e$2,U as n$2,X as t$1,d as t$4,o as t$2,r as n$1,v as t,y as t$3}from"./libs/remeda.mjs";import{a as GraphvizWasmAdapter,f as handleInitOptions,i as QueueGraphvizLayoter,l as NoFileSystem,m as logger$1,n as createLanguageServices$1,o as WithFileSystem,s as WithLikeC4ManualLayouts,t as GraphvizBinaryAdapter,u as NoLikeC4ManualLayouts,y as loggable}from"./GraphvizBinaryAdapter.mjs";import{t as defu}from"./libs/defu.mjs";import{r as resolve,t as basename}from"./libs/pathe.mjs";import{t as u}from"./libs/tinyrainbow.mjs";import{t as lib}from"./libs/json5.mjs";import{a as expandToNode,i as toString,n as CompositeGeneratorNode,r as NL,t as joinToNode}from"./libs/langium.mjs";import{o as joinURL}from"./libs/ufo.mjs";import{LikeC4Model}from"@likec4/core/model";import{invariant,isNonEmptyArray,memoizeProp,nonexhaustive}from"@likec4/core";import{pathToFileURL}from"url";import{RichText as RichText$1}from"@likec4/core/types";import{compareNatural}from"@likec4/core/utils";function createLanguageServices(r){let i=logger$1.getChild(`lang`),a=defu(r,{useFileSystem:!0,manualLayouts:!0,watch:!1,graphviz:`wasm`}),o=a.graphviz===`binary`;return i.info(`${u.dim(`layout`)} ${o?`binary`:`wasm`}`),createLanguageServices$1({...a.useFileSystem?{...WithFileSystem(a.watch),...a.manualLayouts?WithLikeC4ManualLayouts:NoLikeC4ManualLayouts}:{...NoFileSystem,...NoLikeC4ManualLayouts}},{likec4:{Layouter:()=>new QueueGraphvizLayoter({graphviz:o?new GraphvizBinaryAdapter:new GraphvizWasmAdapter})}})}async function fromWorkspace(r,i){let a=resolve(r);return memoizeProp(globalThis,`likec4:`+a,async()=>{let r=logger$1.getChild(`lang`),o=defu(i,{useFileSystem:!0,manualLayouts:!0,watch:!1});if(o.mcp)throw Error(`MCP server is not supported in this build`);let s=createLanguageServices(o),c={name:basename(a),uri:pathToFileURL(a).toString()},l=s.shared.workspace.WorkspaceManager;r.info(`${u.dim(`workspace:`)} ${a}`),l.initialize({capabilities:{},processId:null,rootUri:null,workspaceFolders:[c]}),await l.initializeWorkspace([c]);let d=s.shared.workspace.LangiumDocuments.userDocuments.toArray();if(d.length===0)throw r.error(`no LikeC4 sources found`),Error(`no LikeC4 sources found`);return r.info(`${u.dim(`workspace:`)} found ${d.length} source files`),handleInitOptions(s,logger$1,i)})}const logger=logger$1.getChild(`vite`);async function calcAdhocView({logger:r,likec4:i},a){r.info([u.green(`adhoc:view`),u.dim(`project:`),a.projectId].join(` `));let o=await i.views.adhocView(a.predicates,a.projectId);return r.info([u.green(`adhoc:view`),`✅`].join(` `)),o}function splitErrorMessage(r){let i=r.split(`
2
+ `),a=/^\s+at\s+/,o=i.findIndex(r=>a.test(r));return o===-1&&(o=1),{message:i.slice(0,o).join(`
3
+ `),stack:i.slice(o).join(`
4
+ `)}}function sendError(r,{name:i,error:a}){r.hot.send({type:`error`,err:{...splitErrorMessage(a),name:i??`LikeC4PluginError`,plugin:`vite-plugin-likec4`}})}async function updateView({logger:r,likec4:i},a){r.info([u.green(`view:onChange`),u.dim(`project`)+`:`,a.projectId,u.dim(`view`)+`:`,a.viewId,u.dim(`change`)+`:`,a.change.op].join(` `));let o=await i.editor.applyChange(a);if(!o.success){r.error(`Failed to apply view change:\n${o.error}`);let i=Error(o.error);throw i.stack=o.error,i}r.info([u.green(`view:onChange`),`✅`].join(` `))}function enablePluginRPC(i){let a=null,o=i.server;createBirpc({updateView:r=>updateView(i,r),calcAdhocView:r=>calcAdhocView(i,r)},{on:r=>o.hot.on(`likec4:rpc`,r),post:r=>o.hot.send(`likec4:rpc`,r),onFunctionError:(r,s)=>{i.logger.error(`RPC error in ${s}`,{error:r});let c=r.stack??r.message;try{a!==c&&(a=c,sendError(o,{name:r.name,error:c}))}catch(r){i.logger.error(`Failed to send error to client`,{error:r})}}})}const capitalizeFirstLetter$2=r=>r.charAt(0).toLocaleUpperCase()+r.slice(1),fqnName$2=r=>r.split(`.`).map(capitalizeFirstLetter$2).join(``),nodeName$2=r=>fqnName$2(r.parent?r.id.slice(r.parent.length+1):r.id),d2direction=({autoLayout:r})=>{switch(r.direction){case`TB`:return`down`;case`BT`:return`up`;case`LR`:return`right`;case`RL`:return`left`}},d2shape=({shape:r})=>{switch(r){case`queue`:case`cylinder`:case`rectangle`:case`document`:return r;case`person`:return`c4-person`;case`storage`:return`stored_data`;case`component`:case`bucket`:case`mobile`:case`browser`:return`rectangle`}};function generateD2(r){let a=r.$view,{nodes:o,edges:s}=a,c=new Map,l=(r,i)=>{let a=nodeName$2(r),s=(i?i+`.`:``)+a;c.set(r.id,s);let d=JSON.stringify(r.title),f=d2shape(r);return new CompositeGeneratorNode().append(a,`: {`,NL).indent({indentedChildren:i=>i.append(`label: `,d,NL).appendIf(f!==`rectangle`,`shape: `,f,NL).appendIf(r.children.length>0,NL,joinToNode(o.filter(i=>i.parent===r.id),r=>l(r,s))),indentation:2}).append(`}`,NL)},d=r=>new CompositeGeneratorNode().append(c.get(r.source),` -> `,c.get(r.target)).append(i=>r.label&&i.append(`: `,JSON.stringify(r.label)));return toString(new CompositeGeneratorNode().append(`direction: `,d2direction(a),NL,NL).append(joinToNode(o.filter(r=>e(r.parent)),r=>l(r),{appendNewLineIfNotEmpty:!0})).appendIf(s.length>0,NL,joinToNode(s,r=>d(r),{appendNewLineIfNotEmpty:!0})))}const capitalizeFirstLetter$1=r=>r.charAt(0).toLocaleUpperCase()+r.slice(1),fqnName$1=r=>r.split(`.`).map(capitalizeFirstLetter$1).join(``),nodeName$1=r=>fqnName$1(r.parent?r.id.slice(r.parent.length+1):r.id),toSingleQuotes=r=>r.replace(/\\?"/g,`'`),mmdshape=({shape:r,title:i})=>{let a=`label: ${JSON.stringify(i)}`;switch(r){case`queue`:return`@{ shape: horizontal-cylinder, ${a} }`;case`person`:return`@{ icon: "fa:user", shape: rounded, ${a} }`;case`storage`:return`@{ shape: disk, ${a} }`;case`cylinder`:return`@{ shape: cylinder, ${a} }`;case`mobile`:case`browser`:return`@{ shape: rounded, ${a} }`;case`bucket`:return`@{ shape: trap-t, ${a} }`;case`rectangle`:return`@{ shape: rectangle, ${a} }`;case`document`:return`@{ shape: doc, ${a} }`;case`component`:return`@{ shape: rectangle, ${a} }`;default:nonexhaustive(r)}};function generateMermaid(r){let a=r.$view,{nodes:o,edges:s}=a,c=new Map,l=(r,i)=>{let a=nodeName$1(r),s=(i?i+`.`:``)+a;c.set(r.id,s);let d=new CompositeGeneratorNode;if(r.children.length>0){let i=toSingleQuotes(r.title);d.append(`subgraph `,s,'["`',i,'`"]',NL).indent({indentedChildren:[joinToNode(o.filter(i=>i.parent===r.id),r=>l(r,s),{appendNewLineIfNotEmpty:!0})],indentation:2}).append(`end`,NL)}else d.append(s,mmdshape(r));return d},d=r=>new CompositeGeneratorNode().append(c.get(r.source),` -.`,r.label?' "`'+toSingleQuotes(r.label)+'`" .-':`-`,`> `,c.get(r.target));return toString(new CompositeGeneratorNode().append(`---`,NL,`title: ${JSON.stringify(toSingleQuotes(r.titleOrId))}`,NL,`---`,NL).append(`graph `,a.autoLayout.direction,NL).indent({indentedChildren:r=>{r.append(joinToNode(o.filter(r=>e(r.parent)),r=>l(r),{appendNewLineIfNotEmpty:!0})).appendIf(s.length>0,joinToNode(s,r=>d(r),{appendNewLineIfNotEmpty:!0}))},indentation:2}))}const capitalizeFirstLetter=r=>r.charAt(0).toLocaleUpperCase()+r.slice(1),fqnName=r=>r.split(/[.-]/).map(capitalizeFirstLetter).join(``),nodeName=r=>fqnName(r.parent?r.id.slice(r.parent.length+1):r.id),pumlColor=(r,i,a=`#3b82f6`)=>r?i(r)??a:a,pumlDirection=({autoLayout:r})=>{switch(r.direction){case`TB`:return`top to bottom`;case`BT`:return console.warn(`Bottom to top direction is not supported. Defaulting to top to bottom.`),`top to bottom`;case`LR`:return`left to right`;case`RL`:return console.warn(`Right to left direction is not supported. Defaulting to left to right.`),`left to right`}},pumlShape=({shape:r})=>{switch(r){case`queue`:case`rectangle`:case`person`:return r;case`storage`:case`cylinder`:return`database`;case`component`:return`component`;case`document`:case`mobile`:case`bucket`:case`browser`:return`rectangle`;default:nonexhaustive(r)}},escapeLabel=r=>e$1(r)?null:JSON.stringify(r).slice(1,-1).replace(/\\"/g,`"`);function generatePuml(r){let a=r.$view,o=r.$model.$styles.theme.colors,{nodes:c,edges:l}=a,d=r=>i=>i in o?o[i].elements[r]:void 0,f=r=>i=>i in o?o[i].relationships[r]:void 0,p=new Map,m=()=>new CompositeGeneratorNode().append(`title "`,r.titleOrId,`"`,NL).append(pumlDirection(a),` direction`,NL),h=()=>new CompositeGeneratorNode().append(`hide stereotype`,NL).append(`skinparam ranksep `,`60`,NL).append(`skinparam nodesep `,`30`,NL).append(`skinparam {`,NL).indent({indentedChildren:r=>r.append(`arrowFontSize `,`10`,NL).append(`defaultTextAlignment `,`center`,NL).append(`wrapWidth `,`200`,NL).append(`maxMessageSize `,`100`,NL).append(`shadowing `,`false`,NL),indentation:2}).append(`}`,NL),g=r=>{let i=pumlShape(r),a=fqnName(r.id);return new CompositeGeneratorNode().append(`skinparam `,i,`<<`,a,`>>`,`{`,NL).indent({indentedChildren:i=>i.append(`BackgroundColor `,pumlColor(r.color,d(`fill`)),NL).append(`FontColor `,pumlColor(r.color,d(`hiContrast`),`#FFFFFF`),NL).append(`BorderColor `,pumlColor(r.color,d(`stroke`)),NL),indentation:2}).append(`}`,NL)},_=r=>{let i=pumlShape(r),a=fqnName(r.id),o=escapeLabel(r.title)||nodeName(r),s=escapeLabel(r.technology);p.set(r.id,a);let c=RichText$1.from(r.description);return new CompositeGeneratorNode().append(i,` `).append(`"`).append(`==`,o).appendIf(!!s,`\\n<size:10>[`,s,`]</size>`).appendIf(c.nonEmpty,`\\n\\n`,escapeLabel(c.text)).append(`"`,` <<`,a,`>> `,`as `,a,NL)},v=r=>{let i=escapeLabel(r.title)||nodeName(r),a=fqnName(r.id);return p.set(r.id,a),new CompositeGeneratorNode().append(`rectangle "`,i,`" <<`,a,`>> as `,a,` {`,NL).indent({indentedChildren:i=>i.append(`skinparam `,`RectangleBorderColor<<`,a,`>> `,pumlColor(r.color,d(`fill`)),NL).append(`skinparam `,`RectangleFontColor<<`,a,`>> `,pumlColor(r.color,d(`fill`)),NL).append(`skinparam `,`RectangleBorderStyle<<`,a,`>> `,`dashed`,NL,NL).append(joinToNode(c.filter(i=>i.parent===r.id),r=>r.children.length>0?v(r):_(r))),indentation:2}).append(`}`,NL)},y=r=>{let i=r.technology||``,a=r.label||i,o=pumlColor(r.color,f(`line`),`#777777`),c=r=>`<color:${o}>${r.replaceAll(`"`,`'`)}`,l=new CompositeGeneratorNode().append(p.get(r.source),` .[`,o,`,thickness=2].> `,p.get(r.target));return(a||i)&&(l.append(` : `,a.split(`
5
+ `).map(r=>e$1(r)?r:c(r)).join(`\\n`)),i&&i!==a&&l.append(`\\n<size:8>[`,c(i),`]</size>`)),l.append(NL)};return toString(new CompositeGeneratorNode().append(`@startuml`,NL).append(m(),NL).append(h(),NL).append(joinToNode(c.filter(r=>r.children.length==0),r=>g(r),{appendNewLineIfNotEmpty:!0})).append(joinToNode(c.filter(r=>e(r.parent)),r=>r.children.length>0?v(r):_(r),{appendNewLineIfNotEmpty:!0})).appendIf(l.length>0,NL,joinToNode(l,r=>y(r),{appendNewLineIfNotEmpty:!0})).append(`@enduml`,NL))}function generateMatches(r,i=`.js`){return{matches:a=>{let{module:o,projectId:s}=a.match(/^likec4:plugin\/(?<projectId>.+)\/(?<module>.+)$/)?.groups??a.match(/^likec4:(?<module>.+)\/(?<projectId>.+)$/)?.groups??{};return!o||!s?null:(o.endsWith(i)&&(o=o.slice(0,-i.length)),o===r?s:null)},virtualId:a=>joinURL(`likec4:plugin`,a,r)+i}}const charMap={"<":`\\u003C`,">":`\\u003E`,"/":`\\u002F`,"\\":`\\\\`,"\b":`\\b`,"\f":`\\f`,"\n":`\\n`,"\r":`\\r`," ":`\\t`,"\0":`\\0`,"\u2028":`\\u2028`,"\u2029":`\\u2029`};function escapeUnsafeChars(r){return r.replace(/[<>\b\f\n\r\t\0\u2028\u2029\\]/g,r=>charMap[r])}function generateCombinedProjects(r,i){return{id:`likec4:${r}`,virtualId:`likec4:plugin/${r}.js`,async load({logger:a,projects:o}){return a.info(u.dim(`generating likec4:${r}`)),`
6
+ export let ${i}Fn = {
7
+ ${o.map(({id:i})=>{let a=escapeUnsafeChars(JSON.stringify(joinURL(`likec4:${r}`,i)));return`${JSON.stringify(i)}: () => import(${a})`}).join(`,
8
+ `)}
335
9
  }
336
10
 
337
- export async function ${fnName}(projectId) {
338
- let fn = ${fnName}Fn[projectId]
11
+ export async function ${i}(projectId) {
12
+ let fn = ${i}Fn[projectId]
339
13
  if (!fn) {
340
- const projects = Object.keys(${fnName}Fn)
14
+ const projects = Object.keys(${i}Fn)
341
15
  console.error('Unknown projectId: ' + projectId + ' (available: ' + projects + ')')
342
16
  if (projects.length === 0) {
343
17
  throw new Error('No projects found, invalid state')
344
18
  }
345
19
  projectId = projects[0]
346
20
  console.warn('Falling back to project: ' + projectId)
347
- fn = ${fnName}Fn[projectId]
21
+ fn = ${i}Fn[projectId]
348
22
  }
349
23
  return await fn()
350
24
  }
@@ -352,9 +26,9 @@ export async function ${fnName}(projectId) {
352
26
  if (import.meta.hot) {
353
27
  import.meta.hot.accept(md => {
354
28
  if (!import.meta.hot.data.$update) {
355
- import.meta.hot.data.$update = ${fnName}Fn
29
+ import.meta.hot.data.$update = ${i}Fn
356
30
  }
357
- const update = md.${fnName}Fn
31
+ const update = md.${i}Fn
358
32
  if (update) {
359
33
  Object.assign(import.meta.hot.data.$update, update)
360
34
  } else {
@@ -362,16 +36,7 @@ if (import.meta.hot) {
362
36
  }
363
37
  })
364
38
  }
365
- `;
366
- }
367
- };
368
- }
369
-
370
- //#endregion
371
- //#region src/vite-plugin/virtuals/d2.ts
372
- function code$8(model) {
373
- const out = new CompositeGeneratorNode();
374
- out.appendTemplate`
39
+ `}}}function code$8(r){let i=new CompositeGeneratorNode;return i.appendTemplate`
375
40
  /******************************************************************************
376
41
  * This file was generated
377
42
  * DO NOT EDIT MANUALLY!
@@ -380,38 +45,17 @@ function code$8(model) {
380
45
 
381
46
  export function d2Source(viewId) {
382
47
  switch (viewId) {
383
- `.appendNewLine().indent({
384
- indentation: 4,
385
- indentedChildren(indented) {
386
- indented.append(joinToNode([...model.views()], (view) => expandToNode`
387
- case ${JSON.stringify(view.id)}: {
388
- return ${JSON.stringify(generateD2(view))}
48
+ `.appendNewLine().indent({indentation:4,indentedChildren(i){i.append(joinToNode([...r.views()],r=>expandToNode`
49
+ case ${JSON.stringify(r.id)}: {
50
+ return ${JSON.stringify(generateD2(r))}
389
51
  }
390
- `, { appendNewLineIfNotEmpty: true })).appendTemplate`
52
+ `,{appendNewLineIfNotEmpty:!0})).appendTemplate`
391
53
  default: {
392
54
  throw new Error('Unknown viewId: ' + viewId)
393
55
  }
394
- `;
395
- }
396
- }).append(NL, " }", NL).appendTemplate`
56
+ `}}).append(NL,` }`,NL).appendTemplate`
397
57
  }
398
- `.append(NL, NL);
399
- return toString(out);
400
- }
401
- const projectD2Module = {
402
- ...generateMatches("d2"),
403
- async load({ likec4, project, logger }) {
404
- logger.info(u.dim(`generating likec4:d2/${project.id}`));
405
- return code$8(await likec4.computedModel(project.id));
406
- }
407
- };
408
- const d2Module = generateCombinedProjects("d2", "loadD2Sources");
409
-
410
- //#endregion
411
- //#region src/vite-plugin/virtuals/dot.ts
412
- function code$7(sources) {
413
- const out = new CompositeGeneratorNode();
414
- out.appendTemplate`
58
+ `.append(NL,NL),toString(i)}const projectD2Module={...generateMatches(`d2`),async load({likec4:r,project:i,logger:a}){return a.info(u.dim(`generating likec4:d2/${i.id}`)),code$8(await r.computedModel(i.id))}},d2Module=generateCombinedProjects(`d2`,`loadD2Sources`);function code$7(r){let i=new CompositeGeneratorNode;return i.appendTemplate`
415
59
  /******************************************************************************
416
60
  * This file was generated
417
61
  * DO NOT EDIT MANUALLY!
@@ -420,77 +64,35 @@ function code$7(sources) {
420
64
 
421
65
  export function dotSource(viewId) {
422
66
  switch (viewId) {
423
- `.appendNewLine().indent({
424
- indentation: 4,
425
- indentedChildren(indented) {
426
- indented.append(joinToNode(Object.keys(sources), (key) => expandToNode`
427
- case ${JSON.stringify(key)}: {
428
- return ${JSON.stringify(sources[key].dot)}
67
+ `.appendNewLine().indent({indentation:4,indentedChildren(i){i.append(joinToNode(Object.keys(r),i=>expandToNode`
68
+ case ${JSON.stringify(i)}: {
69
+ return ${JSON.stringify(r[i].dot)}
429
70
  }
430
- `, { appendNewLineIfNotEmpty: true })).appendTemplate`
71
+ `,{appendNewLineIfNotEmpty:!0})).appendTemplate`
431
72
  default: {
432
73
  throw new Error('Unknown viewId: ' + viewId)
433
74
  }
434
- `;
435
- }
436
- }).append(NL, " }", NL).appendTemplate`
75
+ `}}).append(NL,` }`,NL).appendTemplate`
437
76
  }
438
77
 
439
78
  export function svgSource(viewId) {
440
79
  switch (viewId) {
441
- `.appendNewLine().indent({
442
- indentation: 4,
443
- indentedChildren(indented) {
444
- indented.append(joinToNode(Object.keys(sources), (key) => expandToNode`
445
- case ${JSON.stringify(key)}: {
446
- return ${JSON.stringify(sources[key].svg)}
80
+ `.appendNewLine().indent({indentation:4,indentedChildren(i){i.append(joinToNode(Object.keys(r),i=>expandToNode`
81
+ case ${JSON.stringify(i)}: {
82
+ return ${JSON.stringify(r[i].svg)}
447
83
  }
448
- `, { appendNewLineIfNotEmpty: true })).appendTemplate`
84
+ `,{appendNewLineIfNotEmpty:!0})).appendTemplate`
449
85
  default: {
450
86
  throw new Error('Unknown viewId: ' + viewId)
451
87
  }
452
- `;
453
- }
454
- }).append(NL, " }", NL, "}", NL, NL);
455
- return toString(out);
456
- }
457
- const projectDotSourcesModule = {
458
- ...generateMatches("dot"),
459
- async load({ likec4, project, logger }) {
460
- logger.info(u.dim(`generating likec4:dot/${project.id}`));
461
- return code$7(t(await likec4.views.viewsAsGraphvizOut(project.id), ({ id, svg, dot }) => [id, {
462
- dot,
463
- svg
464
- }]));
465
- }
466
- };
467
- const dotModule = generateCombinedProjects("dot", "loadDotSources");
468
-
469
- //#endregion
470
- //#region src/vite-plugin/virtuals/icons.ts
471
- function code$6(views) {
472
- const { imports, cases } = t$1(views.flatMap((v) => v.nodes.map((n) => n.icon)), n((s) => e$2(s) && !(s.toLowerCase().startsWith("http:") || s.toLowerCase().startsWith("https:"))), n$1(), t$2(compareNatural)).reduce((acc, s, i) => {
473
- const isLocalImage = s.startsWith("file:");
474
- const Component = "Icon" + i.toString().padStart(2, "0");
475
- if (isLocalImage) {
476
- acc.imports.push(`import ${Component} from '${s}?inline'`);
477
- acc.cases.push(` '${s}': () => jsx('img', { src: ${Component} })`);
478
- return acc;
479
- }
480
- const [group, icon] = s.split(":");
481
- acc.imports.push(`import ${Component} from '@likec4/icons/${group}/${icon}'`);
482
- acc.cases.push(` '${group}:${icon}': ${Component}`);
483
- return acc;
484
- }, {
485
- imports: [],
486
- cases: []
487
- });
488
- return `
88
+ `}}).append(NL,` }`,NL,`}`,NL,NL),toString(i)}const projectDotSourcesModule={...generateMatches(`dot`),async load({likec4:r,project:i,logger:a}){return a.info(u.dim(`generating likec4:dot/${i.id}`)),code$7(t(await r.views.viewsAsGraphvizOut(i.id),({id:r,svg:i,dot:a})=>[r,{dot:a,svg:i}]))}},dotModule=generateCombinedProjects(`dot`,`loadDotSources`);function code$6(r){let{imports:i,cases:a}=t$1(r.flatMap(r=>r.nodes.map(r=>r.icon)),n(r=>e$2(r)&&!(r.toLowerCase().startsWith(`http:`)||r.toLowerCase().startsWith(`https:`))),n$1(),t$2(compareNatural)).reduce((r,i,a)=>{let o=i.startsWith(`file:`),s=`Icon`+a.toString().padStart(2,`0`);if(o)return r.imports.push(`import ${s} from '${i}?inline'`),r.cases.push(` '${i}': () => jsx('img', { src: ${s} })`),r;let[c,l]=i.split(`:`);return r.imports.push(`import ${s} from '@likec4/icons/${c}/${l}'`),r.cases.push(` '${c}:${l}': ${s}`),r},{imports:[],cases:[]});return`
489
89
  import { jsx } from 'react/jsx-runtime'
490
- ${imports.join("\n")}
90
+ ${i.join(`
91
+ `)}
491
92
 
492
93
  const Icons = {
493
- ${cases.join(",\n")}
94
+ ${a.join(`,
95
+ `)}
494
96
  }
495
97
  export function IconRenderer({ node, ...props }) {
496
98
  const IconComponent = Icons[node.icon ?? '']
@@ -499,55 +101,44 @@ export function IconRenderer({ node, ...props }) {
499
101
  }
500
102
  return jsx(IconComponent, props)
501
103
  }
502
- `;
503
- }
504
- const projectIconsModule = {
505
- ...generateMatches("icons", ".jsx"),
506
- async load({ likec4, project, logger }) {
507
- logger.info(u.dim(`generating likec4:icons/${project.id}`));
508
- return code$6(await likec4.views.computedViews(project.id));
509
- }
510
- };
511
- const iconsModule = {
512
- id: "likec4:icons",
513
- virtualId: "likec4:plugin/icons.jsx",
514
- async load({ projects, logger }) {
515
- logger.info(u.dim(`generating likec4:icons`));
516
- const { imports, cases } = projects.reduce((acc, { id }, i) => {
517
- const Component = "Icons" + i.toString().padStart(2, "0");
518
- const pkg = joinURL("likec4:icons", id);
519
- acc.imports.push(`import { IconRenderer as ${Component} } from ${JSON.stringify(pkg)}`);
520
- acc.cases.push(` case ${JSON.stringify(id)}: return ${Component}`);
521
- return acc;
522
- }, {
523
- imports: [],
524
- cases: []
525
- });
526
- return `
527
- import { jsx } from 'react/jsx-runtime'
528
- ${imports.join("\n")}
104
+ `}const projectIconsModule={...generateMatches(`icons`,`.jsx`),async load({likec4:r,project:i,logger:a}){return a.info(u.dim(`generating likec4:icons/${i.id}`)),code$6(await r.views.computedViews(i.id))}},iconsModule={id:`likec4:icons`,virtualId:`likec4:plugin/icons.jsx`,async load({projects:r,logger:i}){return i.info(u.dim(`generating likec4:icons`)),`
105
+ import { jsx } from 'react/jsx-runtime'
106
+ import { lazy, Suspense } from 'react'
107
+ export let ProjectIconsRegistry = {
108
+ ${r.map(r=>({id:JSON.stringify(r.id),pkg:JSON.stringify(joinURL(`likec4:icons`,r.id))})).map(({id:r,pkg:i})=>`${r}: lazy(() => import(${i}).then(m => ({default: m.IconRenderer})))`).join(`,
109
+ `)}
110
+ }
111
+
529
112
 
530
- function getProjectIcons(projectId) {
531
- switch (projectId) {
532
- ${cases.join("\n")}
533
- default:
534
- throw new Error('Unknown projectId: ' + projectId)
113
+ export function getProjectIcons(projectId) {
114
+ let fn = ProjectIconsRegistry[projectId]
115
+ if (!fn) {
116
+ const projects = Object.keys(ProjectIconsRegistry)
117
+ console.error('Unknown projectId: ' + projectId + ' (available: ' + projects + ')')
118
+ if (projects.length === 0) {
119
+ throw new Error('No projects found, invalid state')
120
+ }
121
+ projectId = projects[0]
122
+ console.warn('Falling back to project: ' + projectId)
123
+ fn = ProjectIconsRegistry[projectId]
535
124
  }
125
+ return (props) => jsx(Suspense, { children: jsx(fn, props) })
536
126
  }
537
127
 
538
- export function ProjectIcons({ projectId, ...props }) {
539
- const IconComponent = getProjectIcons(projectId)
540
- return jsx(IconComponent, props)
541
- }
542
- `;
543
- }
544
- };
545
-
546
- //#endregion
547
- //#region src/vite-plugin/virtuals/mmd.ts
548
- function code$5(model) {
549
- const out = new CompositeGeneratorNode();
550
- out.appendTemplate`
128
+ if (import.meta.hot) {
129
+ import.meta.hot.accept(md => {
130
+ if (!import.meta.hot.data.$update) {
131
+ import.meta.hot.data.$update = ProjectIconsRegistry
132
+ }
133
+ const update = md.ProjectIconsRegistry
134
+ if (update) {
135
+ Object.assign(import.meta.hot.data.$update, update)
136
+ } else {
137
+ import.meta.hot.invalidate()
138
+ }
139
+ })
140
+ }
141
+ `}};function code$5(r){let i=new CompositeGeneratorNode;return i.appendTemplate`
551
142
  /******************************************************************************
552
143
  * This file was generated
553
144
  * DO NOT EDIT MANUALLY!
@@ -556,41 +147,21 @@ function code$5(model) {
556
147
 
557
148
  export function mmdSource(viewId) {
558
149
  switch (viewId) {
559
- `.appendNewLine().indent({
560
- indentation: 4,
561
- indentedChildren(indented) {
562
- indented.append(joinToNode([...model.views()], (view) => expandToNode`
563
- case ${JSON.stringify(view.id)}: {
564
- return ${JSON.stringify(generateMermaid(view))}
150
+ `.appendNewLine().indent({indentation:4,indentedChildren(i){i.append(joinToNode([...r.views()],r=>expandToNode`
151
+ case ${JSON.stringify(r.id)}: {
152
+ return ${JSON.stringify(generateMermaid(r))}
565
153
  }
566
- `, { appendNewLineIfNotEmpty: true })).appendTemplate`
154
+ `,{appendNewLineIfNotEmpty:!0})).appendTemplate`
567
155
  default: {
568
156
  throw new Error('Unknown viewId: ' + viewId)
569
157
  }
570
- `;
571
- }
572
- }).append(NL, " }", NL).appendTemplate`
158
+ `}}).append(NL,` }`,NL).appendTemplate`
573
159
  }
574
160
 
575
- `.append(NL, NL);
576
- return toString(out);
577
- }
578
- const projectMmdSourcesModule = {
579
- ...generateMatches("mmd"),
580
- async load({ likec4, project, logger }) {
581
- logger.info(u.dim(`generating virtual:likec4/mmd/${project.id}`));
582
- return code$5(await likec4.computedModel(project.id));
583
- }
584
- };
585
- const mmdModule = generateCombinedProjects("mmd", "loadMmdSources");
586
-
587
- //#endregion
588
- //#region src/vite-plugin/virtuals/model.ts
589
- var import_lib = /* @__PURE__ */ __toESM(require_lib(), 1);
590
- const projectModelCode = (model) => `
161
+ `.append(NL,NL),toString(i)}const projectMmdSourcesModule={...generateMatches(`mmd`),async load({likec4:r,project:i,logger:a}){return a.info(u.dim(`generating virtual:likec4/mmd/${i.id}`)),code$5(await r.computedModel(i.id))}},mmdModule=generateCombinedProjects(`mmd`,`loadMmdSources`),projectModelCode=r=>`
591
162
  import { createHooksForModel, atom } from 'likec4/vite-plugin/internal'
592
163
 
593
- export const $likec4data = atom(${import_lib.default.stringify(model.$data)})
164
+ export const $likec4data = atom(${lib.stringify(r.$data)})
594
165
 
595
166
  export const {
596
167
  updateModel,
@@ -613,23 +184,11 @@ if (import.meta.hot) {
613
184
  }
614
185
  })
615
186
  }
616
- `;
617
- const projectModelModule = {
618
- ...generateMatches("model"),
619
- async load({ likec4, project, logger }) {
620
- logger.info(u.dim(`generating likec4:model/${project.id}`));
621
- return projectModelCode(await likec4.layoutedModel(project.id));
622
- }
623
- };
624
- const modelModule = generateCombinedProjects("model", "loadModel");
625
-
626
- //#endregion
627
- //#region src/vite-plugin/virtuals/projects.ts
628
- const code$4 = (projects) => `
187
+ `,projectModelModule={...generateMatches(`model`),async load({likec4:r,project:i,logger:a}){return a.info(u.dim(`generating likec4:model/${i.id}`)),projectModelCode(await r.layoutedModel(i.id))}},modelModule=generateCombinedProjects(`model`,`loadModel`),code$4=r=>`
629
188
  import { atom, useStore } from 'likec4/vite-plugin/internal'
630
189
 
631
- export const isSingleProject = ${projects.length === 1};
632
- export const projects = ${import_lib.default.stringify(projects, null, 2)};
190
+ export const isSingleProject = ${r.length===1};
191
+ export const projects = ${lib.stringify(r,null,2)};
633
192
 
634
193
  export const $projects = atom([...projects])
635
194
 
@@ -655,22 +214,10 @@ if (import.meta.hot) {
655
214
  }
656
215
  })
657
216
  }
658
- `;
659
- const projectsModule = {
660
- id: "likec4:projects",
661
- virtualId: "likec4:plugin/projects.js",
662
- async load({ logger, projects }) {
663
- logger.info(u.dim("generating likec4:projects"));
664
- return code$4(t$3(projects, t$4(["id", "title"])));
665
- }
666
- };
667
-
668
- //#endregion
669
- //#region src/vite-plugin/virtuals/projectsOverview.ts
670
- const code$3 = (view) => `
217
+ `,projectsModule={id:`likec4:projects`,virtualId:`likec4:plugin/projects.js`,async load({logger:r,projects:i}){return r.info(u.dim(`generating likec4:projects`)),code$4(t$3(i,t$4([`id`,`title`])))}},code$3=r=>`
671
218
  import { atom, useStore } from 'likec4/vite-plugin/internal'
672
219
 
673
- export const $viewdata = atom(${import_lib.default.stringify(view)})
220
+ export const $viewdata = atom(${lib.stringify(r)})
674
221
 
675
222
  export function useLikeC4ProjectsOverview() {
676
223
  return useStore($viewdata)
@@ -681,7 +228,7 @@ if (import.meta.hot) {
681
228
  if (!import.meta.hot.data.$viewdata) {
682
229
  import.meta.hot.data.$viewdata = $viewdata
683
230
  }
684
- const update = md.$viewdata?.get()
231
+ const update = md.$viewdata?.value
685
232
  if (update) {
686
233
  import.meta.hot.data.$viewdata.set(update)
687
234
  } else {
@@ -689,27 +236,11 @@ if (import.meta.hot) {
689
236
  }
690
237
  })
691
238
  }
692
- `;
693
- const noProjects = () => `
239
+ `,noProjects=()=>`
694
240
  export function useLikeC4ProjectsOverview() {
695
241
  throw new Error('No projects overview available for this workspace: single project mode is enabled')
696
242
  }
697
- `;
698
- const projectsOverviewModule = {
699
- id: "likec4:projects-overview",
700
- virtualId: "likec4:plugin/projects-overview.js",
701
- async load({ logger, projects, likec4 }) {
702
- if (projects.length < 2) return noProjects();
703
- logger.info(u.dim("generating likec4:projects-overview"));
704
- return code$3(await likec4.projectsOverview());
705
- }
706
- };
707
-
708
- //#endregion
709
- //#region src/vite-plugin/virtuals/puml.ts
710
- function code$2(model) {
711
- const out = new CompositeGeneratorNode();
712
- out.appendTemplate`
243
+ `,projectsOverviewModule={id:`likec4:projects-overview`,virtualId:`likec4:plugin/projects-overview.js`,async load({logger:r,projects:i,likec4:a}){return i.length<2?noProjects():(r.info(u.dim(`generating likec4:projects-overview`)),code$3(await a.projectsOverview()))}};function code$2(r){let i=new CompositeGeneratorNode;return i.appendTemplate`
713
244
  /******************************************************************************
714
245
  * This file was generated
715
246
  * DO NOT EDIT MANUALLY!
@@ -718,41 +249,22 @@ function code$2(model) {
718
249
 
719
250
  export function pumlSource(viewId) {
720
251
  switch (viewId) {
721
- `.appendNewLine().indent({
722
- indentation: 4,
723
- indentedChildren(indented) {
724
- indented.append(joinToNode([...model.views()], (view) => expandToNode`
725
- case ${JSON.stringify(view.id)}: {
726
- return ${JSON.stringify(generatePuml(view))}
252
+ `.appendNewLine().indent({indentation:4,indentedChildren(i){i.append(joinToNode([...r.views()],r=>expandToNode`
253
+ case ${JSON.stringify(r.id)}: {
254
+ return ${JSON.stringify(generatePuml(r))}
727
255
  }
728
- `, { appendNewLineIfNotEmpty: true })).appendTemplate`
256
+ `,{appendNewLineIfNotEmpty:!0})).appendTemplate`
729
257
  default: {
730
258
  throw new Error('Unknown viewId: ' + viewId)
731
259
  }
732
- `;
733
- }
734
- }).append(NL, " }", NL).appendTemplate`
260
+ `}}).append(NL,` }`,NL).appendTemplate`
735
261
  }
736
- `.append(NL, NL);
737
- return toString(out);
738
- }
739
- const projectPumlModule = {
740
- ...generateMatches("puml"),
741
- async load({ likec4, project, logger }) {
742
- logger.info(u.dim(`generating likec4:puml/${project.id}`));
743
- return code$2(await likec4.computedModel(project.id));
744
- }
745
- };
746
- const pumlModule = generateCombinedProjects("puml", "loadPumlSources");
747
-
748
- //#endregion
749
- //#region src/vite-plugin/virtuals/react.ts
750
- const projectCode = (id) => `
262
+ `.append(NL,NL),toString(i)}const projectPumlModule={...generateMatches(`puml`),async load({likec4:r,project:i,logger:a}){return a.info(u.dim(`generating likec4:puml/${i.id}`)),code$2(await r.computedModel(i.id))}},pumlModule=generateCombinedProjects(`puml`,`loadPumlSources`),projectCode=r=>`
751
263
  import { jsx as _jsx } from "react/jsx-runtime";
752
264
  import { LikeC4ModelProvider as Provider, LikeC4View as GenericView, ReactLikeC4 as GenericReactLikeC4 } from 'likec4/react';
753
- import { IconRenderer } from 'likec4:icons/${id}'
265
+ import { IconRenderer } from 'likec4:icons/${r}'
754
266
 
755
- import { useLikeC4Model, useLikeC4Views, useLikeC4View } from 'likec4:model/${id}'
267
+ import { useLikeC4Model, useLikeC4Views, useLikeC4View } from 'likec4:model/${r}'
756
268
 
757
269
  export function LikeC4ModelProvider({ children }) {
758
270
  const likeC4Model = useLikeC4Model()
@@ -770,27 +282,7 @@ export {
770
282
  useLikeC4View,
771
283
  useLikeC4Views
772
284
  }
773
- `;
774
- const projectReactModule = {
775
- ...generateMatches("react"),
776
- async load({ project, logger }) {
777
- logger.info(u.dim(`generating likec4:react/${project.id}`));
778
- return projectCode(project.id);
779
- }
780
- };
781
- const singleProjectReactModule = {
782
- id: "likec4:react",
783
- virtualId: "likec4:plugin/react.js",
784
- async load({ logger, projects }) {
785
- const project = n$2(projects);
786
- logger.info(u.dim("generating likec4:react for") + " " + project.id);
787
- return projectCode(project.id);
788
- }
789
- };
790
-
791
- //#endregion
792
- //#region src/vite-plugin/virtuals/rpc.ts
793
- const code$1 = `
285
+ `,projectReactModule={...generateMatches(`react`),async load({project:r,logger:i}){return i.info(u.dim(`generating likec4:react/${r.id}`)),projectCode(r.id)}},singleProjectReactModule={id:`likec4:react`,virtualId:`likec4:plugin/react.js`,async load({logger:r,projects:i}){let a=n$2(i);return r.info(u.dim(`generating likec4:react for`)+` `+a.id),projectCode(a.id)}},rpcModule={id:`likec4:rpc`,virtualId:`likec4:plugin/rpc.js`,async load({logger:r}){return r.info(u.dim(`generating likec4:rpc`)),`
794
286
  import { createRpc } from 'likec4/vite-plugin/internal'
795
287
 
796
288
  export const isRpcAvailable = !!import.meta.hot
@@ -817,180 +309,14 @@ export const likec4rpc = rpc ?? {
817
309
  throw new Error('likec4rpc.calcAdhocView is not available in production')
818
310
  },
819
311
  }
820
- `;
821
- const rpcModule = {
822
- id: "likec4:rpc",
823
- virtualId: "likec4:plugin/rpc.js",
824
- async load({ logger }) {
825
- logger.info(u.dim("generating likec4:rpc"));
826
- return code$1;
827
- }
828
- };
829
-
830
- //#endregion
831
- //#region src/vite-plugin/virtuals/single-project.ts
832
- const code = (id) => `
833
- export { IconRenderer } from 'likec4:icons/${id}'
312
+ `}},code=r=>`
313
+ export { IconRenderer } from 'likec4:icons/${r}'
834
314
  export {
835
315
  $likec4data,
836
316
  $likec4model,
837
317
  useLikeC4Model,
838
318
  useLikeC4Views,
839
319
  useLikeC4View
840
- } from 'likec4:model/${id}'
841
- export const projectId = ${JSON.stringify(id)}
842
- `;
843
- const singleProjectModule = {
844
- id: "likec4:single-project",
845
- virtualId: "likec4:plugin/single-project.js",
846
- async load({ logger, projects }) {
847
- const project = n$2(projects);
848
- logger.info(u.dim("generating likec4:single-project for") + " " + project.id);
849
- return code(project.id);
850
- }
851
- };
852
-
853
- //#endregion
854
- //#region src/vite-plugin/plugin.ts
855
- const hmrProjectVirtuals = [
856
- projectModelModule,
857
- projectIconsModule,
858
- projectD2Module,
859
- projectDotSourcesModule,
860
- projectMmdSourcesModule,
861
- projectPumlModule
862
- ];
863
- const projectVirtuals = [...hmrProjectVirtuals, projectReactModule];
864
- const virtuals = [
865
- projectsModule,
866
- modelModule,
867
- projectsOverviewModule,
868
- singleProjectModule,
869
- singleProjectReactModule,
870
- d2Module,
871
- dotModule,
872
- mmdModule,
873
- pumlModule,
874
- iconsModule,
875
- rpcModule
876
- ];
877
- function LikeC4VitePlugin({ environments, ...opts }) {
878
- let logger;
879
- let likec4;
880
- let assetsDir;
881
- let shouldDisposeOnStop = opts.watch ?? false;
882
- return {
883
- name: "vite-plugin-likec4",
884
- applyToEnvironment(env) {
885
- return environments ? environments.includes(env.name) : true;
886
- },
887
- async configResolved(config) {
888
- config.server.hmr;
889
- logger = config.logger;
890
- if (opts.languageServices) likec4 = opts.languageServices;
891
- else {
892
- const watch = shouldDisposeOnStop = opts.watch ?? config.mode === "development";
893
- likec4 = (await LikeC4.fromWorkspace(opts.workspace ?? config.root, {
894
- logger,
895
- graphviz: opts.graphviz ?? "wasm",
896
- printErrors: opts.printErrors ?? true,
897
- throwIfInvalid: opts.throwIfInvalid ?? false,
898
- watch
899
- })).languageServices;
900
- }
901
- assetsDir = likec4.workspaceUri.fsPath;
902
- },
903
- resolveId(id) {
904
- for (const module of projectVirtuals) {
905
- const projectId = module.matches(id);
906
- if (projectId) return module.virtualId(projectId);
907
- }
908
- for (const module of virtuals) if (module.id === id) return module.virtualId;
909
- return null;
910
- },
911
- async load(id) {
912
- for (const module of projectVirtuals) {
913
- const projectId = module.matches(id);
914
- if (projectId) {
915
- const project = likec4.project(projectId);
916
- return await module.load({
917
- logger,
918
- likec4,
919
- project,
920
- assetsDir
921
- });
922
- }
923
- }
924
- for (const module of virtuals) if (module.virtualId === id) {
925
- const projects = likec4.projects();
926
- invariant(isNonEmptyArray(projects));
927
- return await module.load({
928
- logger,
929
- likec4,
930
- projects,
931
- assetsDir
932
- });
933
- }
934
- return null;
935
- },
936
- configureServer(server) {
937
- const hotChannel = server.hot;
938
- enablePluginRPC.call(this, {
939
- logger,
940
- likec4,
941
- server
942
- });
943
- const readProjects = () => t$3(likec4.projects(), (p) => ({
944
- id: p.id,
945
- title: p.title,
946
- folder: p.folder.fsPath
947
- }));
948
- let _projects = readProjects();
949
- const reloadModule = async (id) => {
950
- const md = server.moduleGraph.getModuleById(id);
951
- if (md && md.importers.size > 0) try {
952
- await server.reloadModule(md);
953
- } catch (err) {
954
- logger.error(err);
955
- }
956
- };
957
- likec4.builder.onModelParsed(async () => {
958
- const [error] = likec4.getErrors();
959
- if (error) {
960
- const [message, ...stack] = error.message.split("\n");
961
- hotChannel.send({
962
- type: "error",
963
- err: {
964
- name: "LikeC4ValidationError",
965
- message,
966
- stack: stack.join("\n"),
967
- plugin: "vite-plugin-likec4",
968
- loc: {
969
- file: error.sourceFsPath,
970
- line: error.line,
971
- column: error.range.start.character + 1
972
- }
973
- }
974
- });
975
- return;
976
- }
977
- const _updated = readProjects();
978
- if (!t$5(_updated, _projects)) {
979
- _projects = _updated;
980
- await reloadModule(projectsModule.virtualId);
981
- await reloadModule(iconsModule.virtualId);
982
- await reloadModule(modelModule.virtualId);
983
- if (_projects.length > 1) await reloadModule(projectsOverviewModule.virtualId);
984
- return;
985
- }
986
- for (const project of _projects) for (const projectModule of hmrProjectVirtuals) await reloadModule(projectModule.virtualId(project.id));
987
- });
988
- },
989
- async buildEnd() {
990
- if (shouldDisposeOnStop) await likec4.dispose();
991
- }
992
- };
993
- }
994
-
995
- //#endregion
996
- export { generateD2 as i, generatePuml as n, generateMermaid as r, LikeC4VitePlugin as t };
320
+ } from 'likec4:model/${r}'
321
+ export const projectId = ${JSON.stringify(r)}
322
+ `,singleProjectModule={id:`likec4:single-project`,virtualId:`likec4:plugin/single-project.js`,async load({logger:r,projects:i}){let a=n$2(i);return r.info(u.dim(`generating likec4:single-project for`)+` `+a.id),code(a.id)}},hmrProjectVirtuals=[projectModelModule,projectIconsModule,projectD2Module,projectDotSourcesModule,projectMmdSourcesModule,projectPumlModule],projectVirtuals=[...hmrProjectVirtuals,projectReactModule],virtuals=[projectsModule,modelModule,projectsOverviewModule,singleProjectModule,singleProjectReactModule,d2Module,dotModule,mmdModule,pumlModule,iconsModule,rpcModule];function LikeC4VitePlugin({environments:r,...i}){let o,s,c=i.watch??!1;return{name:`vite-plugin-likec4`,applyToEnvironment(i){return r?r.includes(i.name):!0},async configResolved(r){if(i.languageServices)o=i.languageServices;else{let a=c=i.watch??r.mode===`development`;o=(await fromWorkspace(i.workspace??r.root,{graphviz:i.graphviz??`wasm`,watch:a})).languageServices}s=o.workspaceUri.fsPath},resolveId(r){for(let i of projectVirtuals){let a=i.matches(r);if(a)return i.virtualId(a)}for(let i of virtuals)if(i.id===r)return i.virtualId;return null},async load(r){for(let i of projectVirtuals){let a=i.matches(r);if(a){let r=o.project(a);return await i.load({logger,likec4:o,project:r,assetsDir:s})}}for(let i of virtuals)if(i.virtualId===r){let r=o.projects();return invariant(isNonEmptyArray(r)),await i.load({logger,likec4:o,projects:r,assetsDir:s})}return null},configureServer(r){let i=r.hot;enablePluginRPC.call(this,{logger,likec4:o,server:r});let s=()=>t$3(o.projects(),r=>({id:r.id,title:r.title,folder:r.folder.toString()})),c=s(),l=async i=>{let a=r.moduleGraph.getModuleById(i);if(a&&a.importers.size>0)try{await r.reloadModule(a)}catch(r){logger.error(loggable(r))}};o.builder.onModelParsed(async()=>{let[r]=o.getErrors();if(r){i.send({type:`error`,err:{name:`LikeC4ValidationError`,...splitErrorMessage(r.message),plugin:`vite-plugin-likec4`,loc:{file:r.sourceFsPath,line:r.line,column:r.range.start.character+1}}});return}let d=s();if(!t$5(d,c)){c=d,await l(projectsModule.virtualId),await l(iconsModule.virtualId),await l(modelModule.virtualId),c.length>1&&await l(projectsOverviewModule.virtualId);return}for(let r of d)for(let i of hmrProjectVirtuals)await l(i.virtualId(r.id))})},async buildEnd(){c&&await o.dispose()}}}export{fromWorkspace as a,generateD2 as i,generatePuml as n,generateMermaid as r,LikeC4VitePlugin as t};