@api-client/core 0.6.13 → 0.6.16

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 (155) hide show
  1. package/build/browser.d.ts +9 -2
  2. package/build/browser.js +12 -2
  3. package/build/browser.js.map +1 -1
  4. package/build/index.d.ts +9 -2
  5. package/build/index.js +12 -2
  6. package/build/index.js.map +1 -1
  7. package/build/src/amf/AmfMixin.d.ts +395 -0
  8. package/build/src/amf/AmfMixin.js +1146 -0
  9. package/build/src/amf/AmfMixin.js.map +1 -0
  10. package/build/src/amf/AmfSerializer.d.ts +136 -0
  11. package/build/src/amf/AmfSerializer.js +1913 -0
  12. package/build/src/amf/AmfSerializer.js.map +1 -0
  13. package/build/src/amf/AmfShapeGenerator.d.ts +85 -0
  14. package/build/src/amf/AmfShapeGenerator.js +385 -0
  15. package/build/src/amf/AmfShapeGenerator.js.map +1 -0
  16. package/build/src/amf/AmfTypes.d.ts +24 -0
  17. package/build/src/amf/AmfTypes.js +122 -0
  18. package/build/src/amf/AmfTypes.js.map +1 -0
  19. package/build/src/amf/ApiExampleGenerator.d.ts +36 -0
  20. package/build/src/amf/ApiExampleGenerator.js +109 -0
  21. package/build/src/amf/ApiExampleGenerator.js.map +1 -0
  22. package/build/src/amf/ApiMonacoSchemaGenerator.d.ts +67 -0
  23. package/build/src/amf/ApiMonacoSchemaGenerator.js +243 -0
  24. package/build/src/amf/ApiMonacoSchemaGenerator.js.map +1 -0
  25. package/build/src/amf/ApiSchemaGenerator.d.ts +55 -0
  26. package/build/src/amf/ApiSchemaGenerator.js +94 -0
  27. package/build/src/amf/ApiSchemaGenerator.js.map +1 -0
  28. package/build/src/amf/ApiSchemaValues.d.ts +98 -0
  29. package/build/src/amf/ApiSchemaValues.js +382 -0
  30. package/build/src/amf/ApiSchemaValues.js.map +1 -0
  31. package/build/src/amf/Utils.d.ts +41 -0
  32. package/build/src/amf/Utils.js +176 -0
  33. package/build/src/amf/Utils.js.map +1 -0
  34. package/build/src/amf/data-node/DataNodeBase.d.ts +31 -0
  35. package/build/src/amf/data-node/DataNodeBase.js +77 -0
  36. package/build/src/amf/data-node/DataNodeBase.js.map +1 -0
  37. package/build/src/amf/data-node/JsonDataNodeGenerator.d.ts +15 -0
  38. package/build/src/amf/data-node/JsonDataNodeGenerator.js +24 -0
  39. package/build/src/amf/data-node/JsonDataNodeGenerator.js.map +1 -0
  40. package/build/src/amf/data-node/UrlEncodedDataNodeGenerator.d.ts +13 -0
  41. package/build/src/amf/data-node/UrlEncodedDataNodeGenerator.js +42 -0
  42. package/build/src/amf/data-node/UrlEncodedDataNodeGenerator.js.map +1 -0
  43. package/build/src/amf/data-node/XmlDataNodeGenerator.d.ts +21 -0
  44. package/build/src/amf/data-node/XmlDataNodeGenerator.js +30 -0
  45. package/build/src/amf/data-node/XmlDataNodeGenerator.js.map +1 -0
  46. package/build/src/amf/definitions/Amf.d.ts +362 -0
  47. package/build/src/amf/definitions/Amf.js +2 -0
  48. package/build/src/amf/definitions/Amf.js.map +1 -0
  49. package/build/src/amf/definitions/Api.d.ts +381 -0
  50. package/build/src/amf/definitions/Api.js +2 -0
  51. package/build/src/amf/definitions/Api.js.map +1 -0
  52. package/build/src/amf/definitions/Base.d.ts +11 -0
  53. package/build/src/amf/definitions/Base.js +2 -0
  54. package/build/src/amf/definitions/Base.js.map +1 -0
  55. package/build/src/amf/definitions/Namespace.d.ts +311 -0
  56. package/build/src/amf/definitions/Namespace.js +330 -0
  57. package/build/src/amf/definitions/Namespace.js.map +1 -0
  58. package/build/src/amf/definitions/Shapes.d.ts +309 -0
  59. package/build/src/amf/definitions/Shapes.js +87 -0
  60. package/build/src/amf/definitions/Shapes.js.map +1 -0
  61. package/build/src/amf/models/AmfDataNode.d.ts +68 -0
  62. package/build/src/amf/models/AmfDataNode.js +188 -0
  63. package/build/src/amf/models/AmfDataNode.js.map +1 -0
  64. package/build/src/amf/shape/ShapeBase.d.ts +75 -0
  65. package/build/src/amf/shape/ShapeBase.js +90 -0
  66. package/build/src/amf/shape/ShapeBase.js.map +1 -0
  67. package/build/src/amf/shape/ShapeJsonSchemaGenerator.d.ts +46 -0
  68. package/build/src/amf/shape/ShapeJsonSchemaGenerator.js +406 -0
  69. package/build/src/amf/shape/ShapeJsonSchemaGenerator.js.map +1 -0
  70. package/build/src/amf/shape/ShapeXmlSchemaGenerator.d.ts +84 -0
  71. package/build/src/amf/shape/ShapeXmlSchemaGenerator.js +820 -0
  72. package/build/src/amf/shape/ShapeXmlSchemaGenerator.js.map +1 -0
  73. package/build/src/models/Thing.d.ts +17 -0
  74. package/build/src/models/Thing.js +19 -1
  75. package/build/src/models/Thing.js.map +1 -1
  76. package/build/src/models/data/Bindings.d.ts +161 -0
  77. package/build/src/models/data/Bindings.js +2 -0
  78. package/build/src/models/data/Bindings.js.map +1 -0
  79. package/build/src/models/data/DataAssociation.d.ts +135 -14
  80. package/build/src/models/data/DataAssociation.js +154 -21
  81. package/build/src/models/data/DataAssociation.js.map +1 -1
  82. package/build/src/models/data/DataAssociationSchema.d.ts +36 -0
  83. package/build/src/models/data/DataEntity.d.ts +76 -4
  84. package/build/src/models/data/DataEntity.js +136 -9
  85. package/build/src/models/data/DataEntity.js.map +1 -1
  86. package/build/src/models/data/DataFile.d.ts +3 -0
  87. package/build/src/models/data/DataFile.js +3 -0
  88. package/build/src/models/data/DataFile.js.map +1 -1
  89. package/build/src/models/data/DataModel.d.ts +1 -1
  90. package/build/src/models/data/DataModel.js.map +1 -1
  91. package/build/src/models/data/DataNamespace.d.ts +6 -0
  92. package/build/src/models/data/DataNamespace.js +11 -1
  93. package/build/src/models/data/DataNamespace.js.map +1 -1
  94. package/build/src/models/data/DataProperty.d.ts +131 -36
  95. package/build/src/models/data/DataProperty.js +200 -17
  96. package/build/src/models/data/DataProperty.js.map +1 -1
  97. package/data/apis/oas-date/oas-date.yaml +28 -0
  98. package/data/apis/oas-types/oas-types.yaml +159 -0
  99. package/data/apis/oas-unions/oas-unions.yaml +75 -0
  100. package/data/apis/raml-date/raml-date.raml +28 -0
  101. package/data/apis/recursive/recursive.raml +14 -0
  102. package/data/apis/schema-api/examples/person.json +14 -0
  103. package/data/apis/schema-api/examples/person.raml +14 -0
  104. package/data/apis/schema-api/examples/person.url.encoded +1 -0
  105. package/data/apis/schema-api/examples/person.xml +14 -0
  106. package/data/apis/schema-api/library/demo-types.raml +43 -0
  107. package/data/apis/schema-api/schema-api.raml +644 -0
  108. package/data/apis/schema-api/schemas/person.json +104 -0
  109. package/data/apis/schema-api/schemas/person.xsd +26 -0
  110. package/data/apis/schema-api/types/DemoPerson.raml +67 -0
  111. package/data/model.js +106 -0
  112. package/data/models/oas-date.json +637 -0
  113. package/data/models/oas-types.json +5352 -0
  114. package/data/models/oas-unions.json +1881 -0
  115. package/data/models/raml-date.json +1096 -0
  116. package/data/models/recursive.json +610 -0
  117. package/data/models/schema-api.json +37319 -0
  118. package/package.json +9 -6
  119. package/src/amf/AmfMixin.ts +1623 -0
  120. package/src/amf/AmfSerializer.ts +2028 -0
  121. package/src/amf/AmfShapeGenerator.ts +400 -0
  122. package/src/amf/AmfTypes.ts +126 -0
  123. package/src/amf/ApiExampleGenerator.ts +112 -0
  124. package/src/amf/ApiMonacoSchemaGenerator.ts +296 -0
  125. package/src/amf/ApiSchemaGenerator.ts +108 -0
  126. package/src/amf/ApiSchemaValues.ts +411 -0
  127. package/src/amf/Utils.ts +182 -0
  128. package/src/amf/data-node/DataNodeBase.ts +81 -0
  129. package/src/amf/data-node/JsonDataNodeGenerator.ts +26 -0
  130. package/src/amf/data-node/README.md +3 -0
  131. package/src/amf/data-node/UrlEncodedDataNodeGenerator.ts +43 -0
  132. package/src/amf/data-node/XmlDataNodeGenerator.ts +38 -0
  133. package/src/amf/definitions/Amf.ts +443 -0
  134. package/src/amf/definitions/Api.ts +427 -0
  135. package/src/amf/definitions/Base.ts +13 -0
  136. package/src/amf/definitions/Namespace.ts +341 -0
  137. package/src/amf/definitions/Shapes.ts +414 -0
  138. package/src/amf/models/AmfDataNode.ts +200 -0
  139. package/src/amf/shape/README.md +4 -0
  140. package/src/amf/shape/ShapeBase.ts +160 -0
  141. package/src/amf/shape/ShapeJsonSchemaGenerator.ts +422 -0
  142. package/src/amf/shape/ShapeXmlSchemaGenerator.ts +876 -0
  143. package/src/models/Thing.ts +25 -1
  144. package/src/models/data/Bindings.ts +186 -0
  145. package/src/models/data/DataAssociation.ts +226 -29
  146. package/src/models/data/DataAssociationSchema.ts +38 -0
  147. package/src/models/data/DataEntity.ts +170 -13
  148. package/src/models/data/DataFile.ts +3 -0
  149. package/src/models/data/DataModel.ts +1 -1
  150. package/src/models/data/DataNamespace.ts +16 -1
  151. package/src/models/data/DataProperty.ts +250 -47
  152. package/build/src/models/data/DataPropertySchema.d.ts +0 -125
  153. package/build/src/models/data/DataPropertySchema.js +0 -33
  154. package/build/src/models/data/DataPropertySchema.js.map +0 -1
  155. package/src/models/data/DataPropertySchema.ts +0 -156
