likec4 1.55.0 → 1.55.1

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{s as e}from"../_chunks/rolldown-runtime.mjs";import"../_chunks/libs/birpc.mjs";import{$ as t,C as n,K as r,W as i,Y as a,Z as o,k as s,m as c,t as l,w as u,x as d}from"../_chunks/libs/remeda.mjs";import"../_chunks/libs/@logtape/logtape.mjs";import"../_chunks/libs/merge-error-cause.mjs";import"../_chunks/libs/is-error-instance.mjs";import"../_chunks/libs/is-plain-obj.mjs";import"../_chunks/libs/safe-stringify.mjs";import{a as f,c as p,d as m,f as h,i as g,l as _,n as v,o as y,r as ee,s as b,u as te}from"../_chunks/node.mjs";import{t as ne}from"../_chunks/libs/defu.mjs";import{H as re,V as ie}from"../_chunks/libs/langium.mjs";import"../_chunks/libs/@chevrotain/regexp-to-ast.mjs";import"../_chunks/libs/chevrotain.mjs";import"../_chunks/libs/@chevrotain/cst-dts-gen.mjs";import"../_chunks/libs/@chevrotain/utils.mjs";import"../_chunks/libs/chevrotain-allstar.mjs";import{t as x}from"../_chunks/libs/tinyrainbow.mjs";import{c as ae,l as oe,o as se,r as ce,s as le}from"../_chunks/libs/ufo.mjs";import"../_chunks/libs/json5.mjs";import{i as ue,n as de,r as fe,t as pe}from"../_chunks/libs/@hono/mcp.mjs";import"../_chunks/src.mjs";import"../_chunks/libs/pathe.mjs";import"../_chunks/sequence.mjs";import"../_chunks/libs/@lume/kiwi.mjs";import"../_chunks/libs/ts-graphviz.mjs";import"../_chunks/libs/word-wrap.mjs";import"../_chunks/libs/khroma.mjs";import"../_chunks/libs/p-limit.mjs";import"../_chunks/libs/eventemitter3.mjs";import"../_chunks/libs/p-queue.mjs";import"../_chunks/libs/isexe.mjs";import"../_chunks/libs/which.mjs";import"../_chunks/libs/parse-ms.mjs";import{t as me}from"../_chunks/libs/pretty-ms.mjs";import{t as he}from"../_chunks/libs/picomatch.mjs";import"../_chunks/libs/p-timeout.mjs";import"../_chunks/libs/fast-equals.mjs";import{n as ge}from"../_chunks/libs/strip-indent.mjs";import"../_chunks/libs/destr.mjs";import"../_chunks/libs/unstorage.mjs";import{a as _e,c as ve,d as ye,i as be,l as xe,n as Se,o as Ce,r as we,s as Te,t as Ee,u as De}from"../_chunks/src2.mjs";import"../_chunks/libs/pako.mjs";import{LikeC4Model as Oe}from"../model/index.mjs";import"../_chunks/libs/is-docker.mjs";import{t as S}from"../_chunks/libs/is-inside-container.mjs";import"../_chunks/libs/ansi-regex.mjs";import{t as ke}from"../_chunks/libs/boxen.mjs";import"../_chunks/libs/ansi-align.mjs";import"../_chunks/libs/ansi-styles.mjs";import"../_chunks/libs/find-up-simple.mjs";import{t as Ae}from"../_chunks/libs/package-up.mjs";import{n as je,t as Me}from"../_chunks/libs/package-manager-detector.mjs";import{t as Ne}from"../_chunks/libs/esm-env.mjs";import{n as Pe,t as Fe}from"../_chunks/libs/conf.mjs";import"../_chunks/libs/atomically.mjs";import{a as C,c as w,d as T,f as Ie,i as Le,l as E,n as D,o as Re,p as ze,r as O,s as k,t as Be,u as A}from"../_chunks/libs/@modelcontextprotocol/sdk.mjs";import"../_chunks/libs/ajv.mjs";import{t as Ve}from"../_chunks/libs/ky.mjs";import{n as He,t as Ue}from"../_chunks/libs/get-port.mjs";import{t as We}from"../_chunks/libs/vscode-languageserver.mjs";import{t as Ge}from"../_chunks/libs/@hono/node-server.mjs";import Ke from"node:module";import{isDeploymentElementModel as qe,isDeploymentNodeModel as Je,isDeploymentRelationModel as Ye,isElementModel as Xe,isLikeC4ViewModel as Ze,isRelationModel as Qe,modelConnection as $e}from"@likec4/core/model";import{invariant as j,nonexhaustive as et}from"@likec4/core";import{basename as tt,dirname as M,extname as nt,isAbsolute as rt,join as N,relative as P,resolve as F,sep as it}from"node:path";import{ifilter as at,invariant as ot,isSameHierarchy as st}from"@likec4/core/utils";import ct from"nano-spawn";import{tmpdir as lt}from"node:os";import{resolve as I}from"path";import{env as ut,isCI as dt,isDevelopment as ft,isTest as pt,nodeENV as mt}from"std-env";import{copyFile as ht,mkdir as L,mkdtemp as gt,readFile as _t,readdir as vt,realpath as yt,rm as bt,stat as xt,writeFile as R}from"node:fs/promises";import{copyFileSync as St,existsSync as z,readFileSync as Ct,readdirSync as wt,rmSync as Tt,statSync as Et}from"node:fs";import{argv as Dt,cwd as Ot,exit as kt,hrtime as At,stdout as jt}from"node:process";import Mt from"yargs";import{hideBin as Nt}from"yargs/helpers";import{fileURLToPath as Pt,pathToFileURL as Ft}from"node:url";import It from"@vitejs/plugin-react";import{viteSingleFile as Lt}from"vite-plugin-singlefile";import{build as Rt,createServer as zt,preview as Bt}from"vite";import{setTimeout as Vt}from"node:timers/promises";import{setTimeout as Ht}from"node:timers";var Ut=`likec4`,Wt=`1.55.0`;const B=p.getChild(`cli`);function V(e){let t=p.getChild(e);return{info(e){t.info(e)},debug(e,...n){n.length===0?t.debug(e):t.debug(e,{args:n})},warn(e){if(e instanceof Error){t.warn(`${x.red(e.name+` `+e.message)}`,{msg:e});return}if(typeof e==`string`){t.warn(e);return}t.warn`${e}`},warnOnce(e){t.warn(e)},error(e,n){let r=n?.error??e;if(r instanceof Error){if(e===r){t.error(`${x.red(r.name+` `+r.message)}`,{error:r});return}t.error(x.red(e),{error:r});return}if(typeof e==`string`){t.error(x.red(e));return}t.error`${e}`},clearScreen:function(e){},hasErrorLogged:function(e){return!1},hasWarned:!1}}function Gt(e){let[t,n]=At(e),r=t*1e3+n/1e6;return{ms:r,pretty:me(r)}}function H(e){let t=At();return{stopAndLog(n=`done in `){n=x.green(`${n}${Gt(t).pretty}`),(e||B).info(n)}}}function U(e,t){console.log(ke(e,{padding:1,margin:1,dimBorder:!0,...t}))}const Kt=V(`vite`),qt=M(Pt(import.meta.url)),Jt={banner:`/* prettier-ignore-start */
2
+ import{s as e}from"../_chunks/rolldown-runtime.mjs";import"../_chunks/libs/birpc.mjs";import{$ as t,C as n,K as r,W as i,Y as a,Z as o,k as s,m as c,t as l,w as u,x as d}from"../_chunks/libs/remeda.mjs";import"../_chunks/libs/@logtape/logtape.mjs";import"../_chunks/libs/merge-error-cause.mjs";import"../_chunks/libs/is-error-instance.mjs";import"../_chunks/libs/is-plain-obj.mjs";import"../_chunks/libs/safe-stringify.mjs";import{a as f,c as p,d as m,f as h,i as g,l as _,n as v,o as y,r as b,s as ee,u as te}from"../_chunks/node.mjs";import{t as x}from"../_chunks/libs/defu.mjs";import{H as S,V as ne}from"../_chunks/libs/langium.mjs";import"../_chunks/libs/@chevrotain/regexp-to-ast.mjs";import"../_chunks/libs/chevrotain.mjs";import"../_chunks/libs/@chevrotain/cst-dts-gen.mjs";import"../_chunks/libs/@chevrotain/utils.mjs";import"../_chunks/libs/chevrotain-allstar.mjs";import{t as C}from"../_chunks/libs/tinyrainbow.mjs";import{c as re,l as ie,o as ae,r as oe,s as se}from"../_chunks/libs/ufo.mjs";import"../_chunks/libs/json5.mjs";import{i as ce,n as le,r as ue,t as de}from"../_chunks/libs/@hono/mcp.mjs";import"../_chunks/src.mjs";import"../_chunks/libs/pathe.mjs";import"../_chunks/sequence.mjs";import"../_chunks/libs/@lume/kiwi.mjs";import"../_chunks/libs/ts-graphviz.mjs";import"../_chunks/libs/word-wrap.mjs";import"../_chunks/libs/khroma.mjs";import"../_chunks/libs/p-limit.mjs";import"../_chunks/libs/eventemitter3.mjs";import"../_chunks/libs/p-queue.mjs";import"../_chunks/libs/isexe.mjs";import"../_chunks/libs/which.mjs";import"../_chunks/libs/parse-ms.mjs";import{t as fe}from"../_chunks/libs/pretty-ms.mjs";import{t as pe}from"../_chunks/libs/picomatch.mjs";import"../_chunks/libs/p-timeout.mjs";import"../_chunks/libs/fast-equals.mjs";import{n as me}from"../_chunks/libs/strip-indent.mjs";import"../_chunks/libs/destr.mjs";import"../_chunks/libs/unstorage.mjs";import{a as he,c as ge,d as _e,i as ve,l as ye,n as be,o as xe,r as Se,s as Ce,t as we,u as Te}from"../_chunks/src2.mjs";import"../_chunks/libs/pako.mjs";import{LikeC4Model as Ee}from"../model/index.mjs";import"../_chunks/libs/is-docker.mjs";import{t as De}from"../_chunks/libs/is-inside-container.mjs";import"../_chunks/libs/ansi-regex.mjs";import{t as Oe}from"../_chunks/libs/boxen.mjs";import"../_chunks/libs/ansi-align.mjs";import"../_chunks/libs/ansi-styles.mjs";import"../_chunks/libs/find-up-simple.mjs";import{t as ke}from"../_chunks/libs/package-up.mjs";import{n as Ae,t as je}from"../_chunks/libs/package-manager-detector.mjs";import{t as Me}from"../_chunks/libs/esm-env.mjs";import{n as Ne,t as Pe}from"../_chunks/libs/conf.mjs";import"../_chunks/libs/atomically.mjs";import{a as w,c as T,d as E,f as Fe,i as Ie,l as D,n as O,o as Le,p as Re,r as k,s as A,t as ze,u as j}from"../_chunks/libs/@modelcontextprotocol/sdk.mjs";import"../_chunks/libs/ajv.mjs";import{t as Be}from"../_chunks/libs/ky.mjs";import{n as Ve,t as He}from"../_chunks/libs/get-port.mjs";import{t as Ue}from"../_chunks/libs/vscode-languageserver.mjs";import{t as We}from"../_chunks/libs/@hono/node-server.mjs";import Ge from"node:module";import{isDeploymentElementModel as Ke,isDeploymentNodeModel as qe,isDeploymentRelationModel as Je,isElementModel as Ye,isLikeC4ViewModel as Xe,isRelationModel as Ze,modelConnection as Qe}from"@likec4/core/model";import{invariant as M,nonexhaustive as $e}from"@likec4/core";import{basename as et,dirname as N,extname as tt,isAbsolute as nt,join as P,relative as F,resolve as I,sep as rt}from"node:path";import{ifilter as it,invariant as at,isSameHierarchy as ot}from"@likec4/core/utils";import st from"nano-spawn";import{tmpdir as ct}from"node:os";import{resolve as L}from"path";import{env as lt,isCI as ut,isDevelopment as dt,isTest as ft,nodeENV as pt}from"std-env";import{copyFile as mt,mkdir as R,mkdtemp as ht,readFile as gt,readdir as _t,realpath as vt,rm as yt,stat as bt,writeFile as z}from"node:fs/promises";import{copyFileSync as xt,existsSync as B,readFileSync as St,readdirSync as Ct,rmSync as wt,statSync as Tt}from"node:fs";import{argv as Et,cwd as Dt,exit as Ot,hrtime as kt,stdout as At}from"node:process";import jt from"yargs";import{hideBin as Mt}from"yargs/helpers";import{fileURLToPath as Nt,pathToFileURL as Pt}from"node:url";import Ft from"@vitejs/plugin-react";import{viteSingleFile as It}from"vite-plugin-singlefile";import{build as Lt,createServer as Rt,preview as zt}from"vite";import{setTimeout as Bt}from"node:timers/promises";import{setTimeout as Vt}from"node:timers";var Ht=`likec4`,Ut=`1.55.1`;const V=p.getChild(`cli`);function H(e){let t=p.getChild(e);return{info(e){t.info(e)},debug(e,...n){n.length===0?t.debug(e):t.debug(e,{args:n})},warn(e){if(e instanceof Error){t.warn(`${C.red(e.name+` `+e.message)}`,{msg:e});return}if(typeof e==`string`){t.warn(e);return}t.warn`${e}`},warnOnce(e){t.warn(e)},error(e,n){let r=n?.error??e;if(r instanceof Error){if(e===r){t.error(`${C.red(r.name+` `+r.message)}`,{error:r});return}t.error(C.red(e),{error:r});return}if(typeof e==`string`){t.error(C.red(e));return}t.error`${e}`},clearScreen:function(e){},hasErrorLogged:function(e){return!1},hasWarned:!1}}function Wt(e){let[t,n]=kt(e),r=t*1e3+n/1e6;return{ms:r,pretty:fe(r)}}function U(e){let t=kt();return{stopAndLog(n=`done in `){n=C.green(`${n}${Wt(t).pretty}`),(e||V).info(n)}}}function W(e,t){console.log(Oe(e,{padding:1,margin:1,dimBorder:!0,...t}))}const Gt=H(`vite`),Kt=N(Nt(import.meta.url)),qt={banner:`/* prettier-ignore-start */
3
3
  /* eslint-disable */
4
4
 
5
5
  /******************************************************************************
@@ -10,10 +10,10 @@ import{s as e}from"../_chunks/rolldown-runtime.mjs";import"../_chunks/libs/birpc
10
10
  `,footer:`
11
11
 
12
12
  /* prettier-ignore-end */
13
- `};function Yt(){let e=Ae({cwd:qt});if(!e)throw Error(`likec4 package folder not found`);return M(e)}function Xt(){let e=[F(Yt(),`__app__`),F(qt,`../__app__`),F(qt,`../../__app__`),F(qt,`../../dist/__app__`)],t=r(e,z);if(!t)throw p.error(`likec4 app root does not exist, tried:\n${e.join(`
14
- `)}`),Error(`likec4 app root does not exist`);return t}async function Zt(){let e=await gt(N(lt(),`.likec4-public-`));return await R(N(e,`likec4-views.js`),`// generated by likec4
15
- `),e}function Qt(e){return P(Ot(),e)}const $t=1e4;function en(){let e=Yt();return{"likec4/icons":`@likec4/icons`,"likec4/react":F(e,`react/index.mjs`),"likec4/model":F(e,`dist/model/index.mjs`),"likec4/vite-plugin/internal":F(e,`dist/vite-plugin/internal.mjs`)}}const tn=async({languageServices:e,likec4AssetsDir:t,...n})=>{let r=n.customLogger??Kt,i=Xt();r.info(`${x.cyan(`likec4 app root`)} ${x.dim(Qt(i))}`);let a=n.outputDir??F(e.workspace,`dist`);r.info(x.cyan(`outDir`)+` `+x.dim(Qt(a)));let o=`/`;n.base&&(o=oe(n.base),!ce(o)&&o!==`./`&&(o=le(o))),o!==`/`&&r.info(`${x.green(`app base url`)} ${x.dim(o)}`);let s=n.webcomponentPrefix??`likec4`,c=n.title??`LikeC4`,l=n.outputSingleFile??!1;return{isDev:!1,likec4AssetsDir:t,webcomponentPrefix:s,title:c,root:i,languageServices:e,clearScreen:!1,base:o,resolve:{conditions:[`production`],dedupe:[`react`,`react-dom`,`react/jsx-runtime`,`react/jsx-dev-runtime`,`react-dom/client`],alias:{...en(),"likec4/previews":t}},configFile:!1,mode:`production`,optimizeDeps:{include:[`react`,`react-dom`,`react/jsx-runtime`,`react/jsx-dev-runtime`,`react-dom/client`,`@likec4/core/types`,`@likec4/core/model`,`@likec4/core/styles`,`@likec4/core/utils`,`@likec4/core`,`likec4/vite-plugin/internal`],noDiscovery:!0},esbuild:{tsconfigRaw:{compilerOptions:{target:`ESNext`,jsx:`react-jsx`}}},define:{WEBCOMPONENT_PREFIX:JSON.stringify(s),PAGE_TITLE:JSON.stringify(c),__USE_HASH_HISTORY__:n?.useHashHistory===!0?`true`:`false`,__DEFAULT_THEME__:JSON.stringify(n?.theme??`auto`),"process.env.NODE_ENV":`"production"`},build:{outDir:a,emptyOutDir:!1,sourcemap:!1,cssMinify:!1,minify:!0,copyPublicDir:!0,chunkSizeWarningLimit:$t,assetsInlineLimit:1e5,rollupOptions:{treeshake:{preset:`recommended`},...!l&&{input:[F(i,`index.html`),F(i,`src`,`main.js`),F(i,`src`,`fonts.css`),F(i,`src`,`style.css`)],output:{manualChunks:e=>{if(!(e.endsWith(`.css`)||e.endsWith(`.html`)||e.includes(`likec4/icons`)||e.includes(`const.js`))){if(e.includes(`__app__`)){let t=e.match(/__app__\/src\/([\w]+)\.js/)?.[1];return t?t[1]:void 0}if(e.includes(`likec4`))return`likec4`;if(e.includes(`node_modules`))return`vendors`}}}}}},customLogger:r,plugins:[It(),Ee({languageServices:e.languageServices}),l?Lt():void 0]}};async function nn({languageServices:e,outDir:t,base:n,webcomponentPrefix:r=`likec4`,filename:i=`likec4-views.js`}){let a=V([`vite`,`webcomponent`]),o=Xt();return a.info(x.cyan(`outDir`)+` `+x.dim(t)),{root:o,clearScreen:!1,base:n,configFile:!1,publicDir:!1,mode:`production`,resolve:{conditions:[`production`],alias:en(),dedupe:[`react`,`react-dom`,`react/jsx-runtime`,`react/jsx-dev-runtime`,`react-dom/client`]},define:{WEBCOMPONENT_PREFIX:JSON.stringify(r),"process.env.NODE_ENV":`"production"`},esbuild:{...Jt,tsconfigRaw:{compilerOptions:{target:`ESNext`,jsx:`react-jsx`}}},build:{outDir:t,emptyOutDir:!1,sourcemap:!1,minify:!0,assetsInlineLimit:1024*1024,chunkSizeWarningLimit:$t,lib:{entry:`src/webcomponent.js`,fileName(e,t){return i},formats:[`iife`],name:`LikeC4Views`},rollupOptions:{treeshake:{preset:`recommended`},output:{format:`iife`,hoistTransitiveImports:!1,compact:!0}}},customLogger:a,plugins:[It(),Ee({languageServices:e.languageServices})]}}const rn=[`favicon.ico`,`robots.txt`];async function an({buildWebcomponent:e=!0,webcomponentPrefix:t=`likec4`,title:n,languageServices:r,likec4AssetsDir:i,outputSingleFile:a,...o}){i??=await gt(N(lt(),`.likec4-assets-`));let s=await tn({...o,languageServices:r,likec4AssetsDir:i,webcomponentPrefix:t,title:n,outputSingleFile:a}),c=!z(s.build.outDir)||wt(s.build.outDir).length===0,l=await Zt();for(let e of rn){let t=F(s.root,e);z(t)&&St(t,F(l,e))}let u=r.languageServices.projects();if(u.length===1){let e=await r.viewsService.computedViews(),t=await r.diagrams();if(t.length===0)throw process.exitCode=1,Error(`no views found`);t.length===e.length?s.customLogger.info(`${x.dim(`workspace:`)} ${x.green(`✓ all views layouted`)}`):s.customLogger.warn(`${x.dim(`workspace:`)} ${x.yellow(`✗ layouted ${t.length} of ${e.length} views`)}`),t.forEach(e=>{(e.hasLayoutDrift||e.drifts&&e.drifts.length>0)&&s.customLogger.warn(x.dim(`view`)+` `+x.red(e.id)+` `+x.yellow(`is out of date, layout drift detected`))});let n=u[0].config.landingPage;if(n&&(`include`in n||`exclude`in n)){let e=`include`in n?n.include:n.exclude;t.some(t=>e.some(e=>e.startsWith(`#`)?t.tags?.some(t=>t===e.slice(1)):t.id===e))||s.customLogger.warn(x.dim(`landingPage:`)+` `+x.yellow(`no views match the configured filter`))}}else for(let e of u){let t=await r.viewsService.computedViews(e.id);t.length===0?s.customLogger.warn(`${x.dim(`project:`)} ${e.id} ${x.yellow(`✗ no views found`)}`):s.customLogger.info(`${x.dim(`project:`)} ${e.id} ${x.green(`${t.length} views`)}`);let n=await r.diagrams(e.id),i=e.config.landingPage;if(i&&(`include`in i||`exclude`in i)){let t=`include`in i?i.include:i.exclude;n.some(e=>t.some(t=>t.startsWith(`#`)?e.tags?.some(e=>e===t.slice(1)):e.id===t))||s.customLogger.warn(`${x.dim(`project:`)} ${e.id} ${x.yellow(`landingPage: no views match the configured filter`)}`)}}if(e&&!a&&await Rt(await nn({webcomponentPrefix:t,languageServices:r,outDir:l,base:s.base})),await Rt({...s,customLogger:s.customLogger,publicDir:l,mode:`production`}),a){if(!c){s.customLogger.warn(x.yellow(`outDir was not empty, skipping cleanup`));return}for(let e of wt(F(s.build.outDir)).filter(e=>e!==`index.html`))Tt(F(s.build.outDir,e),{recursive:!0})}let d=F(s.build.outDir,`index.html`);z(d)&&St(d,F(s.build.outDir,`404.html`))}function on(e){try{return!!Ke.createRequire(import.meta.url).resolve(e)}catch(e){return B.debug(h(e)),!1}}async function sn(){if(on(`react`)&&on(`react-dom`)){B.debug(`react already installed`);return}B.warn(`react not installed`);let e=await Me();e||(B.error`Package manager not detected, please install dependencies manually: ${`react`} ${`react-dom`}`,process.exit(1));let t=je(e.agent,`add`,[`react`,`react-dom`]);t||(B.error`Please install dependencies manually: ${`react`} ${`react-dom`}`,process.exit(1));try{await ct(t.command,t.args,{stdio:`inherit`})}catch(e){B.debug(h(e)),B.error`Please install dependencies manually: ${`react`} ${`react-dom`}`,process.exit(1)}}async function cn(){if(on(`playwright`)){B.debug(`playwright already installed`);return}B.warn(`playwright not installed`);let e=await Me();e||(B.error`Package manager not detected, please install dependencies manually: ${`playwright`}`,process.exit(1));let t=je(e.agent,`add`,[`playwright`]);t||(B.error`Please install dependencies manually: ${`playwright`}`,process.exit(1));try{await ct(t.command,t.args,{preferLocal:!0,stdio:`inherit`})}catch(e){B.debug(h(e)),B.error`Please install dependencies manually: ${`playwright`}`,process.exit(1)}}const W={type:`string`,desc:`<directory> with LikeC4 sources (default is current directory or 'LIKEC4_WORKSPACE' env)`,normalize:!0,default:ut.LIKEC4_WORKSPACE||`.`,coerce:F},G={alias:`use-dot-bin`,boolean:!0,type:`boolean`,desc:S()?`enabled in container, disable by --no-use-dot`:`use graphviz binaries ("dot" should be on PATH)`,default:S()},ln={boolean:!0,type:`boolean`,desc:"use `@likec4/core` package in types",default:!1},un={boolean:!0,type:`boolean`,desc:`use hash history for navigation, e.g. "/#/view" instead of "/view"`},K={alias:[`o`,`output`],string:!0,desc:`output directory`,normalize:!0,nargs:1,coerce:F},dn={alias:`w`,string:!0,desc:`prefix for Webcomponents, e.g "c4" generates <c4-view ../>`,default:`likec4`,nargs:1},fn={alias:`t`,string:!0,desc:`base title of the app pages (default is "LikeC4")`,default:`LikeC4`,nargs:1},pn={choices:[`light`,`dark`],desc:`default color scheme for the built website (default: auto, follows system preference)`,nargs:1},mn={alias:[`base-url`],string:!0,desc:`base url the app is being served from, e.g. "/" or "/pages/"`,nargs:1},hn={boolean:!0,desc:`outputs a single self-contained HTML file with all required resources inlined`},gn={alias:`l`,string:!0,...S()?{desc:`listen 0.0.0.0 by default in container`,default:`0.0.0.0`}:{desc:`ip address of the network interface to listen on`},nargs:1},_n={number:!0,desc:`port number for the dev server (default is 5173, or PORT environment variable)`,nargs:1},q={alias:`p`,string:!0,desc:`select LikeC4 project by name (e.g. "my-project") or by path`,nargs:1},vn={hidden:!0,nargs:1,desc:`force log level`,choices:[`trace`,`debug`,`info`,`warning`,`error`],conflicts:[`verbose`]},yn={boolean:!0,desc:`verbose logging`,conflicts:[`log-level`]},bn=Ne?`trace`:`debug`,xn={name:Ut,version:Wt},Sn=c(()=>new Fe({projectName:Ut,clearInvalidConfig:!0})),Cn=1e3*60,wn=Cn*60*24*7;function J(){if(!dt)try{let e=Sn(),t=e.get(`lastSupportUsMessage`);if(!t){e.set(`lastSupportUsMessage`,Date.now()-wn+5*Cn);return}if(t+wn>Date.now())return;e.set(`lastSupportUsMessage`,Date.now()),U([x.dim(`If you are working in a commercial environment`),x.dim(`consider supporting the project`),``,x.dim(`How to get more?`)+` `+x.underline(`https://likec4.dev/sponsor/`)].join(`
16
- `))}catch{}}function Y(){var e=typeof SuppressedError==`function`?SuppressedError:function(e,t){var n=Error();return n.name=`SuppressedError`,n.error=e,n.suppressed=t,n},t={},n=[];function r(e,t){if(t!=null){if(Object(t)!==t)throw TypeError(`using declarations can only be used with objects, functions, null, or undefined.`);if(e)var r=t[Symbol.asyncDispose||Symbol.for(`Symbol.asyncDispose`)];if(r===void 0&&(r=t[Symbol.dispose||Symbol.for(`Symbol.dispose`)],e))var i=r;if(typeof r!=`function`)throw TypeError(`Object is not disposable.`);i&&(r=function e(){try{i.call(t)}catch(e){return Promise.reject(e)}}),n.push({v:t,d:r,a:e})}else e&&n.push({d:t,a:e});return t}return{e:t,u:r.bind(null,!1),a:r.bind(null,!0),d:function r(){var i,a=this.e,o=0;function s(){for(;i=n.pop();)try{if(!i.a&&o===1)return o=0,n.push(i),Promise.resolve().then(s);if(i.d){var e=i.d.call(i.v);if(i.a)return o|=2,Promise.resolve(e).then(s,c)}else o|=1}catch(e){return c(e)}if(o===1)return a===t?Promise.resolve():Promise.reject(a);if(a!==t)throw a}function c(n){return a=a===t?n:new e(n,a),s()}return s()}}}const Tn=e=>e.command({command:`build [path]`,aliases:[`bundle`],describe:`Build a static website`,builder:e=>e.positional(`path`,W).option(`output`,{alias:`o`,type:`string`,desc:`output directory for production build`,normalize:!0,coerce:F}).option(`base`,mn).option(`use-hash-history`,un).option(`use-dot`,G).option(`webcomponent-prefix`,dn).option(`title`,fn).option(`output-single-file`,hn).option(`theme`,pn).example(`${x.green(`$0 build -o ./build ./src`)}`,x.gray(`Search for likec4 files in 'src' and output static site to 'build'`)).example(`${x.green(`$0 build --theme dark -o ./build ./src`)}`,x.gray(`Build with dark color scheme as default`)),handler:async e=>{try{var t=Y();let n={useHashHistory:e[`use-hash-history`]??!1,useDotBin:e[`use-dot`],webcomponentPrefix:e[`webcomponent-prefix`],outputSingleFile:e[`output-single-file`]??!1};await sn();let r=V(`c4:build`),i=t.a(await v(e.path,{graphviz:e[`use-dot`]?`binary`:`wasm`,watch:!1})),a=e.output??F(i.workspace,`dist`),o=F(a,`assets`);await an({base:e.base,useHashHistory:n.outputSingleFile||n.useHashHistory,customLogger:r,webcomponentPrefix:n.webcomponentPrefix,title:e.title,theme:e.theme,languageServices:i,likec4AssetsDir:o,outputDir:a,outputSingleFile:n.outputSingleFile}),J()}catch(e){t.e=e}finally{await t.d()}}});var En=e(Pe(),1);const Dn=`check-update`;async function On(){if(dt||pt||mt===Dn)return;let e=Sn(),t=e.get(`lastUpdateCheck`);if(!t){await kn(!1);return}let n=e.get(`latestVersion`);if(s(n)||s(t)||t+864e5<Date.now())try{ct(`likec4`,[`check-update`],{stdio:`ignore`,timeout:5e3,preferLocal:!0,detached:!0,env:{NODE_ENV:Dn}}).catch(()=>{})}catch{}n&&(0,En.gt)(n,xn.version)&&U([`Update available: `,x.dim(xn.version),x.reset(` → `),x.green(n)].join(``))}async function kn(e=!0){try{let t=Sn();t.set({lastUpdateCheck:Date.now()});let n=await An();j(n,`No version found in latest npm`),t.set({lastUpdateCheck:Date.now(),latestVersion:n}),(0,En.gt)(n,xn.version)?U([`Update available: `,x.dim(xn.version),x.reset(` → `),x.green(n)].join(``)):e&&U(x.dim(`Up to date: `)+` `+x.green(xn.version))}catch(e){B.warning(h(e))}}async function An(){return(await Ve(`https://registry.npmjs.org/likec4/latest`,{headers:{accept:`application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*`},timeout:5e3,keepalive:!0}).json()).version}const jn=e=>e.command({command:`check-update`,describe:`Check for updates`,handler:async()=>{await kn()}});function Mn(e,t){if(!t)return e.languageServices.projectsManager.ensureProjectId();let n=F(t);if(n===e.workspace)return e.languageServices.projectsManager.ensureProjectId();if(z(n)&&Et(n).isDirectory()){B.debug`Project path exists: ${n}`;let t=re.file(n.endsWith(it)?n:n+it),r=e.languageServices.projects().find(e=>e.folder.fsPath===t.fsPath);if(r)return B.debug`Found project ${r.id} at path: ${n}`,r.id;B.debug`No project registered at path: ${n}`}return e.languageServices.projectsManager.ensureProjectId(t)}function Nn(e,t){let n=Mn(e,t),r=e.languageServices.projectsManager.getProject(n);return e.languageServices.projectsManager.defaultProjectId=n,{projectId:n,projectFolder:r.folderUri.fsPath,config:r.config}}const Pn=B.getChild(`generator`);async function Fn({name:e,path:t,useDotBin:n,project:r}){try{var i=Y();let a=H(Pn),o=i.a(await v(t,{graphviz:n?`binary`:`wasm`,watch:!1})),{projectId:s,config:c}=Nn(o,r);r&&Pn.info(`${x.dim(`project`)} ${x.green(s)}`);let l=c.generators?.[e];if(!l)throw Pn.error(x.red(`generator ${e} does not exist in project config`)),Error(`generator ${e} does not exist in project config`);Pn.info(`${x.dim(`generator`)} ${x.green(e)}`),await In({likec4:o,model:await o.layoutedModel(s),generator:l,logger:Pn.getChild(e)}),a.stopAndLog()}catch(e){i.e=e}finally{await i.d()}}async function In({likec4:e,model:t,generator:n,logger:r}){let i=e.languageServices,a=new Set,o=i.project(t.project.id),s=t.project.id;r.debug(`${x.dim(`running for project:`)} ${x.green(o.id)}`),await Promise.resolve().then(()=>n({likec4model:t,ctx:{workspace:e.languageServices.workspaceUri,project:o,locate:e=>{let t=null;switch(!0){case Xe(e):t=i.locate({element:e.id,projectId:s});break;case Ze(e):t=i.locate({view:e.id,projectId:s});break;case qe(e):t=i.locate({deployment:e.id,projectId:s});break;case Qe(e):case Ye(e):t=i.locate({relation:e.id,projectId:s});break;default:et(e)}if(!t)throw r.error(`Cannot locate ${e.id}`,{target:e}),Error(`Cannot locate ${e.id}`);let n=re.parse(t.uri);return{range:t.range,document:n,relativePath:ie.relative(o.folder,n),folder:ie.dirname(n).fsPath,filename:ie.basename(n)}},write:async({path:e,content:t})=>{let n;n=Array.isArray(e)?F(o.folder.fsPath,...e):re.isUri(e)?e.fsPath:F(o.folder.fsPath,`${e}`);let i=M(n);a.has(i)||(z(i)||(r.debug(`${x.dim(`create directory`)} ${i}`),await L(i,{recursive:!0})),a.add(i)),r.debug(`${x.dim(`write`)} ${n}`),await R(n,t)},abort:e=>{throw r.error(e||`Generator aborted`),Error(e||`Generator aborted`)}}}))}async function Ln(e,t,n){t??=F(e.workspace,`likec4.generated.ts`),nt(t)!==`.ts`&&(t+=`.ts`),await L(M(t),{recursive:!0});let r=we([...await e.diagrams()]);await R(t,r),n.info(`${x.dim(`generated`)} ${P(process.cwd(),t)}`)}async function Rn(e,t,n){await L(t,{recursive:!0}),n.info(`${x.dim(`format`)} ${x.green(`dot`)}`),n.info(`${x.dim(`outdir`)} ${t}`);let r=new Set,i=await e.computedModel(),a=l(i.$data.views),o=0;for(let s of a)try{let a=await e.viewsService.layouter.dot({view:s,styles:i.$styles}),c=`.`;s.sourcePath&&(c=M(s.sourcePath)),c=F(t,c),r.has(c)||(await L(c,{recursive:!0}),r.add(c));let l=F(c,s.id+`.dot`);await R(l,a),n.info(`${x.dim(`generated`)} ${P(process.cwd(),l)}`),o++}catch(e){B.error(`error while generating ${s.id}`,{error:e})}o>0&&n.info(`${x.dim(`total`)} ${o} files`)}async function zn(e,t,n,r){await L(n,{recursive:!0}),r.info(`${x.dim(`format`)} ${x.green(t)}`),r.info(`${x.dim(`outdir`)} ${n}`);let i,a;switch(t){case`d2`:i=`.d2`,a=ye;break;case`mermaid`:i=`.mmd`,a=Ce;break;case`plantuml`:i=`.puml`,a=be;break;default:et(t)}let o=new Set,s=await e.layoutedModel(),c=0;for(let e of s.views()){let t=e.$view;try{let s=`.`;t.sourcePath&&(s=M(t.sourcePath)),s=F(n,s),o.has(s)||(await L(s,{recursive:!0}),o.add(s));let l=F(s,t.id+i);await R(l,a(e)),r.info(`${x.dim(`generated`)} ${P(process.cwd(),l)}`),c++}catch(e){r.error(`error while generating ${t.id}`,{error:e})}}c>0&&r.info(`${x.dim(`total`)} ${c} files`)}async function Bn({path:e,useDotBin:t,...n}){let r=V(`c4:codegen`),i=H(r),a=await v(e,{graphviz:t?`binary`:`wasm`,watch:!1});if(a.ensureSingleProject(),(await a.viewsService.computedViews()).length===0)throw r.warn(`no views found`),process.exitCode=1,Error(`no views found`);switch(n.format){case`views`:await Ln(a,n.outfile,r);break;case`dot`:await Rn(a,n.outdir??e,r);break;case`d2`:case`mermaid`:case`plantuml`:await zn(a,n.format,n.outdir??e,r);break;default:et(n)}i.stopAndLog()}const Vn=M(Pt(import.meta.url));function Hn(){try{let e=JSON.parse(Ct(N(Vn,`..`,`package.json`),`utf8`));if(e.version)return e.version}catch{}try{let e=JSON.parse(Ct(N(Vn,`..`,`..`,`package.json`),`utf8`));if(e.version)return e.version}catch{}return`0.1.0`}const Un=Hn(),Wn=`leanix`,Gn=`depends on`,Kn=new Set([`factSheetTypes`,`relationTypes`,`metadataToFields`]);function qn(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;for(let t of Object.values(e))if(typeof t!=`string`)return!1;return!0}function Jn(e){if(e==null)return e;if(typeof e!=`object`||Array.isArray(e))throw Error(`LeanIX mapping must be a plain object (not an array or primitive)`);let t=e;for(let e of Object.keys(t))if(!Kn.has(e))throw Error(`LeanIX mapping has unknown key "${e}". Allowed: factSheetTypes, relationTypes, metadataToFields`);if(t.factSheetTypes!==void 0&&!qn(t.factSheetTypes))throw Error(`LeanIX mapping "factSheetTypes" must be an object with string keys and string values`);if(t.relationTypes!==void 0&&!qn(t.relationTypes))throw Error(`LeanIX mapping "relationTypes" must be an object with string keys and string values`);if(t.metadataToFields!==void 0&&!qn(t.metadataToFields))throw Error(`LeanIX mapping "metadataToFields" must be an object with string keys and string values`);return e}const Yn={factSheetTypes:{system:`Application`,container:`ITComponent`,component:`ITComponent`,actor:`Provider`},relationTypes:{default:Gn},metadataToFields:{title:`name`,description:`description`,technology:`technology`}};function Xn(e){let t=Jn(e),n={factSheetTypes:{...Yn.factSheetTypes},relationTypes:{...Yn.relationTypes},metadataToFields:{...Yn.metadataToFields}};return t?{factSheetTypes:{...n.factSheetTypes,...t.factSheetTypes},relationTypes:{...n.relationTypes,...t.relationTypes},metadataToFields:{...n.metadataToFields,...t.metadataToFields}}:n}function Zn(e,t){return t.factSheetTypes[e]??t.factSheetTypes.default??`Application`}function Qn(e,t){let n=e??`default`;return t.relationTypes[n]??t.relationTypes.default??Gn}const $n={manifestVersion:`1.0`,bridgeVersion:Un,mappingProfile:`default`};function er(e){let t={};for(let n of e.elements())t[n.id]={canonicalId:n.id,external:{}};return t}function tr(e){let t={};for(let n of e.views())t[n.id]={viewId:n.id,external:{}};return t}function nr(e){let t=[];for(let n of e.relationships())t.push({relationId:n.id,sourceFqn:n.source.id,targetFqn:n.target.id,compositeKey:`${n.source.id}|${n.target.id}|${n.id}`,external:{}});return t}function rr(e,t={}){let n={...$n,...t,generatedAt:t.generatedAt??new Date().toISOString()};return{manifestVersion:n.manifestVersion,generatedAt:n.generatedAt,bridgeVersion:n.bridgeVersion,mappingProfile:n.mappingProfile,projectId:e.projectId,entities:er(e),views:tr(e),relations:nr(e)}}function ir(e,t){let n=[];for(let r of e.elements()){let e=Zn(r.kind,t),i=r.getMetadata(),a=typeof i.description==`string`?i.description:void 0,o=r.technology??(typeof i.technology==`string`?i.technology:void 0);n.push({type:e,likec4Id:r.id,name:r.title,...a!==void 0&&{description:a},...o!==void 0&&{technology:o},...r.tags.length>0&&{tags:[...r.tags]},...Object.keys(i).length>0&&{metadata:{...i}}})}return n.sort((e,t)=>e.likec4Id.localeCompare(t.likec4Id)),n}function ar(e,t){let n=[];for(let r of e.relationships()){let e=r.title??r.kind;n.push({type:Qn(r.kind,t),likec4RelationId:r.id,sourceLikec4Id:r.source.id,targetLikec4Id:r.target.id,...e!=null&&e!==``&&{title:String(e)}})}return n.sort((e,t)=>e.likec4RelationId.localeCompare(t.likec4RelationId)),n}function or(e,t={}){let n=Xn(t.mapping),r=t.generatedAt??new Date().toISOString(),i=t.mappingProfile??(t.mapping?`custom`:`default`);return{generatedAt:r,projectId:e.projectId,mappingProfile:i,factSheets:ir(e,n),relations:ar(e,n)}}function sr(e,t){let n=[];return e.projectId!==t.projectId&&n.push(`projectId (manifest: ${e.projectId}, leanixDryRun: ${t.projectId})`),e.mappingProfile!==t.mappingProfile&&n.push(`mappingProfile (manifest: ${e.mappingProfile}, leanixDryRun: ${t.mappingProfile})`),`Manifest and LeanIX dry-run must belong to the same run. Mismatch: ${n.join(`; `)}`}function cr(e,t){if(e.projectId!==t.projectId||e.mappingProfile!==t.mappingProfile)throw Error(sr(e,t));return{generatedAt:e.generatedAt,projectId:e.projectId,manifestVersion:e.manifestVersion,bridgeVersion:e.bridgeVersion,mappingProfile:e.mappingProfile,counts:{entities:Object.keys(e.entities).length,views:Object.keys(e.views).length,relations:e.relations.length,factSheets:t.factSheets.length,leanixRelations:t.relations.length},artifacts:{manifest:`manifest.json`,leanixDryRun:`leanix-dry-run.json`}}}var lr=class extends Error{constructor(e,t,n){super(e),this.statusCode=t,this.graphqlErrors=n,this.name=`LeanixApiError`}};function ur(e){return new Promise(t=>setTimeout(t,e))}var dr=class{baseUrl;apiToken;requestDelayMs;lastRequestTime=0;rateLimitLock=Promise.resolve();constructor(e){this.apiToken=e.apiToken,this.baseUrl=(e.baseUrl??`https://app.leanix.net`).replace(/\/$/,``),this.requestDelayMs=e.requestDelayMs??200}async graphql(e,t){let n=async()=>{let n=Date.now()-this.lastRequestTime;n<this.requestDelayMs&&await ur(this.requestDelayMs-n),this.lastRequestTime=Date.now();let r=`${this.baseUrl}/services/pathfinder/v1/graphql`,i;try{i=await fetch(r,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${this.apiToken}`},body:JSON.stringify({query:e,variables:t})})}catch(e){throw new lr(`GraphQL request failed: ${r} POST - ${e instanceof Error?e.message:String(e)}`)}let a;try{a=await i.json()}catch(e){let t=e instanceof Error?e.message:String(e);throw new lr(`Invalid JSON response: ${r} ${i.status} ${i.statusText} - ${t}`,i.status)}if(!i.ok)throw new lr(a.errors?.[0]?.message??`HTTP ${i.status} ${i.statusText}`,i.status,a.errors);if(a.errors&&a.errors.length>0)throw new lr(a.errors.map(e=>e.message).join(`; `),i.status,a.errors);if(a.data===void 0)throw new lr(`GraphQL response had no data and no errors`);return a.data},r=this.rateLimitLock,i;this.rateLimitLock=new Promise(e=>{i=e}),await r;try{return await n()}finally{i()}}};async function fr(e,t,n){let r=(await e.graphql(`
13
+ `};function Jt(){let e=ke({cwd:Kt});if(!e)throw Error(`likec4 package folder not found`);return N(e)}function Yt(){let e=[I(Jt(),`__app__`),I(Kt,`../__app__`),I(Kt,`../../__app__`),I(Kt,`../../dist/__app__`)],t=r(e,B);if(!t)throw p.error(`likec4 app root does not exist, tried:\n${e.join(`
14
+ `)}`),Error(`likec4 app root does not exist`);return t}async function Xt(){let e=await ht(P(ct(),`.likec4-public-`));return await z(P(e,`likec4-views.js`),`// generated by likec4
15
+ `),e}function Zt(e){return F(Dt(),e)}const Qt=1e4;function $t(){let e=Jt();return{"likec4/icons":`@likec4/icons`,"likec4/react":I(e,`react/index.mjs`),"likec4/model":I(e,`dist/model/index.mjs`),"likec4/vite-plugin/internal":I(e,`dist/vite-plugin/internal.mjs`)}}const en=async({languageServices:e,likec4AssetsDir:t,...n})=>{let r=n.customLogger??Gt,i=Yt();r.info(`${C.cyan(`likec4 app root`)} ${C.dim(Zt(i))}`);let a=n.outputDir??I(e.workspace,`dist`);r.info(C.cyan(`outDir`)+` `+C.dim(Zt(a)));let o=`/`;n.base&&(o=ie(n.base),!oe(o)&&o!==`./`&&(o=se(o))),o!==`/`&&r.info(`${C.green(`app base url`)} ${C.dim(o)}`);let s=n.webcomponentPrefix??`likec4`,c=n.title??`LikeC4`,l=n.outputSingleFile??!1;return{isDev:!1,likec4AssetsDir:t,webcomponentPrefix:s,title:c,root:i,languageServices:e,clearScreen:!1,base:o,resolve:{conditions:[`production`],dedupe:[`react`,`react-dom`,`react/jsx-runtime`,`react/jsx-dev-runtime`,`react-dom/client`],alias:{...$t(),"likec4/previews":t}},configFile:!1,mode:`production`,optimizeDeps:{include:[`react`,`react-dom`,`react/jsx-runtime`,`react/jsx-dev-runtime`,`react-dom/client`,`@likec4/core/types`,`@likec4/core/model`,`@likec4/core/styles`,`@likec4/core/utils`,`@likec4/core`,`likec4/vite-plugin/internal`],noDiscovery:!0},esbuild:{tsconfigRaw:{compilerOptions:{target:`ESNext`,jsx:`react-jsx`}}},define:{WEBCOMPONENT_PREFIX:JSON.stringify(s),PAGE_TITLE:JSON.stringify(c),__USE_HASH_HISTORY__:n?.useHashHistory===!0?`true`:`false`,__DEFAULT_THEME__:JSON.stringify(n?.theme??`auto`),"process.env.NODE_ENV":`"production"`},build:{outDir:a,emptyOutDir:!1,sourcemap:!1,cssMinify:!1,minify:!0,copyPublicDir:!0,chunkSizeWarningLimit:Qt,assetsInlineLimit:1e5,rollupOptions:{treeshake:{preset:`recommended`},...!l&&{input:[I(i,`index.html`),I(i,`src`,`main.js`),I(i,`src`,`fonts.css`),I(i,`src`,`style.css`)],output:{manualChunks:e=>{if(!(e.endsWith(`.css`)||e.endsWith(`.html`)||e.includes(`likec4/icons`)||e.includes(`const.js`))){if(e.includes(`__app__`)){let t=e.match(/__app__\/src\/([\w]+)\.js/)?.[1];return t?t[1]:void 0}if(e.includes(`likec4`))return`likec4`;if(e.includes(`node_modules`))return`vendors`}}}}}},customLogger:r,plugins:[Ft(),we({languageServices:e.languageServices}),l?It():void 0]}};async function tn({languageServices:e,outDir:t,base:n,webcomponentPrefix:r=`likec4`,filename:i=`likec4-views.js`}){let a=H([`vite`,`webcomponent`]),o=Yt();return a.info(C.cyan(`outDir`)+` `+C.dim(t)),{root:o,clearScreen:!1,base:n,configFile:!1,publicDir:!1,mode:`production`,resolve:{conditions:[`production`],alias:$t(),dedupe:[`react`,`react-dom`,`react/jsx-runtime`,`react/jsx-dev-runtime`,`react-dom/client`]},define:{WEBCOMPONENT_PREFIX:JSON.stringify(r),"process.env.NODE_ENV":`"production"`},esbuild:{...qt,tsconfigRaw:{compilerOptions:{target:`ESNext`,jsx:`react-jsx`}}},build:{outDir:t,emptyOutDir:!1,sourcemap:!1,minify:!0,assetsInlineLimit:1024*1024,chunkSizeWarningLimit:Qt,lib:{entry:`src/webcomponent.js`,fileName(e,t){return i},formats:[`iife`],name:`LikeC4Views`},rollupOptions:{treeshake:{preset:`recommended`},output:{format:`iife`,hoistTransitiveImports:!1,compact:!0}}},customLogger:a,plugins:[Ft(),we({languageServices:e.languageServices})]}}const nn=[`favicon.ico`,`robots.txt`];async function rn({buildWebcomponent:e=!0,webcomponentPrefix:t=`likec4`,title:n,languageServices:r,likec4AssetsDir:i,outputSingleFile:a,...o}){i??=await ht(P(ct(),`.likec4-assets-`));let s=await en({...o,languageServices:r,likec4AssetsDir:i,webcomponentPrefix:t,title:n,outputSingleFile:a}),c=!B(s.build.outDir)||Ct(s.build.outDir).length===0,l=await Xt();for(let e of nn){let t=I(s.root,e);B(t)&&xt(t,I(l,e))}let u=r.languageServices.projects();if(u.length===1){let e=await r.viewsService.computedViews(),t=await r.diagrams();if(t.length===0)throw process.exitCode=1,Error(`no views found`);t.length===e.length?s.customLogger.info(`${C.dim(`workspace:`)} ${C.green(`✓ all views layouted`)}`):s.customLogger.warn(`${C.dim(`workspace:`)} ${C.yellow(`✗ layouted ${t.length} of ${e.length} views`)}`),t.forEach(e=>{(e.hasLayoutDrift||e.drifts&&e.drifts.length>0)&&s.customLogger.warn(C.dim(`view`)+` `+C.red(e.id)+` `+C.yellow(`is out of date, layout drift detected`))});let n=u[0].config.landingPage;if(n&&(`include`in n||`exclude`in n)){let e=`include`in n?n.include:n.exclude;t.some(t=>e.some(e=>e.startsWith(`#`)?t.tags?.some(t=>t===e.slice(1)):t.id===e))||s.customLogger.warn(C.dim(`landingPage:`)+` `+C.yellow(`no views match the configured filter`))}}else for(let e of u){let t=await r.viewsService.computedViews(e.id);t.length===0?s.customLogger.warn(`${C.dim(`project:`)} ${e.id} ${C.yellow(`✗ no views found`)}`):s.customLogger.info(`${C.dim(`project:`)} ${e.id} ${C.green(`${t.length} views`)}`);let n=await r.diagrams(e.id),i=e.config.landingPage;if(i&&(`include`in i||`exclude`in i)){let t=`include`in i?i.include:i.exclude;n.some(e=>t.some(t=>t.startsWith(`#`)?e.tags?.some(e=>e===t.slice(1)):e.id===t))||s.customLogger.warn(`${C.dim(`project:`)} ${e.id} ${C.yellow(`landingPage: no views match the configured filter`)}`)}}if(e&&!a&&await Lt(await tn({webcomponentPrefix:t,languageServices:r,outDir:l,base:s.base})),await Lt({...s,customLogger:s.customLogger,publicDir:l,mode:`production`}),a){if(!c){s.customLogger.warn(C.yellow(`outDir was not empty, skipping cleanup`));return}for(let e of Ct(I(s.build.outDir)).filter(e=>e!==`index.html`))wt(I(s.build.outDir,e),{recursive:!0})}let d=I(s.build.outDir,`index.html`);B(d)&&xt(d,I(s.build.outDir,`404.html`))}function an(e){try{return!!Ge.createRequire(import.meta.url).resolve(e)}catch(e){return V.debug(h(e)),!1}}async function on(){if(an(`react`)&&an(`react-dom`)){V.debug(`react already installed`);return}V.warn(`react not installed`);let e=await je();e||(V.error`Package manager not detected, please install dependencies manually: ${`react`} ${`react-dom`}`,process.exit(1));let t=Ae(e.agent,`add`,[`react`,`react-dom`]);t||(V.error`Please install dependencies manually: ${`react`} ${`react-dom`}`,process.exit(1));try{await st(t.command,t.args,{stdio:`inherit`})}catch(e){V.debug(h(e)),V.error`Please install dependencies manually: ${`react`} ${`react-dom`}`,process.exit(1)}}async function sn(){if(an(`playwright`)){V.debug(`playwright already installed`);return}V.warn(`playwright not installed`);let e=await je();e||(V.error`Package manager not detected, please install dependencies manually: ${`playwright`}`,process.exit(1));let t=Ae(e.agent,`add`,[`playwright`]);t||(V.error`Please install dependencies manually: ${`playwright`}`,process.exit(1));try{await st(t.command,t.args,{preferLocal:!0,stdio:`inherit`})}catch(e){V.debug(h(e)),V.error`Please install dependencies manually: ${`playwright`}`,process.exit(1)}}const G={type:`string`,desc:`<directory> with LikeC4 sources (default is current directory or 'LIKEC4_WORKSPACE' env)`,normalize:!0,default:lt.LIKEC4_WORKSPACE||`.`,coerce:I},K={alias:`use-dot-bin`,boolean:!0,type:`boolean`,desc:De()?`enabled in container, disable by --no-use-dot`:`use graphviz binaries ("dot" should be on PATH)`,default:De()},cn={boolean:!0,type:`boolean`,desc:"use `@likec4/core` package in types",default:!1},ln={boolean:!0,type:`boolean`,desc:`use hash history for navigation, e.g. "/#/view" instead of "/view"`},un={alias:[`o`,`output`],string:!0,desc:`output directory`,normalize:!0,nargs:1,coerce:I},dn={alias:`w`,string:!0,desc:`prefix for Webcomponents, e.g "c4" generates <c4-view ../>`,default:`likec4`,nargs:1},fn={alias:`t`,string:!0,desc:`base title of the app pages (default is "LikeC4")`,default:`LikeC4`,nargs:1},pn={choices:[`light`,`dark`],desc:`default color scheme for the built website (default: auto, follows system preference)`,nargs:1},mn={alias:[`base-url`],string:!0,desc:`base url the app is being served from, e.g. "/" or "/pages/"`,nargs:1},hn={boolean:!0,desc:`outputs a single self-contained HTML file with all required resources inlined`},gn={alias:`l`,string:!0,...De()?{desc:`listen 0.0.0.0 by default in container`,default:`0.0.0.0`}:{desc:`ip address of the network interface to listen on`},nargs:1},_n={number:!0,desc:`port number for the dev server (default is 5173, or PORT environment variable)`,nargs:1},q={alias:`p`,string:!0,desc:`select LikeC4 project by name (e.g. "my-project") or by path`,nargs:1},vn={hidden:!0,nargs:1,desc:`force log level`,choices:[`trace`,`debug`,`info`,`warning`,`error`],conflicts:[`verbose`]},yn={boolean:!0,desc:`verbose logging`,conflicts:[`log-level`]},bn=Me?`trace`:`debug`,xn={name:Ht,version:Ut},Sn=c(()=>new Pe({projectName:Ht,clearInvalidConfig:!0})),Cn=1e3*60,wn=Cn*60*24*7;function J(){if(!ut)try{let e=Sn(),t=e.get(`lastSupportUsMessage`);if(!t){e.set(`lastSupportUsMessage`,Date.now()-wn+5*Cn);return}if(t+wn>Date.now())return;e.set(`lastSupportUsMessage`,Date.now()),W([C.dim(`If you are working in a commercial environment`),C.dim(`consider supporting the project`),``,C.dim(`How to get more?`)+` `+C.underline(`https://likec4.dev/sponsor/`)].join(`
16
+ `))}catch{}}function Y(){var e=typeof SuppressedError==`function`?SuppressedError:function(e,t){var n=Error();return n.name=`SuppressedError`,n.error=e,n.suppressed=t,n},t={},n=[];function r(e,t){if(t!=null){if(Object(t)!==t)throw TypeError(`using declarations can only be used with objects, functions, null, or undefined.`);if(e)var r=t[Symbol.asyncDispose||Symbol.for(`Symbol.asyncDispose`)];if(r===void 0&&(r=t[Symbol.dispose||Symbol.for(`Symbol.dispose`)],e))var i=r;if(typeof r!=`function`)throw TypeError(`Object is not disposable.`);i&&(r=function e(){try{i.call(t)}catch(e){return Promise.reject(e)}}),n.push({v:t,d:r,a:e})}else e&&n.push({d:t,a:e});return t}return{e:t,u:r.bind(null,!1),a:r.bind(null,!0),d:function r(){var i,a=this.e,o=0;function s(){for(;i=n.pop();)try{if(!i.a&&o===1)return o=0,n.push(i),Promise.resolve().then(s);if(i.d){var e=i.d.call(i.v);if(i.a)return o|=2,Promise.resolve(e).then(s,c)}else o|=1}catch(e){return c(e)}if(o===1)return a===t?Promise.resolve():Promise.reject(a);if(a!==t)throw a}function c(n){return a=a===t?n:new e(n,a),s()}return s()}}}const Tn=e=>e.command({command:`build [path]`,aliases:[`bundle`],describe:`Build a static website`,builder:e=>e.positional(`path`,G).option(`output`,{alias:`o`,type:`string`,desc:`output directory for production build`,normalize:!0,coerce:I}).option(`base`,mn).option(`use-hash-history`,ln).option(`use-dot`,K).option(`webcomponent-prefix`,dn).option(`title`,fn).option(`output-single-file`,hn).option(`theme`,pn).example(`${C.green(`$0 build -o ./build ./src`)}`,C.gray(`Search for likec4 files in 'src' and output static site to 'build'`)).example(`${C.green(`$0 build --theme dark -o ./build ./src`)}`,C.gray(`Build with dark color scheme as default`)),handler:async e=>{try{var t=Y();let n={useHashHistory:e[`use-hash-history`]??!1,useDotBin:e[`use-dot`],webcomponentPrefix:e[`webcomponent-prefix`],outputSingleFile:e[`output-single-file`]??!1};await on();let r=H(`c4:build`),i=t.a(await v(e.path,{graphviz:e[`use-dot`]?`binary`:`wasm`,watch:!1})),a=e.output??I(i.workspace,`dist`),o=I(a,`assets`);await rn({base:e.base,useHashHistory:n.outputSingleFile||n.useHashHistory,customLogger:r,webcomponentPrefix:n.webcomponentPrefix,title:e.title,theme:e.theme,languageServices:i,likec4AssetsDir:o,outputDir:a,outputSingleFile:n.outputSingleFile}),J()}catch(e){t.e=e}finally{await t.d()}}});var En=e(Ne(),1);const Dn=`check-update`;async function On(){if(ut||ft||pt===Dn)return;let e=Sn(),t=e.get(`lastUpdateCheck`);if(!t){await kn(!1);return}let n=e.get(`latestVersion`);if(s(n)||s(t)||t+864e5<Date.now())try{st(`likec4`,[`check-update`],{stdio:`ignore`,timeout:5e3,preferLocal:!0,detached:!0,env:{NODE_ENV:Dn}}).catch(()=>{})}catch{}n&&(0,En.gt)(n,xn.version)&&W([`Update available: `,C.dim(xn.version),C.reset(` → `),C.green(n)].join(``))}async function kn(e=!0){try{let t=Sn();t.set({lastUpdateCheck:Date.now()});let n=await An();M(n,`No version found in latest npm`),t.set({lastUpdateCheck:Date.now(),latestVersion:n}),(0,En.gt)(n,xn.version)?W([`Update available: `,C.dim(xn.version),C.reset(` → `),C.green(n)].join(``)):e&&W(C.dim(`Up to date: `)+` `+C.green(xn.version))}catch(e){V.warning(h(e))}}async function An(){return(await Be(`https://registry.npmjs.org/likec4/latest`,{headers:{accept:`application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*`},timeout:5e3,keepalive:!0}).json()).version}const jn=e=>e.command({command:`check-update`,describe:`Check for updates`,handler:async()=>{await kn()}});function Mn(e,t){if(!t)return e.languageServices.projectsManager.ensureProjectId();let n=I(t);if(n===e.workspace)return e.languageServices.projectsManager.ensureProjectId();if(B(n)&&Tt(n).isDirectory()){V.debug`Project path exists: ${n}`;let t=S.file(n.endsWith(rt)?n:n+rt),r=e.languageServices.projects().find(e=>e.folder.fsPath===t.fsPath);if(r)return V.debug`Found project ${r.id} at path: ${n}`,r.id;V.debug`No project registered at path: ${n}`}return e.languageServices.projectsManager.ensureProjectId(t)}function Nn(e,t){let n=Mn(e,t),r=e.languageServices.projectsManager.getProject(n);return e.languageServices.projectsManager.defaultProjectId=n,{projectId:n,projectFolder:r.folderUri.fsPath,config:r.config}}const Pn=V.getChild(`generator`);async function Fn({name:e,path:t,useDotBin:n,project:r}){try{var i=Y();let a=U(Pn),o=i.a(await v(t,{graphviz:n?`binary`:`wasm`,watch:!1})),{projectId:s,config:c}=Nn(o,r);r&&Pn.info(`${C.dim(`project`)} ${C.green(s)}`);let l=c.generators?.[e];if(!l)throw Pn.error(C.red(`generator ${e} does not exist in project config`)),Error(`generator ${e} does not exist in project config`);Pn.info(`${C.dim(`generator`)} ${C.green(e)}`),await In({likec4:o,model:await o.layoutedModel(s),generator:l,logger:Pn.getChild(e)}),a.stopAndLog()}catch(e){i.e=e}finally{await i.d()}}async function In({likec4:e,model:t,generator:n,logger:r}){let i=e.languageServices,a=new Set,o=i.project(t.project.id),s=t.project.id;r.debug(`${C.dim(`running for project:`)} ${C.green(o.id)}`),await Promise.resolve().then(()=>n({likec4model:t,ctx:{workspace:e.languageServices.workspaceUri,project:o,locate:e=>{let t=null;switch(!0){case Ye(e):t=i.locate({element:e.id,projectId:s});break;case Xe(e):t=i.locate({view:e.id,projectId:s});break;case Ke(e):t=i.locate({deployment:e.id,projectId:s});break;case Ze(e):case Je(e):t=i.locate({relation:e.id,projectId:s});break;default:$e(e)}if(!t)throw r.error(`Cannot locate ${e.id}`,{target:e}),Error(`Cannot locate ${e.id}`);let n=S.parse(t.uri);return{range:t.range,document:n,relativePath:ne.relative(o.folder,n),folder:ne.dirname(n).fsPath,filename:ne.basename(n)}},write:async({path:e,content:t})=>{let n;n=Array.isArray(e)?I(o.folder.fsPath,...e):S.isUri(e)?e.fsPath:I(o.folder.fsPath,`${e}`);let i=N(n);a.has(i)||(B(i)||(r.debug(`${C.dim(`create directory`)} ${i}`),await R(i,{recursive:!0})),a.add(i)),r.debug(`${C.dim(`write`)} ${n}`),await z(n,t)},abort:e=>{throw r.error(e||`Generator aborted`),Error(e||`Generator aborted`)}}}))}async function Ln(e,t,n){t??=I(e.workspace,`likec4.generated.ts`),tt(t)!==`.ts`&&(t+=`.ts`),await R(N(t),{recursive:!0});let r=Se([...await e.diagrams()]);await z(t,r),n.info(`${C.dim(`generated`)} ${F(process.cwd(),t)}`)}async function Rn(e,t,n){await R(t,{recursive:!0}),n.info(`${C.dim(`format`)} ${C.green(`dot`)}`),n.info(`${C.dim(`outdir`)} ${t}`);let r=new Set,i=await e.computedModel(),a=l(i.$data.views),o=0;for(let s of a)try{let a=await e.viewsService.layouter.dot({view:s,styles:i.$styles}),c=`.`;s.sourcePath&&(c=N(s.sourcePath)),c=I(t,c),r.has(c)||(await R(c,{recursive:!0}),r.add(c));let l=I(c,s.id+`.dot`);await z(l,a),n.info(`${C.dim(`generated`)} ${F(process.cwd(),l)}`),o++}catch(e){V.error(`error while generating ${s.id}`,{error:e})}o>0&&n.info(`${C.dim(`total`)} ${o} files`)}async function zn(e,t,n,r){await R(n,{recursive:!0}),r.info(`${C.dim(`format`)} ${C.green(t)}`),r.info(`${C.dim(`outdir`)} ${n}`);let i,a;switch(t){case`d2`:i=`.d2`,a=_e;break;case`mermaid`:i=`.mmd`,a=xe;break;case`plantuml`:i=`.puml`,a=ve;break;default:$e(t)}let o=new Set,s=await e.layoutedModel(),c=0;for(let e of s.views()){let t=e.$view;try{let s=`.`;t.sourcePath&&(s=N(t.sourcePath)),s=I(n,s),o.has(s)||(await R(s,{recursive:!0}),o.add(s));let l=I(s,t.id+i);await z(l,a(e)),r.info(`${C.dim(`generated`)} ${F(process.cwd(),l)}`),c++}catch(e){r.error(`error while generating ${t.id}`,{error:e})}}c>0&&r.info(`${C.dim(`total`)} ${c} files`)}async function Bn({path:e,useDotBin:t,...n}){let r=H(`c4:codegen`),i=U(r),a=await v(e,{graphviz:t?`binary`:`wasm`,watch:!1});if(a.ensureSingleProject(),(await a.viewsService.computedViews()).length===0)throw r.warn(`no views found`),process.exitCode=1,Error(`no views found`);switch(n.format){case`views`:await Ln(a,n.outfile,r);break;case`dot`:await Rn(a,n.outdir??e,r);break;case`d2`:case`mermaid`:case`plantuml`:await zn(a,n.format,n.outdir??e,r);break;default:$e(n)}i.stopAndLog()}const Vn=N(Nt(import.meta.url));function Hn(){try{let e=JSON.parse(St(P(Vn,`..`,`package.json`),`utf8`));if(e.version)return e.version}catch{}try{let e=JSON.parse(St(P(Vn,`..`,`..`,`package.json`),`utf8`));if(e.version)return e.version}catch{}return`0.1.0`}const Un=Hn(),Wn=`leanix`,Gn=`depends on`,Kn=new Set([`factSheetTypes`,`relationTypes`,`metadataToFields`]);function qn(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;for(let t of Object.values(e))if(typeof t!=`string`)return!1;return!0}function Jn(e){if(e==null)return e;if(typeof e!=`object`||Array.isArray(e))throw Error(`LeanIX mapping must be a plain object (not an array or primitive)`);let t=e;for(let e of Object.keys(t))if(!Kn.has(e))throw Error(`LeanIX mapping has unknown key "${e}". Allowed: factSheetTypes, relationTypes, metadataToFields`);if(t.factSheetTypes!==void 0&&!qn(t.factSheetTypes))throw Error(`LeanIX mapping "factSheetTypes" must be an object with string keys and string values`);if(t.relationTypes!==void 0&&!qn(t.relationTypes))throw Error(`LeanIX mapping "relationTypes" must be an object with string keys and string values`);if(t.metadataToFields!==void 0&&!qn(t.metadataToFields))throw Error(`LeanIX mapping "metadataToFields" must be an object with string keys and string values`);return e}const Yn={factSheetTypes:{system:`Application`,container:`ITComponent`,component:`ITComponent`,actor:`Provider`},relationTypes:{default:Gn},metadataToFields:{title:`name`,description:`description`,technology:`technology`}};function Xn(e){let t=Jn(e),n={factSheetTypes:{...Yn.factSheetTypes},relationTypes:{...Yn.relationTypes},metadataToFields:{...Yn.metadataToFields}};return t?{factSheetTypes:{...n.factSheetTypes,...t.factSheetTypes},relationTypes:{...n.relationTypes,...t.relationTypes},metadataToFields:{...n.metadataToFields,...t.metadataToFields}}:n}function Zn(e,t){return t.factSheetTypes[e]??t.factSheetTypes.default??`Application`}function Qn(e,t){let n=e??`default`;return t.relationTypes[n]??t.relationTypes.default??Gn}const $n={manifestVersion:`1.0`,bridgeVersion:Un,mappingProfile:`default`};function er(e){let t={};for(let n of e.elements())t[n.id]={canonicalId:n.id,external:{}};return t}function tr(e){let t={};for(let n of e.views())t[n.id]={viewId:n.id,external:{}};return t}function nr(e){let t=[];for(let n of e.relationships())t.push({relationId:n.id,sourceFqn:n.source.id,targetFqn:n.target.id,compositeKey:`${n.source.id}|${n.target.id}|${n.id}`,external:{}});return t}function rr(e,t={}){let n={...$n,...t,generatedAt:t.generatedAt??new Date().toISOString()};return{manifestVersion:n.manifestVersion,generatedAt:n.generatedAt,bridgeVersion:n.bridgeVersion,mappingProfile:n.mappingProfile,projectId:e.projectId,entities:er(e),views:tr(e),relations:nr(e)}}function ir(e,t){let n=[];for(let r of e.elements()){let e=Zn(r.kind,t),i=r.getMetadata(),a=typeof i.description==`string`?i.description:void 0,o=r.technology??(typeof i.technology==`string`?i.technology:void 0);n.push({type:e,likec4Id:r.id,name:r.title,...a!==void 0&&{description:a},...o!==void 0&&{technology:o},...r.tags.length>0&&{tags:[...r.tags]},...Object.keys(i).length>0&&{metadata:{...i}}})}return n.sort((e,t)=>e.likec4Id.localeCompare(t.likec4Id)),n}function ar(e,t){let n=[];for(let r of e.relationships()){let e=r.title??r.kind;n.push({type:Qn(r.kind,t),likec4RelationId:r.id,sourceLikec4Id:r.source.id,targetLikec4Id:r.target.id,...e!=null&&e!==``&&{title:String(e)}})}return n.sort((e,t)=>e.likec4RelationId.localeCompare(t.likec4RelationId)),n}function or(e,t={}){let n=Xn(t.mapping),r=t.generatedAt??new Date().toISOString(),i=t.mappingProfile??(t.mapping?`custom`:`default`);return{generatedAt:r,projectId:e.projectId,mappingProfile:i,factSheets:ir(e,n),relations:ar(e,n)}}function sr(e,t){let n=[];return e.projectId!==t.projectId&&n.push(`projectId (manifest: ${e.projectId}, leanixDryRun: ${t.projectId})`),e.mappingProfile!==t.mappingProfile&&n.push(`mappingProfile (manifest: ${e.mappingProfile}, leanixDryRun: ${t.mappingProfile})`),`Manifest and LeanIX dry-run must belong to the same run. Mismatch: ${n.join(`; `)}`}function cr(e,t){if(e.projectId!==t.projectId||e.mappingProfile!==t.mappingProfile)throw Error(sr(e,t));return{generatedAt:e.generatedAt,projectId:e.projectId,manifestVersion:e.manifestVersion,bridgeVersion:e.bridgeVersion,mappingProfile:e.mappingProfile,counts:{entities:Object.keys(e.entities).length,views:Object.keys(e.views).length,relations:e.relations.length,factSheets:t.factSheets.length,leanixRelations:t.relations.length},artifacts:{manifest:`manifest.json`,leanixDryRun:`leanix-dry-run.json`}}}var lr=class extends Error{constructor(e,t,n){super(e),this.statusCode=t,this.graphqlErrors=n,this.name=`LeanixApiError`}};function ur(e){return new Promise(t=>setTimeout(t,e))}var dr=class{baseUrl;apiToken;requestDelayMs;lastRequestTime=0;rateLimitLock=Promise.resolve();constructor(e){this.apiToken=e.apiToken,this.baseUrl=(e.baseUrl??`https://app.leanix.net`).replace(/\/$/,``),this.requestDelayMs=e.requestDelayMs??200}async graphql(e,t){let n=async()=>{let n=Date.now()-this.lastRequestTime;n<this.requestDelayMs&&await ur(this.requestDelayMs-n),this.lastRequestTime=Date.now();let r=`${this.baseUrl}/services/pathfinder/v1/graphql`,i;try{i=await fetch(r,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${this.apiToken}`},body:JSON.stringify({query:e,variables:t})})}catch(e){throw new lr(`GraphQL request failed: ${r} POST - ${e instanceof Error?e.message:String(e)}`)}let a;try{a=await i.json()}catch(e){let t=e instanceof Error?e.message:String(e);throw new lr(`Invalid JSON response: ${r} ${i.status} ${i.statusText} - ${t}`,i.status)}if(!i.ok)throw new lr(a.errors?.[0]?.message??`HTTP ${i.status} ${i.statusText}`,i.status,a.errors);if(a.errors&&a.errors.length>0)throw new lr(a.errors.map(e=>e.message).join(`; `),i.status,a.errors);if(a.data===void 0)throw new lr(`GraphQL response had no data and no errors`);return a.data},r=this.rateLimitLock,i;this.rateLimitLock=new Promise(e=>{i=e}),await r;try{return await n()}finally{i()}}};async function fr(e,t,n){let r=(await e.graphql(`
17
17
  query FindFactSheet($name: String!, $type: String!) {
18
18
  allFactSheets(filter: { name: $name, factSheetType: $type }) {
19
19
  edges { node { id name type } }
@@ -77,27 +77,27 @@ import{s as e}from"../_chunks/rolldown-runtime.mjs";import"../_chunks/libs/birpc
77
77
  }
78
78
  }
79
79
  }
