@api-client/core 0.14.0 → 0.14.2
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.
- package/build/src/amf/AmfTypes.d.ts +1 -1
- package/build/src/amf/AmfTypes.js +1 -1
- package/build/src/amf/AmfTypes.js.map +1 -1
- package/build/src/amf/Utils.d.ts +0 -6
- package/build/src/amf/Utils.d.ts.map +1 -1
- package/build/src/amf/Utils.js +0 -14
- package/build/src/amf/Utils.js.map +1 -1
- package/build/src/browser.d.ts +2 -1
- package/build/src/browser.d.ts.map +1 -1
- package/build/src/browser.js +1 -0
- package/build/src/browser.js.map +1 -1
- package/build/src/index.d.ts +2 -1
- package/build/src/index.d.ts.map +1 -1
- package/build/src/index.js +1 -0
- package/build/src/index.js.map +1 -1
- package/build/src/legacy.d.ts +0 -8
- package/build/src/legacy.d.ts.map +1 -1
- package/build/src/legacy.js +0 -9
- package/build/src/legacy.js.map +1 -1
- package/build/src/modeling/Bindings.d.ts +1 -1
- package/build/src/modeling/Bindings.js.map +1 -1
- package/build/src/modeling/DataDomain.js +2 -2
- package/build/src/modeling/DataDomain.js.map +1 -1
- package/build/src/modeling/DataFormat.d.ts +0 -40
- package/build/src/modeling/DataFormat.d.ts.map +1 -1
- package/build/src/modeling/DataFormat.js +0 -27
- package/build/src/modeling/DataFormat.js.map +1 -1
- package/build/src/modeling/DomainAssociation.d.ts +63 -0
- package/build/src/modeling/DomainAssociation.d.ts.map +1 -1
- package/build/src/modeling/DomainAssociation.js +110 -4
- package/build/src/modeling/DomainAssociation.js.map +1 -1
- package/build/src/modeling/DomainEntity.d.ts +25 -9
- package/build/src/modeling/DomainEntity.d.ts.map +1 -1
- package/build/src/modeling/DomainEntity.js +65 -21
- package/build/src/modeling/DomainEntity.js.map +1 -1
- package/build/src/modeling/DomainFile.d.ts +1 -1
- package/build/src/modeling/DomainFile.js +1 -1
- package/build/src/modeling/DomainFile.js.map +1 -1
- package/build/src/modeling/DomainImpactAnalysis.d.ts +1 -1
- package/build/src/modeling/DomainImpactAnalysis.d.ts.map +1 -1
- package/build/src/modeling/DomainImpactAnalysis.js +3 -3
- package/build/src/modeling/DomainImpactAnalysis.js.map +1 -1
- package/build/src/modeling/DomainModel.d.ts +2 -2
- package/build/src/modeling/DomainModel.js +2 -2
- package/build/src/modeling/DomainModel.js.map +1 -1
- package/build/src/modeling/DomainProperty.d.ts +28 -12
- package/build/src/modeling/DomainProperty.d.ts.map +1 -1
- package/build/src/modeling/DomainProperty.js +61 -26
- package/build/src/modeling/DomainProperty.js.map +1 -1
- package/build/src/modeling/Semantics.d.ts +117 -0
- package/build/src/modeling/Semantics.d.ts.map +1 -0
- package/build/src/modeling/Semantics.js +112 -0
- package/build/src/modeling/Semantics.js.map +1 -0
- package/build/src/models/kinds.d.ts +0 -24
- package/build/src/models/kinds.d.ts.map +1 -1
- package/build/src/models/kinds.js +0 -24
- package/build/src/models/kinds.js.map +1 -1
- package/build/src/models/store/data_catalog.d.ts +1 -1
- package/build/src/models/store/data_catalog.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/data/models/APIC-187.json +3 -3
- package/data/models/APIC-188.json +3 -3
- package/data/models/APIC-233.json +1 -1
- package/data/models/APIC-391.json +2 -2
- package/data/models/APIC-483.json +1 -1
- package/data/models/APIC-487.json +1 -1
- package/data/models/APIC-655.json +1 -1
- package/data/models/APIC-689.json +1 -1
- package/data/models/APIC-690.json +5 -5
- package/data/models/SE-10469.json +1 -1
- package/data/models/SE-13092.json +5 -5
- package/data/models/SE-22063.json +12 -2
- package/data/models/amf-helper-api.json +154 -14
- package/data/models/arc-demo-api.json +95 -15
- package/data/models/async-api.json +1 -1
- package/data/models/example-generator-api.json +369 -29
- package/data/models/expanded-api.json +1 -1
- package/data/models/flattened-api.json +1 -1
- package/data/models/multiple-servers.json +1 -1
- package/data/models/oas-3-api.json +1 -1
- package/data/models/oas-date.json +1 -1
- package/data/models/oas-types.json +1 -1
- package/data/models/oas-unions.json +1 -1
- package/data/models/petstore.json +1 -1
- package/data/models/raml-date.json +1 -1
- package/data/models/recursive.json +1 -1
- package/data/models/schema-api.json +62 -2
- package/data/models/secured-api.json +16 -16
- package/data/models/tracked-to-linked.json +4 -4
- package/package.json +2 -2
- package/src/amf/AmfTypes.ts +1 -1
- package/src/amf/Utils.ts +0 -15
- package/src/modeling/Bindings.ts +1 -1
- package/src/modeling/DataDomain.ts +2 -2
- package/src/modeling/DataFormat.ts +0 -48
- package/src/modeling/DomainAssociation.ts +122 -3
- package/src/modeling/DomainEntity.ts +56 -17
- package/src/modeling/DomainFile.ts +1 -1
- package/src/modeling/DomainImpactAnalysis.ts +3 -3
- package/src/modeling/DomainModel.ts +2 -2
- package/src/modeling/DomainProperty.ts +60 -21
- package/src/modeling/Semantics.ts +195 -0
- package/src/modeling/graph.md +14 -14
- package/src/modeling/readme.md +29 -29
- package/src/models/kinds.ts +0 -25
- package/src/models/store/data_catalog.ts +1 -1
- package/tests/unit/modeling/data_domain_change_observers.spec.ts +11 -10
- package/tests/unit/modeling/data_domain_entities.spec.ts +129 -1
- package/tests/unit/modeling/data_domain_property.spec.ts +1 -1
- package/tests/unit/modeling/domain_asociation.spec.ts +267 -0
- package/tests/unit/modeling/domain_entity.spec.ts +27 -26
- package/tests/unit/modeling/domain_entity_example_generator_json.spec.ts +11 -11
- package/tests/unit/modeling/domain_entity_example_generator_xml.spec.ts +10 -10
- package/tests/unit/modeling/{domain.property.spec.ts → domain_property.spec.ts} +139 -23
- package/tests/unit/modeling/semantics.spec.ts +149 -0
- package/build/src/amf/AmfShapeGenerator.d.ts +0 -103
- package/build/src/amf/AmfShapeGenerator.d.ts.map +0 -1
- package/build/src/amf/AmfShapeGenerator.js +0 -416
- package/build/src/amf/AmfShapeGenerator.js.map +0 -1
- package/build/src/modeling/legacy/DataAssociation.d.ts +0 -284
- package/build/src/modeling/legacy/DataAssociation.d.ts.map +0 -1
- package/build/src/modeling/legacy/DataAssociation.js +0 -443
- package/build/src/modeling/legacy/DataAssociation.js.map +0 -1
- package/build/src/modeling/legacy/DataEntity.d.ts +0 -358
- package/build/src/modeling/legacy/DataEntity.d.ts.map +0 -1
- package/build/src/modeling/legacy/DataEntity.js +0 -855
- package/build/src/modeling/legacy/DataEntity.js.map +0 -1
- package/build/src/modeling/legacy/DataEntityBuilder.d.ts +0 -162
- package/build/src/modeling/legacy/DataEntityBuilder.d.ts.map +0 -1
- package/build/src/modeling/legacy/DataEntityBuilder.js +0 -221
- package/build/src/modeling/legacy/DataEntityBuilder.js.map +0 -1
- package/build/src/modeling/legacy/DataImpactAnalysis.d.ts +0 -298
- package/build/src/modeling/legacy/DataImpactAnalysis.d.ts.map +0 -1
- package/build/src/modeling/legacy/DataImpactAnalysis.js +0 -441
- package/build/src/modeling/legacy/DataImpactAnalysis.js.map +0 -1
- package/build/src/modeling/legacy/DataModel.d.ts +0 -99
- package/build/src/modeling/legacy/DataModel.d.ts.map +0 -1
- package/build/src/modeling/legacy/DataModel.js +0 -237
- package/build/src/modeling/legacy/DataModel.js.map +0 -1
- package/build/src/modeling/legacy/DataNamespace.d.ts +0 -340
- package/build/src/modeling/legacy/DataNamespace.d.ts.map +0 -1
- package/build/src/modeling/legacy/DataNamespace.js +0 -784
- package/build/src/modeling/legacy/DataNamespace.js.map +0 -1
- package/build/src/modeling/legacy/DataProperty.d.ts +0 -332
- package/build/src/modeling/legacy/DataProperty.d.ts.map +0 -1
- package/build/src/modeling/legacy/DataProperty.js +0 -415
- package/build/src/modeling/legacy/DataProperty.js.map +0 -1
- package/build/src/models/store/DataFile.d.ts +0 -29
- package/build/src/models/store/DataFile.d.ts.map +0 -1
- package/build/src/models/store/DataFile.js +0 -87
- package/build/src/models/store/DataFile.js.map +0 -1
- package/src/amf/AmfShapeGenerator.ts +0 -477
- package/src/modeling/legacy/DataAssociation.ts +0 -554
- package/src/modeling/legacy/DataEntity.ts +0 -1019
- package/src/modeling/legacy/DataEntityBuilder.ts +0 -236
- package/src/modeling/legacy/DataImpactAnalysis.ts +0 -530
- package/src/modeling/legacy/DataModel.ts +0 -276
- package/src/modeling/legacy/DataNamespace.ts +0 -929
- package/src/modeling/legacy/DataProperty.ts +0 -630
- package/src/models/store/DataFile.ts +0 -95
- package/tests/unit/modeling/legacy/amf_shape_generator.spec.ts +0 -1041
- package/tests/unit/modeling/legacy/data_association.spec.ts +0 -710
- package/tests/unit/modeling/legacy/data_entity.spec.ts +0 -2061
- package/tests/unit/modeling/legacy/data_entity_generator_json.spec.ts +0 -987
- package/tests/unit/modeling/legacy/data_entity_generator_xml.spec.ts +0 -1451
- package/tests/unit/modeling/legacy/data_model.spec.ts +0 -395
- package/tests/unit/modeling/legacy/data_namespace.spec.ts +0 -1312
- package/tests/unit/modeling/legacy/data_property.spec.ts +0 -887
- package/tests/unit/modeling/legacy/impact_analysis.spec.ts +0 -373
|
@@ -10,6 +10,27 @@ import type { AssociationBinding, AssociationBindings, AssociationWebBindings }
|
|
|
10
10
|
import { DomainAttributeAttribute, DomainAttributeAttributes } from './DataFormat.js'
|
|
11
11
|
import type { AssociationTarget, DomainGraphEdge } from './types.js'
|
|
12
12
|
import { ShapeGenerator } from './amf/ShapeGenerator.js'
|
|
13
|
+
import { DataSemantics, isAssociationSemantic, type SemanticType, type AppliedDataSemantic } from './Semantics.js'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Defines the behavior when a parent entity in an association is deleted.
|
|
17
|
+
*
|
|
18
|
+
* - `restrict`: Prevents the deletion of a parent entity if it has any associated child entities.
|
|
19
|
+
* The generated API should return a clear and specific error message (e.g., 409 Conflict).
|
|
20
|
+
* - _Example_: Do not allow a Department to be deleted if it still has Employees.
|
|
21
|
+
* - `cascade`: Automatically deletes all associated child entities when the parent entity is deleted.
|
|
22
|
+
* - _Example_: Deleting a User will also delete all their associated Posts and Comments.
|
|
23
|
+
* - `setNull`: Sets the foreign key of the associated child entities to NULL. This is only valid if the
|
|
24
|
+
* association property on the child entity is nullable.
|
|
25
|
+
* - _Example_: When a `Project` is deleted, the `project_id` on associated `Tasks` is set to NULL,
|
|
26
|
+
* making them unassigned but not deleting them.
|
|
27
|
+
* - `doNothing`: No action is taken on the associated child entities when the parent entity is deleted.
|
|
28
|
+
* - _Example_: Deleting a `Category` does not affect associated `Products`, which remain in the database
|
|
29
|
+
* but may become orphaned.
|
|
30
|
+
* This is useful when the association is optional or when child entities should not be deleted
|
|
31
|
+
* or modified upon the deletion of a parent entity.
|
|
32
|
+
*/
|
|
33
|
+
export type OnDeleteRule = 'restrict' | 'cascade' | 'setNull' | 'doNothing'
|
|
13
34
|
|
|
14
35
|
export interface DomainAssociationSchema extends DomainElementSchema {
|
|
15
36
|
kind: typeof DomainAssociationKind
|
|
@@ -47,6 +68,20 @@ export interface DomainAssociationSchema extends DomainElementSchema {
|
|
|
47
68
|
* When multiple associations are set then we are dealing with an union.
|
|
48
69
|
*/
|
|
49
70
|
targets?: AssociationTarget[]
|
|
71
|
+
/**
|
|
72
|
+
* The semantics applied to this association.
|
|
73
|
+
* This is a list of applied semantics that can be used to
|
|
74
|
+
* describe the association in more detail.
|
|
75
|
+
*/
|
|
76
|
+
semantics?: AppliedDataSemantic[]
|
|
77
|
+
/**
|
|
78
|
+
* Defines the behavior when a parent entity in an association is deleted.
|
|
79
|
+
*/
|
|
80
|
+
onDelete?: OnDeleteRule
|
|
81
|
+
/**
|
|
82
|
+
* Whether the association is read-only.
|
|
83
|
+
*/
|
|
84
|
+
readOnly?: boolean
|
|
50
85
|
}
|
|
51
86
|
|
|
52
87
|
/**
|
|
@@ -141,6 +176,21 @@ export class DomainAssociation extends DomainElement {
|
|
|
141
176
|
*/
|
|
142
177
|
@observed({ deep: true }) accessor targets: AssociationTarget[]
|
|
143
178
|
|
|
179
|
+
/**
|
|
180
|
+
* Semantics applied to this association.
|
|
181
|
+
*/
|
|
182
|
+
@observed({ deep: true }) accessor semantics: AppliedDataSemantic[] = []
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Defines the behavior when a parent entity in an association is deleted.
|
|
186
|
+
*/
|
|
187
|
+
@observed() accessor onDelete: OnDeleteRule | undefined
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Whether the association is read-only.
|
|
191
|
+
*/
|
|
192
|
+
@observed() accessor readOnly: boolean | undefined
|
|
193
|
+
|
|
144
194
|
/**
|
|
145
195
|
* Creates a full data association schema with defaults.
|
|
146
196
|
*
|
|
@@ -148,13 +198,22 @@ export class DomainAssociation extends DomainElement {
|
|
|
148
198
|
* @returns The data association schema.
|
|
149
199
|
*/
|
|
150
200
|
static createSchema(input: Partial<DomainAssociationSchema> = {}): DomainAssociationSchema {
|
|
151
|
-
const { key = nanoid() } = input
|
|
201
|
+
const { key = nanoid(), semantics = [] } = input
|
|
152
202
|
const info = Thing.fromJSON(input.info, { name: 'new_association' }).toJSON()
|
|
153
203
|
const result: DomainAssociationSchema = {
|
|
154
204
|
kind: DomainAssociationKind,
|
|
155
205
|
key,
|
|
156
206
|
info,
|
|
157
207
|
}
|
|
208
|
+
if (Array.isArray(semantics)) {
|
|
209
|
+
result.semantics = [...semantics]
|
|
210
|
+
}
|
|
211
|
+
if (input.onDelete) {
|
|
212
|
+
result.onDelete = input.onDelete
|
|
213
|
+
}
|
|
214
|
+
if (typeof input.readOnly === 'boolean') {
|
|
215
|
+
result.readOnly = input.readOnly
|
|
216
|
+
}
|
|
158
217
|
if (input.schema) {
|
|
159
218
|
result.schema = structuredClone(input.schema)
|
|
160
219
|
}
|
|
@@ -207,6 +266,17 @@ export class DomainAssociation extends DomainElement {
|
|
|
207
266
|
} else {
|
|
208
267
|
this.targets = []
|
|
209
268
|
}
|
|
269
|
+
if (Array.isArray(init.semantics)) {
|
|
270
|
+
this.semantics = init.semantics.map((item) => structuredClone(item))
|
|
271
|
+
} else {
|
|
272
|
+
this.semantics = []
|
|
273
|
+
}
|
|
274
|
+
if (init.onDelete) {
|
|
275
|
+
this.onDelete = init.onDelete
|
|
276
|
+
}
|
|
277
|
+
if (typeof init.readOnly === 'boolean') {
|
|
278
|
+
this.readOnly = init.readOnly
|
|
279
|
+
}
|
|
210
280
|
}
|
|
211
281
|
|
|
212
282
|
/**
|
|
@@ -230,10 +300,19 @@ export class DomainAssociation extends DomainElement {
|
|
|
230
300
|
result.required = this.required
|
|
231
301
|
}
|
|
232
302
|
if (Array.isArray(this.bindings) && this.bindings.length) {
|
|
233
|
-
result.bindings =
|
|
303
|
+
result.bindings = toRaw(this, this.bindings)?.map((i) => structuredClone(i))
|
|
234
304
|
}
|
|
235
305
|
if (Array.isArray(this.targets) && this.targets.length) {
|
|
236
|
-
result.targets =
|
|
306
|
+
result.targets = toRaw(this, this.targets)?.map((i) => ({ ...i }))
|
|
307
|
+
}
|
|
308
|
+
if (Array.isArray(this.semantics) && this.semantics.length) {
|
|
309
|
+
result.semantics = toRaw(this, this.semantics)?.map((i) => structuredClone(i))
|
|
310
|
+
}
|
|
311
|
+
if (this.onDelete) {
|
|
312
|
+
result.onDelete = this.onDelete
|
|
313
|
+
}
|
|
314
|
+
if (typeof this.readOnly === 'boolean' && this.readOnly) {
|
|
315
|
+
result.readOnly = this.readOnly
|
|
237
316
|
}
|
|
238
317
|
return result
|
|
239
318
|
}
|
|
@@ -472,4 +551,44 @@ export class DomainAssociation extends DomainElement {
|
|
|
472
551
|
const serializer = new ShapeGenerator()
|
|
473
552
|
return serializer.associationProperty(this)
|
|
474
553
|
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Adds or updates a semantic to the association.
|
|
557
|
+
* @param semantic The semantic to add to the association.
|
|
558
|
+
* @throws Error if the semantic is not an association semantic.
|
|
559
|
+
*/
|
|
560
|
+
addSemantic(semantic: AppliedDataSemantic): void {
|
|
561
|
+
const sem = DataSemantics[semantic.id]
|
|
562
|
+
if (!isAssociationSemantic(sem)) {
|
|
563
|
+
throw new Error(`Invalid semantic type: ${semantic.id}. Expected an association semantic.`)
|
|
564
|
+
}
|
|
565
|
+
const index = this.semantics.findIndex((s) => s.id === semantic.id)
|
|
566
|
+
if (index >= 0) {
|
|
567
|
+
this.semantics[index] = semantic
|
|
568
|
+
} else {
|
|
569
|
+
this.semantics.push(semantic)
|
|
570
|
+
}
|
|
571
|
+
this.domain.notifyChange()
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Removes a semantic from the association.
|
|
576
|
+
* @param semanticId The ID of the semantic to remove.
|
|
577
|
+
*/
|
|
578
|
+
removeSemantic(semanticId: SemanticType): void {
|
|
579
|
+
const index = this.semantics.findIndex((s) => s.id === semanticId)
|
|
580
|
+
if (index >= 0) {
|
|
581
|
+
this.semantics.splice(index, 1)
|
|
582
|
+
this.domain.notifyChange()
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Checks if the association has a specific semantic.
|
|
588
|
+
* @param semanticId The ID of the semantic to check.
|
|
589
|
+
* @returns True if the semantic is present, false otherwise.
|
|
590
|
+
*/
|
|
591
|
+
hasSemantic(semanticId: SemanticType): boolean {
|
|
592
|
+
return this.semantics.some((s) => s.id === semanticId)
|
|
593
|
+
}
|
|
475
594
|
}
|
|
@@ -17,6 +17,7 @@ import { ShapeGenerator } from './amf/ShapeGenerator.js'
|
|
|
17
17
|
import type { IShapeRenderOptions } from '../amf/shape/ShapeBase.js'
|
|
18
18
|
import { ApiSchemaGenerator } from '../amf/ApiSchemaGenerator.js'
|
|
19
19
|
import { removeGraphNode } from './GraphUtils.js'
|
|
20
|
+
import { DataSemantics, isEntitySemantic, type SemanticType, type AppliedDataSemantic } from './Semantics.js'
|
|
20
21
|
|
|
21
22
|
export interface EntityOrderedItem {
|
|
22
23
|
/**
|
|
@@ -43,11 +44,11 @@ export interface DomainEntitySchema extends DomainElementSchema {
|
|
|
43
44
|
tags?: string[]
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
47
|
+
* The semantics applied to this entity.
|
|
48
|
+
* This is a list of applied semantics that can be used to
|
|
49
|
+
* describe the entity in more detail.
|
|
49
50
|
*/
|
|
50
|
-
|
|
51
|
+
semantics?: AppliedDataSemantic[]
|
|
51
52
|
|
|
52
53
|
/**
|
|
53
54
|
* The ordered list of fields (properties and associations) in the schema.
|
|
@@ -76,7 +77,7 @@ export interface DomainEntitySchema extends DomainElementSchema {
|
|
|
76
77
|
* - **Properties:** Defines the data elements (fields) within the entity.
|
|
77
78
|
* - **Associations:** Defines relationships to other entities.
|
|
78
79
|
* - **Inheritance:** Supports inheriting properties and associations from parent entities.
|
|
79
|
-
* - **Metadata:** Supports tags,
|
|
80
|
+
* - **Metadata:** Supports tags, semantics, and deprecation status.
|
|
80
81
|
* - **AMF Shape Generation:** Can be serialized to an AMF (API Modeling Framework) shape.
|
|
81
82
|
* - **Example Generation:** Can generate example databased on its schema.
|
|
82
83
|
*
|
|
@@ -139,11 +140,9 @@ export class DomainEntity extends DomainElement {
|
|
|
139
140
|
@observed({ deep: true }) accessor tags: string[]
|
|
140
141
|
|
|
141
142
|
/**
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* The keys of the taxonomy items associated with the entity.
|
|
143
|
+
* Semantics applied to this property.
|
|
145
144
|
*/
|
|
146
|
-
@observed({ deep: true }) accessor
|
|
145
|
+
@observed({ deep: true }) accessor semantics: AppliedDataSemantic[] = []
|
|
147
146
|
|
|
148
147
|
/**
|
|
149
148
|
* The ordered list of fields (properties and associations) in the schema.
|
|
@@ -165,7 +164,7 @@ export class DomainEntity extends DomainElement {
|
|
|
165
164
|
* @returns The data entity schema.
|
|
166
165
|
*/
|
|
167
166
|
static createSchema(input: Partial<DomainEntitySchema> = {}): DomainEntitySchema {
|
|
168
|
-
const { key = nanoid(), tags,
|
|
167
|
+
const { key = nanoid(), tags, semantics, fields, deprecated } = input
|
|
169
168
|
const info = Thing.fromJSON(input.info, { name: 'New entity' }).toJSON()
|
|
170
169
|
const result: DomainEntitySchema = {
|
|
171
170
|
kind: DomainEntityKind,
|
|
@@ -175,8 +174,8 @@ export class DomainEntity extends DomainElement {
|
|
|
175
174
|
if (Array.isArray(tags)) {
|
|
176
175
|
result.tags = [...tags]
|
|
177
176
|
}
|
|
178
|
-
if (Array.isArray(
|
|
179
|
-
result.
|
|
177
|
+
if (Array.isArray(semantics)) {
|
|
178
|
+
result.semantics = [...semantics]
|
|
180
179
|
}
|
|
181
180
|
if (Array.isArray(fields)) {
|
|
182
181
|
result.fields = [...fields]
|
|
@@ -206,10 +205,10 @@ export class DomainEntity extends DomainElement {
|
|
|
206
205
|
} else {
|
|
207
206
|
this.tags = []
|
|
208
207
|
}
|
|
209
|
-
if (Array.isArray(init.
|
|
210
|
-
this.
|
|
208
|
+
if (Array.isArray(init.semantics)) {
|
|
209
|
+
this.semantics = init.semantics.map((item) => structuredClone(item))
|
|
211
210
|
} else {
|
|
212
|
-
this.
|
|
211
|
+
this.semantics = []
|
|
213
212
|
}
|
|
214
213
|
if (Array.isArray(init.fields)) {
|
|
215
214
|
this.fields = [...init.fields]
|
|
@@ -235,8 +234,8 @@ export class DomainEntity extends DomainElement {
|
|
|
235
234
|
if (Array.isArray(this.fields) && this.fields.length) {
|
|
236
235
|
result.fields = [...this.fields]
|
|
237
236
|
}
|
|
238
|
-
if (Array.isArray(this.
|
|
239
|
-
result.
|
|
237
|
+
if (Array.isArray(this.semantics) && this.semantics.length) {
|
|
238
|
+
result.semantics = toRaw(this, this.semantics)?.map((i) => structuredClone(i))
|
|
240
239
|
}
|
|
241
240
|
if (Array.isArray(this.tags) && this.tags.length) {
|
|
242
241
|
result.tags = [...(toRaw(this, this.tags) as string[])]
|
|
@@ -841,4 +840,44 @@ export class DomainEntity extends DomainElement {
|
|
|
841
840
|
}
|
|
842
841
|
return property
|
|
843
842
|
}
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Adds or updates a semantic to the entity.
|
|
846
|
+
* @param semantic The semantic to add to the entity.
|
|
847
|
+
* @throws Error if the semantic is not an entity semantic.
|
|
848
|
+
*/
|
|
849
|
+
addSemantic(semantic: AppliedDataSemantic): void {
|
|
850
|
+
const sem = DataSemantics[semantic.id]
|
|
851
|
+
if (!isEntitySemantic(sem)) {
|
|
852
|
+
throw new Error(`Invalid semantic type: ${semantic.id}. Expected an entity semantic.`)
|
|
853
|
+
}
|
|
854
|
+
const index = this.semantics.findIndex((s) => s.id === semantic.id)
|
|
855
|
+
if (index >= 0) {
|
|
856
|
+
this.semantics[index] = semantic
|
|
857
|
+
} else {
|
|
858
|
+
this.semantics.push(semantic)
|
|
859
|
+
}
|
|
860
|
+
this.domain.notifyChange()
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Removes a semantic from the entity.
|
|
865
|
+
* @param semanticId The ID of the semantic to remove.
|
|
866
|
+
*/
|
|
867
|
+
removeSemantic(semanticId: SemanticType): void {
|
|
868
|
+
const index = this.semantics.findIndex((s) => s.id === semanticId)
|
|
869
|
+
if (index >= 0) {
|
|
870
|
+
this.semantics.splice(index, 1)
|
|
871
|
+
this.domain.notifyChange()
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Checks if the entity has a specific semantic.
|
|
877
|
+
* @param semanticId The ID of the semantic to check.
|
|
878
|
+
* @returns True if the semantic is present, false otherwise.
|
|
879
|
+
*/
|
|
880
|
+
hasSemantic(semanticId: SemanticType): boolean {
|
|
881
|
+
return this.semantics.some((s) => s.id === semanticId)
|
|
882
|
+
}
|
|
844
883
|
}
|
|
@@ -436,7 +436,7 @@ export class DomainImpactAnalysis {
|
|
|
436
436
|
this.deleteNamespaceAnalysis(key, rootKey)
|
|
437
437
|
break
|
|
438
438
|
case DomainModelKind:
|
|
439
|
-
this.
|
|
439
|
+
this.deleteModelAnalysis(key, rootKey)
|
|
440
440
|
break
|
|
441
441
|
case DomainEntityKind:
|
|
442
442
|
this.deleteEntityAnalysis(key, rootKey)
|
|
@@ -469,11 +469,11 @@ export class DomainImpactAnalysis {
|
|
|
469
469
|
this.deleteNamespaceAnalysis(child.key, rootKey)
|
|
470
470
|
}
|
|
471
471
|
for (const child of ns.listModels()) {
|
|
472
|
-
this.
|
|
472
|
+
this.deleteModelAnalysis(child.key, rootKey)
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
-
protected
|
|
476
|
+
protected deleteModelAnalysis(key: string, rootKey: string): void {
|
|
477
477
|
const model = this.root.findModel(key)
|
|
478
478
|
if (!model) {
|
|
479
479
|
return
|
|
@@ -64,10 +64,10 @@ export interface DomainModelSchema extends DomainElementSchema {
|
|
|
64
64
|
*
|
|
65
65
|
* ```typescript
|
|
66
66
|
* const dataDomain = new DataDomain();
|
|
67
|
-
* const
|
|
67
|
+
* const ns = dataDomain.addNamespace({
|
|
68
68
|
* key: 'myNamespace',
|
|
69
69
|
* });
|
|
70
|
-
* const userModel =
|
|
70
|
+
* const userModel = ns.addModel({
|
|
71
71
|
* key: 'userModel',
|
|
72
72
|
* info: { name: 'User Model' },
|
|
73
73
|
* });
|
|
@@ -16,12 +16,13 @@ import {
|
|
|
16
16
|
type NumberFormat,
|
|
17
17
|
NumberFormats,
|
|
18
18
|
} from './DataFormat.js'
|
|
19
|
+
import { ShapeGenerator } from './amf/ShapeGenerator.js'
|
|
19
20
|
import type { PropertyBinding, PropertyBindings, PropertyWebBindings } from './Bindings.js'
|
|
20
21
|
import type { ModelValidationOptions } from '../models/types.js'
|
|
21
22
|
import type { DomainEntity } from './DomainEntity.js'
|
|
22
23
|
import type { IApiPropertyShape } from '../amf/definitions/Shapes.js'
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
24
|
+
import type { PropertySchema } from './types.js'
|
|
25
|
+
import { DataSemantics, isPropertySemantic, type SemanticType, type AppliedDataSemantic } from './Semantics.js'
|
|
25
26
|
|
|
26
27
|
export interface DomainPropertySchema extends DomainElementSchema {
|
|
27
28
|
kind: typeof DomainPropertyKind
|
|
@@ -62,11 +63,11 @@ export interface DomainPropertySchema extends DomainElementSchema {
|
|
|
62
63
|
*/
|
|
63
64
|
tags?: string[]
|
|
64
65
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
66
|
+
* The semantics applied to this property.
|
|
67
|
+
* This is a list of applied semantics that can be used to
|
|
68
|
+
* describe the property in more detail.
|
|
68
69
|
*/
|
|
69
|
-
|
|
70
|
+
semantics?: AppliedDataSemantic[]
|
|
70
71
|
/**
|
|
71
72
|
* The data type for this property.
|
|
72
73
|
* Note, not all schemas support the same type. For example, defining `sint32`
|
|
@@ -106,21 +107,21 @@ export interface DomainPropertySchema extends DomainElementSchema {
|
|
|
106
107
|
* - **Bindings:** Allows defining how the property is
|
|
107
108
|
* represented in different formats (e.g., web APIs,
|
|
108
109
|
* protocol buffers).
|
|
109
|
-
* - **Metadata:** Supports metadata such as tags,
|
|
110
|
+
* - **Metadata:** Supports metadata such as tags, semantics,
|
|
110
111
|
* read-only/write-only status, and deprecation.
|
|
111
112
|
* - **Schema:** Allows defining a general schema for the
|
|
112
113
|
* property, which is propagated to all bindings.
|
|
113
114
|
*
|
|
114
115
|
* **Usage:**
|
|
115
116
|
*
|
|
116
|
-
* Use the `
|
|
117
|
+
* Use the `DomainEntity.addProperty` method to add a new property to an
|
|
117
118
|
* entity. The property can be created using the constructor, but it
|
|
118
119
|
* won't be added to the graph until you call the `addProperty` method.
|
|
119
120
|
*
|
|
120
121
|
* **Example:**
|
|
121
122
|
*
|
|
122
123
|
* ```typescript
|
|
123
|
-
* const entity =
|
|
124
|
+
* const entity = domainModel.addEntity({ key: 'user' });
|
|
124
125
|
* const property = entity.addProperty({
|
|
125
126
|
* key: 'name',
|
|
126
127
|
* type: 'string',
|
|
@@ -185,11 +186,9 @@ export class DomainProperty extends DomainElement {
|
|
|
185
186
|
@observed({ deep: true }) accessor tags: string[] = []
|
|
186
187
|
|
|
187
188
|
/**
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
* The keys of the taxonomy items associated with the property.
|
|
189
|
+
* Semantics applied to this property.
|
|
191
190
|
*/
|
|
192
|
-
@observed({ deep: true }) accessor
|
|
191
|
+
@observed({ deep: true }) accessor semantics: AppliedDataSemantic[] = []
|
|
193
192
|
|
|
194
193
|
/**
|
|
195
194
|
* The data type for this property.
|
|
@@ -232,7 +231,7 @@ export class DomainProperty extends DomainElement {
|
|
|
232
231
|
readOnly,
|
|
233
232
|
writeOnly,
|
|
234
233
|
tags,
|
|
235
|
-
|
|
234
|
+
semantics,
|
|
236
235
|
deprecated,
|
|
237
236
|
schema,
|
|
238
237
|
bindings,
|
|
@@ -273,8 +272,8 @@ export class DomainProperty extends DomainElement {
|
|
|
273
272
|
if (Array.isArray(tags)) {
|
|
274
273
|
result.tags = [...tags]
|
|
275
274
|
}
|
|
276
|
-
if (Array.isArray(
|
|
277
|
-
result.
|
|
275
|
+
if (Array.isArray(semantics)) {
|
|
276
|
+
result.semantics = [...semantics]
|
|
278
277
|
}
|
|
279
278
|
if (schema) {
|
|
280
279
|
result.schema = structuredClone(schema)
|
|
@@ -353,10 +352,10 @@ export class DomainProperty extends DomainElement {
|
|
|
353
352
|
} else {
|
|
354
353
|
this.tags = []
|
|
355
354
|
}
|
|
356
|
-
if (Array.isArray(init.
|
|
357
|
-
this.
|
|
355
|
+
if (Array.isArray(init.semantics)) {
|
|
356
|
+
this.semantics = [...init.semantics]
|
|
358
357
|
} else {
|
|
359
|
-
this.
|
|
358
|
+
this.semantics = []
|
|
360
359
|
}
|
|
361
360
|
if (init.schema) {
|
|
362
361
|
this.schema = structuredClone(init.schema)
|
|
@@ -419,8 +418,8 @@ export class DomainProperty extends DomainElement {
|
|
|
419
418
|
if (Array.isArray(this.tags) && this.tags.length) {
|
|
420
419
|
result.tags = [...this.tags]
|
|
421
420
|
}
|
|
422
|
-
if (Array.isArray(this.
|
|
423
|
-
result.
|
|
421
|
+
if (Array.isArray(this.semantics) && this.semantics.length) {
|
|
422
|
+
result.semantics = toRaw(this, this.semantics)?.map((i) => structuredClone(i))
|
|
424
423
|
}
|
|
425
424
|
if (this.schema) {
|
|
426
425
|
result.schema = structuredClone(toRaw(this, this.schema))
|
|
@@ -545,4 +544,44 @@ export class DomainProperty extends DomainElement {
|
|
|
545
544
|
const serializer = new ShapeGenerator()
|
|
546
545
|
return serializer.property(this)
|
|
547
546
|
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Adds or updates a semantic to the property.
|
|
550
|
+
* @param semantic The semantic to add to the property.
|
|
551
|
+
* @throws Error if the semantic is not an property semantic.
|
|
552
|
+
*/
|
|
553
|
+
addSemantic(semantic: AppliedDataSemantic): void {
|
|
554
|
+
const sem = DataSemantics[semantic.id]
|
|
555
|
+
if (!isPropertySemantic(sem)) {
|
|
556
|
+
throw new Error(`Invalid semantic type: ${semantic.id}. Expected a property semantic.`)
|
|
557
|
+
}
|
|
558
|
+
const index = this.semantics.findIndex((s) => s.id === semantic.id)
|
|
559
|
+
if (index >= 0) {
|
|
560
|
+
this.semantics[index] = semantic
|
|
561
|
+
} else {
|
|
562
|
+
this.semantics.push(semantic)
|
|
563
|
+
}
|
|
564
|
+
this.domain.notifyChange()
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Removes a semantic from the property.
|
|
569
|
+
* @param semanticId The ID of the semantic to remove.
|
|
570
|
+
*/
|
|
571
|
+
removeSemantic(semanticId: SemanticType): void {
|
|
572
|
+
const index = this.semantics.findIndex((s) => s.id === semanticId)
|
|
573
|
+
if (index >= 0) {
|
|
574
|
+
this.semantics.splice(index, 1)
|
|
575
|
+
this.domain.notifyChange()
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Checks if the property has a specific semantic.
|
|
581
|
+
* @param semanticId The ID of the semantic to check.
|
|
582
|
+
* @returns True if the semantic is present, false otherwise.
|
|
583
|
+
*/
|
|
584
|
+
hasSemantic(semanticId: SemanticType): boolean {
|
|
585
|
+
return this.semantics.some((s) => s.id === semanticId)
|
|
586
|
+
}
|
|
548
587
|
}
|