@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,476 @@
1
+ import type { DataDomain } from './DataDomain.js'
2
+ import { DomainAssociationKind } from '../models/kinds.js'
3
+ import { DomainElement, type DomainElementSchema } from './DomainElement.js'
4
+ import { nanoid } from 'nanoid'
5
+ import { type IThing, Thing } from '../models/Thing.js'
6
+ import { observed, retargetChange, toRaw } from './observed.js'
7
+ import type { DomainEntity } from './DomainEntity.js'
8
+ import type { IApiAssociationShape, IApiPropertyShape } from '../amf/definitions/Shapes.js'
9
+ import type { AssociationBinding, AssociationBindings, AssociationWebBindings } from './Bindings.js'
10
+ import { Json } from '@api-client/json'
11
+ import { DomainAttributeAttribute, DomainAttributeAttributes } from './DataFormat.js'
12
+ import type { AssociationTarget, DomainGraphEdge } from './types.js'
13
+ import { ShapeGenerator } from './amf/ShapeGenerator.js'
14
+
15
+ export interface DomainAssociationSchema extends DomainElementSchema {
16
+ kind: typeof DomainAssociationKind
17
+ /**
18
+ * The data association description.
19
+ */
20
+ info: IThing
21
+ /**
22
+ * Wether the data association is required.
23
+ */
24
+ required?: boolean
25
+ /**
26
+ * Whether the data association allows multiple items.
27
+ */
28
+ multiple?: boolean
29
+ /**
30
+ * The schema allowing to translate the model into a specific format (like JSON, RAML, XML, etc.)
31
+ *
32
+ * When this is defined then it is used as the schema. When this is not defined it uses
33
+ * referenced entities schemas. Note, changes in the referenced entities may not be propagated
34
+ * to schemas altered by the user.
35
+ */
36
+ schema?: IApiAssociationShape
37
+ /**
38
+ * The list of bindings for this property.
39
+ *
40
+ * A binding defines a translation from a data model to a specific format.
41
+ * For example allows to define properties required to generate AMF shape and therefore RAML/OAS shapes for web APIs
42
+ * or a protocol buffer schema.
43
+ */
44
+ bindings?: AssociationBinding[]
45
+ /**
46
+ * The list of keys associated with the entity through this association.
47
+ * An association without a target is considered invalid and discarded when processing the values.
48
+ * When multiple associations are set then we are dealing with an union.
49
+ */
50
+ targets?: AssociationTarget[]
51
+ }
52
+
53
+ /**
54
+ * Represents an association between entities in a data domain.
55
+ *
56
+ * A `DomainAssociation` defines a relationship between a
57
+ * `DomainEntity` and one or more other entities. It specifies
58
+ * how entities are connected and can represent various types
59
+ * of relationships, such as one-to-one, one-to-many, or
60
+ * many-to-many.
61
+ *
62
+ * **Key Features:**
63
+ *
64
+ * - **Target Entities:** Specifies the entities that are
65
+ * the target of the association.
66
+ * - **Cardinality:** Defines whether the association is
67
+ * single-valued or multi-valued (e.g., one-to-one vs.
68
+ * one-to-many).
69
+ * - **Required Status:** Indicates whether the association
70
+ * is mandatory or optional.
71
+ * - **Schema Customization:** Allows defining a custom
72
+ * schema for the association, overriding the default
73
+ * schema derived from the target entities.
74
+ * - **Bindings:** Supports defining how the association is
75
+ * represented in different formats (e.g., web APIs,
76
+ * protocol buffers).
77
+ * - **Foreign Namespaces:** Can target entities in other
78
+ * namespaces, enabling cross-namespace relationships.
79
+ *
80
+ * **Usage:**
81
+ *
82
+ * The preferred way to create a `DomainAssociation` is
83
+ * through the `DomainEntity.addAssociation()` method.
84
+ *
85
+ * **Example:**
86
+ *
87
+ * ```typescript
88
+ * const dataDomain = new DataDomain();
89
+ * const userModel = dataDomain.addModel({ key: 'userModel' });
90
+ * const userEntity = userModel.addEntity({ key: 'user' });
91
+ * const addressEntity = userModel.addEntity({ key: 'address' });
92
+ * // Add an association from User to Address
93
+ * const addressAssociation = userEntity.addAssociation();
94
+ * addressAssociation.addTarget(addressEntity);
95
+ * ```
96
+ */
97
+ export class DomainAssociation extends DomainElement {
98
+ /**
99
+ * The kind of the domain element.
100
+ */
101
+ override kind: typeof DomainAssociationKind
102
+
103
+ /**
104
+ * The description of the association namespace.
105
+ */
106
+ @retargetChange() accessor info: Thing
107
+
108
+ /**
109
+ * Wether the data association is required.
110
+ */
111
+ @observed() accessor required: boolean | undefined
112
+
113
+ /**
114
+ * Whether the data association allows multiple items.
115
+ */
116
+ @observed() accessor multiple: boolean | undefined
117
+
118
+ /**
119
+ * The schema allowing to translate the model into a
120
+ * specific format (like JSON, RAML, XML, etc.)
121
+ */
122
+ @observed({ deep: true }) accessor schema: IApiAssociationShape | undefined
123
+
124
+ /**
125
+ * The list of bindings for this property.
126
+ *
127
+ * A binding defines a translation from a data model to a specific format.
128
+ * For example allows to define properties required to generate AMF shape and therefore RAML/OAS shapes for web APIs
129
+ * or a protocol buffer schema.
130
+ */
131
+ @observed({ deep: true }) accessor bindings: AssociationBinding[]
132
+
133
+ /**
134
+ * The key of the parent entity.
135
+ */
136
+ protected parent: string
137
+
138
+ /**
139
+ * The list of keys associated with the entity through this association.
140
+ * An association without a target is considered invalid and discarded when processing the values.
141
+ * When multiple associations are set then we are dealing with an union.
142
+ */
143
+ @observed({ deep: true }) accessor targets: AssociationTarget[]
144
+
145
+ /**
146
+ * Creates a full data association schema with defaults.
147
+ *
148
+ * @param input The partial data association schema.
149
+ * @returns The data association schema.
150
+ */
151
+ static createSchema(input: Partial<DomainAssociationSchema> = {}): DomainAssociationSchema {
152
+ const { key = nanoid() } = input
153
+ const info = Thing.fromJSON(input.info, { name: 'New association' }).toJSON()
154
+ const result: DomainAssociationSchema = {
155
+ kind: DomainAssociationKind,
156
+ key,
157
+ info,
158
+ }
159
+ if (input.schema) {
160
+ result.schema = structuredClone(input.schema)
161
+ }
162
+ if (typeof input.multiple === 'boolean') {
163
+ result.multiple = input.multiple
164
+ }
165
+ if (typeof input.required === 'boolean') {
166
+ result.required = input.required
167
+ }
168
+ if (Array.isArray(input.bindings)) {
169
+ result.bindings = input.bindings.map((i) => structuredClone(i))
170
+ }
171
+ if (Array.isArray(input.targets)) {
172
+ result.targets = input.targets.map((i) => ({ ...i }))
173
+ }
174
+ return result
175
+ }
176
+
177
+ /**
178
+ * Creates a new data association instance.
179
+ *
180
+ * You probably want to use the `DomainEntity.addAssociation()` method instead.
181
+ *
182
+ * @param root A reference to the root DataDomain instance.
183
+ * @param parent The key of the parent entity.
184
+ * @param input The partial data association schema.
185
+ */
186
+ constructor(root: DataDomain, parent: string, input?: Partial<DomainAssociationSchema>) {
187
+ const init = DomainAssociation.createSchema(input)
188
+ super(root, init.key)
189
+ this.parent = parent
190
+ this.kind = DomainAssociationKind
191
+ this.info = new Thing(init.info)
192
+ if (init.schema) {
193
+ this.schema = structuredClone(init.schema)
194
+ }
195
+ if (typeof init.multiple === 'boolean') {
196
+ this.multiple = init.multiple
197
+ }
198
+ if (typeof init.required === 'boolean') {
199
+ this.required = init.required
200
+ }
201
+ if (Array.isArray(init.bindings)) {
202
+ this.bindings = init.bindings.map((i) => structuredClone(i))
203
+ } else {
204
+ this.bindings = []
205
+ }
206
+ if (Array.isArray(init.targets)) {
207
+ this.targets = init.targets.map((i) => ({ ...i }))
208
+ } else {
209
+ this.targets = []
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Generates a JSON representation of the association.
215
+ *
216
+ * @returns A plain object representation of the `DomainAssociation`.
217
+ */
218
+ toJSON(): DomainAssociationSchema {
219
+ const result: DomainAssociationSchema = {
220
+ kind: this.kind,
221
+ key: this.key,
222
+ info: this.info.toJSON(),
223
+ }
224
+ if (this.schema) {
225
+ result.schema = Json.clone(toRaw(this, this.schema))
226
+ }
227
+ if (typeof this.multiple === 'boolean') {
228
+ result.multiple = this.multiple
229
+ }
230
+ if (typeof this.required === 'boolean') {
231
+ result.required = this.required
232
+ }
233
+ if (Array.isArray(this.bindings) && this.bindings.length) {
234
+ result.bindings = (toRaw(this, this.bindings) as AssociationBinding[]).map((i) => Json.clone(i))
235
+ }
236
+ if (Array.isArray(this.targets) && this.targets.length) {
237
+ result.targets = (toRaw(this, this.targets) as AssociationTarget[]).map((i) => ({ ...i }))
238
+ }
239
+ return result
240
+ }
241
+
242
+ /**
243
+ * Returns a parent data entity where this data property exist.
244
+ *
245
+ * @returns The parent `DomainEntity` or undefined if not found.
246
+ */
247
+ getParentInstance(): DomainEntity | undefined {
248
+ return this.root.graph.node(this.parent) as DomainEntity | undefined
249
+ }
250
+
251
+ /**
252
+ * Removes this property from the parent entity.
253
+ *
254
+ * This method removes the association from the parent
255
+ * entity's list of associations.
256
+ *
257
+ * @example
258
+ * ```typescript
259
+ * association.remove();
260
+ * ```
261
+ */
262
+ remove(): void {
263
+ const parent = this.getParentInstance()
264
+ parent?.removeAssociation(this.key)
265
+ }
266
+
267
+ /**
268
+ * Creates the `schema` object if missing and returns it.
269
+ *
270
+ * @returns The schema object.
271
+ * @example
272
+ * ```typescript
273
+ * const schema = association.ensureSchema();
274
+ * ```
275
+ */
276
+ ensureSchema(): IApiAssociationShape {
277
+ if (!this.schema) {
278
+ this.schema = {}
279
+ }
280
+ return this.schema
281
+ }
282
+
283
+ /**
284
+ * Checks whether the passed value is one of the supported
285
+ * data property attributes.
286
+ *
287
+ * @param value The value to test
288
+ * @returns True when the passed value is one of the
289
+ * supported data property attributes.
290
+ */
291
+ static isValidAttribute(value: unknown): value is DomainAttributeAttribute {
292
+ if (typeof value !== 'string') {
293
+ return false
294
+ }
295
+ return DomainAttributeAttributes.includes(value as DomainAttributeAttribute)
296
+ }
297
+
298
+ /**
299
+ * Creates if not existing and returns web bindings
300
+ * definition.
301
+ *
302
+ * @returns The web binding definition
303
+ * @example
304
+ * ```typescript
305
+ * const webBindings = association.getWebBinding();
306
+ * webBindings.hidden = true;
307
+ * ```
308
+ */
309
+ getWebBinding(): AssociationWebBindings {
310
+ let object = this.bindings.find((i) => i.type === 'web') as AssociationBinding | undefined
311
+ if (!object) {
312
+ object = { type: 'web', schema: {} } as AssociationBinding
313
+ this.bindings.push(object)
314
+ this.domain.notifyChange()
315
+ }
316
+ return object.schema as AssociationWebBindings
317
+ }
318
+
319
+ /**
320
+ * Returns the schema value of the binding, if any was
321
+ * created.
322
+ *
323
+ * @param type The type of the binding to read.
324
+ * @returns The binding schema, if any
325
+ * @example
326
+ * ```typescript
327
+ * const webBindings = association.readBinding('web');
328
+ * if (webBindings) {
329
+ * // ...
330
+ * }
331
+ * ```
332
+ */
333
+ readBinding(type: 'web' | 'protobuf'): AssociationBindings | undefined {
334
+ const item = this.bindings.find((i) => i.type === type) as AssociationBinding
335
+ return item?.schema || undefined
336
+ }
337
+
338
+ /**
339
+ * Adds a target entity to the association.
340
+ *
341
+ * If the entity comes from another namespace then it is
342
+ * set as a foreign entity.
343
+ *
344
+ * @param entity - The `DomainEntity` instance to add.
345
+ * @example
346
+ * ```typescript
347
+ * association.addTarget(addressEntity);
348
+ * ```
349
+ */
350
+ addTarget(entity: DomainEntity): void
351
+
352
+ /**
353
+ * Adds a target entity to the association.
354
+ *
355
+ * @param entity - The `DomainEntity` definition or just
356
+ * its key.
357
+ * @param namespace - The key of the foreign namespace this
358
+ * entity belongs to. Do not set this value for local
359
+ * entities.
360
+ * @example
361
+ * ```typescript
362
+ * association.addTarget('address', 'foreignNamespace');
363
+ * ```
364
+ */
365
+ addTarget(entity: string, namespace?: string): void
366
+
367
+ /**
368
+ * Adds a target entity to the association.
369
+ *
370
+ * @param init The key of an entity, its instance, or schema.
371
+ * @param namespace - The key of the foreign namespace this
372
+ * entity belongs to. Do not set this value for local entities.
373
+ */
374
+ addTarget(init: string | DomainEntity, namespace?: string): void {
375
+ let key: string
376
+ if (typeof init === 'string') {
377
+ key = init
378
+ } else {
379
+ key = init.key
380
+ if (init.domain.key !== this.root.key) {
381
+ namespace = init.domain.key
382
+ }
383
+ }
384
+ if (this.targets.some((i) => i.key === key && i.domain === namespace)) {
385
+ const message = `Target ${key} already exists.`
386
+ throw new Error(message)
387
+ }
388
+ if (namespace && !this.root.dependencies.has(namespace)) {
389
+ throw new Error(`Foreign namespace "${namespace}" does not exist.`)
390
+ }
391
+ const info: AssociationTarget = {
392
+ key,
393
+ }
394
+ if (namespace) {
395
+ info.domain = namespace
396
+ }
397
+ this.targets.push(info)
398
+ const targetKey = namespace ? `${namespace}:${key}` : key
399
+ const label: DomainGraphEdge = {
400
+ type: 'association',
401
+ }
402
+ if (namespace) {
403
+ label.domain = namespace
404
+ label.foreign = true
405
+ }
406
+ // We need to associate the target with the association
407
+ // in the graph. This way, when looking for associations
408
+ // on a target entities we can easily locate the
409
+ // association.
410
+ this.root.graph.setEdge(this.key, targetKey, label)
411
+ // this.root.notifyChange()
412
+ }
413
+
414
+ /**
415
+ * Removes a target entity from the targets list.
416
+ *
417
+ * @param init The key of an entity, its instance, or
418
+ * schema.
419
+ * @example
420
+ * ```typescript
421
+ * association.removeTarget(addressEntity);
422
+ * ```
423
+ */
424
+ removeTarget(init: string | DomainEntity): void {
425
+ let key: string
426
+ if (typeof init === 'string') {
427
+ key = init
428
+ } else {
429
+ key = init.key
430
+ }
431
+ const index = this.targets.findIndex((i) => i.key === key)
432
+ if (index >= 0) {
433
+ this.targets.splice(index, 1)
434
+ // this.root.notifyChange()
435
+ }
436
+ this.root.graph.removeEdge(this.key, key)
437
+ }
438
+
439
+ /**
440
+ * Lists all target entities of this association.
441
+ *
442
+ * @returns A generator that yields each target
443
+ * `DomainEntity`.
444
+ * @example
445
+ * ```typescript
446
+ * for (const target of association.listTargets()) {
447
+ * console.log(target.key);
448
+ * }
449
+ * ```
450
+ */
451
+ *listTargets(): Generator<DomainEntity> {
452
+ for (const target of this.targets) {
453
+ const { key, domain } = target
454
+ const targetKey = domain ? `${domain}:${key}` : key
455
+ const entity = this.root.graph.node(targetKey) as DomainEntity | undefined
456
+ if (entity) {
457
+ yield entity
458
+ }
459
+ }
460
+ }
461
+
462
+ /**
463
+ * Creates a Property Shape of AMF.
464
+ * The property itself is auto-generated. If the `schema` is defined then it is used
465
+ * as the `range` of the property. Otherwise basic shape is generated for the range.
466
+ *
467
+ * This is a preferred way of reading the AMF shape as this synchronizes changed
468
+ * data properties with the shape definition.
469
+ *
470
+ * @returns AMF property shape definition.
471
+ */
472
+ toApiShape(): IApiPropertyShape {
473
+ const serializer = new ShapeGenerator()
474
+ return serializer.associationProperty(this)
475
+ }
476
+ }
@@ -0,0 +1,50 @@
1
+ import type { DataDomain } from './DataDomain.js'
2
+
3
+ export interface DomainElementSchema {
4
+ /**
5
+ * The kind of the domain element.
6
+ */
7
+ kind: string
8
+ /**
9
+ * The unique key of the domain element.
10
+ */
11
+ key: string
12
+ }
13
+
14
+ export abstract class DomainElement implements DomainElementSchema {
15
+ /**
16
+ * A reference to the root DataDomain instance.
17
+ */
18
+ protected root: DataDomain
19
+
20
+ /**
21
+ * The root DataDomain instance.
22
+ */
23
+ get domain(): DataDomain {
24
+ return this.root
25
+ }
26
+
27
+ abstract accessor kind: string
28
+
29
+ /**
30
+ * The unique key of the domain element.
31
+ * Since keys are immutable, we use a private field to store the key.
32
+ */
33
+ #key: string
34
+
35
+ /**
36
+ * The unique key of the domain element.
37
+ */
38
+ get key(): string {
39
+ return this.#key
40
+ }
41
+
42
+ /**
43
+ * @param root The root DataDomain instance.
44
+ * @param key The unique key of the domain element.
45
+ */
46
+ constructor(root: DataDomain, key: string) {
47
+ this.root = root
48
+ this.#key = key
49
+ }
50
+ }