@api-client/core 0.11.10 → 0.12.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 (252) hide show
  1. package/Testing.md +1 -1
  2. package/bin/plugins/events/EventPlugin.ts +61 -0
  3. package/bin/plugins/events/assert.ts +193 -0
  4. package/bin/plugins/events/types.ts +6 -0
  5. package/bin/test.ts +8 -1
  6. package/build/src/amf/AmfShapeGenerator.d.ts +6 -3
  7. package/build/src/amf/AmfShapeGenerator.d.ts.map +1 -1
  8. package/build/src/amf/AmfShapeGenerator.js +4 -1
  9. package/build/src/amf/AmfShapeGenerator.js.map +1 -1
  10. package/build/src/amf/AmfTypes.d.ts +2 -2
  11. package/build/src/amf/AmfTypes.d.ts.map +1 -1
  12. package/build/src/amf/AmfTypes.js.map +1 -1
  13. package/build/src/amf/DataValueGenerator.d.ts +15 -15
  14. package/build/src/amf/DataValueGenerator.d.ts.map +1 -1
  15. package/build/src/amf/DataValueGenerator.js +14 -14
  16. package/build/src/amf/DataValueGenerator.js.map +1 -1
  17. package/build/src/browser.d.ts +12 -9
  18. package/build/src/browser.d.ts.map +1 -1
  19. package/build/src/browser.js +11 -8
  20. package/build/src/browser.js.map +1 -1
  21. package/build/src/exceptions/attach_exception.d.ts +11 -0
  22. package/build/src/exceptions/attach_exception.d.ts.map +1 -0
  23. package/build/src/exceptions/attach_exception.js +11 -0
  24. package/build/src/exceptions/attach_exception.js.map +1 -0
  25. package/build/src/exceptions/detach_exception.d.ts +11 -0
  26. package/build/src/exceptions/detach_exception.d.ts.map +1 -0
  27. package/build/src/exceptions/detach_exception.js +11 -0
  28. package/build/src/exceptions/detach_exception.js.map +1 -0
  29. package/build/src/exceptions/remove_model_exception.d.ts +8 -0
  30. package/build/src/exceptions/remove_model_exception.d.ts.map +1 -0
  31. package/build/src/exceptions/remove_model_exception.js +8 -0
  32. package/build/src/exceptions/remove_model_exception.js.map +1 -0
  33. package/build/src/exceptions/remove_namespace_exception.d.ts +8 -0
  34. package/build/src/exceptions/remove_namespace_exception.d.ts.map +1 -0
  35. package/build/src/exceptions/remove_namespace_exception.js +8 -0
  36. package/build/src/exceptions/remove_namespace_exception.js.map +1 -0
  37. package/build/src/index.d.ts +12 -9
  38. package/build/src/index.d.ts.map +1 -1
  39. package/build/src/index.js +11 -8
  40. package/build/src/index.js.map +1 -1
  41. package/build/src/legacy.d.ts +8 -0
  42. package/build/src/legacy.d.ts.map +1 -1
  43. package/build/src/legacy.js +9 -0
  44. package/build/src/legacy.js.map +1 -1
  45. package/build/src/modeling/Bindings.d.ts +2 -2
  46. package/build/src/modeling/Bindings.d.ts.map +1 -1
  47. package/build/src/modeling/Bindings.js.map +1 -1
  48. package/build/src/modeling/DataDomain.d.ts +601 -0
  49. package/build/src/modeling/DataDomain.d.ts.map +1 -0
  50. package/build/src/modeling/DataDomain.js +1142 -0
  51. package/build/src/modeling/DataDomain.js.map +1 -0
  52. package/build/src/modeling/DataFormat.d.ts +42 -41
  53. package/build/src/modeling/DataFormat.d.ts.map +1 -1
  54. package/build/src/modeling/DataFormat.js +30 -131
  55. package/build/src/modeling/DataFormat.js.map +1 -1
  56. package/build/src/modeling/DomainAssociation.d.ts +281 -0
  57. package/build/src/modeling/DomainAssociation.d.ts.map +1 -0
  58. package/build/src/modeling/DomainAssociation.js +440 -0
  59. package/build/src/modeling/DomainAssociation.js.map +1 -0
  60. package/build/src/modeling/DomainElement.d.ts +33 -0
  61. package/build/src/modeling/DomainElement.d.ts.map +1 -0
  62. package/build/src/modeling/DomainElement.js +32 -0
  63. package/build/src/modeling/DomainElement.js.map +1 -0
  64. package/build/src/modeling/DomainEntity.d.ts +383 -0
  65. package/build/src/modeling/DomainEntity.d.ts.map +1 -0
  66. package/build/src/modeling/DomainEntity.js +718 -0
  67. package/build/src/modeling/DomainEntity.js.map +1 -0
  68. package/build/src/modeling/DomainFile.d.ts +25 -0
  69. package/build/src/modeling/DomainFile.d.ts.map +1 -0
  70. package/build/src/modeling/DomainFile.js +86 -0
  71. package/build/src/modeling/DomainFile.js.map +1 -0
  72. package/build/src/modeling/DomainImpactAnalysis.d.ts +60 -47
  73. package/build/src/modeling/DomainImpactAnalysis.d.ts.map +1 -1
  74. package/build/src/modeling/DomainImpactAnalysis.js +201 -132
  75. package/build/src/modeling/DomainImpactAnalysis.js.map +1 -1
  76. package/build/src/modeling/DomainModel.d.ts +226 -0
  77. package/build/src/modeling/DomainModel.d.ts.map +1 -0
  78. package/build/src/modeling/DomainModel.js +401 -0
  79. package/build/src/modeling/DomainModel.js.map +1 -0
  80. package/build/src/modeling/DomainNamespace.d.ts +268 -0
  81. package/build/src/modeling/DomainNamespace.d.ts.map +1 -0
  82. package/build/src/modeling/DomainNamespace.js +512 -0
  83. package/build/src/modeling/DomainNamespace.js.map +1 -0
  84. package/build/src/modeling/DomainProperty.d.ts +281 -0
  85. package/build/src/modeling/DomainProperty.d.ts.map +1 -0
  86. package/build/src/modeling/DomainProperty.js +560 -0
  87. package/build/src/modeling/DomainProperty.js.map +1 -0
  88. package/build/src/modeling/DomainSerialization.d.ts +40 -0
  89. package/build/src/modeling/DomainSerialization.d.ts.map +1 -0
  90. package/build/src/modeling/DomainSerialization.js +288 -0
  91. package/build/src/modeling/DomainSerialization.js.map +1 -0
  92. package/build/src/modeling/DomainVersioning.d.ts +17 -0
  93. package/build/src/modeling/DomainVersioning.d.ts.map +1 -0
  94. package/build/src/modeling/DomainVersioning.js +124 -0
  95. package/build/src/modeling/DomainVersioning.js.map +1 -0
  96. package/build/src/modeling/GraphUtils.d.ts +8 -0
  97. package/build/src/modeling/GraphUtils.d.ts.map +1 -0
  98. package/build/src/modeling/GraphUtils.js +26 -0
  99. package/build/src/modeling/GraphUtils.js.map +1 -0
  100. package/build/src/modeling/amf/ShapeGenerator.d.ts +164 -0
  101. package/build/src/modeling/amf/ShapeGenerator.d.ts.map +1 -0
  102. package/build/src/modeling/amf/ShapeGenerator.js +492 -0
  103. package/build/src/modeling/amf/ShapeGenerator.js.map +1 -0
  104. package/build/src/modeling/{DataAssociation.d.ts → legacy/DataAssociation.d.ts} +10 -5
  105. package/build/src/modeling/legacy/DataAssociation.d.ts.map +1 -0
  106. package/build/src/modeling/{DataAssociation.js → legacy/DataAssociation.js} +9 -6
  107. package/build/src/modeling/legacy/DataAssociation.js.map +1 -0
  108. package/build/src/modeling/{DataEntity.d.ts → legacy/DataEntity.d.ts} +12 -7
  109. package/build/src/modeling/legacy/DataEntity.d.ts.map +1 -0
  110. package/build/src/modeling/{DataEntity.js → legacy/DataEntity.js} +19 -18
  111. package/build/src/modeling/legacy/DataEntity.js.map +1 -0
  112. package/build/src/modeling/{DataEntityBuilder.d.ts → legacy/DataEntityBuilder.d.ts} +3 -2
  113. package/build/src/modeling/legacy/DataEntityBuilder.d.ts.map +1 -0
  114. package/build/src/modeling/{DataEntityBuilder.js → legacy/DataEntityBuilder.js} +3 -2
  115. package/build/src/modeling/legacy/DataEntityBuilder.js.map +1 -0
  116. package/build/src/modeling/legacy/DataImpactAnalysis.d.ts +298 -0
  117. package/build/src/modeling/legacy/DataImpactAnalysis.d.ts.map +1 -0
  118. package/build/src/modeling/legacy/DataImpactAnalysis.js +441 -0
  119. package/build/src/modeling/legacy/DataImpactAnalysis.js.map +1 -0
  120. package/build/src/modeling/{DataModel.d.ts → legacy/DataModel.d.ts} +6 -4
  121. package/build/src/modeling/legacy/DataModel.d.ts.map +1 -0
  122. package/build/src/modeling/{DataModel.js → legacy/DataModel.js} +7 -6
  123. package/build/src/modeling/legacy/DataModel.js.map +1 -0
  124. package/build/src/modeling/{DataNamespace.d.ts → legacy/DataNamespace.d.ts} +22 -3
  125. package/build/src/modeling/legacy/DataNamespace.d.ts.map +1 -0
  126. package/build/src/modeling/{DataNamespace.js → legacy/DataNamespace.js} +7 -3
  127. package/build/src/modeling/legacy/DataNamespace.js.map +1 -0
  128. package/build/src/modeling/{DataProperty.d.ts → legacy/DataProperty.d.ts} +13 -5
  129. package/build/src/modeling/legacy/DataProperty.d.ts.map +1 -0
  130. package/build/src/modeling/{DataProperty.js → legacy/DataProperty.js} +8 -5
  131. package/build/src/modeling/legacy/DataProperty.js.map +1 -0
  132. package/build/src/modeling/observed.d.ts +67 -0
  133. package/build/src/modeling/observed.d.ts.map +1 -0
  134. package/build/src/modeling/observed.js +230 -0
  135. package/build/src/modeling/observed.js.map +1 -0
  136. package/build/src/modeling/types.d.ts +165 -1
  137. package/build/src/modeling/types.d.ts.map +1 -1
  138. package/build/src/modeling/types.js.map +1 -1
  139. package/build/src/models/Thing.d.ts +26 -5
  140. package/build/src/models/Thing.d.ts.map +1 -1
  141. package/build/src/models/Thing.js +193 -91
  142. package/build/src/models/Thing.js.map +1 -1
  143. package/build/src/models/kinds.d.ts +31 -6
  144. package/build/src/models/kinds.d.ts.map +1 -1
  145. package/build/src/models/kinds.js +31 -6
  146. package/build/src/models/kinds.js.map +1 -1
  147. package/build/src/models/store/DataFile.d.ts +3 -1
  148. package/build/src/models/store/DataFile.d.ts.map +1 -1
  149. package/build/src/models/store/DataFile.js +2 -0
  150. package/build/src/models/store/DataFile.js.map +1 -1
  151. package/build/src/models/types.d.ts +12 -0
  152. package/build/src/models/types.d.ts.map +1 -0
  153. package/build/src/models/types.js +2 -0
  154. package/build/src/models/types.js.map +1 -0
  155. package/build/src/runtime/store/FilesSdk.d.ts +2 -2
  156. package/build/src/runtime/store/FilesSdk.d.ts.map +1 -1
  157. package/build/src/runtime/store/FilesSdk.js.map +1 -1
  158. package/data/models/example-generator-api.json +26 -26
  159. package/package.json +20 -6
  160. package/readme.md +1 -1
  161. package/src/amf/AmfShapeGenerator.ts +7 -4
  162. package/src/amf/AmfTypes.ts +2 -2
  163. package/src/amf/DataValueGenerator.ts +21 -21
  164. package/src/exceptions/attach_exception.ts +11 -0
  165. package/src/exceptions/detach_exception.ts +11 -0
  166. package/src/exceptions/remove_model_exception.ts +8 -0
  167. package/src/exceptions/remove_namespace_exception.ts +8 -0
  168. package/src/modeling/Bindings.ts +2 -2
  169. package/src/modeling/DataDomain.ts +1221 -0
  170. package/src/modeling/DataFormat.ts +54 -163
  171. package/src/modeling/DomainAssociation.ts +476 -0
  172. package/src/modeling/DomainElement.ts +50 -0
  173. package/src/modeling/DomainEntity.ts +769 -0
  174. package/src/modeling/DomainFile.ts +94 -0
  175. package/src/modeling/DomainImpactAnalysis.ts +218 -144
  176. package/src/modeling/DomainModel.ts +421 -0
  177. package/src/modeling/DomainNamespace.ts +537 -0
  178. package/src/modeling/DomainProperty.ts +548 -0
  179. package/src/modeling/DomainSerialization.ts +312 -0
  180. package/src/modeling/DomainVersioning.ts +144 -0
  181. package/src/modeling/GraphUtils.ts +28 -0
  182. package/src/modeling/amf/ShapeGenerator.ts +552 -0
  183. package/src/modeling/graph.md +115 -0
  184. package/src/modeling/{DataAssociation.ts → legacy/DataAssociation.ts} +13 -8
  185. package/src/modeling/{DataEntity.ts → legacy/DataEntity.ts} +28 -23
  186. package/src/modeling/{DataEntityBuilder.ts → legacy/DataEntityBuilder.ts} +4 -3
  187. package/src/modeling/legacy/DataImpactAnalysis.ts +530 -0
  188. package/src/modeling/{DataModel.ts → legacy/DataModel.ts} +10 -8
  189. package/src/modeling/{DataNamespace.ts → legacy/DataNamespace.ts} +23 -5
  190. package/src/modeling/{DataProperty.ts → legacy/DataProperty.ts} +15 -7
  191. package/src/modeling/observed.ts +267 -0
  192. package/src/modeling/types.ts +174 -1
  193. package/src/models/Thing.ts +70 -5
  194. package/src/models/kinds.ts +32 -6
  195. package/src/models/store/DataFile.ts +3 -1
  196. package/src/models/types.ts +11 -0
  197. package/src/runtime/store/FilesSdk.ts +2 -6
  198. package/tests/unit/amf/data_value_generator.spec.ts +15 -15
  199. package/tests/unit/legacy-transformers/ARC-legacy-import.spec.ts +1 -1
  200. package/tests/unit/modeling/amf/shape_generator.spec.ts +1174 -0
  201. package/tests/unit/modeling/data_domain.spec.ts +444 -0
  202. package/tests/unit/modeling/data_domain_associations.spec.ts +279 -0
  203. package/tests/unit/modeling/data_domain_change_observers.spec.ts +681 -0
  204. package/tests/unit/modeling/data_domain_entities.spec.ts +449 -0
  205. package/tests/unit/modeling/data_domain_foreign.spec.ts +355 -0
  206. package/tests/unit/modeling/data_domain_models.spec.ts +658 -0
  207. package/tests/unit/modeling/data_domain_namespaces.spec.ts +668 -0
  208. package/tests/unit/modeling/data_domain_property.spec.ts +264 -0
  209. package/tests/unit/modeling/data_domain_serialization.spec.ts +294 -0
  210. package/tests/unit/modeling/domain.property.spec.ts +822 -0
  211. package/tests/unit/modeling/domain_asociation.spec.ts +643 -0
  212. package/tests/unit/modeling/domain_asociation_targets.spec.ts +350 -0
  213. package/tests/unit/modeling/domain_entity.spec.ts +730 -0
  214. package/tests/unit/modeling/domain_entity_associations.spec.ts +330 -0
  215. package/tests/unit/modeling/domain_entity_example_generator_json.spec.ts +988 -0
  216. package/tests/unit/modeling/domain_entity_example_generator_xml.spec.ts +1451 -0
  217. package/tests/unit/modeling/domain_entity_fields.spec.ts +113 -0
  218. package/tests/unit/modeling/domain_entity_generators.spec.ts +20 -0
  219. package/tests/unit/modeling/domain_entity_parents.spec.ts +291 -0
  220. package/tests/unit/modeling/domain_entity_properties.spec.ts +305 -0
  221. package/tests/unit/modeling/{data_file.spec.ts → domain_file.spec.ts} +29 -85
  222. package/tests/unit/modeling/domain_impact_analysis.spec.ts +452 -0
  223. package/tests/unit/modeling/domain_model.spec.ts +568 -0
  224. package/tests/unit/modeling/domain_model_entities.spec.ts +408 -0
  225. package/tests/unit/modeling/domain_namespace.spec.ts +514 -0
  226. package/tests/unit/modeling/domain_namespace_models.spec.ts +324 -0
  227. package/tests/unit/modeling/domain_namespace_namespaces.spec.ts +404 -0
  228. package/tests/unit/modeling/domain_versioning.spec.ts +140 -0
  229. package/tests/unit/{amf → modeling/legacy}/amf_shape_generator.spec.ts +11 -11
  230. package/tests/unit/modeling/{data_association.spec.ts → legacy/data_association.spec.ts} +3 -11
  231. package/tests/unit/modeling/{data_entity.spec.ts → legacy/data_entity.spec.ts} +10 -8
  232. package/tests/unit/modeling/{data_entity_generator_json.spec.ts → legacy/data_entity_generator_json.spec.ts} +1 -1
  233. package/tests/unit/modeling/{data_entity_generator_xml.spec.ts → legacy/data_entity_generator_xml.spec.ts} +1 -1
  234. package/tests/unit/modeling/{data_model.spec.ts → legacy/data_model.spec.ts} +3 -3
  235. package/tests/unit/modeling/{data_namespace.spec.ts → legacy/data_namespace.spec.ts} +3 -10
  236. package/tests/unit/modeling/{data_property.spec.ts → legacy/data_property.spec.ts} +3 -6
  237. package/tests/unit/modeling/{impact_analysis.spec.ts → legacy/impact_analysis.spec.ts} +9 -9
  238. package/tests/unit/models/File/new.spec.ts +1 -1
  239. package/tests/unit/models/HttpProject.spec.ts +3 -3
  240. package/tsconfig.node.json +35 -0
  241. package/build/src/modeling/DataAssociation.d.ts.map +0 -1
  242. package/build/src/modeling/DataAssociation.js.map +0 -1
  243. package/build/src/modeling/DataEntity.d.ts.map +0 -1
  244. package/build/src/modeling/DataEntity.js.map +0 -1
  245. package/build/src/modeling/DataEntityBuilder.d.ts.map +0 -1
  246. package/build/src/modeling/DataEntityBuilder.js.map +0 -1
  247. package/build/src/modeling/DataModel.d.ts.map +0 -1
  248. package/build/src/modeling/DataModel.js.map +0 -1
  249. package/build/src/modeling/DataNamespace.d.ts.map +0 -1
  250. package/build/src/modeling/DataNamespace.js.map +0 -1
  251. package/build/src/modeling/DataProperty.d.ts.map +0 -1
  252. package/build/src/modeling/DataProperty.js.map +0 -1