80
- `,{id:t,first:100,after:i})),s=o?.factSheet?.relations?.edges??[],c=o?.factSheet?.relations?.pageInfo;for(let e of s){let i=e.node,a=i?.targetFactSheet?.id;!a||!r.has(a)||n.push({...i?.id?{id:i.id}:{},sourceFactSheetId:t,targetFactSheetId:a,type:i?.type??`RELATES_TO`})}a=c?.hasNextPage===!0,i=c?.endCursor??null}return n}for(let e=0;e<t.length;e+=10){let r=t.slice(e,e+10),a=await Promise.all(r.map(e=>i(e)));for(let e of a)n.push(...e)}return n}function jr(e,t,n,r){let i=e.external?.[Wn],a=i?.factSheetId??i?.externalId;if(a==null)return null;let o=n.get(a);return!o||r.has(o.id)?null:(r.add(o.id),{canonicalId:t,factSheetId:o.id,name:o.name,type:o.type})}function Mr(e,t,n){let r=t.get(e);return!r||n.has(r.id)?null:(n.add(r.id),{canonicalId:e,factSheetId:r.id,name:r.name,type:r.type})}function Nr(e,t,n,r,i,a,o,s){let c=`${t??e}${n??``}`,l=r.get(c)?.filter(e=>!i.has(e.id))??[];if(l.length===0)o.push({canonicalId:e,...t===void 0?{}:{name:t},...n===void 0?{}:{type:n}});else if(l.length===1){let t=l[0];a.push({canonicalId:e,factSheetId:t.id,name:t.name,type:t.type}),i.add(t.id)}else s.push({canonicalId:e,...t===void 0?{}:{name:t},...n===void 0?{}:{type:n},candidateFactSheetIds:l.map(e=>e.id)})}function Pr(e,t,n={}){let r=n.generatedAt??new Date().toISOString(),i=n.dryRun,a=[],o=[],s=[],c=new Map(e.factSheets.map(e=>[e.id,e])),l=new Map,u=new Map;for(let t of e.factSheets){t.likec4Id&&l.set(t.likec4Id,t);let e=`${t.name}${t.type}`;u.has(e)||u.set(e,[]),u.get(e).push(t)}let d=i?new Map(i.factSheets.map(e=>[e.likec4Id,e])):null,f=new Set;for(let[e,n]of Object.entries(t.entities)){let t=jr(n,e,c,f);if(t){a.push(t);continue}let r=Mr(e,l,f);if(r){a.push(r);continue}let i=d?.get(e);Nr(e,i?.name??void 0,i?.type??void 0,u,f,a,o,s)}let p=e.factSheets.filter(e=>!f.has(e.id)).map(e=>({factSheetId:e.id,name:e.name,type:e.type,...e.likec4Id?{likec4Id:e.likec4Id}:{}}));return{generatedAt:r,manifestProjectId:t.projectId,snapshotGeneratedAt:e.generatedAt,matched:a,unmatchedInLikec4:o,unmatchedInLeanix:p,ambiguous:s,summary:{matched:a.length,unmatchedInLikec4:o.length,unmatchedInLeanix:p.length,ambiguous:s.length}}}function Fr(e){return typeof e==`object`&&!!e}function Ir(e){return Fr(e)?typeof e.canonicalId==`string`:!1}function Lr(e){return Fr(e)?typeof e.viewId==`string`:!1}function Rr(e){return Fr(e)?typeof e.relationId==`string`&&typeof e.sourceFqn==`string`&&typeof e.targetFqn==`string`&&typeof e.compositeKey==`string`:!1}function zr(e){return Fr(e)?typeof e.id==`string`&&typeof e.name==`string`&&typeof e.type==`string`:!1}function Br(e){return Fr(e)?typeof e.sourceFactSheetId==`string`&&typeof e.targetFactSheetId==`string`&&typeof e.type==`string`:!1}function Vr(e){if(!Fr(e)||typeof e.manifestVersion!=`string`||typeof e.generatedAt!=`string`||typeof e.bridgeVersion!=`string`||typeof e.mappingProfile!=`string`||typeof e.projectId!=`string`)return!1;let t=e.entities;if(typeof t!=`object`||!t||Array.isArray(t))return!1;for(let e of Object.values(t))if(!Ir(e))return!1;let n=e.views;if(typeof n!=`object`||!n||Array.isArray(n))return!1;for(let e of Object.values(n))if(!Lr(e))return!1;let r=e.relations;if(!Array.isArray(r))return!1;for(let e of r)if(!Rr(e))return!1;return!0}function Hr(e){if(!Fr(e)||typeof e.generatedAt!=`string`||e.workspaceId!==void 0&&typeof e.workspaceId!=`string`||!Array.isArray(e.factSheets))return!1;for(let t of e.factSheets)if(!zr(t))return!1;if(!Array.isArray(e.relations))return!1;for(let t of e.relations)if(!Br(t))return!1;return!0}const Ur=`No project or empty model`,Wr=`LEANIX_API_TOKEN is required for likec4 sync leanix --apply`,Gr=`default`,Kr=`manifest.json`,qr=`leanix-dry-run.json`,Jr=`report.json`;function Yr(e){return{projectId:String(e.projectId),elements:()=>e.elements(),relationships:()=>e.relationships(),views:()=>e.views()}}function Xr(e){let t=rr(e,{mappingProfile:Gr}),n=or(e,{mappingProfile:Gr});return{manifest:t,dryRun:n,report:cr(t,n)}}async function Zr(e,t,n,r=process.cwd()){await L(e,{recursive:!0});let i=F(e,Kr),a=F(e,qr),o=F(e,Jr);await R(i,JSON.stringify(t.manifest,null,2)),await R(a,JSON.stringify(t.dryRun,null,2)),await R(o,JSON.stringify(t.report,null,2)),n.info(`${x.dim(`generated`)} ${P(r,i)}`),n.info(`${x.dim(`generated`)} ${P(r,a)}`),n.info(`${x.dim(`generated`)} ${P(r,o)}`)}const Qr={manifest:Kr,dryRun:qr,report:Jr};async function $r(e){let t=V(`c4:gen:leanix:dry-run`),n=H(t),{path:r,outdir:i,project:a,useDotBin:o}=e;try{try{var s=Y();let e=s.a(await v(r,{graphviz:o?`binary`:`wasm`,watch:!1})),{projectId:n}=Nn(e,a);a&&t.info(`${x.dim(`project`)} ${x.green(n)}`);let c=await e.layoutedModel(n);if(c===Oe.EMPTY)throw t.error(Ur),Error(Ur);await Zr(i,Xr(Yr(c)),t)}catch(e){s.e=e}finally{await s.d()}}finally{n.stopAndLog()}}function ei(){let e=process.env.LEANIX_API_TOKEN?.trim();return e?new dr({apiToken:e,baseUrl:process.env.LEANIX_BASE_URL?.trim()||`https://app.leanix.net`,requestDelayMs:200}):null}function ti(){let e=ei();if(!e)throw Error(`LEANIX_API_TOKEN is required. Set it in the environment to call the LeanIX API.`);return e}async function ni(e){let t=V(`c4:gen:leanix:inventory`),n=H(t),{outdir:r,likec4IdAttribute:i}=e;try{let e=ti(),n={};typeof i==`string`&&i.trim()!==``&&(n.likec4IdAttribute=i.trim());let a=await Dr(e,n);await L(r,{recursive:!0});let o=F(r,`leanix-inventory-snapshot.json`);await R(o,JSON.stringify(a,null,2)),t.info(`${x.dim(`generated`)} ${P(process.cwd(),o)}`),t.info(`${x.dim(`snapshot`)} ${a.factSheets.length} fact sheets, ${a.relations.length} relations`)}finally{n.stopAndLog()}}const ri=`manifest.json`,ii=`leanix-inventory-snapshot.json`;async function ai(e){let t=F(e,ri),n=F(e,ii),[r,i]=await Promise.all([_t(t,`utf-8`),_t(n,`utf-8`)]),a=JSON.parse(r),o=JSON.parse(i);if(!Vr(a))throw Error(`Invalid manifest format: missing manifestVersion, projectId, entities, relations, or views`);if(!Hr(o))throw Error(`Invalid snapshot format: missing factSheets or relations arrays`);return{manifest:a,snapshot:o}}async function oi(e,t,n){try{var r=Y();let i=r.a(await v(e,{graphviz:n?`binary`:`wasm`,watch:!1})),{projectId:a}=Nn(i,t),o=await i.layoutedModel(a);return o===Oe.EMPTY?void 0:Xr(Yr(o)).dryRun}catch(e){r.e=e}finally{await r.d()}}async function si(e){let t=V(`c4:gen:leanix:reconcile`),n=H(t),{path:r,outdir:i,project:a,useDotBin:o}=e;try{let e,n;try{let t=await ai(i);e=t.manifest,n=t.snapshot}catch(e){let n=e instanceof Error?e.message:String(e);throw t.error(`Failed to read ${ri} or ${ii} from ${i}: ${n}`),e}let s;try{s=await oi(r,a,o)}catch(e){let n=e instanceof Error?e.message:String(e);if(a!=null&&a!==``)throw t.error(`Failed to load workspace for dryRun enrichment: ${n}`),e;t.warn(`Could not load workspace for dryRun enrichment; proceeding without it: ${n}`),s=void 0}let c=Pr(n,e,{...s==null?{}:{dryRun:s}}),l=F(i,`reconciliation-report.json`);await R(l,JSON.stringify(c,null,2)),t.info(`${x.dim(`generated`)} ${P(process.cwd(),l)}`),t.info(`${x.dim(`reconcile`)} matched=${c.summary.matched} unmatchedLikec4=${c.summary.unmatchedInLikec4} unmatchedLeanix=${c.summary.unmatchedInLeanix} ambiguous=${c.summary.ambiguous}`)}finally{n.stopAndLog()}}async function ci({path:e,useDotBin:t,useCorePackage:n,outfile:r,project:i}){try{var a=Y();let o=V(`c4:codegen`),s=H(o),c=a.a(await v(e,{graphviz:t?`binary`:`wasm`,watch:!1})),{projectId:l,projectFolder:u}=Nn(c,i);i&&o.info(`${x.dim(`project`)} ${x.green(l)}`),o.info(`${x.dim(`format`)} ${x.green(`model`)}`);let d=await c.layoutedModel(l);for(let e of d.views())e.hasLayoutDrifts&&o.warn(x.yellow(`layout drift detected, view:`)+` `+x.red(e.id));let f=F(c.projectsManager.hasMultipleProjects()?u:c.workspace,`likec4-model.ts`);if(r&&(f=rt(r)?r:F(r),z(r)&&(await xt(r)).isDirectory()))throw Error(`output file is a directory: ${r}`);let p=tt(f);o.info(`${x.dim(`filename`)} ${p}`);let m=nt(p).toLocaleLowerCase();if(![`.ts`,`.mts`,`.cts`].includes(m))throw o.error(`output file ${r} has extension "${m}"`),Error(`output file ${r} must be a .ts, .mts or .cts file`);let h=M(f);o.info(`${x.dim(`outdir`)} ${h}`),await L(h,{recursive:!0}),await R(f,_e(d,{useCorePackage:n}),{encoding:`utf-8`}),s.stopAndLog(),U(ge(`
81
- ${x.dim(`Source generated:`)}
82
- ${P(Ot(),f)}
83
-
84
- ${x.dim(`How to use:`)}
85
- ${x.underline(`https://likec4.dev/tooling/code-generation/model/`)}
86
- `).trim(),{padding:1,borderColor:`green`,borderStyle:`round`})}catch(e){a.e=e}finally{await a.d()}}async function li({languageServices:e,outDir:t,filename:n=`likec4-react.mjs`}){let r=V([`vite`,`react`]),i=Xt();return r.info(`${x.cyan(`likec4 app root`)} ${x.dim(Qt(i))}`),r.info(x.cyan(`outDir`)+` `+x.dim(Qt(t))),{customLogger:r,root:i,configFile:!1,clearScreen:!1,publicDir:!1,mode:`production`,resolve:{conditions:[`production`],alias:en()},esbuild:{banner:`'use client'
87
- `+Jt.banner,footer:Jt.footer,jsx:`transform`,jsxDev:!1,jsxSideEffects:!1,minifyIdentifiers:!1,minifySyntax:!1,minifyWhitespace:!1,tsconfigRaw:{compilerOptions:{target:`ES2022`,useDefineForClassFields:!0,verbatimModuleSyntax:!0,jsx:`react-jsx`}}},build:{outDir:t,emptyOutDir:!1,sourcemap:!1,minify:!1,copyPublicDir:!1,chunkSizeWarningLimit:$t,assetsInlineLimit:5e5,lib:{entry:`react/likec4.tsx`,fileName(e,t){return n},formats:[`es`]},rollupOptions:{output:{compact:!1,exports:`named`},external:[`likec4/react`,`likec4/model`,`react`,`react-dom`,`react/jsx-runtime`,`react/jsx-dev-runtime`,`react-dom/client`,/@likec4\/core.*/],onwarn(e,t){e.code!==`SOURCEMAP_ERROR`&&t(e)}}},plugins:[It({}),Ee({languageServices:e.languageServices})]}}async function ui({path:e,useDotBin:t,useCorePackage:n,outfile:r,project:i}){try{var a=Y();await sn();let o=V(`c4:codegen`),s=H(o),c=a.a(await v(e,{graphviz:t?`binary`:`wasm`,watch:!1})),{projectId:l,projectFolder:u}=Nn(c,i);i&&o.info(`${x.dim(`project`)} ${x.green(l)}`),o.info(`${x.dim(`format`)} ${x.green(`react`)}`);let d=await c.diagrams(l);if(d.length===0)throw process.exitCode=1,Error(`no views found`);d.forEach(e=>{if(e.drifts&&e.drifts.length>0){o.info(x.yellow(`layout drift detected, view:`)+` `+x.red(e.id));return}if(e.hasLayoutDrift){o.warn(x.yellow(`drift detected, manual layout can not be applied, view:`)+` `+x.red(e.id));return}});let f=F(c.projectsManager.hasMultipleProjects()?u:c.workspace,`likec4-views.js`);if(r&&(f=rt(r)?r:F(r),z(r)&&(await xt(r)).isDirectory()))throw Error(`output file is a directory: ${r}`);let p=M(f);o.info(`${x.dim(`outdir`)} ${p}`);let m=tt(f);o.info(`${x.dim(`filename`)} ${m}`);let h=nt(m).toLocaleLowerCase();if(![`.js`,`.mjs`,`.jsx`].includes(h))throw o.error(`output file ${r} has extension "${h}"`),Error(`output file ${r} must be a .js, .jsx or .mjs`);await Rt({...await li({languageServices:c,outDir:p,filename:m}),logLevel:`warn`});let g=await c.layoutedModel(l),_=F(p,tt(f,h)+(h===`.mjs`?`.d.mts`:`.d.ts`));await R(_,Se(g,{useCorePackage:n})),s.stopAndLog(),U(ge(`
88
- ${x.dim(`Sources generated:`)}
89
- ${P(Ot(),f)}
90
- ${P(Ot(),_)}
91
-
92
- ${x.dim(`How to use:`)}
93
- ${x.underline(`https://likec4.dev/tooling/code-generation/react/`)}
94
- `),{padding:1,borderColor:`green`,borderStyle:`round`})}catch(e){a.e=e}finally{await a.d()}}async function di({project:e,path:t,useDotBin:n,webcomponentPrefix:r=`likec4`,outfile:i}){try{var o=Y();await sn();let s=V(`c4:codegen`),c=H(s),l=o.a(await v(t,{graphviz:n?`binary`:`wasm`,watch:!1})),{projectId:u,projectFolder:d}=Nn(l,e);e&&s.info(`${x.dim(`project`)} ${x.green(u)}`),s.info(`${x.dim(`format`)} ${x.green(`webcomponent`)}`);let f=await l.diagrams(u);if(!a(f,1))throw s.warn(`no views found`),process.exitCode=1,Error(`no views found`);f.forEach(e=>{e.hasLayoutDrift&&s.warn(x.yellow(`drift detected, manual layout can not be applied, view:`)+` `+x.red(e.id))});let p=F(l.projectsManager.hasMultipleProjects()?d:l.workspace,`likec4-views.js`);if(i&&(p=rt(i)?i:F(i),z(i)&&(await xt(i)).isDirectory()))throw Error(`output file is a directory: ${i}`);s.debug(`${x.dim(`outfilepath`)} ${p}`);let m=tt(p);s.debug(`${x.dim(`filename`)} ${m}`);let h=nt(m).toLocaleLowerCase();if(h!==`.js`&&h!==`.mjs`)throw s.warn(`output file ${i} has extension "${h}"`),Error(`output file ${i} must be a .js or .mjs`);let g=await Zt();s.debug(`${x.dim(`created temp public`)} ${g}`);let _=await nn({languageServices:l,outDir:g,filename:m,webcomponentPrefix:r,base:`/`});s.debug(`${x.dim(`vite build webcomponent`)}`),await Rt({..._,logLevel:`warn`});let y=F(g,m);if(!z(y))throw Error(`output file not found: ${y}`);await L(M(p),{recursive:!0}),await ht(y,p),s.info(`${x.dim(`generated`)} ${p}`),s.debug(`${x.dim(`remove temp public`)}`),await bt(g,{recursive:!0,force:!0}),c.stopAndLog(),U(ge(`
95
- ${x.dim(`Webcomponents generated to:`)}
96
- ${P(Ot(),p)}
97
-
98
- ${x.dim(`Setup and usage instructions:`)}
99
- ${x.blue(`https://likec4.dev/tooling/code-generation/webcomponent/`)}
100
- `))}catch(e){o.e=e}finally{await o.d()}}const fi=e=>e.command({command:`gen <command> [path]`,aliases:[`generate`,`codegen`],describe:`Generate various artifacts from LikeC4 sources`,builder:e=>e.positional(`path`,W).command(`react [path]`,`generate react component to render likec4 view`,e=>e.positional(`path`,W).option(`project`,q).option(`outfile`,{alias:[`o`,`output`],type:`string`,desc:`<file> path to output file (.jsx, .mjs or .js)`,normalize:!0,coerce:I}).option(`use-dot`,G).option(`use-core-package`,ln),async e=>{await ui({project:e.project,useDotBin:e.useDotBin,path:e.path,outfile:e.outfile,useCorePackage:e.useCorePackage}),J()}).command({command:`webcomponent [path]`,aliases:[`wc`,`webcomp`],describe:`generate js with webcomponents`,builder:e=>e.positional(`path`,W).option(`project`,q).option(`outfile`,{alias:[`o`,`output`],type:`string`,desc:`<file> path to output file (.mjs or .js)`,normalize:!0,coerce:I}).option(`webcomponent-prefix`,dn).option(`use-dot`,G),handler:async e=>{await di({project:e.project,useDotBin:e.useDotBin,path:e.path,outfile:e.outfile,webcomponentPrefix:e.webcomponentPrefix}),J()}}).command({command:`model [path]`,aliases:[`ts`],describe:`generate LikeC4Model (.ts)`,builder:e=>e.positional(`path`,W).option(`project`,q).option(`outfile`,{alias:[`o`,`output`],type:`string`,desc:`<file> path to output file (.ts)`,normalize:!0,coerce:I}).option(`use-dot`,G).option(`use-core-package`,ln),handler:async e=>{await ci({path:e.path,useDotBin:e.useDotBin,useCorePackage:e.useCorePackage,outfile:e.outfile,project:e.project}),J()}}).command({command:`views-data [path]`,aliases:[`views`],describe:`{deprecated} use codegen model`,deprecated:!0,builder:e=>e.positional(`path`,W).option(`outfile`,{alias:[`o`,`output`],type:`string`,desc:`<file> output .ts file`,normalize:!0,coerce:I}).option(`use-dot`,G),handler:async e=>{await Bn({format:`views`,path:e.path,useDotBin:e.useDotBin,outfile:e.outfile})}}).command({command:`leanix [path]`,describe:`LeanIX bridge: dry-run, inventory snapshot, reconcile`,builder:e=>e.positional(`path`,W).demandCommand(1,`Choose a subcommand: dry-run, inventory, reconcile`).command(`dry-run [path]`,`generate LeanIX bridge artifacts (manifest, dry-run inventory, report)`,e=>e.positional(`path`,W).option(`outdir`,{...K,desc:`<dir> output directory for manifest.json, leanix-dry-run.json, report.json`}).option(`project`,q).option(`use-dot`,G).example(`${x.green(`$0 gen leanix dry-run -o out/bridge`)}`,x.gray(`Write bridge artifacts to out/bridge`)),async e=>{await $r({path:e.path,outdir:e.outdir??I(process.cwd(),`out`,`bridge`),project:e.project,useDotBin:e.useDotBin})}).command(`inventory`,`fetch LeanIX inventory (read-only) and write leanix-inventory-snapshot.json`,e=>e.option(`outdir`,{...K,default:I(process.cwd(),`out`,`bridge`),desc:`<dir> output directory for leanix-inventory-snapshot.json`}).option(`likec4-id-attribute`,{type:`string`,desc:`custom LeanIX attribute key for likec4Id (e.g. "likec4Id")`}).example(`${x.green(`$0 gen leanix inventory -o out/bridge`)}`,x.gray(`Requires LEANIX_API_TOKEN`)),async e=>{await ni({outdir:e.outdir??I(process.cwd(),`out`,`bridge`),...e.likec4IdAttribute==null?{}:{likec4IdAttribute:e.likec4IdAttribute}})}).command(`reconcile [path]`,`reconcile manifest with leanix-inventory-snapshot; write reconciliation-report.json`,e=>e.positional(`path`,W).option(`outdir`,{...K,default:I(process.cwd(),`out`,`bridge`),desc:`<dir> directory with manifest.json and leanix-inventory-snapshot.json`}).option(`project`,q).option(`use-dot`,G).example(`${x.green(`$0 gen leanix reconcile -o out/bridge`)}`,x.gray(`Reads manifest + snapshot from outdir; optional workspace for name+type matching`)),async e=>{await si({path:e.path,outdir:e.outdir??I(process.cwd(),`out`,`bridge`),project:e.project,useDotBin:e.useDotBin})}),handler:async()=>{}}).command({command:`dot [path]`,describe:`generate graphviz files (.dot)`,builder:e=>e.positional(`path`,W).option(`outdir`,K).option(`use-dot`,G),handler:async e=>{await Bn({format:`dot`,path:e.path,useDotBin:e.useDotBin,outdir:e.outdir}),J()}}).command({command:`d2 [path]`,describe:`generate D2 files (.d2)`,builder:e=>e.positional(`path`,W).option(`outdir`,K).option(`use-dot`,G),handler:async e=>{await Bn({format:`d2`,path:e.path,useDotBin:e.useDotBin,outdir:e.outdir}),J()}}).command({command:`mermaid [path]`,aliases:[`mmd`],describe:`generate Mermaid files (.mmd)`,builder:e=>e.positional(`path`,W).option(`outdir`,K).option(`use-dot`,G),handler:async e=>{await Bn({format:`mermaid`,useDotBin:e.useDotBin,path:e.path,outdir:e.outdir}),J()}}).command({command:`plantuml [path]`,aliases:[`puml`],describe:`generate PlantUML files (.puml)`,builder:e=>e.positional(`path`,W).option(`outdir`,K).option(`use-dot`,G),handler:async e=>{await Bn({format:`plantuml`,useDotBin:e.useDotBin,path:e.path,outdir:e.outdir}),J()}}).command({command:`<custom> [path]`,describe:`run custom generator from likec4 config`,builder:e=>e.positional(`path`,W).option(`project`,q).option(`use-dot`,G),handler:async e=>{await Fn({name:`custom`,path:e.path,project:e.project,useDotBin:e.useDotBin})}}).epilog(`${x.bold(`Examples:`)}
80
+ `,{id:t,first:100,after:i})),s=o?.factSheet?.relations?.edges??[],c=o?.factSheet?.relations?.pageInfo;for(let e of s){let i=e.node,a=i?.targetFactSheet?.id;!a||!r.has(a)||n.push({...i?.id?{id:i.id}:{},sourceFactSheetId:t,targetFactSheetId:a,type:i?.type??`RELATES_TO`})}a=c?.hasNextPage===!0,i=c?.endCursor??null}return n}for(let e=0;e<t.length;e+=10){let r=t.slice(e,e+10),a=await Promise.all(r.map(e=>i(e)));for(let e of a)n.push(...e)}return n}function jr(e,t,n,r){let i=e.external?.[Wn],a=i?.factSheetId??i?.externalId;if(a==null)return null;let o=n.get(a);return!o||r.has(o.id)?null:(r.add(o.id),{canonicalId:t,factSheetId:o.id,name:o.name,type:o.type})}function Mr(e,t,n){let r=t.get(e);return!r||n.has(r.id)?null:(n.add(r.id),{canonicalId:e,factSheetId:r.id,name:r.name,type:r.type})}function Nr(e,t,n,r,i,a,o,s){let c=`${t??e}${n??``}`,l=r.get(c)?.filter(e=>!i.has(e.id))??[];if(l.length===0)o.push({canonicalId:e,...t===void 0?{}:{name:t},...n===void 0?{}:{type:n}});else if(l.length===1){let t=l[0];a.push({canonicalId:e,factSheetId:t.id,name:t.name,type:t.type}),i.add(t.id)}else s.push({canonicalId:e,...t===void 0?{}:{name:t},...n===void 0?{}:{type:n},candidateFactSheetIds:l.map(e=>e.id)})}function Pr(e,t,n={}){let r=n.generatedAt??new Date().toISOString(),i=n.dryRun,a=[],o=[],s=[],c=new Map(e.factSheets.map(e=>[e.id,e])),l=new Map,u=new Map;for(let t of e.factSheets){t.likec4Id&&l.set(t.likec4Id,t);let e=`${t.name}${t.type}`;u.has(e)||u.set(e,[]),u.get(e).push(t)}let d=i?new Map(i.factSheets.map(e=>[e.likec4Id,e])):null,f=new Set;for(let[e,n]of Object.entries(t.entities)){let t=jr(n,e,c,f);if(t){a.push(t);continue}let r=Mr(e,l,f);if(r){a.push(r);continue}let i=d?.get(e);Nr(e,i?.name??void 0,i?.type??void 0,u,f,a,o,s)}let p=e.factSheets.filter(e=>!f.has(e.id)).map(e=>({factSheetId:e.id,name:e.name,type:e.type,...e.likec4Id?{likec4Id:e.likec4Id}:{}}));return{generatedAt:r,manifestProjectId:t.projectId,snapshotGeneratedAt:e.generatedAt,matched:a,unmatchedInLikec4:o,unmatchedInLeanix:p,ambiguous:s,summary:{matched:a.length,unmatchedInLikec4:o.length,unmatchedInLeanix:p.length,ambiguous:s.length}}}function Fr(e){return typeof e==`object`&&!!e}function Ir(e){return Fr(e)?typeof e.canonicalId==`string`:!1}function Lr(e){return Fr(e)?typeof e.viewId==`string`:!1}function Rr(e){return Fr(e)?typeof e.relationId==`string`&&typeof e.sourceFqn==`string`&&typeof e.targetFqn==`string`&&typeof e.compositeKey==`string`:!1}function zr(e){return Fr(e)?typeof e.id==`string`&&typeof e.name==`string`&&typeof e.type==`string`:!1}function Br(e){return Fr(e)?typeof e.sourceFactSheetId==`string`&&typeof e.targetFactSheetId==`string`&&typeof e.type==`string`:!1}function Vr(e){if(!Fr(e)||typeof e.manifestVersion!=`string`||typeof e.generatedAt!=`string`||typeof e.bridgeVersion!=`string`||typeof e.mappingProfile!=`string`||typeof e.projectId!=`string`)return!1;let t=e.entities;if(typeof t!=`object`||!t||Array.isArray(t))return!1;for(let e of Object.values(t))if(!Ir(e))return!1;let n=e.views;if(typeof n!=`object`||!n||Array.isArray(n))return!1;for(let e of Object.values(n))if(!Lr(e))return!1;let r=e.relations;if(!Array.isArray(r))return!1;for(let e of r)if(!Rr(e))return!1;return!0}function Hr(e){if(!Fr(e)||typeof e.generatedAt!=`string`||e.workspaceId!==void 0&&typeof e.workspaceId!=`string`||!Array.isArray(e.factSheets))return!1;for(let t of e.factSheets)if(!zr(t))return!1;if(!Array.isArray(e.relations))return!1;for(let t of e.relations)if(!Br(t))return!1;return!0}const Ur=`No project or empty model`,Wr=`LEANIX_API_TOKEN is required for likec4 sync leanix --apply`,Gr=`default`,Kr=`manifest.json`,qr=`leanix-dry-run.json`,Jr=`report.json`;function Yr(e){return{projectId:String(e.projectId),elements:()=>e.elements(),relationships:()=>e.relationships(),views:()=>e.views()}}function Xr(e){let t=rr(e,{mappingProfile:Gr}),n=or(e,{mappingProfile:Gr});return{manifest:t,dryRun:n,report:cr(t,n)}}async function Zr(e,t,n,r=process.cwd()){await R(e,{recursive:!0});let i=I(e,Kr),a=I(e,qr),o=I(e,Jr);await z(i,JSON.stringify(t.manifest,null,2)),await z(a,JSON.stringify(t.dryRun,null,2)),await z(o,JSON.stringify(t.report,null,2)),n.info(`${C.dim(`generated`)} ${F(r,i)}`),n.info(`${C.dim(`generated`)} ${F(r,a)}`),n.info(`${C.dim(`generated`)} ${F(r,o)}`)}const Qr={manifest:Kr,dryRun:qr,report:Jr};async function $r(e){let t=H(`c4:gen:leanix:dry-run`),n=U(t),{path:r,outdir:i,project:a,useDotBin:o}=e;try{try{var s=Y();let e=s.a(await v(r,{graphviz:o?`binary`:`wasm`,watch:!1})),{projectId:n}=Nn(e,a);a&&t.info(`${C.dim(`project`)} ${C.green(n)}`);let c=await e.layoutedModel(n);if(c===Ee.EMPTY)throw t.error(Ur),Error(Ur);await Zr(i,Xr(Yr(c)),t)}catch(e){s.e=e}finally{await s.d()}}finally{n.stopAndLog()}}function ei(){let e=process.env.LEANIX_API_TOKEN?.trim();return e?new dr({apiToken:e,baseUrl:process.env.LEANIX_BASE_URL?.trim()||`https://app.leanix.net`,requestDelayMs:200}):null}function ti(){let e=ei();if(!e)throw Error(`LEANIX_API_TOKEN is required. Set it in the environment to call the LeanIX API.`);return e}async function ni(e){let t=H(`c4:gen:leanix:inventory`),n=U(t),{outdir:r,likec4IdAttribute:i}=e;try{let e=ti(),n={};typeof i==`string`&&i.trim()!==``&&(n.likec4IdAttribute=i.trim());let a=await Dr(e,n);await R(r,{recursive:!0});let o=I(r,`leanix-inventory-snapshot.json`);await z(o,JSON.stringify(a,null,2)),t.info(`${C.dim(`generated`)} ${F(process.cwd(),o)}`),t.info(`${C.dim(`snapshot`)} ${a.factSheets.length} fact sheets, ${a.relations.length} relations`)}finally{n.stopAndLog()}}const ri=`manifest.json`,ii=`leanix-inventory-snapshot.json`;async function ai(e){let t=I(e,ri),n=I(e,ii),[r,i]=await Promise.all([gt(t,`utf-8`),gt(n,`utf-8`)]),a=JSON.parse(r),o=JSON.parse(i);if(!Vr(a))throw Error(`Invalid manifest format: missing manifestVersion, projectId, entities, relations, or views`);if(!Hr(o))throw Error(`Invalid snapshot format: missing factSheets or relations arrays`);return{manifest:a,snapshot:o}}async function oi(e,t,n){try{var r=Y();let i=r.a(await v(e,{graphviz:n?`binary`:`wasm`,watch:!1})),{projectId:a}=Nn(i,t),o=await i.layoutedModel(a);return o===Ee.EMPTY?void 0:Xr(Yr(o)).dryRun}catch(e){r.e=e}finally{await r.d()}}async function si(e){let t=H(`c4:gen:leanix:reconcile`),n=U(t),{path:r,outdir:i,project:a,useDotBin:o}=e;try{let e,n;try{let t=await ai(i);e=t.manifest,n=t.snapshot}catch(e){let n=e instanceof Error?e.message:String(e);throw t.error(`Failed to read ${ri} or ${ii} from ${i}: ${n}`),e}let s;try{s=await oi(r,a,o)}catch(e){let n=e instanceof Error?e.message:String(e);if(a!=null&&a!==``)throw t.error(`Failed to load workspace for dryRun enrichment: ${n}`),e;t.warn(`Could not load workspace for dryRun enrichment; proceeding without it: ${n}`),s=void 0}let c=Pr(n,e,{...s==null?{}:{dryRun:s}}),l=I(i,`reconciliation-report.json`);await z(l,JSON.stringify(c,null,2)),t.info(`${C.dim(`generated`)} ${F(process.cwd(),l)}`),t.info(`${C.dim(`reconcile`)} matched=${c.summary.matched} unmatchedLikec4=${c.summary.unmatchedInLikec4} unmatchedLeanix=${c.summary.unmatchedInLeanix} ambiguous=${c.summary.ambiguous}`)}finally{n.stopAndLog()}}async function ci({path:e,useDotBin:t,useCorePackage:n,outfile:r,project:i}){try{var a=Y();let o=H(`c4:codegen`),s=U(o),c=a.a(await v(e,{graphviz:t?`binary`:`wasm`,watch:!1})),{projectId:l,projectFolder:u}=Nn(c,i);i&&o.info(`${C.dim(`project`)} ${C.green(l)}`),o.info(`${C.dim(`format`)} ${C.green(`model`)}`);let d=await c.layoutedModel(l);for(let e of d.views())e.hasLayoutDrifts&&o.warn(C.yellow(`layout drift detected, view:`)+` `+C.red(e.id));let f=I(c.projectsManager.hasMultipleProjects()?u:c.workspace,`likec4-model.ts`);if(r&&(f=nt(r)?r:I(r),B(r)&&(await bt(r)).isDirectory()))throw Error(`output file is a directory: ${r}`);let p=et(f);o.info(`${C.dim(`filename`)} ${p}`);let m=tt(p).toLocaleLowerCase();if(![`.ts`,`.mts`,`.cts`].includes(m))throw o.error(`output file ${r} has extension "${m}"`),Error(`output file ${r} must be a .ts, .mts or .cts file`);let h=N(f);o.info(`${C.dim(`outdir`)} ${h}`),await R(h,{recursive:!0}),await z(f,he(d,{useCorePackage:n}),{encoding:`utf-8`}),s.stopAndLog(),W(me(`
81
+ ${C.dim(`Source generated:`)}
82
+ ${F(Dt(),f)}
83
+
84
+ ${C.dim(`How to use:`)}
85
+ ${C.underline(`https://likec4.dev/tooling/code-generation/model/`)}
86
+ `).trim(),{padding:1,borderColor:`green`,borderStyle:`round`})}catch(e){a.e=e}finally{await a.d()}}async function li({languageServices:e,outDir:t,filename:n=`likec4-react.mjs`}){let r=H([`vite`,`react`]),i=Yt();return r.info(`${C.cyan(`likec4 app root`)} ${C.dim(Zt(i))}`),r.info(C.cyan(`outDir`)+` `+C.dim(Zt(t))),{customLogger:r,root:i,configFile:!1,clearScreen:!1,publicDir:!1,mode:`production`,resolve:{conditions:[`production`],alias:$t()},esbuild:{banner:`'use client'
87
+ `+qt.banner,footer:qt.footer,jsx:`transform`,jsxDev:!1,jsxSideEffects:!1,minifyIdentifiers:!1,minifySyntax:!1,minifyWhitespace:!1,tsconfigRaw:{compilerOptions:{target:`ES2022`,useDefineForClassFields:!0,verbatimModuleSyntax:!0,jsx:`react-jsx`}}},build:{outDir:t,emptyOutDir:!1,sourcemap:!1,minify:!1,copyPublicDir:!1,chunkSizeWarningLimit:Qt,assetsInlineLimit:5e5,lib:{entry:`react/likec4.tsx`,fileName(e,t){return n},formats:[`es`]},rollupOptions:{output:{compact:!1,exports:`named`},external:[`likec4/react`,`likec4/model`,`react`,`react-dom`,`react/jsx-runtime`,`react/jsx-dev-runtime`,`react-dom/client`,/@likec4\/core.*/],onwarn(e,t){e.code!==`SOURCEMAP_ERROR`&&t(e)}}},plugins:[Ft({}),we({languageServices:e.languageServices})]}}async function ui({path:e,useDotBin:t,useCorePackage:n,outfile:r,project:i}){try{var a=Y();await on();let o=H(`c4:codegen`),s=U(o),c=a.a(await v(e,{graphviz:t?`binary`:`wasm`,watch:!1})),{projectId:l,projectFolder:u}=Nn(c,i);i&&o.info(`${C.dim(`project`)} ${C.green(l)}`),o.info(`${C.dim(`format`)} ${C.green(`react`)}`);let d=await c.diagrams(l);if(d.length===0)throw process.exitCode=1,Error(`no views found`);d.forEach(e=>{if(e.drifts&&e.drifts.length>0){o.info(C.yellow(`layout drift detected, view:`)+` `+C.red(e.id));return}if(e.hasLayoutDrift){o.warn(C.yellow(`drift detected, manual layout can not be applied, view:`)+` `+C.red(e.id));return}});let f=I(c.projectsManager.hasMultipleProjects()?u:c.workspace,`likec4-views.js`);if(r&&(f=nt(r)?r:I(r),B(r)&&(await bt(r)).isDirectory()))throw Error(`output file is a directory: ${r}`);let p=N(f);o.info(`${C.dim(`outdir`)} ${p}`);let m=et(f);o.info(`${C.dim(`filename`)} ${m}`);let h=tt(m).toLocaleLowerCase();if(![`.js`,`.mjs`,`.jsx`].includes(h))throw o.error(`output file ${r} has extension "${h}"`),Error(`output file ${r} must be a .js, .jsx or .mjs`);await Lt({...await li({languageServices:c,outDir:p,filename:m}),logLevel:`warn`});let g=await c.layoutedModel(l),_=I(p,et(f,h)+(h===`.mjs`?`.d.mts`:`.d.ts`));await z(_,be(g,{useCorePackage:n})),s.stopAndLog(),W(me(`
88
+ ${C.dim(`Sources generated:`)}
89
+ ${F(Dt(),f)}
90
+ ${F(Dt(),_)}
91
+
92
+ ${C.dim(`How to use:`)}
93
+ ${C.underline(`https://likec4.dev/tooling/code-generation/react/`)}
94
+ `),{padding:1,borderColor:`green`,borderStyle:`round`})}catch(e){a.e=e}finally{await a.d()}}async function di({project:e,path:t,useDotBin:n,webcomponentPrefix:r=`likec4`,outfile:i}){try{var o=Y();await on();let s=H(`c4:codegen`),c=U(s),l=o.a(await v(t,{graphviz:n?`binary`:`wasm`,watch:!1})),{projectId:u,projectFolder:d}=Nn(l,e);e&&s.info(`${C.dim(`project`)} ${C.green(u)}`),s.info(`${C.dim(`format`)} ${C.green(`webcomponent`)}`);let f=await l.diagrams(u);if(!a(f,1))throw s.warn(`no views found`),process.exitCode=1,Error(`no views found`);f.forEach(e=>{e.hasLayoutDrift&&s.warn(C.yellow(`drift detected, manual layout can not be applied, view:`)+` `+C.red(e.id))});let p=I(l.projectsManager.hasMultipleProjects()?d:l.workspace,`likec4-views.js`);if(i&&(p=nt(i)?i:I(i),B(i)&&(await bt(i)).isDirectory()))throw Error(`output file is a directory: ${i}`);s.debug(`${C.dim(`outfilepath`)} ${p}`);let m=et(p);s.debug(`${C.dim(`filename`)} ${m}`);let h=tt(m).toLocaleLowerCase();if(h!==`.js`&&h!==`.mjs`)throw s.warn(`output file ${i} has extension "${h}"`),Error(`output file ${i} must be a .js or .mjs`);let g=await Xt();s.debug(`${C.dim(`created temp public`)} ${g}`);let _=await tn({languageServices:l,outDir:g,filename:m,webcomponentPrefix:r,base:`/`});s.debug(`${C.dim(`vite build webcomponent`)}`),await Lt({..._,logLevel:`warn`});let y=I(g,m);if(!B(y))throw Error(`output file not found: ${y}`);await R(N(p),{recursive:!0}),await mt(y,p),s.info(`${C.dim(`generated`)} ${p}`),s.debug(`${C.dim(`remove temp public`)}`),await yt(g,{recursive:!0,force:!0}),c.stopAndLog(),W(me(`
95
+ ${C.dim(`Webcomponents generated to:`)}
96
+ ${F(Dt(),p)}
97
+
98
+ ${C.dim(`Setup and usage instructions:`)}
99
+ ${C.blue(`https://likec4.dev/tooling/code-generation/webcomponent/`)}
100
+ `))}catch(e){o.e=e}finally{await o.d()}}const fi=e=>e.command({command:`gen <command> [path]`,aliases:[`generate`,`codegen`],describe:`Generate various artifacts from LikeC4 sources`,builder:e=>e.positional(`path`,G).command(`react [path]`,`generate react component to render likec4 view`,e=>e.positional(`path`,G).option(`project`,q).option(`outfile`,{alias:[`o`,`output`],type:`string`,desc:`<file> path to output file (.jsx, .mjs or .js)`,normalize:!0,coerce:L}).option(`use-dot`,K).option(`use-core-package`,cn),async e=>{await ui({project:e.project,useDotBin:e.useDotBin,path:e.path,outfile:e.outfile,useCorePackage:e.useCorePackage}),J()}).command({command:`webcomponent [path]`,aliases:[`wc`,`webcomp`],describe:`generate js with webcomponents`,builder:e=>e.positional(`path`,G).option(`project`,q).option(`outfile`,{alias:[`o`,`output`],type:`string`,desc:`<file> path to output file (.mjs or .js)`,normalize:!0,coerce:L}).option(`webcomponent-prefix`,dn).option(`use-dot`,K),handler:async e=>{await di({project:e.project,useDotBin:e.useDotBin,path:e.path,outfile:e.outfile,webcomponentPrefix:e.webcomponentPrefix}),J()}}).command({command:`model [path]`,aliases:[`ts`],describe:`generate LikeC4Model (.ts)`,builder:e=>e.positional(`path`,G).option(`project`,q).option(`outfile`,{alias:[`o`,`output`],type:`string`,desc:`<file> path to output file (.ts)`,normalize:!0,coerce:L}).option(`use-dot`,K).option(`use-core-package`,cn),handler:async e=>{await ci({path:e.path,useDotBin:e.useDotBin,useCorePackage:e.useCorePackage,outfile:e.outfile,project:e.project}),J()}}).command({command:`views-data [path]`,aliases:[`views`],describe:`{deprecated} use codegen model`,deprecated:!0,builder:e=>e.positional(`path`,G).option(`outfile`,{alias:[`o`,`output`],type:`string`,desc:`<file> output .ts file`,normalize:!0,coerce:L}).option(`use-dot`,K),handler:async e=>{await Bn({format:`views`,path:e.path,useDotBin:e.useDotBin,outfile:e.outfile})}}).command({command:`leanix [path]`,describe:`LeanIX bridge: dry-run, inventory snapshot, reconcile`,builder:e=>e.positional(`path`,G).demandCommand(1,`Choose a subcommand: dry-run, inventory, reconcile`).command(`dry-run [path]`,`generate LeanIX bridge artifacts (manifest, dry-run inventory, report)`,e=>e.positional(`path`,G).option(`outdir`,{...un,desc:`<dir> output directory for manifest.json, leanix-dry-run.json, report.json`}).option(`project`,q).option(`use-dot`,K).example(`${C.green(`$0 gen leanix dry-run -o out/bridge`)}`,C.gray(`Write bridge artifacts to out/bridge`)),async e=>{await $r({path:e.path,outdir:e.outdir??L(process.cwd(),`out`,`bridge`),project:e.project,useDotBin:e.useDotBin})}).command(`inventory`,`fetch LeanIX inventory (read-only) and write leanix-inventory-snapshot.json`,e=>e.option(`outdir`,{...un,default:L(process.cwd(),`out`,`bridge`),desc:`<dir> output directory for leanix-inventory-snapshot.json`}).option(`likec4-id-attribute`,{type:`string`,desc:`custom LeanIX attribute key for likec4Id (e.g. "likec4Id")`}).example(`${C.green(`$0 gen leanix inventory -o out/bridge`)}`,C.gray(`Requires LEANIX_API_TOKEN`)),async e=>{await ni({outdir:e.outdir??L(process.cwd(),`out`,`bridge`),...e.likec4IdAttribute==null?{}:{likec4IdAttribute:e.likec4IdAttribute}})}).command(`reconcile [path]`,`reconcile manifest with leanix-inventory-snapshot; write reconciliation-report.json`,e=>e.positional(`path`,G).option(`outdir`,{...un,default:L(process.cwd(),`out`,`bridge`),desc:`<dir> directory with manifest.json and leanix-inventory-snapshot.json`}).option(`project`,q).option(`use-dot`,K).example(`${C.green(`$0 gen leanix reconcile -o out/bridge`)}`,C.gray(`Reads manifest + snapshot from outdir; optional workspace for name+type matching`)),async e=>{await si({path:e.path,outdir:e.outdir??L(process.cwd(),`out`,`bridge`),project:e.project,useDotBin:e.useDotBin})}),handler:async()=>{}}).command({command:`dot [path]`,describe:`generate graphviz files (.dot)`,builder:e=>e.positional(`path`,G).option(`outdir`,un).option(`use-dot`,K),handler:async e=>{await Bn({format:`dot`,path:e.path,useDotBin:e.useDotBin,outdir:e.outdir}),J()}}).command({command:`d2 [path]`,describe:`generate D2 files (.d2)`,builder:e=>e.positional(`path`,G).option(`outdir`,un).option(`use-dot`,K),handler:async e=>{await Bn({format:`d2`,path:e.path,useDotBin:e.useDotBin,outdir:e.outdir}),J()}}).command({command:`mermaid [path]`,aliases:[`mmd`],describe:`generate Mermaid files (.mmd)`,builder:e=>e.positional(`path`,G).option(`outdir`,un).option(`use-dot`,K),handler:async e=>{await Bn({format:`mermaid`,useDotBin:e.useDotBin,path:e.path,outdir:e.outdir}),J()}}).command({command:`plantuml [path]`,aliases:[`puml`],describe:`generate PlantUML files (.puml)`,builder:e=>e.positional(`path`,G).option(`outdir`,un).option(`use-dot`,K),handler:async e=>{await Bn({format:`plantuml`,useDotBin:e.useDotBin,path:e.path,outdir:e.outdir}),J()}}).command({command:`<custom> [path]`,describe:`run custom generator from likec4 config`,builder:e=>e.positional(`path`,G).option(`project`,q).option(`use-dot`,K),handler:async e=>{await Fn({name:`custom`,path:e.path,project:e.project,useDotBin:e.useDotBin})}}).epilog(`${C.bold(`Examples:`)}
101
101
  likec4 gen react -o dist/likec4-views.mjs ./src/likec4
