likec4 1.56.0 → 1.57.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 (154) hide show
  1. package/__app__/chunks/AIChat2.mjs +2 -0
  2. package/__app__/chunks/DiagramActorProvider.mjs +4 -4
  3. package/__app__/chunks/EmbedPage.mjs +1 -0
  4. package/__app__/chunks/ExportPage.mjs +2 -0
  5. package/__app__/chunks/LikeC4Diagram.mjs +5 -5
  6. package/__app__/chunks/LikeC4Styles.mjs +11 -11
  7. package/__app__/chunks/Markdown.mjs +1 -0
  8. package/__app__/chunks/NavigationPanel.mjs +1 -1
  9. package/__app__/chunks/ViewReact.mjs +1 -1
  10. package/__app__/chunks/adhoc-editor.mjs +1 -1
  11. package/__app__/chunks/aichat.mjs +1 -0
  12. package/__app__/chunks/box.mjs +1 -0
  13. package/__app__/chunks/create-style-context.mjs +1 -0
  14. package/__app__/chunks/css.mjs +1 -0
  15. package/__app__/chunks/factory.mjs +1 -0
  16. package/__app__/chunks/hooks.mjs +1 -1
  17. package/__app__/chunks/hstack.mjs +1 -0
  18. package/__app__/chunks/libs/@dagrejs/dagre.mjs +1 -1
  19. package/__app__/chunks/libs/@floating-ui/core.mjs +1 -1
  20. package/__app__/chunks/libs/@floating-ui/dom.mjs +1 -1
  21. package/__app__/chunks/libs/@floating-ui/react.mjs +1 -1
  22. package/__app__/chunks/libs/@mantine/core.mjs +24 -24
  23. package/__app__/chunks/libs/@mantine/hooks.mjs +1 -1
  24. package/__app__/chunks/libs/@nanostores/react.mjs +1 -1
  25. package/__app__/chunks/libs/@react-hookz/web.mjs +1 -1
  26. package/__app__/chunks/libs/@tabler/icons-react.mjs +347 -4
  27. package/__app__/chunks/libs/@tanstack/ai-client.mjs +2 -0
  28. package/__app__/chunks/libs/@tanstack/ai-react-ui.mjs +1 -0
  29. package/__app__/chunks/libs/@tanstack/ai-react.mjs +1 -0
  30. package/__app__/chunks/libs/@tanstack/ai.mjs +2 -0
  31. package/__app__/chunks/libs/@tanstack/history.mjs +1 -1
  32. package/__app__/chunks/libs/@tanstack/react-router.mjs +3 -3
  33. package/__app__/chunks/libs/@tanstack/router-core.mjs +1 -1
  34. package/__app__/chunks/libs/@xstate/react.mjs +1 -1
  35. package/__app__/chunks/libs/@xstate/store.mjs +1 -1
  36. package/__app__/chunks/libs/@xyflow/react.mjs +3 -3
  37. package/__app__/chunks/libs/@zag-js/anatomy.mjs +1 -1
  38. package/__app__/chunks/libs/@zag-js/collection.mjs +1 -1
  39. package/__app__/chunks/libs/@zag-js/core.mjs +1 -1
  40. package/__app__/chunks/libs/@zag-js/react.mjs +1 -1
  41. package/__app__/chunks/libs/@zag-js/tree-view.mjs +1 -1
  42. package/__app__/chunks/libs/bezier-js.mjs +1 -1
  43. package/__app__/chunks/libs/copy-anything.mjs +1 -0
  44. package/__app__/chunks/libs/d3-path.mjs +1 -1
  45. package/__app__/chunks/libs/d3-shape.mjs +1 -1
  46. package/__app__/chunks/libs/fast-equals.mjs +1 -1
  47. package/__app__/chunks/libs/framer-motion.mjs +3 -3
  48. package/__app__/chunks/libs/html-to-image.mjs +2 -2
  49. package/__app__/chunks/libs/motion-dom.mjs +1 -1
  50. package/__app__/chunks/libs/nanostores.mjs +1 -1
  51. package/__app__/chunks/libs/react-error-boundary.mjs +1 -1
  52. package/__app__/chunks/libs/react-resizable-panels.mjs +1 -1
  53. package/__app__/chunks/libs/remeda.mjs +1 -1
  54. package/__app__/chunks/libs/superjson.mjs +1 -0
  55. package/__app__/chunks/libs/zod.mjs +39 -14
  56. package/__app__/chunks/rolldown-runtime.mjs +1 -1
  57. package/__app__/chunks/styles.css.mjs +1 -1
  58. package/__app__/chunks/txt.mjs +1 -0
  59. package/__app__/chunks/useLikeC4Project.mjs +1 -1
  60. package/__app__/codegen/webcomponent.mjs +221 -69
  61. package/__app__/src/aichat/index.mjs +1 -0
  62. package/__app__/src/main.mjs +45 -1
  63. package/__app__/src/pages/AdHocViewEditor.mjs +1 -1
  64. package/__app__/src/pages/EmbedPage.mjs +1 -1
  65. package/__app__/src/pages/ExportPage.mjs +1 -1
  66. package/__app__/src/pages/ProjectsOverview.mjs +1 -1
  67. package/__app__/src/pages/ViewAsD2.mjs +1 -1
  68. package/__app__/src/pages/ViewAsDot.mjs +1 -1
  69. package/__app__/src/pages/ViewAsMmd.mjs +1 -1
  70. package/__app__/src/pages/ViewAsPuml.mjs +1 -1
  71. package/__app__/src/pages/ViewEditor.mjs +1 -1
  72. package/__app__/src/style.css +1 -1
  73. package/config/schema.json +14 -41
  74. package/dist/chunks/enableServer.mjs +1 -0
  75. package/dist/chunks/index2.d.mts +569 -377
  76. package/dist/chunks/libs/@hono/mcp.mjs +33 -8
  77. package/dist/chunks/libs/@hono/node-server.mjs +1 -1
  78. package/dist/chunks/libs/@modelcontextprotocol/sdk.mjs +7 -7
  79. package/dist/chunks/libs/@ts-graphviz/ast.mjs +3 -0
  80. package/dist/chunks/libs/@ts-graphviz/common.d.mts +9 -0
  81. package/dist/chunks/libs/@ts-graphviz/core.mjs +1 -0
  82. package/dist/chunks/libs/ajv.mjs +1 -1
  83. package/dist/chunks/libs/ansi-styles.mjs +1 -1
  84. package/dist/chunks/libs/boxen.mjs +2 -2
  85. package/dist/chunks/libs/chevrotain.mjs +2 -2
  86. package/dist/chunks/libs/conf.mjs +1 -1
  87. package/dist/chunks/libs/langium.d.mts +5 -5
  88. package/dist/chunks/libs/langium.mjs +10 -10
  89. package/dist/chunks/libs/merge-error-cause.mjs +1 -1
  90. package/dist/chunks/libs/pako.mjs +3 -1
  91. package/dist/chunks/libs/remeda.mjs +1 -1
  92. package/dist/chunks/libs/ts-graphviz.mjs +1 -4
  93. package/dist/chunks/libs/unctx.mjs +1 -0
  94. package/dist/chunks/libs/vscode-languageserver.mjs +1 -1
  95. package/dist/chunks/libs/zod.d.mts +60 -25
  96. package/dist/chunks/node.mjs +62 -45
  97. package/dist/chunks/plugin.mjs +234 -41
  98. package/dist/chunks/sequence-view.mjs +1 -1
  99. package/dist/cli/index.mjs +142 -139
  100. package/dist/index.d.mts +1 -130
  101. package/dist/model/index.d.mts +1 -1
  102. package/dist/vite-plugin/index.d.mts +53 -2
  103. package/dist/vite-plugin/internal/index.d.mts +331 -3
  104. package/dist/vite-plugin/internal/index.mjs +1 -1
  105. package/package.json +65 -51
  106. package/react/index.d.mts +82 -50
  107. package/react/index.mjs +34017 -32421
  108. package/vite-plugin-modules.d.ts +4 -0
  109. package/__app__/chunks/ColorSchemeToggle.mjs +0 -1
  110. package/__app__/chunks/Fallback.mjs +0 -1
  111. package/__app__/chunks/Header.mjs +0 -13
  112. package/__app__/chunks/IconRenderer.mjs +0 -1
  113. package/__app__/chunks/LikeC4ModelContext.mjs +0 -1
  114. package/__app__/chunks/LikeC4ModelContext2.mjs +0 -1
  115. package/__app__/chunks/StaticLikeC4Diagram.mjs +0 -1
  116. package/__app__/chunks/__root.mjs +0 -1
  117. package/__app__/chunks/libs/motion.mjs +0 -1
  118. package/__app__/chunks/libs/xstate.mjs +0 -1
  119. package/__app__/chunks/safeCtx.mjs +0 -1
  120. package/__app__/chunks/searchParams.mjs +0 -1
  121. package/__app__/chunks/single-index.mjs +0 -1
  122. package/__app__/chunks/styled-system.mjs +0 -1
  123. package/__app__/chunks/useUpdateEffect.mjs +0 -1
  124. package/__app__/src/routeTree.gen.mjs +0 -1
  125. package/__app__/src/routes/__root.mjs +0 -1
  126. package/__app__/src/routes/_single/adhoc.mjs +0 -1
  127. package/__app__/src/routes/_single/embed._viewId.mjs +0 -1
  128. package/__app__/src/routes/_single/export._viewId.mjs +0 -1
  129. package/__app__/src/routes/_single/route.mjs +0 -1
  130. package/__app__/src/routes/_single/single-index.mjs +0 -1
  131. package/__app__/src/routes/_single/view._viewId.d2.mjs +0 -1
  132. package/__app__/src/routes/_single/view._viewId.dot.mjs +0 -1
  133. package/__app__/src/routes/_single/view._viewId.index.mjs +0 -1
  134. package/__app__/src/routes/_single/view._viewId.mjs +0 -1
  135. package/__app__/src/routes/_single/view._viewId.mmd.mjs +0 -1
  136. package/__app__/src/routes/_single/view._viewId.puml.mjs +0 -1
  137. package/__app__/src/routes/_single/webcomponent._.mjs +0 -33
  138. package/__app__/src/routes/index.mjs +0 -1
  139. package/__app__/src/routes/project._projectId/-components.mjs +0 -1
  140. package/__app__/src/routes/project._projectId/adhoc.mjs +0 -1
  141. package/__app__/src/routes/project._projectId/embed._viewId.mjs +0 -1
  142. package/__app__/src/routes/project._projectId/export._viewId.mjs +0 -1
  143. package/__app__/src/routes/project._projectId/index.mjs +0 -1
  144. package/__app__/src/routes/project._projectId/route.mjs +0 -1
  145. package/__app__/src/routes/project._projectId/view._viewId.d2.mjs +0 -1
  146. package/__app__/src/routes/project._projectId/view._viewId.dot.mjs +0 -1
  147. package/__app__/src/routes/project._projectId/view._viewId.index.mjs +0 -1
  148. package/__app__/src/routes/project._projectId/view._viewId.mjs +0 -1
  149. package/__app__/src/routes/project._projectId/view._viewId.mmd.mjs +0 -1
  150. package/__app__/src/routes/project._projectId/view._viewId.puml.mjs +0 -1
  151. package/__app__/src/routes/projects.mjs +0 -1
  152. package/dist/chunks/libs/ts-graphviz.d.mts +0 -12
  153. package/dist/vite-plugin/internal/chunks/libs/@nanostores/react.d.mts +0 -269
  154. package/dist/vite-plugin/internal/chunks/libs/nanostores.d.mts +0 -59
