@api-client/core 0.18.62 → 0.18.64

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 (80) hide show
  1. package/API_MODELING_EXPLAINER.md +57 -0
  2. package/DATA_MODELING_EXPLAINER.md +74 -0
  3. package/build/src/modeling/DataDomain.d.ts +6 -5
  4. package/build/src/modeling/DataDomain.d.ts.map +1 -1
  5. package/build/src/modeling/DataDomain.js +5 -4
  6. package/build/src/modeling/DataDomain.js.map +1 -1
  7. package/build/src/modeling/DomainAssociation.js +1 -1
  8. package/build/src/modeling/DomainAssociation.js.map +1 -1
  9. package/build/src/modeling/DomainEntity.d.ts +9 -6
  10. package/build/src/modeling/DomainEntity.d.ts.map +1 -1
  11. package/build/src/modeling/DomainEntity.js +34 -18
  12. package/build/src/modeling/DomainEntity.js.map +1 -1
  13. package/build/src/modeling/ai/Semantics.d.ts +7 -0
  14. package/build/src/modeling/ai/Semantics.d.ts.map +1 -0
  15. package/build/src/modeling/ai/Semantics.js +552 -0
  16. package/build/src/modeling/ai/Semantics.js.map +1 -0
  17. package/build/src/modeling/definitions/Calculated.d.ts +1 -1
  18. package/build/src/modeling/definitions/Calculated.js.map +1 -1
  19. package/build/src/modeling/definitions/Country.d.ts +1 -1
  20. package/build/src/modeling/definitions/Country.js.map +1 -1
  21. package/build/src/modeling/definitions/Derived.d.ts +1 -1
  22. package/build/src/modeling/definitions/Derived.js.map +1 -1
  23. package/build/src/modeling/definitions/Description.d.ts +0 -1
  24. package/build/src/modeling/definitions/Description.d.ts.map +1 -1
  25. package/build/src/modeling/definitions/Description.js.map +1 -1
  26. package/build/src/modeling/definitions/Email.d.ts +5 -1
  27. package/build/src/modeling/definitions/Email.d.ts.map +1 -1
  28. package/build/src/modeling/definitions/Email.js.map +1 -1
  29. package/build/src/modeling/definitions/HTML.d.ts +0 -22
  30. package/build/src/modeling/definitions/HTML.d.ts.map +1 -1
  31. package/build/src/modeling/definitions/HTML.js +0 -1
  32. package/build/src/modeling/definitions/HTML.js.map +1 -1
  33. package/build/src/modeling/definitions/Markdown.d.ts +0 -16
  34. package/build/src/modeling/definitions/Markdown.d.ts.map +1 -1
  35. package/build/src/modeling/definitions/Markdown.js +0 -1
  36. package/build/src/modeling/definitions/Markdown.js.map +1 -1
  37. package/build/src/modeling/helpers/Intelisense.d.ts.map +1 -1
  38. package/build/src/modeling/helpers/Intelisense.js +2 -2
  39. package/build/src/modeling/helpers/Intelisense.js.map +1 -1
  40. package/build/src/modeling/importers/JsonSchemaImporter.js +1 -1
  41. package/build/src/modeling/importers/JsonSchemaImporter.js.map +1 -1
  42. package/build/src/modeling/types.d.ts +0 -14
  43. package/build/src/modeling/types.d.ts.map +1 -1
  44. package/build/src/modeling/types.js.map +1 -1
  45. package/build/tsconfig.tsbuildinfo +1 -1
  46. package/data/models/example-generator-api.json +15 -15
  47. package/package.json +4 -4
  48. package/src/modeling/DataDomain.ts +6 -6
  49. package/src/modeling/DomainAssociation.ts +1 -1
  50. package/src/modeling/DomainEntity.ts +36 -18
  51. package/src/modeling/ai/Semantics.ts +597 -0
  52. package/src/modeling/ai/readme.md +7 -0
  53. package/src/modeling/definitions/Calculated.ts +1 -1
  54. package/src/modeling/definitions/Country.ts +1 -1
  55. package/src/modeling/definitions/Derived.ts +1 -1
  56. package/src/modeling/definitions/Description.ts +0 -1
  57. package/src/modeling/definitions/Email.ts +5 -1
  58. package/src/modeling/definitions/HTML.ts +0 -23
  59. package/src/modeling/definitions/Markdown.ts +0 -17
  60. package/src/modeling/helpers/Intelisense.ts +8 -14
  61. package/src/modeling/importers/JsonSchemaImporter.ts +1 -1
  62. package/src/modeling/types.ts +0 -15
  63. package/tests/unit/modeling/amf/shape_generator.spec.ts +4 -4
  64. package/tests/unit/modeling/api_model_expose_entity.spec.ts +11 -11
  65. package/tests/unit/modeling/api_model_remove_entity.spec.ts +1 -1
  66. package/tests/unit/modeling/data_domain_associations.spec.ts +6 -6
  67. package/tests/unit/modeling/data_domain_foreign.spec.ts +2 -2
  68. package/tests/unit/modeling/data_domain_namespaces.spec.ts +1 -1
  69. package/tests/unit/modeling/data_domain_serialization.spec.ts +15 -15
  70. package/tests/unit/modeling/domain_asociation.spec.ts +15 -15
  71. package/tests/unit/modeling/domain_entity.spec.ts +3 -3
  72. package/tests/unit/modeling/domain_entity_associations.spec.ts +4 -4
  73. package/tests/unit/modeling/domain_entity_example_generator_json.spec.ts +16 -16
  74. package/tests/unit/modeling/domain_entity_example_generator_xml.spec.ts +14 -14
  75. package/tests/unit/modeling/domain_property.spec.ts +1 -1
  76. package/tests/unit/modeling/domain_validation.spec.ts +3 -3
  77. package/tests/unit/modeling/domain_versioning.spec.ts +5 -5
  78. package/tests/unit/modeling/exposed_entity_setter_validation.spec.ts +1 -1
  79. package/tests/unit/modeling/validation/association_validation.spec.ts +40 -56
  80. package/tests/unit/modeling/validation/entity_validation.spec.ts +2 -2