@@ -12,6 +12,11 @@ export declare interface IThing {
12
12
  * The name of the thing.
13
13
  */
14
14
  name?: string;
15
+ /**
16
+ * Optional value to overwrite the `name` in the UI.
17
+ * The primary descriptive field is the `name`. The display name is only used in the presentation of the data.
18
+ */
19
+ displayName?: string;
15
20
  /**
16
21
  * The description of the thing.
17
22
  */
@@ -28,6 +33,11 @@ export class Thing {
28
33
  * The name of the thing.
29
34
  */
30
35
  name?: string;
36
+ /**
37
+ * Optional value to overwrite the `name` in the UI.
38
+ * The primary descriptive field is the `name`. The display name is only used in the presentation of the data.
39
+ */
40
+ displayName?: string;
31
41
  /**
32
42
  * The description of the thing.
33
43
  */
@@ -37,6 +47,16 @@ export class Thing {
37
47
  */
38
48
  version?: string;
39
49
 
50
+ /**
51
+ * Returns one in this order:
52
+ * - displayName
53
+ * - name
54
+ * - 'Unnamed object'
55
+ */
56
+ get renderLabel(): string {
57
+ return this.displayName || this.name || 'Unnamed object';
58
+ }
59
+
40
60
  /**
41
61
  * Creates a basic description from a name.
42
62
  */
@@ -74,9 +94,10 @@ export class Thing {
74
94
  if (!Thing.isThing(init)) {
75
95
  throw new Error(`Not a thing.`);
76
96
  }
77
- const { description, name, version } = init;
97
+ const { description, name, version, displayName } = init;
78
98
  this.kind = Kind;
79
99
  this.name = name;
100
+ this.displayName = displayName;
80
101
  this.description = description;
81
102
  this.version = version;
82
103
  }
@@ -99,6 +120,9 @@ export class Thing {
99
120
  if (typeof this.name === 'string') {
100
121
  result.name = this.name;
101
122
  }
123
+ if (typeof this.displayName === 'string') {
124
+ result.displayName = this.displayName;
125
+ }
102
126
  if (this.description) {
103
127
  result.description = this.description;
104
128
  }
@@ -0,0 +1,186 @@
1
+ /* eslint-disable import/export */
2
+ import { IXmlSerializer } from "../../amf/definitions/Shapes.js";
3
+
4
+ /**
5
+ * A general schema definition for a property. This is propagated to all bindings (when they support these properties).
6
+ */
7
+ export interface IPropertySchema {
8
+ /**
9
+ * The enum values for the property.
10
+ * They are always encoded as strings. The actual type is defined in the `dataType` property.
11
+ */
12
+ enum?: string[];
13
+ /**
14
+ * The default value for the property.
15
+ * This is always encoded as a string. The actual type is defined in the `dataType` property.
16
+ */
17
+ defaultValue?: string;
18
+ /**
19
+ * The example values for the property.
20
+ * They are always encoded as strings. The actual type is defined in the `dataType` property.
21
+ */
22
+ examples?: string[];
23
+ }
24
+
25
+ /**
26
+ * Binding for web API schema types (RAML, OAS)
27
+ *
28
+ * Data type translation (type to dataType)
29
+ *
30
+ * - `string` -> `string` with appropriate format
31
+ * - `number` -> `number` data type with format `float`, `double`, or none format for OAS
32
+ * - `integer` -> `integer` data type with `int32`, `int64`, or none format for OAS
33
+ * - `nil` -> `nullable` property on OAS or `nil` type in RAML
34
+ * - `boolean` -> `boolean` (both the same)
35
+ * - `date` ->
36
+ * - `any` -> `any` in RAML, `{}` shorthand in OAS
37
+ *
38
+ *
39
+ *
40
+ * The `binary` type
41
+ *
42
+ * OAS
43
+ *
44
+ * `http://www.w3.org/2001/XMLSchema#byte` For a file
45
+ * `http://www.w3.org/2001/XMLSchema#base64Binary` for base 64
46
+ *
47
+ * RAML
48
+ *
49
+ * Has it's own AMF shape: FileShape.
50
+ *
51
+ * The `data` type
52
+ *
53
+ * OAS
54
+ *
55
+ * `http://www.w3.org/2001/XMLSchema#date` for a `date`
56
+ * `http://www.w3.org/2001/XMLSchema#dateTime` for a `datetime` and `time`.
57
+ * Note, OAS has no concept of `time` do we add `time` as the `format which is a custom thing.
58
+ *
59
+ * RAML
60
+ *
61
+ * `http://www.w3.org/2001/XMLSchema#date` for a `date` (raml's date-only)
62
+ * `http://a.ml/vocabularies/shapes#dateTimeOnly` for a `time` (raml's time-only)
63
+ * `http://www.w3.org/2001/XMLSchema#dateTime` for a `datetime` (raml's datetime) + format
64
+ *
65
+ * Note, we won't support RAML's `datetime-only`.
66
+ */
67
+ export interface IPropertyWebBindings {
68
+ /**
69
+ * When set it overrides the `name` of the property.
70
+ */
71
+ name?: string;
72
+ /**
73
+ * The data type of the property consistent with AMF's data types.
74
+ */
75
+ dataType?: string;
76
+ /**
77
+ * The XML encoding instructions.
78
+ */
79
+ xml?: IXmlSerializer;
80
+ /**
81
+ * Only valid for the `file` property type.
82
+ * The list of file mime types.
83
+ */
84
+ fileTypes?: string[];
85
+ /**
86
+ * The patter to use wit a string scalar
87
+ */
88
+ pattern?: string;
89
+ /**
90
+ * Minimum length of a string scalar or a file type.
91
+ */
92
+ minLength?: number;
93
+ /**
94
+ * Maximum length of a string scalar or a file type.
95
+ */
96
+ maxLength?: number;
97
+ /**
98
+ * Minimum value for a number scalar.
99
+ */
100
+ minimum?: number;
101
+ /**
102
+ * Maximum value for a number scalar.
103
+ */
104
+ maximum?: number;
105
+ /**
106
+ * The multiplier value for a number scalar.
107
+ */
108
+ multipleOf?: number;
109
+ /**
110
+ * When `false`: value ≥ minimum.
111
+ * When `true`: value > minimum.
112
+ */
113
+ exclusiveMinimum?: boolean;
114
+ /**
115
+ * When `false`: value ≤ maximum.
116
+ * When `true`: value < minimum.
117
+ */
118
+ exclusiveMaximum?: boolean;
119
+
120
+ format?:
121
+ //
122
+ // OAS 3 formats
123
+ //
124
+
125
+ // numbers
126
+ 'float' | 'double' | 'int32' | 'int64' |
127
+ // string
128
+ 'date' | 'date-time' | 'password' |
129
+ // files
130
+ 'binary' | 'byte' |
131
+ // non-standard
132
+ 'email' | 'uuid' | 'uri' | 'hostname' | 'ipv4' | 'ipv6' | string |
133
+
134
+ //
135
+ // RAML formats
136
+ //
137
+
138
+ 'rfc3339' | 'rfc2616'
139
+ }
140
+
141
+
142
+ /**
143
+ * Binding to the protocol buffer.
144
+ *
145
+ * Data type translation (type to dataType)
146
+ *
147
+ * - `string` -> `string`
148
+ * - `number` -> `double`, `float`
149
+ * - `integer` -> `int32`, `int64`, `uint32`, `uint64`, `sint32`, `sint64`, `fixed32`, `fixed64`, `sfixed32`, `sfixed64`
150
+ * - `nil` -> No translation.
151
+ * - `boolean` -> `boolean`
152
+ * - `date` -> No translation, we allow string or number (date string or a timestamp with a combination with format but this is not standard for ProtoBuf)
153
+ * - `any` -> No translation, the user has to pick any of the data formats.
154
+ * - `binary` -> `bytes`
155
+ */
156
+ export interface IPropertyProtobufBindings {
157
+ /**
158
+ * The field number in a protocol buffer message
159
+ */
160
+ field?: number;
161
+ /**
162
+ * Whether this property (field) is reserved
163
+ */
164
+ reserved?: boolean;
165
+ /**
166
+ * The data type of the property consistent with AMF's data types.
167
+ */
168
+ dataType?: string;
169
+ }
170
+
171
+ export interface IPropertyBindings {
172
+ /**
173
+ * The type of the bindings
174
+ *
175
+ * - Protocol buffers: `protobuf`
176
+ * - RAML or OAS - `web`
177
+ */
178
+ type: 'protobuf' | 'web';
179
+ /**
180
+ * The definition of the bindings.
181
+ * The bindings tells how to translated the DataProperty to a specific format.
182
+ * For example, it allows to define the `dataType` and `format` for RAML / OAS (via the AMF shapes)
183
+ * or the field number for protocol buffer.
184
+ */
185
+ schema: IPropertyProtobufBindings | IPropertyWebBindings;
186
+ }
@@ -1,15 +1,27 @@
1
+ import { Core as JsonCore } from '@api-client/json';
2
+ import { AmfShapeGenerator } from '../../amf/AmfShapeGenerator.js';
3
+ import { IAssociationShape, IPropertyShape } from '../../amf/definitions/Shapes.js';
1
4
  import v4 from '../../lib/uuid.js';
2
5
  import { IThing, Thing } from "../Thing.js";
3
- import { IDataAssociationSchema } from './DataAssociationSchema.js';
4
- import { DataEntity } from './DataEntity.js';
6
+ import { DataEntity, IDataEntity } from './DataEntity.js';
5
7
  import { DataNamespace } from './DataNamespace.js';
6
8
 
7
9
  export const Kind = 'Core#DataAssociation';
8
10
 
11
+ /**
12
+ * Describes an association between entities. An association is another property of an entity. The `name` is the name of the
13
+ * property and the value is the associated target or targets.
14
+ *
15
+ * An association can have multiple targets to allow describing the model as `allOf`, `anyOf` and `oneOf` schemas.
16
+ * When the association has only one target, then generated schema cannot have union types.
17
+ *
18
+ * Depending on the schema translation an association can be embedded as a sub-object in the generated schema
19
+ * or can be references via a primary key.
20
+ */
9
21
  export interface IDataAssociation {
10
22
  kind: typeof Kind;
11
23
  /**
12
- * The key of the namespace.
24
+ * The key of the association.
13
25
  */
14
26
  key: string;
15
27
  /**
@@ -25,23 +37,54 @@ export interface IDataAssociation {
25
37
  */
26
38
  multiple?: boolean;
27
39
  /**
28
- * The target entity of this association.
40
+ * Whether the attribute is hidden in the schema (not a part of it).
41
+ * The hidden attribute should only appear in the adapted attribute.
42
+ * Has no effect when added to the "main" attribute.
43
+ */
44
+ hidden?: boolean;
45
+ /**
46
+ * The list of keys associated with the entity through this association.
29
47
  * An association without a target is considered invalid and discarded when processing the values.
30
48
  */
31
- target?: string;
49
+ targets?: string[];
32
50
  /**
33
51
  * The schema allowing to translate the model into a specific format (like JSON, RAML, XML, etc.)
52
+ *
53
+ * When this is defined then it is used as the schema. When this is not defined it uses
54
+ * referenced entities schemas. Note, changes in the referenced entities may not be propagated
55
+ * to schemas altered by the user.
56
+ *
57
+ * Note, schema can only occur on an adapted property. Has no effect on the "main"
58
+ * property.
59
+ */
60
+ schema?: IAssociationShape;
61
+ /**
62
+ * The key of the association that is adapted by this association.
63
+ * Adapted associations can manipulate the shape of the schema for the association.
64
+ *
65
+ * Each value defined on the adapted association changes the original value defined on
66
+ * the association.
34
67
  */
35
- schema?: IDataAssociationSchema;
68
+ adapts?: string;
36
69
  }
37
70
 
71
+ /**
72
+ * Describes an association between entities. An association is another property of an entity. The `name` is the name of the
73
+ * property and the value is the associated target or targets.
74
+ *
75
+ * An association can have multiple targets to allow describing the model as `allOf`, `anyOf` and `oneOf` schemas.
76
+ * When the association has only one target, then generated schema cannot have union types.
77
+ *
78
+ * Depending on the schema translation an association can be embedded as a sub-object in the generated schema
79
+ * or can be references via a primary key.
80
+ */
38
81
  export class DataAssociation {
39
82
  kind = Kind;
40
83
 
41
84
  key = '';
42
85
 
43
86
  /**
44
- * The description of the data namespace.
87
+ * The description of the data association.
45
88
  */
46
89
  info: Thing = Thing.fromName('');
47
90
 
@@ -56,25 +99,65 @@ export class DataAssociation {
56
99
  multiple?: boolean;
57
100
 
58
101
  /**
59
- * The target entity of this association.
102
+ * Whether the attribute is hidden in the schema (not a part of it).
103
+ * The hidden attribute should only appear in the adapted attribute.
104
+ * Has no effect when added to the "main" attribute.
105
+ */
106
+ hidden?: boolean;
107
+
108
+ /**
109
+ * The list of keys associated with the entity through this association.
60
110
  * An association without a target is considered invalid and discarded when processing the values.
61
111
  */
62
- target?: string;
112
+ targets: string[] = [];
63
113
 
64
114
  /**
65
115
  * The schema allowing to translate the model into a specific format (like JSON, RAML, XML, etc.)
66
116
  *
67
- * Implementation note, when an entity is removed this property is not changed. The target can't
68
- * be read but it can be tracked to a deleted entity.
117
+ * When this is defined then it is used as the schema. When this is not defined it uses
118
+ * referenced entities schemas. Note, changes in the referenced entities may not be propagated
119
+ * to schemas altered by the user.
120
+ *
121
+ * Note, schema can only occur on an adapted property. Has no effect on the "main"
122
+ * property.
123
+ */
124
+ schema?: IAssociationShape;
125
+
126
+ /**
127
+ * The key of the association that is adapted by this association.
128
+ * Adapted associations can manipulate the shape of the schema for the association.
129
+ *
130
+ * Each value defined on the adapted association changes the original value defined on
131
+ * the association.
69
132
  */
70
- schema?: IDataAssociationSchema;
133
+ adapts?: string;
71
134
 
135
+ /**
136
+ * Returns true when the association has 0 or 1 targets.
137
+ */
138
+ get isSingle(): boolean {
139
+ return this.targets.length < 2;
140
+ }
141
+
142
+ /**
143
+ * Creates an instance of DataAssociation from a target entity key.
144
+ * Note, this entity will have no name. The default name is used instead.
145
+ *
146
+ * @param root The namespace root.
147
+ * @param target The target entity key.
148
+ */
72
149
  static fromTarget(root: DataNamespace, target: string): DataAssociation {
73
150
  const assoc = new DataAssociation(root);
74
- assoc.target = target;
151
+ assoc.targets = [target];
75
152
  return assoc;
76
153
  }
77
154
 
155
+ /**
156
+ * Creates an instance of DataAssociation from a name, without defining a target.
157
+ *
158
+ * @param root The namespace root.
159
+ * @param name The name of the association.
160
+ */
78
161
  static fromName(root: DataNamespace, name: string): DataAssociation {
79
162
  const assoc = new DataAssociation(root);
80
163
  assoc.info = Thing.fromName(name);
@@ -84,7 +167,7 @@ export class DataAssociation {
84
167
  /**
85
168
  * @param input The data association definition to restore.
86
169
  */
87
- constructor(protected root: DataNamespace, input?: string | IDataAssociation) {
170
+ constructor(public root: DataNamespace, input?: string | IDataAssociation) {
88
171
  let init: IDataAssociation;
89
172
  if (typeof input === 'string') {
90
173
  init = JSON.parse(input);
@@ -94,7 +177,7 @@ export class DataAssociation {
94
177
  init = {
95
178
  kind: Kind,
96
179
  key: v4(),
97
- info: Thing.fromName('').toJSON(),
180
+ info: Thing.fromName('Unnamed association').toJSON(),
98
181
  };
99
182
  }
100
183
  this.new(init);
@@ -104,7 +187,10 @@ export class DataAssociation {
104
187
  if (!DataAssociation.isDataAssociation(init)) {
105
188
  throw new Error(`Not a data association.`);
106
189
  }
107
- const { info, key = v4(), kind = Kind, schema, multiple, required, target } = init;
190
+ const {
191
+ info, key = v4(), kind = Kind, schema, multiple, required, targets,
192
+ adapts, hidden,
193
+ } = init;
108
194
  this.kind = kind;
109
195
  this.key = key;
110
196
  if (info) {
@@ -113,7 +199,7 @@ export class DataAssociation {
113
199
  this.info = Thing.fromName('');
114
200
  }
115
201
  if (schema) {
116
- this.schema = { ...schema };
202
+ this.schema = JsonCore.clone(schema);
117
203
  } else {
118
204
  this.schema = undefined;
119
205
  }
@@ -127,10 +213,20 @@ export class DataAssociation {
127
213
  } else {
128
214
  this.required = undefined;
129
215
  }
130
- if (typeof target === 'string') {
131
- this.target = target;
216
+ if (Array.isArray(targets)) {
217
+ this.targets = [...targets];
132
218
  } else {
133
- this.target = undefined;
219
+ this.targets = [];
220
+ }
221
+ if (typeof hidden === 'boolean') {
222
+ this.hidden = hidden;
223
+ } else {
224
+ this.hidden = undefined;
225
+ }
226
+ if (typeof adapts === 'string') {
227
+ this.adapts = adapts;
228
+ } else {
229
+ this.adapts = undefined;
134
230
  }
135
231
  }
136
232
 
@@ -149,7 +245,7 @@ export class DataAssociation {
149
245
  info: this.info.toJSON(),
150
246
  };
151
247
  if (this.schema) {
152
- result.schema = { ...this.schema };
248
+ result.schema = JsonCore.clone(this.schema);
153
249
  }
154
250
  if (typeof this.multiple === 'boolean') {
155
251
  result.multiple = this.multiple;
@@ -157,18 +253,24 @@ export class DataAssociation {
157
253
  if (typeof this.required === 'boolean') {
158
254
  result.required = this.required;
159
255
  }
160
- if (typeof this.target === 'string') {
161
- result.target = this.target;
256
+ if (Array.isArray(this.targets) && this.targets.length) {
257
+ result.targets = [...this.targets];
258
+ }
259
+ if (typeof this.hidden === 'boolean') {
260
+ result.hidden = this.hidden;
261
+ }
262
+ if (this.adapts) {
263
+ result.adapts = this.adapts;
162
264
  }
163
265
  return result;
164
266
  }
165
267
 
166
- getTarget(): DataEntity | undefined {
167
- const { root, target } = this;
168
- if (!target) {
169
- return undefined;
170
- }
171
- return root.definitions.entities.find(i => i.key === target);
268
+ /**
269
+ * @returns The list of DataEntity definitions for the current targets.
270
+ */
271
+ getTargets(): DataEntity[] {
272
+ const { root, targets } = this;
273
+ return root.definitions.entities.filter(item => targets.some(i => i === item.key));
172
274
  }
173
275
 
174
276
  /**
@@ -186,4 +288,99 @@ export class DataAssociation {
186
288
  this.root.definitions.associations.splice(defIndex, 1);
187
289
  }
188
290
  }
291
+
292
+ /**
293
+ * Adds a target to the targets list from an entity.
294
+ * @param entity The instance or schema of an entity.
295
+ */
296
+ addTarget(entity: DataEntity | IDataEntity): void;
297
+
298
+ /**
299
+ * Adds the target to the targets list with an entity key..
300
+ * @param key The key of the entity to add.
301
+ */
302
+ addTarget(key: string): void;
303
+
304
+ /**
305
+ * @param init The key of an entity, its instance, or schema.
306
+ */
307
+ addTarget(init: string | DataEntity | IDataEntity): void {
308
+ if (typeof init === 'string') {
309
+ this.targets.push(init);
310
+ } else {
311
+ const { key } = init;
312
+ this.targets.push(key);
313
+ }
314
+ }
315
+
316
+ /**
317
+ * Removes a target entity from the targets list.
318
+ *
319
+ * @param entity The instance or schema of the entity to remove.
320
+ */
321
+ removeTarget(entity: DataEntity | IDataEntity): void;
322
+
323
+ /**
324
+ * Removes a target entity from the targets list.
325
+ *
326
+ * @param key The key of the target entity to remove.
327
+ */
328
+ removeTarget(key: string): void;
329
+
330
+ /**
331
+ * Removes a target entity from the targets list.
332
+ *
333
+ * @param init The key of an entity, its instance, or schema.
334
+ */
335
+ removeTarget(init: string | DataEntity | IDataEntity): void {
336
+ let key: string;
337
+ if (typeof init === 'string') {
338
+ key = init;
339
+ } else {
340
+ key = init.key;
341
+ }
342
+ const index = this.targets.indexOf(key);
343
+ if (index >= 0) {
344
+ this.targets.splice(index, 1);
345
+ }
346
+ }
347
+
348
+ /**
349
+ * Creates a Property Shape of AMF.
350
+ * The property itself is auto-generated. If the `schema` is defined then it is used
351
+ * as the `range` of the property. Otherwise basic shape is generated for the range.
352
+ *
353
+ * This is a preferred way of reading the AMF shape as this synchronizes changed
354
+ * data properties with the shape definition.
355
+ *
356
+ * @returns AMF property shape definition.
357
+ */
358
+ toApiShape(): IPropertyShape {
359
+ const serializer = new AmfShapeGenerator();
360
+ return serializer.associationProperty(this);
361
+ }
362
+
363
+ /**
364
+ * @returns The adapted association, if any
365
+ */
366
+ readAdapted(): DataAssociation | undefined {
367
+ const { adapts } = this;
368
+ if (!adapts) {
369
+ return undefined;
370
+ }
371
+ return this.root.definitions.associations.find(i => i.key === adapts);
372
+ }
373
+
374
+ /**
375
+ * Creates new adapted association and associates it with this association.
376
+ * @returns The instance of the created association.
377
+ */
378
+ createAdapted(): DataAssociation {
379
+ const association = new DataAssociation(this.root);
380
+ // disallow defaults as this would influence the schema generation
381
+ association.info.name = undefined;
382
+ this.root.definitions.associations.push(association);
383
+ this.adapts = association.key;
384
+ return association;
385
+ }
189
386
  }
@@ -29,4 +29,42 @@ export interface IDataAssociationSchema {
29
29
  * ```
30
30
  */
31
31
  embedded?: boolean;
32
+
33
+ /**
34
+ * Describes XML specific serialization.
35
+ */
36
+ xml?: {
37
+ /**
38
+ * The name of the attribute or a wrapped property to use when serializing the property.
39
+ *
40
+ * ```
41
+ * <Person fullName="John Doe"></Person>
42
+ * ```
43
+ */
44
+ name?: string;
45
+
46
+ /**
47
+ * When the property is an array (has the `multiple` set to true)
48
+ * then it tells that the list of values should be wrapped with a parent
49
+ * element:
50
+ *
51
+ * ```
52
+ * <Person>
53
+ * <Person fullName="John Doe"></Person>
54
+ * </Person>
55
+ * ```
56
+ *
57
+ * Use this with the combination with `name` to describe the name of the wrapped
58
+ * element
59
+ *
60
+ * ```
61
+ * <people>
62
+ * <Person fullName="John Doe"></Person>
63
+ * </people>
64
+ * ```
65
+ *
66
+ * Note, this is mutually exclusive with `attribute`.
67
+ */
68
+ wrapped?: boolean;
69
+ }
32
70
  }