@likec4/core 1.17.1 → 1.18.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 (112) hide show
  1. package/dist/compute-view/index.d.mts +91 -0
  2. package/dist/compute-view/index.d.ts +91 -0
  3. package/dist/compute-view/index.mjs +79 -0
  4. package/dist/index.d.mts +246 -434
  5. package/dist/index.d.ts +246 -434
  6. package/dist/index.mjs +418 -1322
  7. package/dist/model/index.d.mts +642 -0
  8. package/dist/model/index.d.ts +642 -0
  9. package/dist/model/index.mjs +2 -0
  10. package/dist/shared/core.BBgiAAv1.mjs +144 -0
  11. package/dist/shared/core.BPyJvuMU.mjs +2420 -0
  12. package/dist/shared/core.BQ4AbfvB.mjs +9228 -0
  13. package/dist/shared/{core.CoLQkcYL.d.mts → core.DMYY7C8s.d.mts} +398 -249
  14. package/dist/shared/{core.CoLQkcYL.d.ts → core.DMYY7C8s.d.ts} +398 -249
  15. package/dist/shared/core.k12s_keD.mjs +203 -0
  16. package/dist/types/index.d.mts +69 -1
  17. package/dist/types/index.d.ts +69 -1
  18. package/dist/types/index.mjs +21 -1
  19. package/package.json +38 -40
  20. package/src/builder/Builder.deployment.ts +219 -0
  21. package/src/builder/Builder.deploymentModel.ts +360 -0
  22. package/src/builder/Builder.element.ts +17 -19
  23. package/src/builder/Builder.model.ts +13 -2
  24. package/src/builder/Builder.test-d.ts +59 -4
  25. package/src/builder/Builder.ts +238 -53
  26. package/src/builder/Builder.view.ts +238 -53
  27. package/src/builder/_types.ts +87 -15
  28. package/src/compute-view/LikeC4ModelGraph.ts +330 -0
  29. package/src/compute-view/compute-view.ts +92 -0
  30. package/src/compute-view/deployment-view/Memory.ts +108 -0
  31. package/src/compute-view/deployment-view/Stage.ts +145 -0
  32. package/src/compute-view/deployment-view/__test__/fixture.ts +210 -0
  33. package/src/compute-view/deployment-view/_types.ts +29 -0
  34. package/src/compute-view/deployment-view/clean-connections.ts +229 -0
  35. package/src/compute-view/deployment-view/compute.ts +111 -0
  36. package/src/compute-view/deployment-view/predicates/deployment-ref.ts +146 -0
  37. package/src/compute-view/deployment-view/predicates/relation-direct.ts +130 -0
  38. package/src/compute-view/deployment-view/predicates/relation-in-out.ts +43 -0
  39. package/src/compute-view/deployment-view/predicates/relation-incoming.ts +46 -0
  40. package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +49 -0
  41. package/src/compute-view/deployment-view/predicates/wildcard.ts +29 -0
  42. package/src/compute-view/deployment-view/utils.ts +212 -0
  43. package/src/compute-view/dynamic-view/__test__/fixture.ts +58 -0
  44. package/src/compute-view/dynamic-view/compute.ts +310 -0
  45. package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +456 -0
  46. package/src/compute-view/element-view/__test__/fixture.ts +645 -0
  47. package/src/compute-view/element-view/compute.ts +734 -0
  48. package/src/compute-view/element-view/predicates.ts +517 -0
  49. package/src/compute-view/index.ts +5 -0
  50. package/src/compute-view/utils/__snapshots__/sortNodes.spec.ts.snap +113 -0
  51. package/src/compute-view/utils/ancestorsOfNode.ts +19 -0
  52. package/src/compute-view/utils/applyCustomElementProperties.ts +66 -0
  53. package/src/compute-view/utils/applyCustomRelationProperties.ts +41 -0
  54. package/src/compute-view/utils/applyViewRuleStyles.ts +53 -0
  55. package/src/compute-view/utils/buildComputedNodes.ts +148 -0
  56. package/src/compute-view/utils/buildElementNotations.ts +63 -0
  57. package/src/compute-view/utils/derive-edge-props-from-relationships.ts +97 -0
  58. package/src/compute-view/utils/elementExpressionToPredicate.ts +52 -0
  59. package/src/compute-view/utils/link-nodes-with-edges.ts +58 -0
  60. package/src/compute-view/utils/relationExpressionToPredicates.ts +55 -0
  61. package/src/compute-view/utils/resolve-extended-views.ts +65 -0
  62. package/src/compute-view/utils/resolve-global-rules.ts +83 -0
  63. package/src/compute-view/utils/sortNodes.ts +101 -0
  64. package/src/compute-view/utils/topological-sort.ts +160 -0
  65. package/src/compute-view/utils/uniqueTags.test.ts +42 -0
  66. package/src/compute-view/utils/uniqueTags.ts +21 -0
  67. package/src/compute-view/utils/view-hash.ts +27 -0
  68. package/src/compute-view/utils/with-readable-edges.ts +31 -0
  69. package/src/index.ts +5 -1
  70. package/src/model/DeploymentElementModel.ts +534 -0
  71. package/src/model/DeploymentModel.ts +364 -0
  72. package/src/model/ElementModel.ts +195 -0
  73. package/src/model/LikeC4Model.test-d.ts +151 -0
  74. package/src/model/LikeC4Model.ts +280 -457
  75. package/src/model/RelationModel.ts +84 -0
  76. package/src/model/__test__/fixture.ts +153 -338
  77. package/src/model/connection/ConnectionModel.ts +94 -0
  78. package/src/model/connection/DeploymentConnectionModel.ts +99 -0
  79. package/src/model/connection/deployment.ts +124 -0
  80. package/src/model/connection/model.ts +123 -0
  81. package/src/model/index.ts +4 -2
  82. package/src/model/types.ts +95 -15
  83. package/src/model/view/EdgeModel.ts +103 -0
  84. package/src/model/view/LikeC4ViewModel.ts +220 -0
  85. package/src/model/view/NodeModel.ts +228 -0
  86. package/src/types/_common.ts +2 -0
  87. package/src/types/deployments.ts +237 -0
  88. package/src/types/element.ts +7 -3
  89. package/src/types/expression.ts +8 -6
  90. package/src/types/index.ts +1 -0
  91. package/src/types/model.ts +68 -9
  92. package/src/types/overview-graph.ts +2 -2
  93. package/src/types/relation.ts +4 -4
  94. package/src/types/view-notation.ts +2 -2
  95. package/src/types/view.ts +104 -30
  96. package/src/utils/{commonHead.ts → common-head.ts} +2 -0
  97. package/src/utils/fqn.ts +83 -27
  98. package/src/utils/getOrCreate.ts +42 -0
  99. package/src/utils/graphlib.ts +10 -0
  100. package/src/utils/index.ts +4 -1
  101. package/src/utils/object-hash.ts +3 -0
  102. package/src/utils/set.ts +76 -0
  103. package/src/utils/string-hash.ts +16 -0
  104. package/dist/index.cjs +0 -5452
  105. package/dist/index.d.cts +0 -1053
  106. package/dist/shared/core.BXTs-8n7.mjs +0 -293
  107. package/dist/shared/core.CoLQkcYL.d.cts +0 -734
  108. package/dist/shared/core.DIYZvpVg.cjs +0 -353
  109. package/dist/types/index.cjs +0 -70
  110. package/dist/types/index.d.cts +0 -2
  111. package/src/model/LikeC4DiagramModel.ts +0 -338
  112. package/src/model/LikeC4ViewModel.ts +0 -320