102
102
  likec4 gen model -o likec4-model.ts
103
103
  likec4 gen leanix dry-run -o out/bridge
@@ -110,55 +110,68 @@ import{s as e}from"../_chunks/rolldown-runtime.mjs";import"../_chunks/libs/birpc
110
110
  likec4 gen dot -o out .
111
111
  `),handler:async e=>{await Fn({name:e.command,path:e.path,project:e.project,useDotBin:e.useDotBin})}}),pi=new Set([`node_modules`,`.git`]);function mi(e){return e.endsWith(`.c4`)||e.endsWith(`.likec4`)}function hi(e,t=`
112
112
 
113
- `){return e.filter(e=>e.trim()!==``).join(t)}const gi=`No project or empty model`,_i=`No views could be exported`;function vi(){return`${x.bold(`Examples:`)}
114
- ${x.green(`$0 export drawio`)}
115
- ${x.gray(`Export each view to a separate .drawio file`)}
113
+ `){return e.filter(e=>e.trim()!==``).join(t)}const gi=`No project or empty model`,_i=`No views could be exported`;function vi(){return`${C.bold(`Examples:`)}
114
+ ${C.green(`$0 export drawio`)}
115
+ ${C.gray(`Export each view to a separate .drawio file`)}
116
116
 
117
- ${x.green(`$0 export drawio --all-in-one -o ./diagrams src/`)}
118
- ${x.gray(`Export all views as tabs in one .drawio file`)}
117
+ ${C.green(`$0 export drawio --all-in-one -o ./diagrams src/`)}
118
+ ${C.gray(`Export all views as tabs in one .drawio file`)}
119
119
 
