@likec4/core 1.31.0 → 1.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +407 -5
  2. package/dist/builder/index.d.mts +221 -42
  3. package/dist/builder/index.mjs +118 -65
  4. package/dist/compute-view/index.d.mts +23 -7
  5. package/dist/compute-view/index.mjs +11 -6
  6. package/dist/compute-view/relationships-view/index.d.mts +9 -7
  7. package/dist/compute-view/relationships-view/index.mjs +3 -2
  8. package/dist/index.d.mts +10 -14
  9. package/dist/index.mjs +9 -6
  10. package/dist/model/index.d.mts +173 -19
  11. package/dist/model/index.mjs +6 -1
  12. package/dist/shared/core.BaYE_r29.d.mts +258 -0
  13. package/dist/shared/core.Bk7wEZFG.mjs +276 -0
  14. package/dist/shared/core.BrCnZFTn.mjs +32 -0
  15. package/dist/shared/core.BuO4ncfY.d.mts +146 -0
  16. package/dist/shared/{core.Bq753SYD.mjs → core.CBpKAlhj.mjs} +2012 -4422
  17. package/dist/shared/core.CUYDgv2-.mjs +214 -0
  18. package/dist/shared/{core.Cu-UdkSl.mjs → core.CpXlRyE5.mjs} +7 -494
  19. package/dist/shared/{core.C-YXI-43.mjs → core.Cy9smucx.mjs} +3 -1
  20. package/dist/shared/core.CywrQs86.d.mts +31 -0
  21. package/dist/shared/core.DXzRBkuI.d.mts +1264 -0
  22. package/dist/shared/core.DoK86JEe.mjs +518 -0
  23. package/dist/shared/{core.D2830qgg.d.mts → core.Pf5I9o0e.d.mts} +1 -1
  24. package/dist/shared/core.cbA9VZ02.mjs +2681 -0
  25. package/dist/shared/{core.CQXU9DF7.mjs → core.rmvsy0n3.mjs} +23 -32
  26. package/dist/shared/core.znRaUX_A.d.mts +920 -0
  27. package/dist/types/aux.d.mts +3 -0
  28. package/dist/types/aux.mjs +1 -0
  29. package/dist/types/index.d.mts +7 -45
  30. package/dist/types/index.mjs +130 -3
  31. package/dist/utils/index.d.mts +221 -53
  32. package/dist/utils/index.mjs +14 -10
  33. package/package.json +16 -8
  34. package/src/builder/Builder.deploymentModel.ts +82 -18
  35. package/src/builder/Builder.element.ts +40 -20
  36. package/src/builder/Builder.model.ts +66 -17
  37. package/src/builder/Builder.ts +168 -76
  38. package/src/builder/Builder.view-common.ts +35 -17
  39. package/src/builder/Builder.view-deployment.ts +25 -25
  40. package/src/builder/Builder.view-element.ts +13 -12
  41. package/src/builder/Builder.views.ts +12 -7
  42. package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +62 -34
  43. package/src/builder/__snapshots__/Builder-style2.compute-model.json5 +319 -0
  44. package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +45 -24
  45. package/src/builder/_types.ts +34 -27
  46. package/src/compute-view/compute-view.ts +31 -34
  47. package/src/compute-view/deployment-view/__test__/TestHelper.ts +27 -14
  48. package/src/compute-view/deployment-view/__test__/fixture.ts +15 -13
  49. package/src/compute-view/deployment-view/_types.ts +10 -10
  50. package/src/compute-view/deployment-view/clean-connections.ts +5 -7
  51. package/src/compute-view/deployment-view/compute.ts +16 -13
  52. package/src/compute-view/deployment-view/memory/memory.ts +5 -6
  53. package/src/compute-view/deployment-view/predicates/deploymentRefs.ts +4 -5
  54. package/src/compute-view/deployment-view/predicates/relation-direct.ts +25 -50
  55. package/src/compute-view/deployment-view/predicates/relation-in-out.ts +5 -7
  56. package/src/compute-view/deployment-view/predicates/relation-incoming.ts +7 -11
  57. package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +7 -10
  58. package/src/compute-view/deployment-view/predicates/utils.ts +37 -31
  59. package/src/compute-view/deployment-view/predicates/wildcard.ts +3 -2
  60. package/src/compute-view/deployment-view/stages/stage-final.ts +2 -2
  61. package/src/compute-view/deployment-view/stages/stage-include.ts +1 -1
  62. package/src/compute-view/deployment-view/utils.ts +79 -72
  63. package/src/compute-view/dynamic-view/__test__/fixture.ts +20 -11
  64. package/src/compute-view/dynamic-view/compute.ts +60 -53
  65. package/src/compute-view/element-view/__test__/TestHelper.ts +53 -29
  66. package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +26 -26
  67. package/src/compute-view/element-view/__test__/fixture.ts +134 -83
  68. package/src/compute-view/element-view/_types.ts +14 -19
  69. package/src/compute-view/element-view/clean-connections.ts +12 -8
  70. package/src/compute-view/element-view/compute.ts +61 -51
  71. package/src/compute-view/element-view/memory/NodeGroup.ts +8 -9
  72. package/src/compute-view/element-view/memory/memory.ts +22 -22
  73. package/src/compute-view/element-view/memory/stage-include.ts +5 -3
  74. package/src/compute-view/element-view/predicates/_utils.ts +18 -14
  75. package/src/compute-view/element-view/predicates/element-expand.ts +4 -5
  76. package/src/compute-view/element-view/predicates/element-kind-tag.ts +3 -4
  77. package/src/compute-view/element-view/predicates/element-ref.ts +3 -4
  78. package/src/compute-view/element-view/predicates/relation-direct.ts +16 -12
  79. package/src/compute-view/element-view/predicates/relation-in-out.ts +7 -8
  80. package/src/compute-view/element-view/predicates/relation-in.ts +19 -26
  81. package/src/compute-view/element-view/predicates/relation-out.ts +20 -21
  82. package/src/compute-view/element-view/predicates/wildcard.ts +3 -3
  83. package/src/compute-view/element-view/utils.ts +25 -23
  84. package/src/compute-view/index.ts +1 -1
  85. package/src/compute-view/memory/AbstractStageExclude.ts +3 -4
  86. package/src/compute-view/memory/AbstractStageInclude.ts +1 -1
  87. package/src/compute-view/memory/_types.ts +3 -2
  88. package/src/compute-view/relationships-view/_types.ts +3 -4
  89. package/src/compute-view/relationships-view/compute.ts +8 -11
  90. package/src/compute-view/relationships-view/layout.ts +6 -6
  91. package/src/compute-view/relationships-view/utils.ts +4 -4
  92. package/src/compute-view/utils/ancestorsOfNode.ts +7 -7
  93. package/src/compute-view/utils/applyCustomElementProperties.ts +16 -8
  94. package/src/compute-view/utils/applyCustomRelationProperties.ts +19 -9
  95. package/src/compute-view/utils/applyViewRuleStyles.ts +18 -10
  96. package/src/compute-view/utils/buildComputedNodes.ts +40 -40
  97. package/src/compute-view/utils/buildElementNotations.ts +14 -14
  98. package/src/compute-view/utils/elementExpressionToPredicate.ts +14 -15
  99. package/src/compute-view/utils/link-nodes-with-edges.ts +6 -4
  100. package/src/compute-view/utils/merge-props-from-relationships.ts +52 -20
  101. package/src/compute-view/utils/relationExpressionToPredicates.ts +19 -19
  102. package/src/compute-view/utils/resolve-extended-views.ts +8 -7
  103. package/src/compute-view/utils/resolve-global-rules.ts +31 -26
  104. package/src/compute-view/utils/topological-sort.ts +14 -14
  105. package/src/compute-view/utils/view-hash.ts +2 -2
  106. package/src/compute-view/utils/with-readable-edges.ts +9 -5
  107. package/src/index.ts +0 -32
  108. package/src/model/DeploymentElementModel.ts +171 -144
  109. package/src/model/DeploymentModel.ts +88 -65
  110. package/src/model/ElementModel.ts +85 -74
  111. package/src/model/LikeC4Model.ts +430 -241
  112. package/src/model/RelationModel.ts +63 -29
  113. package/src/model/__test__/fixture.ts +50 -36
  114. package/src/model/connection/Connection.ts +2 -2
  115. package/src/model/connection/deployment/DeploymentConnectionModel.ts +21 -24
  116. package/src/model/connection/deployment/find.ts +1 -1
  117. package/src/model/connection/model/ConnectionModel.ts +21 -20
  118. package/src/model/connection/model/find.ts +7 -7
  119. package/src/model/connection/ops.ts +6 -6
  120. package/src/model/guards.ts +66 -14
  121. package/src/model/index.ts +20 -7
  122. package/src/model/types.ts +41 -97
  123. package/src/model/view/EdgeModel.ts +47 -41
  124. package/src/model/view/LikeC4ViewModel.ts +130 -80
  125. package/src/model/view/NodeModel.ts +102 -96
  126. package/src/theme/element.ts +1 -1
  127. package/src/theme/index.ts +9 -9
  128. package/src/theme/relationships.ts +1 -1
  129. package/src/types/_common.ts +21 -15
  130. package/src/types/aux.ts +285 -0
  131. package/src/types/const.ts +34 -0
  132. package/src/types/expression-model.ts +292 -0
  133. package/src/types/expression.ts +311 -0
  134. package/src/types/fqnRef.ts +88 -0
  135. package/src/types/geometry.ts +131 -0
  136. package/src/types/global.ts +10 -8
  137. package/src/types/index.ts +39 -201
  138. package/src/types/model-data.ts +52 -84
  139. package/src/types/model-deployment.ts +87 -0
  140. package/src/types/model-dump.ts +72 -0
  141. package/src/types/model-logical.ts +111 -0
  142. package/src/types/model-spec.ts +81 -0
  143. package/src/types/operators.ts +51 -52
  144. package/src/types/scalar.ts +114 -0
  145. package/src/types/{theme.ts → styles.ts} +55 -15
  146. package/src/types/view-changes.ts +4 -5
  147. package/src/types/view-common.ts +157 -0
  148. package/src/types/view-computed.ts +113 -0
  149. package/src/types/view-layouted.ts +82 -0
  150. package/src/types/view-parsed.deployment.ts +40 -0
  151. package/src/types/view-parsed.dynamic.ts +78 -0
  152. package/src/types/view-parsed.element.ts +65 -0
  153. package/src/types/view.ts +122 -542
  154. package/src/utils/compare-natural.ts +43 -1
  155. package/src/utils/getOrCreate.ts +0 -34
  156. package/src/utils/index.ts +7 -12
  157. package/src/utils/iterable/filter.ts +1 -1
  158. package/src/utils/iterable/find.ts +3 -1
  159. package/src/utils/iterable/head.ts +22 -0
  160. package/src/utils/iterable/index.ts +1 -0
  161. package/src/utils/iterable/map.ts +1 -1
  162. package/src/utils/iterable/reduce.ts +1 -1
  163. package/src/utils/iterable/some.ts +1 -1
  164. package/src/utils/memoize-prop.ts +30 -0
  165. package/src/utils/object-hash.ts +1 -1
  166. package/src/utils/relations.ts +14 -11
  167. package/src/utils/string-hash.ts +1 -1
  168. package/dist/shared/core.CQDU11hR.d.mts +0 -753
  169. package/dist/shared/core.DJvmfnEi.d.mts +0 -1153
  170. package/dist/shared/core.DgfwjBtu.mjs +0 -495
  171. package/dist/shared/core.Dx7siloV.d.mts +0 -146
  172. package/dist/shared/core.SjLhMA7a.d.mts +0 -62
  173. package/src/builder/__snapshots__/Builder.spec.ts.snap +0 -374
  174. package/src/compute-view/element-view/predicates.ts +0 -520
  175. package/src/compute-view/utils/uniqueTags.ts +0 -21
  176. package/src/types/deployments.ts +0 -170
  177. package/src/types/element.ts +0 -109
  178. package/src/types/expression-v2-model.ts +0 -314
  179. package/src/types/expression-v2.ts +0 -392
  180. package/src/types/overview-graph.ts +0 -43
  181. package/src/types/relation.ts +0 -61
  182. package/src/types/scalars.ts +0 -39
  183. package/src/types/view-notation.ts +0 -9
  184. package/src/utils/graphlib.ts +0 -10
  185. /package/src/{errors/index.ts → utils/invariant.ts} +0 -0
