@likec4/language-server 1.21.1 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +4 -1
  2. package/bin/likec4-language-server.mjs +5 -2
  3. package/dist/LikeC4FileSystem.js +2 -2
  4. package/dist/browser.d.ts +3 -3
  5. package/dist/browser.js +17 -2
  6. package/dist/bundled.d.ts +8 -0
  7. package/dist/bundled.js +25 -0
  8. package/dist/bundled.mjs +2555 -4022
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.js +23 -2
  11. package/dist/logger.d.ts +9 -3
  12. package/dist/logger.js +35 -55
  13. package/dist/model/fqn-computation.js +2 -2
  14. package/dist/model/model-builder.js +13 -14
  15. package/dist/model-change/ModelChanges.js +2 -2
  16. package/dist/module.js +1 -4
  17. package/dist/references/scope-provider.js +3 -3
  18. package/dist/view-utils/manual-layout.js +2 -2
  19. package/dist/views/configurable-layouter.js +4 -4
  20. package/dist/views/likec4-views.d.ts +2 -1
  21. package/dist/views/likec4-views.js +2 -2
  22. package/package.json +14 -12
  23. package/dist/test/setup.d.ts +0 -1
  24. package/dist/test/setup.js +0 -7
  25. package/src/LikeC4FileSystem.ts +0 -38
  26. package/src/Rpc.ts +0 -134
  27. package/src/ast.ts +0 -556
  28. package/src/browser.ts +0 -35
  29. package/src/documentation/documentation-provider.ts +0 -52
  30. package/src/documentation/index.ts +0 -1
  31. package/src/formatting/LikeC4Formatter.ts +0 -639
  32. package/src/formatting/utils.ts +0 -26
  33. package/src/generated/ast.ts +0 -3735
  34. package/src/generated/grammar.ts +0 -10
  35. package/src/generated/module.ts +0 -33
  36. package/src/generated-lib/icons.ts +0 -1538
  37. package/src/index.ts +0 -30
  38. package/src/like-c4.langium +0 -901
  39. package/src/likec4lib.ts +0 -6
  40. package/src/logger.ts +0 -80
  41. package/src/lsp/CodeLensProvider.ts +0 -50
  42. package/src/lsp/CompletionProvider.ts +0 -147
  43. package/src/lsp/DocumentHighlightProvider.ts +0 -12
  44. package/src/lsp/DocumentLinkProvider.ts +0 -65
  45. package/src/lsp/DocumentSymbolProvider.ts +0 -313
  46. package/src/lsp/HoverProvider.ts +0 -92
  47. package/src/lsp/RenameProvider.ts +0 -8
  48. package/src/lsp/SemanticTokenProvider.ts +0 -383
  49. package/src/lsp/index.ts +0 -8
  50. package/src/model/deployments-index.ts +0 -209
  51. package/src/model/fqn-computation.ts +0 -83
  52. package/src/model/fqn-index.ts +0 -138
  53. package/src/model/index.ts +0 -6
  54. package/src/model/model-builder.ts +0 -724
  55. package/src/model/model-locator.ts +0 -146
  56. package/src/model/model-parser-where.ts +0 -84
  57. package/src/model/model-parser.ts +0 -86
  58. package/src/model/parser/Base.ts +0 -113
  59. package/src/model/parser/DeploymentModelParser.ts +0 -192
  60. package/src/model/parser/DeploymentViewParser.ts +0 -122
  61. package/src/model/parser/FqnRefParser.ts +0 -143
  62. package/src/model/parser/GlobalsParser.ts +0 -96
  63. package/src/model/parser/ModelParser.ts +0 -170
  64. package/src/model/parser/PredicatesParser.ts +0 -315
  65. package/src/model/parser/SpecificationParser.ts +0 -133
  66. package/src/model/parser/ViewsParser.ts +0 -428
  67. package/src/model-change/ModelChanges.ts +0 -101
  68. package/src/model-change/changeElementStyle.ts +0 -172
  69. package/src/model-change/changeViewLayout.ts +0 -47
  70. package/src/model-change/saveManualLayout.ts +0 -41
  71. package/src/module.ts +0 -255
  72. package/src/protocol.ts +0 -93
  73. package/src/references/index.ts +0 -3
  74. package/src/references/name-provider.ts +0 -37
  75. package/src/references/scope-computation.ts +0 -364
  76. package/src/references/scope-provider.ts +0 -201
  77. package/src/shared/NodeKindProvider.ts +0 -121
  78. package/src/shared/WorkspaceManager.ts +0 -48
  79. package/src/shared/WorkspaceSymbolProvider.ts +0 -3
  80. package/src/shared/index.ts +0 -3
  81. package/src/test/index.ts +0 -1
  82. package/src/test/setup.ts +0 -8
  83. package/src/test/testServices.ts +0 -152
  84. package/src/utils/disposable.ts +0 -30
  85. package/src/utils/elementRef.ts +0 -26
  86. package/src/utils/fqnRef.ts +0 -56
  87. package/src/utils/index.ts +0 -2
  88. package/src/utils/printDocs.ts +0 -3
  89. package/src/utils/stringHash.ts +0 -6
  90. package/src/validation/_shared.ts +0 -29
  91. package/src/validation/deployment-checks.ts +0 -131
  92. package/src/validation/dynamic-view-rule.ts +0 -23
  93. package/src/validation/dynamic-view-step.ts +0 -36
  94. package/src/validation/element.ts +0 -56
  95. package/src/validation/index.ts +0 -171
  96. package/src/validation/property-checks.ts +0 -52
  97. package/src/validation/relation.ts +0 -63
  98. package/src/validation/specification.ts +0 -205
  99. package/src/validation/view-predicates/element-with.ts +0 -36
  100. package/src/validation/view-predicates/expanded-element.ts +0 -16
  101. package/src/validation/view-predicates/expression-v2.ts +0 -101
  102. package/src/validation/view-predicates/incoming.ts +0 -20
  103. package/src/validation/view-predicates/index.ts +0 -6
  104. package/src/validation/view-predicates/outgoing.ts +0 -20
  105. package/src/validation/view-predicates/relation-with.ts +0 -17
  106. package/src/validation/view.ts +0 -37
  107. package/src/view-utils/assignNavigateTo.ts +0 -31
  108. package/src/view-utils/index.ts +0 -2
  109. package/src/view-utils/manual-layout.ts +0 -116
  110. package/src/view-utils/resolve-relative-paths.ts +0 -90
  111. package/src/views/configurable-layouter.ts +0 -65
  112. package/src/views/index.ts +0 -1
  113. package/src/views/likec4-views.ts +0 -139