120
- ${x.green(`$0 export drawio --roundtrip -o ./out`)}
121
- ${x.gray(`Re-apply layout/waypoints from comment blocks (e.g. after import from DrawIO)`)}
120
+ ${C.green(`$0 export drawio --roundtrip -o ./out`)}
121
+ ${C.gray(`Re-apply layout/waypoints from comment blocks (e.g. after import from DrawIO)`)}
122
122
 
123
- ${x.green(`$0 export drawio --uncompressed -o ./out`)}
124
- ${x.gray(`Export with raw XML (no compression) for draw.io desktop compatibility`)}
123
+ ${C.green(`$0 export drawio --uncompressed -o ./out`)}
124
+ ${C.gray(`Export with raw XML (no compression) for draw.io desktop compatibility`)}
125
125
 
126
- ${x.green(`$0 export drawio --profile leanix -o ./out`)}
127
- ${x.gray(`Export with bridge-managed metadata (likec4Id, likec4ViewId, etc.) for LeanIX interoperability`)}`}function yi(e){return e instanceof Error?e:Error(h(e))}function bi(e,t,n){let r=yi(n);throw e.error(t,{error:r}),r}async function xi(e,t){let n=[],r=new Set;async function i(e,a){if(a>=50)return;let o=await yt(e).catch(()=>null);if(o==null||r.has(o))return;r.add(o);let s=await vt(e,{withFileTypes:!0}).catch(n=>(t?.debug&&t.debug(`${x.dim(`Roundtrip:`)} readdir failed`,{dir:e,err:n}),[]));for(let r of s){let o=N(e,r.name);switch(!0){case r.isDirectory():pi.has(r.name)||await i(o,a+1);break;case r.isSymbolicLink():if((await xt(o).catch(()=>null))?.isFile()&&mi(r.name)){let e=await _t(o,`utf-8`).catch(e=>(t?.debug&&t.debug(`${x.dim(`Roundtrip:`)} readFile failed`,{file:o,err:e}),``));e&&n.push(e)}break;case r.isFile()&&mi(r.name):{let e=await _t(o,`utf-8`).catch(e=>(t?.debug&&t.debug(`${x.dim(`Roundtrip:`)} readFile failed`,{file:o,err:e}),``));e&&n.push(e);break}}}}return await i(e,0),hi(n)}async function Si(e,t,n){if(t)return xi(F(e),n)}function Ci(e,t,n){let r=e?{compressed:!1}:{compressed:!0};return t===`leanix`&&(r.profile=`leanix`,r.projectId=n),r}function wi(e,t,n,r,i){return Te(e.map(e=>String(e.$view.id)),t,Ci(n,r,i))}async function Ti(e){let{viewmodels:t,outdir:n,workspacePath:r,roundtrip:i,uncompressed:a,profile:o,projectId:s,logger:c}=e,l=xe(t,wi(t,await Si(r,i,c),a,o,s)),u=F(n,De);await R(u,l),c.info(`${x.dim(`generated`)} ${P(process.cwd(),u)} (${t.length} tab(s))`)}async function Ei(e,t,n,r){let i=String(e.$view.id);try{let a=ve(e,t[i]),o=F(n,i+`.drawio`);return await L(M(o),{recursive:!0}),await R(o,a),r.info(`${x.dim(`generated`)} ${P(process.cwd(),o)}`),!0}catch(e){return r.error(`Failed to export view ${i}`,{error:yi(e)}),!1}}async function Di(e){let{viewmodels:t,outdir:n,workspacePath:r,roundtrip:i,uncompressed:a,profile:o,projectId:s,logger:c}=e,l=wi(t,await Si(r,i,c),a,o,s),u=0;for(let e of t)await Ei(e,l,n,c)&&u++;return{succeeded:u}}async function Oi(e,t){try{var n=Y();let r=H(t),i=n.a(await v(e.path,{graphviz:e.useDot?`binary`:`wasm`,watch:!1}));e.project||i.ensureSingleProject();let a=e.project==null?void 0:i.languageServices.projectsManager.ensureProjectId(e.project),o=await i.layoutedModel(a);if(o===Oe.EMPTY)throw t.error(gi),Error(gi);let s=[...o.views()];if(s.length===0)throw t.error(`No views to export`),Error(_i);await L(e.outdir,{recursive:!0});let c=String(o.projectId),l={viewmodels:s,outdir:e.outdir,workspacePath:e.path,roundtrip:e.roundtrip,uncompressed:e.uncompressed,profile:e.profile,projectId:c,logger:t};if(e.allInOne)try{await Ti(l)}catch(e){bi(t,`Failed to export DrawIO`,e)}else{let{succeeded:e}=await Di(l);if(e===0)throw t.error(_i),Error(_i);t.info(`${x.dim(`total`)} ${e} DrawIO file(s)`)}r.stopAndLog(`✓ export drawio in `)}catch(e){n.e=e}finally{await n.d()}}function ki(e){return e.command({command:`drawio [path]`,describe:`export view(s) to DrawIO (.drawio) for editing in draw.io`,builder:e=>e.positional(`path`,W).option(`outdir`,{alias:`o`,type:`string`,desc:`<dir> output directory for .drawio files`,normalize:!0,coerce:F}).option(`all-in-one`,{type:`boolean`,default:!1,desc:`write one .drawio file with all views as tabs (diagrams)`}).option(`roundtrip`,{type:`boolean`,default:!1,desc:`apply layout/stroke/waypoints from DrawIO round-trip comment blocks in .c4 source`}).option(`uncompressed`,{type:`boolean`,default:!1,desc:`write diagram XML uncompressed inside .drawio (larger file; use if draw.io desktop fails to open compressed export)`}).option(`profile`,{type:`string`,choices:[`default`,`leanix`],default:`default`,desc:`export profile: default (round-trip) or leanix (bridge-managed metadata for LeanIX interoperability)`}).options({project:q,"use-dot":G}).epilog(vi()),handler:async e=>{let t=V(`c4:export`);await Oi({path:e.path,outdir:e.outdir??e.path,allInOne:!!e.allInOne,roundtrip:!!e.roundtrip,uncompressed:!!e.uncompressed,profile:e.profile===`leanix`?`leanix`:`default`,project:e.project,useDot:!!e[`use-dot`]},t)}})}const Ai=`project not found`,ji=`No projects found`;async function Mi(e,t){try{var n=Y();let r=H(t),i=n.a(await v(e.path,{graphviz:e.useDot?`binary`:`wasm`,watch:!1})),o=[...i.projectsManager.all];if(e.project){if(o=o.filter(t=>t===e.project),!a(o,1))throw t.error(`${Ai}: ${e.project}`),Error(`${Ai}: ${e.project}`)}else{if(!a(o,1))throw t.error(ji),Error(ji);t.info(`${x.dim(`workspace:`)} Found ${o.length} projects`)}let s=[];for(let n of o){let r;if(e.skipLayout?(t.info(`Generate model for project ${x.green(n)} ${x.dim(`(skip layout)`)}`),r=await i.computedModel(n)):(t.info(`Generating layouted model for project ${x.green(n)}`),r=await i.layoutedModel(n)),r===Oe.EMPTY){t.warn(x.yellow(`Project ${n} is empty, skipping`));continue}s.push(r.$data)}if(s.length===0)throw t.warn(`No models generated, aborting export`),Error(`No models generated; all projects are empty or were skipped`);let c=e.outfile;nt(c).toLowerCase()!==`.json`&&(c+=`.json`),await L(M(c),{recursive:!0});let l=s.length===1?s[0]:s,u=e.pretty?JSON.stringify(l,void 0,2):JSON.stringify(l);await R(c,u);let d=c.startsWith(e.path)?P(e.path,c):c;t.info(`${x.dim(`generated`)} ${d}`),r.stopAndLog(`✓ export in `)}catch(e){n.e=e}finally{await n.d()}}function Ni(e){return e.command({command:`json [path]`,describe:`export model(s) to JSON`,builder:e=>e.positional(`path`,W).option(`outfile`,{alias:`o`,type:`string`,desc:`<file> output .json file`,default:`likec4.json`,normalize:!0,coerce:F}).options({project:q,"use-dot":G,"skip-layout":{type:`boolean`,desc:`skip layouting (only compute model)`},pretty:{type:`boolean`,desc:`indented JSON output`}}).epilog(`${x.bold(`Examples:`)}
128
- ${x.green(`$0 export json --skip-layout`)}
129
- ${x.gray(`Search for likec4 files in current directory and output JSON to likec4.json (no layout)`)}
130
-
131
- ${x.green(`$0 export json --pretty -o ./generated/likec4.json src/likec4 `)}
132
- ${x.gray(`Search for likec4 files in src/likec4 and output JSON to generated/likec4.json`)}
133
- `),handler:async e=>{let t=V(`c4:export`);await Mi({path:e.path,outfile:e.outfile,project:e.project,skipLayout:!!e.skipLayout,pretty:!!e.pretty,useDot:!!e[`use-dot`]},t),J()}})}var Pi=e(he(),1);function Fi(e){if(e.resolvedUrls)return i(e.resolvedUrls.network)??i(e.resolvedUrls.local)}function Ii(e){if(!e.resolvedUrls)throw Error(`Vite server is not ready, no resolvedUrls`);U([x.green(`LikeC4 served at:`),``,x.dim(`Local: `)+e.resolvedUrls.local.join(`
134
- `+``.padEnd(9,` `)),e.resolvedUrls.network.length?x.dim(`Network: `)+e.resolvedUrls.network.join(`
126
+ ${C.green(`$0 export drawio --profile leanix -o ./out`)}
127
+ ${C.gray(`Export with bridge-managed metadata (likec4Id, likec4ViewId, etc.) for LeanIX interoperability`)}`}function yi(e){return e instanceof Error?e:Error(h(e))}function bi(e,t,n){let r=yi(n);throw e.error(t,{error:r}),r}async function xi(e,t){let n=[],r=new Set;async function i(e,a){if(a>=50)return;let o=await vt(e).catch(()=>null);if(o==null||r.has(o))return;r.add(o);let s=await _t(e,{withFileTypes:!0}).catch(n=>(t?.debug&&t.debug(`${C.dim(`Roundtrip:`)} readdir failed`,{dir:e,err:n}),[]));for(let r of s){let o=P(e,r.name);switch(!0){case r.isDirectory():pi.has(r.name)||await i(o,a+1);break;case r.isSymbolicLink():if((await bt(o).catch(()=>null))?.isFile()&&mi(r.name)){let e=await gt(o,`utf-8`).catch(e=>(t?.debug&&t.debug(`${C.dim(`Roundtrip:`)} readFile failed`,{file:o,err:e}),``));e&&n.push(e)}break;case r.isFile()&&mi(r.name):{let e=await gt(o,`utf-8`).catch(e=>(t?.debug&&t.debug(`${C.dim(`Roundtrip:`)} readFile failed`,{file:o,err:e}),``));e&&n.push(e);break}}}}return await i(e,0),hi(n)}async function Si(e,t,n){if(t)return xi(I(e),n)}function Ci(e,t,n){let r=e?{compressed:!1}:{compressed:!0};return t===`leanix`&&(r.profile=`leanix`,r.projectId=n),r}function wi(e,t,n,r,i){return Ce(e.map(e=>String(e.$view.id)),t,Ci(n,r,i))}async function Ti(e){let{viewmodels:t,outdir:n,workspacePath:r,roundtrip:i,uncompressed:a,profile:o,projectId:s,logger:c}=e,l=ye(t,wi(t,await Si(r,i,c),a,o,s)),u=I(n,Te);await z(u,l),c.info(`${C.dim(`generated`)} ${F(process.cwd(),u)} (${t.length} tab(s))`)}async function Ei(e,t,n,r){let i=String(e.$view.id);try{let a=ge(e,t[i]),o=I(n,i+`.drawio`);return await R(N(o),{recursive:!0}),await z(o,a),r.info(`${C.dim(`generated`)} ${F(process.cwd(),o)}`),!0}catch(e){return r.error(`Failed to export view ${i}`,{error:yi(e)}),!1}}async function Di(e){let{viewmodels:t,outdir:n,workspacePath:r,roundtrip:i,uncompressed:a,profile:o,projectId:s,logger:c}=e,l=wi(t,await Si(r,i,c),a,o,s),u=0;for(let e of t)await Ei(e,l,n,c)&&u++;return{succeeded:u}}async function Oi(e,t){try{var n=Y();let r=U(t),i=n.a(await v(e.path,{graphviz:e.useDot?`binary`:`wasm`,watch:!1}));e.project||i.ensureSingleProject();let a=e.project==null?void 0:i.languageServices.projectsManager.ensureProjectId(e.project),o=await i.layoutedModel(a);if(o===Ee.EMPTY)throw t.error(gi),Error(gi);let s=[...o.views()];if(s.length===0)throw t.error(`No views to export`),Error(_i);await R(e.outdir,{recursive:!0});let c=String(o.projectId),l={viewmodels:s,outdir:e.outdir,workspacePath:e.path,roundtrip:e.roundtrip,uncompressed:e.uncompressed,profile:e.profile,projectId:c,logger:t};if(e.allInOne)try{await Ti(l)}catch(e){bi(t,`Failed to export DrawIO`,e)}else{let{succeeded:e}=await Di(l);if(e===0)throw t.error(_i),Error(_i);t.info(`${C.dim(`total`)} ${e} DrawIO file(s)`)}r.stopAndLog(`✓ export drawio in `)}catch(e){n.e=e}finally{await n.d()}}function ki(e){return e.command({command:`drawio [path]`,describe:`export view(s) to DrawIO (.drawio) for editing in draw.io`,builder:e=>e.positional(`path`,G).option(`outdir`,{alias:`o`,type:`string`,desc:`<dir> output directory for .drawio files`,normalize:!0,coerce:I}).option(`all-in-one`,{type:`boolean`,default:!1,desc:`write one .drawio file with all views as tabs (diagrams)`}).option(`roundtrip`,{type:`boolean`,default:!1,desc:`apply layout/stroke/waypoints from DrawIO round-trip comment blocks in .c4 source`}).option(`uncompressed`,{type:`boolean`,default:!1,desc:`write diagram XML uncompressed inside .drawio (larger file; use if draw.io desktop fails to open compressed export)`}).option(`profile`,{type:`string`,choices:[`default`,`leanix`],default:`default`,desc:`export profile: default (round-trip) or leanix (bridge-managed metadata for LeanIX interoperability)`}).options({project:q,"use-dot":K}).epilog(vi()),handler:async e=>{let t=H(`c4:export`);await Oi({path:e.path,outdir:e.outdir??e.path,allInOne:!!e.allInOne,roundtrip:!!e.roundtrip,uncompressed:!!e.uncompressed,profile:e.profile===`leanix`?`leanix`:`default`,project:e.project,useDot:!!e[`use-dot`]},t)}})}var Ai=e(pe(),1);function ji(e){if(e.resolvedUrls)return i(e.resolvedUrls.network)??i(e.resolvedUrls.local)}function Mi(e){if(!e.resolvedUrls)throw Error(`Vite server is not ready, no resolvedUrls`);W([C.green(`LikeC4 served at:`),``,C.dim(`Local: `)+e.resolvedUrls.local.join(`
128
+ `+``.padEnd(9,` `)),e.resolvedUrls.network.length?C.dim(`Network: `)+e.resolvedUrls.network.join(`
135
129
  `+``.padEnd(9,` `)):void 0].filter(e=>u(e)).join(`