package/README.md CHANGED
@@ -1,9 +1,411 @@
1
1
  # `@likec4/core`
2
2
 
3
- [docs](https://likec4.dev/)
3
+ <a href="https://www.npmjs.com/package/%40likec4%2Fcore" target="_blank">![NPM Version](https://img.shields.io/npm/v/%40likec4%2Fcore)</a>
4
+ <a href="https://www.npmjs.com/package/%40likec4%2Fcore" target="_blank">![NPM Downloads](https://img.shields.io/npm/dw/%40likec4%2Fcore)</a>
4
5
 
5
- Package contains:
6
+ A core package for LikeC4, containing types, api, utilities and guards.
6
7
 
7
- - types
8
- - utilities and guards
9
- - errors
8
+ > [!NOTE]
9
+ > This package is a low level API for working with LikeC4.\
10
+ > It is exposed mostly through [`likec4`](../likec4/README.md), that generates models from DSL.
11
+
12
+ ## Types
13
+
14
+ Includes a set of types that are used across the project
15
+
16
+ ```ts
17
+ import type {
18
+ DiagramView,
19
+ Element,
20
+ ElementViewPredicate,
21
+ Fqn,
22
+ // ....
23
+ } from '@likec4/core/types'
24
+ ```
25
+
26
+ There is some concept that allows to build models in a type-safe way.\
27
+ Consider the following example:
28
+
29
+ ```ts
30
+ import type { aux } from '@likec4/core/types'
31
+
32
+ interface Element<A extends aux.Any = aux.Any> {
33
+ id: aux.Fqn<A>
34
+ kind: aux.ElementKind<A>
35
+ title: string
36
+ tags: aux.Tags<A>
37
+ }
38
+ ```
39
+
40
+ `Aux` is a registry that keeps track of the specification (kinds, tags), all the elements and views.
41
+ Thus, it is used to generate types for the identifiers (FQNs, view predicates, etc.).
42
+
43
+ When you generate the model from DSL or use builder, `Aux` is generated automatically.
44
+
45
+ You can use `aux.Any` as the default type, that infers to string.
46
+
47
+ ## Model API
48
+
49
+ This is the main API to work with LikeC4 model.\
50
+ It provides methods to query and traverse the model (get element, children, incoming relationships, etc.)\
51
+ Model is built from `ModelData`, and has three stages:
52
+
53
+ - `parsed`\
54
+ Sourced from `ParsedLikeC4ModelData` - represents model parsed from DSL or generated using builder.\
55
+ All the elements and relations are available, but views are not processed yet, and have `rules[]` property (that are predicates to compute)\
56
+ These views are available as `ParsedView`, or `ParsedDynamicView` as a type for specific view.
57
+
58
+ - `computed`\
59
+ Model is computed from parsed model (source type `ComputedLikeC4ModelData`)\
60
+ Now views are available as `ComputedView` (or `ComputedDynamicView`), and have nodes and edges.\
61
+ Also, elements have additional traversal methods, like `views()` - to get views where element is included.
62
+
63
+ - `layouted`\
64
+ Model is layouted from computed model.\
65
+ Now every view (and its nodes and edges) has layout data (dimensions, positions).\
66
+ Source type is `LayoutedLikeC4ModelData`.
67
+ Views are available as `LayoutedView` (or `DiagramView`)
68
+
69
+ Example:
70
+
71
+ ```ts
72
+ const parsedData: ParsedLikeC4ModelData<Aux1> = {}
73
+ const computedData: ComputedLikeC4ModelData<Aux2> = {}
74
+ const layoutedData: LayoutedLikeC4ModelData<Aux3> = {}
75
+
76
+ const m1 = LikeC4Model.create(parsedData)
77
+ // m1 is LikeC4Model.Parsed<Aux1>
78
+ // m1.stage === 'parsed'
79
+
80
+ const m2 = LikeC4Model.create(computedData)
81
+ // m2 is LikeC4Model.Computed<Aux2>
82
+ // m2.stage === 'computed'
83
+
84
+ const m3 = LikeC4Model.create(layoutedData)
85
+ // m3 is LikeC4Model.Layouted<Aux3>
86
+ // m3.stage === 'layouted'
87
+ ```
88
+
89
+ `LikeC4Model.create` expects `Aux` to be provided, or fallback to `aux.Any`.
90
+
91
+ There is also `LikeC4Model.fromDump` method, that infers `Aux` from the code (if constant is given).
92
+
93
+ > [!TIP]
94
+ > Try `npx likec4 codegen model` to play with your model.
95
+
96
+ ### Usage
97
+
98
+ If Model has `Aux` with literals, every method is type-safe:
99
+
100
+ ```ts
101
+ // Compiler error here, if there is no element with such FQN
102
+ model.element('non.existing.element')
103
+
104
+ // Workaround:
105
+ model.findElement('non.existing.element') // returns ElementModel | null
106
+ ```
107
+
108
+ Other examples:
109
+
110
+ ```ts
111
+ // Get model source
112
+ const source = model.$data
113
+
114
+ // Get elements of some kind
115
+ const elements = model.elementsOfKind('kind1')
116
+
117
+ // Use where operator to filter elements:
118
+ // kind is 'kind1' and (tag is 'tag2' or tag is not 'tag3')
119
+ const elements = model.elementsWhere({
120
+ and: [
121
+ { kind: 'kind1' },
122
+ {
123
+ or: [
124
+ { tag: 'tag2' },
125
+ {
126
+ tag: {
127
+ neq: 'tag3',
128
+ },
129
+ },
130
+ ],
131
+ },
132
+ ],
133
+ })
134
+
135
+ // Find all views, tagged with "tag1" and scoped for elements nested in "parent"
136
+ const parent = model.element('some.parent')
137
+ for (const v of model.findByTag('tag1', 'views')) {
138
+ if (v.isScopedElementView() && v.viewOf.isDescendantOf(parent)) {
139
+ //
140
+ }
141
+ }
142
+
143
+ // Deployment model
144
+ for (const node of model.deployment.nodes()) {
145
+ if (node.isDeployedInstance()) {
146
+ // node is DeploymentNodeModel
147
+ }
148
+ }
149
+ ```
150
+
151
+ > [!NOTE]
152
+ > Most methods return lazy evaluated iterators, use `for...of` or spread operator to retrieve all values (or methods like [`toArray()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/toArray))
153
+
154
+ Models have guards to check their type, like in example above we check if view is a scoped element view.
155
+
156
+ Generic guards are also available in `@likec4/core/model`:
157
+
158
+ ```ts
159
+ import {
160
+ isElementModel,,
161
+ isDeployedInstanceModel,
162
+ isLikeC4ViewModel,
163
+ // ... other guards
164
+ } from '@likec4/core/model'
165
+ ```
166
+
167
+ ### Connections
168
+
169
+ Connections can be used to find all relationships between elements (direct or derived).
170
+
171
+ ```ts
172
+ import { modelConnection } from '@likec4/core/model'
173
+
174
+ const source = model.element('some.source')
175
+ const target = model.element('some.target')
176
+
177
+ const connection = modelConnection.findConnection(source, target)
178
+ ```
179
+
180
+ Check [sources](./src/model/index.ts) for available methods.
181
+
182
+ ### Compute Model
183
+
184
+ You rarely need to compute model yourself, but in case you need to:
185
+
186
+ ```ts
187
+ import { computeLikeC4Model } from '@likec4/core/compute-view'
188
+
189
+ const parsedData: ParsedLikeC4ModelData<Aux1> = {}
190
+ const model = computeLikeC4Model(parsedData)
191
+ ```
192
+
193
+ ## Model Builder
194
+
195
+ We use it internally a lot for testing, but it is also available for you to build models in a type-safe way.
196
+
197
+ Two styles are available. You can mix both styles, depending on your preference and use cases.
198
+
199
+ ### via chain
200
+
201
+ ```ts
202
+ import { Builder } from '@likec4/core/builder'
203
+
204
+ const m = Builder
205
+ .specification({
206
+ elements: {
207
+ actor: {
208
+ style: {
209
+ shape: 'person',
210
+ },
211
+ },
212
+ system: {},
213
+ component: {},
214
+ },
215
+ relationships: {
216
+ likes: {},
217
+ },
218
+ tags: ['tag1', 'tag2', 'tag1'],
219
+ })
220
+ .model(({ actor, system, component, relTo, rel }, _) =>
221
+ _(
222
+ actor('alice'),
223
+ actor('bob'),
224
+ rel('alice', 'bob', {
225
+ tags: ['tag1'], // you get code completion for tags
226
+ kind: 'likes', // code completion for kind
227
+ }),
228
+ system('cloud', { tags: ['tag1', 'tag2'] }).with(
229
+ component('backend').with(
230
+ component('api'),
231
+ component('db'),
232
+ // code completion for relationships
233
+ rel('cloud.backend.api', 'cloud.backend.db'),
234
+ ),
235
+ component('frontend').with(
236
+ relTo('cloud.backend.api'),
237
+ ),
238
+ ),
239
+ )
240
+ )
241
+ .views(({ view, viewOf, $include, $style }, _) =>
242
+ _(
243
+ view('index', 'Index').with(
244
+ // code completion for predicates
245
+ $include('cloud.*'),
246
+ ),
247
+ viewOf('ui', 'cloud.ui').with(
248
+ $include('* -> cloud.**'),
249
+ $style('cloud.ui', { color: 'red' }),
250
+ ),
251
+ )
252
+ )
253
+ .toLikeC4Model()
254
+ ```
255
+
256
+ Builder has two methods:
257
+
258
+ - `build()`: returns `ParsedLikeC4ModelData`
259
+ - `toLikeC4Model()`: returns already computed `LikeC4Model`
260
+
261
+ ### via composition
262
+
263
+ ```ts
264
+ import { Builder } from '@likec4/core/builder'
265
+
266
+ // Get composition functions for given specification
267
+ const {
268
+ model: {
269
+ model,
270
+ actor,
271
+ system,
272
+ component,
273
+ rel,
274
+ relTo,
275
+ },
276
+ views: {
277
+ view,
278
+ viewOf,
279
+ views,
280
+ $include,
281
+ $style,
282
+ },
283
+ builder,
284
+ } = Builder.forSpecification({
285
+ elements: {
286
+ actor: {
287
+ style: {
288
+ shape: 'person',
289
+ },
290
+ },
291
+ system: {},
292
+ component: {},
293
+ },
294
+ relationships: {
295
+ likes: {},
296
+ },
297
+ tags: ['tag1', 'tag2', 'tag1'],
298
+ })
299
+
300
+ const b1 = builder.with(
301
+ model(
302
+ actor('alice'),
303
+ actor('bob'),
304
+ rel('alice', 'bob', {
305
+ tags: ['tag1'],
306
+ kind: 'likes',
307
+ }),
308
+ system('cloud', { tags: ['tag1', 'tag2'] }).with(
309
+ component('backend').with(
310
+ component('api'),
311
+ component('db'),
312
+ rel('cloud.backend.api', 'cloud.backend.db'),
313
+ ),
314
+ component('frontend').with(
315
+ relTo('cloud.backend.api'),
316
+ ),
317
+ ),
318
+ ),
319
+ )
320
+
321
+ const b2 = b1.with(
322
+ views(
323
+ view('index', 'Index').with(
324
+ $include('cloud.*'),
325
+ ),
326
+ viewOf('ui', 'cloud.ui').with(
327
+ $include('* -> cloud.**'),
328
+ $style('cloud.ui', { color: 'red' }),
329
+ ),
330
+ ),
331
+ )
332
+ .toLikeC4Model()
333
+ ```
334
+
335
+ > [!TIP]
336
+ > You can also use specification from existing model:
337
+ >
338
+ > ```ts
339
+ > const b = Builder.specification(existingModel.specification)
340
+ > ```
341
+
342
+ ## Utils
343
+
344
+ Project uses [remeda](https://remedajs.com/) internally, and exports some model-related utilities.\
345
+ Check sources for available functions.
346
+
347
+ ### Full Qualified Name (FQN) utils
348
+
349
+ There are various functions to work with Full Qualified Name (FQN) of elements, like `isAncestor`, `commonAncestor`, `compareFqnHierarchically`, etc.
350
+
351
+ ```ts
352
+ import { isAncestor, isDescendantOf, sortNaturalByFqn } from '@likec4/core/utils'
353
+
354
+ if (isAncestor('parent', 'child')) {
355
+ // do something
356
+ }
357
+
358
+ // filter elements that are descendants of parent
359
+ elements.filter(isDescendantOf(parent))
360
+
361
+ // Sort elements by FQN, like
362
+ // a
363
+ // a.b2
364
+ // a.b10
365
+ // a.b.c
366
+ sortNaturalByFqn(elements)
367
+ ```
368
+
369
+ ### Iterables
370
+
371
+ Functions like `filter`, `find`, `flat`, `map`, `reduce`, `some`, `unique`, but for iterables, are available as `i*` functions, and can be used in pipelines.
372
+
373
+ ```ts
374
+ import { isElementModel } from '@likec4/core/model'
375
+ import { ifilter, imap } from '@likec4/core/utils'
376
+ import { isTruthy, pipe, prop } from 'remeda'
377
+
378
+ pipe(
379
+ model.findByTag('tag1'),
380
+ ifilter(isElementModel),
381
+ imap(prop('defaultView')),
382
+ ifilter(isTruthy),
383
+ )
384
+ ```
385
+
386
+ This composes to single iterator, avoiding intermediate arrays.
387
+
388
+ ## Getting help
389
+
390
+ We are always happy to help you get started:
391
+
392
+ - [Join Discord community](https://discord.gg/86ZSpjKAdA) – it is the easiest way to get help
393
+ - [GitHub Discussions](https://github.com/likec4/likec4/discussions) – ask anything about the project or give feedback
394
+
395
+ ## Contributors
396
+
397
+ <a href="https://github.com/likec4/likec4/graphs/contributors">
398
+ <img src="https://contrib.rocks/image?repo=likec4/likec4" />
399
+ </a>
400
+
401
+ [Become a contributor](../../CONTRIBUTING.md)
402
+
403
+ ## Support development
404
+
405
+ LikeC4 is a MIT-licensed open source project with its ongoing development made possible entirely by your support.\
406
+ If you like the project, please consider contributing financially to help grow and improve it.\
407
+ You can support us via [OpenCollective](https://opencollective.com/likec4) or [GitHub Sponsors](https://github.com/sponsors/likec4).
408
+
409
+ ## License
410
+
411
+ This project is released under the [MIT License](LICENSE)