@@ -3,7 +3,7 @@ import type { BorderStyle, ElementKind, ElementShape, Fqn, Tag } from './element
3
3
  import type { WhereOperator } from './operators'
4
4
  import type { RelationshipArrowType, RelationshipLineType } from './relation'
5
5
  import type { Color } from './theme'
6
- import type { ViewID } from './view'
6
+ import type { ViewId } from './view'
7
7
 
8
8
  interface BaseExpr {
9
9
  where?: never
@@ -13,7 +13,8 @@ interface BaseExpr {
13
13
  elementKind?: never
14
14
  elementTag?: never
15
15
  isEqual?: never
16
- isDescedants?: never
16
+ isChildren?: never
17
+ isDescendants?: never
17
18
  wildcard?: never
18
19
  source?: never
19
20
  target?: never
@@ -23,9 +24,10 @@ interface BaseExpr {
23
24
  customRelation?: never
24
25
  }
25
26
 
26
- export interface ElementRefExpr extends Omit<BaseExpr, 'element' | 'isDescedants'> {
27
+ export interface ElementRefExpr extends Omit<BaseExpr, 'element' | 'isChildren' | 'isDescendants'> {
27
28
  element: Fqn
28
- isDescedants?: boolean
29
+ isChildren?: boolean
30
+ isDescendants?: boolean
29
31
  }
30
32
  export function isElementRef(expr: Expression): expr is ElementRefExpr {
31
33
  return 'element' in expr
@@ -50,7 +52,7 @@ export interface CustomElementExpr extends Omit<BaseExpr, 'custom'> {
50
52
  icon?: IconUrl
51
53
  border?: BorderStyle
52
54
  opacity?: number
53
- navigateTo?: ViewID
55
+ navigateTo?: ViewId
54
56
  }
55
57
  }
56
58
 
@@ -162,7 +164,7 @@ export interface CustomRelationExpr extends Omit<BaseExpr, 'customRelation'> {
162
164
  technology?: string
163
165
  notation?: string
164
166
  // Link to dynamic view
165
- navigateTo?: ViewID
167
+ navigateTo?: ViewId
166
168
  // Notes for walkthrough
167
169
  notes?: string
168
170
  color?: Color
@@ -1,4 +1,5 @@
1
1
  export * from './_common'
2
+ export * from './deployments'
2
3
  export * from './element'
3
4
  export * from './expression'
4
5
  export * from './global'
@@ -1,7 +1,14 @@
1
+ import type { KeysOf } from './_common'
2
+ import type {
3
+ DeploymentElement,
4
+ DeploymentNodeKind,
5
+ DeploymentNodeKindSpecification,
6
+ DeploymentRelation
7
+ } from './deployments'
1
8
  import type { ElementKindSpecification, Tag, TypedElement } from './element'
2
9
  import type { ModelGlobals } from './global'
3
- import type { Relation, RelationID, RelationshipKindSpecification } from './relation'
4
- import type { ComputedView, DiagramView, LikeC4View, ViewID } from './view'
10
+ import type { Relation, RelationId, RelationshipKindSpecification } from './relation'
11
+ import type { ComputedView, DiagramView, LikeC4View } from './view'
5
12
 
6
13
  /**
7
14
  * Parsed elements, relations, and views.
@@ -11,31 +18,83 @@ export interface ParsedLikeC4Model<
11
18
  RelationKinds extends string = string,
12
19
  Tags extends string = string,
13
20
  Fqns extends string = string,
14
- Views extends string = string
21
+ Views extends string = string,
22
+ DeploymentFqns extends string = string
15
23
  > {
16
24
  specification: {
17
25
  tags: Tag<Tags>[]
18
26
  elements: Record<ElementKinds, ElementKindSpecification>
27
+ deployments: Record<DeploymentNodeKind, DeploymentNodeKindSpecification>
19
28
  relationships: Record<RelationKinds, RelationshipKindSpecification>
20
29
  }
21
30
  elements: Record<Fqns, TypedElement<Fqns, ElementKinds, Tags>>
22
- relations: Record<RelationID, Relation>
31
+ relations: Record<RelationId, Relation>
23
32
  globals: ModelGlobals
24
33
  views: Record<Views, LikeC4View<Views, Tags>>
34
+ /**
35
+ * Deployment Model.
36
+ */
37
+ deployments: {
38
+ elements: Record<DeploymentFqns, DeploymentElement>
39
+ relations: Record<RelationId, DeploymentRelation>
40
+ }
41
+ }
42
+ /**
43
+ * Hook to get types from dump
44
+ */
45
+ export type ParsedLikeC4ModelDump = {
46
+ elements: {
47
+ [kind: string]: object
48
+ }
49
+ deployments: {
50
+ elements: {
51
+ [kind: string]: object
52
+ }
53
+ }
54
+ views: {
55
+ [kind: string]: object
56
+ }
57
+ }
58
+
59
+ export interface AnyLikeC4Model<
60
+ Fqns extends string = string,
61
+ DeploymentFqns extends string = string,
62
+ Views extends string = string,
63
+ Tags extends string = string,
64
+ T = 'computed' | 'layouted'
65
+ > extends Omit<ParsedLikeC4Model<string, string, Tags, Fqns, Views, DeploymentFqns>, 'views'> {
66
+ __?: T
67
+ views: Record<Views, ComputedView | DiagramView>
25
68
  }
26
69
 
27
70
  /**
28
71
  * Same as `ParsedLikeC4Model` but with computed views.
29
72
  */
30
- export interface ComputedLikeC4Model extends Omit<ParsedLikeC4Model, 'views'> {
31
- __?: never
32
- views: Record<ViewID, ComputedView>
73
+ export interface ComputedLikeC4Model<
74
+ Fqns extends string = string,
75
+ DeploymentFqns extends string = string,
76
+ Views extends string = string,
77
+ Tags extends string = string
78
+ > extends Omit<AnyLikeC4Model<Fqns, DeploymentFqns, Views, Tags, 'computed'>, 'views'> {
79
+ views: Record<Views, ComputedView>
33
80
  }
34
81
 
82
+ export type ComputedLikeC4ModelFromParsed<M> = M extends ParsedLikeC4Model ? ComputedLikeC4Model<
83
+ KeysOf<M['elements']>,
84
+ KeysOf<M['deployments']['elements']>,
85
+ KeysOf<M['views']>
86
+ >
87
+ : ComputedLikeC4Model
88
+
35
89
  /**
36
90
  * Same as `ParsedLikeC4Model` but with layouted views (DiagramView)
37
91
  */
38
- export interface LayoutedLikeC4Model extends Omit<ParsedLikeC4Model, 'views'> {
92
+ export interface LayoutedLikeC4Model<
93
+ Fqns extends string = string,
94
+ DeploymentFqns extends string = string,
95
+ Views extends string = string,
96
+ Tags extends string = string
97
+ > extends Omit<AnyLikeC4Model<Fqns, DeploymentFqns, Views, Tags, 'layouted'>, 'views'> {
39
98
  __: 'layouted'
40
- views: Record<ViewID, DiagramView>
99
+ views: Record<Views, DiagramView<Views, Tags>>
41
100
  }
@@ -1,5 +1,5 @@
1
1
  import type { NonEmptyArray, Point, XYPoint } from './_common'
2
- import type { BBox, ViewID } from './view'
2
+ import type { BBox, ViewId } from './view'
3
3
 
4
4
  /**
5
5
  * OverviewGraph is a graph representation of all views in a model
@@ -17,7 +17,7 @@ export namespace OverviewGraph {
17
17
  } | {
18
18
  id: string
19
19
  type: 'view'
20
- viewId: ViewID
20
+ viewId: ViewId
21
21
  label: string
22
22
  parentId: string | null
23
23
  position: XYPoint
@@ -2,9 +2,9 @@ import type { Tagged } from 'type-fest'
2
2
  import type { NonEmptyArray } from './_common'
3
3
  import type { Fqn, Link, Tag } from './element'
4
4
  import type { Color, ThemeColor } from './theme'
5
- import type { ViewID } from './view'
5
+ import type { ViewId } from './view'
6
6
 
7
- export type RelationID = Tagged<string, 'RelationID'>
7
+ export type RelationId = Tagged<string, 'RelationID'>
8
8
  export type RelationshipKind<Kinds extends string = string> = Tagged<Kinds, 'RelationshipKind'>
9
9
 
10
10
  export type RelationshipLineType = 'dashed' | 'solid' | 'dotted'
@@ -28,7 +28,7 @@ export const DefaultRelationshipColor = 'gray' satisfies ThemeColor
28
28
 
29
29
  // TODO: rename to Relationship
30
30
  export interface Relation {
31
- readonly id: RelationID
31
+ readonly id: RelationId
32
32
  readonly source: Fqn
33
33
  readonly target: Fqn
34
34
  readonly title: string
@@ -42,7 +42,7 @@ export interface Relation {
42
42
  readonly tail?: RelationshipArrowType
43
43
  readonly links?: NonEmptyArray<Link>
44
44
  // Link to dynamic view
45
- readonly navigateTo?: ViewID
45
+ readonly navigateTo?: ViewId
46
46
  readonly metadata?: { [key: string]: string }
47
47
  }
48
48
 
@@ -1,8 +1,8 @@
1
- import type { ElementKind, ElementShape } from './element'
1
+ import type { ElementShape } from './element'
2
2
  import type { Color } from './theme'
3
3
 
4
4
  export type ElementNotation = {
5
- kinds: ElementKind[]
5
+ kinds: string[]
6
6
  shape: ElementShape
7
7
  color: Color
8
8
  title: string
package/src/types/view.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { isArray, isNullish } from 'remeda'
2
2
  import type { Tagged } from 'type-fest'
3
3
  import type { IconUrl, NonEmptyArray, Point, XYPoint } from './_common'
4
+ import type { DeploymentExpression } from './deployments'
4
5
  import {
5
6
  type BorderStyle,
6
7
  ElementKind,
@@ -12,11 +13,11 @@ import {
12
13
  } from './element'
13
14
  import type { ElementExpression, ElementPredicateExpression, Expression } from './expression'
14
15
  import type { GlobalPredicateId, GlobalStyleID } from './global'
15
- import type { RelationID, RelationshipArrowType, RelationshipKind, RelationshipLineType } from './relation'
16
+ import type { RelationId, RelationshipArrowType, RelationshipKind, RelationshipLineType } from './relation'
16
17
  import type { Color, ThemeColorValues } from './theme'
17
18
  import type { ElementNotation } from './view-notation'
18
19
 
19
- export type ViewID<Id extends string = string> = Tagged<Id, 'ViewID'>
20
+ export type ViewId<Id extends string = string> = Tagged<Id, 'ViewID'>
20
21
 
21
22
  export type ViewRulePredicate =
22
23
  | {
@@ -27,7 +28,11 @@ export type ViewRulePredicate =
27
28
  include?: never
28
29
  exclude: Expression[]
29
30
  }
30
- export function isViewRulePredicate(rule: ViewRule): rule is ViewRulePredicate {
31
+
32
+ export function isViewRulePredicate(rule: DeploymentViewRule): rule is DeploymentViewRulePredicate
33
+ export function isViewRulePredicate(rule: DynamicViewRule): rule is DynamicViewIncludeRule
34
+ export function isViewRulePredicate(rule: ViewRule): rule is ViewRulePredicate
35
+ export function isViewRulePredicate(rule: object) {
31
36
  return (
32
37
  ('include' in rule && Array.isArray(rule.include))
33
38
  || ('exclude' in rule && Array.isArray(rule.exclude))
@@ -50,8 +55,10 @@ export interface ViewRuleStyle {
50
55
  icon?: IconUrl
51
56
  }
52
57
  }
53
- export function isViewRuleStyle(rule: ViewRule): rule is ViewRuleStyle {
54
- return 'style' in rule && 'targets' in rule
58
+ export function isViewRuleStyle(rule: DeploymentViewRule): rule is DeploymentViewRuleStyle
59
+ export function isViewRuleStyle(rule: ViewRule): rule is ViewRuleStyle
60
+ export function isViewRuleStyle(rule: object) {
61
+ return 'style' in rule && 'targets' in rule && Array.isArray(rule.targets)
55
62
  }
56
63
 
57
64
  export interface ViewRuleGlobalStyle {
@@ -73,7 +80,10 @@ export interface ViewRuleAutoLayout {
73
80
  nodeSep?: number
74
81
  rankSep?: number
75
82
  }
76
- export function isViewRuleAutoLayout(rule: ViewRule): rule is ViewRuleAutoLayout {
83
+
84
+ export function isViewRuleAutoLayout(
85
+ rule: DeploymentViewRule | DynamicViewRule | ViewRule
86
+ ): rule is ViewRuleAutoLayout {
77
87
  return 'direction' in rule
78
88
  }
79
89
 
@@ -99,12 +109,12 @@ export type ViewRule =
99
109
  | ViewRuleAutoLayout
100
110
 
101
111
  export interface BasicView<
102
- ViewType extends 'element' | 'dynamic',
112
+ ViewType extends 'element' | 'dynamic' | 'deployment',
103
113
  ViewIDs extends string,
104
114
  Tags extends string
105
115
  > {
106
116
  readonly __?: ViewType
107
- readonly id: ViewID<ViewIDs>
117
+ readonly id: ViewId<ViewIDs>
108
118
  readonly title: string | null
109
119
  readonly description: string | null
110
120
  readonly tags: NonEmptyArray<Tag<Tags>> | null
@@ -148,7 +158,7 @@ export interface ScopedElementView<ViewIDs extends string, Tags extends string>
148
158
  export interface ExtendsElementView<ViewIDs extends string, Tags extends string>
149
159
  extends BasicElementView<ViewIDs, Tags>
150
160
  {
151
- readonly extends: ViewID<ViewIDs>
161
+ readonly extends: ViewId<ViewIDs>
152
162
  }
153
163
  export type ElementView<
154
164
  ViewIDs extends string = string,
@@ -173,7 +183,7 @@ export interface DynamicViewStep {
173
183
  readonly tail?: RelationshipArrowType
174
184
  readonly isBackward?: boolean
175
185
  // Link to dynamic view
176
- readonly navigateTo?: ViewID
186
+ readonly navigateTo?: ViewId
177
187
  __parallel?: never
178
188
  }
179
189
 
@@ -187,10 +197,6 @@ export type DynamicViewIncludeRule = {
187
197
  include: ElementPredicateExpression[]
188
198
  }
189
199
 
190
- export function isDynamicViewIncludeRule(rule: DynamicViewRule): rule is DynamicViewIncludeRule {
191
- return 'include' in rule && Array.isArray(rule.include)
192
- }
193
-
194
200
  export type DynamicViewRule =
195
201
  | DynamicViewIncludeRule
196
202
  | ViewRuleGlobalPredicateRef
@@ -214,11 +220,44 @@ export function isDynamicViewParallelSteps(step: DynamicViewStepOrParallel): ste
214
220
 
215
221
  export type CustomColorDefinitions = { [key: string]: ThemeColorValues }
216
222
 
223
+ export type DeploymentViewRulePredicate =
224
+ | {
225
+ include: DeploymentExpression[]
226
+ exclude?: never
227
+ }
228
+ | {
229
+ include?: never
230
+ exclude: DeploymentExpression[]
231
+ }
232
+ export type DeploymentViewRuleStyle = {
233
+ targets: DeploymentExpression[]
234
+ notation?: string
235
+ style: ElementStyle & {
236
+ color?: Color
237
+ shape?: ElementShape
238
+ icon?: IconUrl
239
+ }
240
+ }
241
+ export type DeploymentViewRule = DeploymentViewRulePredicate | ViewRuleAutoLayout | DeploymentViewRuleStyle
242
+
243
+ export interface DeploymentView<
244
+ ViewIDs extends string = string,
245
+ Tags extends string = string
246
+ > extends BasicView<'deployment', ViewIDs, Tags> {
247
+ readonly __: 'deployment'
248
+ readonly rules: DeploymentViewRule[]
249
+ }
250
+
217
251
  export type LikeC4View<
218
252
  ViewIDs extends string = string,
219
253
  Tags extends string = string
220
- > = ElementView<ViewIDs, Tags> | DynamicView<ViewIDs, Tags>
254
+ > = ElementView<ViewIDs, Tags> | DynamicView<ViewIDs, Tags> | DeploymentView<ViewIDs, Tags>
221
255
 
256
+ export function isDeploymentView(view: LikeC4View): view is DeploymentView
257
+ export function isDeploymentView<V extends { __?: string }>(view: V): boolean
258
+ export function isDeploymentView(view: LikeC4View): view is DeploymentView {
259
+ return view.__ === 'deployment'
260
+ }
222
261
  export function isDynamicView(view: LikeC4View): view is DynamicView {
223
262
  return view.__ === 'dynamic'
224
263
  }
@@ -239,7 +278,7 @@ export type NodeId<IDs extends string = string> = Tagged<IDs, 'Fqn'>
239
278
  export type EdgeId = Tagged<string, 'EdgeId'>
240
279
  export type StepEdgeIdLiteral = `step-${number}` | `step-${number}.${number}`
241
280
  export type StepEdgeId = Tagged<StepEdgeIdLiteral, 'EdgeId'>
242
- export function StepEdgeId(step: number, parallelStep?: number): StepEdgeId {
281
+ export function stepEdgeId(step: number, parallelStep?: number): StepEdgeId {
243
282
  const id = `step-${String(step).padStart(2, '0')}` as StepEdgeId
244
283
  return parallelStep ? `${id}.${parallelStep}` as StepEdgeId : id
245
284
  }
@@ -266,8 +305,18 @@ export function getParallelStepsPrefix(id: string): string | null {
266
305
 
267
306
  export interface ComputedNode {
268
307
  id: NodeId
269
- kind: ElementKind
308
+ kind: string // TODO: fix ElementKind | DeploymentNodeKind
270
309
  parent: NodeId | null
310
+ /**
311
+ * Reference to model element
312
+ * If 1 - node id is a reference
313
+ */
314
+ modelRef?: 1 | Fqn
315
+ /**
316
+ * Reference to deployment element
317
+ * If 1 - node id is a reference
318
+ */
319
+ deploymentRef?: 1 | Fqn
271
320
  title: string
272
321
  description: string | null
273
322
  technology: string | null
@@ -278,16 +327,13 @@ export interface ComputedNode {
278
327
  inEdges: EdgeId[]
279
328
  outEdges: EdgeId[]
280
329
  shape: ElementShape
281
- /**
282
- * @deprecated Use `style` instead
283
- */
284
330
  color: Color
285
331
  /**
286
332
  * @deprecated Use `style` instead
287
333
  */
288
334
  icon?: IconUrl
289
335
  style: ElementStyle
290
- navigateTo?: ViewID
336
+ navigateTo?: ViewId
291
337
  level: number
292
338
  // For compound nodes, the max depth of nested nodes
293
339
  depth?: number
@@ -297,6 +343,12 @@ export interface ComputedNode {
297
343
  isCustomized?: boolean
298
344
  }
299
345
  export namespace ComputedNode {
346
+ export function modelRef(node: ComputedNode): Fqn | null {
347
+ return node.modelRef === 1 ? node.id : (node.modelRef ?? null)
348
+ }
349
+ export function deploymentRef(node: ComputedNode): Fqn | null {
350
+ return node.deploymentRef === 1 ? node.id : (node.deploymentRef ?? null)
351
+ }
300
352
  /**
301
353
  * Nodes group is a special kind of node, exisiting only in view
302
354
  */
@@ -313,7 +365,7 @@ export interface ComputedEdge {
313
365
  label: string | null
314
366
  description?: string
315
367
  technology?: string
316
- relations: RelationID[]
368
+ relations: RelationId[]
317
369
  kind?: RelationshipKind
318
370
  notation?: string
319
371
  // Notes for walkthrough
@@ -324,7 +376,7 @@ export interface ComputedEdge {
324
376
  tail?: RelationshipArrowType
325
377
  tags?: NonEmptyArray<Tag>
326
378
  // Link to dynamic view
327
- navigateTo?: ViewID
379
+ navigateTo?: ViewId
328
380
  /**
329
381
  * If this edge is derived from custom relationship predicate
330
382
  */
@@ -333,7 +385,7 @@ export interface ComputedEdge {
333
385
  * For layouting purposes
334
386
  * @default 'forward'
335
387
  */
336
- dir?: 'forward' | 'back'
388
+ dir?: 'forward' | 'back' | 'both'
337
389
  }
338
390
 
339
391
  export interface ViewWithHash {
@@ -358,7 +410,7 @@ export interface ComputedElementView<
358
410
  ViewIDs extends string = string,
359
411
  Tags extends string = string
360
412
  > extends Omit<ElementView<ViewIDs, Tags>, 'rules' | 'docUri'>, ViewWithHash, ViewWithNotation {
361
- readonly extends?: ViewID<ViewIDs>
413
+ readonly extends?: ViewId<ViewIDs>
362
414
  readonly autoLayout: ViewAutoLayout
363
415
  readonly nodes: ComputedNode[]
364
416
  readonly edges: ComputedEdge[]
@@ -376,17 +428,33 @@ export interface ComputedDynamicView<
376
428
  rules?: never
377
429
  docUri?: never
378
430
  }
379
- export function isComputedDynamicView(view: ComputedView): view is ComputedDynamicView {
380
- return view.__ === 'dynamic'
431
+
432
+ export interface ComputedDeploymentView<
433
+ ViewIDs extends string = string,
434
+ Tags extends string = string
435
+ > extends Omit<DeploymentView<ViewIDs, Tags>, 'rules' | 'docUri'>, ViewWithHash, ViewWithNotation {
436
+ readonly autoLayout: ViewAutoLayout
437
+ readonly nodes: ComputedNode[]
438
+ readonly edges: ComputedEdge[]
439
+ rules?: never
440
+ docUri?: never
381
441
  }
382
442
 
383
443
  export type ComputedView<
384
444
  ViewIDs extends string = string,
385
445
  Tags extends string = string
386
- > = ComputedElementView<ViewIDs, Tags> | ComputedDynamicView<ViewIDs, Tags>
446
+ > = ComputedElementView<ViewIDs, Tags> | ComputedDynamicView<ViewIDs, Tags> | ComputedDeploymentView<ViewIDs, Tags>
387
447
 
388
- export function isComputedElementView(view: ComputedView): view is ComputedElementView {
389
- return isNullish(view.__) || view.__ === 'element'
448
+ export namespace ComputedView {
449
+ export function isDeployment(view: ComputedView): view is ComputedDeploymentView {
450
+ return view.__ === 'deployment'
451
+ }
452
+ export function isDynamic(view: ComputedView): view is ComputedDynamicView {
453
+ return view.__ === 'dynamic'
454
+ }
455
+ export function isElement(view: ComputedView): view is ComputedElementView {
456
+ return isNullish(view.__) || view.__ === 'element'
457
+ }
390
458
  }
391
459
 
392
460
  // Bounding box
@@ -418,6 +486,12 @@ export interface DiagramNode extends ComputedNode {
418
486
  }
419
487
 
420
488
  export namespace DiagramNode {
489
+ export function modelRef(node: DiagramNode): Fqn | null {
490
+ return node.modelRef === 1 ? node.id : (node.modelRef ?? null)
491
+ }
492
+ export function deploymentRef(node: DiagramNode): Fqn | null {
493
+ return node.deploymentRef === 1 ? node.id : (node.deploymentRef ?? null)
494
+ }
421
495
  /**
422
496
  * Nodes group is a special kind of node, exisiting only in view
423
497
  */
@@ -2,6 +2,8 @@ import { map, pipe, takeWhile, zip } from 'remeda'
2
2
 
3
3
  /**
4
4
  * Common head of two arrays
5
+ *
6
+ * @param equals - Equality function, defaults to `Object.is`
5
7
  */
6
8
  export function commonHead<T>(
7
9
  sources: ReadonlyArray<T>,