@api-client/core 0.11.11 → 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 +16 -16
  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 -2
  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,537 @@
1
+ import type { DataDomain } from './DataDomain.js'
2
+ import { DomainModelKind, DomainNamespaceKind } from '../models/kinds.js'
3
+ import { DomainElement, DomainElementSchema } from './DomainElement.js'
4
+ import { nanoid } from 'nanoid'
5
+ import { IThing, Thing } from '../models/Thing.js'
6
+ import { observed, retargetChange } from './observed.js'
7
+ import { DomainModel, DomainModelSchema } from './DomainModel.js'
8
+ import { RemoveNamespaceException } from '../exceptions/remove_namespace_exception.js'
9
+ import { RemoveModelException } from '../exceptions/remove_model_exception.js'
10
+ import { removeGraphNode } from './GraphUtils.js'
11
+ import { DetachException } from '../exceptions/detach_exception.js'
12
+ import { AttachException } from '../exceptions/attach_exception.js'
13
+
14
+ export interface NamespaceOrderedItem {
15
+ /**
16
+ * The type of the ordered item.
17
+ */
18
+ type: 'namespace' | 'model'
19
+
20
+ /**
21
+ * The key of the ordered item.
22
+ */
23
+ key: string
24
+ }
25
+
26
+ export interface DomainNamespaceSchema extends DomainElementSchema {
27
+ kind: typeof DomainNamespaceKind
28
+ /**
29
+ * The data namespace description.
30
+ */
31
+ info: IThing
32
+ /**
33
+ * The ordered list of fields (namespace and models) in the schema.
34
+ * These only keep references to define the order of these properties
35
+ * in the schema as graph won't do it.
36
+ */
37
+ fields?: NamespaceOrderedItem[]
38
+
39
+ /**
40
+ * Whether this namespace is deprecated.
41
+ */
42
+ deprecated?: boolean
43
+ }
44
+
45
+ /**
46
+ * The domain namespace is a way to create a logical structure around data models.
47
+ * It groups data models that represent a whole schema, like a Product data namespace
48
+ * can have data models that describe: the product data model, price history data model,
49
+ * product location, etc.
50
+ *
51
+ * It is optional to have a namespace, but it is recommended to have one for complex
52
+ * data domains.
53
+ *
54
+ * A data domain can be a child of another data domain. It can also contain multiple
55
+ * data domains and data models.
56
+ */
57
+ export class DomainNamespace extends DomainElement {
58
+ override kind: typeof DomainNamespaceKind
59
+
60
+ /**
61
+ * The description of the domain namespace.
62
+ */
63
+ @retargetChange() accessor info: Thing
64
+
65
+ /**
66
+ * The ordered list of fields (namespace and models) in the schema.
67
+ * These only keep references to define the order of these properties
68
+ * in the schema as graph won't do it.
69
+ */
70
+ accessor fields: NamespaceOrderedItem[]
71
+
72
+ /**
73
+ * Whether this namespace is deprecated.
74
+ */
75
+ @observed() accessor deprecated: boolean | undefined
76
+
77
+ /**
78
+ * Creates a full namespace schema with defaults.
79
+ * @param input The partial namespace schema.
80
+ * @returns The namespace schema.
81
+ */
82
+ static createSchema(input: Partial<DomainNamespaceSchema> = {}): DomainNamespaceSchema {
83
+ const { key = nanoid(), fields, deprecated } = input
84
+ const info = Thing.fromJSON(input.info, { name: 'New namespace' }).toJSON()
85
+ const result: DomainNamespaceSchema = {
86
+ kind: DomainNamespaceKind,
87
+ key,
88
+ info,
89
+ }
90
+ if (Array.isArray(fields)) {
91
+ result.fields = [...fields]
92
+ }
93
+ if (typeof deprecated === 'boolean') {
94
+ result.deprecated = deprecated
95
+ }
96
+ return result
97
+ }
98
+
99
+ /**
100
+ * Creates a new namespace instance.
101
+ * It does not add it to the graph.
102
+ * You need to call the `addNamespace` method of the graph to add it.
103
+ *
104
+ * @param root A reference to the root DataDomain instance.
105
+ * @param input The partial namespace schema.
106
+ * @returns Created namespace instance.
107
+ */
108
+ constructor(root: DataDomain, input?: Partial<DomainNamespaceSchema>) {
109
+ const init = DomainNamespace.createSchema(input)
110
+ super(root, init.key)
111
+ this.kind = DomainNamespaceKind
112
+ this.info = new Thing(init.info)
113
+ if (Array.isArray(init.fields)) {
114
+ this.fields = [...init.fields]
115
+ } else {
116
+ this.fields = []
117
+ }
118
+ if (typeof init.deprecated === 'boolean') {
119
+ this.deprecated = init.deprecated
120
+ } else {
121
+ this.deprecated = undefined
122
+ }
123
+ }
124
+
125
+ toJSON(): DomainNamespaceSchema {
126
+ const result: DomainNamespaceSchema = {
127
+ kind: this.kind,
128
+ key: this.key,
129
+ info: this.info.toJSON(),
130
+ }
131
+ if (Array.isArray(this.fields) && this.fields.length) {
132
+ result.fields = [...this.fields]
133
+ }
134
+ if (typeof this.deprecated === 'boolean') {
135
+ result.deprecated = this.deprecated
136
+ }
137
+ return result
138
+ }
139
+
140
+ /**
141
+ * Adds a child namespace to the current namespace.
142
+ *
143
+ * @param value The partial namespace schema.
144
+ * @returns The created namespace instance.
145
+ * @example
146
+ * ```typescript
147
+ * const property = namespace.addNamespace({
148
+ * key: 'e-commerce'
149
+ * })
150
+ * ```
151
+ */
152
+ addNamespace(value?: Partial<DomainNamespaceSchema>): DomainNamespace {
153
+ if (value && value.key && this.root.graph.hasNode(value.key)) {
154
+ throw new Error(`Trying to add a namespace to ${this.key}, but it already exists`)
155
+ }
156
+ const instance = new DomainNamespace(this.root, value)
157
+ this.root.graph.setNode(instance.key, instance)
158
+ this.root.graph.setParent(instance.key, this.key)
159
+ this.fields.push({
160
+ type: 'namespace',
161
+ key: instance.key,
162
+ })
163
+ this.root.notifyChange()
164
+ return instance
165
+ }
166
+
167
+ /**
168
+ * Removes a namespace from the current namespace.
169
+ *
170
+ * @param key The key of the namespace to remove.
171
+ * @throws {RemoveNamespaceException} If the namespace does not exist.
172
+ * @example
173
+ * ```typescript
174
+ * namespace.removeNamespace('e-commerce')
175
+ * ```
176
+ */
177
+ removeNamespace(key: string): this {
178
+ if (!this.root.graph.hasNode(key)) {
179
+ throw new RemoveNamespaceException(`Trying to remove the ${key} namespace, but it doesn't exist`)
180
+ }
181
+ const node = this.root.graph.node(key)
182
+ if (!node || node.kind !== DomainNamespaceKind) {
183
+ throw new RemoveNamespaceException(`Trying to remove the ${key} namespace, but it is not a namespace`)
184
+ }
185
+ removeGraphNode(this.root.graph, key)
186
+ this.removeField(key)
187
+ this.root.notifyChange()
188
+ return this
189
+ }
190
+
191
+ /**
192
+ * Attaches a namespace to the current namespace. It changes the parent of the namespace
193
+ * to the current namespace in the graph.
194
+ *
195
+ * The attached namespace must be already a child of another namespace.
196
+ *
197
+ * @param key The key of the namespace to attach.
198
+ * @throws {Error} If the namespace does not exist.
199
+ * @example
200
+ * ```typescript
201
+ * namespace.attachNamespace('e-commerce')
202
+ * ```
203
+ */
204
+ attachNamespace(key: string): this {
205
+ if (!this.root.graph.hasNode(key)) {
206
+ throw new Error(`Trying to attach the ${key} namespace, but it doesn't exist`)
207
+ }
208
+ const node = this.root.graph.node(key)
209
+ if (!node || node.kind !== DomainNamespaceKind) {
210
+ throw new Error(`Trying to attach the ${key} namespace, but it is not a namespace`)
211
+ }
212
+ if (node.domain.key !== this.root.key) {
213
+ throw new Error(`Trying to attach the ${key} namespace, but it is not in the same domain`)
214
+ }
215
+ const parent = node.getParentInstance()
216
+ if (parent === this) {
217
+ throw new AttachException(`Trying to attach the ${key} entity, but it is already a child of this model`)
218
+ }
219
+ if (this.root !== parent) {
220
+ ;(parent as DomainNamespace).detachNamespace(key)
221
+ }
222
+ this.fields.push({
223
+ type: 'namespace',
224
+ key: key,
225
+ })
226
+ this.root.graph.setParent(key, this.key)
227
+ this.root.notifyChange()
228
+ return this
229
+ }
230
+
231
+ /**
232
+ * Detaches a namespace from the current namespace. It changes the parent of the namespace
233
+ * to the root graph.
234
+ * Unlike remove, it doesn't remove the namespace from the graph nor notifies the change.
235
+ * @param key The key of the namespace to detach.
236
+ * @throws {RemoveNamespaceException} If the namespace does not exist.
237
+ */
238
+ detachNamespace(key: string): this {
239
+ const index = this.fields.findIndex((item) => item.key === key)
240
+ if (index === -1) {
241
+ throw new RemoveNamespaceException(`Trying to detach the ${key} namespace, but it doesn't exist`)
242
+ }
243
+ const node = this.root.graph.node(key)
244
+ if (!node || node.kind !== DomainNamespaceKind) {
245
+ throw new RemoveNamespaceException(`Trying to detach the ${key} namespace, but it is not a namespace`)
246
+ }
247
+ this.fields.splice(index, 1)
248
+ this.root.graph.setParent(key)
249
+ return this
250
+ }
251
+
252
+ /**
253
+ * Lists all namespaces of this namespaces.
254
+ *
255
+ * Note, it accounts for the order of the namespaces as
256
+ * defined in the `fields` array.
257
+ *
258
+ * @returns A generator that yields each `DomainNamespace`.
259
+ * @example
260
+ * ```typescript
261
+ * for (const ns of namespace.listNamespaces()) {
262
+ * console.log(ns.key);
263
+ * }
264
+ * ```
265
+ */
266
+ *listNamespaces(): Generator<DomainNamespace> {
267
+ for (const { key, type } of this.fields) {
268
+ if (type !== 'namespace') {
269
+ continue
270
+ }
271
+ const node = this.root.graph.node(key)
272
+ if (!node || node.kind !== DomainNamespaceKind) {
273
+ continue
274
+ }
275
+ yield node
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Checks if this namespace has any namespaces.
281
+ *
282
+ * @returns True if the namespace has namespaces.
283
+ * @example
284
+ * ```typescript
285
+ * if (namespace.hasNamespaces()) {
286
+ * // ...
287
+ * }
288
+ * ```
289
+ */
290
+ hasNamespaces(): boolean {
291
+ return this.fields.some((item) => item.type === 'namespace')
292
+ }
293
+
294
+ /**
295
+ * Adds a data model to the current namespace.
296
+ * @param value The partial data model schema.
297
+ * @returns The created data model instance.
298
+ * @example
299
+ * ```typescript
300
+ * const property = namespace.addModel({
301
+ * key: 'inventory'
302
+ * })
303
+ * ```
304
+ */
305
+ addModel(input?: Partial<DomainModelSchema>): DomainModel {
306
+ if (input && input.key && this.root.graph.hasNode(input.key)) {
307
+ throw new Error(`Trying to add a model to ${this.key}, but it already exists`)
308
+ }
309
+ const item = new DomainModel(this.root, input)
310
+ this.root.graph.setNode(item.key, item)
311
+ this.root.graph.setParent(item.key, this.key)
312
+ this.fields.push({
313
+ type: 'model',
314
+ key: item.key,
315
+ })
316
+ this.root.notifyChange()
317
+ return item
318
+ }
319
+
320
+ /**
321
+ * Removes a data model from the current namespace.
322
+ *
323
+ * @param key The key of the data model to remove.
324
+ * @throws {RemoveModelException} If the data model does not exist.
325
+ * @example
326
+ * ```typescript
327
+ * namespace.removeModel('inventory')
328
+ * ```
329
+ */
330
+ removeModel(key: string): this {
331
+ if (!this.root.graph.hasNode(key)) {
332
+ throw new RemoveModelException(`Trying to remove the ${key} model, but it doesn't exist`)
333
+ }
334
+ const node = this.root.graph.node(key)
335
+ if (!node || node.kind !== DomainModelKind) {
336
+ throw new RemoveModelException(`Trying to remove the ${key} model, but it is not a model`)
337
+ }
338
+ removeGraphNode(this.root.graph, key)
339
+ this.removeField(key)
340
+ this.root.notifyChange()
341
+ return this
342
+ }
343
+
344
+ /**
345
+ * Attaches a model to the current namespace and sets its parent to the current namespace.
346
+ *
347
+ * The attached model is already a child of another namespace.
348
+ * This method only adds this model to its internal list of fields.
349
+ *
350
+ * Unlike `addModel`, it doesn't create a new model or add it to the graph.
351
+ * It only adds the model to the list of fields.
352
+ *
353
+ * @param key The key of the model to attach.
354
+ * @throws {AttachException} If the model does not exist.
355
+ * @throws {AttachException} If the model is not a model.
356
+ * @throws {AttachException} If the model is not in the same domain.
357
+ * @throws {AttachException} If the model is already a child of this namespace.
358
+ * @example
359
+ * ```typescript
360
+ * namespace.attachModel('inventory')
361
+ * ```
362
+ */
363
+ attachModel(key: string): this {
364
+ if (!this.root.graph.hasNode(key)) {
365
+ throw new AttachException(`Trying to attach the ${key} model, but it doesn't exist`)
366
+ }
367
+ const node = this.root.graph.node(key)
368
+ if (!node || node.kind !== DomainModelKind) {
369
+ throw new AttachException(`Trying to attach the ${key} model, but it is not a model`)
370
+ }
371
+ if (node.domain.key !== this.root.key) {
372
+ throw new AttachException(`Trying to attach the ${key} model, but it is not in the same domain`)
373
+ }
374
+ const parent = node.getParentInstance()
375
+ if (parent === this) {
376
+ throw new AttachException(`Trying to attach the ${key} model, but it is already a child of this namespace`)
377
+ }
378
+ if (this.root !== parent) {
379
+ ;(parent as DomainNamespace).detachModel(key)
380
+ }
381
+ this.fields.push({
382
+ type: 'model',
383
+ key: key,
384
+ })
385
+ this.root.graph.setParent(key, this.key)
386
+ this.root.notifyChange()
387
+ return this
388
+ }
389
+
390
+ /**
391
+ * Detaches a model from the current namespace and sets its parent to the root graph.
392
+ * Unlike remove, it doesn't remove the model from the graph nor notifies the change.
393
+ * @param key The key of the model to detach.
394
+ * @throws {DetachException} If the model does not exist.
395
+ * @throws {DetachException} If the model is not a model.
396
+ * @throws {DetachException} If the model is not a child of this namespace.
397
+ */
398
+ detachModel(key: string): this {
399
+ const index = this.fields.findIndex((item) => item.key === key)
400
+ if (index === -1) {
401
+ throw new DetachException(`Trying to detach the ${key} model, but it doesn't exist`)
402
+ }
403
+ const node = this.root.graph.node(key)
404
+ if (!node || node.kind !== DomainModelKind) {
405
+ throw new DetachException(`Trying to detach the ${key} model, but it is not a model`)
406
+ }
407
+ if (node.getParentInstance() !== this) {
408
+ throw new DetachException(`Trying to detach the ${key} model, but it is not a child of this namespace`)
409
+ }
410
+ this.fields.splice(index, 1)
411
+ this.root.graph.setParent(key)
412
+ return this
413
+ }
414
+
415
+ /**
416
+ * Lists all models of this namespaces.
417
+ *
418
+ * Note, it accounts for the order of the models as
419
+ * defined in the `fields` array.
420
+ *
421
+ * @returns A generator that yields each `DomainModel`.
422
+ * @example
423
+ * ```typescript
424
+ * for (const ns of namespace.listModels()) {
425
+ * console.log(ns.key);
426
+ * }
427
+ * ```
428
+ */
429
+ *listModels(): Generator<DomainModel> {
430
+ for (const { key, type } of this.fields) {
431
+ if (type !== 'model') {
432
+ continue
433
+ }
434
+ const node = this.root.graph.node(key)
435
+ if (!node || node.kind !== DomainModelKind) {
436
+ continue
437
+ }
438
+ yield node
439
+ }
440
+ }
441
+
442
+ /**
443
+ * Checks if this namespace has any models.
444
+ *
445
+ * @returns True if the namespace has models.
446
+ * @example
447
+ * ```typescript
448
+ * if (namespace.hasModels()) {
449
+ * // ...
450
+ * }
451
+ * ```
452
+ */
453
+ hasModels(): boolean {
454
+ return this.fields.some((item) => item.type === 'model')
455
+ }
456
+
457
+ /**
458
+ * Returns a parent data namespace or the data domain where this data namespace exist.
459
+ */
460
+ getParentInstance(): DomainNamespace | DataDomain {
461
+ let parentKey: string | undefined
462
+ for (const parent of this.root.graph.parents(this.key)) {
463
+ parentKey = parent
464
+ break
465
+ }
466
+ if (!parentKey) {
467
+ return this.root
468
+ }
469
+ return this.root.graph.node(parentKey) as DomainNamespace
470
+ }
471
+
472
+ /**
473
+ * Lists all fields (namespace and models) of this namespace.
474
+ *
475
+ * @returns A generator that yields each `DomainAssociation` or `DomainProperty`.
476
+ * @example
477
+ * ```typescript
478
+ * for (const field of namespace.listFields()) {
479
+ * console.log(field.key);
480
+ * }
481
+ * ```
482
+ */
483
+ *listFields(): Generator<DomainNamespace | DomainModel> {
484
+ for (const { key } of this.fields) {
485
+ const node = this.root.graph.node(key)
486
+ if (!node) {
487
+ continue
488
+ }
489
+ if (node.kind === DomainNamespaceKind || node.kind === DomainModelKind) {
490
+ yield node
491
+ }
492
+ }
493
+ }
494
+
495
+ /**
496
+ * Checks if this namespace has any fields (namespace and models).
497
+ *
498
+ * @returns True if the namespace has fields.
499
+ * @example
500
+ * ```typescript
501
+ * if (namespace.hasFields()) {
502
+ * // ...
503
+ * }
504
+ * ```
505
+ */
506
+ hasFields(): boolean {
507
+ return this.fields.length > 0
508
+ }
509
+
510
+ private removeField(key: string): void {
511
+ this.fields = this.fields.filter((item) => item.key !== key)
512
+ }
513
+
514
+ /**
515
+ * Checks whether the namespace is a child of the given namespace.
516
+ * The relationship doesn't have to be direct, as long as the namespace is in the hierarchy it will return true.
517
+ *
518
+ * @param key The key of the parent namespace to check.
519
+ * @returns True if this namespace is a child of the given namespace.
520
+ */
521
+ isChildOf(key: string): boolean {
522
+ if (this.key === key) {
523
+ return false
524
+ }
525
+ const parent = this.getParentInstance()
526
+ if (!parent) {
527
+ return false
528
+ }
529
+ if (parent.key === key) {
530
+ return true
531
+ }
532
+ if (parent === this.root) {
533
+ return false
534
+ }
535
+ return (parent as DomainNamespace).isChildOf(key)
536
+ }
537
+ }