@likec4/language-server 1.47.0 → 1.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. package/LICENSE +1 -1
  2. package/browser/package.json +2 -2
  3. package/browser-worker/package.json +2 -2
  4. package/bundled/package.json +4 -0
  5. package/dist/LikeC4LanguageServices.d.mts +4 -0
  6. package/dist/LikeC4LanguageServices.mjs +3 -0
  7. package/dist/_chunks/ConfigurableLayouter.mjs +1956 -0
  8. package/dist/_chunks/LikeC4LanguageServices.d.mts +1978 -0
  9. package/dist/_chunks/LikeC4LanguageServices.mjs +725 -0
  10. package/dist/_chunks/ast.d.mts +1444 -0
  11. package/dist/_chunks/ast.mjs +2375 -0
  12. package/dist/_chunks/ast2.mjs +176 -0
  13. package/dist/_chunks/common-exports.mjs +0 -0
  14. package/dist/_chunks/filesystem.mjs +58 -0
  15. package/dist/_chunks/grammar.mjs +8 -0
  16. package/dist/_chunks/icons.mjs +5211 -0
  17. package/dist/_chunks/libs/@hono/node-server.mjs +436 -0
  18. package/dist/_chunks/libs/@msgpack/msgpack.mjs +805 -0
  19. package/dist/_chunks/libs/eventemitter3.mjs +243 -0
  20. package/dist/_chunks/libs/fast-equals.mjs +446 -0
  21. package/dist/_chunks/libs/hono.mjs +1829 -0
  22. package/dist/_chunks/libs/p-queue.mjs +449 -0
  23. package/dist/_chunks/libs/parse-ms.mjs +36 -0
  24. package/dist/_chunks/libs/picomatch.mjs +1673 -0
  25. package/dist/_chunks/libs/pretty-ms.mjs +80 -0
  26. package/dist/_chunks/libs/remeda.mjs +482 -0
  27. package/dist/_chunks/libs/strip-indent.mjs +15 -0
  28. package/dist/_chunks/libs/ufo.mjs +166 -0
  29. package/dist/_chunks/likec4lib.mjs +9 -0
  30. package/dist/_chunks/mcp.mjs +33 -0
  31. package/dist/_chunks/module.mjs +28 -0
  32. package/dist/_chunks/module2.mjs +6576 -0
  33. package/dist/_chunks/protocol.d.mts +311 -0
  34. package/dist/_chunks/protocol.mjs +78 -0
  35. package/dist/_chunks/rolldown-runtime.mjs +42 -0
  36. package/dist/ast.d.mts +4 -0
  37. package/dist/ast.mjs +4 -0
  38. package/dist/browser-worker.d.mts +1 -0
  39. package/dist/browser-worker.mjs +6 -0
  40. package/dist/browser.d.mts +11 -0
  41. package/dist/browser.mjs +27 -0
  42. package/dist/bundled.d.mts +28 -0
  43. package/dist/bundled.mjs +51 -4853
  44. package/dist/common-exports.d.mts +4 -0
  45. package/dist/common-exports.mjs +5 -0
  46. package/dist/filesystem/index.d.mts +4 -0
  47. package/dist/filesystem/index.mjs +3 -0
  48. package/dist/generated/ast.d.mts +2 -0
  49. package/dist/generated/ast.mjs +3 -0
  50. package/dist/generated/grammar.d.mts +6 -0
  51. package/dist/generated/grammar.mjs +3 -0
  52. package/dist/generated/module.d.mts +14 -0
  53. package/dist/generated/module.mjs +3 -0
  54. package/dist/generated-lib/icons.d.mts +4 -0
  55. package/dist/generated-lib/icons.mjs +3 -0
  56. package/dist/index.d.mts +4 -0
  57. package/dist/index.mjs +48 -0
  58. package/dist/likec4lib.d.mts +9 -0
  59. package/dist/likec4lib.mjs +4 -0
  60. package/dist/mcp/index.d.mts +4 -0
  61. package/dist/mcp/index.mjs +3 -0
  62. package/dist/module.d.mts +4 -0
  63. package/dist/module.mjs +3 -0
  64. package/dist/protocol.d.mts +2 -0
  65. package/dist/protocol.mjs +3 -0
  66. package/likec4lib/package.json +2 -2
  67. package/package.json +106 -63
  68. package/protocol/package.json +2 -2
  69. package/dist/LikeC4LanguageServices.d.ts +0 -115
  70. package/dist/LikeC4LanguageServices.js +0 -164
  71. package/dist/Rpc.d.ts +0 -9
  72. package/dist/Rpc.js +0 -276
  73. package/dist/ast.d.ts +0 -226
  74. package/dist/ast.js +0 -264
  75. package/dist/browser-worker.d.ts +0 -1
  76. package/dist/browser-worker.js +0 -4
  77. package/dist/browser.d.ts +0 -10
  78. package/dist/browser.js +0 -34
  79. package/dist/bundled.d.ts +0 -8
  80. package/dist/bundled.js +0 -44
  81. package/dist/documentation/documentation-provider.d.ts +0 -8
  82. package/dist/documentation/documentation-provider.js +0 -51
  83. package/dist/documentation/index.d.ts +0 -1
  84. package/dist/documentation/index.js +0 -1
  85. package/dist/empty.d.ts +0 -2
  86. package/dist/empty.js +0 -2
  87. package/dist/filesystem/ChokidarWatcher.d.ts +0 -19
  88. package/dist/filesystem/ChokidarWatcher.js +0 -133
  89. package/dist/filesystem/FileSystemWatcher.d.ts +0 -19
  90. package/dist/filesystem/FileSystemWatcher.js +0 -14
  91. package/dist/filesystem/LikeC4FileSystem.d.ts +0 -3
  92. package/dist/filesystem/LikeC4FileSystem.js +0 -140
  93. package/dist/filesystem/index.d.ts +0 -55
  94. package/dist/filesystem/index.js +0 -29
  95. package/dist/formatting/LikeC4Formatter.d.ts +0 -59
  96. package/dist/formatting/LikeC4Formatter.js +0 -637
  97. package/dist/formatting/utils.d.ts +0 -6
  98. package/dist/formatting/utils.js +0 -18
  99. package/dist/generated/ast.d.ts +0 -1411
  100. package/dist/generated/ast.js +0 -2207
  101. package/dist/generated/grammar.d.ts +0 -6
  102. package/dist/generated/grammar.js +0 -7
  103. package/dist/generated/module.d.ts +0 -14
  104. package/dist/generated/module.js +0 -27
  105. package/dist/generated-lib/icons.d.ts +0 -1
  106. package/dist/generated-lib/icons.js +0 -18
  107. package/dist/index.d.ts +0 -37
  108. package/dist/index.js +0 -54
  109. package/dist/likec4lib.d.ts +0 -6
  110. package/dist/likec4lib.js +0 -7
  111. package/dist/logger.d.ts +0 -17
  112. package/dist/logger.js +0 -81
  113. package/dist/lsp/CodeActionProvider.d.ts +0 -14
  114. package/dist/lsp/CodeActionProvider.js +0 -33
  115. package/dist/lsp/CodeLensProvider.d.ts +0 -9
  116. package/dist/lsp/CodeLensProvider.js +0 -44
  117. package/dist/lsp/CompletionProvider.d.ts +0 -13
  118. package/dist/lsp/CompletionProvider.js +0 -238
  119. package/dist/lsp/DocumentHighlightProvider.d.ts +0 -9
  120. package/dist/lsp/DocumentHighlightProvider.js +0 -10
  121. package/dist/lsp/DocumentLinkProvider.d.ts +0 -11
  122. package/dist/lsp/DocumentLinkProvider.js +0 -58
  123. package/dist/lsp/DocumentSymbolProvider.d.ts +0 -33
  124. package/dist/lsp/DocumentSymbolProvider.js +0 -317
  125. package/dist/lsp/HoverProvider.d.ts +0 -10
  126. package/dist/lsp/HoverProvider.js +0 -106
  127. package/dist/lsp/RenameProvider.d.ts +0 -5
  128. package/dist/lsp/RenameProvider.js +0 -6
  129. package/dist/lsp/SemanticTokenProvider.d.ts +0 -19
  130. package/dist/lsp/SemanticTokenProvider.js +0 -305
  131. package/dist/lsp/index.d.ts +0 -8
  132. package/dist/lsp/index.js +0 -9
  133. package/dist/mcp/MCPServerFactory.d.ts +0 -8
  134. package/dist/mcp/MCPServerFactory.js +0 -73
  135. package/dist/mcp/NoopLikeC4MCPServer.d.ts +0 -9
  136. package/dist/mcp/NoopLikeC4MCPServer.js +0 -17
  137. package/dist/mcp/interfaces.d.ts +0 -13
  138. package/dist/mcp/interfaces.js +0 -4
  139. package/dist/mcp/server/StdioLikeC4MCPServer.d.ts +0 -16
  140. package/dist/mcp/server/StdioLikeC4MCPServer.js +0 -51
  141. package/dist/mcp/server/StreamableLikeC4MCPServer.d.ts +0 -16
  142. package/dist/mcp/server/StreamableLikeC4MCPServer.js +0 -121
  143. package/dist/mcp/server/WithMCPServer.d.ts +0 -4
  144. package/dist/mcp/server/WithMCPServer.js +0 -54
  145. package/dist/mcp/tools/_common.d.ts +0 -88
  146. package/dist/mcp/tools/_common.js +0 -49
  147. package/dist/mcp/tools/find-relationships.d.ts +0 -202
  148. package/dist/mcp/tools/find-relationships.js +0 -150
  149. package/dist/mcp/tools/list-projects.d.ts +0 -194
  150. package/dist/mcp/tools/list-projects.js +0 -62
  151. package/dist/mcp/tools/open-view.d.ts +0 -200
  152. package/dist/mcp/tools/open-view.js +0 -52
  153. package/dist/mcp/tools/read-deployment.d.ts +0 -200
  154. package/dist/mcp/tools/read-deployment.js +0 -150
  155. package/dist/mcp/tools/read-element.d.ts +0 -200
  156. package/dist/mcp/tools/read-element.js +0 -218
  157. package/dist/mcp/tools/read-project-summary.d.ts +0 -198
  158. package/dist/mcp/tools/read-project-summary.js +0 -176
  159. package/dist/mcp/tools/read-view.d.ts +0 -200
  160. package/dist/mcp/tools/read-view.js +0 -203
  161. package/dist/mcp/tools/search-element.d.ts +0 -198
  162. package/dist/mcp/tools/search-element.js +0 -177
  163. package/dist/mcp/utils.d.ts +0 -18
  164. package/dist/mcp/utils.js +0 -48
  165. package/dist/model/builder/MergedExtends.d.ts +0 -13
  166. package/dist/model/builder/MergedExtends.js +0 -74
  167. package/dist/model/builder/MergedSpecification.d.ts +0 -32
  168. package/dist/model/builder/MergedSpecification.js +0 -175
  169. package/dist/model/builder/buildModel.d.ts +0 -16
  170. package/dist/model/builder/buildModel.js +0 -245
  171. package/dist/model/deployments-index.d.ts +0 -10
  172. package/dist/model/deployments-index.js +0 -102
  173. package/dist/model/fqn-index.d.ts +0 -61
  174. package/dist/model/fqn-index.js +0 -253
  175. package/dist/model/index.d.ts +0 -6
  176. package/dist/model/index.js +0 -6
  177. package/dist/model/model-builder.d.ts +0 -54
  178. package/dist/model/model-builder.js +0 -233
  179. package/dist/model/model-locator.d.ts +0 -39
  180. package/dist/model/model-locator.js +0 -240
  181. package/dist/model/model-parser-where.d.ts +0 -4
  182. package/dist/model/model-parser-where.js +0 -81
  183. package/dist/model/model-parser.d.ts +0 -645
  184. package/dist/model/model-parser.js +0 -133
  185. package/dist/model/parser/Base.d.ts +0 -69
  186. package/dist/model/parser/Base.js +0 -382
  187. package/dist/model/parser/DeploymentModelParser.d.ts +0 -71
  188. package/dist/model/parser/DeploymentModelParser.js +0 -176
  189. package/dist/model/parser/DeploymentViewParser.d.ts +0 -75
  190. package/dist/model/parser/DeploymentViewParser.js +0 -86
  191. package/dist/model/parser/FqnRefParser.d.ts +0 -66
  192. package/dist/model/parser/FqnRefParser.js +0 -382
  193. package/dist/model/parser/GlobalsParser.d.ts +0 -109
  194. package/dist/model/parser/GlobalsParser.js +0 -84
  195. package/dist/model/parser/ImportsParser.d.ts +0 -46
  196. package/dist/model/parser/ImportsParser.js +0 -24
  197. package/dist/model/parser/ModelParser.d.ts +0 -71
  198. package/dist/model/parser/ModelParser.js +0 -209
  199. package/dist/model/parser/PredicatesParser.d.ts +0 -75
  200. package/dist/model/parser/PredicatesParser.js +0 -45
  201. package/dist/model/parser/SpecificationParser.d.ts +0 -53
  202. package/dist/model/parser/SpecificationParser.js +0 -113
  203. package/dist/model/parser/ValueConverter.d.ts +0 -4
  204. package/dist/model/parser/ValueConverter.js +0 -12
  205. package/dist/model/parser/ViewsParser.d.ts +0 -112
  206. package/dist/model/parser/ViewsParser.js +0 -492
  207. package/dist/model-change/ModelChanges.d.ts +0 -18
  208. package/dist/model-change/ModelChanges.js +0 -129
  209. package/dist/model-change/changeElementStyle.d.ts +0 -16
  210. package/dist/model-change/changeElementStyle.js +0 -134
  211. package/dist/model-change/changeViewLayout.d.ts +0 -12
  212. package/dist/model-change/changeViewLayout.js +0 -28
  213. package/dist/model-change/removeManualLayoutV1.d.ts +0 -7
  214. package/dist/model-change/removeManualLayoutV1.js +0 -27
  215. package/dist/module.d.ts +0 -92
  216. package/dist/module.js +0 -143
  217. package/dist/protocol.d.ts +0 -289
  218. package/dist/protocol.js +0 -123
  219. package/dist/references/index.d.ts +0 -3
  220. package/dist/references/index.js +0 -3
  221. package/dist/references/name-provider.d.ts +0 -9
  222. package/dist/references/name-provider.js +0 -37
  223. package/dist/references/scope-computation.d.ts +0 -20
  224. package/dist/references/scope-computation.js +0 -288
  225. package/dist/references/scope-provider.d.ts +0 -40
  226. package/dist/references/scope-provider.js +0 -239
  227. package/dist/shared/NodeKindProvider.d.ts +0 -15
  228. package/dist/shared/NodeKindProvider.js +0 -57
  229. package/dist/shared/WorkspaceSymbolProvider.d.ts +0 -3
  230. package/dist/shared/WorkspaceSymbolProvider.js +0 -3
  231. package/dist/shared/index.d.ts +0 -2
  232. package/dist/shared/index.js +0 -2
  233. package/dist/test/index.d.ts +0 -1
  234. package/dist/test/index.js +0 -1
  235. package/dist/test/testServices.d.ts +0 -64
  236. package/dist/test/testServices.js +0 -210
  237. package/dist/utils/disposable.d.ts +0 -8
  238. package/dist/utils/disposable.js +0 -26
  239. package/dist/utils/elementRef.d.ts +0 -11
  240. package/dist/utils/elementRef.js +0 -33
  241. package/dist/utils/fqnRef.d.ts +0 -11
  242. package/dist/utils/fqnRef.js +0 -63
  243. package/dist/utils/index.d.ts +0 -11
  244. package/dist/utils/index.js +0 -35
  245. package/dist/utils/printDocs.d.ts +0 -2
  246. package/dist/utils/printDocs.js +0 -1
  247. package/dist/utils/projectId.d.ts +0 -4
  248. package/dist/utils/projectId.js +0 -16
  249. package/dist/utils/stringHash.d.ts +0 -1
  250. package/dist/utils/stringHash.js +0 -5
  251. package/dist/validation/DocumentValidator.d.ts +0 -11
  252. package/dist/validation/DocumentValidator.js +0 -17
  253. package/dist/validation/_shared.d.ts +0 -3
  254. package/dist/validation/_shared.js +0 -26
  255. package/dist/validation/deployment-checks.d.ts +0 -7
  256. package/dist/validation/deployment-checks.js +0 -140
  257. package/dist/validation/dynamic-view.d.ts +0 -6
  258. package/dist/validation/dynamic-view.js +0 -67
  259. package/dist/validation/element-ref.d.ts +0 -4
  260. package/dist/validation/element-ref.js +0 -12
  261. package/dist/validation/element.d.ts +0 -4
  262. package/dist/validation/element.js +0 -49
  263. package/dist/validation/imports.d.ts +0 -4
  264. package/dist/validation/imports.js +0 -46
  265. package/dist/validation/index.d.ts +0 -15
  266. package/dist/validation/index.js +0 -167
  267. package/dist/validation/property-checks.d.ts +0 -7
  268. package/dist/validation/property-checks.js +0 -108
  269. package/dist/validation/relation.d.ts +0 -6
  270. package/dist/validation/relation.js +0 -141
  271. package/dist/validation/specification.d.ts +0 -12
  272. package/dist/validation/specification.js +0 -190
  273. package/dist/validation/view-checks.d.ts +0 -4
  274. package/dist/validation/view-checks.js +0 -46
  275. package/dist/validation/view-predicates/fqn-expr-with.d.ts +0 -4
  276. package/dist/validation/view-predicates/fqn-expr-with.js +0 -43
  277. package/dist/validation/view-predicates/fqn-ref-expr.d.ts +0 -4
  278. package/dist/validation/view-predicates/fqn-ref-expr.js +0 -51
  279. package/dist/validation/view-predicates/incoming.d.ts +0 -4
  280. package/dist/validation/view-predicates/incoming.js +0 -16
  281. package/dist/validation/view-predicates/index.d.ts +0 -6
  282. package/dist/validation/view-predicates/index.js +0 -6
  283. package/dist/validation/view-predicates/outgoing.d.ts +0 -4
  284. package/dist/validation/view-predicates/outgoing.js +0 -20
  285. package/dist/validation/view-predicates/relation-expr.d.ts +0 -4
  286. package/dist/validation/view-predicates/relation-expr.js +0 -46
  287. package/dist/validation/view-predicates/relation-with.d.ts +0 -4
  288. package/dist/validation/view-predicates/relation-with.js +0 -16
  289. package/dist/validation/view.d.ts +0 -4
  290. package/dist/validation/view.js +0 -42
  291. package/dist/view-utils/assignNavigateTo.d.ts +0 -2
  292. package/dist/view-utils/assignNavigateTo.js +0 -27
  293. package/dist/view-utils/index.d.ts +0 -2
  294. package/dist/view-utils/index.js +0 -2
  295. package/dist/view-utils/manual-layout.d.ts +0 -13
  296. package/dist/view-utils/manual-layout.js +0 -149
  297. package/dist/views/ConfigurableLayouter.d.ts +0 -7
  298. package/dist/views/ConfigurableLayouter.js +0 -51
  299. package/dist/views/LikeC4ManualLayouts.d.ts +0 -42
  300. package/dist/views/LikeC4ManualLayouts.js +0 -209
  301. package/dist/views/LikeC4Views.d.ts +0 -89
  302. package/dist/views/LikeC4Views.js +0 -216
  303. package/dist/views/index.d.ts +0 -4
  304. package/dist/views/index.js +0 -11
  305. package/dist/workspace/AstNodeDescriptionProvider.d.ts +0 -7
  306. package/dist/workspace/AstNodeDescriptionProvider.js +0 -18
  307. package/dist/workspace/IndexManager.d.ts +0 -10
  308. package/dist/workspace/IndexManager.js +0 -26
  309. package/dist/workspace/LangiumDocuments.d.ts +0 -29
  310. package/dist/workspace/LangiumDocuments.js +0 -104
  311. package/dist/workspace/ProjectsManager.d.ts +0 -134
  312. package/dist/workspace/ProjectsManager.js +0 -610
  313. package/dist/workspace/WorkspaceManager.d.ts +0 -31
  314. package/dist/workspace/WorkspaceManager.js +0 -132
  315. package/dist/workspace/index.d.ts +0 -5
  316. package/dist/workspace/index.js +0 -5