136
- `))}async function Li({buildWebcomponent:e=!0,hmr:t=!0,webcomponentPrefix:n=`likec4`,title:r,languageServices:i,likec4AssetsDir:a,openBrowser:o,listen:s,port:c,...l}){a??=await gt(N(lt(),`.likec4-assets-`));let{isDev:u,...d}=await tn({...l,languageServices:i,likec4AssetsDir:a,webcomponentPrefix:n,title:r}),f=d.customLogger;c??=ut.PORT?parseInt(ut.PORT,10):void 0,c||=await Ue({port:[5173,5174,...He(61e3,61010),...He(62002,62010)]});let p=24678,m=await Zt(),g=s??(S()?`0.0.0.0`:`localhost`);t?(p=await Ue({port:He(24678,24690)}),f.info(`Enabling HMR: localhost:${p}`),S()&&f.info(x.yellow(`ensure port ${p} is published from container`))):f.info(`Disabling HMR`);let _=await zt({...d,define:t?{...d.define,"process.env.NODE_ENV":`"development"`}:d.define,mode:t?`development`:d.mode,publicDir:m,server:{host:g,allowedHosts:!0,port:c,hmr:t&&{overlay:!0,port:p},fs:{strict:!1},open:o??(!u&&!S())}});return e?(f.info(`Building webcomponent`),nn({webcomponentPrefix:n,languageServices:i,outDir:m,base:d.base}).then(e=>Rt({...e,logLevel:`warn`})).catch(e=>{f.warn(h(e)),f.warn(`webcomponent build failed, ignoring error and continue`)})):f.info(`Skip webcomponent build`),await _.listen(),_}async function Ri({browserContext:e,views:r,output:i,logger:a,timeout:o,maxAttempts:s,dynamicVariant:c,outputType:l,theme:u}){let d,f=r.map(e=>({view:e,attempt:1})),p=[],m;for(;m=f.shift();){let{view:r,attempt:h}=m,g=`export/${encodeURIComponent(r.id)}/`;try{if(h>1){d&&=(d.close({runBeforeUnload:!0}).catch(e=>a.error(`failed to close page: ${e}`)),void 0);let e=t(h*200,{min:200,max:1e3});a.info(x.cyan(g)+x.dim(` attempt ${h} of ${s} after ${e}ms`)),await Vt(e)}else r.hasLayoutDrift&&a.warn(x.yellow(`Drift detected, manual layout can not be applied, view may be invalid: `)+x.red(r.id));let f=`.`;l===`relative`&&(f=r.sourcePath??`.`,f=f.includes(`/`)?f.slice(0,f.lastIndexOf(`/`)):`.`);let m=F(i,f,`${r.id}.png`);d??=await e.newPage();let _=r.bounds;c===`sequence`&&r._type===`dynamic`&&(_=r.sequenceLayout.bounds),await d.setViewportSize({width:_.width+40+20,height:_.height+40+20}),await d.goto(ae(g,{padding:20,theme:u,dynamic:c})),a.info(x.cyan(g)+x.dim(` -> ${P(i,m)}`)),await d.waitForSelector(`.react-flow.initialized`),r.nodes.some(e=>n(e.icon)&&e.icon.toLowerCase().startsWith(`http`))&&await zi(d,o),await d.getByTestId(`export-page`).screenshot({animations:`disabled`,path:m,omitBackground:!0}),p.push({view:r,path:m})}catch(e){d?.close({runBeforeUnload:!0}).catch(e=>a.error(`failed to close page: ${e}`)),a.error(x.red(`failed `+g+`
137
- `+e)),h<s&&(f.push({view:r,attempt:h+1}),a.info(x.dim(`retry ${g}`))),d=void 0}}return p}async function zi(e,t){let n=await e.locator(`//img`).all();if(!n.length)return;let r=n.map(e=>e.evaluate(e=>e.complete||new Promise(t=>{e.onload=t,e.onerror=t}),{timeout:Math.max(15e3,t)}));await Promise.allSettled(r)}async function Bi({logger:e,serverUrl:t,theme:n=`light`,timeoutMs:r=15e3,views:i,output:a,outputType:o=`relative`,maxAttempts:s=3,chromiumSandbox:c=!1,sequence:l=!1}){e.info(`${x.dim(`output`)} ${a}`),e.info(`${x.dim(`base url`)} ${t}\n`);let{chromium:u}=await import(`playwright`),d=u.executablePath();e.info(x.cyan(`Start chromium`)+` `+x.dim(d));let f=await u.launch({chromiumSandbox:c,headless:!0});e.info(x.cyan(`Color scheme: `)+n+`
138
- `);let p=await f.newContext({deviceScaleFactor:2,colorScheme:n,baseURL:t,bypassCSP:!0,ignoreHTTPSErrors:!0,isMobile:!1});p.setDefaultNavigationTimeout(r),p.setDefaultTimeout(r);try{return await Ri({browserContext:p,views:i,output:a,outputType:o,logger:e,maxAttempts:s,dynamicVariant:l?`sequence`:`diagram`,timeout:r,theme:n})}finally{e.info(x.cyan(`close chromium`)),await p.close(),await f.close()}}async function Vi(e,t){try{var n=Y();let{path:r,useDotBin:i,project:o,theme:s=`light`,output:c,outputType:l,serverUrl:u,ignore:d=!1,timeoutMs:f=15e3,maxAttempts:p=3,filter:m,sequence:h=!1,chromiumSandbox:g=!1}=e,_=n.a(await v(r,{graphviz:i?`binary`:`wasm`,watch:!1})),y=c??_.workspace,ee,b=u,te=[..._.languageServices.projects()];if(o&&!te.some(e=>e.id===o))throw t.error(`project not found: ${o}`),Error(`project not found: ${o}`);try{if(!b&&(t.info(x.cyan(`start preview server`)),ee=await Li({languageServices:_,buildWebcomponent:!1,openBrowser:!1,hmr:!1}),b=Fi(ee),!b))throw t.error(`Vite server is not ready, no resolvedUrls`),Error(`Vite server is not ready, no resolvedUrls`);for(let e of te){if(o&&e.id!==o)continue;te.length>1&&(t.info(x.dim(`---------`)),t.info(`${x.dim(`project:`)} ${e.id}`),t.info(`${x.dim(`folder:`)} ${e.folder.fsPath}`));let n=await _.diagrams(e.id);if(m&&a(m,1)&&a(n,1)){let e=(0,Pi.default)(m);t.info(`${x.cyan(`filter`)} ${x.dim(JSON.stringify(m))}`),n=n.filter(n=>e(n.id)?(t.info(`${x.green(`include`)} ${n.id} ✅`),!0):(t.info(`${x.gray(`skip`)} ${x.dim(n.id)}`),!1))}if(!a(n,1)){t.warn(`no views found`);continue}let r=te.length>1?oe(se(b,`project`,e.id)):b,i=te.length>1?se(y,e.id):y,c=At(),u=await Bi({logger:t,serverUrl:r,theme:s,timeoutMs:f,views:n,output:i,outputType:l,maxAttempts:p,sequence:h,chromiumSandbox:g}),{pretty:v}=Gt(c);if(u.length>0&&t.info(x.green(`exported ${u.length} views in ${v}`)+`
139
- `),u.length!==n.length&&(d&&u.length>0?t.info(x.dim(`ignore`)+` `+x.red(`failed ${n.length-u.length} out of ${n.length} views`)):t.error(x.red(`failed ${n.length-u.length} out of ${n.length} views`))),u.length!==n.length&&(u.length===0||!d))throw Error(`Failed ${n.length-u.length} out of ${n.length} views`)}}finally{ee&&(t.info(x.cyan(`stop server`)),await ee.close().catch(e=>{t.error(e)}))}}catch(e){n.e=e}finally{await n.d()}}async function Hi(e){await Vi(e,V(`c4:export`))}function Ui(e){return e.command({command:`png [path]`,describe:`export views to PNG`,builder:e=>e.positional(`path`,W).options({outdir:{alias:[`o`,`output`],type:`string`,desc:`output directory for PNG files; if not specified, images are saved next to sources`,normalize:!0,nargs:1,coerce:F},project:q,theme:{choices:[`light`,`dark`],desc:`color-scheme to use, defaults to light`,conflicts:[`dark`,`light`],nargs:1},dark:{type:`boolean`,desc:`use dark theme, shortcut for --theme=dark`,conflicts:[`theme`,`light`]},light:{type:`boolean`,desc:`use light theme, shortcut for --theme=light`,conflicts:[`theme`,`dark`]},"use-dot":G,seq:{alias:[`sequence`],type:`boolean`,desc:`use sequence layout for dynamic views`},flat:{alias:[`flatten`],type:`boolean`,desc:`flatten all images in outdir ignoring sources structure`},filter:{alias:`f`,array:!0,string:!0,desc:`include views with ids matching given patterns
140
- multiple patterns are combined with OR`},ignore:{boolean:!0,alias:`i`,desc:`continue if export fails for some views`},timeout:{type:`number`,alias:`t`,desc:`timeout for playwright (in seconds)`,default:15,nargs:1},"max-attempts":{type:`number`,desc:`max attempts to export failing view, 1 means no retry`,default:3,nargs:1},"server-url":{type:`string`,desc:`use this url instead of starting new likec4 server`,nargs:1},"chromium-sandbox":{boolean:!0,desc:`enable chromium sandbox (see Playwright docs)`,default:!1}}).epilog(`${x.bold(`Examples:`)}
141
- ${x.green(`$0 export png`)}
142
- ${x.gray(`Search for likec4 files in current directory and output PNG next to sources`)}
143
-
144
- ${x.green(`$0 export png --theme dark -o ./png src/likec4`)}
145
- ${x.gray(`Search for likec4 files in src/likec4 and output PNG with dark theme to png folder`)}
146
-
147
- ${x.green(`$0 export png -f "team1*" -f "team2*" --flat -o ./png src/likec4`)}
148
- ${x.gray(`Export views matching team1* or team2* only`)}
149
-
150
- ${x.green(`$0 export png -f "use-case*" --sequence src/likec4`)}
151
- ${x.gray(`Export views matching use-case* using sequence layout`)}
152
- `),handler:async e=>{j(e.timeout>=1,`timeout must be >= 1`),j(e[`max-attempts`]>=1,`max-attempts must be >= 1`),await sn(),await cn();let t=e.theme??(e.dark?`dark`:`light`);await Hi({path:e.path,useDotBin:e[`use-dot`],output:e.outdir,project:e.project,timeoutMs:e.timeout*1e3,maxAttempts:e[`max-attempts`],ignore:e.ignore===!0,outputType:e.flat?`flat`:`relative`,serverUrl:e[`server-url`],theme:t,filter:e.filter,sequence:e.seq,chromiumSandbox:e[`chromium-sandbox`]}),J()}})}const Wi=e=>e.command({command:`export <format> [path]`,describe:`Export to images, JSON, or DrawIO`,builder:e=>o(e.usage(`${x.bold(`Usage:`)} $0 export <format> [path]`),Ui,Ni,ki).updateStrings({"Commands:":x.bold(`Formats:`)}),handler:()=>void 0}),Gi=e=>e.command({command:`format [path]`,aliases:[`fmt`],describe:`Format LikeC4 source files`,builder:e=>e.positional(`path`,W).options({project:{alias:`p`,type:`string`,array:!0,desc:`select project(s) to format (repeatable)`},files:{type:`string`,array:!0,normalize:!0,coerce:e=>e.map(e=>F(e)),desc:`specific file(s) to format (repeatable)`},check:{type:`boolean`,desc:`Check if files are formatted (exit with 1 if not)`,default:!1}}),handler:async e=>{try{var t=Y();let n=V(`c4:format`),r=H(n),i=e.check,a;try{a=await v(e.path,{watch:!1})}catch(e){n.error(e instanceof Error?e.message:String(e)),process.exitCode=1;return}t.a(a);let o=e.project?.filter(Boolean),s=e.files?.filter(Boolean).map(e=>Ft(e).toString());if(n.debug(`workspace: ${e.path}`),o?.length){n.debug(`projects:`);for(let e of o)n.debug(` ${e}`)}if(s?.length){n.debug(`files:`);for(let e of s)n.debug(` ${Pt(e)}`)}let c;try{c=await a.format({...o?.length&&{projects:o},...s?.length&&{documentUris:s}})}catch(e){n.error(e instanceof Error?e.message:String(e)),process.exitCode=1;return}n.debug(`${c.size} document(s) to process`);let l=process.cwd(),u=e=>{let t=P(l,e);return t.startsWith(`..`)?e:t};if(s){let e=s.filter(e=>!c.has(e));for(let t of e)n.warn(`${x.yellow(`skipped`)} ${u(Pt(t))} (not found in workspace)`)}let d=0,f=0,p=[];for(let[e,t]of c){let r=Pt(e),a=u(r),o;try{o=await _t(r,`utf-8`)}catch(e){n.error(`Failed to read ${a}: ${e}`),f++;continue}if(o===t){n.debug(`${x.dim(`unchanged`)} ${a}`);continue}if(d++,p.push(a),i)n.info(`${x.yellow(`needs formatting`)} ${a}`);else try{await R(r,t,`utf-8`),n.info(`${x.green(`formatted`)} ${a}`)}catch(e){n.error(`Failed to write ${a}: ${e}`),f++}}if(f>0){n.error(`${f} file(s) failed to process`),process.exitCode=1;return}if(i){if(d>0){n.error(`${d} of ${c.size} file(s) need formatting:\n${p.map(e=>` ${e}`).join(`
153
- `)}`),process.exitCode=1;return}n.info(x.green(`All ${c.size} file(s) are formatted`))}else d>0?n.info(`${x.green(String(d))} of ${c.size} file(s) formatted`):n.info(x.green(`All ${c.size} file(s) already formatted`));r.stopAndLog(`✓ format in `)}catch(e){t.e=e}finally{await t.d()}}}),Ki=e=>e.command({command:`list-icons`,describe:`List available built-in icons`,builder:e=>e.option(`format`,{alias:`f`,choices:[`text`,`json`],default:`text`,description:`Output format`}).option(`group`,{alias:`g`,choices:g,description:`Filter icons by group`}),handler:e=>{let t=e.group?[e.group]:g;switch(!0){case e.format===`json`:{let e=Object.fromEntries(t.map(e=>[e,f[e]]));console.log(JSON.stringify(e,null,2));break}default:for(let e of t)for(let t of f[e])console.log(`${e}:${t}`)}}});var qi=We();function Ji(e){return e.command({command:`lsp`,aliases:[],describe:`Start LSP server`,builder:e=>e.usage(`${x.bold(`Usage:`)} $0 lsp`).option(`log-level`,vn).option(`verbose`,yn).options({"node-ipc":{boolean:!0,description:`use node-ipc transport`,conflicts:[`stdio`,`socket`,`pipe`]},stdio:{boolean:!0,description:`use stdio transport`,conflicts:[`node-ipc`,`socket`,`pipe`]},socket:{number:!0,description:`use socket transport on specified port`,conflicts:[`node-ipc`,`stdio`,`pipe`],nargs:1},pipe:{string:!0,description:`use pipe transport with specified pipe name`,conflicts:[`node-ipc`,`stdio`,`socket`],nargs:1},"manual-layouts":{boolean:!0,description:`enable/disable manual layouts`,default:!0,defaultDescription:`enabled`},watch:{alias:`w`,boolean:!0,description:`enable built-in watcher`,default:!1,defaultDescription:`disabled`},telemetry:{boolean:!0,default:!0,defaultDescription:`IDE setting`,description:`enable/disable telemetry`,hidden:!0}}).option(`use-dot`,G).showHidden().epilog(`${x.bold(`Examples:`)}
154
-
155
- ${x.green(`$0 lsp --stdio `)}
156
- ${x.gray(`Start LSP with stdio transport`)}
157
-
158
- ${x.green(`$0 lsp --node-ipc --watch --no-manual-layouts --no-color `)}
159
- ${x.gray(`Start LSP with node-ipc transport and watcher, disabled manual layouts and disabled color`)}
160
-
161
- `),handler:e=>{let t;if(e.nodeIpc||e.stdio||e.socket||e.pipe)t=(0,qi.createConnection)(qi.ProposedFeatures.all);else throw Error(`No transport specified`);y({lspConnection:t,useStdErr:e.stdio===!0,colors:x.isColorSupported,enableTelemetry:e.telemetry,logLevel:e.verbose?bn:e.logLevel}),ee({connection:t,enableManualLayouts:e.manualLayouts,enableWatcher:e.watch,graphviz:e.useDot?`binary`:`wasm`,configureLogger:!1})}})}const X=p.getChild(`mcp`);function Z(e,t){let{name:n,description:r,...i}=e;return e=>[n,{description:r?.trim()??``,...i},Yi(n,e,t)]}function Yi(e,t,n){let r=n.bind(null,t);return(async function t(n,i){X.debug(`Calling tool {name}, args: {args}`,{name:e,args:n});try{let e=await r.call(null,n,i);return typeof e==`string`?{content:[{type:`text`,text:e}]}:{content:[{type:`text`,text:JSON.stringify(e)}],structuredContent:e}}catch(t){return X.error(`Tool ${e} failed`,{err:t}),{content:[{type:`text`,text:h(t)}],isError:!0}}})}var Xi=`1.55.0`;const Zi=w({name:A().describe(`Project identifier`),title:A().optional().describe(`Human-readable project title`),contactPerson:A().optional().describe(`Maintainer contact information`),metadata:E(A(),Ie()).optional().describe(`Custom project metadata as key-value pairs`),extends:T([A(),D(A())]).optional().describe(`Style inheritance paths`),exclude:D(A()).optional().describe(`File exclusion patterns`),include:w({paths:D(A()).describe(`Include paths`),maxDepth:k().describe(`Maximum directory depth`),fileThreshold:k().describe(`File threshold`)}).optional().describe(`Include configuration`),manualLayouts:w({outDir:A().describe(`Output directory for manual layouts`)}).optional().describe(`Manual layouts configuration`),styles:w({hasTheme:O().describe(`Whether theme customization is defined`),hasDefaults:O().describe(`Whether default style values are defined`),hasCustomCss:O().describe(`Whether custom CSS is defined`)}).optional().describe(`Simplified styles configuration (boolean flags)`)});function Qi(e){let t={name:e.name};return e.title!=null&&(t.title=e.title),e.contactPerson!=null&&(t.contactPerson=e.contactPerson),e.metadata&&(t.metadata=e.metadata),e.extends&&(t.extends=e.extends),e.exclude&&(t.exclude=e.exclude),e.include&&(t.include={paths:e.include.paths||[],maxDepth:e.include.maxDepth??3,fileThreshold:e.include.fileThreshold??30}),e.manualLayouts&&(t.manualLayouts={outDir:e.manualLayouts.outDir??`.likec4`}),e.styles&&(t.styles={hasTheme:!!e.styles.theme,hasDefaults:!!e.styles.defaults,hasCustomCss:!!e.styles.customCss}),t}const $i=w({id:A().describe(`Element id (FQN)`),name:A().describe(`Element name`),kind:A().describe(`Element kind`),title:A(),tags:D(A()),metadata:E(T([A(),D(A())])),includedInViews:D(w({id:A().describe(`View id`),title:A().describe(`View title`),type:C([`element`,`deployment`,`dynamic`]).describe(`View type`)})).describe(`Views that include this element`)});function Q(e){return{id:e.id,name:e.name,kind:e.kind,title:e.title,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:ra(e.views())}}function ea(e,t,n,r,i,a){j(e.findElement(t),`Element "${t}" not found`);let o=new Set,s={},c=0,l=!1,u=[{elementId:t,depth:0}];for(;u.length>0;){let{elementId:t,depth:d}=u.shift();if(d>i||o.has(t))continue;if(o.size>=a){l=!0;break}let f=e.findElement(t);if(!f)continue;o.add(t),c=Math.max(c,d);let p=(n===`incoming`?[...f.incoming(r)]:[...f.outgoing(r)]).map(e=>{let t={elementId:n===`incoming`?e.source.id:e.target.id};return e.title&&(t.relationshipLabel=e.title),e.technology&&(t.technology=e.technology),t});s[t]={...Q(f),neighbors:p,depth:d};for(let e of p)o.has(e.elementId)||u.push({elementId:e.elementId,depth:d+1})}for(let e of Object.values(s))e.neighbors=e.neighbors.filter(e=>e.elementId in s);return{target:t,totalNodes:o.size,maxDepth:c,truncated:l,nodes:s}}const ta=w({path:A().describe(`Path to the file`),range:w({start:w({line:k(),character:k()}),end:w({line:k(),character:k()})}).describe(`Range in the file`)}).nullable(),$=A().refine(e=>!0).optional().default(`default`).describe(`Project id (optional, will use "default" if not specified)`),na=D(w({id:A().describe(`View id`),title:A().describe(`View title`),type:C([`element`,`deployment`,`dynamic`]).describe(`View type`)})),ra=e=>[...e].map(e=>({id:e.id,title:e.titleOrId,type:e.$view._type})),ia=(e,t)=>n=>{try{let r=e.locate({projectId:t,...n});return r?{path:re.parse(r.uri).fsPath,range:r.range}:null}catch(e){return X.debug(`Failed to locate {params}`,{error:e,params:n}),null}},aa=$i.extend({description:A().nullable().describe(`Element description`),technology:A().nullable().describe(`Element technology`),shape:A().describe(`Rendered shape`),color:A().describe(`Rendered color`),children:D(A()).describe(`Direct child element ids`),incomingCount:k().describe(`Number of incoming relationships`),outgoingCount:k().describe(`Number of outgoing relationships`)}),oa=Z({name:`batch-read-elements`,description:`
130
+ `))}async function Ni({buildWebcomponent:e=!0,hmr:t=!0,webcomponentPrefix:n=`likec4`,title:r,languageServices:i,likec4AssetsDir:a,openBrowser:o,listen:s,port:c,...l}){a??=await ht(P(ct(),`.likec4-assets-`));let{isDev:u,...d}=await en({...l,languageServices:i,likec4AssetsDir:a,webcomponentPrefix:n,title:r}),f=d.customLogger;c??=lt.PORT?parseInt(lt.PORT,10):void 0,c||=await He({port:[5173,5174,...Ve(61e3,61010),...Ve(62002,62010)]});let p=24678,m=await Xt(),g=s??(De()?`0.0.0.0`:`localhost`);t?(p=await He({port:Ve(24678,24690)}),f.info(`Enabling HMR: localhost:${p}`),De()&&f.info(C.yellow(`ensure port ${p} is published from container`))):f.info(`Disabling HMR`);let _=await Rt({...d,define:t?{...d.define,"process.env.NODE_ENV":`"development"`}:d.define,mode:t?`development`:d.mode,publicDir:m,server:{host:g,allowedHosts:!0,port:c,hmr:t&&{overlay:!0,port:p},fs:{strict:!1},open:o??(!u&&!De())}});return e?(f.info(`Building webcomponent`),tn({webcomponentPrefix:n,languageServices:i,outDir:m,base:d.base}).then(e=>Lt({...e,logLevel:`warn`})).catch(e=>{f.warn(h(e)),f.warn(`webcomponent build failed, ignoring error and continue`)})):f.info(`Skip webcomponent build`),await _.listen(),_}async function Pi({browserContext:e,views:r,output:i,logger:a,timeout:o,maxAttempts:s,dynamicVariant:c,outputType:l,theme:u,format:d=`png`,quality:f}){let p,m=r.map(e=>({view:e,attempt:1})),h=[],g;for(;g=m.shift();){let{view:r,attempt:_}=g,v=`export/${encodeURIComponent(r.id)}/`;try{if(_>1){p&&=(p.close({runBeforeUnload:!0}).catch(e=>a.error(`failed to close page: ${e}`)),void 0);let e=t(_*200,{min:200,max:1e3});a.info(C.cyan(v)+C.dim(` attempt ${_} of ${s} after ${e}ms`)),await Bt(e)}else r.hasLayoutDrift&&a.warn(C.yellow(`Drift detected, manual layout can not be applied, view may be invalid: `)+C.red(r.id));let m=`.`;l===`relative`&&(m=r.sourcePath??`.`,m=m.includes(`/`)?m.slice(0,m.lastIndexOf(`/`)):`.`);let g=d===`jpeg`?`.jpg`:`.png`,y=I(i,m,`${r.id}${g}`);p??=await e.newPage();let b=r.bounds;c===`sequence`&&r._type===`dynamic`&&(b=r.sequenceLayout.bounds),await p.setViewportSize({width:b.width+40+20,height:b.height+40+20}),await p.goto(re(v,{padding:20,theme:u,dynamic:c,...d===`jpeg`?{format:`jpeg`}:{}})),a.info(C.cyan(v)+C.dim(` -> ${F(i,y)}`)),await p.waitForSelector(`.react-flow.initialized`),r.nodes.some(e=>n(e.icon)&&e.icon.toLowerCase().startsWith(`http`))&&await Fi(p,o),await p.getByTestId(`export-page`).screenshot({animations:`disabled`,path:y,type:d===`jpeg`?`jpeg`:`png`,...d===`jpeg`?{quality:f??80,omitBackground:!1}:{omitBackground:!0}}),h.push({view:r,path:y})}catch(e){p?.close({runBeforeUnload:!0}).catch(e=>a.error(`failed to close page: ${e}`)),a.error(C.red(`failed `+v+`
131
+ `+e)),_<s&&(m.push({view:r,attempt:_+1}),a.info(C.dim(`retry ${v}`))),p=void 0}}return h}async function Fi(e,t){let n=await e.locator(`//img`).all();if(!n.length)return;let r=n.map(e=>e.evaluate(e=>e.complete||new Promise(t=>{e.onload=t,e.onerror=t}),{timeout:Math.max(15e3,t)}));await Promise.allSettled(r)}async function Ii({logger:e,serverUrl:t,theme:n=`light`,timeoutMs:r=15e3,views:i,output:a,outputType:o=`relative`,maxAttempts:s=3,chromiumSandbox:c=!1,sequence:l=!1,format:u=`png`,quality:d}){e.info(`${C.dim(`output`)} ${a}`),e.info(`${C.dim(`base url`)} ${t}\n`);let{chromium:f}=await import(`playwright`),p=f.executablePath();e.info(C.cyan(`Start chromium`)+` `+C.dim(p));let m=await f.launch({chromiumSandbox:c,headless:!0});e.info(C.cyan(`Color scheme: `)+n+`
132
+ `);let h=await m.newContext({deviceScaleFactor:2,colorScheme:n,baseURL:t,bypassCSP:!0,ignoreHTTPSErrors:!0,isMobile:!1});h.setDefaultNavigationTimeout(r),h.setDefaultTimeout(r);try{return await Pi({browserContext:h,views:i,output:a,outputType:o,logger:e,maxAttempts:s,dynamicVariant:l?`sequence`:`diagram`,timeout:r,theme:n,format:u,quality:d})}finally{e.info(C.cyan(`close chromium`)),await h.close(),await m.close()}}async function Li(e,t){try{var n=Y();let{path:r,useDotBin:i,project:o,theme:s=`light`,output:c,outputType:l,serverUrl:u,ignore:d=!1,timeoutMs:f=15e3,maxAttempts:p=3,filter:m,sequence:h=!1,chromiumSandbox:g=!1,format:_=`png`,quality:y}=e,b=n.a(await v(r,{graphviz:i?`binary`:`wasm`,watch:!1})),ee=c??b.workspace,te,x=u,S=[...b.languageServices.projects()];if(o&&!S.some(e=>e.id===o))throw t.error(`project not found: ${o}`),Error(`project not found: ${o}`);try{if(!x&&(t.info(C.cyan(`start preview server`)),te=await Ni({languageServices:b,buildWebcomponent:!1,openBrowser:!1,hmr:!1}),x=ji(te),!x))throw t.error(`Vite server is not ready, no resolvedUrls`),Error(`Vite server is not ready, no resolvedUrls`);for(let e of S){if(o&&e.id!==o)continue;S.length>1&&(t.info(C.dim(`---------`)),t.info(`${C.dim(`project:`)} ${e.id}`),t.info(`${C.dim(`folder:`)} ${e.folder.fsPath}`));let n=await b.diagrams(e.id);if(m&&a(m,1)&&a(n,1)){let e=(0,Ai.default)(m);t.info(`${C.cyan(`filter`)} ${C.dim(JSON.stringify(m))}`),n=n.filter(n=>e(n.id)?(t.info(`${C.green(`include`)} ${n.id} ✅`),!0):(t.info(`${C.gray(`skip`)} ${C.dim(n.id)}`),!1))}if(!a(n,1)){t.warn(`no views found`);continue}let r=S.length>1?ie(ae(x,`project`,e.id)):x,i=S.length>1?ae(ee,e.id):ee,c=kt(),u=await Ii({logger:t,serverUrl:r,theme:s,timeoutMs:f,views:n,output:i,outputType:l,maxAttempts:p,sequence:h,chromiumSandbox:g,format:_,quality:y}),{pretty:v}=Wt(c);if(u.length>0&&t.info(C.green(`exported ${u.length} views in ${v}`)+`
133
+ `),u.length!==n.length&&(d&&u.length>0?t.info(C.dim(`ignore`)+` `+C.red(`failed ${n.length-u.length} out of ${n.length} views`)):t.error(C.red(`failed ${n.length-u.length} out of ${n.length} views`))),u.length!==n.length&&(u.length===0||!d))throw Error(`Failed ${n.length-u.length} out of ${n.length} views`)}}finally{te&&(t.info(C.cyan(`stop server`)),await te.close().catch(e=>{t.error(e)}))}}catch(e){n.e=e}finally{await n.d()}}async function Ri(e){await Li(e,H(`c4:export`))}function zi(e){return e.command({command:`png [path]`,describe:`export views to PNG`,builder:e=>e.positional(`path`,G).options({outdir:{alias:[`o`,`output`],type:`string`,desc:`output directory for PNG files; if not specified, images are saved next to sources`,normalize:!0,nargs:1,coerce:I},project:q,theme:{choices:[`light`,`dark`],desc:`color-scheme to use, defaults to light`,conflicts:[`dark`,`light`],nargs:1},dark:{type:`boolean`,desc:`use dark theme, shortcut for --theme=dark`,conflicts:[`theme`,`light`]},light:{type:`boolean`,desc:`use light theme, shortcut for --theme=light`,conflicts:[`theme`,`dark`]},"use-dot":K,seq:{alias:[`sequence`],type:`boolean`,desc:`use sequence layout for dynamic views`},flat:{alias:[`flatten`],type:`boolean`,desc:`flatten all images in outdir ignoring sources structure`},filter:{alias:`f`,array:!0,string:!0,desc:`include views with ids matching given patterns
134
+ multiple patterns are combined with OR`},ignore:{boolean:!0,alias:`i`,desc:`continue if export fails for some views`},timeout:{type:`number`,alias:`t`,desc:`timeout for playwright (in seconds)`,default:15,nargs:1},"max-attempts":{type:`number`,desc:`max attempts to export failing view, 1 means no retry`,default:3,nargs:1},"server-url":{type:`string`,desc:`use this url instead of starting new likec4 server`,nargs:1},"chromium-sandbox":{boolean:!0,desc:`enable chromium sandbox (see Playwright docs)`,default:!1}}).epilog(`${C.bold(`Examples:`)}
135
+ ${C.green(`$0 export png`)}
136
+ ${C.gray(`Search for likec4 files in current directory and output PNG next to sources`)}
137
+
138
+ ${C.green(`$0 export png --theme dark -o ./png src/likec4`)}
139
+ ${C.gray(`Search for likec4 files in src/likec4 and output PNG with dark theme to png folder`)}
140
+
141
+ ${C.green(`$0 export png -f "team1*" -f "team2*" --flat -o ./png src/likec4`)}
142
+ ${C.gray(`Export views matching team1* or team2* only`)}
143
+
144
+ ${C.green(`$0 export png -f "use-case*" --sequence src/likec4`)}
145
+ ${C.gray(`Export views matching use-case* using sequence layout`)}
146
+ `),handler:async e=>{M(e.timeout>=1,`timeout must be >= 1`),M(e[`max-attempts`]>=1,`max-attempts must be >= 1`),await on(),await sn();let t=e.theme??(e.dark?`dark`:`light`);await Ri({path:e.path,useDotBin:e[`use-dot`],output:e.outdir,project:e.project,timeoutMs:e.timeout*1e3,maxAttempts:e[`max-attempts`],ignore:e.ignore===!0,outputType:e.flat?`flat`:`relative`,serverUrl:e[`server-url`],theme:t,filter:e.filter,sequence:e.seq,chromiumSandbox:e[`chromium-sandbox`]}),J()}})}async function Bi(e){let t=H(`c4:export`);await Li({...e,format:`jpeg`},t)}function Vi(e){return e.command({command:`jpg [path]`,describe:`export views to JPEG`,builder:e=>e.positional(`path`,G).options({outdir:{alias:[`o`,`output`],type:`string`,desc:`output directory for JPEG files; if not specified, images are saved next to sources`,normalize:!0,nargs:1,coerce:I},project:q,quality:{alias:`q`,type:`number`,desc:`JPEG quality (1-100)`,default:80,nargs:1},theme:{choices:[`light`,`dark`],desc:`color-scheme to use, defaults to light`,conflicts:[`dark`,`light`],nargs:1},dark:{type:`boolean`,desc:`use dark theme, shortcut for --theme=dark`,conflicts:[`theme`,`light`]},light:{type:`boolean`,desc:`use light theme, shortcut for --theme=light`,conflicts:[`theme`,`dark`]},"use-dot":K,seq:{alias:[`sequence`],type:`boolean`,desc:`use sequence layout for dynamic views`},flat:{alias:[`flatten`],type:`boolean`,desc:`flatten all images in outdir ignoring sources structure`},filter:{alias:`f`,array:!0,string:!0,desc:`include views with ids matching given patterns
147
+ multiple patterns are combined with OR`},ignore:{boolean:!0,alias:`i`,desc:`continue if export fails for some views`},timeout:{type:`number`,alias:`t`,desc:`timeout for playwright (in seconds)`,default:15,nargs:1},"max-attempts":{type:`number`,desc:`max attempts to export failing view, 1 means no retry`,default:3,nargs:1},"server-url":{type:`string`,desc:`use this url instead of starting new likec4 server`,nargs:1},"chromium-sandbox":{boolean:!0,desc:`enable chromium sandbox (see Playwright docs)`,default:!1}}).epilog(`${C.bold(`Examples:`)}
148
+ ${C.green(`$0 export jpg`)}
149
+ ${C.gray(`Search for likec4 files in current directory and output JPEG next to sources`)}
150
+
151
+ ${C.green(`$0 export jpg --theme dark -o ./jpg src/likec4`)}
152
+ ${C.gray(`Search for likec4 files in src/likec4 and output JPEG with dark theme to jpg folder`)}
153
+
154
+ ${C.green(`$0 export jpg --quality 90 -o ./jpg src/likec4`)}
155
+ ${C.gray(`Export JPEG with 90% quality`)}
156
+
157
+ ${C.green(`$0 export jpg -f "team1*" -f "team2*" --flat -o ./jpg src/likec4`)}
158
+ ${C.gray(`Export views matching team1* or team2* only`)}
159
+ `),handler:async e=>{M(e.quality>=1&&e.quality<=100,`quality must be between 1 and 100`),M(e.timeout>=1,`timeout must be >= 1`),M(e[`max-attempts`]>=1,`max-attempts must be >= 1`),await on(),await sn();let t=e.theme??(e.dark?`dark`:`light`);await Bi({path:e.path,useDotBin:e[`use-dot`],output:e.outdir,project:e.project,timeoutMs:e.timeout*1e3,maxAttempts:e[`max-attempts`],ignore:e.ignore===!0,outputType:e.flat?`flat`:`relative`,serverUrl:e[`server-url`],theme:t,filter:e.filter,sequence:e.seq,chromiumSandbox:e[`chromium-sandbox`],format:`jpeg`,quality:e.quality}),J()}})}const Hi=`project not found`,Ui=`No projects found`;async function Wi(e,t){try{var n=Y();let r=U(t),i=n.a(await v(e.path,{graphviz:e.useDot?`binary`:`wasm`,watch:!1})),o=[...i.projectsManager.all];if(e.project){if(o=o.filter(t=>t===e.project),!a(o,1))throw t.error(`${Hi}: ${e.project}`),Error(`${Hi}: ${e.project}`)}else{if(!a(o,1))throw t.error(Ui),Error(Ui);t.info(`${C.dim(`workspace:`)} Found ${o.length} projects`)}let s=[];for(let n of o){let r;if(e.skipLayout?(t.info(`Generate model for project ${C.green(n)} ${C.dim(`(skip layout)`)}`),r=await i.computedModel(n)):(t.info(`Generating layouted model for project ${C.green(n)}`),r=await i.layoutedModel(n)),r===Ee.EMPTY){t.warn(C.yellow(`Project ${n} is empty, skipping`));continue}s.push(r.$data)}if(s.length===0)throw t.warn(`No models generated, aborting export`),Error(`No models generated; all projects are empty or were skipped`);let c=e.outfile;tt(c).toLowerCase()!==`.json`&&(c+=`.json`),await R(N(c),{recursive:!0});let l=s.length===1?s[0]:s,u=e.pretty?JSON.stringify(l,void 0,2):JSON.stringify(l);await z(c,u);let d=c.startsWith(e.path)?F(e.path,c):c;t.info(`${C.dim(`generated`)} ${d}`),r.stopAndLog(`✓ export in `)}catch(e){n.e=e}finally{await n.d()}}function Gi(e){return e.command({command:`json [path]`,describe:`export model(s) to JSON`,builder:e=>e.positional(`path`,G).option(`outfile`,{alias:`o`,type:`string`,desc:`<file> output .json file`,default:`likec4.json`,normalize:!0,coerce:I}).options({project:q,"use-dot":K,"skip-layout":{type:`boolean`,desc:`skip layouting (only compute model)`},pretty:{type:`boolean`,desc:`indented JSON output`}}).epilog(`${C.bold(`Examples:`)}
160
+ ${C.green(`$0 export json --skip-layout`)}
161
+ ${C.gray(`Search for likec4 files in current directory and output JSON to likec4.json (no layout)`)}
162
+
163
+ ${C.green(`$0 export json --pretty -o ./generated/likec4.json src/likec4 `)}
164
+ ${C.gray(`Search for likec4 files in src/likec4 and output JSON to generated/likec4.json`)}
165
+ `),handler:async e=>{let t=H(`c4:export`);await Wi({path:e.path,outfile:e.outfile,project:e.project,skipLayout:!!e.skipLayout,pretty:!!e.pretty,useDot:!!e[`use-dot`]},t),J()}})}const Ki=e=>e.command({command:`export <format> [path]`,describe:`Export to images, JSON, or DrawIO`,builder:e=>o(e.usage(`${C.bold(`Usage:`)} $0 export <format> [path]`),zi,Vi,Gi,ki).updateStrings({"Commands:":C.bold(`Formats:`)}),handler:()=>void 0}),qi=e=>e.command({command:`format [path]`,aliases:[`fmt`],describe:`Format LikeC4 source files`,builder:e=>e.positional(`path`,G).options({project:{alias:`p`,type:`string`,array:!0,desc:`select project(s) to format (repeatable)`},files:{type:`string`,array:!0,normalize:!0,coerce:e=>e.map(e=>I(e)),desc:`specific file(s) to format (repeatable)`},check:{type:`boolean`,desc:`Check if files are formatted (exit with 1 if not)`,default:!1}}),handler:async e=>{try{var t=Y();let n=H(`c4:format`),r=U(n),i=e.check,a;try{a=await v(e.path,{watch:!1})}catch(e){n.error(e instanceof Error?e.message:String(e)),process.exitCode=1;return}t.a(a);let o=e.project?.filter(Boolean),s=e.files?.filter(Boolean).map(e=>Pt(e).toString());if(n.debug(`workspace: ${e.path}`),o?.length){n.debug(`projects:`);for(let e of o)n.debug(` ${e}`)}if(s?.length){n.debug(`files:`);for(let e of s)n.debug(` ${Nt(e)}`)}let c;try{c=await a.format({...o?.length&&{projects:o},...s?.length&&{documentUris:s}})}catch(e){n.error(e instanceof Error?e.message:String(e)),process.exitCode=1;return}n.debug(`${c.size} document(s) to process`);let l=process.cwd(),u=e=>{let t=F(l,e);return t.startsWith(`..`)?e:t};if(s){let e=s.filter(e=>!c.has(e));for(let t of e)n.warn(`${C.yellow(`skipped`)} ${u(Nt(t))} (not found in workspace)`)}let d=0,f=0,p=[];for(let[e,t]of c){let r=Nt(e),a=u(r),o;try{o=await gt(r,`utf-8`)}catch(e){n.error(`Failed to read ${a}: ${e}`),f++;continue}if(o===t){n.debug(`${C.dim(`unchanged`)} ${a}`);continue}if(d++,p.push(a),i)n.info(`${C.yellow(`needs formatting`)} ${a}`);else try{await z(r,t,`utf-8`),n.info(`${C.green(`formatted`)} ${a}`)}catch(e){n.error(`Failed to write ${a}: ${e}`),f++}}if(f>0){n.error(`${f} file(s) failed to process`),process.exitCode=1;return}if(i){if(d>0){n.error(`${d} of ${c.size} file(s) need formatting:\n${p.map(e=>` ${e}`).join(`
166
+ `)}`),process.exitCode=1;return}n.info(C.green(`All ${c.size} file(s) are formatted`))}else d>0?n.info(`${C.green(String(d))} of ${c.size} file(s) formatted`):n.info(C.green(`All ${c.size} file(s) already formatted`));r.stopAndLog(`✓ format in `)}catch(e){t.e=e}finally{await t.d()}}}),Ji=e=>e.command({command:`list-icons`,describe:`List available built-in icons`,builder:e=>e.option(`format`,{alias:`f`,choices:[`text`,`json`],default:`text`,description:`Output format`}).option(`group`,{alias:`g`,choices:g,description:`Filter icons by group`}),handler:e=>{let t=e.group?[e.group]:g;switch(!0){case e.format===`json`:{let e=Object.fromEntries(t.map(e=>[e,f[e]]));console.log(JSON.stringify(e,null,2));break}default:for(let e of t)for(let t of f[e])console.log(`${e}:${t}`)}}});var Yi=Ue();function Xi(e){return e.command({command:`lsp`,aliases:[],describe:`Start LSP server`,builder:e=>e.usage(`${C.bold(`Usage:`)} $0 lsp`).option(`log-level`,vn).option(`verbose`,yn).options({"node-ipc":{boolean:!0,description:`use node-ipc transport`,conflicts:[`stdio`,`socket`,`pipe`]},stdio:{boolean:!0,description:`use stdio transport`,conflicts:[`node-ipc`,`socket`,`pipe`]},socket:{number:!0,description:`use socket transport on specified port`,conflicts:[`node-ipc`,`stdio`,`pipe`],nargs:1},pipe:{string:!0,description:`use pipe transport with specified pipe name`,conflicts:[`node-ipc`,`stdio`,`socket`],nargs:1},"manual-layouts":{boolean:!0,description:`enable/disable manual layouts`,default:!0,defaultDescription:`enabled`},watch:{alias:`w`,boolean:!0,description:`enable built-in watcher`,default:!1,defaultDescription:`disabled`},telemetry:{boolean:!0,default:!0,defaultDescription:`IDE setting`,description:`enable/disable telemetry`,hidden:!0}}).option(`use-dot`,K).showHidden().epilog(`${C.bold(`Examples:`)}
167
+
168
+ ${C.green(`$0 lsp --stdio `)}
169
+ ${C.gray(`Start LSP with stdio transport`)}
170
+
171
+ ${C.green(`$0 lsp --node-ipc --watch --no-manual-layouts --no-color `)}
172
+ ${C.gray(`Start LSP with node-ipc transport and watcher, disabled manual layouts and disabled color`)}
173
+
174
+ `),handler:e=>{let t;if(e.nodeIpc||e.stdio||e.socket||e.pipe)t=(0,Yi.createConnection)(Yi.ProposedFeatures.all);else throw Error(`No transport specified`);y({lspConnection:t,useStdErr:e.stdio===!0,colors:C.isColorSupported,enableTelemetry:e.telemetry,logLevel:e.verbose?bn:e.logLevel}),b({connection:t,enableManualLayouts:e.manualLayouts,enableWatcher:e.watch,graphviz:e.useDot?`binary`:`wasm`,configureLogger:!1})}})}const X=p.getChild(`mcp`);function Z(e,t){let{name:n,description:r,...i}=e;return e=>[n,{description:r?.trim()??``,...i},Zi(n,e,t)]}function Zi(e,t,n){let r=n.bind(null,t);return(async function t(n,i){X.debug(`Calling tool {name}, args: {args}`,{name:e,args:n});try{let e=await r.call(null,n,i);return typeof e==`string`?{content:[{type:`text`,text:e}]}:{content:[{type:`text`,text:JSON.stringify(e)}],structuredContent:e}}catch(t){return X.error(`Tool ${e} failed`,{err:t}),{content:[{type:`text`,text:h(t)}],isError:!0}}})}var Qi=`1.55.1`;const $i=T({name:j().describe(`Project identifier`),title:j().optional().describe(`Human-readable project title`),contactPerson:j().optional().describe(`Maintainer contact information`),metadata:D(j(),Fe()).optional().describe(`Custom project metadata as key-value pairs`),extends:E([j(),O(j())]).optional().describe(`Style inheritance paths`),exclude:O(j()).optional().describe(`File exclusion patterns`),include:T({paths:O(j()).describe(`Include paths`),maxDepth:A().describe(`Maximum directory depth`),fileThreshold:A().describe(`File threshold`)}).optional().describe(`Include configuration`),manualLayouts:T({outDir:j().describe(`Output directory for manual layouts`)}).optional().describe(`Manual layouts configuration`),styles:T({hasTheme:k().describe(`Whether theme customization is defined`),hasDefaults:k().describe(`Whether default style values are defined`),hasCustomCss:k().describe(`Whether custom CSS is defined`)}).optional().describe(`Simplified styles configuration (boolean flags)`)});function ea(e){let t={name:e.name};return e.title!=null&&(t.title=e.title),e.contactPerson!=null&&(t.contactPerson=e.contactPerson),e.metadata&&(t.metadata=e.metadata),e.extends&&(t.extends=e.extends),e.exclude&&(t.exclude=e.exclude),e.include&&(t.include={paths:e.include.paths||[],maxDepth:e.include.maxDepth??3,fileThreshold:e.include.fileThreshold??30}),e.manualLayouts&&(t.manualLayouts={outDir:e.manualLayouts.outDir??`.likec4`}),e.styles&&(t.styles={hasTheme:!!e.styles.theme,hasDefaults:!!e.styles.defaults,hasCustomCss:!!e.styles.customCss}),t}const ta=T({id:j().describe(`Element id (FQN)`),name:j().describe(`Element name`),kind:j().describe(`Element kind`),title:j(),tags:O(j()),metadata:D(E([j(),O(j())])),includedInViews:O(T({id:j().describe(`View id`),title:j().describe(`View title`),type:w([`element`,`deployment`,`dynamic`]).describe(`View type`)})).describe(`Views that include this element`)});function Q(e){return{id:e.id,name:e.name,kind:e.kind,title:e.title,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:aa(e.views())}}function na(e,t,n,r,i,a){M(e.findElement(t),`Element "${t}" not found`);let o=new Set,s={},c=0,l=!1,u=[{elementId:t,depth:0}];for(;u.length>0;){let{elementId:t,depth:d}=u.shift();if(d>i||o.has(t))continue;if(o.size>=a){l=!0;break}let f=e.findElement(t);if(!f)continue;o.add(t),c=Math.max(c,d);let p=(n===`incoming`?[...f.incoming(r)]:[...f.outgoing(r)]).map(e=>{let t={elementId:n===`incoming`?e.source.id:e.target.id};return e.title&&(t.relationshipLabel=e.title),e.technology&&(t.technology=e.technology),t});s[t]={...Q(f),neighbors:p,depth:d};for(let e of p)o.has(e.elementId)||u.push({elementId:e.elementId,depth:d+1})}for(let e of Object.values(s))e.neighbors=e.neighbors.filter(e=>e.elementId in s);return{target:t,totalNodes:o.size,maxDepth:c,truncated:l,nodes:s}}const ra=T({path:j().describe(`Path to the file`),range:T({start:T({line:A(),character:A()}),end:T({line:A(),character:A()})}).describe(`Range in the file`)}).nullable(),$=j().refine(e=>!0).optional().default(`default`).describe(`Project id (optional, will use "default" if not specified)`),ia=O(T({id:j().describe(`View id`),title:j().describe(`View title`),type:w([`element`,`deployment`,`dynamic`]).describe(`View type`)})),aa=e=>[...e].map(e=>({id:e.id,title:e.titleOrId,type:e.$view._type})),oa=(e,t)=>n=>{try{let r=e.locate({projectId:t,...n});return r?{path:S.parse(r.uri).fsPath,range:r.range}:null}catch(e){return X.debug(`Failed to locate {params}`,{error:e,params:n}),null}},sa=ta.extend({description:j().nullable().describe(`Element description`),technology:j().nullable().describe(`Element technology`),shape:j().describe(`Rendered shape`),color:j().describe(`Rendered color`),children:O(j()).describe(`Direct child element ids`),incomingCount:A().describe(`Number of incoming relationships`),outgoingCount:A().describe(`Number of outgoing relationships`)}),ca=Z({name:`batch-read-elements`,description:`
162
175
  Read details of multiple elements in a single call, reducing round-trips.