@@ -0,0 +1,421 @@
1
+ import type { DataDomain } from './DataDomain.js'
2
+ import { DomainEntityKind, DomainModelKind } from '../models/kinds.js'
3
+ import { DomainElement, DomainElementSchema } from './DomainElement.js'
4
+ import { nanoid } from 'nanoid'
5
+ import { type IThing, Thing } from '../models/Thing.js'
6
+ import { observed, retargetChange } from './observed.js'
7
+ import type { DomainNamespace } from './DomainNamespace.js'
8
+ import type { FileBreadcrumb } from '../models/store/File.js'
9
+ import { DomainEntity, type DomainEntitySchema } from './DomainEntity.js'
10
+ import { RemoveEntityException } from '../exceptions/remove_entity_exception.js'
11
+ import { removeGraphNode } from './GraphUtils.js'
12
+ import { AttachException } from '../exceptions/attach_exception.js'
13
+ import { DetachException } from '../exceptions/detach_exception.js'
14
+
15
+ export interface ModelOrderedItem {
16
+ /**
17
+ * The type of the ordered item.
18
+ */
19
+ type: 'entity'
20
+
21
+ /**
22
+ * The key of the ordered item.
23
+ */
24
+ key: string
25
+ }
26
+
27
+ export interface DomainModelSchema extends DomainElementSchema {
28
+ kind: typeof DomainModelKind
29
+ /**
30
+ * The data model description.
31
+ */
32
+ info: IThing
33
+ /**
34
+ * The ordered list of entities in the schema.
35
+ */
36
+ fields?: ModelOrderedItem[]
37
+
38
+ /**
39
+ * Whether this model is deprecated.
40
+ */
41
+ deprecated?: boolean
42
+ }
43
+
44
+ /**
45
+ * Represents a data model within a data domain.
46
+ *
47
+ * A `DomainModel` groups related `DomainEntity` instances, providing a logical structure for organizing
48
+ * data. It acts as a container for entities that share a common purpose or context.
49
+ *
50
+ * **Key Features:**
51
+ *
52
+ * - **Entity Container:** Holds a collection of `DomainEntity` instances.
53
+ * - **Logical Grouping:** Organizes entities into meaningful groups.
54
+ * - **Metadata:** Supports a description for the data model.
55
+ * - **Namespace Integration:** Belongs to a `DomainNamespace`, creating a hierarchical structure.
56
+ *
57
+ * **Usage:**
58
+ *
59
+ * The preferred way to create a `DomainModel` is through
60
+ * the `DomainNamespace.addModel()` or
61
+ * `DataDomain.addModel()` method.
62
+ *
63
+ * **Example:**
64
+ *
65
+ * ```typescript
66
+ * const dataDomain = new DataDomain();
67
+ * const dataNamespace = dataDomain.addNamespace({
68
+ * key: 'myNamespace',
69
+ * });
70
+ * const userModel = dataNamespace.addModel({
71
+ * key: 'userModel',
72
+ * info: { name: 'User Model' },
73
+ * });
74
+ * ```
75
+ */
76
+ export class DomainModel extends DomainElement {
77
+ override kind: typeof DomainModelKind
78
+
79
+ /**
80
+ * The description of the domain model.
81
+ */
82
+ @retargetChange() accessor info: Thing
83
+
84
+ /**
85
+ * The ordered list of entities in the schema.
86
+ */
87
+ accessor fields: ModelOrderedItem[]
88
+ /**
89
+ * Whether this model is deprecated.
90
+ */
91
+ @observed() accessor deprecated: boolean | undefined
92
+
93
+ /**
94
+ * Creates a full data model schema with defaults.
95
+ * @param input The partial data model schema.
96
+ * @returns The data model schema.
97
+ */
98
+ static createSchema(input: Partial<DomainModelSchema> = {}): DomainModelSchema {
99
+ const { key = nanoid(), fields, deprecated } = input
100
+ const info = Thing.fromJSON(input.info, { name: 'New model' }).toJSON()
101
+ const result: DomainModelSchema = {
102
+ kind: DomainModelKind,
103
+ key,
104
+ info,
105
+ }
106
+ if (Array.isArray(fields)) {
107
+ result.fields = [...fields]
108
+ }
109
+ if (typeof deprecated === 'boolean') {
110
+ result.deprecated = deprecated
111
+ }
112
+ return result
113
+ }
114
+
115
+ /**
116
+ * Creates a new model instance.
117
+ *
118
+ * You should use the `DomainNamespace.addModel()` or
119
+ * `DataDomain.addModel()` method instead.
120
+ *
121
+ * @param root A reference to the root DataDomain instance.
122
+ * @param input The partial model schema.
123
+ */
124
+ constructor(root: DataDomain, input?: Partial<DomainModelSchema>) {
125
+ const init = DomainModel.createSchema(input)
126
+ super(root, init.key)
127
+ this.kind = DomainModelKind
128
+ this.info = new Thing(init.info)
129
+ if (Array.isArray(init.fields)) {
130
+ this.fields = [...init.fields]
131
+ } else {
132
+ this.fields = []
133
+ }
134
+ if (typeof init.deprecated === 'boolean') {
135
+ this.deprecated = init.deprecated
136
+ } else {
137
+ this.deprecated = undefined
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Generates a JSON representation of the data model.
143
+ *
144
+ * @returns A plain object representation of the
145
+ * `DomainModel`.
146
+ * @example
147
+ * ```typescript
148
+ * const json = userModel.toJSON();
149
+ * console.log(json);
150
+ * ```
151
+ */
152
+ toJSON(): DomainModelSchema {
153
+ const result: DomainModelSchema = {
154
+ kind: this.kind,
155
+ key: this.key,
156
+ info: this.info.toJSON(),
157
+ }
158
+ if (Array.isArray(this.fields) && this.fields.length) {
159
+ result.fields = [...this.fields]
160
+ }
161
+ if (typeof this.deprecated === 'boolean') {
162
+ result.deprecated = this.deprecated
163
+ }
164
+ return result
165
+ }
166
+
167
+ /**
168
+ * Returns the parent namespace where this data model
169
+ * exists.
170
+ *
171
+ * @returns The parent `DomainNamespace`.
172
+ * @throws Error When no parent is found.
173
+ * @example
174
+ * ```typescript
175
+ * const parent = userModel.getParentInstance();
176
+ * console.log(parent.key);
177
+ * ```
178
+ */
179
+ getParentInstance(): DomainNamespace | DataDomain {
180
+ const parentKey = this.root.graph.parent(this.key)
181
+ if (!parentKey) {
182
+ return this.root
183
+ }
184
+ return this.root.graph.node(parentKey) as DomainNamespace
185
+ }
186
+
187
+ /**
188
+ * Adds a child entity to the current model.
189
+ *
190
+ * @param value The partial entity schema.
191
+ * @returns The created entity instance.
192
+ * @example
193
+ * ```typescript
194
+ * const entity = model.addEntity({
195
+ * key: 'address',
196
+ * info: { name: 'Address' },
197
+ * })
198
+ * ```
199
+ */
200
+ addEntity(input?: Partial<DomainEntitySchema>): DomainEntity {
201
+ if (input && input.key && this.root.graph.hasNode(input.key)) {
202
+ throw new Error(`Entity with key ${input?.key} already exists`)
203
+ }
204
+ const item = new DomainEntity(this.root, input)
205
+ this.root.graph.setNode(item.key, item)
206
+ this.root.graph.setParent(item.key, this.key)
207
+ this.fields.push({
208
+ key: item.key,
209
+ type: 'entity',
210
+ })
211
+ this.root.notifyChange()
212
+ return item
213
+ }
214
+
215
+ /**
216
+ * Removes an entity from the current model.
217
+ *
218
+ * @param key The key of the model to remove.
219
+ * @throws {RemoveEntityException} If the model does not exist.
220
+ * @example
221
+ * ```typescript
222
+ * model.removeEntity('address')
223
+ * ```
224
+ */
225
+ removeEntity(key: string): void {
226
+ if (!this.root.graph.hasNode(key)) {
227
+ throw new RemoveEntityException(`Trying to remove the ${key} entity, but it doesn't exist`)
228
+ }
229
+ const node = this.root.graph.node(key)
230
+ if (!node || node.kind !== DomainEntityKind) {
231
+ throw new RemoveEntityException(`Trying to remove the ${key} entity, but it is not an entity`)
232
+ }
233
+ if (node.getParentInstance() !== this) {
234
+ throw new RemoveEntityException(`Trying to remove the ${key} entity, but it is not a child of this model`)
235
+ }
236
+ removeGraphNode(this.root.graph, key)
237
+ this.removeField(key)
238
+ this.root.notifyChange()
239
+ }
240
+
241
+ /**
242
+ * Attaches an entity to the current model. It changes the parent of the entity
243
+ * to the current model in the graph.
244
+ *
245
+ * The attached entity must be already a child of another model. It detaches the entity
246
+ * from the previous model.
247
+ *
248
+ * @param key The key of the entity to attach.
249
+ * @throws {AttachException} If the entity does not exist.
250
+ * @throws {AttachException} If passed key doesn't belong to an entity.
251
+ * @throws {AttachException} When the entity is already a child of the current model.
252
+ * @throws {AttachException} If the entity is not in the same domain.
253
+ * @example
254
+ * ```typescript
255
+ * model.attachEntity('address')
256
+ * ```
257
+ */
258
+ attachEntity(key: string): this {
259
+ if (!this.root.graph.hasNode(key)) {
260
+ throw new AttachException(`Trying to attach the ${key} entity, but it doesn't exist`)
261
+ }
262
+ const node = this.root.graph.node(key)
263
+ if (!node || node.kind !== DomainEntityKind) {
264
+ throw new AttachException(`Trying to attach the ${key} entity, but it is not a entity`)
265
+ }
266
+ if (node.domain.key !== this.root.key) {
267
+ throw new AttachException(`Trying to attach the ${key} entity, but it is not in the same domain`)
268
+ }
269
+ const parent = node.getParentInstance() as DomainModel
270
+ if (parent === this) {
271
+ throw new AttachException(`Trying to attach the ${key} entity, but it is already a child of this model`)
272
+ }
273
+ parent.detachEntity(key)
274
+ this.fields.push({
275
+ type: 'entity',
276
+ key: key,
277
+ })
278
+ this.root.graph.setParent(key, this.key)
279
+ this.root.notifyChange()
280
+ return this
281
+ }
282
+
283
+ /**
284
+ * Detaches an entity from the current model. It changes the parent of the entity
285
+ * to the root graph.
286
+ * Unlike remove, it doesn't remove the entity from the graph nor notifies the change.
287
+ * @param key The key of the entity to detach.
288
+ * @throws {DetachException} If the entity does not exist.
289
+ * @throws {DetachException} If passed key doesn't belong to an entity.
290
+ * @throws {DetachException} When the entity is not a child of the current model.
291
+ */
292
+ detachEntity(key: string): this {
293
+ const index = this.fields.findIndex((item) => item.key === key)
294
+ if (index === -1) {
295
+ throw new DetachException(`Trying to detach the ${key} entity, but it doesn't exist`)
296
+ }
297
+ const node = this.root.graph.node(key)
298
+ if (!node || node.kind !== DomainEntityKind) {
299
+ throw new DetachException(`Trying to detach the ${key} entity, but it is not an entity`)
300
+ }
301
+ if (node.getParentInstance() !== this) {
302
+ throw new DetachException(`Trying to detach the ${key} entity, but it is not a child of this model`)
303
+ }
304
+ this.fields.splice(index, 1)
305
+ this.root.graph.setParent(key)
306
+ return this
307
+ }
308
+
309
+ /**
310
+ * Lists all entities.
311
+ *
312
+ * Note, it accounts for the order of the entities as
313
+ * defined in the `fields` array.
314
+ *
315
+ * @returns A generator that yields each `DomainEntity`.
316
+ * @example
317
+ * ```typescript
318
+ * for (const entity of model.listEntities()) {
319
+ * console.log(entity.key);
320
+ * }
321
+ * ```
322
+ */
323
+ *listEntities(): Generator<DomainEntity> {
324
+ for (const { key, type } of this.fields) {
325
+ if (type !== 'entity') {
326
+ continue
327
+ }
328
+ const node = this.root.graph.node(key)
329
+ if (!node || node.kind !== DomainEntityKind) {
330
+ continue
331
+ }
332
+ yield node
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Checks if this model has any entities.
338
+ *
339
+ * @returns True if the model has entities.
340
+ * @example
341
+ * ```typescript
342
+ * if (model.hasEntities()) {
343
+ * // ...
344
+ * }
345
+ * ```
346
+ */
347
+ hasEntities(): boolean {
348
+ return this.fields.some((item) => item.type === 'entity')
349
+ }
350
+
351
+ /**
352
+ * Creates breadcrumbs from this data model to the root namespace.
353
+ */
354
+ breadcrumbs(): FileBreadcrumb[] {
355
+ const result: FileBreadcrumb[] = []
356
+ result.push({
357
+ key: this.key,
358
+ name: this.info.getLabel('Unnamed model'),
359
+ kind: DomainModelKind,
360
+ })
361
+ let parent: DomainNamespace | DataDomain = this.getParentInstance()
362
+ while (parent && parent !== this.root) {
363
+ result.push({
364
+ key: parent.key,
365
+ kind: parent.kind,
366
+ name: parent.info.getLabel('Unnamed namespace'),
367
+ })
368
+ const typed = parent as DomainNamespace
369
+ parent = typed.getParentInstance()
370
+ }
371
+ result.push({
372
+ key: this.root.key,
373
+ name: this.root.info.getLabel('Unnamed data domain'),
374
+ kind: this.root.kind,
375
+ })
376
+ return result.reverse()
377
+ }
378
+
379
+ /**
380
+ * Checks if this model has any fields (entities).
381
+ *
382
+ * @returns True if the model has fields.
383
+ * @example
384
+ * ```typescript
385
+ * if (model.hasFields()) {
386
+ * // ...
387
+ * }
388
+ * ```
389
+ */
390
+ hasFields(): boolean {
391
+ return this.fields.length > 0
392
+ }
393
+
394
+ private removeField(key: string): void {
395
+ this.fields = this.fields.filter((item) => item.key !== key)
396
+ }
397
+
398
+ /**
399
+ * Checks whether the data model is a child of the given namespace.
400
+ * The relationship doesn't have to be direct, as long as the data model is in the hierarchy it will return true.
401
+ *
402
+ * @param key The key of the parent namespace to check.
403
+ * @returns True if this data model is a child of the given namespace.
404
+ */
405
+ isChildOf(key: string): boolean {
406
+ if (this.key === key) {
407
+ return false
408
+ }
409
+ const parent = this.getParentInstance()
410
+ if (!parent) {
411
+ return false
412
+ }
413
+ if (parent.key === key) {
414
+ return true
415
+ }
416
+ if (parent === this.root) {
417
+ return false
418
+ }
419
+ return (parent as DomainNamespace).isChildOf(key)
420
+ }
421
+ }