@@ -1,42 +0,0 @@
1
- import { CstUtils } from 'langium';
2
- import { ast } from '../ast';
3
- import { projectIdFrom } from '../utils';
4
- import { hasManualLayout } from '../view-utils/manual-layout';
5
- import { RESERVED_WORDS, tryOrLog } from './_shared';
6
- export const viewChecks = (services) => {
7
- const index = services.shared.workspace.IndexManager;
8
- return tryOrLog((el, accept) => {
9
- const commentNode = CstUtils.findCommentNode(el.$cstNode, ['BLOCK_COMMENT']);
10
- if (commentNode && hasManualLayout(commentNode.text)) {
11
- accept('warning', `Migrate to the new manual layout snapshots (run LikeC4: Migrate manual layouts)`, {
12
- node: el,
13
- range: commentNode.range,
14
- code: 'manual-layout-v1',
15
- // codeDescription: {
16
- // href: 'https://likec4.dev/docs/guides/manual-layout#migrating-from-v1-to-v2-manual-layout',
17
- // },
18
- });
19
- }
20
- if (!el.name) {
21
- return;
22
- }
23
- if (RESERVED_WORDS.includes(el.name)) {
24
- accept('error', `Reserved word: ${el.name}`, {
25
- node: el,
26
- property: 'name',
27
- });
28
- }
29
- const projectId = projectIdFrom(el);
30
- const anotherViews = index
31
- .projectElements(projectId, ast.LikeC4View)
32
- .filter(n => n.name === el.name)
33
- .limit(2)
34
- .count();
35
- if (anotherViews > 1) {
36
- accept('error', `Duplicate view '${el.name}'`, {
37
- node: el,
38
- property: 'name',
39
- });
40
- }
41
- });
42
- };
@@ -1,2 +0,0 @@
1
- import { type ComputedView } from '@likec4/core';
2
- export declare function assignNavigateTo<R extends Iterable<ComputedView>>(views: R): R;
@@ -1,27 +0,0 @@
1
- import { isElementView } from '@likec4/core';
2
- import { find, isNullish } from 'remeda';
3
- export function assignNavigateTo(views) {
4
- const allElementViews = new Map();
5
- for (const v of views) {
6
- if (isElementView(v) && v.viewOf && isNullish(v.extends)) {
7
- const viewsOf = allElementViews.get(v.viewOf) ?? [];
8
- viewsOf.push(v.id);
9
- allElementViews.set(v.viewOf, viewsOf);
10
- }
11
- }
12
- // set default navigateTo
13
- for (const { id, nodes } of views) {
14
- for (const node of nodes) {
15
- const modelRef = node.modelRef;
16
- if (node.navigateTo || !modelRef) {
17
- continue;
18
- }
19
- // find first element view that is not the current one
20
- const navigateTo = find(allElementViews.get(modelRef) ?? [], v => v !== id);
21
- if (navigateTo) {
22
- node.navigateTo = navigateTo;
23
- }
24
- }
25
- }
26
- return views;
27
- }
@@ -1,2 +0,0 @@
1
- export * from './assignNavigateTo';
2
- export * from './manual-layout';
@@ -1,2 +0,0 @@
1
- export * from './assignNavigateTo';
2
- export * from './manual-layout';
@@ -1,13 +0,0 @@
1
- import type * as c4 from '@likec4/core';
2
- import { type ViewManualLayout } from '@likec4/core';
3
- import type { ast } from '../ast';
4
- export declare function serializeToComment(layout: ViewManualLayout): string;
5
- export declare function hasManualLayout(comment: string): boolean;
6
- export declare function deserializeFromComment(comment: string): ViewManualLayout;
7
- export declare function parseViewManualLayout(node: ast.LikeC4View): c4.ViewManualLayout | undefined;
8
- /**
9
- * Applies styles from the latest layout to the manual layout
10
- * @param manualLayouted
11
- * @param latest
12
- */
13
- export declare function applyStylesToManualLayout<A extends c4.AnyAux>(manualLayouted: NoInfer<c4.LayoutedView<A>>, latest: c4.ComputedView<A> | c4.LayoutedView<A>): c4.LayoutedView<A>;
@@ -1,149 +0,0 @@
1
- import { exact, isAutoLayoutDirection } from '@likec4/core';
2
- import { decode, encode } from '@msgpack/msgpack';
3
- import { fromBase64, toBase64 } from '@smithy/util-base64';
4
- import { shallowEqual } from 'fast-equals';
5
- import { AstUtils, CstUtils } from 'langium';
6
- import { find, mapValues } from 'remeda';
7
- import { logger, logWarnError } from '../logger';
8
- const { getDocument } = AstUtils;
9
- function pack({ nodes, edges, ...rest }) {
10
- return {
11
- ...rest,
12
- nodes: mapValues(nodes, ({ x, y, width, height, isCompound, ...n }) => ({
13
- ...n,
14
- b: [x, y, width, height],
15
- c: isCompound,
16
- })),
17
- edges: mapValues(edges, ({ points, controlPoints, labelBBox, ...e }) => ({
18
- ...!!controlPoints && { cp: controlPoints },
19
- ...!!labelBBox && { l: labelBBox },
20
- ...e,
21
- p: points,
22
- })),
23
- };
24
- }
25
- function unpack({ nodes, edges, autoLayout, ...rest }) {
26
- return {
27
- ...rest,
28
- /// Try to parse the old format for backward compatibility
29
- autoLayout: isAutoLayoutDirection(autoLayout) ? { direction: autoLayout } : autoLayout,
30
- nodes: mapValues(nodes, ({ b, c, ...n }) => ({
31
- x: b[0],
32
- y: b[1],
33
- width: b[2],
34
- height: b[3],
35
- isCompound: c,
36
- ...n,
37
- })),
38
- edges: mapValues(edges, ({ p, cp, l, ...e }) => ({
39
- ...!!cp && { controlPoints: cp },
40
- ...!!l && { labelBBox: l },
41
- ...e,
42
- points: p,
43
- })),
44
- };
45
- }
46
- const MAX_LINE_LENGTH = 500;
47
- export function serializeToComment(layout) {
48
- const bytes = encode(pack(layout));
49
- const base64 = toBase64(bytes);
50
- const lines = [];
51
- let offset = 0;
52
- while (offset < base64.length) {
53
- lines.push(' * ' + base64.slice(offset, Math.min(offset + MAX_LINE_LENGTH, base64.length)));
54
- offset += MAX_LINE_LENGTH;
55
- }
56
- lines.unshift('/**', ' * @likec4-generated(v1)');
57
- lines.push(' */');
58
- return lines.join('\n');
59
- }
60
- export function hasManualLayout(comment) {
61
- return comment.includes('@likec4-generated');
62
- }
63
- export function deserializeFromComment(comment) {
64
- if (!hasManualLayout(comment)) {
65
- throw new Error(`Not a likec4-generated comment: ${comment}`);
66
- }
67
- const b64 = comment
68
- .trim()
69
- .split('\n')
70
- .filter(l => !l.includes('**') && !l.includes('@likec4-') && !l.includes('*/'))
71
- .map(l => l.replaceAll('*', '').trim())
72
- .join('');
73
- const decodedb64 = fromBase64(b64);
74
- return unpack(decode(decodedb64));
75
- }
76
- export function parseViewManualLayout(node) {
77
- const commentNode = CstUtils.findCommentNode(node.$cstNode, ['BLOCK_COMMENT']);
78
- if (!commentNode || !hasManualLayout(commentNode.text)) {
79
- return undefined;
80
- }
81
- try {
82
- return deserializeFromComment(commentNode.text);
83
- }
84
- catch (e) {
85
- const doc = getDocument(node);
86
- logWarnError(e);
87
- logger.warn(`Ignoring manual layout of "${node.name ?? 'unnamed'}" at ${doc.uri.fsPath}:${1 + (commentNode.range.start.line || 0)}`);
88
- return undefined;
89
- }
90
- }
91
- /**
92
- * Applies styles from the latest layout to the manual layout
93
- * @param manualLayouted
94
- * @param latest
95
- */
96
- export function applyStylesToManualLayout(manualLayouted, latest) {
97
- const nodes = manualLayouted.nodes.map(n => {
98
- const latestNode = find(latest.nodes, l => l.id === n.id);
99
- if (!latestNode) {
100
- return n;
101
- }
102
- const color = latestNode.color;
103
- if (color !== n.color) {
104
- n = {
105
- ...n,
106
- color,
107
- };
108
- }
109
- const { opacity, border } = latestNode.style;
110
- if (opacity !== n.style.opacity || border !== n.style.border) {
111
- n = {
112
- ...n,
113
- style: exact({
114
- ...n.style,
115
- opacity,
116
- border,
117
- }),
118
- };
119
- }
120
- return n;
121
- });
122
- const edges = manualLayouted.edges.map(e => {
123
- const latestEdge = find(latest.edges, l => l.id === e.id);
124
- if (!latestEdge) {
125
- return e;
126
- }
127
- if (latestEdge.color !== e.color) {
128
- e = {
129
- ...e,
130
- color: latestEdge.color,
131
- };
132
- }
133
- if (latestEdge.line !== e.line) {
134
- e = {
135
- ...e,
136
- line: latestEdge.line,
137
- };
138
- }
139
- return e;
140
- });
141
- if (!shallowEqual(manualLayouted.nodes, nodes) || !shallowEqual(manualLayouted.edges, edges)) {
142
- return {
143
- ...manualLayouted,
144
- nodes,
145
- edges,
146
- };
147
- }
148
- return manualLayouted;
149
- }
@@ -1,7 +0,0 @@
1
- import { QueueGraphvizLayoter } from '@likec4/layouts';
2
- import type { LikeC4Services } from '../module';
3
- export declare const ConfigurableLayouter: {
4
- likec4: {
5
- Layouter(services: LikeC4Services): QueueGraphvizLayoter;
6
- };
7
- };
@@ -1,51 +0,0 @@
1
- import { GraphvizWasmAdapter, QueueGraphvizLayoter } from '@likec4/layouts';
2
- import { GraphvizBinaryAdapter } from '@likec4/layouts/graphviz/binary';
3
- import { isEmpty } from 'remeda';
4
- import which from 'which';
5
- import { logger } from '../logger';
6
- function graphvizBinPath() {
7
- try {
8
- return which.sync('dot');
9
- }
10
- catch (error) {
11
- logger.error('Error checking for native Graphviz:', { error });
12
- return null;
13
- }
14
- }
15
- export const ConfigurableLayouter = {
16
- likec4: {
17
- Layouter(services) {
18
- logger.debug('Creating ConfigurableLayouter');
19
- const layouter = new QueueGraphvizLayoter();
20
- services.shared.workspace.ConfigurationProvider.onConfigurationSectionUpdate((update) => {
21
- logger.debug('Configuration update: {update}', { update });
22
- if (update.section !== services.LanguageMetaData.languageId) {
23
- logger.debug(`Ignoring configuration update as it is not for ${services.LanguageMetaData.languageId}`);
24
- return;
25
- }
26
- try {
27
- const { mode, path } = update.configuration.graphviz ?? {
28
- mode: 'wasm',
29
- path: '',
30
- };
31
- if (mode !== 'wasm') {
32
- let binaryPath = isEmpty(path) ? graphvizBinPath() : path;
33
- if (!isEmpty(binaryPath)) {
34
- layouter.changePort(new GraphvizBinaryAdapter(binaryPath));
35
- logger.info `use graphviz binary: ${binaryPath}`;
36
- return;
37
- }
38
- logger.warn(`No Graphviz binaries found on PATH, use graphviz wasm`);
39
- services.shared.lsp.Connection?.window.showWarningMessage('No Graphviz binaries found on PATH, set path to binaries in settings.');
40
- }
41
- layouter.changePort(new GraphvizWasmAdapter());
42
- logger.info('use graphviz wasm');
43
- }
44
- catch (error) {
45
- logger.error('Failed to update configuration', { error });
46
- }
47
- });
48
- return layouter;
49
- },
50
- },
51
- };
@@ -1,42 +0,0 @@
1
- import type { LayoutedView, ProjectId, ViewId } from '@likec4/core';
2
- import { URI, WorkspaceCache } from 'langium';
3
- import { type Location } from 'vscode-languageserver-types';
4
- import type { LikeC4Services } from '../module';
5
- import type { Project } from '../workspace/ProjectsManager';
6
- /**
7
- * @todo sync with vscode extension watchers
8
- * (search for ".likec4.snap" references)
9
- */
10
- export declare const isManualLayoutFile: (path: string) => boolean;
11
- export interface LikeC4ManualLayouts {
12
- read(project: Project): Promise<Record<ViewId, LayoutedView> | null>;
13
- write(project: Project, layouted: LayoutedView): Promise<Location>;
14
- remove(project: Project, view: ViewId): Promise<Location | null>;
15
- clearCaches(): void;
16
- }
17
- export interface LikeC4ManualLayoutsModuleContext {
18
- manualLayouts: (services: LikeC4Services) => LikeC4ManualLayouts;
19
- }
20
- export declare const WithLikeC4ManualLayouts: LikeC4ManualLayoutsModuleContext;
21
- export declare class DefaultLikeC4ManualLayouts implements LikeC4ManualLayouts {
22
- private services;
23
- protected cache: WorkspaceCache<ProjectId, Promise<Record<ViewId, LayoutedView> | null>>;
24
- constructor(services: LikeC4Services);
25
- read(project: Project): Promise<Record<ViewId, LayoutedView> | null>;
26
- write(project: Project, layouted: LayoutedView): Promise<Location>;
27
- remove(project: Project, view: ViewId): Promise<Location | null>;
28
- clearCaches(): void;
29
- /**
30
- * When we save snapshot - it may contain fullpath to icons on the machine it was created,
31
- * that is wrong when opened on another.
32
- *
33
- * Prepares a snapshot for writing by converting absolute icon paths to relative paths.
34
- * Absolute paths starting with 'file://' are converted to relative paths prefixed with 'file://./'
35
- */
36
- protected normalizeIconPathsForWrite(layouted: LayoutedView, projectUri: URI): LayoutedView;
37
- /**
38
- * Postprocesses a snapshot after reading by converting relative icon paths back to absolute paths.
39
- * Relative paths prefixed with 'file://./' are converted to absolute paths based on project folder.
40
- */
41
- protected resolveIconPathsAfterRead(layouted: LayoutedView, projectUri: URI): LayoutedView;
42
- }
@@ -1,209 +0,0 @@
1
- import JSON5 from 'json5';
2
- import { DocumentState, URI, UriUtils, WorkspaceCache } from 'langium';
3
- import { indexBy, prop } from 'remeda';
4
- import { Position, Range, } from 'vscode-languageserver-types';
5
- import { logger as rootLogger } from '../logger';
6
- const layoutsLogger = rootLogger.getChild('manual-layouts');
7
- /**
8
- * @todo sync with vscode extension watchers
9
- * (search for ".likec4.snap" references)
10
- */
11
- export const isManualLayoutFile = (path) => path.endsWith('.likec4.snap');
12
- function fileName(view) {
13
- return `${view}.likec4.snap`;
14
- }
15
- function getManualLayoutsOutDir(project) {
16
- return UriUtils.resolvePath(project.folderUri, project.config.manualLayouts?.outDir ?? '.likec4');
17
- }
18
- export const WithLikeC4ManualLayouts = {
19
- manualLayouts: (services) => new DefaultLikeC4ManualLayouts(services),
20
- };
21
- const RELATIVE_PATH_PREFIX = 'file://./';
22
- export class DefaultLikeC4ManualLayouts {
23
- services;
24
- cache;
25
- constructor(services) {
26
- this.services = services;
27
- this.cache = new WorkspaceCache(services.shared, DocumentState.Validated);
28
- }
29
- async read(project) {
30
- return await this.cache.get(project.id, async () => {
31
- const logger = layoutsLogger.getChild(project.id);
32
- const fs = this.services.shared.workspace.FileSystemProvider;
33
- const outDir = getManualLayoutsOutDir(project);
34
- const manualLayouts = [];
35
- try {
36
- const files = await fs.scanDirectory(outDir, isManualLayoutFile);
37
- if (files.length === 0) {
38
- return null;
39
- }
40
- for (const file of files) {
41
- if (file.isFile) {
42
- try {
43
- const content = await fs.readFile(file.uri);
44
- const parsed = JSON5.parse(content);
45
- const resolved = this.resolveIconPathsAfterRead(parsed, project.folderUri);
46
- manualLayouts.push({
47
- ...resolved,
48
- _layout: 'manual',
49
- });
50
- }
51
- catch (err) {
52
- logger.warn(`Failed to read view snapshot ${file.uri.fsPath}`, { err });
53
- }
54
- }
55
- }
56
- if (manualLayouts.length) {
57
- logger.debug `read manual layouts for ${project.id}, found ${manualLayouts.length}`;
58
- }
59
- }
60
- catch (err) {
61
- logger.warn(`Failed to read manual layouts for ${project.folderUri.fsPath}`, { err });
62
- }
63
- if (manualLayouts.length === 0) {
64
- return null;
65
- }
66
- return indexBy(manualLayouts, prop('id'));
67
- });
68
- }
69
- async write(project, layouted) {
70
- const logger = layoutsLogger.getChild(project.id);
71
- const outDir = getManualLayoutsOutDir(project);
72
- const file = UriUtils.joinPath(outDir, fileName(layouted.id));
73
- // Ensure the manualLayout field is omitted (may exist in migration)
74
- if ('manualLayout' in layouted) {
75
- const { manualLayout: _, ...rest } = layouted;
76
- layouted = rest;
77
- }
78
- const content = JSON5.stringify(
79
- // Normalize icon paths before writing
80
- this.normalizeIconPathsForWrite(layouted, project.folderUri), {
81
- space: 2,
82
- quote: '\'',
83
- });
84
- const location = {
85
- uri: file.toString(),
86
- range: Range.create(Position.create(0, 0), Position.create(content.split('\n').length - 1, 1)),
87
- };
88
- logger.debug `write snapshot of ${layouted.id} in project ${project.id} to ${file.fsPath}`;
89
- const fs = this.services.shared.workspace.FileSystemProvider;
90
- try {
91
- await fs.writeFile(file, content + '\n');
92
- }
93
- catch (err) {
94
- logger.warn(`Failed to write snapshot ${layouted.id} to ${file.fsPath}`, { err });
95
- }
96
- const projectCachesPromise = this.cache.get(project.id);
97
- if (projectCachesPromise) {
98
- const projectCaches = await projectCachesPromise;
99
- if (projectCaches) {
100
- logger.debug `update snapshot cache of ${layouted.id} in project ${project.id}`;
101
- projectCaches[layouted.id] = layouted;
102
- }
103
- else {
104
- logger.debug `clean cache of project ${project.id}`;
105
- // Cache was null, remove it entirely
106
- this.cache.delete(project.id);
107
- }
108
- }
109
- this.services.likec4.ModelBuilder.clearCache();
110
- return location;
111
- }
112
- async remove(project, view) {
113
- const logger = layoutsLogger.getChild(project.id);
114
- const outDir = getManualLayoutsOutDir(project);
115
- const file = UriUtils.joinPath(outDir, fileName(view));
116
- logger.debug `delete snapshot of ${view} in project ${project.id}. File: ${file.fsPath}`;
117
- const location = {
118
- uri: file.toString(),
119
- range: Range.create(0, 0, 0, 0),
120
- };
121
- try {
122
- const fs = this.services.shared.workspace.FileSystemProvider;
123
- if (!(await fs.deleteFile(file))) {
124
- logger.warn `Snapshot ${view} did not exist at ${file.fsPath}`;
125
- return null;
126
- }
127
- }
128
- catch (err) {
129
- logger.warn(`Failed to delete snapshot ${view} from ${file.fsPath}`, { err });
130
- }
131
- const projectCachesPromise = this.cache.get(project.id);
132
- if (projectCachesPromise) {
133
- const projectCaches = await projectCachesPromise;
134
- if (projectCaches) {
135
- logger.debug `clean cached view ${view} in project ${project.id}`;
136
- delete projectCaches[view];
137
- }
138
- else {
139
- logger.debug `reset empty cache of project ${project.id}`;
140
- // Cache was null, remove it entirely
141
- this.cache.delete(project.id);
142
- }
143
- }
144
- this.services.likec4.ModelBuilder.clearCache();
145
- return location;
146
- }
147
- clearCaches() {
148
- this.cache.clear();
149
- }
150
- /**
151
- * When we save snapshot - it may contain fullpath to icons on the machine it was created,
152
- * that is wrong when opened on another.
153
- *
154
- * Prepares a snapshot for writing by converting absolute icon paths to relative paths.
155
- * Absolute paths starting with 'file://' are converted to relative paths prefixed with 'file://./'
156
- */
157
- normalizeIconPathsForWrite(layouted, projectUri) {
158
- const nodes = layouted.nodes.map((node) => {
159
- if (!node.icon || typeof node.icon !== 'string') {
160
- return node;
161
- }
162
- // Check if icon is an absolute file path
163
- if (node.icon.startsWith('file://')) {
164
- const iconUri = URI.parse(node.icon);
165
- // Get relative path from project folder to icon
166
- const relativePath = UriUtils.relative(projectUri, iconUri);
167
- // If icon is outside of project folder - leave it as is,
168
- // to avoid security issues on reading snapshots on another machine
169
- if (relativePath.startsWith('..')) {
170
- return node;
171
- }
172
- return {
173
- ...node,
174
- icon: `${RELATIVE_PATH_PREFIX}${relativePath}`,
175
- };
176
- }
177
- return node;
178
- });
179
- return {
180
- ...layouted,
181
- nodes: nodes,
182
- };
183
- }
184
- /**
185
- * Postprocesses a snapshot after reading by converting relative icon paths back to absolute paths.
186
- * Relative paths prefixed with 'file://./' are converted to absolute paths based on project folder.
187
- */
188
- resolveIconPathsAfterRead(layouted, projectUri) {
189
- const nodes = layouted.nodes.map((node) => {
190
- if (!node.icon || typeof node.icon !== 'string') {
191
- return node;
192
- }
193
- // Check if icon is a relative file path
194
- if (node.icon.startsWith(RELATIVE_PATH_PREFIX)) {
195
- const relativePath = node.icon.substring(RELATIVE_PATH_PREFIX.length);
196
- const absoluteUri = UriUtils.joinPath(projectUri, relativePath);
197
- return {
198
- ...node,
199
- icon: absoluteUri.toString(),
200
- };
201
- }
202
- return node;
203
- });
204
- return {
205
- ...layouted,
206
- nodes: nodes,
207
- };
208
- }
209
- }
@@ -1,89 +0,0 @@
1
- import type { ComputedView, DiagramView, LayoutedView, LayoutType, ProjectId, ViewId } from '@likec4/core';
2
- import { type QueueGraphvizLayoter, GraphvizLayouter } from '@likec4/layouts';
3
- import type { CancellationToken } from 'vscode-languageserver';
4
- import type { LikeC4Services } from '../module';
5
- export type GraphvizOut = {
6
- readonly dot: string;
7
- readonly diagram: LayoutedView;
8
- };
9
- type GraphvizSvgOut = {
10
- readonly id: ViewId;
11
- readonly dot: string;
12
- readonly svg: string;
13
- };
14
- type LayoutViewParams = {
15
- viewId: ViewId;
16
- /**
17
- * Type of layout to apply
18
- * - 'manual' - applies manual layout if any
19
- * - 'auto' - returns latest version with drifts from manual layout if any
20
- * - undefined - returns latest layout as is
21
- */
22
- layoutType?: LayoutType | undefined;
23
- projectId?: ProjectId | undefined;
24
- cancelToken?: CancellationToken | undefined;
25
- };
26
- export interface LikeC4Views {
27
- readonly layouter: GraphvizLayouter;
28
- /**
29
- * Returns computed views (i.e. views with predicates computed)
30
- */
31
- computedViews(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<ComputedView[]>;
32
- /**
33
- * Layouts all views (ignoring any manual snapshots)
34
- */
35
- layoutAllViews(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<GraphvizOut[]>;
36
- /**
37
- * Layouts a view.
38
- * If layoutType is 'manual' - applies manual layout if any.
39
- * If layoutType is 'auto' - returns latest version with drifts from manual layout if any
40
- * If not specified - returns latest layout as is
41
- *
42
- * If view not found in model, but there is a snapshot - it will be returned (with empty DOT)
43
- */
44
- layoutView(params: LayoutViewParams): Promise<GraphvizOut | null>;
45
- /**
46
- * Returns diagrams.
47
- * If diagram has manual layout, it will be used.
48
- */
49
- diagrams(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<Array<DiagramView>>;
50
- /**
51
- * Returns all layouted views as Graphviz output (i.e. views with layout computed)
52
- */
53
- viewsAsGraphvizOut(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<Array<GraphvizSvgOut>>;
54
- /**
55
- * Open view in the preview panel.
56
- * (works only if running as a vscode extension)
57
- */
58
- openView(viewId: ViewId, projectId?: ProjectId | undefined): Promise<void>;
59
- }
60
- export declare class DefaultLikeC4Views implements LikeC4Views {
61
- private services;
62
- private cache;
63
- /**
64
- * Set of viewIds with reported errors
65
- * value is `${projectId}-${viewId}`
66
- */
67
- private viewsWithReportedErrors;
68
- private ModelBuilder;
69
- constructor(services: LikeC4Services);
70
- get layouter(): QueueGraphvizLayoter;
71
- computedViews(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<ComputedView[]>;
72
- private _layoutAllViews;
73
- layoutAllViews(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<GraphvizOut[]>;
74
- layoutView({ viewId, layoutType, projectId, cancelToken, }: LayoutViewParams): Promise<GraphvizOut | null>;
75
- diagrams(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<Array<LayoutedView>>;
76
- viewsAsGraphvizOut(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<Array<GraphvizSvgOut>>;
77
- /**
78
- * Open a view in the preview panel.
79
- */
80
- openView(viewId: ViewId, projectId: ProjectId): Promise<void>;
81
- private reportViewError;
82
- /**
83
- * Applies manual layout or calculates drifts from snapshot
84
- * if layoutType is specified
85
- */
86
- private withLayoutType;
87
- private viewSucceed;
88
- }
89
- export {};