163
176
  Returns a compact summary for each element including metadata, description, technology, shape, children, and relationship counts.
164
177
 
@@ -220,7 +233,7 @@ Example response:
220
233
  ],
221
234
  "notFound": []
222
235
  }
223
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Batch read elements`},inputSchema:{ids:D(A()).min(1).max(50).describe(`Array of element ids (FQNs) to read (max 50)`),project:$},outputSchema:{elements:D(aa),notFound:D(A()).describe(`Element ids that were not found`)}},async(e,t)=>{j(t.ids.length<=50,`Maximum 50 element ids per call`);let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=[],a=[];for(let e of t.ids){let t=r.findElement(e);if(!t){a.push(e);continue}i.push({...Q(t),description:t.description.text,technology:t.technology,shape:t.shape,color:t.color,children:[...t.children()].map(e=>e.id),incomingCount:t.allIncoming.size,outgoingCount:t.allOutgoing.size})}return{elements:i,notFound:a}}),sa=w({id:A(),kind:A(),title:A(),description:A().nullable(),technology:A().nullable(),shape:A(),color:A()}),ca=w({element1:sa,element2:sa,propertyDiffs:D(w({property:A().describe(`Property name`),element1Value:A().nullable().describe(`Value in element1`),element2Value:A().nullable().describe(`Value in element2`)})).describe(`Properties that differ between the two elements`),tags:w({onlyInElement1:D(A()).describe(`Tags present only in element1`),onlyInElement2:D(A()).describe(`Tags present only in element2`),common:D(A()).describe(`Tags present in both elements`)}),metadata:w({onlyInElement1:E(T([A(),D(A())])).describe(`Metadata keys only in element1`),onlyInElement2:E(T([A(),D(A())])).describe(`Metadata keys only in element2`),different:D(w({key:A(),element1Value:T([A(),D(A())]),element2Value:T([A(),D(A())])})).describe(`Metadata keys present in both but with different values`),common:E(T([A(),D(A())])).describe(`Metadata keys with identical values in both`)}),relationships:w({incomingOnlyElement1:k().describe(`Count of unique source elements sending to element1 only`),incomingOnlyElement2:k().describe(`Count of unique source elements sending to element2 only`),incomingShared:k().describe(`Count of unique source elements sending to both`),outgoingOnlyElement1:k().describe(`Count of unique target elements receiving from element1 only`),outgoingOnlyElement2:k().describe(`Count of unique target elements receiving from element2 only`),outgoingShared:k().describe(`Count of unique target elements receiving from both`)})}),la=Z({name:`element-diff`,description:`
236
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Batch read elements`},inputSchema:{ids:O(j()).min(1).max(50).describe(`Array of element ids (FQNs) to read (max 50)`),project:$},outputSchema:{elements:O(sa),notFound:O(j()).describe(`Element ids that were not found`)}},async(e,t)=>{M(t.ids.length<=50,`Maximum 50 element ids per call`);let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=[],a=[];for(let e of t.ids){let t=r.findElement(e);if(!t){a.push(e);continue}i.push({...Q(t),description:t.description.text,technology:t.technology,shape:t.shape,color:t.color,children:[...t.children()].map(e=>e.id),incomingCount:t.allIncoming.size,outgoingCount:t.allOutgoing.size})}return{elements:i,notFound:a}}),la=T({id:j(),kind:j(),title:j(),description:j().nullable(),technology:j().nullable(),shape:j(),color:j()}),ua=T({element1:la,element2:la,propertyDiffs:O(T({property:j().describe(`Property name`),element1Value:j().nullable().describe(`Value in element1`),element2Value:j().nullable().describe(`Value in element2`)})).describe(`Properties that differ between the two elements`),tags:T({onlyInElement1:O(j()).describe(`Tags present only in element1`),onlyInElement2:O(j()).describe(`Tags present only in element2`),common:O(j()).describe(`Tags present in both elements`)}),metadata:T({onlyInElement1:D(E([j(),O(j())])).describe(`Metadata keys only in element1`),onlyInElement2:D(E([j(),O(j())])).describe(`Metadata keys only in element2`),different:O(T({key:j(),element1Value:E([j(),O(j())]),element2Value:E([j(),O(j())])})).describe(`Metadata keys present in both but with different values`),common:D(E([j(),O(j())])).describe(`Metadata keys with identical values in both`)}),relationships:T({incomingOnlyElement1:A().describe(`Count of unique source elements sending to element1 only`),incomingOnlyElement2:A().describe(`Count of unique source elements sending to element2 only`),incomingShared:A().describe(`Count of unique source elements sending to both`),outgoingOnlyElement1:A().describe(`Count of unique target elements receiving from element1 only`),outgoingOnlyElement2:A().describe(`Count of unique target elements receiving from element2 only`),outgoingShared:A().describe(`Count of unique target elements receiving from both`)})}),da=Z({name:`element-diff`,description:`
224
237
  Compare two elements side-by-side, showing differences in properties, tags, metadata, and relationships.
225
238
 
226
239
  Request:
@@ -280,7 +293,7 @@ Example response:
280
293
  "outgoingShared": 2
281
294
  }
282
295
  }
283
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Compare two elements`},inputSchema:{element1Id:A().describe(`First element id (FQN)`),element2Id:A().describe(`Second element id (FQN)`),project:$},outputSchema:ca.shape},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=r.findElement(t.element1Id);j(i,`Element "${t.element1Id}" not found in project "${n}"`);let a=r.findElement(t.element2Id);j(a,`Element "${t.element2Id}" not found in project "${n}"`);let o=[],s=[{name:`kind`,get:e=>e.kind},{name:`title`,get:e=>e.title},{name:`description`,get:e=>e.description.text},{name:`technology`,get:e=>e.technology},{name:`shape`,get:e=>e.shape},{name:`color`,get:e=>e.color}];for(let e of s){let t=e.get(i),n=e.get(a);t!==n&&o.push({property:e.name,element1Value:t,element2Value:n})}let c=new Set(i.tags),l=new Set(a.tags),u=[],d=[],f=[];for(let e of c)l.has(e)?u.push(e):d.push(e);for(let e of l)c.has(e)||f.push(e);let p=i.getMetadata(),m=a.getMetadata(),h=new Set([...Object.keys(p),...Object.keys(m)]),g={},_={},v=[],y={};for(let e of h){let t=p[e],n=m[e];t!==void 0&&n===void 0?g[e]=t:t===void 0&&n!==void 0?_[e]=n:t!==void 0&&n!==void 0&&(JSON.stringify(t)===JSON.stringify(n)?y[e]=t:v.push({key:e,element1Value:t,element2Value:n}))}let ee=new Set([...i.incoming()].map(e=>e.source.id)),b=new Set([...a.incoming()].map(e=>e.source.id)),te=new Set([...i.outgoing()].map(e=>e.target.id)),ne=new Set([...a.outgoing()].map(e=>e.target.id)),re=0,ie=0,x=0;for(let e of ee)b.has(e)?re++:ie++;for(let e of b)ee.has(e)||x++;let ae=0,oe=0,se=0;for(let e of te)ne.has(e)?ae++:oe++;for(let e of ne)te.has(e)||se++;return{element1:{id:i.id,kind:i.kind,title:i.title,description:i.description.text,technology:i.technology,shape:i.shape,color:i.color},element2:{id:a.id,kind:a.kind,title:a.title,description:a.description.text,technology:a.technology,shape:a.shape,color:a.color},propertyDiffs:o,tags:{onlyInElement1:d,onlyInElement2:f,common:u},metadata:{onlyInElement1:g,onlyInElement2:_,different:v,common:y},relationships:{incomingOnlyElement1:ie,incomingOnlyElement2:x,incomingShared:re,outgoingOnlyElement1:oe,outgoingOnlyElement2:se,outgoingShared:ae}}}),ua=Z({name:`find-relationship-paths`,description:`
296
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Compare two elements`},inputSchema:{element1Id:j().describe(`First element id (FQN)`),element2Id:j().describe(`Second element id (FQN)`),project:$},outputSchema:ua.shape},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=r.findElement(t.element1Id);M(i,`Element "${t.element1Id}" not found in project "${n}"`);let a=r.findElement(t.element2Id);M(a,`Element "${t.element2Id}" not found in project "${n}"`);let o=[],s=[{name:`kind`,get:e=>e.kind},{name:`title`,get:e=>e.title},{name:`description`,get:e=>e.description.text},{name:`technology`,get:e=>e.technology},{name:`shape`,get:e=>e.shape},{name:`color`,get:e=>e.color}];for(let e of s){let t=e.get(i),n=e.get(a);t!==n&&o.push({property:e.name,element1Value:t,element2Value:n})}let c=new Set(i.tags),l=new Set(a.tags),u=[],d=[],f=[];for(let e of c)l.has(e)?u.push(e):d.push(e);for(let e of l)c.has(e)||f.push(e);let p=i.getMetadata(),m=a.getMetadata(),h=new Set([...Object.keys(p),...Object.keys(m)]),g={},_={},v=[],y={};for(let e of h){let t=p[e],n=m[e];t!==void 0&&n===void 0?g[e]=t:t===void 0&&n!==void 0?_[e]=n:t!==void 0&&n!==void 0&&(JSON.stringify(t)===JSON.stringify(n)?y[e]=t:v.push({key:e,element1Value:t,element2Value:n}))}let b=new Set([...i.incoming()].map(e=>e.source.id)),ee=new Set([...a.incoming()].map(e=>e.source.id)),te=new Set([...i.outgoing()].map(e=>e.target.id)),x=new Set([...a.outgoing()].map(e=>e.target.id)),S=0,ne=0,C=0;for(let e of b)ee.has(e)?S++:ne++;for(let e of ee)b.has(e)||C++;let re=0,ie=0,ae=0;for(let e of te)x.has(e)?re++:ie++;for(let e of x)te.has(e)||ae++;return{element1:{id:i.id,kind:i.kind,title:i.title,description:i.description.text,technology:i.technology,shape:i.shape,color:i.color},element2:{id:a.id,kind:a.kind,title:a.title,description:a.description.text,technology:a.technology,shape:a.shape,color:a.color},propertyDiffs:o,tags:{onlyInElement1:d,onlyInElement2:f,common:u},metadata:{onlyInElement1:g,onlyInElement2:_,different:v,common:y},relationships:{incomingOnlyElement1:ne,incomingOnlyElement2:C,incomingShared:S,outgoingOnlyElement1:ie,outgoingOnlyElement2:ae,outgoingShared:re}}}),fa=Z({name:`find-relationship-paths`,description:`
284
297
  Discover all paths (chains of relationships) between two elements, supporting multi-hop traversal.
285
298
 
286
299
  Request:
@@ -369,7 +382,7 @@ Example response:
369
382
  }
370
383
  ]
371
384
  }
372
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Find relationship paths`},inputSchema:{sourceId:A().describe(`Source element FQN`),targetId:A().describe(`Target element FQN`),maxDepth:k().int().min(1).max(5).optional().default(3).describe(`Maximum path length (default: 3, max: 5)`),includeIndirect:O().optional().default(!1).describe(`Include indirect (implied) relationships through nested elements (default: false)`),project:$},outputSchema:{paths:D(w({length:k().describe(`Number of hops in the path`),steps:D(w({source:A().describe(`Source element FQN`),target:A().describe(`Target element FQN`),relationship:w({kind:A().nullable().describe(`Relationship kind`),title:A().nullable().describe(`Relationship title`),description:A().nullable().describe(`Relationship description`),technology:A().nullable().describe(`Relationship technology`),tags:D(A()).describe(`Relationship tags`)})})).describe(`Ordered sequence of relationships in the path`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=r.findElement(t.sourceId);j(i,`Source element "${t.sourceId}" not found in project "${n}"`);let a=r.findElement(t.targetId);j(a,`Target element "${t.targetId}" not found in project "${n}"`),j(i.id!==a.id,`Source and target must be different elements`);let o=t.maxDepth,s=t.includeIndirect?`all`:`direct`,c=[{elementId:i.id,path:[],visited:new Set([i.id])}],l=[];for(;c.length>0&&l.length<100;){let e=c.shift();if(e.path.length>=o)continue;let t=r.findElement(e.elementId);if(t)for(let n of t.outgoing(s)){let t=n.target.id;if(t===a.id){let t={source:n.source.id,target:n.target.id,relationship:{kind:n.kind,title:n.title,description:n.description.text,technology:n.technology,tags:[...n.tags]}};if(l.push({length:e.path.length+1,steps:[...e.path,t]}),l.length>=100)break;continue}if(e.visited.has(t))continue;let r={source:n.source.id,target:n.target.id,relationship:{kind:n.kind,title:n.title,description:n.description.text,technology:n.technology,tags:[...n.tags]}};c.push({elementId:t,path:[...e.path,r],visited:new Set([...e.visited,t])})}}return l.sort((e,t)=>e.length-t.length),{paths:l}}),da=w({id:A(),title:A(),kind:A()}),fa=w({type:C([`direct`,`indirect`]).describe(`Type of relationship, "direct" for direct relationships, "indirect" for relationships through nested elements`),source:da,target:da,kind:A().nullable().describe(`Relationship kind`),title:A().nullable().describe(`Relationship title`),description:A().nullable().describe(`Relationship description`),technology:A().nullable().describe(`Relationship technology`),tags:D(A()).describe(`Relationship tags`),includedInViews:na.describe(`Views that include this relationship`),sourceLocation:ta}),pa=Z({name:`find-relationships`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Find relationships between two elements`},description:`
385
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Find relationship paths`},inputSchema:{sourceId:j().describe(`Source element FQN`),targetId:j().describe(`Target element FQN`),maxDepth:A().int().min(1).max(5).optional().default(3).describe(`Maximum path length (default: 3, max: 5)`),includeIndirect:k().optional().default(!1).describe(`Include indirect (implied) relationships through nested elements (default: false)`),project:$},outputSchema:{paths:O(T({length:A().describe(`Number of hops in the path`),steps:O(T({source:j().describe(`Source element FQN`),target:j().describe(`Target element FQN`),relationship:T({kind:j().nullable().describe(`Relationship kind`),title:j().nullable().describe(`Relationship title`),description:j().nullable().describe(`Relationship description`),technology:j().nullable().describe(`Relationship technology`),tags:O(j()).describe(`Relationship tags`)})})).describe(`Ordered sequence of relationships in the path`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=r.findElement(t.sourceId);M(i,`Source element "${t.sourceId}" not found in project "${n}"`);let a=r.findElement(t.targetId);M(a,`Target element "${t.targetId}" not found in project "${n}"`),M(i.id!==a.id,`Source and target must be different elements`);let o=t.maxDepth,s=t.includeIndirect?`all`:`direct`,c=[{elementId:i.id,path:[],visited:new Set([i.id])}],l=[];for(;c.length>0&&l.length<100;){let e=c.shift();if(e.path.length>=o)continue;let t=r.findElement(e.elementId);if(t)for(let n of t.outgoing(s)){let t=n.target.id;if(t===a.id){let t={source:n.source.id,target:n.target.id,relationship:{kind:n.kind,title:n.title,description:n.description.text,technology:n.technology,tags:[...n.tags]}};if(l.push({length:e.path.length+1,steps:[...e.path,t]}),l.length>=100)break;continue}if(e.visited.has(t))continue;let r={source:n.source.id,target:n.target.id,relationship:{kind:n.kind,title:n.title,description:n.description.text,technology:n.technology,tags:[...n.tags]}};c.push({elementId:t,path:[...e.path,r],visited:new Set([...e.visited,t])})}}return l.sort((e,t)=>e.length-t.length),{paths:l}}),pa=T({id:j(),title:j(),kind:j()}),ma=T({type:w([`direct`,`indirect`]).describe(`Type of relationship, "direct" for direct relationships, "indirect" for relationships through nested elements`),source:pa,target:pa,kind:j().nullable().describe(`Relationship kind`),title:j().nullable().describe(`Relationship title`),description:j().nullable().describe(`Relationship description`),technology:j().nullable().describe(`Relationship technology`),tags:O(j()).describe(`Relationship tags`),includedInViews:ia.describe(`Views that include this relationship`),sourceLocation:ra}),ha=Z({name:`find-relationships`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Find relationships between two elements`},description:`
373
386
  Find relationships between two LikeC4 elements within a project.
374
387
 
375
388
  What it does:
@@ -440,7 +453,7 @@ Response:
440
453
  }
441
454
  ]
442
455
  }
443
- `,inputSchema:{element1:A().describe(`Element ID (FQN)`),element2:A().describe(`Element ID (FQN)`),project:$},outputSchema:{found:D(fa)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project);if(st(t.element1,t.element2))throw Error(`No relationships possible between parent-child`);let r=[],i=await e.computedModel(n),a=i.findElement(t.element1);ot(a,`Element "${t.element1}" not found in project "${n}"`);let o=i.findElement(t.element2);ot(o,`Element "${t.element2}" not found in project "${n}"`);let s=ia(e,n),c=$e.findConnection(a,o,`both`).flatMap(e=>[...e.relations]);for(let e of c){let t=e.source===a&&e.target===o||e.source===o&&e.target===a;r.push({type:t?`direct`:`indirect`,source:{id:e.source.id,title:e.source.title,kind:e.source.kind},target:{id:e.target.id,title:e.target.title,kind:e.target.kind},kind:e.kind,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags],includedInViews:ra(e.views()),sourceLocation:s({relation:e.id})})}return{found:r}}),ma=Z({name:`list-projects`,description:`
456
+ `,inputSchema:{element1:j().describe(`Element ID (FQN)`),element2:j().describe(`Element ID (FQN)`),project:$},outputSchema:{found:O(ma)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project);if(ot(t.element1,t.element2))throw Error(`No relationships possible between parent-child`);let r=[],i=await e.computedModel(n),a=i.findElement(t.element1);at(a,`Element "${t.element1}" not found in project "${n}"`);let o=i.findElement(t.element2);at(o,`Element "${t.element2}" not found in project "${n}"`);let s=oa(e,n),c=Qe.findConnection(a,o,`both`).flatMap(e=>[...e.relations]);for(let e of c){let t=e.source===a&&e.target===o||e.source===o&&e.target===a;r.push({type:t?`direct`:`indirect`,source:{id:e.source.id,title:e.source.title,kind:e.source.kind},target:{id:e.target.id,title:e.target.title,kind:e.target.kind},kind:e.kind,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags],includedInViews:aa(e.views()),sourceLocation:s({relation:e.id})})}return{found:r}}),ga=Z({name:`list-projects`,description:`
444
457
  List LikeC4 projects discoverable in the current workspace.
445
458
 
446
459
  Request:
@@ -473,7 +486,7 @@ Example response:
473
486
  }
474
487
  ]
475
488
  }
476
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`List projects`},outputSchema:{projects:D(w({id:A(),title:A(),folder:A(),sources:D(A())}))}},async e=>({projects:e.projects().map(e=>({id:e.id,title:e.title,folder:e.folder.fsPath,sources:e.documents.map(e=>e.fsPath)}))})),ha=C([`exact`,`contains`,`exists`]),ga=Z({name:`query-by-metadata`,description:`
489
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`List projects`},outputSchema:{projects:O(T({id:j(),title:j(),folder:j(),sources:O(j())}))}},async e=>({projects:e.projects().map(e=>({id:e.id,title:e.title,folder:e.folder.fsPath,sources:e.documents.map(e=>e.fsPath)}))})),_a=w([`exact`,`contains`,`exists`]),va=Z({name:`query-by-metadata`,description:`
477
490
  Search elements and deployment nodes by metadata key-value pairs with flexible matching modes.
478
491
 
479
492
  Request:
@@ -539,7 +552,7 @@ Example response:
539
552
  }
540
553
  ]
541
554
  }
542
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query by metadata`},inputSchema:{key:A().describe(`Metadata key to filter by`),value:A().optional().describe(`Metadata value to match (ignored for exists mode)`),matchMode:ha.optional().default(`exact`).describe(`Matching mode`),project:$},outputSchema:{results:D($i.extend({matchedValue:A().describe(`The metadata value that matched`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=t.matchMode,a=[],o=(e,t,n)=>{let r=Array.isArray(e)?e:[e];switch(n){case`exists`:return!0;case`exact`:return t===void 0?!1:r.some(e=>e===t);case`contains`:{if(t===void 0)return!1;let e=t.toLowerCase();return r.some(t=>t.toLowerCase().includes(e))}default:return!1}},s=(e,t,n)=>{let r=Array.isArray(e)?e:[e];if(n===`exists`||t===void 0)return r[0]||``;if(n===`exact`)return r.find(e=>e===t)||r[0]||``;if(n===`contains`){let e=t.toLowerCase();return r.find(t=>t.toLowerCase().includes(e))||r[0]||``}return r[0]||``};for(let e of r.elements()){if(a.length>=50)break;let n=e.getMetadata();if(t.key in n){let r=n[t.key];r!==void 0&&o(r,t.value,i)&&a.push({...Q(e),matchedValue:s(r,t.value,i)})}}if(a.length<50)for(let e of r.deployment.elements()){if(a.length>=50)break;let n=e.getMetadata();if(t.key in n){let r=n[t.key];r!==void 0&&o(r,t.value,i)&&a.push({...Q(e),matchedValue:s(r,t.value,i)})}}return{results:a}}),_a=Z({name:`query-by-tag-pattern`,description:`
555
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query by metadata`},inputSchema:{key:j().describe(`Metadata key to filter by`),value:j().optional().describe(`Metadata value to match (ignored for exists mode)`),matchMode:_a.optional().default(`exact`).describe(`Matching mode`),project:$},outputSchema:{results:O(ta.extend({matchedValue:j().describe(`The metadata value that matched`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=t.matchMode,a=[],o=(e,t,n)=>{let r=Array.isArray(e)?e:[e];switch(n){case`exists`:return!0;case`exact`:return t===void 0?!1:r.some(e=>e===t);case`contains`:{if(t===void 0)return!1;let e=t.toLowerCase();return r.some(t=>t.toLowerCase().includes(e))}default:return!1}},s=(e,t,n)=>{let r=Array.isArray(e)?e:[e];if(n===`exists`||t===void 0)return r[0]||``;if(n===`exact`)return r.find(e=>e===t)||r[0]||``;if(n===`contains`){let e=t.toLowerCase();return r.find(t=>t.toLowerCase().includes(e))||r[0]||``}return r[0]||``};for(let e of r.elements()){if(a.length>=50)break;let n=e.getMetadata();if(t.key in n){let r=n[t.key];r!==void 0&&o(r,t.value,i)&&a.push({...Q(e),matchedValue:s(r,t.value,i)})}}if(a.length<50)for(let e of r.deployment.elements()){if(a.length>=50)break;let n=e.getMetadata();if(t.key in n){let r=n[t.key];r!==void 0&&o(r,t.value,i)&&a.push({...Q(e),matchedValue:s(r,t.value,i)})}}return{results:a}}),ya=Z({name:`query-by-tag-pattern`,description:`
543
556
  Search elements by tag patterns using prefix or substring matching.
544
557
  Useful for tag taxonomies with structured naming conventions (e.g., "schedule_*", "*_asil_*").
545
558
 
@@ -594,7 +607,7 @@ Example response:
594
607
  "truncated": false,
595
608
  "matchedTagValues": ["target_asil_qm", "target_asil_asil_b", "target_asil_qm__tbc"]
596
609
  }
597
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query by tag pattern`},inputSchema:{pattern:A().min(1).describe(`Tag pattern to match`),matchMode:C([`prefix`,`contains`,`suffix`]).optional().default(`prefix`).describe(`Pattern matching mode (default: prefix)`),project:$},outputSchema:{results:D($i.extend({matchedTags:D(A()).describe(`Tags that matched the pattern`)})),truncated:O().describe(`True if results were truncated`),matchedTagValues:D(A()).describe(`All unique tag values matching the pattern across all elements`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=t.pattern.toLowerCase(),a=e=>{let n=e.toLowerCase();switch(t.matchMode){case`prefix`:return n.startsWith(i);case`contains`:return n.includes(i);case`suffix`:return n.endsWith(i)}},o=[],s=!1,c=new Set;for(let e of r.elements()){let t=[...e.tags].filter(a);if(t.length>0){if(t.forEach(e=>c.add(e)),o.length>=50){s=!0;continue}o.push({...Q(e),matchedTags:t})}}for(let e of r.deployment.elements()){if(!Je(e))continue;let t=[...e.tags].filter(a);if(t.length>0){if(t.forEach(e=>c.add(e)),o.length>=50){s=!0;continue}o.push({...Q(e),matchedTags:t})}}return{results:o,truncated:s,matchedTagValues:[...c].sort((e,t)=>e.localeCompare(t))}}),va=Z({name:`query-by-tags`,description:`
610
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query by tag pattern`},inputSchema:{pattern:j().min(1).describe(`Tag pattern to match`),matchMode:w([`prefix`,`contains`,`suffix`]).optional().default(`prefix`).describe(`Pattern matching mode (default: prefix)`),project:$},outputSchema:{results:O(ta.extend({matchedTags:O(j()).describe(`Tags that matched the pattern`)})),truncated:k().describe(`True if results were truncated`),matchedTagValues:O(j()).describe(`All unique tag values matching the pattern across all elements`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=t.pattern.toLowerCase(),a=e=>{let n=e.toLowerCase();switch(t.matchMode){case`prefix`:return n.startsWith(i);case`contains`:return n.includes(i);case`suffix`:return n.endsWith(i)}},o=[],s=!1,c=new Set;for(let e of r.elements()){let t=[...e.tags].filter(a);if(t.length>0){if(t.forEach(e=>c.add(e)),o.length>=50){s=!0;continue}o.push({...Q(e),matchedTags:t})}}for(let e of r.deployment.elements()){if(!qe(e))continue;let t=[...e.tags].filter(a);if(t.length>0){if(t.forEach(e=>c.add(e)),o.length>=50){s=!0;continue}o.push({...Q(e),matchedTags:t})}}return{results:o,truncated:s,matchedTagValues:[...c].sort((e,t)=>e.localeCompare(t))}}),ba=Z({name:`query-by-tags`,description:`
598
611
  Advanced tag filtering with boolean logic (AND, OR, NOT).
599
612
 
600
613
  Request:
@@ -658,7 +671,7 @@ Example response:
658
671
  }
659
672
  ]
660
673
  }
661
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query by tags`},inputSchema:{allOf:D(A()).optional().describe(`Element must have ALL these tags (AND)`),anyOf:D(A()).optional().describe(`Element must have ANY of these tags (OR)`),noneOf:D(A()).optional().describe(`Element must have NONE of these tags (NOT)`),project:$},outputSchema:{results:D($i),truncated:O().describe(`True if results were truncated due to exceeding the 50-result limit`)}},async(e,t)=>{j(t.allOf&&t.allOf.length>0||t.anyOf&&t.anyOf.length>0||t.noneOf&&t.noneOf.length>0,`At least one condition (allOf, anyOf, or noneOf) must be specified with at least one tag`);let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=[],a=!1,o=e=>{let n=e instanceof Set?e:new Set(e);return!(t.allOf&&t.allOf.length>0&&!t.allOf.every(e=>n.has(e))||t.anyOf&&t.anyOf.length>0&&!t.anyOf.some(e=>n.has(e))||t.noneOf&&t.noneOf.length>0&&t.noneOf.some(e=>n.has(e)))};for(let e of r.elements()){if(i.length>=50){a=!0;break}o(e.tags)&&i.push(Q(e))}if(!a)for(let e of r.deployment.elements()){if(i.length>=50){a=!0;break}Je(e)&&o(e.tags)&&i.push(Q(e))}return{results:i,truncated:a}}),ya=C([`ancestors`,`descendants`,`siblings`,`children`,`parent`,`incomers`,`outgoers`]),ba=Z({name:`query-graph`,description:`
674
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query by tags`},inputSchema:{allOf:O(j()).optional().describe(`Element must have ALL these tags (AND)`),anyOf:O(j()).optional().describe(`Element must have ANY of these tags (OR)`),noneOf:O(j()).optional().describe(`Element must have NONE of these tags (NOT)`),project:$},outputSchema:{results:O(ta),truncated:k().describe(`True if results were truncated due to exceeding the 50-result limit`)}},async(e,t)=>{M(t.allOf&&t.allOf.length>0||t.anyOf&&t.anyOf.length>0||t.noneOf&&t.noneOf.length>0,`At least one condition (allOf, anyOf, or noneOf) must be specified with at least one tag`);let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=[],a=!1,o=e=>{let n=e instanceof Set?e:new Set(e);return!(t.allOf&&t.allOf.length>0&&!t.allOf.every(e=>n.has(e))||t.anyOf&&t.anyOf.length>0&&!t.anyOf.some(e=>n.has(e))||t.noneOf&&t.noneOf.length>0&&t.noneOf.some(e=>n.has(e)))};for(let e of r.elements()){if(i.length>=50){a=!0;break}o(e.tags)&&i.push(Q(e))}if(!a)for(let e of r.deployment.elements()){if(i.length>=50){a=!0;break}qe(e)&&o(e.tags)&&i.push(Q(e))}return{results:i,truncated:a}}),xa=w([`ancestors`,`descendants`,`siblings`,`children`,`parent`,`incomers`,`outgoers`]),Sa=Z({name:`query-graph`,description:`
662
675
  Query element hierarchy and relationships in the architecture graph.
663
676
 
664
677
  Request:
@@ -730,7 +743,7 @@ Example response:
730
743
  ],
731
744
  "truncated": false
732
745
  }
733
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query element graph`},inputSchema:{elementId:A().describe(`Element id (FQN) to query`),queryType:ya.describe(`Type of graph query`),includeIndirect:O().optional().default(!0).describe(`For incomers/outgoers: include indirect relationships (default: true)`),project:$},outputSchema:{results:D($i),truncated:O().describe(`True if results were truncated due to exceeding maximum limit`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.elementId);j(r,`Element "${t.elementId}" not found in project "${n}"`);let i=[],a=!1;switch(t.queryType){case`ancestors`:for(let e of r.ancestors()){if(i.length>=100){a=!0;break}i.push(Q(e))}break;case`descendants`:for(let e of r.descendants()){if(i.length>=100){a=!0;break}i.push(Q(e))}break;case`siblings`:for(let e of r.siblings()){if(i.length>=100){a=!0;break}i.push(Q(e))}break;case`children`:for(let e of r.children()){if(i.length>=100){a=!0;break}i.push(Q(e))}break;case`parent`:{let e=r.parent;e&&i.push(Q(e));break}case`incomers`:{let e=t.includeIndirect?`all`:`direct`;for(let t of r.incomers(e)){if(i.length>=100){a=!0;break}i.push(Q(t))}break}case`outgoers`:{let e=t.includeIndirect?`all`:`direct`;for(let t of r.outgoers(e)){if(i.length>=100){a=!0;break}i.push(Q(t))}break}}return{results:i,truncated:a}}),xa=w({elementId:A().describe(`ID of the incoming element`),relationshipLabel:A().optional().describe(`Label on the relationship`),technology:A().optional().describe(`Technology specified on the relationship`)}),Sa=Z({name:`query-incomers-graph`,description:`
746
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query element graph`},inputSchema:{elementId:j().describe(`Element id (FQN) to query`),queryType:xa.describe(`Type of graph query`),includeIndirect:k().optional().default(!0).describe(`For incomers/outgoers: include indirect relationships (default: true)`),project:$},outputSchema:{results:O(ta),truncated:k().describe(`True if results were truncated due to exceeding maximum limit`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.elementId);M(r,`Element "${t.elementId}" not found in project "${n}"`);let i=[],a=!1;switch(t.queryType){case`ancestors`:for(let e of r.ancestors()){if(i.length>=100){a=!0;break}i.push(Q(e))}break;case`descendants`:for(let e of r.descendants()){if(i.length>=100){a=!0;break}i.push(Q(e))}break;case`siblings`:for(let e of r.siblings()){if(i.length>=100){a=!0;break}i.push(Q(e))}break;case`children`:for(let e of r.children()){if(i.length>=100){a=!0;break}i.push(Q(e))}break;case`parent`:{let e=r.parent;e&&i.push(Q(e));break}case`incomers`:{let e=t.includeIndirect?`all`:`direct`;for(let t of r.incomers(e)){if(i.length>=100){a=!0;break}i.push(Q(t))}break}case`outgoers`:{let e=t.includeIndirect?`all`:`direct`;for(let t of r.outgoers(e)){if(i.length>=100){a=!0;break}i.push(Q(t))}break}}return{results:i,truncated:a}}),Ca=T({elementId:j().describe(`ID of the incoming element`),relationshipLabel:j().optional().describe(`Label on the relationship`),technology:j().optional().describe(`Technology specified on the relationship`)}),wa=Z({name:`query-incomers-graph`,description:`
734
747
  Query the complete graph of all elements that provide input to the target element (recursive incomers/producers).