@@ -1,146 +0,0 @@
1
- import type * as c4 from '@likec4/core'
2
- import type { LangiumDocuments } from 'langium'
3
- import { AstUtils, GrammarUtils } from 'langium'
4
- import { isString } from 'remeda'
5
- import type { Location } from 'vscode-languageserver-types'
6
- import type { ParsedAstElement } from '../ast'
7
- import { ast, isParsedLikeC4LangiumDocument } from '../ast'
8
- import type { LikeC4Services } from '../module'
9
- import type { DeploymentsIndex } from './deployments-index'
10
- import { type FqnIndex } from './fqn-index'
11
-
12
- const { findNodeForKeyword, findNodeForProperty } = GrammarUtils
13
- const { getDocument } = AstUtils
14
-
15
- export class LikeC4ModelLocator {
16
- private fqnIndex: FqnIndex
17
- private deploymentsIndex: DeploymentsIndex
18
- private langiumDocuments: LangiumDocuments
19
-
20
- constructor(private services: LikeC4Services) {
21
- this.fqnIndex = services.likec4.FqnIndex
22
- this.deploymentsIndex = services.likec4.DeploymentsIndex
23
- this.langiumDocuments = services.shared.workspace.LangiumDocuments
24
- }
25
-
26
- private documents() {
27
- return this.langiumDocuments.all.filter(isParsedLikeC4LangiumDocument)
28
- }
29
-
30
- public getParsedElement(astNodeOrFqn: ast.Element | c4.Fqn): ParsedAstElement | null {
31
- if (isString(astNodeOrFqn)) {
32
- const fqn = astNodeOrFqn
33
- const entry = this.fqnIndex.byFqn(astNodeOrFqn).head()
34
- if (!entry) {
35
- return null
36
- }
37
- const doc = this.langiumDocuments.getDocument(entry.documentUri)
38
- if (!doc || !isParsedLikeC4LangiumDocument(doc)) {
39
- return null
40
- }
41
- return doc.c4Elements.find(e => e.id === fqn) ?? null
42
- }
43
-
44
- const fqn = this.fqnIndex.getFqn(astNodeOrFqn)
45
- if (!fqn) return null
46
- const doc = getDocument(astNodeOrFqn)
47
- if (!isParsedLikeC4LangiumDocument(doc)) {
48
- return null
49
- }
50
- return doc.c4Elements.find(e => e.id === fqn) ?? null
51
- }
52
-
53
- public locateElement(fqn: c4.Fqn, _prop?: string): Location | null {
54
- const entry = this.fqnIndex.byFqn(fqn).head()
55
- const docsegment = entry?.nameSegment ?? entry?.selectionSegment
56
- if (!entry || !docsegment) {
57
- return null
58
- }
59
- return {
60
- uri: entry.documentUri.toString(),
61
- range: docsegment.range
62
- }
63
- }
64
- public locateDeploymentElement(fqn: c4.Fqn, _prop?: string): Location | null {
65
- const entry = this.deploymentsIndex.byFqn(fqn).head()
66
- const docsegment = entry?.nameSegment ?? entry?.selectionSegment
67
- if (!entry || !docsegment) {
68
- return null
69
- }
70
- return {
71
- uri: entry.documentUri.toString(),
72
- range: docsegment.range
73
- }
74
- }
75
-
76
- public locateRelation(relationId: c4.RelationId): Location | null {
77
- for (const doc of this.documents()) {
78
- const relation = doc.c4Relations.find(r => r.id === relationId)
79
- ?? doc.c4DeploymentRelations.find(r => r.id === relationId)
80
- if (!relation) {
81
- continue
82
- }
83
- const node = this.services.workspace.AstNodeLocator.getAstNode(
84
- doc.parseResult.value,
85
- relation.astPath
86
- )
87
- if (!ast.isRelation(node) && !ast.isDeploymentRelation(node)) {
88
- continue
89
- }
90
-
91
- let targetNode = node.title ? findNodeForProperty(node.$cstNode, 'title') : undefined
92
- targetNode ??= node.kind ? findNodeForProperty(node.$cstNode, 'kind') : undefined
93
- targetNode ??= findNodeForProperty(node.$cstNode, 'target')
94
- targetNode ??= node.$cstNode
95
-
96
- if (!targetNode) {
97
- continue
98
- }
99
-
100
- return {
101
- uri: doc.uri.toString(),
102
- range: targetNode.range
103
- }
104
- }
105
- return null
106
- }
107
-
108
- public locateViewAst(viewId: c4.ViewId) {
109
- for (const doc of this.documents()) {
110
- const view = doc.c4Views.find(r => r.id === viewId)
111
- if (!view) {
112
- continue
113
- }
114
- const viewAst = this.services.workspace.AstNodeLocator.getAstNode(
115
- doc.parseResult.value,
116
- view.astPath
117
- )
118
- if (ast.isLikeC4View(viewAst)) {
119
- return {
120
- doc,
121
- view,
122
- viewAst
123
- }
124
- }
125
- }
126
- return null
127
- }
128
-
129
- public locateView(viewId: c4.ViewId): Location | null {
130
- const res = this.locateViewAst(viewId)
131
- if (!res) {
132
- return null
133
- }
134
- const node = res.viewAst
135
- let targetNode = node.name ? findNodeForProperty(node.$cstNode, 'name') : undefined
136
- targetNode ??= findNodeForKeyword(node.$cstNode, 'view')
137
- targetNode ??= node.$cstNode
138
- if (!targetNode) {
139
- return null
140
- }
141
- return {
142
- uri: res.doc.uri.toString(),
143
- range: targetNode.range
144
- }
145
- }
146
- }
@@ -1,84 +0,0 @@
1
- import { invariant, isNonEmptyArray, nonexhaustive } from '@likec4/core'
2
- import { isAndOperator, isOrOperator } from '@likec4/core'
3
- import type * as c4 from '@likec4/core'
4
- import { ast } from '../ast'
5
-
6
- const parseEquals = (
7
- { operator, not }: ast.WhereKindEqual | ast.WhereTagEqual,
8
- value: string,
9
- ): c4.EqualOperator<string> => {
10
- if (operator.startsWith('!=')) {
11
- return {
12
- neq: value,
13
- }
14
- }
15
- if (operator.startsWith('=')) {
16
- return {
17
- eq: value,
18
- }
19
- }
20
- return not ? { neq: value } : { eq: value }
21
- }
22
-
23
- function parseParticipant(astNode: ast.WhereExpression): ast.Participant | null {
24
- if (!ast.isWhereRelationParticipantKind(astNode) && !ast.isWhereRelationParticipantTag(astNode)) {
25
- return null
26
- }
27
-
28
- return astNode.participant
29
- }
30
-
31
- export function parseWhereClause(astNode: ast.WhereExpression): c4.WhereOperator<string, string> {
32
- switch (true) {
33
- case ast.isWhereTagEqual(astNode): {
34
- const tag = astNode.value?.ref?.name
35
- const participant = parseParticipant(astNode)
36
- invariant(tag, 'Expected tag name')
37
- const tagOperator = { tag: parseEquals(astNode, tag) }
38
- return participant ? { participant, operator: tagOperator } : tagOperator
39
- }
40
- case ast.isWhereKindEqual(astNode): {
41
- const kind = astNode.value?.ref?.name
42
- const participant = parseParticipant(astNode)
43
- invariant(kind, 'Expected kind name')
44
- const kindOperator = { kind: parseEquals(astNode, kind) }
45
- return participant ? { participant, operator: kindOperator } : kindOperator
46
- }
47
- case ast.isWhereElementNegation(astNode) || ast.isWhereRelationNegation(astNode): {
48
- return {
49
- not: parseWhereClause(astNode.value),
50
- }
51
- }
52
- case ast.isWhereBinaryExpression(astNode): {
53
- const left = parseWhereClause(astNode.left)
54
- const right = parseWhereClause(astNode.right)
55
- const operator = astNode.operator.toLowerCase() as Lowercase<ast.WhereBinaryExpression['operator']>
56
- switch (operator) {
57
- case 'and': {
58
- const operands = [
59
- isAndOperator(left) ? left.and : left,
60
- isAndOperator(right) ? right.and : right,
61
- ].flat()
62
- invariant(isNonEmptyArray(operands), 'Expected non-empty array')
63
- return {
64
- and: operands,
65
- }
66
- }
67
- case 'or': {
68
- const operands = [
69
- isOrOperator(left) ? left.or : left,
70
- isOrOperator(right) ? right.or : right,
71
- ].flat()
72
- invariant(isNonEmptyArray(operands), 'Expected non-empty array')
73
- return {
74
- or: operands,
75
- }
76
- }
77
- default:
78
- nonexhaustive(operator)
79
- }
80
- }
81
- default:
82
- nonexhaustive(astNode)
83
- }
84
- }
@@ -1,86 +0,0 @@
1
- import { invariant } from '@likec4/core'
2
- import { type LangiumDocument, DocumentCache, DocumentState } from 'langium'
3
- import { DefaultWeakMap } from 'mnemonist'
4
- import { pipe } from 'remeda'
5
- import type { LikeC4DocumentProps, ParsedLikeC4LangiumDocument } from '../ast'
6
- import { isFqnIndexedDocument } from '../ast'
7
- import type { LikeC4Services } from '../module'
8
- import { BaseParser } from './parser/Base'
9
- import { DeploymentModelParser } from './parser/DeploymentModelParser'
10
- import { DeploymentViewParser } from './parser/DeploymentViewParser'
11
- import { ExpressionV2Parser } from './parser/FqnRefParser'
12
- import { GlobalsParser } from './parser/GlobalsParser'
13
- import { ModelParser } from './parser/ModelParser'
14
- import { PredicatesParser } from './parser/PredicatesParser'
15
- import { SpecificationParser } from './parser/SpecificationParser'
16
- import { ViewsParser } from './parser/ViewsParser'
17
-
18
- export type ModelParsedListener = () => void
19
-
20
- const DocumentParserFromMixins = pipe(
21
- BaseParser,
22
- ExpressionV2Parser,
23
- ModelParser,
24
- DeploymentModelParser,
25
- DeploymentViewParser,
26
- PredicatesParser,
27
- SpecificationParser,
28
- ViewsParser,
29
- GlobalsParser,
30
- )
31
-
32
- export class DocumentParser extends DocumentParserFromMixins {
33
- }
34
-
35
- export class LikeC4ModelParser {
36
- private cachedParsers: DocumentCache<string, DocumentParser>
37
-
38
- constructor(private services: LikeC4Services) {
39
- this.cachedParsers = new DocumentCache(services.shared, DocumentState.Validated)
40
- }
41
-
42
- parse(doc: LangiumDocument): ParsedLikeC4LangiumDocument {
43
- invariant(isFqnIndexedDocument(doc), `Not a FqnIndexedDocument: ${doc.uri.toString(true)}`)
44
- try {
45
- const props: Required<Omit<LikeC4DocumentProps, 'c4fqnIndex' | 'diagnostics'>> = {
46
- c4Specification: {
47
- tags: new Set(),
48
- elements: {},
49
- relationships: {},
50
- colors: {},
51
- deployments: {},
52
- },
53
- c4Elements: [],
54
- c4ExtendElements: [],
55
- c4Relations: [],
56
- c4Deployments: [],
57
- c4DeploymentRelations: [],
58
- c4Globals: {
59
- predicates: {},
60
- dynamicPredicates: {},
61
- styles: {},
62
- },
63
- c4Views: [],
64
- }
65
- doc = Object.assign(doc, props)
66
- const parser = this.forDocument(doc)
67
- parser.parseSpecification()
68
- parser.parseModel()
69
- parser.parseGlobals()
70
- parser.parseDeployment()
71
- parser.parseViews()
72
- return parser.doc
73
- } catch (cause) {
74
- throw new Error(`Error parsing document ${doc.uri.toString()}`, { cause })
75
- }
76
- }
77
-
78
- forDocument(doc: LangiumDocument): DocumentParser {
79
- invariant(isFqnIndexedDocument(doc), `Not a FqnIndexedDocument: ${doc.uri.toString(true)}`)
80
- return this.cachedParsers.get(
81
- doc.uri,
82
- 'DocumentParser',
83
- () => new DocumentParser(this.services, doc as ParsedLikeC4LangiumDocument),
84
- )
85
- }
86
- }
@@ -1,113 +0,0 @@
1
- import type * as c4 from '@likec4/core'
2
- import { invariant, isNonEmptyArray } from '@likec4/core'
3
- import type { AstNode } from 'langium'
4
- import { filter, flatMap, fromEntries, isEmpty, isNonNullish, isTruthy, map, pipe, unique } from 'remeda'
5
- import stripIndent from 'strip-indent'
6
- import { type ParsedLikeC4LangiumDocument, type ParsedLink, ast } from '../../ast'
7
- import type { LikeC4Services } from '../../module'
8
- import { getFqnElementRef } from '../../utils/elementRef'
9
- import { type IsValidFn, checksFromDiagnostics } from '../../validation'
10
-
11
- // the class which this mixin is applied to
12
- export type GConstructor<T = {}> = new(...args: any[]) => T
13
-
14
- export function toSingleLine<T extends string | undefined | null>(str: T): T {
15
- return (isNonNullish(str) ? removeIndent(str).split('\n').join(' ') : undefined) as T
16
- }
17
-
18
- export function removeIndent<T extends string | undefined | null>(str: T): T {
19
- return (isNonNullish(str) ? stripIndent(str).trim() : undefined) as T
20
- }
21
-
22
- export type Base = GConstructor<BaseParser>
23
-
24
- export class BaseParser {
25
- isValid: IsValidFn
26
-
27
- constructor(
28
- public readonly services: LikeC4Services,
29
- public readonly doc: ParsedLikeC4LangiumDocument,
30
- ) {
31
- // do nothing
32
- this.isValid = checksFromDiagnostics(doc).isValid
33
- }
34
-
35
- resolveFqn(node: ast.FqnReferenceable): c4.Fqn {
36
- if (ast.isDeploymentElement(node)) {
37
- return this.services.likec4.DeploymentsIndex.getFqn(node)
38
- }
39
- if (ast.isExtendElement(node)) {
40
- return getFqnElementRef(node.element)
41
- }
42
- const fqn = this.services.likec4.FqnIndex.getFqn(node)
43
- invariant(fqn, `Not indexed element: ${this.getAstNodePath(node)}`)
44
- return fqn
45
- }
46
-
47
- getAstNodePath(node: AstNode) {
48
- return this.services.workspace.AstNodeLocator.getAstNodePath(node)
49
- }
50
-
51
- getMetadata(metadataAstNode: ast.MetadataProperty | undefined): { [key: string]: string } | undefined {
52
- if (!metadataAstNode || !this.isValid(metadataAstNode) || isEmpty(metadataAstNode.props)) {
53
- return undefined
54
- }
55
- const data = pipe(
56
- metadataAstNode.props,
57
- map(p => [p.key, removeIndent(p.value)] as [string, string]),
58
- filter(([_, value]) => isTruthy(value)),
59
- fromEntries(),
60
- )
61
- return isEmpty(data) ? undefined : data
62
- }
63
-
64
- convertTags<E extends { tags?: ast.Tags }>(withTags?: E) {
65
- return this.parseTags(withTags)
66
- }
67
- parseTags<E extends { tags?: ast.Tags }>(withTags?: E): c4.NonEmptyArray<c4.Tag> | null {
68
- let iter = withTags?.tags
69
- if (!iter) {
70
- return null
71
- }
72
- let tags = [] as c4.Tag[]
73
- while (iter) {
74
- try {
75
- if (this.isValid(iter)) {
76
- const values = iter.values.map(t => t.ref?.name).filter(isTruthy) as c4.Tag[]
77
- if (values.length > 0) {
78
- tags.push(...values)
79
- }
80
- }
81
- } catch (e) {
82
- // ignore
83
- }
84
- iter = iter.prev
85
- }
86
- tags = unique(tags.reverse())
87
- return isNonEmptyArray(tags) ? tags : null
88
- }
89
-
90
- convertLinks(source?: ast.LinkProperty['$container']): ParsedLink[] | undefined {
91
- return this.parseLinks(source)
92
- }
93
- parseLinks(source?: ast.LinkProperty['$container']): ParsedLink[] | undefined {
94
- if (!source?.props || source.props.length === 0) {
95
- return undefined
96
- }
97
- return pipe(
98
- source.props,
99
- filter(ast.isLinkProperty),
100
- flatMap(p => {
101
- if (!this.isValid(p)) {
102
- return []
103
- }
104
- const url = p.value
105
- if (isTruthy(url)) {
106
- const title = isTruthy(p.title) ? toSingleLine(p.title) : undefined
107
- return title ? { url, title } : { url }
108
- }
109
- return []
110
- }),
111
- )
112
- }
113
- }
@@ -1,192 +0,0 @@
1
- import type * as c4 from '@likec4/core'
2
- import { FqnRef, isNonEmptyArray, nameFromFqn, nonexhaustive, nonNullable } from '@likec4/core'
3
- import { filter, first, isTruthy, map, mapToObj, pipe } from 'remeda'
4
- import {
5
- type ParsedAstDeployment,
6
- type ParsedAstDeploymentRelation,
7
- ast,
8
- streamDeploymentModel,
9
- toElementStyle,
10
- toRelationshipStyleExcludeDefaults,
11
- } from '../../ast'
12
- import { logWarnError } from '../../logger'
13
- import { elementRef } from '../../utils/elementRef'
14
- import { stringHash } from '../../utils/stringHash'
15
- import { removeIndent, toSingleLine } from './Base'
16
- import type { WithExpressionV2 } from './FqnRefParser'
17
-
18
- export type WithDeploymentModel = ReturnType<typeof DeploymentModelParser>
19
-
20
- export function DeploymentModelParser<TBase extends WithExpressionV2>(B: TBase) {
21
- return class DeploymentModelParser extends B {
22
- parseDeployment() {
23
- const doc = this.doc
24
- for (const el of streamDeploymentModel(doc)) {
25
- try {
26
- switch (true) {
27
- case ast.isDeploymentRelation(el): {
28
- if (this.isValid(el)) {
29
- doc.c4DeploymentRelations.push(this.parseDeploymentRelation(el))
30
- }
31
- break
32
- }
33
- case ast.isDeployedInstance(el):
34
- doc.c4Deployments.push(this.parseDeployedInstance(el))
35
- break
36
- case ast.isDeploymentNode(el): {
37
- doc.c4Deployments.push(this.parseDeploymentNode(el))
38
- break
39
- }
40
- default:
41
- nonexhaustive(el)
42
- }
43
- } catch (e) {
44
- logWarnError(e)
45
- }
46
- }
47
- }
48
-
49
- parseDeploymentNode(astNode: ast.DeploymentNode): ParsedAstDeployment.Node {
50
- const isValid = this.isValid
51
- const id = this.resolveFqn(astNode)
52
- const kind = nonNullable(astNode.kind.ref, 'DeploymentKind not resolved').name as c4.DeploymentNodeKind
53
- const tags = this.convertTags(astNode.body)
54
- const stylePropsAst = astNode.body?.props.find(ast.isElementStyleProperty)?.props
55
- const style = toElementStyle(stylePropsAst, isValid)
56
- const metadata = this.getMetadata(astNode.body?.props.find(ast.isMetadataProperty))
57
-
58
- const bodyProps = pipe(
59
- astNode.body?.props ?? [],
60
- filter(isValid),
61
- filter(ast.isElementStringProperty),
62
- mapToObj(p => [p.key, p.value || undefined]),
63
- )
64
-
65
- const title = removeIndent(astNode.title ?? bodyProps.title)
66
- const description = removeIndent(bodyProps.description)
67
- const technology = toSingleLine(bodyProps.technology)
68
-
69
- const links = this.convertLinks(astNode.body)
70
-
71
- // Property has higher priority than from style
72
- const iconProp = astNode.body?.props.find(ast.isIconProperty)
73
- if (iconProp && isValid(iconProp)) {
74
- const value = iconProp.libicon?.ref?.name ?? iconProp.value
75
- if (isTruthy(value)) {
76
- style.icon = value as c4.IconUrl
77
- }
78
- }
79
-
80
- return {
81
- id,
82
- kind,
83
- title: title ?? nameFromFqn(id),
84
- ...(metadata && { metadata }),
85
- ...(tags && { tags }),
86
- ...(links && isNonEmptyArray(links) && { links }),
87
- ...(isTruthy(technology) && { technology }),
88
- ...(isTruthy(description) && { description }),
89
- style,
90
- }
91
- }
92
-
93
- parseDeployedInstance(astNode: ast.DeployedInstance): ParsedAstDeployment.Instance {
94
- const isValid = this.isValid
95
- const id = this.resolveFqn(astNode)
96
- const element = this.resolveFqn(nonNullable(elementRef(astNode.element), 'DeployedInstance element not found'))
97
-
98
- const tags = this.convertTags(astNode.body)
99
- const stylePropsAst = astNode.body?.props.find(ast.isElementStyleProperty)?.props
100
- const style = toElementStyle(stylePropsAst, isValid)
101
- const metadata = this.getMetadata(astNode.body?.props.find(ast.isMetadataProperty))
102
-
103
- const bodyProps = pipe(
104
- astNode.body?.props ?? [],
105
- filter(isValid),
106
- filter(ast.isElementStringProperty),
107
- mapToObj(p => [p.key, p.value || undefined]),
108
- )
109
-
110
- const title = removeIndent(astNode.title ?? bodyProps.title)
111
- const description = removeIndent(bodyProps.description)
112
- const technology = toSingleLine(bodyProps.technology)
113
-
114
- const links = this.convertLinks(astNode.body)
115
-
116
- // Property has higher priority than from style
117
- const iconProp = astNode.body?.props.find(ast.isIconProperty)
118
- if (iconProp && isValid(iconProp)) {
119
- const value = iconProp.libicon?.ref?.name ?? iconProp.value
120
- if (isTruthy(value)) {
121
- style.icon = value as c4.IconUrl
122
- }
123
- }
124
-
125
- return {
126
- id,
127
- element,
128
- ...(metadata && { metadata }),
129
- ...(title && { title }),
130
- ...(tags && { tags }),
131
- ...(links && isNonEmptyArray(links) && { links }),
132
- ...(isTruthy(technology) && { technology }),
133
- ...(isTruthy(description) && { description }),
134
- style,
135
- }
136
- }
137
-
138
- parseDeploymentRelation(astNode: ast.DeploymentRelation): ParsedAstDeploymentRelation {
139
- const isValid = this.isValid
140
- const astPath = this.getAstNodePath(astNode)
141
- const source = FqnRef.toDeploymentRef(this.parseFqnRef(astNode.source))
142
- const target = FqnRef.toDeploymentRef(this.parseFqnRef(astNode.target))
143
-
144
- const tags = this.convertTags(astNode) ?? this.convertTags(astNode.body)
145
- const links = this.convertLinks(astNode.body)
146
- const kind = astNode.kind?.ref?.name as (c4.RelationshipKind | undefined)
147
- const metadata = this.getMetadata(astNode.body?.props.find(ast.isMetadataProperty))
148
-
149
- const bodyProps = mapToObj(
150
- astNode.body?.props.filter(ast.isRelationStringProperty) ?? [],
151
- p => [p.key, p.value as string | undefined],
152
- )
153
-
154
- const navigateTo = pipe(
155
- astNode.body?.props ?? [],
156
- filter(ast.isRelationNavigateToProperty),
157
- map(p => p.value.view.ref?.name),
158
- filter(isTruthy),
159
- first(),
160
- )
161
-
162
- const title = removeIndent(astNode.title ?? bodyProps.title)
163
- const description = removeIndent(bodyProps.description)
164
- const technology = toSingleLine(astNode.technology) ?? removeIndent(bodyProps.technology)
165
-
166
- const styleProp = astNode.body?.props.find(ast.isRelationStyleProperty)
167
-
168
- const id = stringHash(
169
- 'deployment',
170
- astPath,
171
- source.id,
172
- target.id,
173
- ) as c4.RelationId
174
-
175
- return {
176
- id,
177
- source,
178
- target,
179
- ...title && { title },
180
- ...(metadata && { metadata }),
181
- ...(isTruthy(technology) && { technology }),
182
- ...(isTruthy(description) && { description }),
183
- ...(kind && { kind }),
184
- ...(tags && { tags }),
185
- ...(isNonEmptyArray(links) && { links }),
186
- ...toRelationshipStyleExcludeDefaults(styleProp?.props, isValid),
187
- ...(navigateTo && { navigateTo: navigateTo as c4.ViewId }),
188
- astPath,
189
- }
190
- }
191
- }
192
- }