@@ -3,34 +3,12 @@ import { SemanticType } from '../Semantics.js'
3
3
 
4
4
  /**
5
5
  * Configuration options for the HTML semantic.
6
- * Controls rendering, sanitization, and allowed HTML features.
7
6
  */
8
7
  export interface HTMLConfig {
9
8
  /**
10
9
  * List of allowed HTML tags in the content.
11
10
  */
12
11
  allowedTags?: string[]
13
- /**
14
- * Render mode: 'html', 'text', or 'both'.
15
- *
16
- * - `html` - The API returns the HTML content as-is (after sanitization based on your other rules like allowedTags).
17
- * - `text` - The API returns the text content, stripping out all HTML tags.
18
- * This is extremely useful for various backend and frontend tasks:
19
- * - **Search Indexing**: You can easily feed the plain text content into a search engine like Elasticsearch
20
- * without the noise of HTML tags.
21
- * - **Content Previews/Summaries**: Displaying a snippet of the content in a list view or a notification
22
- * where formatting is not desired.
23
- * - **Compatibility**: Sending the content to systems that don't support HTML, such as plain-text
24
- * emails or SMS notifications.
25
- * - `both` - The API returns an object containing both the raw HTML and the plain text version. For example:
26
- * ```json
27
- * {
28
- * "html": "<p>Hello, <strong>world</strong>!</p>",
29
- * "text": "Hello, world!"
30
- * }
31
- * ```
32
- */
33
- renderMode?: 'html' | 'text' | 'both'
34
12
  /**
35
13
  * Sanitization level: 'strict', 'moderate', or 'none'.
36
14
  */
@@ -119,7 +97,6 @@ export const createHTMLSemantic = (config: HTMLConfig = {}): AppliedHTMLSemantic
119
97
  */
120
98
  export const DEFAULT_HTML_CONFIG: HTMLConfig = {
121
99
  allowedTags: ['b', 'i', 'em', 'strong', 'a', 'ul', 'ol', 'li', 'p', 'br', 'pre', 'code', 'div', 'span'],
122
- renderMode: 'html',
123
100
  sanitizeLevel: 'strict',
124
101
  allowImages: true,
125
102
  allowLinks: true,
@@ -10,22 +10,6 @@ export interface MarkdownConfig {
10
10
  * List of allowed HTML tags in the rendered output.
11
11
  */
12
12
  allowedTags?: string[]
13
- /**
14
- * Render mode: 'html', 'text', or 'both'.
15
- * This controls how the stored Markdown content is transformed and returned by the API.
16
- *
17
- * - `html` - The API converts the Markdown to HTML and returns the sanitized result.
18
- * - `text` - The original Markdown as when created, but sanitized.
19
- * - `both` - The API returns an object containing both the rendered HTML and the plain text version.
20
- * This provides maximum flexibility for client applications.
21
- * ```json
22
- * {
23
- * "html": "<h1>Title</h1><p>Some <strong>bold</strong> text.</p>",
24
- * "text": "Title Some bold text."
25
- * }
26
- * ```
27
- */
28
- renderMode?: 'html' | 'text' | 'both'
29
13
  /**
30
14
  * Sanitization level: 'strict', 'moderate', or 'none'.
31
15
  */
@@ -110,7 +94,6 @@ export const createMarkdownSemantic = (config: MarkdownConfig = {}): AppliedMark
110
94
  */
111
95
  export const DEFAULT_MARKDOWN_CONFIG: MarkdownConfig = {
112
96
  allowedTags: ['b', 'i', 'em', 'strong', 'a', 'ul', 'ol', 'li', 'p', 'br', 'pre', 'code'],
113
- renderMode: 'html',
114
97
  sanitizeLevel: 'strict',
115
98
  allowImages: true,
116
99
  allowLinks: true,
@@ -325,13 +325,10 @@ export function addOwnerField(entity: DomainEntity, info: Partial<IThing> = {}):
325
325
  if (existing) {
326
326
  return existing
327
327
  }
328
- const prop = entity.addAssociation(
329
- {},
330
- {
331
- info: { name: 'owner', displayName: 'Owner', ...info },
332
- required: true,
333
- }
334
- )
328
+ const prop = entity.addAssociation({
329
+ info: { name: 'owner', displayName: 'Owner', ...info },
330
+ required: true,
331
+ })
335
332
  prop.addSemantic({
336
333
  id: SemanticType.ResourceOwnerIdentifier,
337
334
  })
@@ -378,13 +375,10 @@ export function addUpdatedByField(entity: DomainEntity, info: Partial<IThing> =
378
375
  if (existing) {
379
376
  return existing
380
377
  }
381
- const prop = entity.addAssociation(
382
- {},
383
- {
384
- info: { name: 'updated_by', displayName: 'Updated By', ...info },
385
- required: true,
386
- }
387
- )
378
+ const prop = entity.addAssociation({
379
+ info: { name: 'updated_by', displayName: 'Updated By', ...info },
380
+ required: true,
381
+ })
388
382
  prop.addSemantic({
389
383
  id: SemanticType.ResourceOwnerIdentifier,
390
384
  })
@@ -455,7 +455,7 @@ export class JsonSchemaImporter {
455
455
  // Case 2: If any `$ref` was found, we treat it as an Association.
456
456
  if (analysis.refs.size > 0) {
457
457
  const sanitizedName = toDatabaseColumnName(propName, 'untitled_association')
458
- const assoc = entity.addAssociation({}, { info: { name: sanitizedName } })
458
+ const assoc = entity.addAssociation({ info: { name: sanitizedName } })
459
459
  if (sanitizedName !== propName) {
460
460
  assoc.info.displayName = propName // Keep original name for display
461
461
  }
@@ -33,21 +33,6 @@ export interface DataDomainRemoveOptions {
33
33
  force?: boolean
34
34
  }
35
35
 
36
- export interface AssociationAddOptions {
37
- /**
38
- * When set, it is the the association target's origin data domain.
39
- * The key of the target data domain where this target entity is defined.
40
- * Only used when `key` is specified.
41
- */
42
- domain?: string
43
- /**
44
- * The key of the association target, if known.
45
- * If the target of the association is not specified, and the association has no other targets,
46
- * the association is ignored in the namespace while processing.
47
- */
48
- key?: string
49
- }
50
-
51
36
  export interface DomainGraphEdge {
52
37
  /**
53
38
  * Indicates that the edge is to or from a foreign domain.
@@ -95,7 +95,7 @@ test.group('entity()', (group) => {
95
95
 
96
96
  test('adds associations to the properties', ({ assert }) => {
97
97
  e1.addProperty({ key: 'test', info: { name: 'test' } })
98
- e1.addAssociation({}, { info: { name: 'test association' } })
98
+ e1.addAssociation({ info: { name: 'test association' } })
99
99
  const result = e1.toApiShape() as IApiNodeShape
100
100
 
101
101
  assert.lengthOf(result.properties, 2)
@@ -777,7 +777,7 @@ test.group('associationProperty()', (group) => {
777
777
  m1 = root.addModel({ key: 'm1' })
778
778
  e1 = m1.addEntity({ key: 'e1', info: { name: 'e1' } })
779
779
  e2 = m1.addEntity({ key: 'e2', info: { name: 'e2' } })
780
- a1 = e1.addAssociation({ key: e2.key }, { key: 'a1', info: { name: 'a1' } })
780
+ a1 = e1.addAssociation({ targets: [{ key: e2.key }], key: 'a1', info: { name: 'a1' } })
781
781
  e1.addProperty({ key: 'p1', type: 'boolean', info: { name: 'p1' } })
782
782
  p2 = e2.addProperty({ key: 'p2', type: 'number', info: { name: 'p2' } })
783
783
  })
@@ -1048,7 +1048,7 @@ test.group('AI Generated tests', (group) => {
1048
1048
  m1 = root.addModel({ key: 'm1' })
1049
1049
  e1 = m1.addEntity({ key: 'e1', info: { name: 'e1' } })
1050
1050
  e2 = m1.addEntity({ key: 'e2', info: { name: 'e2' } })
1051
- a1 = e1.addAssociation({ key: e2.key }, { key: 'a1', info: { name: 'a1' } })
1051
+ a1 = e1.addAssociation({ targets: [{ key: e2.key }], key: 'a1', info: { name: 'a1' } })
1052
1052
  p1 = e1.addProperty({ key: 'p1', info: { name: 'p1' } })
1053
1053
  })
1054
1054
 
@@ -1067,7 +1067,7 @@ test.group('AI Generated tests', (group) => {
1067
1067
  const e3 = m2.addEntity({ key: 'e3', info: { name: 'e3' } })
1068
1068
  fd1.info.version = '1.0.0'
1069
1069
  root.registerForeignDomain(fd1)
1070
- const a2 = e1.addAssociation({ key: e3.key, domain: fd1.key }, { key: 'a2', info: { name: 'a2' } })
1070
+ const a2 = e1.addAssociation({ targets: [{ key: e3.key, domain: fd1.key }], key: 'a2', info: { name: 'a2' } })
1071
1071
  const result = e1.toApiShape() as IApiNodeShape
1072
1072
  assert.lengthOf(result.properties, 3)
1073
1073
  assert.isTrue(result.properties.some((prop) => prop.id === a2.key))
@@ -72,7 +72,7 @@ test.group('ApiModel.exposeEntity()', () => {
72
72
  const eA = dm.addEntity({ info: { name: 'A' } })
73
73
  const eB = dm.addEntity({ info: { name: 'B' } })
74
74
  // Add association from A to B
75
- eA.addAssociation({ key: eB.key }, { info: { name: 'entityB' } })
75
+ eA.addAssociation({ info: { name: 'entityB' }, targets: [{ key: eB.key }] })
76
76
  const model = new ApiModel()
77
77
  model.attachDataDomain(domain)
78
78
  const exposedA = model.exposeEntity({ key: eA.key }, { followAssociations: true })
@@ -90,8 +90,8 @@ test.group('ApiModel.exposeEntity()', () => {
90
90
  const eA = dm.addEntity({ info: { name: 'A' } })
91
91
  const eB = dm.addEntity({ info: { name: 'B' } })
92
92
  // A -> B, B -> A
93
- eA.addAssociation({ key: eB.key }, { info: { name: 'assocAB' } })
94
- eB.addAssociation({ key: eA.key }, { info: { name: 'assocBA' } })
93
+ eA.addAssociation({ info: { name: 'assocAB' }, targets: [{ key: eB.key }] })
94
+ eB.addAssociation({ info: { name: 'assocBA' }, targets: [{ key: eA.key }] })
95
95
  const model = new ApiModel()
96
96
  model.attachDataDomain(domain)
97
97
  model.exposeEntity({ key: eA.key }, { followAssociations: true, maxDepth: 4 })
@@ -114,7 +114,7 @@ test.group('ApiModel.exposeEntity()', () => {
114
114
  const dm = domain.addModel()
115
115
  const eA = dm.addEntity({ info: { name: 'A' } })
116
116
  // A -> A (self-association)
117
- eA.addAssociation({ key: eA.key }, { info: { name: 'assocAA' } })
117
+ eA.addAssociation({ info: { name: 'assocAA' }, targets: [{ key: eA.key }] })
118
118
  const model = new ApiModel()
119
119
  model.attachDataDomain(domain)
120
120
  model.exposeEntity({ key: eA.key }, { followAssociations: true })
@@ -132,8 +132,8 @@ test.group('ApiModel.exposeEntity()', () => {
132
132
  const eA = dm.addEntity({ info: { name: 'A' } })
133
133
  const eB = dm.addEntity({ info: { name: 'B' } })
134
134
  const eC = dm.addEntity({ info: { name: 'C' } })
135
- eA.addAssociation({ key: eB.key }, { info: { name: 'toB' } })
136
- eB.addAssociation({ key: eC.key }, { info: { name: 'toC' } })
135
+ eA.addAssociation({ info: { name: 'toB' }, targets: [{ key: eB.key }] })
136
+ eB.addAssociation({ info: { name: 'toC' }, targets: [{ key: eC.key }] })
137
137
  const model = new ApiModel()
138
138
  model.attachDataDomain(domain)
139
139
  model.exposeEntity({ key: eA.key }, { followAssociations: true })
@@ -152,8 +152,8 @@ test.group('ApiModel.exposeEntity()', () => {
152
152
  const eA = dm.addEntity({ info: { name: 'A' } })
153
153
  const eB = dm.addEntity({ info: { name: 'B' } })
154
154
  const eC = dm.addEntity({ info: { name: 'C' } })
155
- eA.addAssociation({ key: eB.key }, { info: { name: 'toB' } })
156
- eA.addAssociation({ key: eC.key }, { info: { name: 'toC' } })
155
+ eA.addAssociation({ info: { name: 'toB' }, targets: [{ key: eB.key }] })
156
+ eA.addAssociation({ info: { name: 'toC' }, targets: [{ key: eC.key }] })
157
157
  const model = new ApiModel()
158
158
  model.attachDataDomain(domain)
159
159
  model.exposeEntity({ key: eA.key }, { followAssociations: true })
@@ -173,9 +173,9 @@ test.group('ApiModel.exposeEntity()', () => {
173
173
  const eB = dm.addEntity({ info: { name: 'B' } })
174
174
  const eC = dm.addEntity({ info: { name: 'C' } })
175
175
  const eD = dm.addEntity({ info: { name: 'D' } })
176
- eA.addAssociation({ key: eB.key }, { info: { name: 'toB' } })
177
- eB.addAssociation({ key: eC.key }, { info: { name: 'toC' } })
178
- eC.addAssociation({ key: eD.key }, { info: { name: 'toD' } })
176
+ eA.addAssociation({ info: { name: 'toB' }, targets: [{ key: eB.key }] })
177
+ eB.addAssociation({ info: { name: 'toC' }, targets: [{ key: eC.key }] })
178
+ eC.addAssociation({ info: { name: 'toD' }, targets: [{ key: eD.key }] })
179
179
  const model = new ApiModel()
180
180
  model.attachDataDomain(domain)
181
181
  model.exposeEntity({ key: eA.key }, { followAssociations: true, maxDepth: 2 })
@@ -23,7 +23,7 @@ test.group('ApiModel.removeEntity()', () => {
23
23
  const eA = dm.addEntity({ info: { name: 'A' } })
24
24
  const eB = dm.addEntity({ info: { name: 'B' } })
25
25
  // A -> B
26
- eA.addAssociation({ key: eB.key }, { info: { name: 'toB' } })
26
+ eA.addAssociation({ info: { name: 'toB' }, targets: [{ key: eB.key }] })
27
27
  const model = new ApiModel()
28
28
  model.attachDataDomain(domain)
29
29
  const rootExposure = model.exposeEntity({ key: eA.key }, { followAssociations: true })
@@ -17,7 +17,7 @@ test.group('DataDomain.addAssociation()', () => {
17
17
  const model = dataDomain.addModel({ key: 'test-model' })
18
18
  const entity1 = dataDomain.addEntity(model.key, { key: 'entity1' })
19
19
  const entity2 = dataDomain.addEntity(model.key, { key: 'entity2' })
20
- const association = dataDomain.addAssociation(entity1.key, { key: entity2.key })
20
+ const association = dataDomain.addAssociation(entity1.key, { targets: [{ key: entity2.key }] })
21
21
  assert.instanceOf(association, DomainAssociation)
22
22
  assert.isTrue(dataDomain.graph.hasNode(association.key))
23
23
  }).tags(['@modeling', '@associations', '@add'])
@@ -84,7 +84,7 @@ test.group('DataDomain.addAssociation()', () => {
84
84
 
85
85
  domain1.registerForeignDomain(domain2)
86
86
 
87
- const association = domain1.addAssociation(e1.key, { key: 'entity2', domain: domain2.key })
87
+ const association = domain1.addAssociation(e1.key, { targets: [{ key: 'entity2', domain: domain2.key }] })
88
88
  assert.instanceOf(association, DomainAssociation)
89
89
  assert.isTrue(domain1.graph.hasNode(association.key))
90
90
  }).tags(['@modeling', '@associations', '@add'])
@@ -99,7 +99,7 @@ test.group('DataDomain.addAssociation()', () => {
99
99
  domain1.registerForeignDomain(domain2)
100
100
 
101
101
  assert.throws(() => {
102
- domain1.addAssociation(e1.key, { key: 'non-existent-entity', domain: 'domain2' })
102
+ domain1.addAssociation(e1.key, { targets: [{ key: 'non-existent-entity', domain: 'domain2' }] })
103
103
  }, 'Foreign entity domain2:non-existent-entity not found')
104
104
  }).tags(['@modeling', '@associations', '@add'])
105
105
  })
@@ -159,7 +159,7 @@ test.group('DataDomain.removeAssociation()', () => {
159
159
  domain2.info.version = '1.0.0'
160
160
  domain1.registerForeignDomain(domain2)
161
161
 
162
- const association = domain1.addAssociation(e1.key, { key: e2.key, domain: domain2.key })
162
+ const association = domain1.addAssociation(e1.key, { targets: [{ key: e2.key, domain: domain2.key }] })
163
163
  domain1.removeAssociation(association.key)
164
164
  assert.isFalse(domain1.graph.hasNode(association.key))
165
165
  }).tags(['@modeling', '@associations', '@remove'])
@@ -187,7 +187,7 @@ test.group('DataDomain.removeAssociation()', () => {
187
187
  const model = dataDomain.addModel()
188
188
  const entity1 = dataDomain.addEntity(model.key, { key: 'entity1' })
189
189
  const entity2 = dataDomain.addEntity(model.key, { key: 'entity2' })
190
- const association = dataDomain.addAssociation(entity1.key, { key: entity2.key })
190
+ const association = dataDomain.addAssociation(entity1.key, { targets: [{ key: entity2.key }] })
191
191
  dataDomain.removeAssociation(association.key)
192
192
  assert.isTrue(dataDomain.graph.hasNode(entity1.key))
193
193
  assert.isTrue(dataDomain.graph.hasNode(entity2.key))
@@ -282,7 +282,7 @@ test.group('DataDomain.findAssociation()', () => {
282
282
  const e2 = domain2.addEntity(m2.key, { key: 'entity2' })
283
283
  domain2.info.version = '1.0.0'
284
284
  domain1.registerForeignDomain(domain2)
285
- const association = domain1.addAssociation(e1.key, { key: e2.key, domain: domain2.key })
285
+ const association = domain1.addAssociation(e1.key, { targets: [{ key: e2.key, domain: domain2.key }] })
286
286
 
287
287
  const foundAssociation = domain1.findAssociation(association.key)
288
288
  assert.deepEqual(foundAssociation, association)
@@ -118,7 +118,7 @@ test.group('DataDomain.registerForeignDomain()', () => {
118
118
  const model = foreignDomain.addModel({ key: 'test-model' })
119
119
  const entity1 = foreignDomain.addEntity(model.key, { key: 'entity1' })
120
120
  const entity2 = foreignDomain.addEntity(model.key, { key: 'entity2' })
121
- const association = entity1.addAssociation({ key: entity2.key })
121
+ const association = entity1.addAssociation({ targets: [{ key: entity2.key }] })
122
122
  foreignDomain.info.version = '1.0.0'
123
123
  dataDomain.registerForeignDomain(foreignDomain)
124
124
 
@@ -606,7 +606,7 @@ test.group('DataDomain.findAssociation()', () => {
606
606
  const m1 = fd.addModel()
607
607
  const e1 = m1.addEntity()
608
608
  const e2 = m1.addEntity()
609
- const a1 = e1.addAssociation({ key: e2.key })
609
+ const a1 = e1.addAssociation({ targets: [{ key: e2.key }] })
610
610
  fd.info.version = '1.0.0'
611
611
  domain.registerForeignDomain(fd)
612
612
  const result = domain.findAssociation(a1.key, fd.key)
@@ -143,7 +143,7 @@ test.group('DataDomain.removeNamespace()', () => {
143
143
  const e1 = m1.addEntity({ key: 'entity1' })
144
144
  const e2 = m1.addEntity({ key: 'entity2' })
145
145
  const p1 = e1.addProperty({ key: 'property1' })
146
- const a1 = e1.addAssociation({ key: e2.key })
146
+ const a1 = e1.addAssociation({ targets: [{ key: e2.key }] })
147
147
  d1.removeNamespace(ns1.key)
148
148
  assert.isFalse(d1.graph.hasNode(ns1.key))
149
149
  assert.isFalse(d1.graph.hasNode(ns2.key))
@@ -139,7 +139,7 @@ test.group('DataDomain Serialization and Deserialization', () => {
139
139
  const m1 = domain.addModel()
140
140
  const e1 = m1.addEntity()
141
141
  const e2 = m1.addEntity()
142
- const a1 = e1.addAssociation({ key: e2.key })
142
+ const a1 = e1.addAssociation({ targets: [{ key: e2.key }] })
143
143
 
144
144
  const serialized = domain.toJSON()
145
145
  const restored = new DataDomain(serialized)
@@ -168,7 +168,7 @@ test.group('DataDomain Serialization and Deserialization', () => {
168
168
  e2.addParent(e1.key)
169
169
  const p1 = e1.addProperty({ type: 'string' })
170
170
  const p2 = e2.addProperty({ type: 'number' })
171
- const a1 = e1.addAssociation({ key: e2.key })
171
+ const a1 = e1.addAssociation({ targets: [{ key: e2.key }] })
172
172
 
173
173
  const serialized = domain.toJSON()
174
174
  const restored = new DataDomain(serialized)
@@ -249,7 +249,7 @@ test.group('DataDomain Serialization and Deserialization', () => {
249
249
  domain.registerForeignDomain(fd)
250
250
  const m1 = domain.addModel({ key: 'm1' })
251
251
  const e1 = m1.addEntity({ key: 'e1' })
252
- const a1 = e1.addAssociation({ key: fe1.key, domain: fd.key }, { key: 'a1' })
252
+ const a1 = e1.addAssociation({ key: 'a1', targets: [{ key: fe1.key, domain: fd.key }] })
253
253
  const serialized = domain.toJSON()
254
254
  const restored = new DataDomain(serialized, [fd])
255
255
 
@@ -278,7 +278,7 @@ test.group('DataDomain Serialization and Deserialization', () => {
278
278
  domain.registerForeignDomain(fd)
279
279
  const m1 = domain.addModel()
280
280
  const e1 = m1.addEntity()
281
- const a1 = e1.addAssociation({ key: fe1.key, domain: fd.key })
281
+ const a1 = e1.addAssociation({ targets: [{ key: fe1.key, domain: fd.key }] })
282
282
 
283
283
  const serialized = domain.toJSON()
284
284
  const restored = new DataDomain(serialized)
@@ -311,7 +311,7 @@ test.group('DataDomain Serialization and Deserialization', () => {
311
311
  // Add properties and associations
312
312
  const p1 = e1.addProperty({ type: 'string', key: 'p1' })
313
313
  const p2 = e2.addProperty({ type: 'number', key: 'p2' })
314
- const a1 = e1.addAssociation({ key: e3.key }, { key: 'a1' })
314
+ const a1 = e1.addAssociation({ targets: [{ key: e3.key }], key: 'a1' })
315
315
 
316
316
  const serialized = domain.toJSON()
317
317
  const restored = new DataDomain(serialized)
@@ -411,7 +411,7 @@ test.group('Validation Tests', () => {
411
411
  const m1 = domain.addModel()
412
412
  const e1 = m1.addEntity()
413
413
  const e2 = m1.addEntity()
414
- const a1 = e1.addAssociation({ key: e2.key })
414
+ const a1 = e1.addAssociation({ targets: [{ key: e2.key }] })
415
415
 
416
416
  // Manually break the graph by removing the association edge to parent
417
417
  domain.graph.removeEdge(e1.key, a1.key)
@@ -461,7 +461,7 @@ test.group('Validation Tests', () => {
461
461
  const m1 = domain.addModel()
462
462
  const e1 = m1.addEntity()
463
463
  const e2 = m1.addEntity()
464
- const a1 = e1.addAssociation({ key: e2.key })
464
+ const a1 = e1.addAssociation({ targets: [{ key: e2.key }] })
465
465
 
466
466
  // Remove the association target edge
467
467
  domain.graph.removeEdge(a1.key, e2.key)
@@ -478,7 +478,7 @@ test.group('Validation Tests', () => {
478
478
  const m1 = domain.addModel()
479
479
  const e1 = m1.addEntity()
480
480
  const e2 = m1.addEntity()
481
- const a1 = e1.addAssociation({ key: e2.key })
481
+ const a1 = e1.addAssociation({ targets: [{ key: e2.key }] })
482
482
 
483
483
  // Remove the target entity but keep the edge pointing to it
484
484
  domain.graph.removeNode(e2.key)
@@ -493,7 +493,7 @@ test.group('Validation Tests', () => {
493
493
  const m1 = domain.addModel()
494
494
  const e1 = m1.addEntity()
495
495
  const e2 = m1.addEntity()
496
- const a1 = e1.addAssociation({ key: e2.key })
496
+ const a1 = e1.addAssociation({ targets: [{ key: e2.key }] })
497
497
 
498
498
  // Remove the proper target and make it point to the model instead
499
499
  domain.graph.removeEdge(a1.key, e2.key)
@@ -512,7 +512,7 @@ test.group('Validation Tests', () => {
512
512
  const e1 = m1.addEntity()
513
513
  const e2 = m2.addEntity()
514
514
  e1.addProperty({ type: 'string' })
515
- e1.addAssociation({ key: e2.key })
515
+ e1.addAssociation({ targets: [{ key: e2.key }] })
516
516
 
517
517
  // This should not throw any validation errors
518
518
  assert.doesNotThrow(() => {
@@ -529,7 +529,7 @@ test.group('Validation Tests', () => {
529
529
  const e1 = m1.addEntity()
530
530
  const e2 = m2.addEntity()
531
531
  e1.addProperty({ type: 'string' })
532
- e1.addAssociation({ key: e2.key })
532
+ e1.addAssociation({ targets: [{ key: e2.key }] })
533
533
 
534
534
  // This should not throw any validation errors
535
535
  assert.doesNotThrow(() => {
@@ -547,7 +547,7 @@ test.group('Validation Tests', () => {
547
547
  domain.registerForeignDomain(fd)
548
548
  const m1 = domain.addModel()
549
549
  const e1 = m1.addEntity()
550
- e1.addAssociation({ key: fe1.key, domain: fd.key })
550
+ e1.addAssociation({ targets: [{ key: fe1.key, domain: fd.key }] })
551
551
 
552
552
  // Foreign associations should pass validation
553
553
  assert.doesNotThrow(() => {
@@ -630,7 +630,7 @@ test.group('DataDomain Lenient Mode Deserialization', () => {
630
630
  const m1 = domain.addModel()
631
631
  const e1 = m1.addEntity()
632
632
  const e2 = m1.addEntity()
633
- const a1 = e1.addAssociation({ key: e2.key })
633
+ const a1 = e1.addAssociation({ targets: [{ key: e2.key }] })
634
634
 
635
635
  const serialized = domain.toJSON()
636
636
 
@@ -701,7 +701,7 @@ test.group('DataDomain Lenient Mode Deserialization', () => {
701
701
  domain.registerForeignDomain(fd)
702
702
  const m1 = domain.addModel()
703
703
  const e1 = m1.addEntity()
704
- e1.addAssociation({ key: fe1.key, domain: fd.key })
704
+ e1.addAssociation({ targets: [{ key: fe1.key, domain: fd.key }] })
705
705
 
706
706
  const serialized = domain.toJSON()
707
707
 
@@ -762,7 +762,7 @@ test.group('DataDomain Lenient Mode Deserialization', () => {
762
762
  const e1 = m1.addEntity()
763
763
  const e2 = m1.addEntity()
764
764
  const p1 = e1.addProperty({ type: 'string' })
765
- e1.addAssociation({ key: e2.key })
765
+ e1.addAssociation({ targets: [{ key: e2.key }] })
766
766
 
767
767
  const serialized = domain.toJSON()
768
768
 
@@ -916,7 +916,7 @@ test.group('DomainAssociation.duplicate()', () => {
916
916
  const entity = model.addEntity()
917
917
  const targetEntity = model.addEntity()
918
918
 
919
- const association = entity.addAssociation({ key: targetEntity.key })
919
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
920
920
  association.info.name = 'originalAssociation'
921
921
  association.required = true
922
922
  association.multiple = false
@@ -938,7 +938,7 @@ test.group('DomainAssociation.duplicate()', () => {
938
938
 
939
939
  // Add multiple fields to test ordering
940
940
  const property1 = entity.addProperty({ info: { name: 'first' } })
941
- const association1 = entity.addAssociation({ key: targetEntity.key })
941
+ const association1 = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
942
942
  association1.info.name = 'originalAssoc'
943
943
  const property2 = entity.addProperty({ info: { name: 'second' } })
944
944
 
@@ -959,10 +959,10 @@ test.group('DomainAssociation.duplicate()', () => {
959
959
  const entity = model.addEntity()
960
960
  const targetEntity = model.addEntity()
961
961
 
962
- const association = entity.addAssociation({ key: targetEntity.key })
962
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
963
963
  association.info.name = 'test'
964
964
  // Add another association that conflicts with the first generated name
965
- const conflictAssoc = entity.addAssociation({ key: targetEntity.key })
965
+ const conflictAssoc = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
966
966
  conflictAssoc.info.name = 'test_copy'
967
967
 
968
968
  const duplicate = association.duplicate()
@@ -976,7 +976,7 @@ test.group('DomainAssociation.duplicate()', () => {
976
976
  const entity = model.addEntity()
977
977
  const targetEntity = model.addEntity()
978
978
 
979
- const association = entity.addAssociation({ key: targetEntity.key })
979
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
980
980
  // The association gets the default name "new_association" from schema creation
981
981
  assert.equal(association.info.name, 'new_association')
982
982
 
@@ -991,7 +991,7 @@ test.group('DomainAssociation.duplicate()', () => {
991
991
  const entity = model.addEntity()
992
992
  const targetEntity = model.addEntity()
993
993
 
994
- const association = entity.addAssociation({ key: targetEntity.key })
994
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
995
995
  association.info.name = 'test'
996
996
  // Manually set name to undefined to test the fallback logic
997
997
  association.info.name = undefined
@@ -1007,7 +1007,7 @@ test.group('DomainAssociation.duplicate()', () => {
1007
1007
  const entity = model.addEntity()
1008
1008
  const targetEntity = model.addEntity()
1009
1009
 
1010
- const association = entity.addAssociation({ key: targetEntity.key })
1010
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
1011
1011
  const originalKey = association.key
1012
1012
 
1013
1013
  const duplicate = association.duplicate()
@@ -1022,7 +1022,7 @@ test.group('DomainAssociation.duplicate()', () => {
1022
1022
  const targetEntity1 = model.addEntity()
1023
1023
  const targetEntity2 = model.addEntity()
1024
1024
 
1025
- const association = entity.addAssociation({ key: targetEntity1.key })
1025
+ const association = entity.addAssociation({ targets: [{ key: targetEntity1.key }] })
1026
1026
  association.addTarget(targetEntity2.key)
1027
1027
  association.info.name = 'multiTarget'
1028
1028
 
@@ -1047,7 +1047,7 @@ test.group('DomainAssociation.duplicate()', () => {
1047
1047
  const entity = model.addEntity()
1048
1048
  const targetEntity = model.addEntity()
1049
1049
 
1050
- const association = entity.addAssociation({ key: targetEntity.key })
1050
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
1051
1051
  association.info.name = 'complexAssociation'
1052
1052
  association.info.description = 'A complex association'
1053
1053
  association.required = true
@@ -1077,7 +1077,7 @@ test.group('DomainAssociation.duplicate()', () => {
1077
1077
  const entity = model.addEntity()
1078
1078
  const targetEntity = model.addEntity()
1079
1079
 
1080
- const association = entity.addAssociation({ key: targetEntity.key })
1080
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
1081
1081
  association.info.name = 'original'
1082
1082
  association.schema = { linked: false, unionType: 'anyOf' }
1083
1083
  association.bindings = [{ type: 'web', schema: { hidden: false } }]
@@ -1134,7 +1134,7 @@ test.group('DomainAssociation.duplicate()', () => {
1134
1134
  const entity = model.addEntity()
1135
1135
  const targetEntity = model.addEntity()
1136
1136
 
1137
- const association = entity.addAssociation({ key: targetEntity.key })
1137
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
1138
1138
  association.info.name = 'test'
1139
1139
 
1140
1140
  let notificationCalled = false
@@ -1184,7 +1184,7 @@ test.group('DomainAssociation.duplicate()', () => {
1184
1184
  const model = dataDomain.addModel()
1185
1185
  const entity = model.addEntity()
1186
1186
  const targetEntity = model.addEntity()
1187
- const association = entity.addAssociation({ key: targetEntity.key })
1187
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
1188
1188
  association.info.name = 'only'
1189
1189
 
1190
1190
  const duplicate = association.duplicate()
@@ -1201,7 +1201,7 @@ test.group('DomainAssociation.duplicate()', () => {
1201
1201
  const targetEntity = model.addEntity()
1202
1202
 
1203
1203
  const property1 = entity.addProperty({ info: { name: 'prop1' } })
1204
- const association1 = entity.addAssociation({ key: targetEntity.key })
1204
+ const association1 = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
1205
1205
  association1.info.name = 'assoc1'
1206
1206
  const property2 = entity.addProperty({ info: { name: 'prop2' } })
1207
1207
 
@@ -1217,7 +1217,7 @@ test.group('DomainAssociation.duplicate()', () => {
1217
1217
  const model = dataDomain.addModel()
1218
1218
  const entity = model.addEntity()
1219
1219
  const targetEntity = model.addEntity()
1220
- const association = entity.addAssociation({ key: targetEntity.key })
1220
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
1221
1221
 
1222
1222
  const duplicate = association.duplicate()
1223
1223
 
@@ -1268,7 +1268,7 @@ test.group('DomainAssociation.duplicate()', () => {
1268
1268
  const entity = model.addEntity()
1269
1269
  dataDomain.registerForeignDomain(fd)
1270
1270
 
1271
- const association = entity.addAssociation({ key: fe1.key, domain: fd.key })
1271
+ const association = entity.addAssociation({ targets: [{ key: fe1.key, domain: fd.key }] })
1272
1272
 
1273
1273
  const duplicate = association.duplicate()
1274
1274
 
@@ -785,7 +785,7 @@ test.group('DomainEntity.generateUniqueName()', () => {
785
785
  const targetEntity = model.addEntity()
786
786
 
787
787
  // Add an association that conflicts with the first generated name
788
- const association = entity.addAssociation({ key: targetEntity.key })
788
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
789
789
  association.info.name = 'test_copy'
790
790
 
791
791
  const uniqueName = entity.generateUniqueName('test')
@@ -800,7 +800,7 @@ test.group('DomainEntity.generateUniqueName()', () => {
800
800
 
801
801
  // Add property and association with conflicting names
802
802
  entity.addProperty({ info: { name: 'test_copy' } })
803
- const association = entity.addAssociation({ key: targetEntity.key })
803
+ const association = entity.addAssociation({ targets: [{ key: targetEntity.key }] })
804
804
  association.info.name = 'test_copy_2'
805
805
 
806
806
  const uniqueName = entity.generateUniqueName('test')
@@ -816,7 +816,7 @@ test.group('DomainEntity.generateUniqueName()', () => {
816
816
  // Add property without a name (undefined name)
817
817
  entity.addProperty({ info: {} })
818
818
  // Add association without a name
819
- entity.addAssociation({ key: targetEntity.key })
819
+ entity.addAssociation({ targets: [{ key: targetEntity.key }] })
820
820
 
821
821
  const uniqueName = entity.generateUniqueName('test')
822
822
  assert.equal(uniqueName, 'test_copy')