735
748
 
736
749
  This tool performs a breadth-first traversal to discover all upstream dependencies - elements that directly or
@@ -787,7 +800,7 @@ Notes:
787
800
  Example:
788
801
  For a database element, this returns all services, APIs, and components that write to it,
789
802
  plus all their dependencies, recursively up to maxDepth levels.
790
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query complete incomers graph`},inputSchema:{elementId:A().describe(`Target element id (FQN) to query incomers for`),includeIndirect:O().optional().default(!0).describe(`Include indirect relationships through nested elements (default: true)`),maxDepth:k().int().positive().max(50).optional().default(10).describe(`Maximum traversal depth (default: 10, max: 50)`),maxNodes:k().int().positive().max(2e3).optional().default(200).describe(`Maximum number of nodes to return (default: 200, max: 2000)`),project:$},outputSchema:{target:A().describe(`Target element id`),totalNodes:k().describe(`Total number of nodes in the graph`),maxDepth:k().describe(`Maximum depth reached`),truncated:O().describe(`True if result was truncated due to maxNodes limit`),nodes:E($i.extend({incomers:D(xa).describe(`Incoming relationships with details`),depth:k().describe(`Distance from target element (0 = target)`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n);j(r.findElement(t.elementId),`Element "${t.elementId}" not found in project "${n}"`);let i=t.includeIndirect?`all`:`direct`,a=ea(r,t.elementId,`incoming`,i,t.maxDepth,t.maxNodes),o={};for(let[e,t]of Object.entries(a.nodes)){let{neighbors:n,...r}=t;o[e]={...r,incomers:n}}return{target:a.target,totalNodes:a.totalNodes,maxDepth:a.maxDepth,truncated:a.truncated,nodes:o}}),Ca=w({elementId:A().describe(`ID of the outgoing element`),relationshipLabel:A().optional().describe(`Label on the relationship`),technology:A().optional().describe(`Technology specified on the relationship`)}),wa=Z({name:`query-outgoers-graph`,description:`
803
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query complete incomers graph`},inputSchema:{elementId:j().describe(`Target element id (FQN) to query incomers for`),includeIndirect:k().optional().default(!0).describe(`Include indirect relationships through nested elements (default: true)`),maxDepth:A().int().positive().max(50).optional().default(10).describe(`Maximum traversal depth (default: 10, max: 50)`),maxNodes:A().int().positive().max(2e3).optional().default(200).describe(`Maximum number of nodes to return (default: 200, max: 2000)`),project:$},outputSchema:{target:j().describe(`Target element id`),totalNodes:A().describe(`Total number of nodes in the graph`),maxDepth:A().describe(`Maximum depth reached`),truncated:k().describe(`True if result was truncated due to maxNodes limit`),nodes:D(ta.extend({incomers:O(Ca).describe(`Incoming relationships with details`),depth:A().describe(`Distance from target element (0 = target)`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n);M(r.findElement(t.elementId),`Element "${t.elementId}" not found in project "${n}"`);let i=t.includeIndirect?`all`:`direct`,a=na(r,t.elementId,`incoming`,i,t.maxDepth,t.maxNodes),o={};for(let[e,t]of Object.entries(a.nodes)){let{neighbors:n,...r}=t;o[e]={...r,incomers:n}}return{target:a.target,totalNodes:a.totalNodes,maxDepth:a.maxDepth,truncated:a.truncated,nodes:o}}),Ta=T({elementId:j().describe(`ID of the outgoing element`),relationshipLabel:j().optional().describe(`Label on the relationship`),technology:j().optional().describe(`Technology specified on the relationship`)}),Ea=Z({name:`query-outgoers-graph`,description:`
791
804
  Query the complete graph of all elements that receive output from the target element (recursive outgoers/consumers).
792
805
 
793
806
  This tool performs a breadth-first traversal to discover all downstream dependencies - elements that directly or
@@ -844,7 +857,7 @@ Notes:
844
857
  Example:
845
858
  For an API service, this returns all clients, services, and systems that consume its output,
846
859
  plus all their consumers, recursively up to maxDepth levels.
847
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query complete outgoers graph`},inputSchema:{elementId:A().describe(`Target element id (FQN) to query outgoers for`),includeIndirect:O().optional().default(!0).describe(`Include indirect relationships through nested elements (default: true)`),maxDepth:k().int().positive().max(50).optional().default(10).describe(`Maximum traversal depth (default: 10, max: 50)`),maxNodes:k().int().positive().max(2e3).optional().default(200).describe(`Maximum number of nodes to return (default: 200, max: 2000)`),project:$},outputSchema:{target:A().describe(`Target element id`),totalNodes:k().describe(`Total number of nodes in the graph`),maxDepth:k().describe(`Maximum depth reached`),truncated:O().describe(`True if result was truncated due to maxNodes limit`),nodes:E($i.extend({outgoers:D(Ca).describe(`Outgoing relationships with details`),depth:k().describe(`Distance from target element (0 = target)`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n);j(r.findElement(t.elementId),`Element "${t.elementId}" not found in project "${n}"`);let i=t.includeIndirect?`all`:`direct`,a=ea(r,t.elementId,`outgoing`,i,t.maxDepth,t.maxNodes),o={};for(let[e,t]of Object.entries(a.nodes)){let{neighbors:n,...r}=t;o[e]={...r,outgoers:n}}return{target:a.target,totalNodes:a.totalNodes,maxDepth:a.maxDepth,truncated:a.truncated,nodes:o}}),Ta=Z({name:`read-deployment`,description:`
860
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query complete outgoers graph`},inputSchema:{elementId:j().describe(`Target element id (FQN) to query outgoers for`),includeIndirect:k().optional().default(!0).describe(`Include indirect relationships through nested elements (default: true)`),maxDepth:A().int().positive().max(50).optional().default(10).describe(`Maximum traversal depth (default: 10, max: 50)`),maxNodes:A().int().positive().max(2e3).optional().default(200).describe(`Maximum number of nodes to return (default: 200, max: 2000)`),project:$},outputSchema:{target:j().describe(`Target element id`),totalNodes:A().describe(`Total number of nodes in the graph`),maxDepth:A().describe(`Maximum depth reached`),truncated:k().describe(`True if result was truncated due to maxNodes limit`),nodes:D(ta.extend({outgoers:O(Ta).describe(`Outgoing relationships with details`),depth:A().describe(`Distance from target element (0 = target)`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n);M(r.findElement(t.elementId),`Element "${t.elementId}" not found in project "${n}"`);let i=t.includeIndirect?`all`:`direct`,a=na(r,t.elementId,`outgoing`,i,t.maxDepth,t.maxNodes),o={};for(let[e,t]of Object.entries(a.nodes)){let{neighbors:n,...r}=t;o[e]={...r,outgoers:n}}return{target:a.target,totalNodes:a.totalNodes,maxDepth:a.maxDepth,truncated:a.truncated,nodes:o}}),Da=Z({name:`read-deployment`,description:`
848
861
  Read details about a deployment node or a deployed instance in a LikeC4 project.
849
862
 
850
863
  What it does:
@@ -909,7 +922,7 @@ Example response (deployed instance):
909
922
  "range": { "start": { "line": 10, "character": 0 }, "end": { "line": 25, "character": 0 } }
910
923
  }
911
924
  }
912
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read deployment entity`},inputSchema:{id:A().describe(`Deployment id (FQN)`),project:$},outputSchema:{type:C([`deployment-node`,`deployed-instance`]),id:A().describe(`Deployment id (FQN)`),kind:A().describe(`Deployment node kind, or element kind for deployed instances`),name:A(),title:A(),description:A().nullable(),technology:A().nullable(),tags:D(A()),project:A(),metadata:E(T([A(),D(A())])),links:D(w({title:A().nullable().describe(`Optional link title`),url:A().describe(`Link URL`),relative:A().nullable().describe(`Relative path (if URL is relative to workspace root)`)})).describe(`External links associated with this deployment entity`),shape:A(),color:A(),children:D(A()).describe(`Children of this deployment node (Array of Deployment ids)`),includedInViews:na.describe(`Views that include this deployment node`),instanceof:w({id:A().describe(`Element ID (FQN)`),title:A(),kind:A()}).nullable().describe(`If type is "deployed-instance", the referenced element`),sourceLocation:ta}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).deployment.findElement(t.id);j(r,`Deployment entity "${t.id}" not found in project "${n}"`);let i=ia(e,n);return{type:r.isInstance()?`deployed-instance`:`deployment-node`,id:r.id,name:r.name,kind:r.kind,title:r.title,description:r.description.text,technology:r.technology,tags:[...r.tags],project:n,metadata:r.getMetadata(),links:(r.links??[]).map(e=>({title:e.title??null,url:e.url,relative:e.relative??null})),shape:r.shape,color:r.color,children:r.isInstance()?[]:[...r.children()].map(e=>e.id),includedInViews:ra(r.views()),instanceof:r.isInstance()?{id:r.element.id,title:r.element.title,kind:r.element.kind}:null,sourceLocation:i({deployment:r.id})}}),Ea=Z({name:`read-element`,description:`
925
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read deployment entity`},inputSchema:{id:j().describe(`Deployment id (FQN)`),project:$},outputSchema:{type:w([`deployment-node`,`deployed-instance`]),id:j().describe(`Deployment id (FQN)`),kind:j().describe(`Deployment node kind, or element kind for deployed instances`),name:j(),title:j(),description:j().nullable(),technology:j().nullable(),tags:O(j()),project:j(),metadata:D(E([j(),O(j())])),links:O(T({title:j().nullable().describe(`Optional link title`),url:j().describe(`Link URL`),relative:j().nullable().describe(`Relative path (if URL is relative to workspace root)`)})).describe(`External links associated with this deployment entity`),shape:j(),color:j(),children:O(j()).describe(`Children of this deployment node (Array of Deployment ids)`),includedInViews:ia.describe(`Views that include this deployment node`),instanceof:T({id:j().describe(`Element ID (FQN)`),title:j(),kind:j()}).nullable().describe(`If type is "deployed-instance", the referenced element`),sourceLocation:ra}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).deployment.findElement(t.id);M(r,`Deployment entity "${t.id}" not found in project "${n}"`);let i=oa(e,n);return{type:r.isInstance()?`deployed-instance`:`deployment-node`,id:r.id,name:r.name,kind:r.kind,title:r.title,description:r.description.text,technology:r.technology,tags:[...r.tags],project:n,metadata:r.getMetadata(),links:(r.links??[]).map(e=>({title:e.title??null,url:e.url,relative:e.relative??null})),shape:r.shape,color:r.color,children:r.isInstance()?[]:[...r.children()].map(e=>e.id),includedInViews:aa(r.views()),instanceof:r.isInstance()?{id:r.element.id,title:r.element.title,kind:r.element.kind}:null,sourceLocation:i({deployment:r.id})}}),Oa=Z({name:`read-element`,description:`
913
926
  Read detailed information about a LikeC4 element.
914
927
 
915
928
  Request:
@@ -996,7 +1009,7 @@ Example response:
996
1009
  "range": { "start": { "line": 10, "character": 0 }, "end": { "line": 25, "character": 0 } }
997
1010
  }
998
1011
  }
999
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read element`},inputSchema:{id:A().describe(`Element id (FQN)`),project:$},outputSchema:{id:A().describe(`Element id (FQN)`),kind:A().describe(`Element kind`),name:A().describe(`Element name`),title:A(),description:A().nullable(),technology:A().nullable(),tags:D(A()),project:A(),metadata:E(T([A(),D(A())])),links:D(w({title:A().nullable().describe(`Optional link title`),url:A().describe(`Link URL`),relative:A().nullable().describe(`Relative path (if URL is relative to workspace root)`)})).describe(`External links associated with this element`),shape:A(),color:A(),children:D(A()).describe(`Children of this element (Array of FQNs)`),defaultView:A().nullable().describe(`Name of the default view of this element`),includedInViews:na.describe(`Views that include this element`),relationships:w({incoming:D(w({source:w({id:A(),title:A(),kind:A()}).describe(`Source element of this relationship`),kind:A().nullable().describe(`Relationship kind`),target:A().describe(`Target element id (FQN), either this element or nested element, if relationship is indirect`),title:A().nullable().describe(`Relationship title`),description:A().nullable().describe(`Relationship description`),technology:A().nullable().describe(`Relationship technology`),tags:D(A()).describe(`Relationship tags`)})).describe(`Incoming relationships of this element (direct and indirect, incoming to nested elements)`),outgoing:D(w({source:A().describe(`Source element id (FQN), either this element or nested element, if relationship is indirect`),target:w({id:A(),title:A(),kind:A()}).describe(`Target element of this relationship`),kind:A().nullable().describe(`Relationship kind`),title:A().nullable().describe(`Relationship title`),description:A().nullable().describe(`Relationship description`),technology:A().nullable().describe(`Relationship technology`),tags:D(A()).describe(`Relationship tags`)})).describe(`Outgoing relationships of this element (direct and indirect, outgoing from nested elements)`)}).describe(`Relationships of this element`),deployedInstances:D(A()).describe(`Deployed instances of this element (Array of Deployment FQNs)`),sourceLocation:ta}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.id);j(r,`Element "${t.id}" not found in project "${n}"`);let i=ia(e,n);return{id:r.id,name:r.name,kind:r.kind,title:r.title,description:r.description.text,technology:r.technology,tags:[...r.tags],project:n,metadata:r.getMetadata(),links:(r.links??[]).map(e=>({title:e.title??null,url:e.url,relative:e.relative??null})),shape:r.shape,color:r.color,children:[...r.children()].map(e=>e.id),defaultView:r.defaultView?.id||null,includedInViews:ra(r.views()),relationships:{incoming:[...r.incoming()].map(e=>({source:{id:e.source.id,title:e.source.title,kind:e.source.kind},kind:e.kind,target:e.target.id,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags]})),outgoing:[...r.outgoing()].map(e=>({source:e.source.id,target:{id:e.target.id,title:e.target.title,kind:e.target.kind},kind:e.kind,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags]}))},deployedInstances:[...r.deployments()].map(e=>e.id),sourceLocation:i({element:r.id})}}),Da=Z({name:`read-project-summary`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read project summary`},description:`
1012
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read element`},inputSchema:{id:j().describe(`Element id (FQN)`),project:$},outputSchema:{id:j().describe(`Element id (FQN)`),kind:j().describe(`Element kind`),name:j().describe(`Element name`),title:j(),description:j().nullable(),technology:j().nullable(),tags:O(j()),project:j(),metadata:D(E([j(),O(j())])),links:O(T({title:j().nullable().describe(`Optional link title`),url:j().describe(`Link URL`),relative:j().nullable().describe(`Relative path (if URL is relative to workspace root)`)})).describe(`External links associated with this element`),shape:j(),color:j(),children:O(j()).describe(`Children of this element (Array of FQNs)`),defaultView:j().nullable().describe(`Name of the default view of this element`),includedInViews:ia.describe(`Views that include this element`),relationships:T({incoming:O(T({source:T({id:j(),title:j(),kind:j()}).describe(`Source element of this relationship`),kind:j().nullable().describe(`Relationship kind`),target:j().describe(`Target element id (FQN), either this element or nested element, if relationship is indirect`),title:j().nullable().describe(`Relationship title`),description:j().nullable().describe(`Relationship description`),technology:j().nullable().describe(`Relationship technology`),tags:O(j()).describe(`Relationship tags`)})).describe(`Incoming relationships of this element (direct and indirect, incoming to nested elements)`),outgoing:O(T({source:j().describe(`Source element id (FQN), either this element or nested element, if relationship is indirect`),target:T({id:j(),title:j(),kind:j()}).describe(`Target element of this relationship`),kind:j().nullable().describe(`Relationship kind`),title:j().nullable().describe(`Relationship title`),description:j().nullable().describe(`Relationship description`),technology:j().nullable().describe(`Relationship technology`),tags:O(j()).describe(`Relationship tags`)})).describe(`Outgoing relationships of this element (direct and indirect, outgoing from nested elements)`)}).describe(`Relationships of this element`),deployedInstances:O(j()).describe(`Deployed instances of this element (Array of Deployment FQNs)`),sourceLocation:ra}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.id);M(r,`Element "${t.id}" not found in project "${n}"`);let i=oa(e,n);return{id:r.id,name:r.name,kind:r.kind,title:r.title,description:r.description.text,technology:r.technology,tags:[...r.tags],project:n,metadata:r.getMetadata(),links:(r.links??[]).map(e=>({title:e.title??null,url:e.url,relative:e.relative??null})),shape:r.shape,color:r.color,children:[...r.children()].map(e=>e.id),defaultView:r.defaultView?.id||null,includedInViews:aa(r.views()),relationships:{incoming:[...r.incoming()].map(e=>({source:{id:e.source.id,title:e.source.title,kind:e.source.kind},kind:e.kind,target:e.target.id,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags]})),outgoing:[...r.outgoing()].map(e=>({source:e.source.id,target:{id:e.target.id,title:e.target.title,kind:e.target.kind},kind:e.kind,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags]}))},deployedInstances:[...r.deployments()].map(e=>e.id),sourceLocation:i({element:r.id})}}),ka=Z({name:`read-project-summary`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read project summary`},description:`
1000
1013
  Request:
1001
1014
  - project: string (optional) — project id. Defaults to "default" if omitted.
1002
1015
 
@@ -1087,7 +1100,7 @@ Example response:
1087
1100
  }
1088
1101
  ]
1089
1102
  }
1090
- `,inputSchema:{project:$},outputSchema:{title:A(),folder:A(),sources:D(A()),config:Zi.describe(`Project configuration`),specification:w({elementKinds:D(A()),relationshipKinds:D(A()),deploymentKinds:D(A()),tags:D(A()),metadataKeys:D(A())}),elements:D(w({id:A(),kind:A(),title:A(),tags:D(A())})).describe(`List of elements in the project`),deployments:D(Le(`type`,[w({type:Re(`deployment-node`),id:A().describe(`Node ID`),kind:A().describe(`Deployment node kind`),title:A().describe(`Node title`),tags:D(A())}),w({type:Re(`deployed-instance`),id:A().describe(`Node ID`),title:A().describe(`Node title`),tags:D(A()),referencedElementId:A().describe(`Element ID (FQN)`)})])).describe(`List of deployment nodes and deployed instances in the project`),views:D(w({id:A(),title:A(),type:C([`element`,`deployment`,`dynamic`])}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=e.project(n),i=await e.computedModel(n);return{title:r.title,folder:r.folder.fsPath,sources:r.documents?.map(e=>e.fsPath)??[],config:Qi(r.config),specification:{elementKinds:d(i.specification.elements),relationshipKinds:d(i.specification.relationships),deploymentKinds:d(i.specification.deployments),tags:[...i.tags],metadataKeys:i.specification.metadataKeys??[]},elements:[...i.elements()].filter(e=>!e.imported).map(e=>({id:e.id,kind:e.kind,title:e.title,tags:[...e.tags]})),deployments:[...i.deployment.elements()].map(e=>e.isInstance()?{type:`deployed-instance`,id:e.id,title:e.title,tags:[...e.tags],referencedElementId:e.element.id}:{type:`deployment-node`,id:e.id,kind:e.kind,title:e.title,tags:[...e.tags]}),views:[...i.views()].map(e=>({id:e.id,title:e.titleOrId,type:e.$view._type}))}}),Oa=e=>e.hasElement()?e.element.id:e.hasDeployment()?e.deployment.id:null,ka=Le(`type`,[w({type:Re(`element`),id:A().describe(`Node ID`),elementId:A().describe(`Element ID (FQN)`),kind:A().describe(`Element kind`),title:A().describe(`Node title`),description:A().nullable(),technology:A().nullable(),children:D(A()).describe(`Children nodes, array of node IDs`),shape:A().describe(`Rendered shape`),color:A().describe(`Rendered color`),tags:D(A())}),w({type:Re(`deployment-node`),id:A().describe(`Node ID`),deploymentId:A().describe(`Deployment entity ID (FQN)`),kind:A().describe(`Deployment kind`),title:A().describe(`Node title`),description:A().nullable(),technology:A().nullable(),children:D(A()).describe(`Children nodes, array of node IDs`),shape:A().describe(`Rendered shape`),color:A().describe(`Rendered color`),tags:D(A())}),w({type:Re(`deployed-instance`),id:A().describe(`Node ID`),deploymentId:A().describe(`Deployment entity ID (FQN)`),title:A().describe(`Node title`),description:A().nullable(),technology:A().nullable(),referencedElement:w({id:A().describe(`Element ID (FQN)`),kind:A().describe(`Element kind`),title:A().describe(`Element title`)}),shape:A().describe(`Rendered shape`),color:A().describe(`Rendered color`),tags:D(A())})]),Aa=Z({name:`read-view`,description:`
1103
+ `,inputSchema:{project:$},outputSchema:{title:j(),folder:j(),sources:O(j()),config:$i.describe(`Project configuration`),specification:T({elementKinds:O(j()),relationshipKinds:O(j()),deploymentKinds:O(j()),tags:O(j()),metadataKeys:O(j())}),elements:O(T({id:j(),kind:j(),title:j(),tags:O(j())})).describe(`List of elements in the project`),deployments:O(Ie(`type`,[T({type:Le(`deployment-node`),id:j().describe(`Node ID`),kind:j().describe(`Deployment node kind`),title:j().describe(`Node title`),tags:O(j())}),T({type:Le(`deployed-instance`),id:j().describe(`Node ID`),title:j().describe(`Node title`),tags:O(j()),referencedElementId:j().describe(`Element ID (FQN)`)})])).describe(`List of deployment nodes and deployed instances in the project`),views:O(T({id:j(),title:j(),type:w([`element`,`deployment`,`dynamic`])}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=e.project(n),i=await e.computedModel(n);return{title:r.title,folder:r.folder.fsPath,sources:r.documents?.map(e=>e.fsPath)??[],config:ea(r.config),specification:{elementKinds:d(i.specification.elements),relationshipKinds:d(i.specification.relationships),deploymentKinds:d(i.specification.deployments),tags:[...i.tags],metadataKeys:i.specification.metadataKeys??[]},elements:[...i.elements()].filter(e=>!e.imported).map(e=>({id:e.id,kind:e.kind,title:e.title,tags:[...e.tags]})),deployments:[...i.deployment.elements()].map(e=>e.isInstance()?{type:`deployed-instance`,id:e.id,title:e.title,tags:[...e.tags],referencedElementId:e.element.id}:{type:`deployment-node`,id:e.id,kind:e.kind,title:e.title,tags:[...e.tags]}),views:[...i.views()].map(e=>({id:e.id,title:e.titleOrId,type:e.$view._type}))}}),Aa=e=>e.hasElement()?e.element.id:e.hasDeployment()?e.deployment.id:null,ja=Ie(`type`,[T({type:Le(`element`),id:j().describe(`Node ID`),elementId:j().describe(`Element ID (FQN)`),kind:j().describe(`Element kind`),title:j().describe(`Node title`),description:j().nullable(),technology:j().nullable(),children:O(j()).describe(`Children nodes, array of node IDs`),shape:j().describe(`Rendered shape`),color:j().describe(`Rendered color`),tags:O(j())}),T({type:Le(`deployment-node`),id:j().describe(`Node ID`),deploymentId:j().describe(`Deployment entity ID (FQN)`),kind:j().describe(`Deployment kind`),title:j().describe(`Node title`),description:j().nullable(),technology:j().nullable(),children:O(j()).describe(`Children nodes, array of node IDs`),shape:j().describe(`Rendered shape`),color:j().describe(`Rendered color`),tags:O(j())}),T({type:Le(`deployed-instance`),id:j().describe(`Node ID`),deploymentId:j().describe(`Deployment entity ID (FQN)`),title:j().describe(`Node title`),description:j().nullable(),technology:j().nullable(),referencedElement:T({id:j().describe(`Element ID (FQN)`),kind:j().describe(`Element kind`),title:j().describe(`Element title`)}),shape:j().describe(`Rendered shape`),color:j().describe(`Rendered color`),tags:O(j())})]),Ma=Z({name:`read-view`,description:`
1091
1104
  Read detailed information about a LikeC4 view.
1092
1105
 
1093
1106
  Request:
@@ -1135,7 +1148,7 @@ Example response:
1135
1148
  "range": { "start": { "line": 10, "character": 0 }, "end": { "line": 30, "character": 0 } }
1136
1149
  }
1137
1150
  }
1138
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read view`},inputSchema:{viewId:A().describe(`View id (name)`),project:$},outputSchema:{id:A(),type:C([`element`,`deployment`,`dynamic`]).describe(`View type`),title:A(),description:A().nullable(),tags:D(A()),project:A(),nodes:D(ka),edges:D(w({source:A().describe(`Source node`),target:A().describe(`Target node`),label:A().nullable(),description:A().nullable(),technology:A().nullable(),tags:D(A())})).describe(`Edge represents relationship between nodes`),sourceLocation:ta}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=e.project(n),i=(await e.computedModel(n)).findView(t.viewId);if(!i)throw Error(`View with ID '${t.viewId}' not found in project ${r.id}`);let a=ia(e,r.id);return{id:i.id,type:i.$view._type,title:i.title??i.id,description:i.description.text,tags:[...i.tags],project:r.id,nodes:[...i.nodes()].flatMap(e=>{let t={id:e.id,title:e.title,description:e.description.text,technology:e.technology,shape:e.shape,color:e.color,tags:[...e.tags]};return e.hasDeployedInstance()?{...t,type:`deployed-instance`,deploymentId:e.deployment.id,referencedElement:{id:e.deployment.element.id,kind:e.deployment.element.kind,title:e.deployment.element.title}}:e.hasDeployment()?{...t,type:`deployment-node`,kind:e.deployment.kind,deploymentId:e.deployment.id,children:[...e.children()].map(e=>e.id)}:e.hasElement()?{...t,type:`element`,elementId:e.element.id,kind:e.element.kind,children:[...e.children()].flatMap(e=>Oa(e)??[])}:[]}),edges:[...i.edges()].map(e=>({source:e.source.id,target:e.target.id,label:e.label,description:e.description.text,technology:e.technology,tags:[...e.tags]})),sourceLocation:a({view:i.id})}}),ja=D(Le(`type`,[w({type:Re(`element`),project:A().describe(`Project ID`),id:A().describe(`Element ID (FQN)`),name:A().describe(`Element name`),kind:A(),title:A(),technology:A().nullable(),shape:A(),includedInViews:na,metadata:E(T([A(),D(A())])),tags:D(A())}),w({type:Re(`deployment-node`),project:A().describe(`Project ID`),id:A().describe(`Deployment ID (FQN)`),name:A().describe(`Deployment name`),kind:A(),title:A(),technology:A().nullable(),shape:A(),includedInViews:na,metadata:E(T([A(),D(A())])),tags:D(A())})])),Ma=Z({name:`search-element`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Search elements`},description:`
1151
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read view`},inputSchema:{viewId:j().describe(`View id (name)`),project:$},outputSchema:{id:j(),type:w([`element`,`deployment`,`dynamic`]).describe(`View type`),title:j(),description:j().nullable(),tags:O(j()),project:j(),nodes:O(ja),edges:O(T({source:j().describe(`Source node`),target:j().describe(`Target node`),label:j().nullable(),description:j().nullable(),technology:j().nullable(),tags:O(j())})).describe(`Edge represents relationship between nodes`),sourceLocation:ra}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=e.project(n),i=(await e.computedModel(n)).findView(t.viewId);if(!i)throw Error(`View with ID '${t.viewId}' not found in project ${r.id}`);let a=oa(e,r.id);return{id:i.id,type:i.$view._type,title:i.title??i.id,description:i.description.text,tags:[...i.tags],project:r.id,nodes:[...i.nodes()].flatMap(e=>{let t={id:e.id,title:e.title,description:e.description.text,technology:e.technology,shape:e.shape,color:e.color,tags:[...e.tags]};return e.hasDeployedInstance()?{...t,type:`deployed-instance`,deploymentId:e.deployment.id,referencedElement:{id:e.deployment.element.id,kind:e.deployment.element.kind,title:e.deployment.element.title}}:e.hasDeployment()?{...t,type:`deployment-node`,kind:e.deployment.kind,deploymentId:e.deployment.id,children:[...e.children()].map(e=>e.id)}:e.hasElement()?{...t,type:`element`,elementId:e.element.id,kind:e.element.kind,children:[...e.children()].flatMap(e=>Aa(e)??[])}:[]}),edges:[...i.edges()].map(e=>({source:e.source.id,target:e.target.id,label:e.label,description:e.description.text,technology:e.technology,tags:[...e.tags]})),sourceLocation:a({view:i.id})}}),Na=O(Ie(`type`,[T({type:Le(`element`),project:j().describe(`Project ID`),id:j().describe(`Element ID (FQN)`),name:j().describe(`Element name`),kind:j(),title:j(),technology:j().nullable(),shape:j(),includedInViews:ia,metadata:D(E([j(),O(j())])),tags:O(j())}),T({type:Le(`deployment-node`),project:j().describe(`Project ID`),id:j().describe(`Deployment ID (FQN)`),name:j().describe(`Deployment name`),kind:j(),title:j(),technology:j().nullable(),shape:j(),includedInViews:ia,metadata:D(E([j(),O(j())])),tags:O(j())})])),Pa=Z({name:`search-element`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Search elements`},description:`
1139
1152
  Search LikeC4 elements and deployment nodes across all projects.
1140
1153
 
1141
1154
  Query syntax (case-insensitive):
@@ -1190,7 +1203,7 @@ Example response:
1190
1203
  }
1191
1204
  ]
1192
1205
  }
1193
- `,inputSchema:{search:A().min(2,`Search must be at least 2 characters long`)},outputSchema:{total:k(),found:ja}},async(e,t)=>{let n=e.projects(),r=[],i=t.search.toLowerCase(),a;i.startsWith(`kind:`)?(i=i.slice(5),X.debug(`search by kind: {search}`,{search:i}),a=e=>e.kind.toLowerCase()===i):i.startsWith(`shape:`)?(i=i.slice(6),X.debug(`search by shape: {search}`,{search:i}),a=e=>e.shape.toLowerCase()===i):i.startsWith(`meta:`)?(i=i.slice(5),X.debug(`search by metadata: {search}`,{search:i}),a=e=>!!e.getMetadata(i)):i.startsWith(`#`)?(i=i.slice(1),X.debug(`search by tag: {search}`,{search:i}),a=e=>e.tags.some(e=>e.toLowerCase().includes(i))):(X.debug(`search by id/title: {search}`,{search:i}),a=e=>e.id.toLowerCase().includes(i)||e.title.toLowerCase().includes(i));for(let t of n)try{let n=await e.computedModel(t.id);for(let e of at(n.elements(),e=>!e.imported&&a(e)))r.push({type:`element`,project:t.id,id:e.id,name:e.name,kind:e.kind,title:e.title,technology:e.technology,shape:e.shape,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:ra(e.views())});for(let e of at(n.deployment.nodes(),a))r.push({type:`deployment-node`,project:t.id,id:e.id,name:e.name,kind:e.kind,title:e.title,technology:e.technology,shape:e.shape,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:ra(e.views())})}catch(e){X.error(`Error searching in project ${t.id}:`,{error:e})}return{total:r.length,found:r.slice(0,20)}}),Na=w({id:A().describe(`Element id (FQN)`),name:A().describe(`Element name`),kind:A().describe(`Element kind`),title:A().describe(`Human-readable title`),depth:k().describe(`Depth relative to the root element (1 = direct child)`),tags:D(A()).describe(`Assigned tags`),metadata:E(T([A(),D(A())])).describe(`Element metadata`),childCount:k().describe(`Number of direct children`),incomingCount:k().describe(`Number of incoming relationships`),outgoingCount:k().describe(`Number of outgoing relationships`)}),Pa=Z({name:`subgraph-summary`,description:`
1206
+ `,inputSchema:{search:j().min(2,`Search must be at least 2 characters long`)},outputSchema:{total:A(),found:Na}},async(e,t)=>{let n=e.projects(),r=[],i=t.search.toLowerCase(),a;i.startsWith(`kind:`)?(i=i.slice(5),X.debug(`search by kind: {search}`,{search:i}),a=e=>e.kind.toLowerCase()===i):i.startsWith(`shape:`)?(i=i.slice(6),X.debug(`search by shape: {search}`,{search:i}),a=e=>e.shape.toLowerCase()===i):i.startsWith(`meta:`)?(i=i.slice(5),X.debug(`search by metadata: {search}`,{search:i}),a=e=>!!e.getMetadata(i)):i.startsWith(`#`)?(i=i.slice(1),X.debug(`search by tag: {search}`,{search:i}),a=e=>e.tags.some(e=>e.toLowerCase().includes(i))):(X.debug(`search by id/title: {search}`,{search:i}),a=e=>e.id.toLowerCase().includes(i)||e.title.toLowerCase().includes(i));for(let t of n)try{let n=await e.computedModel(t.id);for(let e of it(n.elements(),e=>!e.imported&&a(e)))r.push({type:`element`,project:t.id,id:e.id,name:e.name,kind:e.kind,title:e.title,technology:e.technology,shape:e.shape,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:aa(e.views())});for(let e of it(n.deployment.nodes(),a))r.push({type:`deployment-node`,project:t.id,id:e.id,name:e.name,kind:e.kind,title:e.title,technology:e.technology,shape:e.shape,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:aa(e.views())})}catch(e){X.error(`Error searching in project ${t.id}:`,{error:e})}return{total:r.length,found:r.slice(0,20)}}),Fa=T({id:j().describe(`Element id (FQN)`),name:j().describe(`Element name`),kind:j().describe(`Element kind`),title:j().describe(`Human-readable title`),depth:A().describe(`Depth relative to the root element (1 = direct child)`),tags:O(j()).describe(`Assigned tags`),metadata:D(E([j(),O(j())])).describe(`Element metadata`),childCount:A().describe(`Number of direct children`),incomingCount:A().describe(`Number of incoming relationships`),outgoingCount:A().describe(`Number of outgoing relationships`)}),Ia=Z({name:`subgraph-summary`,description:`
1194
1207
  Get a compact, table-friendly summary of all descendants of a parent element.
1195
1208
  Returns each descendant with its depth, metadata, tags, and relationship counts in a single call.
1196
1209
  Much more efficient than calling read-element for each descendant individually.
@@ -1256,7 +1269,7 @@ Example response:
1256
1269
  "truncated": false,
1257
1270
  "truncatedByDepth": false
1258
1271
  }
