@api-client/core 0.18.1 → 0.18.3

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@api-client/core",
3
3
  "description": "The API Client's core client library. Works in NodeJS and in a ES enabled browser.",
4
- "version": "0.18.1",
4
+ "version": "0.18.3",
5
5
  "license": "Apache-2.0",
6
6
  "exports": {
7
7
  "./browser.js": {
@@ -3,6 +3,7 @@ import { ApiModelKind, DataDomainKind } from '../models/kinds.js'
3
3
  import { type IThing, Thing } from '../models/Thing.js'
4
4
  import type {
5
5
  AccessRule,
6
+ AssociationTarget,
6
7
  AuthenticationConfiguration,
7
8
  AuthorizationConfiguration,
8
9
  ExposedEntity,
@@ -12,7 +13,40 @@ import type {
12
13
  UsernamePasswordConfiguration,
13
14
  } from './types.js'
14
15
  import { DataDomain } from './DataDomain.js'
15
- import { DependentModel, type DomainDependency, type DependentModelSchema } from './DependentModel.js'
16
+ import { DependentModel, type DependentModelSchema, type DomainDependency } from './DependentModel.js'
17
+ import { observed, toRaw } from './observed.js'
18
+
19
+ /**
20
+ * Contact information for the exposed API.
21
+ */
22
+ export interface ApiContact {
23
+ /**
24
+ * The identifying name of the contact person/organization.
25
+ */
26
+ name?: string
27
+ /**
28
+ * The URL pointing to the contact information. MUST be in the format of a URL.
29
+ */
30
+ url?: string
31
+ /**
32
+ * The email address of the contact person/organization. MUST be in the format of an email address.
33
+ */
34
+ email?: string
35
+ }
36
+
37
+ /**
38
+ * License information for the exposed API.
39
+ */
40
+ export interface ApiLicense {
41
+ /**
42
+ * The license name used for the API. It is recommended to be an SPDX license identifier.
43
+ */
44
+ name: string
45
+ /**
46
+ * A URL to the license used for the API. MUST be in the format of a URL.
47
+ */
48
+ url?: string
49
+ }
16
50
 
17
51
  export interface ApiModelSchema extends DependentModelSchema {
18
52
  /**
@@ -31,11 +65,11 @@ export interface ApiModelSchema extends DependentModelSchema {
31
65
 
32
66
  /**
33
67
  * The designated Data Entity that represents a "User".
34
- * This entity must be marked with the "User" semantic in the Data Modeler.
68
+ * This entity should be marked with the "User" semantic in the Data Modeler.
35
69
  *
36
70
  * This property is required to publish the API.
37
71
  */
38
- userKey?: string
72
+ user?: AssociationTarget
39
73
 
40
74
  /**
41
75
  * Configuration for how users prove their identity.
@@ -74,6 +108,18 @@ export interface ApiModelSchema extends DependentModelSchema {
74
108
  * Defines rules to protect the API from overuse.
75
109
  */
76
110
  rateLimiting?: RateLimitingConfiguration
111
+ /**
112
+ * A URL to the Terms of Service for the API.
113
+ */
114
+ termsOfService?: string
115
+ /**
116
+ * The contact information for the exposed API.
117
+ */
118
+ contact?: ApiContact
119
+ /**
120
+ * The license information for the API.
121
+ */
122
+ license?: ApiLicense
77
123
  }
78
124
 
79
125
  export class ApiModel extends DependentModel {
@@ -97,7 +143,7 @@ export class ApiModel extends DependentModel {
97
143
  *
98
144
  * This property is required to publish the API.
99
145
  */
100
- userKey?: string
146
+ user?: AssociationTarget
101
147
 
102
148
  /**
103
149
  * Configuration for how users prove their identity.
@@ -135,6 +181,18 @@ export class ApiModel extends DependentModel {
135
181
  * Defines rules to protect the API from overuse.
136
182
  */
137
183
  rateLimiting?: RateLimitingConfiguration
184
+ /**
185
+ * A URL to the Terms of Service for the API.
186
+ */
187
+ @observed() accessor termsOfService: string | undefined
188
+ /**
189
+ * The contact information for the exposed API.
190
+ */
191
+ @observed({ deep: true }) accessor contact: ApiContact | undefined
192
+ /**
193
+ * The license information for the API.
194
+ */
195
+ @observed({ deep: true }) accessor license: ApiLicense | undefined
138
196
 
139
197
  /**
140
198
  * When the initializing flag is set to true,
@@ -175,8 +233,8 @@ export class ApiModel extends DependentModel {
175
233
  info,
176
234
  exposes,
177
235
  }
178
- if (input.userKey) {
179
- result.userKey = input.userKey
236
+ if (input.user) {
237
+ result.user = { ...input.user }
180
238
  }
181
239
  if (input.dependencyList) {
182
240
  result.dependencyList = structuredClone(input.dependencyList)
@@ -196,6 +254,15 @@ export class ApiModel extends DependentModel {
196
254
  if (input.rateLimiting) {
197
255
  result.rateLimiting = input.rateLimiting
198
256
  }
257
+ if (input.termsOfService) {
258
+ result.termsOfService = input.termsOfService
259
+ }
260
+ if (input.contact) {
261
+ result.contact = structuredClone(input.contact)
262
+ }
263
+ if (input.license) {
264
+ result.license = structuredClone(input.license)
265
+ }
199
266
  return result
200
267
  }
201
268
 
@@ -213,7 +280,7 @@ export class ApiModel extends DependentModel {
213
280
  this.kind = init.kind
214
281
  this.key = init.key
215
282
  this.info = new Thing(init.info)
216
- this.userKey = init.userKey
283
+ this.user = init.user
217
284
  if (init.authentication) {
218
285
  this.authentication = structuredClone(init.authentication)
219
286
  }
@@ -234,6 +301,15 @@ export class ApiModel extends DependentModel {
234
301
  if (init.rateLimiting) {
235
302
  this.rateLimiting = structuredClone(init.rateLimiting)
236
303
  }
304
+ if (init.termsOfService) {
305
+ this.termsOfService = init.termsOfService
306
+ }
307
+ if (init.contact) {
308
+ this.contact = init.contact
309
+ }
310
+ if (init.license) {
311
+ this.license = init.license
312
+ }
237
313
  this.#initializing = false
238
314
  this.info.addEventListener('change', () => {
239
315
  this.notifyChange()
@@ -247,8 +323,8 @@ export class ApiModel extends DependentModel {
247
323
  info: this.info.toJSON(),
248
324
  exposes: structuredClone(this.exposes),
249
325
  }
250
- if (this.userKey) {
251
- result.userKey = this.userKey
326
+ if (this.user) {
327
+ result.user = { ...this.user }
252
328
  }
253
329
  if (this.dependencyList.length > 0) {
254
330
  result.dependencyList = structuredClone(this.dependencyList)
@@ -268,6 +344,15 @@ export class ApiModel extends DependentModel {
268
344
  if (this.rateLimiting) {
269
345
  result.rateLimiting = structuredClone(this.rateLimiting)
270
346
  }
347
+ if (this.termsOfService) {
348
+ result.termsOfService = this.termsOfService
349
+ }
350
+ if (this.contact) {
351
+ result.contact = structuredClone(toRaw(this, this.contact))
352
+ }
353
+ if (this.license) {
354
+ result.license = structuredClone(toRaw(this, this.license))
355
+ }
271
356
  return result
272
357
  }
273
358
 
@@ -330,14 +415,14 @@ export class ApiModel extends DependentModel {
330
415
 
331
416
  /**
332
417
  * Clears the API model for a new entity change.
333
- * This method resets the dependencies, exposes, userKey,
418
+ * This method resets the dependencies, exposes, user,
334
419
  * authentication, authorization, and session properties.
335
420
  */
336
421
  cleanForEntityChange(): void {
337
422
  this.dependencies.clear()
338
423
  this.dependencyList = []
339
424
  this.exposes = []
340
- this.userKey = undefined
425
+ this.user = undefined
341
426
  if (this.session) {
342
427
  this.session.properties = []
343
428
  }
@@ -6,6 +6,8 @@ import {
6
6
  type RolesBasedAccessControl,
7
7
  type ApiModelSchema,
8
8
  type ExposedEntity,
9
+ type ApiContact,
10
+ type ApiLicense,
9
11
  } from '../../../src/index.js'
10
12
 
11
13
  test.group('ApiModel.createSchema()', (g) => {
@@ -19,13 +21,16 @@ test.group('ApiModel.createSchema()', (g) => {
19
21
  assert.isNotEmpty(schema.key)
20
22
  assert.deepInclude(schema.info, { name: 'Unnamed API' })
21
23
  assert.deepEqual(schema.exposes, [])
22
- assert.isUndefined(schema.userKey)
24
+ assert.isUndefined(schema.user)
23
25
  assert.isUndefined(schema.dependencyList)
24
26
  assert.isUndefined(schema.authentication)
25
27
  assert.isUndefined(schema.authorization)
26
28
  assert.isUndefined(schema.session)
27
29
  assert.isUndefined(schema.accessRule)
28
30
  assert.isUndefined(schema.rateLimiting)
31
+ assert.isUndefined(schema.termsOfService)
32
+ assert.isUndefined(schema.contact)
33
+ assert.isUndefined(schema.license)
29
34
  })
30
35
 
31
36
  test('creates a schema with provided values', ({ assert }) => {
@@ -33,13 +38,16 @@ test.group('ApiModel.createSchema()', (g) => {
33
38
  key: 'test-api',
34
39
  info: { name: 'Test API', description: 'A test API' },
35
40
  exposes: [{ key: 'entity1', actions: [] }],
36
- userKey: 'user-entity',
41
+ user: { key: 'user-entity' },
37
42
  dependencyList: [{ key: 'domain1', version: '1.0.0' }],
38
43
  authentication: { strategy: 'UsernamePassword' },
39
44
  authorization: { strategy: 'RBAC', roleKey: 'role' } as RolesBasedAccessControl,
40
45
  session: { secret: 'secret', properties: ['email'] },
41
46
  accessRule: [{ type: 'public' }],
42
47
  rateLimiting: { rules: [] },
48
+ termsOfService: 'https://example.com/terms',
49
+ contact: { name: 'John Doe', email: 'john.doe@example.com' } as ApiContact,
50
+ license: { name: 'MIT', url: 'https://opensource.org/licenses/MIT' } as ApiLicense,
43
51
  }
44
52
  const schema = ApiModel.createSchema(input)
45
53
 
@@ -47,13 +55,16 @@ test.group('ApiModel.createSchema()', (g) => {
47
55
  assert.equal(schema.key, 'test-api')
48
56
  assert.deepInclude(schema.info, { name: 'Test API', description: 'A test API' })
49
57
  assert.deepEqual(schema.exposes, [{ key: 'entity1', actions: [] }])
50
- assert.equal(schema.userKey, 'user-entity')
58
+ assert.deepEqual(schema.user, { key: 'user-entity' })
51
59
  assert.deepEqual(schema.dependencyList, [{ key: 'domain1', version: '1.0.0' }])
52
60
  assert.deepEqual(schema.authentication, { strategy: 'UsernamePassword' })
53
61
  assert.deepEqual(schema.authorization, { strategy: 'RBAC', roleKey: 'role' })
54
62
  assert.deepEqual(schema.session, { secret: 'secret', properties: ['email'] })
55
63
  assert.deepEqual(schema.accessRule, [{ type: 'public' }])
56
64
  assert.deepEqual(schema.rateLimiting, { rules: [] })
65
+ assert.equal(schema.termsOfService, 'https://example.com/terms')
66
+ assert.deepEqual(schema.contact, { name: 'John Doe', email: 'john.doe@example.com' })
67
+ assert.deepEqual(schema.license, { name: 'MIT', url: 'https://opensource.org/licenses/MIT' })
57
68
  })
58
69
 
59
70
  test('creates a schema with partial info', ({ assert }) => {
@@ -79,12 +90,15 @@ test.group('ApiModel.constructor()', (g) => {
79
90
  assert.isNotEmpty(model.key)
80
91
  assert.equal(model.info.name, 'Unnamed API')
81
92
  assert.deepEqual(model.exposes, [])
82
- assert.isUndefined(model.userKey)
93
+ assert.isUndefined(model.user)
83
94
  assert.isUndefined(model.authentication)
84
95
  assert.isUndefined(model.authorization)
85
96
  assert.isUndefined(model.session)
86
97
  assert.isUndefined(model.accessRule)
87
98
  assert.isUndefined(model.rateLimiting)
99
+ assert.isUndefined(model.termsOfService)
100
+ assert.isUndefined(model.contact)
101
+ assert.isUndefined(model.license)
88
102
  assert.deepEqual(model.dependencyList, [])
89
103
  })
90
104
 
@@ -94,26 +108,32 @@ test.group('ApiModel.constructor()', (g) => {
94
108
  key: 'test-api',
95
109
  info: { name: 'Test API', description: 'A test API' },
96
110
  exposes: [{ key: 'entity1', actions: [] }],
97
- userKey: 'user-entity',
111
+ user: { key: 'user-entity' },
98
112
  dependencyList: [{ key: 'domain1', version: '1.0.0' }],
99
113
  authentication: { strategy: 'UsernamePassword' },
100
114
  authorization: { strategy: 'RBAC', roleKey: 'role' } as RolesBasedAccessControl,
101
115
  session: { secret: 'secret', properties: ['email'] },
102
116
  accessRule: [{ type: 'public' }],
103
117
  rateLimiting: { rules: [] },
118
+ termsOfService: 'https://example.com/terms',
119
+ contact: { name: 'John Doe', email: 'john.doe@example.com' },
120
+ license: { name: 'MIT', url: 'https://opensource.org/licenses/MIT' },
104
121
  }
105
122
  const model = new ApiModel(schema)
106
123
 
107
124
  assert.equal(model.key, 'test-api')
108
125
  assert.equal(model.info.name, 'Test API')
109
126
  assert.deepEqual(model.exposes, [{ key: 'entity1', actions: [] }])
110
- assert.equal(model.userKey, 'user-entity')
127
+ assert.deepEqual(model.user, { key: 'user-entity' })
111
128
  assert.deepEqual(model.dependencyList, [{ key: 'domain1', version: '1.0.0' }])
112
129
  assert.deepEqual(model.authentication, { strategy: 'UsernamePassword' })
113
130
  assert.deepEqual(model.authorization, { strategy: 'RBAC', roleKey: 'role' })
114
131
  assert.deepEqual(model.session, { secret: 'secret', properties: ['email'] })
115
132
  assert.deepEqual(model.accessRule, [{ type: 'public' }])
116
133
  assert.deepEqual(model.rateLimiting, { rules: [] })
134
+ assert.equal(model.termsOfService, 'https://example.com/terms')
135
+ assert.deepEqual(model.contact, { name: 'John Doe', email: 'john.doe@example.com' })
136
+ assert.deepEqual(model.license, { name: 'MIT', url: 'https://opensource.org/licenses/MIT' })
117
137
  })
118
138
 
119
139
  test('creates an instance with a DataDomain', ({ assert }) => {
@@ -152,13 +172,16 @@ test.group('ApiModel.toJSON()', (g) => {
152
172
  assert.equal(json.key, model.key)
153
173
  assert.deepInclude(json.info, { name: 'Unnamed API' })
154
174
  assert.deepEqual(json.exposes, [])
155
- assert.isUndefined(json.userKey)
175
+ assert.isUndefined(json.user)
156
176
  assert.isUndefined(json.dependencyList)
157
177
  assert.isUndefined(json.authentication)
158
178
  assert.isUndefined(json.authorization)
159
179
  assert.isUndefined(json.session)
160
180
  assert.isUndefined(json.accessRule)
161
181
  assert.isUndefined(json.rateLimiting)
182
+ assert.isUndefined(json.termsOfService)
183
+ assert.isUndefined(json.contact)
184
+ assert.isUndefined(json.license)
162
185
  })
163
186
 
164
187
  test('serializes all provided values', ({ assert }) => {
@@ -167,13 +190,16 @@ test.group('ApiModel.toJSON()', (g) => {
167
190
  key: 'test-api',
168
191
  info: { name: 'Test API', description: 'A test API' },
169
192
  exposes: [{ key: 'entity1', actions: [] }],
170
- userKey: 'user-entity',
193
+ user: { key: 'user-entity' },
171
194
  dependencyList: [{ key: 'domain1', version: '1.0.0' }],
172
195
  authentication: { strategy: 'UsernamePassword' },
173
196
  authorization: { strategy: 'RBAC', roleKey: 'role' } as RolesBasedAccessControl,
174
197
  session: { secret: 'secret', properties: ['email'] },
175
198
  accessRule: [{ type: 'public' }],
176
199
  rateLimiting: { rules: [] },
200
+ termsOfService: 'https://example.com/terms',
201
+ contact: { name: 'John Doe', email: 'john.doe@example.com' },
202
+ license: { name: 'MIT', url: 'https://opensource.org/licenses/MIT' },
177
203
  }
178
204
  const model = new ApiModel(schema)
179
205
  const json = model.toJSON()
@@ -181,13 +207,16 @@ test.group('ApiModel.toJSON()', (g) => {
181
207
  assert.equal(json.key, 'test-api')
182
208
  assert.deepInclude(json.info, { name: 'Test API', description: 'A test API' })
183
209
  assert.deepEqual(json.exposes, [{ key: 'entity1', actions: [] }])
184
- assert.equal(json.userKey, 'user-entity')
210
+ assert.deepEqual(json.user, { key: 'user-entity' })
185
211
  assert.deepEqual(json.dependencyList, [{ key: 'domain1', version: '1.0.0' }])
186
212
  assert.deepEqual(json.authentication, { strategy: 'UsernamePassword' })
187
213
  assert.deepEqual(json.authorization, { strategy: 'RBAC', roleKey: 'role' })
188
214
  assert.deepEqual(json.session, { secret: 'secret', properties: ['email'] })
189
215
  assert.deepEqual(json.accessRule, [{ type: 'public' }])
190
216
  assert.deepEqual(json.rateLimiting, { rules: [] })
217
+ assert.equal(json.termsOfService, 'https://example.com/terms')
218
+ assert.deepEqual(json.contact, { name: 'John Doe', email: 'john.doe@example.com' })
219
+ assert.deepEqual(json.license, { name: 'MIT', url: 'https://opensource.org/licenses/MIT' })
191
220
  })
192
221
  })
193
222