@@ -1,6 +1,6 @@
1
- import{i as e}from"./rolldown-runtime.mjs";import{c as t,f as n,n as r}from"./node.mjs";import{a as i,i as a,n as o,r as s,t as c}from"./libs/langium.mjs";import{t as l}from"./libs/tinyrainbow.mjs";import{o as u}from"./libs/ufo.mjs";import{t as d}from"./libs/json5.mjs";import{A as f,C as p,D as m,G as h,J as g,L as _,Q as v,U as y,X as b,o as x,r as S,t as C,v as w,y as T}from"./libs/remeda.mjs";import{t as E}from"./libs/p-debounce.mjs";import{t as D}from"./libs/birpc.mjs";import{t as O}from"./libs/pako.mjs";import{createRequire as k}from"node:module";import{DefaultMap as A,LikeC4Styles as j,invariant as ee,isNonEmptyArray as M,nonexhaustive as N}from"@likec4/core";import{resolve as P}from"node:path";import{RichText as F,flattenMarkdownOrString as I}from"@likec4/core/types";import{compareNatural as L}from"@likec4/core/utils";import"@likec4/core/model";import{existsSync as R}from"node:fs";import{mkdir as z,readFile as B,writeFile as te}from"node:fs/promises";import{cwd as ne}from"node:process";function isJsonStringifyOutput(e){if(e.length===0)return!1;try{return JSON.parse(e),!0}catch{return!1}}function hardenJsonStringLiteralForEmbeddedScript(e){if(typeof e!=`string`)throw TypeError(`hardenJsonStringLiteralForEmbeddedScript: expected JSON.stringify(...) output as a string`);if(!isJsonStringifyOutput(e))throw TypeError(`hardenJsonStringLiteralForEmbeddedScript: expected JSON.stringify(...) output (string, object, array, number, boolean, or null)`);return e.replaceAll(`<`,`\\u003C`).replaceAll(`>`,`\\u003E`).replaceAll(`/`,`\\u002F`).replaceAll(`\u2028`,`\\u2028`).replaceAll(`\u2029`,`\\u2029`)}function generateMatches(e,t=`.js`){return{matches:n=>{let{module:r,projectId:i}=n.match(/likec4:plugin\/(?<projectId>.+)\/(?<module>.+)$/)?.groups??n.match(/likec4:(?<module>.+)\/(?<projectId>.+)$/)?.groups??{};return!r||!i?null:(r.endsWith(t)&&(r=r.slice(0,-t.length)),r===e?i:null)},virtualId:n=>u(`likec4:plugin`,n,e)+t}}function generateCombinedProjects(e,t){return{id:`likec4:${e}`,virtualId:`likec4:plugin/`+e+`.js`,async load({projects:n}){return logGenerating(e),{code:`
1
+ import{i as e}from"./rolldown-runtime.mjs";import{c as t,l as n,n as r,p as i}from"./node.mjs";import{a,n as o,o as s,r as c,t as l}from"./libs/langium.mjs";import{t as u}from"./libs/tinyrainbow.mjs";import{o as d}from"./libs/ufo.mjs";import{t as f}from"./libs/json5.mjs";import{$ as p,Q as m,X as h,lt as g,ot as _,st as v,yt as y}from"./libs/@hono/mcp.mjs";import{C as b,F as ee,G as te,H as x,M as S,O as C,P as w,Q as T,V as E,X as D,Z as O,_ as k,c as ne,et as A,m as j,o as re,q as M,r as N,t as P,v as ie,y as F,z as ae}from"./libs/remeda.mjs";import{t as oe}from"./libs/p-debounce.mjs";import{n as se,t as ce}from"./libs/package-manager-detector.mjs";import{t as le}from"./libs/birpc.mjs";import{t as ue}from"./libs/pako.mjs";import{createRequire as de}from"node:module";import{resolve as I}from"node:path";import{RichText as fe,exact as pe,flattenMarkdownOrString as L}from"@likec4/core/types";import{DefaultMap as R,LikeC4Styles as me,exact as z,invariant as he,nonexhaustive as ge}from"@likec4/core";import{compareNatural as _e,nonNullable as ve}from"@likec4/core/utils";import"@likec4/core/model";import ye from"nano-spawn";import{existsSync as be}from"node:fs";import{mkdir as xe,readFile as B,writeFile as Se}from"node:fs/promises";import{env as V}from"std-env";import H,{cwd as Ce}from"node:process";function isJsonStringifyOutput(e){if(e.length===0)return!1;try{return JSON.parse(e),!0}catch{return!1}}function hardenJsonStringLiteralForEmbeddedScript(e){if(typeof e!=`string`)throw TypeError(`hardenJsonStringLiteralForEmbeddedScript: expected JSON.stringify(...) output as a string`);if(!isJsonStringifyOutput(e))throw TypeError(`hardenJsonStringLiteralForEmbeddedScript: expected JSON.stringify(...) output (string, object, array, number, boolean, or null)`);return e.replaceAll(`<`,`\\u003C`).replaceAll(`>`,`\\u003E`).replaceAll(`/`,`\\u002F`).replaceAll(`\u2028`,`\\u2028`).replaceAll(`\u2029`,`\\u2029`)}function generateMatches(e,t=`.js`){return{matches:n=>{let{module:r,projectId:i}=n.match(/likec4:plugin\/(?<projectId>.+)\/(?<module>.+)$/)?.groups??n.match(/likec4:(?<module>.+)\/(?<projectId>.+)$/)?.groups??{};return!r||!i?null:(r.endsWith(t)&&(r=r.slice(0,-t.length)),r===e?i:null)},virtualId:n=>d(`likec4:plugin`,n,e)+t}}function generateCombinedProjects(e,t){return{id:`likec4:${e}`,virtualId:`likec4:plugin/`+e+`.js`,async load({projects:n}){return logGenerating(e),{code:`
2
2
  export let ${t}Fn = {
3
- ${n.map(({id:t})=>`${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(t))}: async () => await import(${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(u(`likec4:${e}`,t)))})`).join(`,
3
+ ${n.map(({id:t})=>`${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(t))}: async () => await import(${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(d(`likec4:${e}`,t)))})`).join(`,
4
4
  `)}
5
5
  }
6
6
 
@@ -34,14 +34,202 @@ if (import.meta.hot) {
34
34
  }
35
35
  })
36
36
  }
37
- `,moduleType:`js`}}}}const V=t.getChild(`vite`);function logGenerating(e,t){t?V.info(l.dim(`generating `)+l.magenta(`likec4:${e}/`)+l.magentaBright(t)):V.info(l.dim(`generating `)+l.magenta(`likec4:${e}`))}const H=V.getChild(`icons`);function iconBundlePlugin(e){let t=ne(),n=[t];e.workspace&&n.unshift(e.workspace);let r=k(t),i,resolveIcon=async(e,t)=>{try{let i=r.resolve(`@likec4/icons/${e}/${t}`,{paths:n});return H.trace(l.dim(`found in package `)+i),await B(i,`utf-8`)}catch{return}},readFromCache=async(e,t)=>{if(i)try{let n=P(i,e,`${t}.js`);if(R(n))return H.trace(l.dim(`read cached `)+`${e}/${t}.js`),await B(n,`utf-8`)}catch{}},writeToCache=async(e,t,n)=>{if(i)try{let r=P(i,e);R(r)||await z(r,{recursive:!0});let a=P(r,`${t}.js`);await te(a,n),H.trace(l.dim(`written to cache `)+a)}catch(n){H.error(l.dim(`failed to write to cache `)+`${e}/${t}.js`,{error:n})}},fetchFromRemote=async(e,t)=>{let n=u(`https://icons.like-c4.dev`,e,`${t}.js`);H.trace(l.dim(`fetching `)+n);let r=await fetch(n);if(!r.ok)throw Error(`Failed to fetch icon: ${r.status} ${r.statusText}`);return await r.text()},a=new A(async e=>{try{let[t,n]=e.split(`:`);(n.endsWith(`.jsx`)||n.endsWith(`.js`))&&(n=n.slice(0,n.lastIndexOf(`.`))),H.debug(l.dim(`resolving `)+l.green(`${t}:${n}`));let r=await readFromCache(t,n);return r??=await resolveIcon(t,n),r||(r=await fetchFromRemote(t,n),await writeToCache(t,n,r),r)}catch(t){return H.error(l.dim(`failed to resolve icon `)+l.red(e),{error:t}),`
37
+ `,moduleType:`js`}}}}const U=n.getChild(`vite`);function logGenerating(e,t){t?U.info(u.dim(`generating `)+u.magenta(`likec4:${e}/`)+u.magentaBright(t)):U.info(u.dim(`generating `)+u.magenta(`likec4:${e}`))}function isInstalled(e){try{return!!import.meta.resolve(e,H.cwd())}catch(e){return U.trace(i(e)),!1}}async function ensurePackage(e){let t=U.getChild(`pkg`);if(isInstalled(e)){t.trace`${e} installed`;return}t.warn(u.dim(`not found `)+u.green(e));let{command:n,args:r}=ve(se(ve(await ce(),()=>{t.error`Package manager not detected, install ${e} manually`,H.exit(1)}).agent,`add`,[e]),()=>{t.error`Install package ${e} manually`,H.exit(1)});t.info(u.dim(`installing `)+u.green(e));try{await ye(n,r)}catch(n){t.debug(i(n)),t.error`Install package ${e} manually`,H.exit(1)}}const W=U.getChild(`ai`);function chooseModel(e,t){let n=V[e];return n||=(W.info(`I will use `+u.green(t)+` model `+u.dim(`you can override with `)+u.yellow(e)+u.dim(` env var`)),t),n}const G=16e3;async function loadOpenAI(){W.info(`Found `+u.yellow(`OPENAI_API_KEY`)+u.dim(`, loading @tanstack/ai-openai`)),await ensurePackage(`@tanstack/ai-openai`);let{openaiText:e}=await import(`@tanstack/ai-openai`);return{adapter:e(chooseModel(`OPENAI_CHAT_MODEL`,`gpt-5.2`)),modelOptions:{reasoning:{effort:`medium`}},maxTokens:G}}async function loadOpenRouter(){W.info(`Found `+u.yellow(`OPENROUTER_API_KEY`)+u.dim(`, loading @tanstack/ai-openrouter`)),await ensurePackage(`@tanstack/ai-openrouter`);let{openRouterText:e}=await import(`@tanstack/ai-openrouter`);return{adapter:e(chooseModel(`OPENROUTER_CHAT_MODEL`,`openai/gpt-5.4`)),maxTokens:G}}async function loadAnthropic(){W.info(`Found `+u.yellow(`ANTHROPIC_API_KEY`)+u.dim(`, loading @tanstack/ai-anthropic`)),await ensurePackage(`@tanstack/ai-anthropic`);let{anthropicText:e}=await import(`@tanstack/ai-anthropic`);return{adapter:e(chooseModel(`ANTHROPIC_CHAT_MODEL`,`claude-sonnet-4-6`)),maxTokens:G}}async function loadGemini(){W.info(`Found `+u.yellow(`GEMINI_API_KEY`)+u.dim(`, loading @tanstack/ai-gemini`)),await ensurePackage(`@tanstack/ai-gemini`);let{geminiText:e}=await import(`@tanstack/ai-gemini`);return{adapter:e(chooseModel(`GEMINI_CHAT_MODEL`,`gemini-2.5-pro`)),maxTokens:G}}async function loadOllama(){W.info(`Found `+u.yellow(`OLLAMA_HOST`)+u.dim(`, loading @tanstack/ai-ollama`)),await ensurePackage(`@tanstack/ai-ollama`);let{ollamaText:e}=await import(`@tanstack/ai-ollama`),t=chooseModel(`OLLAMA_CHAT_MODEL`,`qwen3`);return{adapter:e(t),modelOptions:{model:t,think:`low`},maxTokens:G}}function pickLoader(){if(b(V.OPENAI_API_KEY))return loadOpenAI;if(b(V.OPENROUTER_API_KEY))return loadOpenRouter;if(b(V.ANTHROPIC_API_KEY))return loadAnthropic;if(b(V.GEMINI_API_KEY))return loadGemini;if(b(V.OLLAMA_HOST))return loadOllama}const we=j(async()=>{let e=pickLoader();if(e){await ensurePackage(`@tanstack/ai`);let t=await e();return W.info([`AI configured with`,u.green(t.adapter.name),`adapter`,u.dim(`you can disable it in plugin options`)].join(` `)),t}}),K=U.getChild(`icons`);function iconBundlePlugin(e){let t=Ce(),n=[t];e.workspace&&n.unshift(e.workspace);let r=de(t),i,resolveIcon=async(e,t)=>{try{let i=r.resolve(`@likec4/icons/${e}/${t}`,{paths:n});return K.trace(u.dim(`found in package `)+i),await B(i,`utf-8`)}catch{return}},readFromCache=async(e,t)=>{if(i)try{let n=I(i,e,`${t}.js`);if(be(n))return K.trace(u.dim(`read cached `)+`${e}/${t}.js`),await B(n,`utf-8`)}catch{}},writeToCache=async(e,t,n)=>{if(i)try{let r=I(i,e);be(r)||await xe(r,{recursive:!0});let a=I(r,`${t}.js`);await Se(a,n),K.trace(u.dim(`written to cache `)+a)}catch(n){K.error(u.dim(`failed to write to cache `)+`${e}/${t}.js`,{error:n})}},fetchFromRemote=async(e,t)=>{let n=d(`https://icons.like-c4.dev`,e,`${t}.js`);K.trace(u.dim(`fetching `)+n);let r=await fetch(n);if(!r.ok)throw Error(`Failed to fetch icon: ${r.status} ${r.statusText}`);return await r.text()},a=new R(async e=>{try{let[t,n]=e.split(`:`);(n.endsWith(`.jsx`)||n.endsWith(`.js`))&&(n=n.slice(0,n.lastIndexOf(`.`))),K.debug(u.dim(`resolving `)+u.green(`${t}:${n}`));let r=await readFromCache(t,n);return r??=await resolveIcon(t,n),r||(r=await fetchFromRemote(t,n),await writeToCache(t,n,r),r)}catch(t){return K.error(u.dim(`failed to resolve icon `)+u.red(e),{error:t}),`
38
38
  export default function NotFoundIcon() {
39
39
  return null
40
40
  }
41
- `}});return{name:`likec4:icon-bundle`,applyToEnvironment(t){return e.environments?e.environments.includes(t.name):!0},configResolved({root:e,...t}){n.unshift(e),t.cacheDir&&(i=P(t.cacheDir,`likec4-icons`))},resolveId:{filter:{id:/likec4:icon-bundle/},handler(e){return{id:e,moduleSideEffects:!1}}},load:{filter:{id:/likec4:icon-bundle/},async handler(e){let t=e.split(`/`).slice(-2);if(!b(t,2))return null;let[n,r]=t;return{moduleType:`jsx`,code:await a.get(`${n}:${r}`)}}}}}async function calcAdhocView({logger:e,likec4:t},n){e.info([l.green(`adhoc:view`),l.dim(`project:`),n.projectId].join(` `));let r=await t.views.adhocView(n.predicates,n.projectId);return e.info([l.green(`adhoc:view`),`✅`].join(` `)),r}function splitErrorMessage(e){let t=e.split(`
41
+ `}});return{name:`likec4:icon-bundle`,sharedDuringBuild:!0,applyToEnvironment(t){return e.environments?e.environments.includes(t.name):!0},configResolved({root:e,...t}){n.unshift(e),t.cacheDir&&(i=I(t.cacheDir,`likec4-icons`))},resolveId:{filter:{id:/likec4:icon-bundle/},handler(e){return{id:e,moduleSideEffects:!1}}},load:{filter:{id:/likec4:icon-bundle/},async handler(e){let t=e.split(`/`).slice(-2);if(!T(t,2))return null;let[n,r]=t;return{moduleType:`jsx`,code:await a.get(`${n}:${r}`)}}}}}const q=t(`ai-layout`);function truncate(e,t=100){return e=e.replaceAll(/\n/g,` `).trim(),e.length<=t?e:e.slice(0,t-1)+`…`}function mappedEntries(e){let t={};for(let[n,r]of e.entries())t[r]=n;return t}function edgeLabel(e){let t=e.label&&e.label!==`[...]`?e.label:void 0,n=L(e.description);return n&&(t=t?`${t}\n${n}`:n),t??=e.technology??void 0,t?truncate(t):void 0}function prepareLLMInput(e){let t=1,n=1,r=new R(e=>e.children.length===0?`n${n++}`:`c${t++}`),findNodeById=t=>e.nodes.find(e=>e.id===t),nodeId=e=>r.get(findNodeById(e)),i=new Set;e.nodes.forEach(e=>{r.get(e),e.children.length===0&&i.add(e.id)});let a=e.edges.find(e=>!i.has(e.source)||!i.has(e.target));if(a)throw q.error(`Non-leaf edge found in view`,{view:e.id,edge:{source:a.source,target:a.target}}),Error(`Non-leaf edge found in view, this is not supported by the current implementation`);let o=1,s=new R(e=>`e${o++}`),c=e.edges.map(e=>{let t=nodeId(e.source),n=nodeId(e.target),r=e.parent?nodeId(e.parent):null;e.dir===`back`&&([t,n]=[n,t]);let i=edgeLabel(e);return{id:s.get(e),...i&&{label:i},...r&&{parent:r},source:t,target:n}}),reduceNodes=(e,t)=>{let{level:n,kind:i,...a}=t,o=r.get(t),s=a.children.length>0,c=a.parent?nodeId(a.parent):void 0,l=truncate(a.title);if(s)return e.compounds.push(pe({id:o,title:l,parent:c,children:a.children.map(nodeId),level:n})),e;let u=a.description?truncate(L(a.description),200):void 0;return e.nodes.push(pe({id:o,kind:i,title:l,description:u,parent:c,level:n})),e};return{serialized:e.nodes.reduce(reduceNodes,{direction:e.autoLayout.direction,compounds:[],nodes:[],edges:c}),mapping:{nodes:mappedEntries(r),edges:mappedEntries(s)}}}const Te=m([`TB`,`BT`,`LR`,`RL`]),J=g().nonempty().brand(),Ee=_({rank:m([`same`,`source`,`sink`,`min`,`max`]),nodes:p(J)}),Y={id:g().nonempty().brand(),weight:h().int().min(0).max(20),minlen:h().int().min(0).max(4)},De=_({source:J,target:J,weight:Y.weight.optional(),minlen:Y.minlen.optional()}),Oe=_({direction:Te.optional(),ranks:p(Ee).default([]),edgeWeight:v(Y.id,Y.weight).default({}),edgeMinlen:v(Y.id,Y.minlen).default({}),reverseRank:p(Y.id).default([]),excludeFromRanking:p(Y.id).default([]),edgeOrder:p(Y.id).default([]),nodeOrder:p(J).default([]),invisibleEdges:p(De).default([]),reasoning:g().default(``)}),ke=/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/;function extractJson(e){let t=ke.exec(e);if(t&&t[1])return t[1];let n=e.indexOf(`{`),r=e.lastIndexOf(`}`);return n!==-1&&r!==-1&&r>n?e.slice(n,r+1):e.trim()}function parseOutput(e,t){try{let n=extractJson(e),r=f.parse(n),i=Oe.safeParse(r);if(!i.success){q.warn(`Failed to validate LLM response
42
+ `+y(i.error));return}return restoreIdsAndMapToHints(i.data,t)}catch(t){q.warn(`Failed to parse LLM response
43
+ {response}`,{error:t,response:e});return}}function restoreIdsAndMapToHints(e,t){let{mapping:n}=t,nodeId=e=>{let t=n.nodes[e]?.id;return t||q.warn`Unknown node ID ${e} in LLM output, skipping`,t},mapToNodeId=e=>A(e,F(nodeId),D(w)),edgeId=e=>{let t=n.edges[e]?.id;return t||q.warn`Unknown edge ID ${e} in LLM output, skipping`,t},mapToNonEmpty=(e,t)=>{let n=e.map(t).filter(w);return T(n,1)?n:void 0},r=A(e.excludeFromRanking,F(edgeId),D(w),N(),e=>T(e,1)?e:void 0),i=A(e.reverseRank,F(edgeId),D(w),N(),e=>T(e,1)?e:void 0),a=(()=>{let e=new Set;return t=>t.filter(t=>e.has(t)?!1:(e.add(t),!0))})(),o=A(e.ranks,F(e=>{let t=a(mapToNodeId(e.nodes));return T(t,1)?{rank:e.rank,nodes:t}:null}),D(b)),s=A(e.invisibleEdges,F(({source:e,target:t,minlen:n=1,weight:r=1})=>{let i=nodeId(e),a=nodeId(t);if(!(!i||!a))return z({weight:r===1?void 0:r,minlen:n===1?void 0:n,source:i,target:a})}),D(w),E(e=>`${e.source}->${e.target}`),k(([e,...t])=>A(t,ne((e,t)=>z({...e,...t,weight:e.weight&&t.weight?Math.max(e.weight,t.weight):e.weight||t.weight,minlen:e.minlen&&t.minlen?Math.max(e.minlen,t.minlen):e.minlen||t.minlen}),e))),P(),e=>T(e,1)?e:void 0),c=e.reasoning;c&&(c=c.replaceAll(`][`,`] [`),O(t.mapping.nodes).forEach(([e,t])=>{c=c.replaceAll(RegExp(`\\[${e}\\]`,`g`),"`"+t.id+"`")}),O(t.mapping.edges).forEach(([e,t])=>{c=c.replaceAll(RegExp(`\\[${e}\\]`,`g`),"`"+t.source+` -> `+t.target+"`")}));let safeMapEdgeKeys=e=>{let t={};for(let[n,r]of O(e)){let e=edgeId(n);e&&(t[e]=r)}return t};return z({direction:e.direction,ranks:o,edgeWeight:safeMapEdgeKeys(e.edgeWeight),edgeMinlen:safeMapEdgeKeys(e.edgeMinlen),excludeFromRanking:r,reverseRank:i,edgeOrder:mapToNonEmpty(e.edgeOrder,edgeId),nodeOrder:mapToNonEmpty(e.nodeOrder,nodeId),invisibleEdges:s,reasoning:c})}const Ae={systemPrompt:`You are an advisor specializing in software architecture diagrams and graphviz (DOT) layout optimizations.
44
+ You receive a JSON of Diagram data with:
45
+ - nodes (architectural elements, rendered as leaf boxes)
46
+ - compounds (group of nodes or other compounds, define hierarchy and rendered as boxes around children)
47
+ - edges (directed relationships between nodes, define flow from source to target)
48
+ - direction (preferred layout direction for the diagram, e.g. TB = top to bottom, LR = left to right)
49
+
50
+ Your task: Suggest layout hints to produce readable and visually balanced diagram.
51
+
52
+ <input>
53
+ Diagram (JSON object) fields:
54
+ - compounds: Compound[]
55
+ - nodes: Node[]
56
+ - edges: Edge[]
57
+ - direction: "TB" | "LR" | "BT" | "RL"
58
+
59
+ Node (JSON object) fields:
60
+ - id: string (starts with "n" followed by a number, e.g. "n1", "n2", etc.)
61
+ - kind: string (semantic type, e.g. "system", "container", "component", "service", "database", etc.)
62
+ - title: string
63
+ - description?: string | undefined - optional description
64
+ - parent?: string (compound ID) | undefined - optional Parent ID, if node is nested inside a compound;
65
+ - level: number - zero-based level in the hierarchy (root level = 0)
66
+
67
+ Compound (JSON object) fields:
68
+ - id: string (starts with "c" followed by a number, e.g. "c1", "c2", etc.)
69
+ - title: string
70
+ - parent?: string (compound ID) | undefined - optional Parent ID, if compound is nested inside another compound;
71
+ - level: number - zero-based level in the hierarchy (root level = 0)
72
+ - children: string[] - IDs of children (compounds or nodes)
73
+
74
+ Edge (JSON object) fields:
75
+ - id: string (starts with "e" followed by a number, e.g. "e1", "e2", etc.)
76
+ - source: string (node ID)
77
+ - target: string (node ID)
78
+ - parent?: string (compound ID) | undefined - optional Parent ID, if edge is inside a compound
79
+ - label?: string | undefined
80
+ </input>
81
+
82
+ <rules>
83
+
84
+ 1. Diagram is a hierarchical directed graph, may contain cycles
85
+ 2. Compound size and position are determined by its children; Node position is determined by its rank and hierarchy
86
+ 3. In vertical direction (TB, BT) rank is a row, in horizontal (LR, RL) rank is a column; rank increases following the direction (i.e from top to bottom for TB)
87
+ 4. Edge exists ONLY between nodes
88
+ 5. Edge increases rank following its direction, i.e making rank of target higher than rank of source; \`minlen\` controls how many ranks apart they should be
89
+ - by default, all edges have \`minlen=1\`
90
+ - \`minlen=2\` adds extra rank between nodes, pushing target node further away from source (adds more space)
91
+ - \`minlen=0\` does not increase rank, but defines relative order within rank (i.e if rank is a row, source node is on the left, or if rank is a column, source node is on the top)
92
+ - keep \`minlen\` in range 0..4
93
+ 6. You can change edge rank direction by adding its ID to the \`reverseRank\` array; this enforces the opposite - rank of source node should be higher than rank of target; It does not change the semantics, and gives more control over ranks. Especially useful to break cycles or swap rank order of source and target
94
+ 7. You can exclude edge from calculations by adding its ID to the \`excludeFromRanking\` array; Edge still visible but does not contribute to node ranks (\`constraint=false\` in graphviz)
95
+ 8. Edge acts like a "spring" that pulls nodes together; its force controlled by \`weight\`; higher weight means shorter and straighter line;
96
+ - by default, all edges have \`weight=1\`
97
+ - \`weight\` is relative to \`weight\` of other edges
98
+ - same \`weight\` value balances edges equally; only difference in \`weight\` values affects layout
99
+ - keep \`weight\` in range 1..10, to emphasize edge use range 6..10
100
+ 9. You can add invisible edges to fine-tune node ranks (and/or order within same rank):
101
+ - invisible edge has same effects as regular edge (changes rank and order), but not visible and does not change semantics
102
+ - to add invisible edge, push an object with \`source\` and \`target\` node IDs to the \`invisibleEdges\` array (\`minlen\` and \`weight\` are optional, but if provided, follow the same rules)
103
+ - you can add edge if only there is no same edge exists, i.e if \`A->B\` exists, you can add \`B->A\`, but not \`A->B\` again
104
+ - invisible edges especially useful to pull semantically related nodes closer, force position of orphan nodes (having only incoming, outgoing, or none edges), move nodes to separate ranks or order nodes strictly in same rank
105
+ 10. You can constrain node ranks by using the \`ranks\` array:
106
+ - \`rank="source"\` constrain node(s) at the minimum rank (top/left)
107
+ - \`rank="sink"\` constrain node(s) at the maximum rank (bottom/right)
108
+ - \`rank="same"\` constrain two or more nodes to be on the same rank
109
+ - Node cannot have multiple rank constraints, if you encounter this, pick the most important (prefer \`rank="same"\` when in doubt)
110
+ - Node rank constraint takes precedence over edge-based rank calculations
111
+ 11. Vertical layout directions (TB,BT) are good for general flows (like interactions, processes, etc.), horizontal layout (LR,RL) for pipelines, request processing; Keep input layout direction, unless it contradicts the semantics
112
+ 12. Node size is 300x200px, rank separation is 200px, spacing within rank is 200px
113
+ 13. Avoid node overlapping, compounds order should be aligned with flows crossing their boundaries
114
+ 14. Minimize edge crossings; prefer balanced, straighter edges
115
+
116
+ </rules>
117
+
118
+ <workflow>
119
+
120
+ 1. Analyze diagram semantics, identify main and auxiliary flows, which nodes are most likely to be sources and which are sinks
121
+ 2. If any compound exists, analyze hierarchy and keep parent-child relationships in mind as constraints
122
+ 3. Plan node positions and rank constraints
123
+ 4. Decide on edges: adjust \`minlen\`, reverse rank direction or exclude from ranking
124
+ 5. Consider adding invisible edges to enforce layout
125
+ 6. Balance the layout by adjusting edge weights
126
+ 7. Output existing edges in semantic order
127
+ 8. Output nodes in semantic order
128
+ </workflow>
129
+
130
+ <output>
131
+ Output ONLY a valid JSON object matching the following schema.
132
+ All fields are optional (omit empty, null, undefined).
133
+ Use \`reasoning\` field to explain your decision, be concise.
134
+ Do not include any other text, comments, questions or explanations.
135
+ Do not pretty-print, compact JSON is preferred.
136
+
137
+ \`\`\`json
138
+ {
139
+ // Force ranks for nodes, use "source" for top level, "sink" for bottom level, "same" for nodes that should be on the same rank
140
+ "ranks": [
141
+ { "rank": "source", "nodes": ["n1", "n2"] },
142
+ { "rank": "same", "nodes": ["n4", "n5"] },
143
+ { "rank": "sink", "nodes": ["n3"] }
144
+ ],
145
+ // Edge weight adjustments (only if you want to change from default weight=1)
146
+ "edgeWeight": {
147
+ "e1": 8,
148
+ "e2": 5
149
+ },
150
+ // Edge rank separation adjustments (only if you want to change from default minlen=1)
151
+ "edgeMinlen": {
152
+ "e1": 2, // two ranks between connected nodes
153
+ "e2": 0 // no rank separation
154
+ },
155
+ // Reverse edge rank
156
+ "reverseRank": ["e4"],
157
+ // Exclude edges from ranking
158
+ "excludeFromRanking": ["e5"],
159
+ // Add invisible edges to enforce better layout
160
+ "invisibleEdges": [
161
+ {
162
+ "source": "n1", // Node ID
163
+ "target": "n2", // Node ID
164
+ "weight": 8, // (optional, default: 1)
165
+ "minlen": 2 // (optional, default: 1)
166
+ }
167
+ ],
168
+ // Suggest to change order of edges to satisfy semantics better (if order from input does not)
169
+ "edgeOrder": ["e2", "e1", "e3"],
170
+ // Suggest to change order of nodes to represent flows better (if order from input does not)
171
+ "nodeOrder": ["n2", "n1", "n3", "n4", "n5"],
172
+ // Suggest to change layout direction, if it would improve readability
173
+ "direction": "LR",
174
+ // Reasoning for debugging. Use ID in brackets, like [e1] or [n1], to reference nodes, compounds or edges (for invisible edges use [source->target]). This is important for displaying references on UI correctly.
175
+ "reasoning": "User-facing actor [n1] at top, data store [n3] at bottom. [n4] and [n2] on separate ranks to show the request flow clearly. Main flows are [e1][e2][e3] and [e4][e6], [e5] is auxiliary and does not affect ranking. Added invisible edge [n8->n9] to pull them closer and emphasize their connection."
176
+ }
177
+ \`\`\`
178
+ </output>
179
+
180
+ <example>
181
+
182
+ INPUT:
183
+ \`\`\`json
184
+ {
185
+ "direction": "TB",
186
+ "compounds": [
187
+ { "id": "c1", "title": "Cloud System", "children": ["n2", "n3", "n4"], "level": 0 },
188
+ { "id": "c2", "title": "Amazon", "children": ["n6", "n7", "n8"], "level": 0 }
189
+ ],
190
+ "nodes": [
191
+ { "id": "n2", "kind": "service", "title": "Cloud Legacy", "parent": "c1", "level": 1 },
192
+ { "id": "n3", "kind": "service", "title": "Cloud Next", "parent": "c1", "level": 1 },
193
+ { "id": "n4", "kind": "ui", "title": "Frontends", "parent": "c1", "level": 1 },
194
+ { "id": "n6", "kind": "storage", "title": "S3", "parent": "c2", "level": 1 },
195
+ { "id": "n7", "kind": "service", "title": "Lambda", "parent": "c2", "level": 1 },
196
+ { "id": "n8", "kind": "storage", "title": "Postgres", "parent": "c2", "level": 1 }
197
+ ],
198
+ "edges": [
199
+ { "id": "e1", "source": "n7", "target": "n8", "parent": "c2"},
200
+ { "id": "e2", "source": "n3", "target": "n7", "label": "calls lambda" },
201
+ { "id": "e3", "source": "n4", "target": "n2", "parent": "c1", "label": "requests" },
202
+ { "id": "e4", "source": "n3", "target": "n4", "parent": "c1", "label": "serves" },
203
+ { "id": "e5", "source": "n3", "target": "n2", "parent": "c1", "label": "calls legacy" },
204
+ { "id": "e6", "source": "n2", "target": "n6", "label": "persists" },
205
+ { "id": "e7", "source": "n3", "target": "n8", "label": "reads users from the database" }
206
+ ]
207
+ }
208
+ \`\`\`
209
+
210
+ OUTPUT:
211
+ \`\`\`json
212
+ {
213
+ "direction": "TB",
214
+ "ranks": [
215
+ { "rank": "source", "nodes": ["n4"] },
216
+ { "rank": "same", "nodes": ["n2", "n3"] },
217
+ { "rank": "sink", "nodes": ["n6", "n8"] }
218
+ ],
219
+ "edgeMinlen": {
220
+ "e5": 0
221
+ },
222
+ "reverseRank": ["e4"],
223
+ "excludeFromRanking": ["e1"],
224
+ "edgeOrder": ["e3", "e4", "e5", "e6", "e7", "e1"],
225
+ "nodeOrder": ["n4", "n2", "n3", "n6", "n7", "n8"],
226
+ "reasoning": "I reversed [e4] as it moves [n4] to the top, pushes [n3] to the next row and balances layout, [e5] \`minlen=0\` to keep [n2][n3] on same rank"
227
+ }
228
+ \`\`\`
229
+ </example>`,userPrompt:`Analyze semantics and suggest layout hints for the following diagram. Return only JSON object without any additional text or markdown formatting.`};async function enhanceLayoutWithAI(e,t,n){try{q.debug`generating AI layout hints for ${e.id} using ${t.name}`;let{serialized:r,mapping:i}=prepareLLMInput(e);return parseOutput(await t.sendRequest({...Ae,view:e,mapping:i,diagram:JSON.stringify(r)},n),{mapping:i,view:e})}catch(e){q.warn`AI layout enhancement failed: ${e}`;return}}async function applySemanticLayout({logger:e,ai:t,likec4:n,server:r},i){he(t,`AI is not configured`),e.info([u.green(`semantic:layout`),u.dim(`project:`),i.projectId,u.dim(`view:`),i.viewId].join(` `));let a={started:()=>r.hot.send(`likec4:apply-semantic-layout`,{type:`started`}),completed:()=>r.hot.send(`likec4:apply-semantic-layout`,{type:`completed`}),log:e=>r.hot.send(`likec4:apply-semantic-layout`,{log:e})},{chat:o,EventType:s}=await import(`@tanstack/ai`),c=(await n.computedModel(i.projectId)).findView(i.viewId);he(c,`View ${i.viewId} not found in project ${i.projectId}`),e.info([u.green(`semantic:layout`),u.dim(`call`),t.adapter.name].join(` `));let l=await enhanceLayoutWithAI(c.$view,{name:t.adapter.name,async sendRequest({systemPrompt:e,userPrompt:n,diagram:r}){a.started();let i=o({...t,systemPrompts:[e],stream:!0,messages:[{role:`user`,content:[{type:`text`,content:e},{type:`text`,content:n},{type:`text`,content:r}]}]}),c=``;for await(let e of i)switch(e.type){case s.TEXT_MESSAGE_CONTENT:a.log(e.delta),c+=e.delta;break;case s.REASONING_MESSAGE_CONTENT:a.log(e.delta);break}return c}});if(a.completed(),!l){e.warn([u.yellow(`semantic:layout`),`No semantic layout generated`].join(` `));return}e.info([u.green(`semantic:layout`),u.dim(`apply ai hints to layout`)].join(` `));let d=await n.views.layoutView({viewId:i.viewId,projectId:i.projectId,layoutHints:l});if(!d){e.error([u.red(`semantic:layout`),`layout hints failed`].join(` `));return}e.info([u.green(`semantic:layout`),u.dim(`save view snapshot`)].join(` `));let f=await n.editor.applyChange({viewId:i.viewId,projectId:i.projectId,change:{op:`save-view-snapshot`,layout:d.diagram}});if(!f.success){e.error([u.red(`semantic:layout`),`apply change failed`,f.error].join(` `));let t=Error(f.error);throw t.stack=f.error,t}e.info([u.green(`semantic:layout`),u.dim(`project:`),i.projectId,u.dim(`view:`),i.viewId,`✅`].join(` `))}async function calcAdhocView({logger:e,likec4:t},n){e.info([u.green(`adhoc:view`),u.dim(`project:`),n.projectId].join(` `));let r=await t.views.adhocView(n.predicates,n.projectId);return e.info([u.green(`adhoc:view`),`✅`].join(` `)),r}async function updateView({logger:e,likec4:t},n){e.info([u.green(`view:onChange`),u.dim(`project`),n.projectId,u.dim(`view`),n.viewId,u.dim(`change`),n.change.op].join(` `));let r=await t.editor.applyChange(n);if(!r.success){e.error(`Failed to apply view change:\n${r.error}`);let t=Error(r.error);throw t.stack=r.error,t}e.info([u.green(`view:onChange`),`✅`].join(` `))}function splitErrorMessage(e){let t=e.split(`
42
230
  `),n=/^\s+at\s+/,r=t.findIndex(e=>n.test(e));return r===-1&&(r=1),{message:t.slice(0,r).join(`
43
231
  `),stack:t.slice(r).join(`
44
- `)}}function sendError(e,{name:t,error:n}){e.hot.send({type:`error`,err:{...splitErrorMessage(n),name:t??`LikeC4PluginError`,plugin:`vite-plugin-likec4`}})}async function updateView({logger:e,likec4:t},n){e.info([l.green(`view:onChange`),l.dim(`project`),n.projectId,l.dim(`view`),n.viewId,l.dim(`change`),n.change.op].join(` `));let r=await t.editor.applyChange(n);if(!r.success){e.error(`Failed to apply view change:\n${r.error}`);let t=Error(r.error);throw t.stack=r.error,t}e.info([l.green(`view:onChange`),`✅`].join(` `))}function enablePluginRPC(e){let t=null,n=e.server;D({updateView:t=>updateView(e,t),calcAdhocView:t=>calcAdhocView(e,t)},{on:e=>n.hot.on(`likec4:rpc`,e),post:e=>n.hot.send(`likec4:rpc`,e),onFunctionError:(r,i)=>{e.logger.error(`RPC error in ${i}`,{error:r});let a=r.stack??r.message;try{t!==a&&(t=a,sendError(n,{name:r.name,error:a}))}catch(t){e.logger.error(`Failed to send error to client`,{error:t})}}})}function createAppConfigModule(e){let{webcomponentPrefix:t=`likec4`,pageTitle:n=`LikeC4`,useHashHistory:r=!1,theme:i=`auto`}=e||{};return{id:`likec4:app-config`,virtualId:`likec4:plugin/app-config.js`,async load(){return logGenerating(`app-config`),`
232
+ `)}}function sendError(e,{name:t,error:n}){e.hot.send({type:`error`,err:{...splitErrorMessage(n),name:t??`LikeC4PluginError`,plugin:`vite-plugin-likec4`}})}function enablePluginRPC(e){let t=null,n=e.server;le({updateView:t=>updateView(e,t),calcAdhocView:t=>calcAdhocView(e,t),applySemanticLayout:t=>applySemanticLayout(e,t)},{on:e=>n.hot.on(`likec4:rpc`,e),post:e=>n.hot.send(`likec4:rpc`,e),onTimeoutError(e){return e===`applySemanticLayout`},onFunctionError:(r,i)=>{e.logger.error(`RPC error in ${i}`,{error:r});let a=r.stack??r.message;try{t!==a&&(t=a,sendError(n,{name:r.name,error:a}))}catch(t){e.logger.error(`Failed to send error to client`,{error:t})}}})}function createAppConfigModule(e){let{webcomponentPrefix:t=`likec4`,pageTitle:n=`LikeC4`,useHashHistory:r=!1,theme:i=`auto`}=e||{};return{id:`likec4:app-config`,virtualId:`likec4:plugin/app-config.js`,async load(){return logGenerating(`app-config`),`
45
233
  export let ComponentName = {
46
234
  View: ${JSON.stringify(t+`-view`)},
47
235
  Browser: ${JSON.stringify(t+`-browser`)},
@@ -64,11 +252,11 @@ export let defaultTheme = ${JSON.stringify(i)}
64
252
  export let krokiD2SvgUrl = import.meta.env.VITE_KROKI_D2_SVG_URL || 'https://kroki.io/d2/svg'
65
253
  export let krokiPumlSvgUrl = import.meta.env.VITE_KROKI_D2_SVG_URL || 'https://kroki.io/plantuml/svg'
66
254
 
67
- `}}}const re=e(e=>e.charAt(0).toLocaleUpperCase()+e.slice(1),`capitalizeFirstLetter`),ie=e(e=>e.split(`.`).map(re).join(``),`fqnName`),ae=e(e=>ie(e.parent?e.id.slice(e.parent.length+1):e.id),`nodeName`),d2direction=({autoLayout:e})=>{switch(e.direction){case`TB`:return`down`;case`BT`:return`up`;case`LR`:return`right`;case`RL`:return`left`}},d2shape=({shape:e})=>{switch(e){case`queue`:case`cylinder`:case`rectangle`:case`document`:return e;case`person`:return`c4-person`;case`storage`:return`stored_data`;case`component`:case`bucket`:case`mobile`:case`browser`:return`rectangle`}};function generateD2(e){let t=e.$view,{nodes:n,edges:r}=t,i=new Map,printNode=(e,t)=>{let r=ae(e),a=(t?t+`.`:``)+r;i.set(e.id,a);let l=JSON.stringify(e.title),u=d2shape(e);return new o().append(r,`: {`,s).indent({indentedChildren:t=>t.append(`label: `,l,s).appendIf(u!==`rectangle`,`shape: `,u,s).appendIf(e.children.length>0,s,c(n.filter(t=>t.parent===e.id),e=>printNode(e,a))),indentation:2}).append(`}`,s)},printEdge=e=>new o().append(i.get(e.source),` -> `,i.get(e.target)).append(t=>e.label&&t.append(`: `,JSON.stringify(e.label)));return a(new o().append(`direction: `,d2direction(t),s,s).append(c(n.filter(e=>m(e.parent)),e=>printNode(e),{appendNewLineIfNotEmpty:!0})).appendIf(r.length>0,s,c(r,e=>printEdge(e),{appendNewLineIfNotEmpty:!0})))}const U=`data:page/id,likec4-`,oe=`diagrams.drawio`;function escapeXml(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`).replaceAll(`"`,`&quot;`).replaceAll(`'`,`&apos;`)}function parseDrawioRoundtripComments(e){let t=e.split(/\r?\n/),n={},r={},i={},a={},o=!1,s=0;for(;s<t.length;){let e=t[s];if(e==null){s+=1;continue}if(e.trim()===`// <likec4.layout.drawio>`){o=!0,s+=1;let e=[];for(;s<t.length&&t[s]?.trim()!==`// </likec4.layout.drawio>`;){let n=t[s]?.trim();n?.startsWith(`// `)&&e.push(n.slice(3)),s+=1}if(e.length>0)try{let t=e.join(`
68
- `);n=JSON.parse(t)}catch{}s+=1;continue}if(e.trim()===`// <likec4.strokeColor.vertices>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.strokeColor.vertices>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)&&e.includes(`=`)){let t=e.slice(3).trim(),n=t.indexOf(`=`);if(n>0){let e=t.slice(0,n).trim(),i=t.slice(n+1).trim();e&&i&&(r[e]=i)}}s+=1}s+=1;continue}if(e.trim()===`// <likec4.strokeWidth.vertices>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.strokeWidth.vertices>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)&&e.includes(`=`)){let t=e.slice(3).trim(),n=t.indexOf(`=`);if(n>0){let e=t.slice(0,n).trim(),r=t.slice(n+1).trim();e&&r!==``&&(i[e]=r)}}s+=1}s+=1;continue}if(e.trim()===`// <likec4.edge.waypoints>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.edge.waypoints>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)){let t=e.slice(3).trim(),n=t.indexOf(` `);if(n>0){let e=t.slice(0,n).trim(),r=t.slice(n+1).trim();if(e&&r)try{let t=JSON.parse(r);Array.isArray(t)&&(a[e]=t)}catch{}}}s+=1}s+=1;continue}s+=1}return o?{layoutByView:n,strokeColorByFqn:r,strokeWidthByFqn:i,edgeWaypoints:a}:null}function compressDrawioDiagramXml(e){let t=encodeURIComponent(e),n=new TextEncoder().encode(t);return uint8ArrayToBase64(O.deflateRaw(n))}function uint8ArrayToBase64(e){if(typeof Buffer<`u`)return Buffer.from(e).toString(`base64`);let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}const W={getNotes(e){return e.notes},getSummary(e){return e.summary},getTags(e){return e.tags},getNavigateTo(e){return e.navigateTo},getIcon(e){return e.icon},getLinks(e){return e.links},getNotation(e){return e.notation},getCustomData(e){return e.customData},getChildren(e){return e.children}},G={getKind(e){return e.kind},getNotation(e){return e.notation},getLinks(e){return e.links},getMetadata(e){return e.metadata},getCustomData(e){return e.customData}};function getEffectiveStyles(e){return e.$styles??j.DEFAULT}function escapeHtml(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`).replaceAll(`"`,`&quot;`)}function toNonEmptyString(e){if(e==null)return``;let t=typeof e;if(t===`string`){let t=e;return t.trim()===``?``:t}return t===`number`||t===`boolean`?String(e):``}function getContainerDashedStyle(e,t){return e&&t!==`none`||t===`dashed`?`dashed=1;`:``}function getDefaultStrokeWidth(e,t){return e===`none`?`0`:t||e?`1`:``}function applyStrokeColorOverride(e,t){return{fill:e?.fill??`#dae8fc`,stroke:t,font:e?.font??t}}function resolveThemeColor(e,t,n){return t&&t in e.theme.colors?t:n}function getThemeColorValues(e,t,n){let r=getEffectiveStyles(e),i=resolveThemeColor(r,t??n,n);try{return r.colors(i)}catch{return j.DEFAULT.colors(n)}}function drawioShape(e){let t=`shape=rectangle;rounded=1;arcSize=12;`;switch(e){case`person`:return`shape=actor;`;case`rectangle`:case`browser`:case`mobile`:case`bucket`:return t;case`cylinder`:case`queue`:case`storage`:return`shape=cylinder3;whiteSpace=wrap;boundedLbl=1;backgroundOutline=1;size=15;`;case`document`:return`shape=document;whiteSpace=wrap;html=1;boundedLbl=1;`;case`component`:return`shape=component;`;default:return t}}function getElementColors(e,t){let n=getThemeColorValues(e,t,`primary`).elements;return{fill:String(n.fill??`#dae8fc`),stroke:String(n.stroke??`#2563eb`),font:String(n.hiContrast??n.stroke??`#1e40af`)}}function getEdgeStrokeColor(e,t){let n=getThemeColorValues(e,t??`gray`,`gray`);return String(n.relationships?.line??`#1e40af`)}function getEdgeLabelColors(e,t){let n=getThemeColorValues(e,t??`gray`,`gray`).relationships;return{font:String(n?.label??n?.line??`#1e40af`),background:String(n?.labelBg??`#ffffff`)}}function edgeAnchors(e,t){let n=e.x+e.width/2,r=e.y+e.height/2,i=t.x+t.width/2,a=t.y+t.height/2,o=i-n,s=a-r,c=Math.abs(o)>=Math.abs(s);return{exitX:c?+(o>=0):.5,exitY:c?.5:+(s>=0),entryX:c?o>=0?0:1:.5,entryY:c?.5:s>=0?0:1}}function normalizeEdgePoint(e){if(Array.isArray(e)&&e.length>=2&&typeof e[0]==`number`&&typeof e[1]==`number`)return[[e[0],e[1]]];let t=e;return typeof t.x==`number`&&typeof t.y==`number`?[[t.x,t.y]]:[]}function buildNodeValueHtml(e,t,n,r,i,a){return n?``:t===``?`<div style="box-sizing:border-box;width:100%;min-height:100%;display:flex;align-items:center;justify-content:center;text-align:center;color:${r};font-family:${i};"><b style="font-size:${a}px;">${escapeHtml(e)}</b></div>`:`<div style="box-sizing:border-box;width:100%;min-height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:${r};font-family:${i};"><b style="font-size:${a}px;">${escapeHtml(e)}</b><br/><span style="font-weight:normal;font-size:${a}px;">${escapeHtml(t)}</span></div>`}function pushStylePart(e,t,n){n!=null&&n!==``&&e.push(`${t}=${encodeURIComponent(n)}`)}function pushStylePartNum(e,t,n){n!=null&&e.push(`${t}=${n}`)}function buildNavLinkStyle(e){return e===``?``:`link=${encodeURIComponent(`${U}${e}`)};`}function toExportString(e){let t=e==null?null:I(e);return t!=null&&!f(t)?t.trim():``}function linksToStyleJson(e){return!Array.isArray(e)||e.length===0?``:encodeURIComponent(JSON.stringify(e.map(e=>({url:e.url,title:e.title}))))}function metadataToStyleJson(e){return typeof e!=`object`||!e||Array.isArray(e)||Object.keys(e).length===0?``:encodeURIComponent(JSON.stringify(e))}const se=/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;function buildLikec4StyleForNode(e){let t=[];return pushStylePart(t,`likec4Description`,e.desc),pushStylePart(t,`likec4Technology`,e.tech),pushStylePart(t,`likec4Notes`,e.notes),pushStylePart(t,`likec4Tags`,e.tagList),pushStylePart(t,`likec4NavigateTo`,e.navTo),pushStylePart(t,`likec4Icon`,e.iconName),pushStylePart(t,`likec4Summary`,e.summaryStr),e.linksJson!==``&&t.push(`likec4Links=${e.linksJson}`),pushStylePart(t,`likec4Border`,e.borderVal),pushStylePartNum(t,`likec4Opacity`,e.containerOpacityNum),pushStylePart(t,`likec4StrokeWidth`,e.strokeWidth),e.colorNameForRoundtrip!==``&&t.push(`likec4ColorName=${e.colorNameForRoundtrip}`),pushStylePart(t,`likec4Size`,e.nodeStyle?.size),pushStylePart(t,`likec4Padding`,e.nodeStyle?.padding),pushStylePart(t,`likec4TextSize`,e.nodeStyle?.textSize),pushStylePart(t,`likec4IconPosition`,e.nodeStyle?.iconPosition),e.strokeHex&&se.test(e.strokeHex)&&pushStylePart(t,`likec4StrokeColor`,e.strokeHex),pushStylePart(t,`likec4Notation`,e.nodeNotation??void 0),t.length>0?t.join(`;`)+`;`:``}function buildBridgeManagedStyleForNode(e,t,n,r){if(r?.profile!==`leanix`)return``;let i=[`bridgeManaged=true`,`likec4Id=${encodeURIComponent(e)}`,`likec4Kind=${encodeURIComponent(t)}`,`likec4ViewId=${encodeURIComponent(n)}`];r.projectId!=null&&r.projectId!==``&&i.push(`likec4ProjectId=${encodeURIComponent(r.projectId)}`);let a=r.leanixFactSheetTypeByKind?.[t];return a!=null&&a!==``&&i.push(`leanixFactSheetType=${encodeURIComponent(a)}`),i.join(`;`)+`;`}function buildBridgeManagedStyleForEdge(e,t){return t?.profile===`leanix`?`bridgeManaged=true;likec4RelationId=${encodeURIComponent(e)};`:``}function buildMxUserObjectXml(e){return!e||typeof e!=`object`||Array.isArray(e)||Object.keys(e).length===0?``:`
69
- <mxUserObject>`+Object.entries(e).map(([e,t])=>{let n=typeof t==`string`?t:t==null?``:String(t);return`<data key="${escapeXml(e)}">${escapeXml(n)}</data>`}).join(``)+`</mxUserObject>`}function buildLikec4StyleForEdge(e){let t=[];return pushStylePart(t,`likec4Description`,e.edgeDesc),pushStylePart(t,`likec4Technology`,e.edgeTech),pushStylePart(t,`likec4Notes`,e.edgeNotes),pushStylePart(t,`likec4NavigateTo`,e.edgeNavTo),pushStylePart(t,`likec4RelationshipKind`,e.edgeKind??void 0),pushStylePart(t,`likec4Notation`,e.edgeNotation??void 0),e.edgeLinksJson!==``&&t.push(`likec4Links=${e.edgeLinksJson}`),e.edgeMetadataJson!==``&&t.push(`likec4Metadata=${e.edgeMetadataJson}`),t.length>0?t.join(`;`)+`;`:``}function buildEdgeLabelValue(e){return e.label?escapeXml(e.label):``}function buildEdgeGeometryXml(e,t){let n=t?.[`${e.source}|${e.target}|${e.id}`]??t?.[`${e.source}|${e.target}`],r=Array.isArray(n)?n.flatMap(normalizeEdgePoint):[];return r.length>0?`<mxGeometry relative="1" as="geometry">${`<Array as="points">`+r.map(([e,t])=>`<mxPoint x="${Math.round(e)}" y="${Math.round(t)}"/>`).join(``)+`</Array>`}</mxGeometry>`:`<mxGeometry relative="1" as="geometry" />`}function buildEdgeStyleString(e,t,n,r,i){let{bboxes:a,fontFamily:o}=t,s=a.get(e.source),c=a.get(e.target),l=s&&c?edgeAnchors(s,c):{exitX:1,exitY:.5,entryX:0,entryY:.5},u=`exitX=${l.exitX};exitY=${l.exitY};entryX=${l.entryX};entryY=${l.entryY};`,d=getEdgeStrokeColor(n,e.color),f=e.line===`dashed`?`dashed=1;`:e.line===`dotted`?`dashed=1;dashPattern=1 1;`:``,p=drawioArrow(e.head),m=e.tail==null||e.tail===`none`?`none`:drawioArrow(e.tail),h=buildLikec4StyleForEdge({edgeDesc:toExportString(e.description),edgeTech:toExportString(e.technology),edgeNotes:toExportString(e.notes),edgeNavTo:toNonEmptyString(e.navigateTo),edgeKind:G.getKind(e),edgeNotation:G.getNotation(e),edgeLinksJson:linksToStyleJson(G.getLinks(e)),edgeMetadataJson:metadataToStyleJson(G.getMetadata(e))}),g=buildBridgeManagedStyleForEdge(e.id,i),_=getEdgeLabelColors(n,e.color);return`endArrow=${p};startArrow=${m};html=1;rounded=0;${u}strokeColor=${d};strokeWidth=2;${f}${r===``?``:`fontColor=${_.font};fontSize=12;align=center;verticalAlign=middle;labelBackgroundColor=none;fontFamily=${encodeURIComponent(o)};`}${h}${g}`}function buildEdgeCellXml(e,t,n,r,i,a){let{defaultParentId:o}=t,s=i(e.source),c=i(e.target),l=buildEdgeLabelValue(e),u=buildEdgeGeometryXml(e,n?.edgeWaypoints);return`<mxCell id="${a}" value="${l}" style="${buildEdgeStyleString(e,t,r,l,n)}" edge="1" parent="${o}" source="${s}" target="${c}">
70
- ${u}${buildMxUserObjectXml(G.getCustomData(e))}
71
- </mxCell>`}function computeNodeGeometry(e,t,n){let{bboxes:r,defaultParentId:i,nodeIdsInView:a}=t,o=n(e.id),s=r.get(e.id),{width:c,height:l}=s,u=e.parent!=null&&a.has(e.parent)?n(e.parent):i,d=e.parent==null?void 0:r.get(e.parent);return{id:o,parentId:u,x:d==null?s.x+t.offsetX:s.x-d.x,y:d==null?s.y+t.offsetY:s.y-d.y,width:c,height:l}}function computeNodeStylePartsAndValue(e,t,n,r){let{containerNodeIds:i,effectiveStyles:a,fontFamily:o,containerTitleFontSizePx:s,containerTitleColor:c}=t,l=n?.strokeColorByNodeId,u=n?.strokeWidthByNodeId,d=i.has(e.id),f=e.kind??``,p=e.title,m=toExportString(e.description),h=toExportString(e.technology),g=toExportString(W.getNotes(e)),_=W.getTags(e),v=Array.isArray(_)&&_.length>0?_.join(`,`):``,y=toNonEmptyString(W.getNavigateTo(e)),b=toNonEmptyString(W.getIcon(e)),x=f===`actor`||e.shape===`person`,S=d?`shape=rectangle;rounded=0;container=1;collapsible=0;startSize=0;`:x?`shape=actor;`:drawioShape(e.shape),C=l?.[e.id],w=u?.[e.id],T=C?applyStrokeColorOverride(getElementColors(r,e.color),C):getElementColors(r,e.color),E=T?.fill??`#dae8fc`,D=T?.stroke??`#2563eb`,O=T?.font??T?.stroke??`#1e40af`,k=`fillColor=${E};strokeColor=${D};fontColor=${O};`,A=e.style,j=a.fontSize(A?.textSize),ee=escapeXml(buildNodeValueHtml(p,m,d,O,o,j)),M=A?.border,N=w??getDefaultStrokeWidth(M,d),P=N===``?``:`strokeWidth=${N};`,F=getContainerDashedStyle(d,M),I=d===!0?A?.opacity??15:void 0,L=I!=null&&d===!0?`fillOpacity=${Math.min(100,Math.max(0,I))};`:``,R=buildLikec4StyleForNode({desc:m,tech:h,notes:g,tagList:v,navTo:y,iconName:b,summaryStr:toExportString(W.getSummary(e)),linksJson:linksToStyleJson(W.getLinks(e)),borderVal:M,containerOpacityNum:I,strokeWidth:N,colorNameForRoundtrip:e.color?encodeURIComponent(String(e.color)):``,nodeStyle:A,strokeHex:D,nodeNotation:W.getNotation(e)})+buildBridgeManagedStyleForNode(e.id,f,t.view.id,n),z=buildMxUserObjectXml(W.getCustomData(e)),B=buildNavLinkStyle(y);return{value:ee,styleStr:`${d?`align=left;verticalAlign=top;overflow=fill;whiteSpace=wrap;html=1;`:`align=center;verticalAlign=middle;verticalLabelPosition=middle;labelPosition=center;fontSize=${j};fontStyle=1;spacingTop=4;spacingLeft=2;spacingRight=2;spacingBottom=2;overflow=fill;whiteSpace=wrap;html=1;fontFamily=${encodeURIComponent(o)};`}${S}${k}${P}${F}${L}${B}${R}`,userObjectXml:z,navTo:y,isContainer:d,title:p,fontFamily:o,containerTitleFontSizePx:s,containerTitleColor:c}}function computeNodeCellExportData(e,t,n,r,i,a){let o=computeNodeGeometry(e,t,i),s=computeNodeStylePartsAndValue(e,t,n,r);return{...o,value:s.value,styleStr:s.styleStr,userObjectXml:s.userObjectXml,navTo:s.navTo,isContainer:s.isContainer,fontFamily:s.fontFamily,...s.isContainer&&{title:s.title??``,titleCellId:String(a),containerTitleFontSizePx:s.containerTitleFontSizePx,containerTitleColor:s.containerTitleColor}}}function buildNodeCellXml(e){let t=`<mxGeometry height="${Math.round(e.height)}" width="${Math.round(e.width)}" x="${Math.round(e.x)}" y="${Math.round(e.y)}" as="geometry" />`,n=e.userObjectXml===``?`\n ${t}`:`${e.userObjectXml}\n ${t}`,r=e.isContainer&&e.title!=null?escapeXml(e.title):e.value,i=e.navTo===``?`<mxCell id="${e.id}" value="${e.value}" style="${e.styleStr}" vertex="1" parent="${e.parentId}">\n ${n}\n</mxCell>`:`<UserObject label="${r}" link="${U}${escapeXml(e.navTo)}" id="${e.id}">\n <mxCell parent="${e.parentId}" style="${e.styleStr}" value="${e.value}" vertex="1">\n ${n}\n</mxCell>\n</UserObject>`;return e.isContainer?{vertexXml:i,titleCellXml:buildContainerTitleCellXml(e.title??``,e.titleCellId??e.id,e.navTo,e.id,e.fontFamily,e.containerTitleFontSizePx??12,e.containerTitleColor??`#74c0fc`),isContainer:!0}:{vertexXml:i,isContainer:!1}}function buildContainerTitleCellXml(e,t,n,r,i,a,o){let s=escapeXml(e),c=Math.max(60,Math.min(260,e.length*8)),l=buildNavLinkStyle(n),u=`shape=text;html=1;fillColor=none;strokeColor=none;align=left;verticalAlign=top;fontSize=${a};fontStyle=1;fontColor=${o};fontFamily=${encodeURIComponent(i)};${l}`;if(n===``)return`<mxCell id="${t}" value="${s}" style="${u}" vertex="1" parent="${r}">\n <mxGeometry x="8" y="8" width="${c}" height="18" as="geometry" />\n</mxCell>`;let d=`<mxCell parent="${r}" style="${u}" value="${s}" vertex="1">\n <mxGeometry x="8" y="8" width="${c}" height="18" as="geometry" />\n</mxCell>`;return`<UserObject label="${escapeXml(e)}" link="${U}${escapeXml(n)}" id="${t}">\n ${d}\n</UserObject>`}function getViewTitle(e){return typeof e.title==`string`?e.title:null}function getViewDescriptionString(e){let t=e.description;return typeof t==`object`&&t&&`txt`in t?String(t.txt):typeof t==`object`&&t&&`md`in t?String(t.md):typeof t==`string`?t:``}function getLeanixRootStyleParts(e,t){let n=[`bridgeManaged=true;`,`likec4ViewId=${encodeURIComponent(e.id)};`];return t.projectId!=null&&t.projectId!==``&&n.push(`likec4ProjectId=${encodeURIComponent(t.projectId)};`),n}function buildRootCellStyle(e,t){let n=getViewTitle(e),r=getViewDescriptionString(e),i=r.trim()===``?``:encodeURIComponent(r.trim()),a=e.notation,o=typeof a==`string`&&a!==``?a:void 0,s=o==null?``:encodeURIComponent(o),c=[`rounded=1;whiteSpace=wrap;html=1;fillColor=none;strokeColor=none;`,`likec4ViewTitle=${encodeURIComponent(n??e.id)};`,i===``?``:`likec4ViewDescription=${i};`,s===``?``:`likec4ViewNotation=${s};`];return t?.profile===`leanix`&&c.push(...getLeanixRootStyleParts(e,t)),c.join(``)}function drawioArrow(e){switch(e){case`none`:return`none`;case`open`:case`onormal`:case`vee`:return`open`;case`diamond`:case`odiamond`:return`diamond`;case`dot`:case`odot`:return`oval`;case`crow`:return`block`;default:return`block`}}const K={x:0,y:0,width:120,height:60};function isDefaultBbox(e){return e.x===K.x&&e.y===K.y&&e.width===K.width&&e.height===K.height}function spreadUnlaidNodesOverVertical(e,t,n){let bboxKey=e=>`${e.x},${e.y},${e.width},${e.height}`,r=t.filter(e=>!n.has(e.id)),i=new Map;for(let t of r){let n=e.get(t.id);if(!n)continue;let r=bboxKey(n),a=i.get(r)??[];a.push(t),i.set(r,a)}for(let t of i.values()){if(t.length<=1)continue;let n=t[0],r=n?e.get(n.id):void 0;r&&isDefaultBbox(r)&&t.forEach((t,n)=>{e.set(t.id,{...r,x:r.x,y:r.y+n*(r.height+24)})})}}function computeContainerBboxesFromChildren(e,t,n,r,i,a){let o=[...n].filter(e=>t.has(e.id)).sort((e,t)=>(t.level??0)-(e.level??0));for(let t of o){let n=(W.getChildren(t)??[]).filter(e=>r.has(e));if(n.length===0||!isDefaultBbox(e.get(t.id)))continue;let o=1/0,s=1/0,c=-1/0,l=-1/0;for(let t of n){let n=e.get(t);n&&(o=Math.min(o,n.x),s=Math.min(s,n.y),c=Math.max(c,n.x+n.width),l=Math.max(l,n.y+n.height))}o!==1/0&&e.set(t.id,{x:o-i,y:s-a,width:c-o+2*i,height:l-s+2*a})}}function computeContentBoundsAndOffsets(e){let t=1/0,n=1/0,r=-1/0,i=-1/0;for(let a of e.values())t=Math.min(t,a.x),n=Math.min(n,a.y),r=Math.max(r,a.x+a.width),i=Math.max(i,a.y+a.height);t===1/0&&(t=0),n===1/0&&(n=0),r===-1/0&&(r=t+800),i===-1/0&&(i=n+600);let a=t+(r-t)/2,o=n+(i-n)/2;return{offsetX:800/2-a,offsetY:600/2-o,canvasWidth:800,canvasHeight:600}}function computeDiagramLayout(e,t){let n=e.$view,{nodes:r}=n,i=t?.layoutOverride,a=[...r].sort((e,t)=>m(e.parent)&&m(t.parent)?0:m(e.parent)?-1:m(t.parent)?1:e.parent===t.parent?0:e.id.startsWith(t.id+`.`)?1:t.id.startsWith(e.id+`.`)?-1:0),getBBox=e=>{let t=i?.[e.id];if(t)return t;let n=e;return{x:typeof n.x==`number`?n.x:Array.isArray(n.position)?n.position[0]:0,y:typeof n.y==`number`?n.y:Array.isArray(n.position)?n.position[1]:0,width:typeof n.width==`number`?n.width:n.size?.width??120,height:typeof n.height==`number`?n.height:n.size?.height??60}},o=new Map;for(let e of a)o.set(e.id,getBBox(e));let s=new Set(r.map(e=>e.id)),c=new Set(r.filter(e=>{let t=W.getChildren(e);return Array.isArray(t)&&t.some(e=>s.has(e))}).map(e=>e.id));spreadUnlaidNodesOverVertical(o,a,c);let l=getEffectiveStyles(e),u=l.theme.spacing.xl;computeContainerBboxesFromChildren(o,c,a,s,u,l.theme.spacing.xl+l.theme.spacing.md);let{offsetX:d,offsetY:f,canvasWidth:p,canvasHeight:h}=computeContentBoundsAndOffsets(o);return{view:n,bboxes:o,containerNodeIds:c,sortedNodes:a,offsetX:d,offsetY:f,canvasWidth:p,canvasHeight:h,defaultParentId:`1`,rootId:`0`,effectiveStyles:l,fontFamily:`'IBM Plex Sans Variable',ui-sans-serif,system-ui,sans-serif`,containerTitleFontSizePx:Math.round(l.theme.textSizes.xs),containerTitleColor:`#74c0fc`,nodeIdsInView:s}}function generateDiagramContent(e,t){let n=e.$view,{edges:r}=n,i=t?.compressed!==!1,a=computeDiagramLayout(e,t),{sortedNodes:o,defaultParentId:s,rootId:c,canvasWidth:l,canvasHeight:u}=a,d=new Map,f=2,getCellId=e=>{let t=d.get(e);if(!t){if(f>=1e4)throw Error(`DrawIO cell ID range exhausted`);t=String(f++),d.set(e,t)}return t},p=[],m=[],h=[],g=1e4;for(let n of o){let r=buildNodeCellXml(computeNodeCellExportData(n,a,t,e,getCellId,g));r.isContainer?(p.push(r.vertexXml),r.titleCellXml&&p.push(r.titleCellXml),g++):m.push(r.vertexXml)}for(let n of r){if(f>=1e4)throw Error(`DrawIO cell ID range exhausted`);let r=String(f++);h.push(buildEdgeCellXml(n,a,t,e,getCellId,r))}let _=[`<mxCell id="${s}" value="" style="${buildRootCellStyle(n,t)}" vertex="1" parent="${c}">
255
+ `}}}const je=e(e=>e.charAt(0).toLocaleUpperCase()+e.slice(1),`capitalizeFirstLetter`),Me=e(e=>e.split(`.`).map(je).join(``),`fqnName`),Ne=e(e=>Me(e.parent?e.id.slice(e.parent.length+1):e.id),`nodeName`),d2direction=({autoLayout:e})=>{switch(e.direction){case`TB`:return`down`;case`BT`:return`up`;case`LR`:return`right`;case`RL`:return`left`}},d2shape=({shape:e})=>{switch(e){case`queue`:case`cylinder`:case`rectangle`:case`document`:return e;case`person`:return`c4-person`;case`storage`:return`stored_data`;case`component`:case`bucket`:case`mobile`:case`browser`:return`rectangle`}};function generateD2(e){let t=e.$view,{nodes:n,edges:r}=t,i=new Map,printNode=(e,t)=>{let r=Ne(e),a=(t?t+`.`:``)+r;i.set(e.id,a);let s=JSON.stringify(e.title),u=d2shape(e);return new o().append(r,`: {`,c).indent({indentedChildren:t=>t.append(`label: `,s,c).appendIf(u!==`rectangle`,`shape: `,u,c).appendIf(e.children.length>0,c,l(n.filter(t=>t.parent===e.id),e=>printNode(e,a))),indentation:2}).append(`}`,c)},printEdge=e=>new o().append(i.get(e.source),` -> `,i.get(e.target)).append(t=>e.label&&t.append(`: `,JSON.stringify(e.label)));return a(new o().append(`direction: `,d2direction(t),c,c).append(l(n.filter(e=>C(e.parent)),e=>printNode(e),{appendNewLineIfNotEmpty:!0})).appendIf(r.length>0,c,l(r,e=>printEdge(e),{appendNewLineIfNotEmpty:!0})))}const X=`data:page/id,likec4-`,Pe=`diagrams.drawio`;function escapeXml(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`).replaceAll(`"`,`&quot;`).replaceAll(`'`,`&apos;`)}function parseDrawioRoundtripComments(e){let t=e.split(/\r?\n/),n={},r={},i={},a={},o=!1,s=0;for(;s<t.length;){let e=t[s];if(e==null){s+=1;continue}if(e.trim()===`// <likec4.layout.drawio>`){o=!0,s+=1;let e=[];for(;s<t.length&&t[s]?.trim()!==`// </likec4.layout.drawio>`;){let n=t[s]?.trim();n?.startsWith(`// `)&&e.push(n.slice(3)),s+=1}if(e.length>0)try{let t=e.join(`
256
+ `);n=JSON.parse(t)}catch{}s+=1;continue}if(e.trim()===`// <likec4.strokeColor.vertices>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.strokeColor.vertices>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)&&e.includes(`=`)){let t=e.slice(3).trim(),n=t.indexOf(`=`);if(n>0){let e=t.slice(0,n).trim(),i=t.slice(n+1).trim();e&&i&&(r[e]=i)}}s+=1}s+=1;continue}if(e.trim()===`// <likec4.strokeWidth.vertices>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.strokeWidth.vertices>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)&&e.includes(`=`)){let t=e.slice(3).trim(),n=t.indexOf(`=`);if(n>0){let e=t.slice(0,n).trim(),r=t.slice(n+1).trim();e&&r!==``&&(i[e]=r)}}s+=1}s+=1;continue}if(e.trim()===`// <likec4.edge.waypoints>`){for(o=!0,s+=1;s<t.length&&t[s]?.trim()!==`// </likec4.edge.waypoints>`;){let e=t[s]?.trim();if(e?.startsWith(`// `)){let t=e.slice(3).trim(),n=t.indexOf(` `);if(n>0){let e=t.slice(0,n).trim(),r=t.slice(n+1).trim();if(e&&r)try{let t=JSON.parse(r);Array.isArray(t)&&(a[e]=t)}catch{}}}s+=1}s+=1;continue}s+=1}return o?{layoutByView:n,strokeColorByFqn:r,strokeWidthByFqn:i,edgeWaypoints:a}:null}function compressDrawioDiagramXml(e){let t=encodeURIComponent(e),n=new TextEncoder().encode(t);return uint8ArrayToBase64(ue.deflateRaw(n))}function uint8ArrayToBase64(e){if(typeof Buffer<`u`)return Buffer.from(e).toString(`base64`);let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}const Z={getNotes(e){return e.notes},getSummary(e){return e.summary},getTags(e){return e.tags},getNavigateTo(e){return e.navigateTo},getIcon(e){return e.icon},getLinks(e){return e.links},getNotation(e){return e.notation},getCustomData(e){return e.customData},getChildren(e){return e.children}},Q={getKind(e){return e.kind},getNotation(e){return e.notation},getLinks(e){return e.links},getMetadata(e){return e.metadata},getCustomData(e){return e.customData}};function getEffectiveStyles(e){return e.$styles??me.DEFAULT}function escapeHtml(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`).replaceAll(`"`,`&quot;`)}function toNonEmptyString(e){if(e==null)return``;let t=typeof e;if(t===`string`){let t=e;return t.trim()===``?``:t}return t===`number`||t===`boolean`?String(e):``}function getContainerDashedStyle(e,t){return e&&t!==`none`||t===`dashed`?`dashed=1;`:``}function getDefaultStrokeWidth(e,t){return e===`none`?`0`:t||e?`1`:``}function applyStrokeColorOverride(e,t){return{fill:e?.fill??`#dae8fc`,stroke:t,font:e?.font??t}}function resolveThemeColor(e,t,n){return t&&t in e.theme.colors?t:n}function getThemeColorValues(e,t,n){let r=getEffectiveStyles(e),i=resolveThemeColor(r,t??n,n);try{return r.colors(i)}catch{return me.DEFAULT.colors(n)}}function drawioShape(e){let t=`shape=rectangle;rounded=1;arcSize=12;`;switch(e){case`person`:return`shape=actor;`;case`rectangle`:case`browser`:case`mobile`:case`bucket`:return t;case`cylinder`:case`queue`:case`storage`:return`shape=cylinder3;whiteSpace=wrap;boundedLbl=1;backgroundOutline=1;size=15;`;case`document`:return`shape=document;whiteSpace=wrap;html=1;boundedLbl=1;`;case`component`:return`shape=component;`;default:return t}}function getElementColors(e,t){let n=getThemeColorValues(e,t,`primary`).elements;return{fill:String(n.fill??`#dae8fc`),stroke:String(n.stroke??`#2563eb`),font:String(n.hiContrast??n.stroke??`#1e40af`)}}function getEdgeStrokeColor(e,t){let n=getThemeColorValues(e,t??`gray`,`gray`);return String(n.relationships?.line??`#1e40af`)}function getEdgeLabelColors(e,t){let n=getThemeColorValues(e,t??`gray`,`gray`).relationships;return{font:String(n?.label??n?.line??`#1e40af`),background:String(n?.labelBg??`#ffffff`)}}function edgeAnchors(e,t){let n=e.x+e.width/2,r=e.y+e.height/2,i=t.x+t.width/2,a=t.y+t.height/2,o=i-n,s=a-r,c=Math.abs(o)>=Math.abs(s);return{exitX:c?+(o>=0):.5,exitY:c?.5:+(s>=0),entryX:c?o>=0?0:1:.5,entryY:c?.5:s>=0?0:1}}function normalizeEdgePoint(e){if(Array.isArray(e)&&e.length>=2&&typeof e[0]==`number`&&typeof e[1]==`number`)return[[e[0],e[1]]];let t=e;return typeof t.x==`number`&&typeof t.y==`number`?[[t.x,t.y]]:[]}function buildNodeValueHtml(e,t,n,r,i,a){return n?``:t===``?`<div style="box-sizing:border-box;width:100%;min-height:100%;display:flex;align-items:center;justify-content:center;text-align:center;color:${r};font-family:${i};"><b style="font-size:${a}px;">${escapeHtml(e)}</b></div>`:`<div style="box-sizing:border-box;width:100%;min-height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:${r};font-family:${i};"><b style="font-size:${a}px;">${escapeHtml(e)}</b><br/><span style="font-weight:normal;font-size:${a}px;">${escapeHtml(t)}</span></div>`}function pushStylePart(e,t,n){n!=null&&n!==``&&e.push(`${t}=${encodeURIComponent(n)}`)}function pushStylePartNum(e,t,n){n!=null&&e.push(`${t}=${n}`)}function buildNavLinkStyle(e){return e===``?``:`link=${encodeURIComponent(`${X}${e}`)};`}function toExportString(e){let t=e==null?null:L(e);return t!=null&&!S(t)?t.trim():``}function linksToStyleJson(e){return!Array.isArray(e)||e.length===0?``:encodeURIComponent(JSON.stringify(e.map(e=>({url:e.url,title:e.title}))))}function metadataToStyleJson(e){return typeof e!=`object`||!e||Array.isArray(e)||Object.keys(e).length===0?``:encodeURIComponent(JSON.stringify(e))}const Fe=/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;function buildLikec4StyleForNode(e){let t=[];return pushStylePart(t,`likec4Description`,e.desc),pushStylePart(t,`likec4Technology`,e.tech),pushStylePart(t,`likec4Notes`,e.notes),pushStylePart(t,`likec4Tags`,e.tagList),pushStylePart(t,`likec4NavigateTo`,e.navTo),pushStylePart(t,`likec4Icon`,e.iconName),pushStylePart(t,`likec4Summary`,e.summaryStr),e.linksJson!==``&&t.push(`likec4Links=${e.linksJson}`),pushStylePart(t,`likec4Border`,e.borderVal),pushStylePartNum(t,`likec4Opacity`,e.containerOpacityNum),pushStylePart(t,`likec4StrokeWidth`,e.strokeWidth),e.colorNameForRoundtrip!==``&&t.push(`likec4ColorName=${e.colorNameForRoundtrip}`),pushStylePart(t,`likec4Size`,e.nodeStyle?.size),pushStylePart(t,`likec4Padding`,e.nodeStyle?.padding),pushStylePart(t,`likec4TextSize`,e.nodeStyle?.textSize),pushStylePart(t,`likec4IconPosition`,e.nodeStyle?.iconPosition),e.strokeHex&&Fe.test(e.strokeHex)&&pushStylePart(t,`likec4StrokeColor`,e.strokeHex),pushStylePart(t,`likec4Notation`,e.nodeNotation??void 0),t.length>0?t.join(`;`)+`;`:``}function buildBridgeManagedStyleForNode(e,t,n,r){if(r?.profile!==`leanix`)return``;let i=[`bridgeManaged=true`,`likec4Id=${encodeURIComponent(e)}`,`likec4Kind=${encodeURIComponent(t)}`,`likec4ViewId=${encodeURIComponent(n)}`];r.projectId!=null&&r.projectId!==``&&i.push(`likec4ProjectId=${encodeURIComponent(r.projectId)}`);let a=r.leanixFactSheetTypeByKind?.[t];return a!=null&&a!==``&&i.push(`leanixFactSheetType=${encodeURIComponent(a)}`),i.join(`;`)+`;`}function buildBridgeManagedStyleForEdge(e,t){return t?.profile===`leanix`?`bridgeManaged=true;likec4RelationId=${encodeURIComponent(e)};`:``}function buildMxUserObjectXml(e){return!e||typeof e!=`object`||Array.isArray(e)||Object.keys(e).length===0?``:`
257
+ <mxUserObject>`+Object.entries(e).map(([e,t])=>{let n=typeof t==`string`?t:t==null?``:String(t);return`<data key="${escapeXml(e)}">${escapeXml(n)}</data>`}).join(``)+`</mxUserObject>`}function buildLikec4StyleForEdge(e){let t=[];return pushStylePart(t,`likec4Description`,e.edgeDesc),pushStylePart(t,`likec4Technology`,e.edgeTech),pushStylePart(t,`likec4Notes`,e.edgeNotes),pushStylePart(t,`likec4NavigateTo`,e.edgeNavTo),pushStylePart(t,`likec4RelationshipKind`,e.edgeKind??void 0),pushStylePart(t,`likec4Notation`,e.edgeNotation??void 0),e.edgeLinksJson!==``&&t.push(`likec4Links=${e.edgeLinksJson}`),e.edgeMetadataJson!==``&&t.push(`likec4Metadata=${e.edgeMetadataJson}`),t.length>0?t.join(`;`)+`;`:``}function buildEdgeLabelValue(e){return e.label?escapeXml(e.label):``}function buildEdgeGeometryXml(e,t){let n=t?.[`${e.source}|${e.target}|${e.id}`]??t?.[`${e.source}|${e.target}`],r=Array.isArray(n)?n.flatMap(normalizeEdgePoint):[];return r.length>0?`<mxGeometry relative="1" as="geometry">${`<Array as="points">`+r.map(([e,t])=>`<mxPoint x="${Math.round(e)}" y="${Math.round(t)}"/>`).join(``)+`</Array>`}</mxGeometry>`:`<mxGeometry relative="1" as="geometry" />`}function buildEdgeStyleString(e,t,n,r,i){let{bboxes:a,fontFamily:o}=t,s=a.get(e.source),c=a.get(e.target),l=s&&c?edgeAnchors(s,c):{exitX:1,exitY:.5,entryX:0,entryY:.5},u=`exitX=${l.exitX};exitY=${l.exitY};entryX=${l.entryX};entryY=${l.entryY};`,d=getEdgeStrokeColor(n,e.color),f=e.line===`dashed`?`dashed=1;`:e.line===`dotted`?`dashed=1;dashPattern=1 1;`:``,p=drawioArrow(e.head),m=e.tail==null||e.tail===`none`?`none`:drawioArrow(e.tail),h=buildLikec4StyleForEdge({edgeDesc:toExportString(e.description),edgeTech:toExportString(e.technology),edgeNotes:toExportString(e.notes),edgeNavTo:toNonEmptyString(e.navigateTo),edgeKind:Q.getKind(e),edgeNotation:Q.getNotation(e),edgeLinksJson:linksToStyleJson(Q.getLinks(e)),edgeMetadataJson:metadataToStyleJson(Q.getMetadata(e))}),g=buildBridgeManagedStyleForEdge(e.id,i),_=getEdgeLabelColors(n,e.color);return`endArrow=${p};startArrow=${m};html=1;rounded=0;${u}strokeColor=${d};strokeWidth=2;${f}${r===``?``:`fontColor=${_.font};fontSize=12;align=center;verticalAlign=middle;labelBackgroundColor=none;fontFamily=${encodeURIComponent(o)};`}${h}${g}`}function buildEdgeCellXml(e,t,n,r,i,a){let{defaultParentId:o}=t,s=i(e.source),c=i(e.target),l=buildEdgeLabelValue(e),u=buildEdgeGeometryXml(e,n?.edgeWaypoints);return`<mxCell id="${a}" value="${l}" style="${buildEdgeStyleString(e,t,r,l,n)}" edge="1" parent="${o}" source="${s}" target="${c}">
258
+ ${u}${buildMxUserObjectXml(Q.getCustomData(e))}
259
+ </mxCell>`}function computeNodeGeometry(e,t,n){let{bboxes:r,defaultParentId:i,nodeIdsInView:a}=t,o=n(e.id),s=r.get(e.id),{width:c,height:l}=s,u=e.parent!=null&&a.has(e.parent)?n(e.parent):i,d=e.parent==null?void 0:r.get(e.parent);return{id:o,parentId:u,x:d==null?s.x+t.offsetX:s.x-d.x,y:d==null?s.y+t.offsetY:s.y-d.y,width:c,height:l}}function computeNodeStylePartsAndValue(e,t,n,r){let{containerNodeIds:i,effectiveStyles:a,fontFamily:o,containerTitleFontSizePx:s,containerTitleColor:c}=t,l=n?.strokeColorByNodeId,u=n?.strokeWidthByNodeId,d=i.has(e.id),f=e.kind??``,p=e.title,m=toExportString(e.description),h=toExportString(e.technology),g=toExportString(Z.getNotes(e)),_=Z.getTags(e),v=Array.isArray(_)&&_.length>0?_.join(`,`):``,y=toNonEmptyString(Z.getNavigateTo(e)),b=toNonEmptyString(Z.getIcon(e)),ee=f===`actor`||e.shape===`person`,te=d?`shape=rectangle;rounded=0;container=1;collapsible=0;startSize=0;`:ee?`shape=actor;`:drawioShape(e.shape),x=l?.[e.id],S=u?.[e.id],C=x?applyStrokeColorOverride(getElementColors(r,e.color),x):getElementColors(r,e.color),w=C?.fill??`#dae8fc`,T=C?.stroke??`#2563eb`,E=C?.font??C?.stroke??`#1e40af`,D=`fillColor=${w};strokeColor=${T};fontColor=${E};`,O=e.style,k=a.fontSize(O?.textSize),ne=escapeXml(buildNodeValueHtml(p,m,d,E,o,k)),A=O?.border,j=S??getDefaultStrokeWidth(A,d),re=j===``?``:`strokeWidth=${j};`,M=getContainerDashedStyle(d,A),N=d===!0?O?.opacity??15:void 0,P=N!=null&&d===!0?`fillOpacity=${Math.min(100,Math.max(0,N))};`:``,ie=buildLikec4StyleForNode({desc:m,tech:h,notes:g,tagList:v,navTo:y,iconName:b,summaryStr:toExportString(Z.getSummary(e)),linksJson:linksToStyleJson(Z.getLinks(e)),borderVal:A,containerOpacityNum:N,strokeWidth:j,colorNameForRoundtrip:e.color?encodeURIComponent(String(e.color)):``,nodeStyle:O,strokeHex:T,nodeNotation:Z.getNotation(e)})+buildBridgeManagedStyleForNode(e.id,f,t.view.id,n),F=buildMxUserObjectXml(Z.getCustomData(e)),ae=buildNavLinkStyle(y);return{value:ne,styleStr:`${d?`align=left;verticalAlign=top;overflow=fill;whiteSpace=wrap;html=1;`:`align=center;verticalAlign=middle;verticalLabelPosition=middle;labelPosition=center;fontSize=${k};fontStyle=1;spacingTop=4;spacingLeft=2;spacingRight=2;spacingBottom=2;overflow=fill;whiteSpace=wrap;html=1;fontFamily=${encodeURIComponent(o)};`}${te}${D}${re}${M}${P}${ae}${ie}`,userObjectXml:F,navTo:y,isContainer:d,title:p,fontFamily:o,containerTitleFontSizePx:s,containerTitleColor:c}}function computeNodeCellExportData(e,t,n,r,i,a){let o=computeNodeGeometry(e,t,i),s=computeNodeStylePartsAndValue(e,t,n,r);return{...o,value:s.value,styleStr:s.styleStr,userObjectXml:s.userObjectXml,navTo:s.navTo,isContainer:s.isContainer,fontFamily:s.fontFamily,...s.isContainer&&{title:s.title??``,titleCellId:String(a),containerTitleFontSizePx:s.containerTitleFontSizePx,containerTitleColor:s.containerTitleColor}}}function buildNodeCellXml(e){let t=`<mxGeometry height="${Math.round(e.height)}" width="${Math.round(e.width)}" x="${Math.round(e.x)}" y="${Math.round(e.y)}" as="geometry" />`,n=e.userObjectXml===``?`\n ${t}`:`${e.userObjectXml}\n ${t}`,r=e.isContainer&&e.title!=null?escapeXml(e.title):e.value,i=e.navTo===``?`<mxCell id="${e.id}" value="${e.value}" style="${e.styleStr}" vertex="1" parent="${e.parentId}">\n ${n}\n</mxCell>`:`<UserObject label="${r}" link="${X}${escapeXml(e.navTo)}" id="${e.id}">\n <mxCell parent="${e.parentId}" style="${e.styleStr}" value="${e.value}" vertex="1">\n ${n}\n</mxCell>\n</UserObject>`;return e.isContainer?{vertexXml:i,titleCellXml:buildContainerTitleCellXml(e.title??``,e.titleCellId??e.id,e.navTo,e.id,e.fontFamily,e.containerTitleFontSizePx??12,e.containerTitleColor??`#74c0fc`),isContainer:!0}:{vertexXml:i,isContainer:!1}}function buildContainerTitleCellXml(e,t,n,r,i,a,o){let s=escapeXml(e),c=Math.max(60,Math.min(260,e.length*8)),l=buildNavLinkStyle(n),u=`shape=text;html=1;fillColor=none;strokeColor=none;align=left;verticalAlign=top;fontSize=${a};fontStyle=1;fontColor=${o};fontFamily=${encodeURIComponent(i)};${l}`;if(n===``)return`<mxCell id="${t}" value="${s}" style="${u}" vertex="1" parent="${r}">\n <mxGeometry x="8" y="8" width="${c}" height="18" as="geometry" />\n</mxCell>`;let d=`<mxCell parent="${r}" style="${u}" value="${s}" vertex="1">\n <mxGeometry x="8" y="8" width="${c}" height="18" as="geometry" />\n</mxCell>`;return`<UserObject label="${escapeXml(e)}" link="${X}${escapeXml(n)}" id="${t}">\n ${d}\n</UserObject>`}function getViewTitle(e){return typeof e.title==`string`?e.title:null}function getViewDescriptionString(e){let t=e.description;return typeof t==`object`&&t&&`txt`in t?String(t.txt):typeof t==`object`&&t&&`md`in t?String(t.md):typeof t==`string`?t:``}function getLeanixRootStyleParts(e,t){let n=[`bridgeManaged=true;`,`likec4ViewId=${encodeURIComponent(e.id)};`];return t.projectId!=null&&t.projectId!==``&&n.push(`likec4ProjectId=${encodeURIComponent(t.projectId)};`),n}function buildRootCellStyle(e,t){let n=getViewTitle(e),r=getViewDescriptionString(e),i=r.trim()===``?``:encodeURIComponent(r.trim()),a=e.notation,o=typeof a==`string`&&a!==``?a:void 0,s=o==null?``:encodeURIComponent(o),c=[`rounded=1;whiteSpace=wrap;html=1;fillColor=none;strokeColor=none;`,`likec4ViewTitle=${encodeURIComponent(n??e.id)};`,i===``?``:`likec4ViewDescription=${i};`,s===``?``:`likec4ViewNotation=${s};`];return t?.profile===`leanix`&&c.push(...getLeanixRootStyleParts(e,t)),c.join(``)}function drawioArrow(e){switch(e){case`none`:return`none`;case`open`:case`onormal`:case`vee`:return`open`;case`diamond`:case`odiamond`:return`diamond`;case`dot`:case`odot`:return`oval`;case`crow`:return`block`;default:return`block`}}const $={x:0,y:0,width:120,height:60};function isDefaultBbox(e){return e.x===$.x&&e.y===$.y&&e.width===$.width&&e.height===$.height}function spreadUnlaidNodesOverVertical(e,t,n){let bboxKey=e=>`${e.x},${e.y},${e.width},${e.height}`,r=t.filter(e=>!n.has(e.id)),i=new Map;for(let t of r){let n=e.get(t.id);if(!n)continue;let r=bboxKey(n),a=i.get(r)??[];a.push(t),i.set(r,a)}for(let t of i.values()){if(t.length<=1)continue;let n=t[0],r=n?e.get(n.id):void 0;r&&isDefaultBbox(r)&&t.forEach((t,n)=>{e.set(t.id,{...r,x:r.x,y:r.y+n*(r.height+24)})})}}function computeContainerBboxesFromChildren(e,t,n,r,i,a){let o=[...n].filter(e=>t.has(e.id)).sort((e,t)=>(t.level??0)-(e.level??0));for(let t of o){let n=(Z.getChildren(t)??[]).filter(e=>r.has(e));if(n.length===0||!isDefaultBbox(e.get(t.id)))continue;let o=1/0,s=1/0,c=-1/0,l=-1/0;for(let t of n){let n=e.get(t);n&&(o=Math.min(o,n.x),s=Math.min(s,n.y),c=Math.max(c,n.x+n.width),l=Math.max(l,n.y+n.height))}o!==1/0&&e.set(t.id,{x:o-i,y:s-a,width:c-o+2*i,height:l-s+2*a})}}function computeContentBoundsAndOffsets(e){let t=1/0,n=1/0,r=-1/0,i=-1/0;for(let a of e.values())t=Math.min(t,a.x),n=Math.min(n,a.y),r=Math.max(r,a.x+a.width),i=Math.max(i,a.y+a.height);t===1/0&&(t=0),n===1/0&&(n=0),r===-1/0&&(r=t+800),i===-1/0&&(i=n+600);let a=t+(r-t)/2,o=n+(i-n)/2;return{offsetX:800/2-a,offsetY:600/2-o,canvasWidth:800,canvasHeight:600}}function computeDiagramLayout(e,t){let n=e.$view,{nodes:r}=n,i=t?.layoutOverride,a=[...r].sort((e,t)=>C(e.parent)&&C(t.parent)?0:C(e.parent)?-1:C(t.parent)?1:e.parent===t.parent?0:e.id.startsWith(t.id+`.`)?1:t.id.startsWith(e.id+`.`)?-1:0),getBBox=e=>{let t=i?.[e.id];if(t)return t;let n=e;return{x:typeof n.x==`number`?n.x:Array.isArray(n.position)?n.position[0]:0,y:typeof n.y==`number`?n.y:Array.isArray(n.position)?n.position[1]:0,width:typeof n.width==`number`?n.width:n.size?.width??120,height:typeof n.height==`number`?n.height:n.size?.height??60}},o=new Map;for(let e of a)o.set(e.id,getBBox(e));let s=new Set(r.map(e=>e.id)),c=new Set(r.filter(e=>{let t=Z.getChildren(e);return Array.isArray(t)&&t.some(e=>s.has(e))}).map(e=>e.id));spreadUnlaidNodesOverVertical(o,a,c);let l=getEffectiveStyles(e),u=l.theme.spacing.xl;computeContainerBboxesFromChildren(o,c,a,s,u,l.theme.spacing.xl+l.theme.spacing.md);let{offsetX:d,offsetY:f,canvasWidth:p,canvasHeight:m}=computeContentBoundsAndOffsets(o);return{view:n,bboxes:o,containerNodeIds:c,sortedNodes:a,offsetX:d,offsetY:f,canvasWidth:p,canvasHeight:m,defaultParentId:`1`,rootId:`0`,effectiveStyles:l,fontFamily:`'IBM Plex Sans Variable',ui-sans-serif,system-ui,sans-serif`,containerTitleFontSizePx:Math.round(l.theme.textSizes.xs),containerTitleColor:`#74c0fc`,nodeIdsInView:s}}function generateDiagramContent(e,t){let n=e.$view,{edges:r}=n,i=t?.compressed!==!1,a=computeDiagramLayout(e,t),{sortedNodes:o,defaultParentId:s,rootId:c,canvasWidth:l,canvasHeight:u}=a,d=new Map,f=2,getCellId=e=>{let t=d.get(e);if(!t){if(f>=1e4)throw Error(`DrawIO cell ID range exhausted`);t=String(f++),d.set(e,t)}return t},p=[],m=[],h=[],g=1e4;for(let n of o){let r=buildNodeCellXml(computeNodeCellExportData(n,a,t,e,getCellId,g));r.isContainer?(p.push(r.vertexXml),r.titleCellXml&&p.push(r.titleCellXml),g++):m.push(r.vertexXml)}for(let n of r){if(f>=1e4)throw Error(`DrawIO cell ID range exhausted`);let r=String(f++);h.push(buildEdgeCellXml(n,a,t,e,getCellId,r))}let _=[`<mxCell id="${s}" value="" style="${buildRootCellStyle(n,t)}" vertex="1" parent="${c}">
72
260
  <mxGeometry x="0" y="0" width="${l}" height="${u}" as="geometry" />
73
261
  </mxCell>`,...p,...m,...h].join(`
74
262
  `),v=(getViewTitle(n)??n.id).trim()||n.id,y=`<mxGraphModel dx="800" dy="800" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
@@ -84,8 +272,8 @@ export let krokiPumlSvgUrl = import.meta.env.VITE_KROKI_D2_SVG_URL || 'https://k
84
272
  ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}">${e.content}</diagram>`).join(`
85
273
  `)}
86
274
  </mxfile>
87
- `}function generateDrawio(e,t){return wrapInMxFile([generateDiagramContent(e,t)],t?.modified)}function generateDrawioMulti(e,t,n){return wrapInMxFile(e.map(e=>generateDiagramContent(e,t?.[e.$view.id])),n)}function buildOptionsFromRoundtrip(e,t,n){let r={compressed:!1,...n};if(!t)return r;let i=t.layoutByView[e]?.nodes;return i!=null&&(r.layoutOverride=i),Object.keys(t.strokeColorByFqn).length>0&&(r.strokeColorByNodeId=t.strokeColorByFqn),Object.keys(t.strokeWidthByFqn).length>0&&(r.strokeWidthByNodeId=t.strokeWidthByFqn),Object.keys(t.edgeWaypoints).length>0&&(r.edgeWaypoints=t.edgeWaypoints),r}function buildDrawioExportOptionsForViews(e,t,n){let r=t?parseDrawioRoundtripComments(t):null;return Object.fromEntries(e.map(e=>[e,buildOptionsFromRoundtrip(e,r,n)]))}function generateDrawioEditUrl(e){let t=compressDrawioDiagramXml(e),n=JSON.stringify({type:`xml`,compressed:!0,data:t});return`https://app.diagrams.net/#create=`+encodeURIComponent(n)}const ce=e(e=>e.charAt(0).toLocaleUpperCase()+e.slice(1),`capitalizeFirstLetter`),le=e(e=>e.split(`.`).map(ce).join(``),`fqnName`),ue=e(e=>le(e.parent?e.id.slice(e.parent.length+1):e.id),`nodeName`),toSingleQuotes=e=>e.replace(/\\?"/g,`'`),mmdshape=({shape:e,title:t})=>{let n=`label: ${JSON.stringify(t)}`;switch(e){case`queue`:return`@{ shape: horizontal-cylinder, ${n} }`;case`person`:return`@{ icon: "fa:user", shape: rounded, ${n} }`;case`storage`:return`@{ shape: disk, ${n} }`;case`cylinder`:return`@{ shape: cylinder, ${n} }`;case`mobile`:case`browser`:return`@{ shape: rounded, ${n} }`;case`bucket`:return`@{ shape: trap-t, ${n} }`;case`rectangle`:return`@{ shape: rectangle, ${n} }`;case`document`:return`@{ shape: doc, ${n} }`;case`component`:return`@{ shape: rectangle, ${n} }`;default:N(e)}};function generateMermaid(e){let t=e.$view,{nodes:n,edges:r}=t,i=new Map,printNode=(e,t)=>{let r=ue(e),a=(t?t+`.`:``)+r;i.set(e.id,a);let l=new o;if(e.children.length>0){let t=toSingleQuotes(e.title);l.append(`subgraph `,a,'["`',t,'`"]',s).indent({indentedChildren:[c(n.filter(t=>t.parent===e.id),e=>printNode(e,a),{appendNewLineIfNotEmpty:!0})],indentation:2}).append(`end`,s)}else l.append(a,mmdshape(e));return l},printEdge=e=>new o().append(i.get(e.source),` -.`,e.label?' "`'+toSingleQuotes(e.label)+'`" .-':`-`,`> `,i.get(e.target));return a(new o().append(`---`,s,`title: ${JSON.stringify(toSingleQuotes(e.titleOrId))}`,s,`---`,s).append(`graph `,t.autoLayout.direction,s).indent({indentedChildren:e=>{e.append(c(n.filter(e=>m(e.parent)),e=>printNode(e),{appendNewLineIfNotEmpty:!0})).appendIf(r.length>0,c(r,e=>printEdge(e),{appendNewLineIfNotEmpty:!0}))},indentation:2}))}const capitalizeFirstLetter=e=>e.charAt(0).toLocaleUpperCase()+e.slice(1),fqnName=e=>e.split(/[.-]/).map(capitalizeFirstLetter).join(``),nodeName=e=>fqnName(e.parent?e.id.slice(e.parent.length+1):e.id),pumlColor=(e,t,n=`#3b82f6`)=>e?t(e)??n:n,pumlDirection=({autoLayout:e})=>{switch(e.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:e})=>{switch(e){case`queue`:case`rectangle`:case`person`:return e;case`storage`:case`cylinder`:return`database`;case`component`:return`component`;case`document`:case`mobile`:case`bucket`:case`browser`:return`rectangle`;default:N(e)}},escapeLabel=e=>f(e)?null:JSON.stringify(e).slice(1,-1).replace(/\\"/g,`"`);function generatePuml(e){let t=e.$view,n=e.$model.$styles.theme.colors,{nodes:r,edges:i}=t,elementColorProvider=e=>t=>t in n?n[t].elements[e]:void 0,relationshipsColorProvider=e=>t=>t in n?n[t].relationships[e]:void 0,l=new Map,printHeader=()=>new o().append(`title "`,e.titleOrId,`"`,s).append(pumlDirection(t),` direction`,s),printTheme=()=>new o().append(`hide stereotype`,s).append(`skinparam ranksep `,`60`,s).append(`skinparam nodesep `,`30`,s).append(`skinparam {`,s).indent({indentedChildren:e=>e.append(`arrowFontSize `,`10`,s).append(`defaultTextAlignment `,`center`,s).append(`wrapWidth `,`200`,s).append(`maxMessageSize `,`100`,s).append(`shadowing `,`false`,s),indentation:2}).append(`}`,s),printStereotypes=e=>{let t=pumlShape(e),n=fqnName(e.id);return new o().append(`skinparam `,t,`<<`,n,`>>`,`{`,s).indent({indentedChildren:t=>t.append(`BackgroundColor `,pumlColor(e.color,elementColorProvider(`fill`)),s).append(`FontColor `,pumlColor(e.color,elementColorProvider(`hiContrast`),`#FFFFFF`),s).append(`BorderColor `,pumlColor(e.color,elementColorProvider(`stroke`)),s),indentation:2}).append(`}`,s)},printNode=e=>{let t=pumlShape(e),n=fqnName(e.id),r=escapeLabel(e.title)||nodeName(e),i=escapeLabel(e.technology);l.set(e.id,n);let a=F.from(e.description);return new o().append(t,` `).append(`"`).append(`==`,r).appendIf(!!i,`\\n<size:10>[`,i,`]</size>`).appendIf(a.nonEmpty,`\\n\\n`,escapeLabel(a.text)).append(`"`,` <<`,n,`>> `,`as `,n,s)},printBoundary=e=>{let t=escapeLabel(e.title)||nodeName(e),n=fqnName(e.id);return l.set(e.id,n),new o().append(`rectangle "`,t,`" <<`,n,`>> as `,n,` {`,s).indent({indentedChildren:t=>t.append(`skinparam `,`RectangleBorderColor<<`,n,`>> `,pumlColor(e.color,elementColorProvider(`fill`)),s).append(`skinparam `,`RectangleFontColor<<`,n,`>> `,pumlColor(e.color,elementColorProvider(`fill`)),s).append(`skinparam `,`RectangleBorderStyle<<`,n,`>> `,`dashed`,s,s).append(c(r.filter(t=>t.parent===e.id),e=>e.children.length>0?printBoundary(e):printNode(e))),indentation:2}).append(`}`,s)},printEdge=e=>{let t=e.technology||``,n=e.label||t,r=pumlColor(e.color,relationshipsColorProvider(`line`),`#777777`),withColor=e=>`<color:${r}>${e.replaceAll(`"`,`'`)}`,i=new o().append(l.get(e.source),` .[`,r,`,thickness=2].> `,l.get(e.target));return(n||t)&&(i.append(` : `,n.split(`
88
- `).map(e=>f(e)?e:withColor(e)).join(`\\n`)),t&&t!==n&&i.append(`\\n<size:8>[`,withColor(t),`]</size>`)),i.append(s)};return a(new o().append(`@startuml`,s).append(printHeader(),s).append(printTheme(),s).append(c(r.filter(e=>e.children.length==0),e=>printStereotypes(e),{appendNewLineIfNotEmpty:!0})).append(c(r.filter(e=>m(e.parent)),e=>e.children.length>0?printBoundary(e):printNode(e),{appendNewLineIfNotEmpty:!0})).appendIf(i.length>0,s,c(i,e=>printEdge(e),{appendNewLineIfNotEmpty:!0})).append(`@enduml`,s))}function code$9(e){let t=new o;return t.appendTemplate`
275
+ `}function generateDrawio(e,t){return wrapInMxFile([generateDiagramContent(e,t)],t?.modified)}function generateDrawioMulti(e,t,n){return wrapInMxFile(e.map(e=>generateDiagramContent(e,t?.[e.$view.id])),n)}function buildOptionsFromRoundtrip(e,t,n){let r={compressed:!1,...n};if(!t)return r;let i=t.layoutByView[e]?.nodes;return i!=null&&(r.layoutOverride=i),Object.keys(t.strokeColorByFqn).length>0&&(r.strokeColorByNodeId=t.strokeColorByFqn),Object.keys(t.strokeWidthByFqn).length>0&&(r.strokeWidthByNodeId=t.strokeWidthByFqn),Object.keys(t.edgeWaypoints).length>0&&(r.edgeWaypoints=t.edgeWaypoints),r}function buildDrawioExportOptionsForViews(e,t,n){let r=t?parseDrawioRoundtripComments(t):null;return Object.fromEntries(e.map(e=>[e,buildOptionsFromRoundtrip(e,r,n)]))}function generateDrawioEditUrl(e){let t=compressDrawioDiagramXml(e),n=JSON.stringify({type:`xml`,compressed:!0,data:t});return`https://app.diagrams.net/#create=`+encodeURIComponent(n)}const Ie=e(e=>e.charAt(0).toLocaleUpperCase()+e.slice(1),`capitalizeFirstLetter`),Le=e(e=>e.split(`.`).map(Ie).join(``),`fqnName`),Re=e(e=>Le(e.parent?e.id.slice(e.parent.length+1):e.id),`nodeName`),toSingleQuotes=e=>e.replace(/\\?"/g,`'`),mmdshape=({shape:e,title:t})=>{let n=`label: ${JSON.stringify(t)}`;switch(e){case`queue`:return`@{ shape: horizontal-cylinder, ${n} }`;case`person`:return`@{ icon: "fa:user", shape: rounded, ${n} }`;case`storage`:return`@{ shape: disk, ${n} }`;case`cylinder`:return`@{ shape: cylinder, ${n} }`;case`mobile`:case`browser`:return`@{ shape: rounded, ${n} }`;case`bucket`:return`@{ shape: trap-t, ${n} }`;case`rectangle`:return`@{ shape: rectangle, ${n} }`;case`document`:return`@{ shape: doc, ${n} }`;case`component`:return`@{ shape: rectangle, ${n} }`;default:ge(e)}};function generateMermaid(e){let t=e.$view,{nodes:n,edges:r}=t,i=new Map,printNode=(e,t)=>{let r=Re(e),a=(t?t+`.`:``)+r;i.set(e.id,a);let s=new o;if(e.children.length>0){let t=toSingleQuotes(e.title);s.append(`subgraph `,a,'["`',t,'`"]',c).indent({indentedChildren:[l(n.filter(t=>t.parent===e.id),e=>printNode(e,a),{appendNewLineIfNotEmpty:!0})],indentation:2}).append(`end`,c)}else s.append(a,mmdshape(e));return s},printEdge=e=>new o().append(i.get(e.source),` -.`,e.label?' "`'+toSingleQuotes(e.label)+'`" .-':`-`,`> `,i.get(e.target));return a(new o().append(`---`,c,`title: ${JSON.stringify(toSingleQuotes(e.titleOrId))}`,c,`---`,c).append(`graph `,t.autoLayout.direction,c).indent({indentedChildren:e=>{e.append(l(n.filter(e=>C(e.parent)),e=>printNode(e),{appendNewLineIfNotEmpty:!0})).appendIf(r.length>0,l(r,e=>printEdge(e),{appendNewLineIfNotEmpty:!0}))},indentation:2}))}const capitalizeFirstLetter=e=>e.charAt(0).toLocaleUpperCase()+e.slice(1),fqnName=e=>e.split(/[.-]/).map(capitalizeFirstLetter).join(``),nodeName=e=>fqnName(e.parent?e.id.slice(e.parent.length+1):e.id),pumlColor=(e,t,n=`#3b82f6`)=>e?t(e)??n:n,pumlDirection=({autoLayout:e})=>{switch(e.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:e})=>{switch(e){case`queue`:case`rectangle`:case`person`:return e;case`storage`:case`cylinder`:return`database`;case`component`:return`component`;case`document`:case`mobile`:case`bucket`:case`browser`:return`rectangle`;default:ge(e)}},escapeLabel=e=>S(e)?null:JSON.stringify(e).slice(1,-1).replace(/\\"/g,`"`);function generatePuml(e){let t=e.$view,n=e.$model.$styles.theme.colors,{nodes:r,edges:i}=t,elementColorProvider=e=>t=>t in n?n[t].elements[e]:void 0,relationshipsColorProvider=e=>t=>t in n?n[t].relationships[e]:void 0,s=new Map,printHeader=()=>new o().append(`title "`,e.titleOrId,`"`,c).append(pumlDirection(t),` direction`,c),printTheme=()=>new o().append(`hide stereotype`,c).append(`skinparam ranksep `,`60`,c).append(`skinparam nodesep `,`30`,c).append(`skinparam {`,c).indent({indentedChildren:e=>e.append(`arrowFontSize `,`10`,c).append(`defaultTextAlignment `,`center`,c).append(`wrapWidth `,`200`,c).append(`maxMessageSize `,`100`,c).append(`shadowing `,`false`,c),indentation:2}).append(`}`,c),printStereotypes=e=>{let t=pumlShape(e),n=fqnName(e.id);return new o().append(`skinparam `,t,`<<`,n,`>>`,`{`,c).indent({indentedChildren:t=>t.append(`BackgroundColor `,pumlColor(e.color,elementColorProvider(`fill`)),c).append(`FontColor `,pumlColor(e.color,elementColorProvider(`hiContrast`),`#FFFFFF`),c).append(`BorderColor `,pumlColor(e.color,elementColorProvider(`stroke`)),c),indentation:2}).append(`}`,c)},printNode=e=>{let t=pumlShape(e),n=fqnName(e.id),r=escapeLabel(e.title)||nodeName(e),i=escapeLabel(e.technology);s.set(e.id,n);let a=fe.from(e.description);return new o().append(t,` `).append(`"`).append(`==`,r).appendIf(!!i,`\\n<size:10>[`,i,`]</size>`).appendIf(a.nonEmpty,`\\n\\n`,escapeLabel(a.text)).append(`"`,` <<`,n,`>> `,`as `,n,c)},printBoundary=e=>{let t=escapeLabel(e.title)||nodeName(e),n=fqnName(e.id);return s.set(e.id,n),new o().append(`rectangle "`,t,`" <<`,n,`>> as `,n,` {`,c).indent({indentedChildren:t=>t.append(`skinparam `,`RectangleBorderColor<<`,n,`>> `,pumlColor(e.color,elementColorProvider(`fill`)),c).append(`skinparam `,`RectangleFontColor<<`,n,`>> `,pumlColor(e.color,elementColorProvider(`fill`)),c).append(`skinparam `,`RectangleBorderStyle<<`,n,`>> `,`dashed`,c,c).append(l(r.filter(t=>t.parent===e.id),e=>e.children.length>0?printBoundary(e):printNode(e))),indentation:2}).append(`}`,c)},printEdge=e=>{let t=e.technology||``,n=e.label||t,r=pumlColor(e.color,relationshipsColorProvider(`line`),`#777777`),withColor=e=>`<color:${r}>${e.replaceAll(`"`,`'`)}`,i=new o().append(s.get(e.source),` .[`,r,`,thickness=2].> `,s.get(e.target));return(n||t)&&(i.append(` : `,n.split(`
276
+ `).map(e=>S(e)?e:withColor(e)).join(`\\n`)),t&&t!==n&&i.append(`\\n<size:8>[`,withColor(t),`]</size>`)),i.append(c)};return a(new o().append(`@startuml`,c).append(printHeader(),c).append(printTheme(),c).append(l(r.filter(e=>e.children.length==0),e=>printStereotypes(e),{appendNewLineIfNotEmpty:!0})).append(l(r.filter(e=>C(e.parent)),e=>e.children.length>0?printBoundary(e):printNode(e),{appendNewLineIfNotEmpty:!0})).appendIf(i.length>0,c,l(i,e=>printEdge(e),{appendNewLineIfNotEmpty:!0})).append(`@enduml`,c))}function code$9(e){let t=new o;return t.appendTemplate`
89
277
  /******************************************************************************
90
278
  * This file was generated
91
279
  * DO NOT EDIT MANUALLY!
@@ -94,7 +282,7 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
94
282
 
95
283
  export let d2Source = (viewId) => {
96
284
  switch (viewId) {
97
- `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(c([...e.views()],e=>i`
285
+ `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(l([...e.views()],e=>s`
98
286
  case ${JSON.stringify(e.id)}: {
99
287
  return ${JSON.stringify(generateD2(e))}
100
288
  }
@@ -102,9 +290,9 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
102
290
  default: {
103
291
  throw new Error('Unknown viewId: ' + viewId)
104
292
  }
105
- `}}).append(s,` }`,s).appendTemplate`
293
+ `}}).append(c,` }`,c).appendTemplate`
106
294
  }
107
- `.append(s,s),a(t)}e(code$9,`code`);const de={...generateMatches(`d2`),async load({likec4:e,project:t}){return logGenerating(`d2`,t.id),{code:code$9(await e.computedModel(t.id)),moduleType:`js`}}},fe=generateCombinedProjects(`d2`,`loadD2Sources`);function code$8(e){let t=new o;return t.appendTemplate`
295
+ `.append(c,c),a(t)}e(code$9,`code`);const ze={...generateMatches(`d2`),async load({likec4:e,project:t}){return logGenerating(`d2`,t.id),{code:code$9(await e.computedModel(t.id)),moduleType:`js`}}},Be=generateCombinedProjects(`d2`,`loadD2Sources`);function code$8(e){let t=new o;return t.appendTemplate`
108
296
  /******************************************************************************
109
297
  * This file was generated
110
298
  * DO NOT EDIT MANUALLY!
@@ -113,7 +301,7 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
113
301
 
114
302
  export let dotSource = (viewId) => {
115
303
  switch (viewId) {
116
- `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(c(Object.keys(e),t=>i`
304
+ `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(l(Object.keys(e),t=>s`
117
305
  case ${JSON.stringify(t)}: {
118
306
  return ${JSON.stringify(e[t].dot)}
119
307
  }
@@ -121,12 +309,12 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
121
309
  default: {
122
310
  throw new Error('Unknown viewId: ' + viewId)
123
311
  }
124
- `}}).append(s,` }`,s).appendTemplate`
312
+ `}}).append(c,` }`,c).appendTemplate`
125
313
  }
126
314
 
127
315
  export let svgSource = (viewId) => {
128
316
  switch (viewId) {
129
- `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(c(Object.keys(e),t=>i`
317
+ `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(l(Object.keys(e),t=>s`
130
318
  case ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(t))}: {
131
319
  return ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(e[t].svg))}
132
320
  }
@@ -134,7 +322,7 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
134
322
  default: {
135
323
  throw new Error('Unknown viewId: ' + viewId)
136
324
  }
137
- `}}).append(s,` }`,s,`}`,s,s),a(t)}e(code$8,`code`);const pe={...generateMatches(`dot`),async load({likec4:e,project:t}){return logGenerating(`dot`,t.id),{code:code$8(w(await e.views.viewsAsGraphvizOut(t.id),({id:e,svg:t,dot:n})=>[e,{dot:n,svg:t}])),moduleType:`js`}}},me=generateCombinedProjects(`dot`,`loadDotSources`);function code$7(e){let t=new o;return t.appendTemplate`
325
+ `}}).append(c,` }`,c,`}`,c,c),a(t)}e(code$8,`code`);const Ve={...generateMatches(`dot`),async load({likec4:e,project:t}){return logGenerating(`dot`,t.id),{code:code$8(ie(await e.views.viewsAsGraphvizOut(t.id),({id:e,svg:t,dot:n})=>[e,{dot:n,svg:t}])),moduleType:`js`}}},He=generateCombinedProjects(`dot`,`loadDotSources`);function code$7(e){let t=new o;return t.appendTemplate`
138
326
  /******************************************************************************
139
327
  * This file was generated
140
328
  * DO NOT EDIT MANUALLY!
@@ -143,7 +331,7 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
143
331
 
144
332
  export function drawioEditUrl(viewId) {
145
333
  switch (viewId) {
146
- `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(c([...e.views()],e=>i`
334
+ `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(l([...e.views()],e=>s`
147
335
  case ${JSON.stringify(e.id)}: {
148
336
  return ${JSON.stringify(generateDrawioEditUrl(generateDrawio(e)))}
149
337
  }
@@ -151,9 +339,9 @@ ${e.map(e=>` <diagram name="${escapeXml(e.name)}" id="likec4-${escapeXml(e.id)}
151
339
  default: {
152
340
  throw new Error('Unknown viewId: ' + viewId)
153
341
  }
154
- `}}).append(s,` }`,s).appendTemplate`
342
+ `}}).append(c,` }`,c).appendTemplate`
155
343
  }
156
- `.append(s,s),a(t)}e(code$7,`code`);const he={...generateMatches(`drawio`),async load({likec4:e,project:t}){return logGenerating(`drawio`,t.id),{code:code$7(await e.layoutedModel(t.id)),moduleType:`js`}}},ge=generateCombinedProjects(`drawio`,`loadDrawioSources`),_e=/^(https?:)?\/\//i;function code$6(e){let{imports:t,cases:n}=v(e,y(e=>e.nodes),T(e=>e.icon??void 0),g(e=>p(e)&&!_e.test(e)),S(),x(L)).reduce((e,t,n)=>{let r=t.startsWith(`file:`),i=`Icon`+n.toString().padStart(2,`0`);if(r)return e.imports.push(`import ${i} from '${t}?inline'`),e.cases.push(` '${t}': () => jsx('img', { src: ${i} })`),e;let[a,o]=t.split(`:`),s=`likec4:icon-bundle/${a}/${o}.jsx`;return e.imports.push(`import ${i} from '${s}'`),e.cases.push(` '${a}:${o}': ${i}`),e},{imports:[],cases:[]});return`
344
+ `.append(c,c),a(t)}e(code$7,`code`);const Ue={...generateMatches(`drawio`),async load({likec4:e,project:t}){return logGenerating(`drawio`,t.id),{code:code$7(await e.layoutedModel(t.id)),moduleType:`js`}}},We=generateCombinedProjects(`drawio`,`loadDrawioSources`),Ge=/^(https?:)?\/\//i;function code$6(e){let{imports:t,cases:n}=A(e,te(e=>e.nodes),F(e=>e.icon??void 0),D(e=>b(e)&&!Ge.test(e)),N(),re(_e)).reduce((e,t,n)=>{let r=t.startsWith(`file:`),i=`Icon`+n.toString().padStart(2,`0`);if(r)return e.imports.push(`import ${i} from '${t}?inline'`),e.cases.push(` '${t}': () => jsx('img', { src: ${i} })`),e;let[a,o]=t.split(`:`),s=`likec4:icon-bundle/${a}/${o}.jsx`;return e.imports.push(`import ${i} from '${s}'`),e.cases.push(` '${a}:${o}': ${i}`),e},{imports:[],cases:[]});return`
157
345
  import { jsx } from 'react/jsx-runtime'
158
346
  ${t.join(`
159
347
  `)}
@@ -169,7 +357,7 @@ export function IconRenderer({ node, ...props }) {
169
357
  }
170
358
  return jsx(IconComponent, props)
171
359
  }
172
- `}e(code$6,`code`);const ve={...generateMatches(`icons`,`.jsx`),async load({likec4:e,project:t}){logGenerating(`icons`,t.id);let n=await e.computedModel(t.id);return{moduleType:`jsx`,code:code$6([...C(n.$data.views),...C(n.$data.manualLayouts??{})])}}},q=/^[a-zA-Z0-9_.-]+$/;function embedProjectIdAsJsString(e){if(!q.test(e))throw Error(`Unsafe value for code generation: ${e}`);return JSON.stringify(e)}function embedUrlAsJsString(e){return JSON.stringify(e)}const J={id:`likec4:icons`,virtualId:`likec4:plugin/icons.jsx`,async load({projects:e,logger:t}){logGenerating(`icons`);let{imports:n,cases:r}=e.filter(e=>q.test(e.id)?!0:(t.warn(l.yellow(`Skipping project with unsafe id for icons registry: ${e.id}`)),!1)).reduce((e,t,n)=>{let r=`Project`+n.toString().padStart(2,`0`),i=hardenJsonStringLiteralForEmbeddedScript(embedProjectIdAsJsString(t.id)),a=hardenJsonStringLiteralForEmbeddedScript(embedUrlAsJsString(u(`likec4:icons`,t.id)));return e.imports.push(`import {IconRenderer as ${r}} from ${a}`),e.cases.push(` ${i}: ${r}`),e},{imports:[],cases:[]});return{code:`
360
+ `}e(code$6,`code`);const Ke={...generateMatches(`icons`,`.jsx`),async load({likec4:e,project:t}){logGenerating(`icons`,t.id);let n=await e.computedModel(t.id);return{moduleType:`jsx`,code:code$6([...P(n.$data.views),...P(n.$data.manualLayouts??{})])}}},qe=/^[a-zA-Z0-9_.-]+$/;function embedProjectIdAsJsString(e){if(!qe.test(e))throw Error(`Unsafe value for code generation: ${e}`);return JSON.stringify(e)}function embedUrlAsJsString(e){return JSON.stringify(e)}const Je={id:`likec4:icons`,virtualId:`likec4:plugin/icons.jsx`,async load({projects:e,logger:t}){logGenerating(`icons`);let{imports:n,cases:r}=e.filter(e=>qe.test(e.id)?!0:(t.warn(u.yellow(`Skipping project with unsafe id for icons registry: ${e.id}`)),!1)).reduce((e,t,n)=>{let r=`Project`+n.toString().padStart(2,`0`),i=hardenJsonStringLiteralForEmbeddedScript(embedProjectIdAsJsString(t.id)),a=hardenJsonStringLiteralForEmbeddedScript(embedUrlAsJsString(d(`likec4:icons`,t.id)));return e.imports.push(`import {IconRenderer as ${r}} from ${a}`),e.cases.push(` ${i}: ${r}`),e},{imports:[],cases:[]});return{code:`
173
361
  import { jsx } from 'react/jsx-runtime'
174
362
  ${n.join(`
175
363
  `)}
@@ -218,7 +406,7 @@ if (import.meta.hot) {
218
406
 
219
407
  export let mmdSource = (viewId) => {
220
408
  switch (viewId) {
221
- `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(c([...e.views()],e=>i`
409
+ `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(l([...e.views()],e=>s`
222
410
  case ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(e.id))}: {
223
411
  return ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(generateMermaid(e)))}
224
412
  }
@@ -226,13 +414,13 @@ if (import.meta.hot) {
226
414
  default: {
227
415
  throw new Error('Unknown viewId: ' + viewId)
228
416
  }
229
- `}}).append(s,` }`,s).appendTemplate`
417
+ `}}).append(c,` }`,c).appendTemplate`
230
418
  }
231
419
 
232
- `.append(s,s),a(t)}e(code$5,`code`);const ye={...generateMatches(`mmd`),async load({likec4:e,project:t}){return logGenerating(`mmd`,t.id),{code:code$5(await e.computedModel(t.id)),moduleType:`js`}}},be=generateCombinedProjects(`mmd`,`loadMmdSources`),projectModelCode=e=>`
420
+ `.append(c,c),a(t)}e(code$5,`code`);const Ye={...generateMatches(`mmd`),async load({likec4:e,project:t}){return logGenerating(`mmd`,t.id),{code:code$5(await e.computedModel(t.id)),moduleType:`js`}}},Xe=generateCombinedProjects(`mmd`,`loadMmdSources`),projectModelCode=e=>`
233
421
  import { createHooksForModel, atom } from 'likec4/vite-plugin/internal'
234
422
 
235
- export let $likec4data = atom(${d.stringify(e.$data)})
423
+ export let $likec4data = atom(${f.stringify(e.$data)})
236
424
 
237
425
  export let {
238
426
  updateModel,
@@ -255,11 +443,11 @@ if (import.meta.hot) {
255
443
  }
256
444
  })
257
445
  }
258
- `,xe={...generateMatches(`model`),async load({likec4:e,project:t}){return logGenerating(`model`,t.id),{code:projectModelCode(await e.layoutedModel(t.id)),moduleType:`js`}}},Y=generateCombinedProjects(`model`,`loadModel`),Se=e(e=>`
446
+ `,Ze={...generateMatches(`model`),async load({likec4:e,project:t}){return logGenerating(`model`,t.id),{code:projectModelCode(await e.layoutedModel(t.id)),moduleType:`js`}}},Qe=generateCombinedProjects(`model`,`loadModel`),$e=e(e=>`
259
447
  import { atom, useStore } from 'likec4/vite-plugin/internal'
260
448
 
261
449
  export const isSingleProject = ${e.length===1};
262
- export const projects = ${d.stringify(e,null,2)};
450
+ export const projects = ${f.stringify(e,null,2)};
263
451
 
264
452
  export const $projects = atom([...projects])
265
453
 
@@ -285,10 +473,10 @@ if (import.meta.hot) {
285
473
  }
286
474
  })
287
475
  }
288
- `,`code`),X={id:`likec4:projects`,virtualId:`likec4:plugin/projects.js`,async load({projects:e}){return logGenerating(`projects`),{code:Se(T(e,e=>({id:e.id,title:e.title,landingPage:e.config.landingPage}))),moduleType:`js`}}},Ce=e(e=>`
476
+ `,`code`),et={id:`likec4:projects`,virtualId:`likec4:plugin/projects.js`,async load({projects:e}){return logGenerating(`projects`),{code:$e(F(e,e=>({id:e.id,title:e.title,landingPage:e.config.landingPage}))),moduleType:`js`}}},tt=e(e=>`
289
477
  import { atom, useStore } from 'likec4/vite-plugin/internal'
290
478
 
291
- export const $viewdata = atom(${d.stringify(e)})
479
+ export const $viewdata = atom(${f.stringify(e)})
292
480
 
293
481
  export function useLikeC4ProjectsOverview() {
294
482
  return useStore($viewdata)
@@ -311,7 +499,7 @@ if (import.meta.hot) {
311
499
  export function useLikeC4ProjectsOverview() {
312
500
  throw new Error('No projects overview available for this workspace: single project mode is enabled')
313
501
  }
314
- `,Z={id:`likec4:projects-overview`,virtualId:`likec4:plugin/projects-overview.js`,async load({projects:e,likec4:t}){return e.length<2?noProjects():(logGenerating(`projects-overview`),{code:Ce(await t.projectsOverview()),moduleType:`js`})}};function code$2(e){let t=new o;return t.appendTemplate`
502
+ `,nt={id:`likec4:projects-overview`,virtualId:`likec4:plugin/projects-overview.js`,async load({projects:e,likec4:t}){return e.length<2?noProjects():(logGenerating(`projects-overview`),{code:tt(await t.projectsOverview()),moduleType:`js`})}};function code$2(e){let t=new o;return t.appendTemplate`
315
503
  /******************************************************************************
316
504
  * This file was generated
317
505
  * DO NOT EDIT MANUALLY!
@@ -320,7 +508,7 @@ export function useLikeC4ProjectsOverview() {
320
508
 
321
509
  export let pumlSource = (viewId) => {
322
510
  switch (viewId) {
323
- `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(c([...e.views()],e=>i`
511
+ `.appendNewLine().indent({indentation:4,indentedChildren(t){t.append(l([...e.views()],e=>s`
324
512
  case ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(e.id))}: {
325
513
  return ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(generatePuml(e)))}
326
514
  }
@@ -328,9 +516,9 @@ export function useLikeC4ProjectsOverview() {
328
516
  default: {
329
517
  throw new Error('Unknown viewId: ' + viewId)
330
518
  }
331
- `}}).append(s,` }`,s).appendTemplate`
519
+ `}}).append(c,` }`,c).appendTemplate`
332
520
  }
333
- `.append(s,s),a(t)}e(code$2,`code`);const we={...generateMatches(`puml`),async load({likec4:e,project:t}){return logGenerating(`puml`,t.id),{code:code$2(await e.computedModel(t.id)),moduleType:`js`}}},Te=generateCombinedProjects(`puml`,`loadPumlSources`),projectCode=e=>`
521
+ `.append(c,c),a(t)}e(code$2,`code`);const rt={...generateMatches(`puml`),async load({likec4:e,project:t}){return logGenerating(`puml`,t.id),{code:code$2(await e.computedModel(t.id)),moduleType:`js`}}},it=generateCombinedProjects(`puml`,`loadPumlSources`),projectCode=e=>`
334
522
  import { jsx as _jsx } from "react/jsx-runtime";
335
523
  import { LikeC4ModelProvider as Provider, LikeC4View as GenericView, ReactLikeC4 as GenericReactLikeC4 } from 'likec4/react';
336
524
  import { IconRenderer } from 'likec4:icons/${e}'
@@ -353,20 +541,22 @@ export {
353
541
  useLikeC4View,
354
542
  useLikeC4Views
355
543
  }
356
- `,Ee={...generateMatches(`react`),async load({project:e}){return logGenerating(`react`,e.id),{code:projectCode(e.id),moduleType:`js`}}},De={id:`likec4:react`,virtualId:`likec4:plugin/react.js`,async load({projects:e}){let t=h(e);return logGenerating(`react-default-project`),{code:`export {
544
+ `,at={...generateMatches(`react`),async load({project:e}){return logGenerating(`react`,e.id),{code:projectCode(e.id),moduleType:`js`}}},ot={id:`likec4:react`,virtualId:`likec4:plugin/react.js`,async load({projects:e}){let t=M(e);return logGenerating(`react-default-project`),{code:`export {
357
545
  useLikeC4Model,
358
546
  useLikeC4View,
359
547
  useLikeC4Views,
360
548
  LikeC4ModelProvider,
361
549
  LikeC4View,
362
550
  ReactLikeC4
363
- } from 'likec4:react/${t.id}'`,moduleType:`js`}}},Oe={id:`likec4:rpc`,virtualId:`likec4:plugin/rpc.js`,async load(){return logGenerating(`rpc`),{code:`
551
+ } from 'likec4:react/${t.id}'`,moduleType:`js`}}},st=e(({isAIAvailable:e,ai:t,rpcEnabled:n})=>`
364
552
  import { createRpc } from 'likec4/vite-plugin/internal'
365
553
 
366
- export const isRpcAvailable = !!import.meta.hot
554
+ export const isRpcAvailable = !!import.meta.hot && ${n}
555
+ export const isAIAvailable = isRpcAvailable && ${e}
556
+ export const AIAdapter = ${JSON.stringify(t?.adapter.name)}
367
557
 
368
558
  let rpc
369
- if (import.meta.hot) {
559
+ if (isRpcAvailable) {
370
560
  rpc = createRpc({
371
561
  send: (event, data) => {
372
562
  import.meta.hot.send(event, data)
@@ -380,6 +570,9 @@ if (import.meta.hot) {
380
570
  }
381
571
 
382
572
  export const likec4rpc = rpc ?? {
573
+ applySemanticLayout: () => {
574
+ throw new Error('likec4rpc.applySemanticLayout is not available in production')
575
+ },
383
576
  updateView: () => {
384
577
  throw new Error('likec4rpc.updateView is not available in production')
385
578
  },
@@ -387,7 +580,7 @@ export const likec4rpc = rpc ?? {
387
580
  throw new Error('likec4rpc.calcAdhocView is not available in production')
388
581
  },
389
582
  }
390
- `,moduleType:`js`,moduleSideEffects:!1}}},code=e=>`
583
+ `,`code`),ct={id:`likec4:rpc`,virtualId:`likec4:plugin/rpc.js`,async load(e){return logGenerating(`rpc`),{code:st(e),moduleType:`js`,moduleSideEffects:!1}}},code=e=>`
391
584
  export { IconRenderer } from 'likec4:icons/${e}'
392
585
  export {
393
586
  $likec4data,
@@ -397,4 +590,4 @@ export {
397
590
  useLikeC4View
398
591
  } from 'likec4:model/${e}'
399
592
  export const projectId = ${hardenJsonStringLiteralForEmbeddedScript(JSON.stringify(e))}
400
- `,ke={id:`likec4:single-project`,virtualId:`likec4:plugin/single-project.js`,async load({projects:e}){let t=h(e);return logGenerating(`single-project`,t.id),code(t.id)}},Q=[xe,ve,de,pe,ye,we,he],$=[...Q,Ee],Ae=[X,Y,Z,ke,De,fe,me,be,Te,ge,J,Oe];function LikeC4VitePlugin({environments:e,appConfig:t,...i}){let a,o,s=i.watch??!1,c=[...Ae,createAppConfigModule(t)],projectsChangeDetector=e=>{let t=T(e=>({id:e.id,title:e.title,folder:e.folder.toString(),landingPage:e.config.landingPage})),n=t(e);return e=>{let r=t(e);return _(n,r)?!1:(n=r,!0)}};return[iconBundlePlugin({environments:e?[e].flat():void 0,workspace:i.workspace??i.languageServices?.workspacePath}),{name:`vite-plugin-likec4`,applyToEnvironment(t){return e?e.includes(t.name):!0},async configResolved(e){if(i.languageServices)a=i.languageServices;else{let t=e.mode===`development`,n=s=i.watch??t;a=(await r(i.workspace??e.root,{graphviz:i.graphviz??`wasm`,configureLogger:`console`,logLevel:i.logLevel??`warning`,printErrors:i.printErrors??!0,throwIfInvalid:i.throwIfInvalid??!1,watch:n})).languageServices}o=a.workspaceUri.fsPath},resolveId:{filter:{id:/^likec4:/},handler(e){for(let t of $){let n=t.matches(e);if(n)return t.virtualId(n)}for(let t of c)if(t.id===e)return t.virtualId;return null}},load:{filter:{id:/likec4:plugin/},async handler(e){for(let t of $){let n=t.matches(e);if(n){let e=a.project(n);return await t.load.call(this,{logger:V,likec4:a,project:e,assetsDir:o})}}for(let t of c)if(t.virtualId===e){let e=a.projects();return ee(M(e)),await t.load.call(this,{logger:V,likec4:a,projects:e,assetsDir:o})}return null}},configureServer(e){let t=e.hot;enablePluginRPC.call(this,{logger:V,likec4:a,server:e});let r=projectsChangeDetector(a.projects()),reloadModule=async t=>{let r=e.moduleGraph.getModuleById(t);if(!(!r||r.importers.size===0))try{await e.reloadModule(r)}catch(e){V.error(n(e))}};a.builder.onModelParsed(E(async()=>{let[e]=a.getErrors();if(e){t.send({type:`error`,err:{name:`LikeC4ValidationError`,...splitErrorMessage(e.message),plugin:`vite-plugin-likec4`,loc:{file:e.sourceFsPath,line:e.line,column:e.range.start.character+1}}});return}let n=a.projects();if(r(n)){await reloadModule(X.virtualId),await reloadModule(J.virtualId),await reloadModule(Y.virtualId),n.length>1&&await reloadModule(Z.virtualId);return}for(let e of n)for(let t of Q)await reloadModule(t.virtualId(e.id))},100))},async buildEnd(){s&&await a.dispose()}}]}export{generateDrawio as a,generateD2 as c,buildDrawioExportOptionsForViews as i,generatePuml as n,generateDrawioMulti as o,generateMermaid as r,oe as s,LikeC4VitePlugin as t};
593
+ `,lt={id:`likec4:single-project`,virtualId:`likec4:plugin/single-project.js`,async load({projects:e}){let t=M(e);return logGenerating(`single-project`,t.id),code(t.id)}},ut=[Ze,Ke,ze,Ve,Ye,rt,Ue],dt=[...ut,at],ft=[et,Qe,nt,lt,ot,Be,He,Xe,it,We,Je,ct];function LikeC4VitePlugin({environments:e,appConfig:t,ai:n=`auto`,...a}){let o,s,c=!1,l,d=a.watch??!1,f=[...ft,createAppConfigModule(t)],initAI=async()=>{if(ee(n))throw Error(`Invalid AI configuration: true is not allowed, use an object with adapter configuration or false to disable AI`);if(n!==`disabled`)return n===`auto`?await we():n};function moduleopts(e){return{rpcEnabled:c,isAIAvailable:!!l,ai:l,assetsDir:s,likec4:o,logger:U,...e}}let projectsChangeDetector=()=>{let e=F(e=>({id:e.id,title:e.title,folder:e.folder.toString(),landingPage:e.config.landingPage})),t;return n=>{let r=e(n);return t??=r,ae(t,r)?!1:(t=r,!0)}};return[iconBundlePlugin({environments:e?[e].flat():void 0,workspace:a.workspace??a.languageServices?.workspacePath}),{name:`vite-plugin-likec4`,sharedDuringBuild:!0,applyToEnvironment(t){return e?e.includes(t.name):!0},async configResolved(e){let t=c=e.command===`serve`;if(a.languageServices)o=a.languageServices;else{let n=d=t&&(a.watch??!0);o=(await r(a.workspace??e.root,{manualLayouts:!0,graphviz:a.graphviz??`wasm`,configureLogger:`console`,logLevel:a.logLevel??`warning`,printErrors:a.printErrors??!0,throwIfInvalid:a.throwIfInvalid??!1,watch:n})).languageServices}s=o.workspaceUri.fsPath,c&&(l=await initAI())},resolveId:{filter:{id:/^likec4:/},handler(e){for(let t of dt){let n=t.matches(e);if(n)return t.virtualId(n)}for(let t of f)if(t.id===e)return t.virtualId;return null}},load:{filter:{id:/likec4:plugin/},async handler(e){for(let t of dt){let n=t.matches(e);if(n){let e=o.project(n);return await t.load.call(this,moduleopts({project:e}))}}for(let t of f)if(t.virtualId===e){let e=o.projects();return T(e,1)?await t.load.call(this,moduleopts({projects:e})):null}return null}},async configureServer(e){if(c){if(enablePluginRPC.call(this,moduleopts({server:e})),l){U.info(u.dim(`enabling`)+` `+u.magenta(`AI Chat`));let{enableAIServer:t}=await import(`./enableServer.mjs`);t.call(this,moduleopts({server:e}))}return()=>{let t=e.hot,n=projectsChangeDetector(),reloadModule=async t=>{let n=e.moduleGraph.getModuleById(t);if(!n||n.importers.size===0)return!1;try{return await e.reloadModule(n),!0}catch(e){return U.error(i(e)),!1}},hasErrors=()=>{let[e]=o.getErrors();if(!e)return!1;try{t.send({type:`error`,err:{name:`LikeC4ValidationError`,...splitErrorMessage(e.message),plugin:`vite-plugin-likec4`,loc:{file:e.sourceFsPath,line:e.line,column:e.range.start.character+1}}}),U.trace(u.dim(`sent LikeC4ValidationError`))}catch(e){U.error(i(e))}return!0},reloadProjects=async()=>{let e=o.projects();n(e)?(U.trace(u.dim(`onProjectsUpdate - change detected`)),await reloadModule(et.virtualId),await reloadModule(Je.virtualId),await reloadModule(Qe.virtualId),e.length>1&&await reloadModule(nt.virtualId)):U.trace(u.dim(`onProjectsUpdate - no change`))};o.projectsManager.onProjectsUpdate(oe(reloadProjects,100)),o.builder.onModelParsed(onModelParsedBatched(async e=>{if(!hasErrors())for(let t of e){U.trace(u.dim(`onModelParsed project`)+` `+u.cyan(t));for(let e of ut)await reloadModule(e.virtualId(t))}}))}}},async buildEnd(){d&&await o.dispose()}}]}function onModelParsedBatched(e){return x(t=>{e(t).catch(e=>{U.error(i(e))})},{reducer:(e,t)=>(e??=new Set,e.add(t),e),triggerAt:`end`,minQuietPeriodMs:130,maxBurstDurationMs:500}).call}export{generateDrawio as a,generateD2 as c,buildDrawioExportOptionsForViews as i,enhanceLayoutWithAI as l,generatePuml as n,generateDrawioMulti as o,generateMermaid as r,Pe as s,LikeC4VitePlugin as t,U as u};