1259
- `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Subgraph summary`},inputSchema:{elementId:A().describe(`Parent element id (FQN) whose descendants to summarize`),maxDepth:k().int().min(1).max(20).optional().default(10).describe(`Maximum depth of descendants to include (default: 10, max: 20)`),metadataKeys:D(A()).optional().describe(`If provided, only include these metadata keys in the response`),project:$},outputSchema:{root:w({id:A(),kind:A(),title:A(),childCount:k()}),descendants:D(Na),totalDescendants:k().describe(`Total number of descendants found`),truncated:O().describe(`True if results were truncated due to exceeding the limit`),truncatedByDepth:O().describe(`True if deeper descendants exist beyond maxDepth`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.elementId);j(r,`Element "${t.elementId}" not found in project "${n}"`);let i=t.maxDepth,a=t.metadataKeys,o=[],s=0,c=!1,l=!1,u=[],d=[...r.children()];for(let e of d)u.push({element:e,depth:1});for(;u.length>0;){let{element:e,depth:t}=u.shift();if(t>i){l=!0;continue}s++;let n=[...e.children()];if(o.length<200){let r=e.getMetadata(),i=a?Object.fromEntries(a.filter(e=>e in r).map(e=>[e,r[e]])):r;o.push({id:e.id,name:e.name,kind:e.kind,title:e.title,depth:t,tags:[...e.tags],metadata:i,childCount:n.length,incomingCount:[...e.incoming()].length,outgoingCount:[...e.outgoing()].length})}else c=!0;for(let e of n)u.push({element:e,depth:t+1})}return{root:{id:r.id,kind:r.kind,title:r.title,childCount:d.length},descendants:o,totalDescendants:s,truncated:c,truncatedByDepth:l}});function Fa(e,t){let n=new Be({name:`LikeC4`,version:Xi},{instructions:`LikeC4 MCP – query and navigate LikeC4 models.
1272
+ `,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Subgraph summary`},inputSchema:{elementId:j().describe(`Parent element id (FQN) whose descendants to summarize`),maxDepth:A().int().min(1).max(20).optional().default(10).describe(`Maximum depth of descendants to include (default: 10, max: 20)`),metadataKeys:O(j()).optional().describe(`If provided, only include these metadata keys in the response`),project:$},outputSchema:{root:T({id:j(),kind:j(),title:j(),childCount:A()}),descendants:O(Fa),totalDescendants:A().describe(`Total number of descendants found`),truncated:k().describe(`True if results were truncated due to exceeding the limit`),truncatedByDepth:k().describe(`True if deeper descendants exist beyond maxDepth`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.elementId);M(r,`Element "${t.elementId}" not found in project "${n}"`);let i=t.maxDepth,a=t.metadataKeys,o=[],s=0,c=!1,l=!1,u=[],d=[...r.children()];for(let e of d)u.push({element:e,depth:1});for(;u.length>0;){let{element:e,depth:t}=u.shift();if(t>i){l=!0;continue}s++;let n=[...e.children()];if(o.length<200){let r=e.getMetadata(),i=a?Object.fromEntries(a.filter(e=>e in r).map(e=>[e,r[e]])):r;o.push({id:e.id,name:e.name,kind:e.kind,title:e.title,depth:t,tags:[...e.tags],metadata:i,childCount:n.length,incomingCount:[...e.incoming()].length,outgoingCount:[...e.outgoing()].length})}else c=!0;for(let e of n)u.push({element:e,depth:t+1})}return{root:{id:r.id,kind:r.kind,title:r.title,childCount:d.length},descendants:o,totalDescendants:s,truncated:c,truncatedByDepth:l}});function La(e,t){let n=new ze({name:`LikeC4`,version:Qi},{instructions:`LikeC4 MCP – query and navigate LikeC4 models.
1260
1273
 
1261
1274
  Conventions:
1262
1275
  - All tools are read-only and idempotent.
@@ -1289,14 +1302,14 @@ Instructions:
1289
1302
  - If response returns "sourceLocation", provide link to this location in the editor
1290
1303
 
1291
1304
  Full documentation: https://likec4.dev/llms-full.txt
1292
- `,enforceStrictCapabilities:!0,...t,capabilities:{tools:{},logging:{},...t?.capabilities}});return n.registerTool(...ma(e)),n.registerTool(...Da(e)),n.registerTool(...Ea(e)),n.registerTool(...Ta(e)),n.registerTool(...Aa(e)),n.registerTool(...Ma(e)),n.registerTool(...pa(e)),n.registerTool(...ba(e)),n.registerTool(...Sa(e)),n.registerTool(...wa(e)),n.registerTool(...ga(e)),n.registerTool(...va(e)),n.registerTool(...ua(e)),n.registerTool(...oa(e)),n.registerTool(..._a(e)),n.registerTool(...la(e)),n.registerTool(...Pa(e)),n.server.onerror=e=>{p.error(h(e))},n}var Ia=class{transport=void 0;_mcp=void 0;constructor(e){this.services=e}get mcp(){if(!this._mcp)throw Error(`MCP server is not started`);return this._mcp}get isStarted(){return this.transport!==void 0}get port(){return NaN}async dispose(){await this.stop()}async start(){this.transport||(X.info(`Starting MCP stdio server`),this._mcp=Fa(this.services),this.transport=new ze,await this._mcp.connect(this.transport),X.info(`LikeC4 MCP Server running on stdio`))}async stop(){if(this.transport)try{X.info(`Stopping MCP stdio server`),await this.transport.close(),this._mcp&&await this._mcp.close()}finally{this._mcp=void 0,this.transport=void 0}}};async function La(e){let t=new ue;t.use(`*`,fe({origin:`*`,allowHeaders:[`Content-Type`,`mcp-session-id`,`Last-Event-ID`,`mcp-protocol-version`],exposeHeaders:[`mcp-session-id`,`mcp-protocol-version`]})),t.get(`/health`,e=>e.json({status:`ok`}));let n=e(),r=new de({eventStore:new pe({})});return t.all(`/mcp`,async e=>(n.isConnected()||await n.connect(r),await r.handleRequest(e))),t.notFound(e=>(X.debug(`${e.req.method} ${e.req.url} not found`),e.json({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not found.`},id:null},{status:404}))),t.onError((e,t)=>(X.error(h(e)),t.json({jsonrpc:`2.0`,error:{code:-32603,message:`Internal server error`},id:null},{status:500}))),t}async function Ra(e){let{factory:t,port:n}=e,r=await La(t);return new Promise((e,t)=>{let i=Ge({fetch:r.fetch,hostname:`0.0.0.0`,port:n}).prependOnceListener(`error`,t).prependOnceListener(`listening`,()=>{i.removeListener(`error`,t),e(i.unref())})})}var za=class{server=void 0;constructor(e,t=33335){this.services=e,this._port=t}get mcp(){throw Error(`StreamableLikeC4MCPServer has access to McpServer only during the request`)}get isStarted(){return this.server?.listening===!0}get port(){return this._port}async dispose(){await this.stop()}async start(e=this._port){if(this.server){if(this.port===e)return;await this.stop()}X.info(`Starting MCP server on port {port}`,{port:e}),this._port=e,this.server=await Ra({factory:()=>Fa(this.services),port:e}),X.info(`MCP server ready at http://0.0.0.0:{port}/mcp`,{port:e})}stop(){let e=this.server;return e?(X.info(`Stopping MCP server`),this.server=void 0,new Promise(t=>{e.close(e=>{e?X.error(`Failed to stop MCP server`,{err:e}):X.info(`MCP server stopped`),t()})})):(X.info(`MCP server is not running, nothing to stop`),Promise.resolve())}};async function Ba(e){let t=ne(e,{workspacePath:`.`,mcp:`stdio`,graphviz:`wasm`,watch:!0,throwIfInvalid:!1,configureLogger:!0});t.configureLogger&&(y({useStdErr:t.mcp===`stdio`,colors:x.isColorSupported&&t.mcp!==`stdio`,logLevel:ft?`debug`:`info`}),process.on(`uncaughtException`,e=>{X.error(`uncaughtException`,{err:e})}),process.on(`unhandledRejection`,e=>{X.error(`unhandledRejection`,{err:e})}));let n=F(t.workspacePath);X.info`Loading LikeC4 from workspace: ${n}`;let r=await v(n,{graphviz:t.graphviz,manualLayouts:!0,configureLogger:!1,watch:t.watch,throwIfInvalid:t.throwIfInvalid}),i=r.languageServices;return{server:t.mcp===`stdio`?new Ia(i):new za(i,t.mcp.port),likec4:r}}async function Va(e){let t=await Ba(e);return await t.server.start(),t}const Ha=e=>e.command({command:`mcp [path]`,aliases:[],describe:`Start MCP server`,builder:e=>e.usage(`${x.bold(`Usage:`)} $0 mcp [path]`).positional(`path`,W).default(`path`,`.`,`current directory`).option(`stdio`,{boolean:!0,description:`use stdio transport`,conflicts:[`http`,`port`]}).option(`http`,{boolean:!0,description:`use streamable http transport (use 33335 port by default)`,conflicts:`stdio`}).option(`port`,{alias:`p`,number:!0,description:`enables http transport and sets the port`,conflicts:`stdio`}).option(`use-dot`,G).option(`log-level`,vn).option(`verbose`,yn).showHidden().epilog(`${x.bold(`Examples:`)}
1293
- ${x.green(`$0 mcp`)}
1294
- ${x.gray(`Start MCP with default stdio transport`)}
1295
- ${x.green(`$0 mcp --http ./src`)}
1296
- ${x.gray(`Start MCP with streamable http transport on port 33335 at ./src folder`)}
1297
- ${x.green(`$0 mcp -p 1234`)}
1298
- ${x.gray(`Start MCP with streamable http transport on port 1234`)}
1299
- `),handler:async e=>{e.http||e.port?(y({colors:x.isColorSupported,logLevel:e.verbose?bn:e.logLevel}),await Ua(e.path,e.useDot,e.port)):(y({useStdErr:!0,colors:!1,logLevel:e.verbose?bn:e.logLevel}),await Wa(e.path,e.useDot))}});async function Ua(e,t,n=33335){await Va({workspacePath:e,mcp:{port:n},watch:!0,configureLogger:!1,graphviz:t?`binary`:`wasm`}),U([x.green(`LikeC4 MCP served at:`),`
1305
+ `,enforceStrictCapabilities:!0,...t,capabilities:{tools:{},logging:{},...t?.capabilities}});return n.registerTool(...ga(e)),n.registerTool(...ka(e)),n.registerTool(...Oa(e)),n.registerTool(...Da(e)),n.registerTool(...Ma(e)),n.registerTool(...Pa(e)),n.registerTool(...ha(e)),n.registerTool(...Sa(e)),n.registerTool(...wa(e)),n.registerTool(...Ea(e)),n.registerTool(...va(e)),n.registerTool(...ba(e)),n.registerTool(...fa(e)),n.registerTool(...ca(e)),n.registerTool(...ya(e)),n.registerTool(...da(e)),n.registerTool(...Ia(e)),n.server.onerror=e=>{p.error(h(e))},n}var Ra=class{transport=void 0;_mcp=void 0;constructor(e){this.services=e}get mcp(){if(!this._mcp)throw Error(`MCP server is not started`);return this._mcp}get isStarted(){return this.transport!==void 0}get port(){return NaN}async dispose(){await this.stop()}async start(){this.transport||(X.info(`Starting MCP stdio server`),this._mcp=La(this.services),this.transport=new Re,await this._mcp.connect(this.transport),X.info(`LikeC4 MCP Server running on stdio`))}async stop(){if(this.transport)try{X.info(`Stopping MCP stdio server`),await this.transport.close(),this._mcp&&await this._mcp.close()}finally{this._mcp=void 0,this.transport=void 0}}};async function za(e){let t=new ce;t.use(`*`,ue({origin:`*`,allowHeaders:[`Content-Type`,`mcp-session-id`,`Last-Event-ID`,`mcp-protocol-version`],exposeHeaders:[`mcp-session-id`,`mcp-protocol-version`]})),t.get(`/health`,e=>e.json({status:`ok`}));let n=e(),r=new le({eventStore:new de({})});return t.all(`/mcp`,async e=>(n.isConnected()||await n.connect(r),await r.handleRequest(e))),t.notFound(e=>(X.debug(`${e.req.method} ${e.req.url} not found`),e.json({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not found.`},id:null},{status:404}))),t.onError((e,t)=>(X.error(h(e)),t.json({jsonrpc:`2.0`,error:{code:-32603,message:`Internal server error`},id:null},{status:500}))),t}async function Ba(e){let{factory:t,port:n}=e,r=await za(t);return new Promise((e,t)=>{let i=We({fetch:r.fetch,hostname:`0.0.0.0`,port:n}).prependOnceListener(`error`,t).prependOnceListener(`listening`,()=>{i.removeListener(`error`,t),e(i.unref())})})}var Va=class{server=void 0;constructor(e,t=33335){this.services=e,this._port=t}get mcp(){throw Error(`StreamableLikeC4MCPServer has access to McpServer only during the request`)}get isStarted(){return this.server?.listening===!0}get port(){return this._port}async dispose(){await this.stop()}async start(e=this._port){if(this.server){if(this.port===e)return;await this.stop()}X.info(`Starting MCP server on port {port}`,{port:e}),this._port=e,this.server=await Ba({factory:()=>La(this.services),port:e}),X.info(`MCP server ready at http://0.0.0.0:{port}/mcp`,{port:e})}stop(){let e=this.server;return e?(X.info(`Stopping MCP server`),this.server=void 0,new Promise(t=>{e.close(e=>{e?X.error(`Failed to stop MCP server`,{err:e}):X.info(`MCP server stopped`),t()})})):(X.info(`MCP server is not running, nothing to stop`),Promise.resolve())}};async function Ha(e){let t=x(e,{workspacePath:`.`,mcp:`stdio`,graphviz:`wasm`,watch:!0,throwIfInvalid:!1,configureLogger:!0});t.configureLogger&&(y({useStdErr:t.mcp===`stdio`,colors:C.isColorSupported&&t.mcp!==`stdio`,logLevel:dt?`debug`:`info`}),process.on(`uncaughtException`,e=>{X.error(`uncaughtException`,{err:e})}),process.on(`unhandledRejection`,e=>{X.error(`unhandledRejection`,{err:e})}));let n=I(t.workspacePath);X.info`Loading LikeC4 from workspace: ${n}`;let r=await v(n,{graphviz:t.graphviz,manualLayouts:!0,configureLogger:!1,watch:t.watch,throwIfInvalid:t.throwIfInvalid}),i=r.languageServices;return{server:t.mcp===`stdio`?new Ra(i):new Va(i,t.mcp.port),likec4:r}}async function Ua(e){let t=await Ha(e);return await t.server.start(),t}const Wa=e=>e.command({command:`mcp [path]`,aliases:[],describe:`Start MCP server`,builder:e=>e.usage(`${C.bold(`Usage:`)} $0 mcp [path]`).positional(`path`,G).default(`path`,`.`,`current directory`).option(`stdio`,{boolean:!0,description:`use stdio transport`,conflicts:[`http`,`port`]}).option(`http`,{boolean:!0,description:`use streamable http transport (use 33335 port by default)`,conflicts:`stdio`}).option(`port`,{alias:`p`,number:!0,description:`enables http transport and sets the port`,conflicts:`stdio`}).option(`use-dot`,K).option(`log-level`,vn).option(`verbose`,yn).showHidden().epilog(`${C.bold(`Examples:`)}
1306
+ ${C.green(`$0 mcp`)}
1307
+ ${C.gray(`Start MCP with default stdio transport`)}
1308
+ ${C.green(`$0 mcp --http ./src`)}
1309
+ ${C.gray(`Start MCP with streamable http transport on port 33335 at ./src folder`)}
1310
+ ${C.green(`$0 mcp -p 1234`)}
1311
+ ${C.gray(`Start MCP with streamable http transport on port 1234`)}
1312
+ `),handler:async e=>{e.http||e.port?(y({colors:C.isColorSupported,logLevel:e.verbose?bn:e.logLevel}),await Ga(e.path,e.useDot,e.port)):(y({useStdErr:!0,colors:!1,logLevel:e.verbose?bn:e.logLevel}),await Ka(e.path,e.useDot))}});async function Ga(e,t,n=33335){await Ua({workspacePath:e,mcp:{port:n},watch:!0,configureLogger:!1,graphviz:t?`binary`:`wasm`}),W([C.green(`LikeC4 MCP served at:`),`
1300
1313
  {
1301
1314
  "mcpServers": {
1302
1315
  "likec4": {
@@ -1305,18 +1318,18 @@ ${x.green(`$0 mcp -p 1234`)}
1305
1318
  }
1306
1319
  }
1307
1320
 
1308
- ${x.dim(`Documentation:`)}
1309
- ${x.underline(`https://likec4.dev/tooling/mcp/#using-extension`)}
1321
+ ${C.dim(`Documentation:`)}
1322
+ ${C.underline(`https://likec4.dev/tooling/mcp/#using-extension`)}
1310
1323
  `].join(`
1311
- `))}async function Wa(e,t){await Va({workspacePath:e,mcp:`stdio`,watch:!0,configureLogger:!1,graphviz:t?`binary`:`wasm`})}async function Ga(e){let t=await tn({...e,likec4AssetsDir:``,webcomponentPrefix:void 0}),n=await Ue({port:He(62001,62010)}),r=e?.open??!1;return await Bt({...t,customLogger:t.customLogger,mode:`production`,preview:{host:e.listen??`127.0.0.1`,allowedHosts:!0,port:n,open:r}})}async function Ka({path:e,output:t,base:n,listen:r}){Ii(await Ga({base:n,languageServices:await v(e,{watch:!1}),outputDir:t,open:!S(),listen:r}))}const qa=e=>e.command({command:`preview [path]`,describe:`Start local server to preview production build`,builder:e=>e.positional(`path`,{type:`string`,desc:`Directory with LikeC4 source files
1312
- if not specified search in current directory`,normalize:!0}).options({output:{alias:`o`,type:`string`,desc:`output directory from production build`,normalize:!0},base:{type:`string`,desc:`base url the app is being served from`},listen:{alias:`l`,type:`string`,desc:`ip address of the network interface to listen on`}}).coerce([`path`,`output`],I).default(`path`,I(`.`),`.`).default(`listen`,`127.0.0.1`,`localhost`),handler:async e=>{await Ka(e)}});async function Ja({path:e,useDotBin:t,webcomponentPrefix:n,title:r,useHashHistory:i,enableWebcomponent:a=!0,enableHMR:o=!0,base:s,listen:c,port:l}){o&&(process.env.NODE_ENV=`development`);let u=await Li({buildWebcomponent:a,hmr:o,base:s,webcomponentPrefix:n,title:r,languageServices:await v(e,{graphviz:t?`binary`:`wasm`,watch:o}),useHashHistory:i,likec4AssetsDir:await gt(N(lt(),`.likec4-assets-`)),listen:c,port:l});u.config.logger.clearScreen(`info`),Ii(u),Ht(J,1e3).unref()}const Ya=e=>e.command({command:`start [path]`,aliases:[`serve`,`dev`],describe:`Start local dev server to preview LikeC4 views`,builder:e=>e.positional(`path`,W).option(`base`,mn).option(`webcomponent-prefix`,dn).option(`title`,fn).option(`use-hash-history`,un).option(`use-dot`,G).option(`listen`,gn).option(`port`,_n).options({"react-hmr":{type:`boolean`,default:!0,describe:`Enable/Disable React HMR`},"build-webcomponent":{type:`boolean`,default:!0,describe:`Enable/Disable Webcomponent build`}}),handler:async e=>{await sn(),await Ja({path:e.path,useDotBin:e[`use-dot`],base:e.base,webcomponentPrefix:e[`webcomponent-prefix`],title:e.title,useHashHistory:e[`use-hash-history`],listen:e.listen,port:e.port,enableHMR:e[`react-hmr`],enableWebcomponent:e[`build-webcomponent`]})}});async function Xa(e,t,n,r){let i=await wr(t,n,{idempotent:!0}),a=F(e,`sync-plan.json`);if(await R(a,JSON.stringify(i,null,2)),r.info(`${x.dim(`generated`)} ${P(process.cwd(),a)}`),i.errors.length>0){let e=`${i.errors.length} plan error(s): ${i.errors.join(`; `)}`;throw r.error(e),Error(e)}}async function Za(e,t,n,r){let i=await Tr(t.manifest,t.dryRun,n,{idempotent:!0}),a=F(e,Qr.manifest);if(await R(a,JSON.stringify(i.manifest,null,2)),r.info(`${x.dim(`generated`)} ${P(process.cwd(),a)} (after sync)`),i.errors.length>0){let e=`${i.errors.length} sync error(s): ${i.errors.join(`; `)}`;throw r.error(e),Error(e)}}async function Qa(e){let t=V(`c4:sync:leanix`),n=H(t),{path:r,outdir:i,project:a,useDotBin:o,dryRun:s,apply:c}=e;try{try{var l=Y();if(s&&c)throw Error(`Choose either dryRun or apply, not both`);let e=l.a(await v(r,{graphviz:o?`binary`:`wasm`,watch:!1})),{projectId:n}=Nn(e,a);a&&t.info(`${x.dim(`project`)} ${x.green(n)}`);let u=await e.layoutedModel(n);if(u===Oe.EMPTY)throw t.error(Ur),Error(Ur);let d=Xr(Yr(u));await Zr(i,d,t);let f=ei();if((s||!c)&&(f?await Xa(i,d.dryRun,f,t):t.info(`${x.dim(`skip`)} sync-plan (set LEANIX_API_TOKEN to include plan)`)),c){if(!f)throw t.error(Wr),Error(Wr);await Za(i,d,f,t)}}catch(e){l.e=e}finally{await l.d()}}finally{n.stopAndLog()}}const $a=F(process.cwd(),`out`,`bridge`);function eo(e){return typeof e!=`object`||!e||!Object.hasOwn(e,`target`)?!1:typeof Reflect.get(e,`target`)==`string`}function to(e){return e.command({command:`sync <target> [path]`,describe:`Sync bridge artifacts (e.g. LeanIX)`,builder:e=>e.positional(`target`,{type:`string`,choices:[`leanix`],describe:`Target system (leanix)`}).positional(`path`,W).option(`outdir`,{...K,default:$a,desc:`<dir> output directory for bridge artifacts (manifest, leanix-dry-run, report, sync-plan)`}).option(`dry-run`,{type:`boolean`,describe:`Only write artifacts and optional sync-plan; do not call LeanIX API for create/update`}).option(`apply`,{type:`boolean`,describe:`Run live sync to LeanIX (requires LEANIX_API_TOKEN)`}).conflicts(`dry-run`,`apply`).option(`project`,q).option(`use-dot`,G).example(`${x.green(`$0 sync leanix --dry-run -o out/bridge`)}`,x.gray(`Write bridge artifacts and optionally sync-plan when LEANIX_API_TOKEN is set`)).example(`${x.green(`$0 sync leanix --apply -o out/bridge`)}`,x.gray(`Write artifacts then run live sync; updates manifest with LeanIX IDs`)),handler:async e=>{if(!eo(e)||e.target!==`leanix`)return;let t=e.apply??!1,n=e.dryRun??!t;await Qa({path:e.path??`.`,outdir:e.outdir??$a,project:e.project,useDotBin:e.useDotBin??!1,dryRun:n,apply:t})}})}const no=e=>e.command({command:`validate [path]`,aliases:[],describe:`Validate syntax, semantics and layout drifts`,builder:e=>e.positional(`path`,W).options({project:q,file:{alias:`f`,array:!0,string:!0,description:`only report errors from these files (can be specified multiple times)`},layout:{boolean:!0,default:!0,defaultDescription:`enabled`,description:`force layout validation, or disable with --no-layout`},json:{boolean:!0,nargs:0,description:`output as JSON (structured)`}}).showHidden().epilog(`${x.bold(`Examples:`)}
1313
- ${x.green(`$0 validate `)}
1314
- ${x.gray(`Validate all in the current directory`)}
1315
-
1316
- ${x.green(`$0 validate --no-layout --json -f ./src/model.c4 -f ./src/deployment.c4 `)}
1317
- ${x.gray([`Validate all`,`ignore layout drifts`,`report only errors from these files`,`output as JSON`].join(`, `))}
1318
-
1319
- ${x.green(`$0 validate --project my-project /some/where`)}
1320
- ${x.gray(`Validate my-project in /some/where`)}
1321
- `),handler:async e=>{try{var t=Y();let n=V(`c4:validate`),r=H(n),i=e.json===!0,a=e.layout===!0,o=e.file?.map(e=>F(e))??null,s=t.a(await v(e.path,{watch:!1,printErrors:!i,throwIfInvalid:!1,configureLogger:i?`stderr`:!1})),c=s.getErrors().map(e=>({message:e.message,file:e.sourceFsPath,line:e.line,range:e.range})),l=[];if(a){n.debug(`running layout validation...`);try{let t=await s.diagrams(e.project);for(let n of t)n.drifts&&n.drifts.length>0&&l.push({message:`Layout drift detected on view '${n.id}'`,file:n.sourcePath?F(e.path,n.sourcePath):``,line:0,range:null})}catch(e){l.push({message:`Layout validation failed: ${e instanceof Error?e.message:String(e)}`,file:``,line:0,range:null})}}let u=[...c,...l],d=s.documentCount(),f=u.length,p=o?u.filter(e=>o.some(t=>e.file===t||e.file.endsWith(`/`+t)||e.file.endsWith(`\\`+t))):u,m=new Set(p.map(e=>e.file)),h=p.length===0;process.exitCode=h?0:1;let g={valid:h,errors:p,stats:{totalFiles:d,totalErrors:f,filteredFiles:o?m.size:d,filteredErrors:p.length}};if(i){console.log(JSON.stringify(g,null,2));return}for(let e of l)n.error(x.red(e.message)+(e.file?` at `+e.file:``));if(h)n.info(x.green(`✓ Valid`)+x.dim(` (${d} files)`));else{let e=o?`, ${p.length} in filtered files`:``;n.error(x.red(`✗ Invalid`)+x.dim(` (${d} files, ${f} errors${e})`))}r.stopAndLog(`validate `)}catch(e){t.e=e}finally{await t.d()}}});function ro(e){let t=e??(ft?`trace`:`info`);b({reset:!0,sinks:{console:_({formatter:x.isColorSupported?te():m()})},loggers:[{category:`likec4`,sinks:[`console`],lowestLevel:t}]})}async function io(){!pt&&!dt&&!S()&&await On(),await o(Mt(Nt(Dt)),Ya,Tn,fi,Wi,Gi,qa,to,no,Ki,Ha,Ji,jn,e=>e.command({command:`completion`,describe:`Generate completion script`,handler:()=>{e.showCompletionScript()}})).scriptName(`likec4`).usage(`Usage: $0 <command>`).version(Wt).alias(`v`,`version`).alias(`h`,`help`).help(`help`).option(`log-level`,vn).option(`verbose`,yn).option(`color`,{boolean:!0,describe:[`force color output, or disable with --no-color`,`respects 'FORCE_COLOR' and 'NO_COLOR' env variables`].join(`
1322
- `),skipValidation:!0,hidden:!0,global:!0}).group([`log-level`,`verbose`,`color`,`help`,`version`,`show-hidden`],`Globals:`).demandCommand(1,`Please run with valid command`).recommendCommands().showHelpOnFail(!0).showHidden().updateStrings({"Globals:":x.bold(`Globals:`),"Options:":x.bold(`Options:`),"Positionals:":x.bold(`Arguments:`),"Commands:":x.bold(`Commands:`),"Examples:":x.bold(`Examples:`)}).wrap(t(jt.columns-10,{min:60,max:180})).middleware(e=>{ro(e.verbose?bn:e.logLevel)}).parseAsync()}function ao(e,t){console.error(t==null?h(e):`${t} ${h(e)}`),kt(1)}io().catch(ao),process.on(`unhandledRejection`,e=>{ao(e,`Unhandled rejection:`)}),process.on(`uncaughtException`,e=>{console.error(e)});export{};
1324
+ `))}async function Ka(e,t){await Ua({workspacePath:e,mcp:`stdio`,watch:!0,configureLogger:!1,graphviz:t?`binary`:`wasm`})}async function qa(e){let t=await en({...e,likec4AssetsDir:``,webcomponentPrefix:void 0}),n=await He({port:Ve(62001,62010)}),r=e?.open??!1;return await zt({...t,customLogger:t.customLogger,mode:`production`,preview:{host:e.listen??`127.0.0.1`,allowedHosts:!0,port:n,open:r}})}async function Ja({path:e,output:t,base:n,listen:r}){Mi(await qa({base:n,languageServices:await v(e,{watch:!1}),outputDir:t,open:!De(),listen:r}))}const Ya=e=>e.command({command:`preview [path]`,describe:`Start local server to preview production build`,builder:e=>e.positional(`path`,{type:`string`,desc:`Directory with LikeC4 source files
1325
+ if not specified search in current directory`,normalize:!0}).options({output:{alias:`o`,type:`string`,desc:`output directory from production build`,normalize:!0},base:{type:`string`,desc:`base url the app is being served from`},listen:{alias:`l`,type:`string`,desc:`ip address of the network interface to listen on`}}).coerce([`path`,`output`],L).default(`path`,L(`.`),`.`).default(`listen`,`127.0.0.1`,`localhost`),handler:async e=>{await Ja(e)}});async function Xa({path:e,useDotBin:t,webcomponentPrefix:n,title:r,useHashHistory:i,enableWebcomponent:a=!0,enableHMR:o=!0,base:s,listen:c,port:l}){o&&(process.env.NODE_ENV=`development`);let u=await Ni({buildWebcomponent:a,hmr:o,base:s,webcomponentPrefix:n,title:r,languageServices:await v(e,{graphviz:t?`binary`:`wasm`,watch:o}),useHashHistory:i,likec4AssetsDir:await ht(P(ct(),`.likec4-assets-`)),listen:c,port:l});u.config.logger.clearScreen(`info`),Mi(u),Vt(J,1e3).unref()}const Za=e=>e.command({command:`start [path]`,aliases:[`serve`,`dev`],describe:`Start local dev server to preview LikeC4 views`,builder:e=>e.positional(`path`,G).option(`base`,mn).option(`webcomponent-prefix`,dn).option(`title`,fn).option(`use-hash-history`,ln).option(`use-dot`,K).option(`listen`,gn).option(`port`,_n).options({"react-hmr":{type:`boolean`,default:!0,describe:`Enable/Disable React HMR`},"build-webcomponent":{type:`boolean`,default:!0,describe:`Enable/Disable Webcomponent build`}}),handler:async e=>{await on(),await Xa({path:e.path,useDotBin:e[`use-dot`],base:e.base,webcomponentPrefix:e[`webcomponent-prefix`],title:e.title,useHashHistory:e[`use-hash-history`],listen:e.listen,port:e.port,enableHMR:e[`react-hmr`],enableWebcomponent:e[`build-webcomponent`]})}});async function Qa(e,t,n,r){let i=await wr(t,n,{idempotent:!0}),a=I(e,`sync-plan.json`);if(await z(a,JSON.stringify(i,null,2)),r.info(`${C.dim(`generated`)} ${F(process.cwd(),a)}`),i.errors.length>0){let e=`${i.errors.length} plan error(s): ${i.errors.join(`; `)}`;throw r.error(e),Error(e)}}async function $a(e,t,n,r){let i=await Tr(t.manifest,t.dryRun,n,{idempotent:!0}),a=I(e,Qr.manifest);if(await z(a,JSON.stringify(i.manifest,null,2)),r.info(`${C.dim(`generated`)} ${F(process.cwd(),a)} (after sync)`),i.errors.length>0){let e=`${i.errors.length} sync error(s): ${i.errors.join(`; `)}`;throw r.error(e),Error(e)}}async function eo(e){let t=H(`c4:sync:leanix`),n=U(t),{path:r,outdir:i,project:a,useDotBin:o,dryRun:s,apply:c}=e;try{try{var l=Y();if(s&&c)throw Error(`Choose either dryRun or apply, not both`);let e=l.a(await v(r,{graphviz:o?`binary`:`wasm`,watch:!1})),{projectId:n}=Nn(e,a);a&&t.info(`${C.dim(`project`)} ${C.green(n)}`);let u=await e.layoutedModel(n);if(u===Ee.EMPTY)throw t.error(Ur),Error(Ur);let d=Xr(Yr(u));await Zr(i,d,t);let f=ei();if((s||!c)&&(f?await Qa(i,d.dryRun,f,t):t.info(`${C.dim(`skip`)} sync-plan (set LEANIX_API_TOKEN to include plan)`)),c){if(!f)throw t.error(Wr),Error(Wr);await $a(i,d,f,t)}}catch(e){l.e=e}finally{await l.d()}}finally{n.stopAndLog()}}const to=I(process.cwd(),`out`,`bridge`);function no(e){return typeof e!=`object`||!e||!Object.hasOwn(e,`target`)?!1:typeof Reflect.get(e,`target`)==`string`}function ro(e){return e.command({command:`sync <target> [path]`,describe:`Sync bridge artifacts (e.g. LeanIX)`,builder:e=>e.positional(`target`,{type:`string`,choices:[`leanix`],describe:`Target system (leanix)`}).positional(`path`,G).option(`outdir`,{...un,default:to,desc:`<dir> output directory for bridge artifacts (manifest, leanix-dry-run, report, sync-plan)`}).option(`dry-run`,{type:`boolean`,describe:`Only write artifacts and optional sync-plan; do not call LeanIX API for create/update`}).option(`apply`,{type:`boolean`,describe:`Run live sync to LeanIX (requires LEANIX_API_TOKEN)`}).conflicts(`dry-run`,`apply`).option(`project`,q).option(`use-dot`,K).example(`${C.green(`$0 sync leanix --dry-run -o out/bridge`)}`,C.gray(`Write bridge artifacts and optionally sync-plan when LEANIX_API_TOKEN is set`)).example(`${C.green(`$0 sync leanix --apply -o out/bridge`)}`,C.gray(`Write artifacts then run live sync; updates manifest with LeanIX IDs`)),handler:async e=>{if(!no(e)||e.target!==`leanix`)return;let t=e.apply??!1,n=e.dryRun??!t;await eo({path:e.path??`.`,outdir:e.outdir??to,project:e.project,useDotBin:e.useDotBin??!1,dryRun:n,apply:t})}})}const io=e=>e.command({command:`validate [path]`,aliases:[],describe:`Validate syntax, semantics and layout drifts`,builder:e=>e.positional(`path`,G).options({project:q,file:{alias:`f`,array:!0,string:!0,description:`only report errors from these files (can be specified multiple times)`},layout:{boolean:!0,default:!0,defaultDescription:`enabled`,description:`force layout validation, or disable with --no-layout`},json:{boolean:!0,nargs:0,description:`output as JSON (structured)`}}).showHidden().epilog(`${C.bold(`Examples:`)}
1326
+ ${C.green(`$0 validate `)}
1327
+ ${C.gray(`Validate all in the current directory`)}
1328
+
1329
+ ${C.green(`$0 validate --no-layout --json -f ./src/model.c4 -f ./src/deployment.c4 `)}
1330
+ ${C.gray([`Validate all`,`ignore layout drifts`,`report only errors from these files`,`output as JSON`].join(`, `))}
1331
+
1332
+ ${C.green(`$0 validate --project my-project /some/where`)}
1333
+ ${C.gray(`Validate my-project in /some/where`)}
1334
+ `),handler:async e=>{try{var t=Y();let n=H(`c4:validate`),r=U(n),i=e.json===!0,a=e.layout===!0,o=e.file?.map(e=>I(e))??null,s=t.a(await v(e.path,{watch:!1,printErrors:!i,throwIfInvalid:!1,configureLogger:i?`stderr`:!1})),c=s.getErrors().map(e=>({message:e.message,file:e.sourceFsPath,line:e.line,range:e.range})),l=[];if(a){n.debug(`running layout validation...`);try{let t=await s.diagrams(e.project);for(let n of t)n.drifts&&n.drifts.length>0&&l.push({message:`Layout drift detected on view '${n.id}'`,file:n.sourcePath?I(e.path,n.sourcePath):``,line:0,range:null})}catch(e){l.push({message:`Layout validation failed: ${e instanceof Error?e.message:String(e)}`,file:``,line:0,range:null})}}let u=[...c,...l],d=s.documentCount(),f=u.length,p=o?u.filter(e=>o.some(t=>e.file===t||e.file.endsWith(`/`+t)||e.file.endsWith(`\\`+t))):u,m=new Set(p.map(e=>e.file)),h=p.length===0;process.exitCode=h?0:1;let g={valid:h,errors:p,stats:{totalFiles:d,totalErrors:f,filteredFiles:o?m.size:d,filteredErrors:p.length}};if(i){console.log(JSON.stringify(g,null,2));return}for(let e of l)n.error(C.red(e.message)+(e.file?` at `+e.file:``));if(h)n.info(C.green(`✓ Valid`)+C.dim(` (${d} files)`));else{let e=o?`, ${p.length} in filtered files`:``;n.error(C.red(`✗ Invalid`)+C.dim(` (${d} files, ${f} errors${e})`))}r.stopAndLog(`validate `)}catch(e){t.e=e}finally{await t.d()}}});function ao(e){let t=e??(dt?`trace`:`info`);ee({reset:!0,sinks:{console:_({formatter:C.isColorSupported?te():m()})},loggers:[{category:`likec4`,sinks:[`console`],lowestLevel:t}]})}async function oo(){!ft&&!ut&&!De()&&await On(),await o(jt(Mt(Et)),Za,Tn,fi,Ki,qi,Ya,ro,io,Ji,Wa,Xi,jn,e=>e.command({command:`completion`,describe:`Generate completion script`,handler:()=>{e.showCompletionScript()}})).scriptName(`likec4`).usage(`Usage: $0 <command>`).version(Ut).alias(`v`,`version`).alias(`h`,`help`).help(`help`).option(`log-level`,vn).option(`verbose`,yn).option(`color`,{boolean:!0,describe:[`force color output, or disable with --no-color`,`respects 'FORCE_COLOR' and 'NO_COLOR' env variables`].join(`
1335
+ `),skipValidation:!0,hidden:!0,global:!0}).group([`log-level`,`verbose`,`color`,`help`,`version`,`show-hidden`],`Globals:`).demandCommand(1,`Please run with valid command`).recommendCommands().showHelpOnFail(!0).showHidden().updateStrings({"Globals:":C.bold(`Globals:`),"Options:":C.bold(`Options:`),"Positionals:":C.bold(`Arguments:`),"Commands:":C.bold(`Commands:`),"Examples:":C.bold(`Examples:`)}).wrap(t(At.columns-10,{min:60,max:180})).middleware(e=>{ao(e.verbose?bn:e.logLevel)}).parseAsync()}function so(e,t){console.error(t==null?h(e):`${t} ${h(e)}`),Ot(1)}oo().catch(so),process.on(`unhandledRejection`,e=>{so(e,`Unhandled rejection:`)}),process.on(`uncaughtException`,e=>{console.error(e)});export{};