@api-client/core 0.14.6 → 0.14.8
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/ApiSchemaValues.js.map +1 -1
- package/build/src/modeling/ApiModel.d.ts +27 -17
- package/build/src/modeling/ApiModel.d.ts.map +1 -1
- package/build/src/modeling/ApiModel.js +69 -20
- package/build/src/modeling/ApiModel.js.map +1 -1
- package/build/src/modeling/DataDomain.d.ts +34 -20
- package/build/src/modeling/DataDomain.d.ts.map +1 -1
- package/build/src/modeling/DataDomain.js +64 -24
- package/build/src/modeling/DataDomain.js.map +1 -1
- package/build/src/modeling/DependentModel.d.ts +26 -0
- package/build/src/modeling/DependentModel.d.ts.map +1 -0
- package/build/src/modeling/DependentModel.js +23 -0
- package/build/src/modeling/DependentModel.js.map +1 -0
- package/build/src/modeling/types.d.ts +2 -0
- package/build/src/modeling/types.d.ts.map +1 -1
- package/build/src/modeling/types.js.map +1 -1
- package/build/src/models/store/Backend.d.ts +0 -168
- package/build/src/models/store/Backend.d.ts.map +1 -1
- package/build/src/models/store/Backend.js +1 -12
- package/build/src/models/store/Backend.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/data/models/example-generator-api.json +16 -16
- package/package.json +1 -1
- package/src/amf/ApiSchemaValues.ts +1 -1
- package/src/modeling/ApiModel.ts +74 -31
- package/src/modeling/DataDomain.ts +65 -35
- package/src/modeling/DependentModel.ts +36 -0
- package/src/modeling/types.ts +2 -0
- package/src/models/store/Backend.ts +0 -176
- package/tests/unit/modeling/api_model.spec.ts +17 -15
- package/tests/unit/modeling/data_domain_foreign.spec.ts +172 -39
|
@@ -42062,10 +42062,10 @@
|
|
|
42062
42062
|
"@id": "#209"
|
|
42063
42063
|
},
|
|
42064
42064
|
{
|
|
42065
|
-
"@id": "#
|
|
42065
|
+
"@id": "#194"
|
|
42066
42066
|
},
|
|
42067
42067
|
{
|
|
42068
|
-
"@id": "#
|
|
42068
|
+
"@id": "#191"
|
|
42069
42069
|
},
|
|
42070
42070
|
{
|
|
42071
42071
|
"@id": "#197"
|
|
@@ -42810,6 +42810,9 @@
|
|
|
42810
42810
|
"@id": "#219"
|
|
42811
42811
|
},
|
|
42812
42812
|
{
|
|
42813
|
+
"@id": "#219"
|
|
42814
|
+
},
|
|
42815
|
+
{
|
|
42813
42816
|
"@id": "#210"
|
|
42814
42817
|
},
|
|
42815
42818
|
{
|
|
@@ -42817,9 +42820,6 @@
|
|
|
42817
42820
|
},
|
|
42818
42821
|
{
|
|
42819
42822
|
"@id": "#213"
|
|
42820
|
-
},
|
|
42821
|
-
{
|
|
42822
|
-
"@id": "#219"
|
|
42823
42823
|
}
|
|
42824
42824
|
],
|
|
42825
42825
|
"doc:root": false,
|
|
@@ -43436,7 +43436,7 @@
|
|
|
43436
43436
|
"doc:ExternalDomainElement",
|
|
43437
43437
|
"doc:DomainElement"
|
|
43438
43438
|
],
|
|
43439
|
-
"doc:raw": "
|
|
43439
|
+
"doc:raw": "addressType: 'REGISTERED-OFFICE-ADDRESS'\nstreetName: 'UITBREIDINGSTRAAT'\nhouseNumber: '84'\nhouseNumberAddition: '/1'\npostalCode: '2600'\ncity: 'BERCHEM (ANTWERPEN)'\ncountry: 'Belgium'\ncountryCode: 'BE'\nfullFormatedAddress: \"UITBREIDINGSTRAAT 84 /1, 2600 BERCHEM (ANTWERPEN), BELIUM\"\n",
|
|
43440
43440
|
"core:mediaType": "application/yaml",
|
|
43441
43441
|
"sourcemaps:sources": [
|
|
43442
43442
|
{
|
|
@@ -43457,7 +43457,7 @@
|
|
|
43457
43457
|
"doc:ExternalDomainElement",
|
|
43458
43458
|
"doc:DomainElement"
|
|
43459
43459
|
],
|
|
43460
|
-
"doc:raw": "
|
|
43460
|
+
"doc:raw": "countryCode: \"BE\"\ngraydonEnterpriseId: 1057155523\nregistrationId: \"0422319093\"\nvatNumber: \"BE0422319093\"\ngraydonCompanyId: \"0422319093\"\nisBranchOffice: false\n",
|
|
43461
43461
|
"core:mediaType": "application/yaml",
|
|
43462
43462
|
"sourcemaps:sources": [
|
|
43463
43463
|
{
|
|
@@ -44232,7 +44232,7 @@
|
|
|
44232
44232
|
"doc:ExternalDomainElement",
|
|
44233
44233
|
"doc:DomainElement"
|
|
44234
44234
|
],
|
|
44235
|
-
"doc:raw": "type: 'GENERAL'\ncountryDialCode : '+32'\nareaCode : '
|
|
44235
|
+
"doc:raw": "type: 'GENERAL'\ncountryDialCode : '+32'\nareaCode : '21'\nsubscriberNumber: '12.87.00'\nformatted: '+32-(0)21 302099'\n",
|
|
44236
44236
|
"core:mediaType": "application/yaml",
|
|
44237
44237
|
"sourcemaps:sources": [
|
|
44238
44238
|
{
|
|
@@ -44253,7 +44253,7 @@
|
|
|
44253
44253
|
"doc:ExternalDomainElement",
|
|
44254
44254
|
"doc:DomainElement"
|
|
44255
44255
|
],
|
|
44256
|
-
"doc:raw": "
|
|
44256
|
+
"doc:raw": "type: \"GENERAL\"\nvalue: \"www.company.be\"\n",
|
|
44257
44257
|
"core:mediaType": "application/yaml",
|
|
44258
44258
|
"sourcemaps:sources": [
|
|
44259
44259
|
{
|
|
@@ -44274,7 +44274,7 @@
|
|
|
44274
44274
|
"doc:ExternalDomainElement",
|
|
44275
44275
|
"doc:DomainElement"
|
|
44276
44276
|
],
|
|
44277
|
-
"doc:raw": "type: 'GENERAL'\
|
|
44277
|
+
"doc:raw": "-\n type: 'GENERAL'\n value: 'info@company.be'\n-\n type: 'IT_DEPT'\n value: 'it-service@company.be'\n",
|
|
44278
44278
|
"core:mediaType": "application/yaml",
|
|
44279
44279
|
"sourcemaps:sources": [
|
|
44280
44280
|
{
|
|
@@ -44295,7 +44295,7 @@
|
|
|
44295
44295
|
"doc:ExternalDomainElement",
|
|
44296
44296
|
"doc:DomainElement"
|
|
44297
44297
|
],
|
|
44298
|
-
"doc:raw": "type:
|
|
44298
|
+
"doc:raw": "type: 'GENERAL'\ncountryDialCode : '+32'\nareaCode : '22'\nsubscriberNumber: '12.87.00'\nformatted: '+32-(0)22 000000'\n",
|
|
44299
44299
|
"core:mediaType": "application/yaml",
|
|
44300
44300
|
"sourcemaps:sources": [
|
|
44301
44301
|
{
|
|
@@ -44756,12 +44756,12 @@
|
|
|
44756
44756
|
{
|
|
44757
44757
|
"@id": "#193/source-map/lexical/element_0",
|
|
44758
44758
|
"sourcemaps:element": "amf://id#193",
|
|
44759
|
-
"sourcemaps:value": "[(1,0)-(
|
|
44759
|
+
"sourcemaps:value": "[(1,0)-(10,0)]"
|
|
44760
44760
|
},
|
|
44761
44761
|
{
|
|
44762
44762
|
"@id": "#196/source-map/lexical/element_0",
|
|
44763
44763
|
"sourcemaps:element": "amf://id#196",
|
|
44764
|
-
"sourcemaps:value": "[(1,0)-(
|
|
44764
|
+
"sourcemaps:value": "[(1,0)-(7,0)]"
|
|
44765
44765
|
},
|
|
44766
44766
|
{
|
|
44767
44767
|
"@id": "#199/source-map/lexical/element_0",
|
|
@@ -45121,17 +45121,17 @@
|
|
|
45121
45121
|
{
|
|
45122
45122
|
"@id": "#215/source-map/lexical/element_0",
|
|
45123
45123
|
"sourcemaps:element": "amf://id#215",
|
|
45124
|
-
"sourcemaps:value": "[(1,0)-(
|
|
45124
|
+
"sourcemaps:value": "[(1,0)-(3,0)]"
|
|
45125
45125
|
},
|
|
45126
45126
|
{
|
|
45127
45127
|
"@id": "#218/source-map/lexical/element_0",
|
|
45128
45128
|
"sourcemaps:element": "amf://id#218",
|
|
45129
|
-
"sourcemaps:value": "[(1,0)-(
|
|
45129
|
+
"sourcemaps:value": "[(1,0)-(7,0)]"
|
|
45130
45130
|
},
|
|
45131
45131
|
{
|
|
45132
45132
|
"@id": "#221/source-map/lexical/element_0",
|
|
45133
45133
|
"sourcemaps:element": "amf://id#221",
|
|
45134
|
-
"sourcemaps:value": "[(1,0)-(
|
|
45134
|
+
"sourcemaps:value": "[(1,0)-(6,0)]"
|
|
45135
45135
|
},
|
|
45136
45136
|
{
|
|
45137
45137
|
"@id": "#338/source-map/synthesized-field/element_1",
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
IApiScalarShape,
|
|
16
16
|
IShapeUnion,
|
|
17
17
|
} from './definitions/Shapes.js'
|
|
18
|
-
import { ILoremWordInit, ITypeHashInit, ITypeNumberInit } from '@pawel-up/data-mock/types.js'
|
|
18
|
+
import type { ILoremWordInit, ITypeHashInit, ITypeNumberInit } from '@pawel-up/data-mock/types.js'
|
|
19
19
|
|
|
20
20
|
export interface IApiSchemaReadOptions {
|
|
21
21
|
/**
|
package/src/modeling/ApiModel.ts
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { nanoid } from '../nanoid.js'
|
|
2
|
-
import { ApiModelKind } from '../models/kinds.js'
|
|
2
|
+
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
6
|
AuthenticationConfiguration,
|
|
7
7
|
AuthorizationConfiguration,
|
|
8
8
|
ExposedEntity,
|
|
9
|
-
ForeignDomainDependency,
|
|
10
9
|
RateLimitingConfiguration,
|
|
10
|
+
RolesBasedAccessControl,
|
|
11
11
|
SessionConfiguration,
|
|
12
|
+
UsernamePasswordConfiguration,
|
|
12
13
|
} from './types.js'
|
|
13
|
-
import { DataDomain
|
|
14
|
+
import { DataDomain } from './DataDomain.js'
|
|
15
|
+
import { DependentModel, type DomainDependency, type DependentModelSchema } from './DependentModel.js'
|
|
14
16
|
|
|
15
|
-
export interface ApiModelSchema {
|
|
17
|
+
export interface ApiModelSchema extends DependentModelSchema {
|
|
16
18
|
/**
|
|
17
19
|
* The data domain kind recognizable by the ecosystem.
|
|
18
20
|
*/
|
|
@@ -35,12 +37,6 @@ export interface ApiModelSchema {
|
|
|
35
37
|
*/
|
|
36
38
|
userKey?: string
|
|
37
39
|
|
|
38
|
-
/**
|
|
39
|
-
* Reference to the stable, version-controlled data definition from the
|
|
40
|
-
* Data Catalog. When not set, the model cannot be published.
|
|
41
|
-
*/
|
|
42
|
-
domain?: ForeignDomainDependency
|
|
43
|
-
|
|
44
40
|
/**
|
|
45
41
|
* Configuration for how users prove their identity.
|
|
46
42
|
* The API model is invalid if this is not set.
|
|
@@ -80,7 +76,7 @@ export interface ApiModelSchema {
|
|
|
80
76
|
rateLimiting?: RateLimitingConfiguration
|
|
81
77
|
}
|
|
82
78
|
|
|
83
|
-
export class ApiModel extends
|
|
79
|
+
export class ApiModel extends DependentModel {
|
|
84
80
|
/**
|
|
85
81
|
* The data domain kind recognizable by the ecosystem.
|
|
86
82
|
*/
|
|
@@ -103,12 +99,6 @@ export class ApiModel extends EventTarget {
|
|
|
103
99
|
*/
|
|
104
100
|
userKey?: string
|
|
105
101
|
|
|
106
|
-
/**
|
|
107
|
-
* Reference to the stable, version-controlled data definition from the
|
|
108
|
-
* Data Catalog. When not set, the model cannot be published.
|
|
109
|
-
*/
|
|
110
|
-
domain?: ForeignDomainDependency
|
|
111
|
-
|
|
112
102
|
/**
|
|
113
103
|
* Configuration for how users prove their identity.
|
|
114
104
|
* The API model is invalid if this is not set.
|
|
@@ -161,9 +151,20 @@ export class ApiModel extends EventTarget {
|
|
|
161
151
|
#notifying = false
|
|
162
152
|
|
|
163
153
|
/**
|
|
164
|
-
* A
|
|
154
|
+
* A convenience getter that returns the DataDomain associated with this API model.
|
|
155
|
+
* Since the API model can have only one DataDomain,
|
|
156
|
+
* this getter returns the first dependency in the list.
|
|
157
|
+
*
|
|
158
|
+
* The parent interface `DependentModel` allows for multiple dependencies,
|
|
159
|
+
* to unify the dependency management across different models.
|
|
165
160
|
*/
|
|
166
|
-
|
|
161
|
+
get domain(): DataDomain | undefined {
|
|
162
|
+
if (this.dependencyList.length === 0) {
|
|
163
|
+
return undefined
|
|
164
|
+
}
|
|
165
|
+
const domain = this.dependencyList[0]
|
|
166
|
+
return this.dependencies.get(domain.key)
|
|
167
|
+
}
|
|
167
168
|
|
|
168
169
|
static createSchema(input: Partial<ApiModelSchema> = {}): ApiModelSchema {
|
|
169
170
|
const { key = nanoid(), exposes = [] } = input
|
|
@@ -177,8 +178,8 @@ export class ApiModel extends EventTarget {
|
|
|
177
178
|
if (input.userKey) {
|
|
178
179
|
result.userKey = input.userKey
|
|
179
180
|
}
|
|
180
|
-
if (input.
|
|
181
|
-
result.
|
|
181
|
+
if (input.dependencyList) {
|
|
182
|
+
result.dependencyList = structuredClone(input.dependencyList)
|
|
182
183
|
}
|
|
183
184
|
if (input.authentication) {
|
|
184
185
|
result.authentication = input.authentication
|
|
@@ -198,16 +199,21 @@ export class ApiModel extends EventTarget {
|
|
|
198
199
|
return result
|
|
199
200
|
}
|
|
200
201
|
|
|
201
|
-
constructor(state?: Partial<ApiModelSchema>, domain?:
|
|
202
|
-
super()
|
|
202
|
+
constructor(state?: Partial<ApiModelSchema>, domain?: DomainDependency) {
|
|
203
203
|
const init = ApiModel.createSchema(state)
|
|
204
|
+
const instances: DataDomain[] = []
|
|
205
|
+
if (domain instanceof DataDomain) {
|
|
206
|
+
instances.push(domain)
|
|
207
|
+
} else if (typeof domain === 'object' && domain.kind === DataDomainKind) {
|
|
208
|
+
instances.push(new DataDomain(domain))
|
|
209
|
+
} else if (domain) {
|
|
210
|
+
throw new Error(`Invalid domain provided. Expected a DataDomain instance or schema.`)
|
|
211
|
+
}
|
|
212
|
+
super(init.dependencyList, instances)
|
|
204
213
|
this.kind = init.kind
|
|
205
214
|
this.key = init.key
|
|
206
215
|
this.info = new Thing(init.info)
|
|
207
216
|
this.userKey = init.userKey
|
|
208
|
-
if (init.domain) {
|
|
209
|
-
this.domain = structuredClone(init.domain)
|
|
210
|
-
}
|
|
211
217
|
if (init.authentication) {
|
|
212
218
|
this.authentication = structuredClone(init.authentication)
|
|
213
219
|
}
|
|
@@ -228,9 +234,6 @@ export class ApiModel extends EventTarget {
|
|
|
228
234
|
if (init.rateLimiting) {
|
|
229
235
|
this.rateLimiting = structuredClone(init.rateLimiting)
|
|
230
236
|
}
|
|
231
|
-
if (domain) {
|
|
232
|
-
this.dataDomain = new DataDomain(domain)
|
|
233
|
-
}
|
|
234
237
|
this.#initializing = false
|
|
235
238
|
this.info.addEventListener('change', () => {
|
|
236
239
|
this.notifyChange()
|
|
@@ -247,8 +250,8 @@ export class ApiModel extends EventTarget {
|
|
|
247
250
|
if (this.userKey) {
|
|
248
251
|
result.userKey = this.userKey
|
|
249
252
|
}
|
|
250
|
-
if (this.
|
|
251
|
-
result.
|
|
253
|
+
if (this.dependencyList.length > 0) {
|
|
254
|
+
result.dependencyList = structuredClone(this.dependencyList)
|
|
252
255
|
}
|
|
253
256
|
if (this.authentication) {
|
|
254
257
|
result.authentication = structuredClone(this.authentication)
|
|
@@ -324,4 +327,44 @@ export class ApiModel extends EventTarget {
|
|
|
324
327
|
getExposedEntity(entityKey: string): ExposedEntity | undefined {
|
|
325
328
|
return this.exposes.find((e) => e.key === entityKey)
|
|
326
329
|
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Clears the API model for a new entity change.
|
|
333
|
+
* This method resets the dependencies, exposes, userKey,
|
|
334
|
+
* authentication, authorization, and session properties.
|
|
335
|
+
*/
|
|
336
|
+
cleanForEntityChange(): void {
|
|
337
|
+
this.dependencies.clear()
|
|
338
|
+
this.dependencyList = []
|
|
339
|
+
this.exposes = []
|
|
340
|
+
this.userKey = undefined
|
|
341
|
+
if (this.session) {
|
|
342
|
+
this.session.properties = []
|
|
343
|
+
}
|
|
344
|
+
if (this.authentication && this.authentication.strategy === 'UsernamePassword') {
|
|
345
|
+
const typed = this.authentication as UsernamePasswordConfiguration
|
|
346
|
+
typed.passwordKey = undefined
|
|
347
|
+
}
|
|
348
|
+
if (this.authorization && this.authorization.strategy == 'RBAC') {
|
|
349
|
+
const typed = this.authorization as RolesBasedAccessControl
|
|
350
|
+
typed.roleKey = ''
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Attaches a DataDomain to this API model.
|
|
356
|
+
* This method clears any existing dependencies and sets the new domain.
|
|
357
|
+
*
|
|
358
|
+
* @param domain The DataDomain to attach to this API model.
|
|
359
|
+
* @throws Error if the domain does not have a version set in its info.
|
|
360
|
+
*/
|
|
361
|
+
attachDataDomain(domain: DataDomain): void {
|
|
362
|
+
if (!domain.info.version) {
|
|
363
|
+
throw new Error(`Cannot attach DataDomain without a version. Please set the version in the domain info.`)
|
|
364
|
+
}
|
|
365
|
+
this.cleanForEntityChange()
|
|
366
|
+
this.dependencies.set(domain.key, domain)
|
|
367
|
+
this.dependencyList = [{ key: domain.key, version: domain.info.version }]
|
|
368
|
+
this.notifyChange()
|
|
369
|
+
}
|
|
327
370
|
}
|
|
@@ -8,13 +8,7 @@ import {
|
|
|
8
8
|
DomainNamespaceKind,
|
|
9
9
|
DomainPropertyKind,
|
|
10
10
|
} from '../models/kinds.js'
|
|
11
|
-
import type {
|
|
12
|
-
AssociationAddOptions,
|
|
13
|
-
DomainGraphEdge,
|
|
14
|
-
DomainGraphNodeType,
|
|
15
|
-
ForeignDomainDependency,
|
|
16
|
-
SerializedGraph,
|
|
17
|
-
} from './types.js'
|
|
11
|
+
import type { AssociationAddOptions, DomainGraphEdge, DomainGraphNodeType, SerializedGraph } from './types.js'
|
|
18
12
|
import { type DomainNamespaceSchema, DomainNamespace, type NamespaceOrderedItem } from './DomainNamespace.js'
|
|
19
13
|
import { type DomainModelSchema, DomainModel } from './DomainModel.js'
|
|
20
14
|
import { type DomainEntitySchema, DomainEntity } from './DomainEntity.js'
|
|
@@ -23,13 +17,13 @@ import { DomainProperty, DomainPropertySchema } from './DomainProperty.js'
|
|
|
23
17
|
import { type IThing, Thing } from '../models/Thing.js'
|
|
24
18
|
import { removeGraphNode } from './GraphUtils.js'
|
|
25
19
|
import { serialize, deserialize, mergeGraph, removeForeignGraph } from './DomainSerialization.js'
|
|
20
|
+
import { DependentModel, type DependentModelSchema, type DomainDependency } from './DependentModel.js'
|
|
26
21
|
|
|
27
|
-
export interface DataDomainSchema {
|
|
22
|
+
export interface DataDomainSchema extends DependentModelSchema {
|
|
28
23
|
info: IThing
|
|
29
24
|
kind: typeof DataDomainKind
|
|
30
25
|
key: string
|
|
31
26
|
graph?: SerializedGraph
|
|
32
|
-
dependencyList?: ForeignDomainDependency[]
|
|
33
27
|
/**
|
|
34
28
|
* The ordered list of fields (namespace and models) in the schema.
|
|
35
29
|
* These only keep references to define the order of these properties
|
|
@@ -104,7 +98,7 @@ export interface DataDomainSchema {
|
|
|
104
98
|
* @todo: Implement a mechanism to move an entity to a new
|
|
105
99
|
* parent model.
|
|
106
100
|
*/
|
|
107
|
-
export class DataDomain extends
|
|
101
|
+
export class DataDomain extends DependentModel {
|
|
108
102
|
/**
|
|
109
103
|
* The kind of the domain element.
|
|
110
104
|
*/
|
|
@@ -119,18 +113,6 @@ export class DataDomain extends EventTarget {
|
|
|
119
113
|
*/
|
|
120
114
|
graph: Graph<unknown, DomainGraphNodeType, DomainGraphEdge>
|
|
121
115
|
|
|
122
|
-
/**
|
|
123
|
-
* A map of foreign data domains.
|
|
124
|
-
* Key: The unique identifier of the foreign domain.
|
|
125
|
-
* Value: The foreign DataDomain instance.
|
|
126
|
-
*/
|
|
127
|
-
dependencies: Map<string, DataDomain> = new Map<string, DataDomain>()
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* The list of foreign domain dependencies.
|
|
131
|
-
*/
|
|
132
|
-
dependencyList: ForeignDomainDependency[] = []
|
|
133
|
-
|
|
134
116
|
/**
|
|
135
117
|
* The description of the domain property.
|
|
136
118
|
*/
|
|
@@ -196,13 +178,24 @@ export class DataDomain extends EventTarget {
|
|
|
196
178
|
* @param state The previously serialized state of the graph.
|
|
197
179
|
* @param dependencies An array of foreign data domains to register with this domain.
|
|
198
180
|
*/
|
|
199
|
-
constructor(state?: Partial<DataDomainSchema>, dependencies
|
|
200
|
-
super()
|
|
181
|
+
constructor(state?: Partial<DataDomainSchema>, dependencies: DomainDependency[] = []) {
|
|
201
182
|
const init = DataDomain.createSchema(state)
|
|
183
|
+
const instances: DataDomain[] = []
|
|
184
|
+
for (const dep of dependencies) {
|
|
185
|
+
if (dep instanceof DataDomain) {
|
|
186
|
+
instances.push(dep)
|
|
187
|
+
} else if (typeof dep === 'object' && dep.kind === DataDomainKind && dep.key) {
|
|
188
|
+
const domain = new DataDomain(dep)
|
|
189
|
+
instances.push(domain)
|
|
190
|
+
} else {
|
|
191
|
+
throw new Error(`Invalid foreign domain dependency: ${dep}`)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
super(init.dependencyList, instances)
|
|
202
195
|
this.kind = init.kind
|
|
203
196
|
this.key = init.key
|
|
204
197
|
this.info = new Thing(init.info)
|
|
205
|
-
this.graph = deserialize(this, init.graph,
|
|
198
|
+
this.graph = deserialize(this, init.graph, instances)
|
|
206
199
|
if (Array.isArray(init.fields)) {
|
|
207
200
|
this.fields = [...init.fields]
|
|
208
201
|
} else {
|
|
@@ -438,10 +431,41 @@ export class DataDomain extends EventTarget {
|
|
|
438
431
|
}
|
|
439
432
|
}
|
|
440
433
|
|
|
434
|
+
/**
|
|
435
|
+
* Builds a reference key for a domain object.
|
|
436
|
+
*
|
|
437
|
+
* If the namespace is provided and it is different from the domain key,
|
|
438
|
+
* it will return the key in the format `namespace:key`. The foreign namespace
|
|
439
|
+
* must be registered in the domain's dependencies otherwise an error will be thrown.
|
|
440
|
+
*
|
|
441
|
+
* @param key The key of the namespace or model.
|
|
442
|
+
* @param namespace The namespace to search in. When different from the domain key, it looks for a foreign namespace.
|
|
443
|
+
* @returns The reference key in the format `namespace:key` or just `key` if no namespace is provided.
|
|
444
|
+
* @throws Error When the foreign domain is not found.
|
|
445
|
+
* @example
|
|
446
|
+
* ```typescript
|
|
447
|
+
* const refKey = dataDomain.buildReferenceKey('userModel', 'domainKey');
|
|
448
|
+
* ```
|
|
449
|
+
*/
|
|
450
|
+
buildReferenceKey(key: string, namespace?: string): string {
|
|
451
|
+
if (namespace && namespace !== this.key) {
|
|
452
|
+
if (typeof namespace !== 'string' || namespace.length === 0) {
|
|
453
|
+
throw new Error(`Invalid namespace key. Expected a string, got ${typeof namespace}`)
|
|
454
|
+
}
|
|
455
|
+
const foreignDomain = this.dependencies.get(namespace)
|
|
456
|
+
if (!foreignDomain) {
|
|
457
|
+
throw new Error(`Foreign domain ${namespace} not found`)
|
|
458
|
+
}
|
|
459
|
+
return `${namespace}:${key}`
|
|
460
|
+
}
|
|
461
|
+
return key
|
|
462
|
+
}
|
|
463
|
+
|
|
441
464
|
/**
|
|
442
465
|
* Finds a namespace by its key.
|
|
443
466
|
*
|
|
444
467
|
* @param key The key of the namespace to find.
|
|
468
|
+
* @param namespace The namespace to search in. When different from the domain key, it looks for a foreign namespace.
|
|
445
469
|
* @returns The namespace instance or undefined if not
|
|
446
470
|
* found.
|
|
447
471
|
* @example
|
|
@@ -452,8 +476,8 @@ export class DataDomain extends EventTarget {
|
|
|
452
476
|
* }
|
|
453
477
|
* ```
|
|
454
478
|
*/
|
|
455
|
-
findNamespace(key: string): DomainNamespace | undefined {
|
|
456
|
-
const result = this.graph.node(key) as DomainNamespace | undefined
|
|
479
|
+
findNamespace(key: string, namespace?: string): DomainNamespace | undefined {
|
|
480
|
+
const result = this.graph.node(this.buildReferenceKey(key, namespace)) as DomainNamespace | undefined
|
|
457
481
|
if (result && result.kind === DomainNamespaceKind) {
|
|
458
482
|
return result
|
|
459
483
|
}
|
|
@@ -696,6 +720,7 @@ export class DataDomain extends EventTarget {
|
|
|
696
720
|
* Finds a data model by its key.
|
|
697
721
|
*
|
|
698
722
|
* @param key The key of the data model to find.
|
|
723
|
+
* @param namespace The namespace to search in. When different from the domain key, it looks for a foreign entity.
|
|
699
724
|
* @returns The data model instance or undefined if not
|
|
700
725
|
* found.
|
|
701
726
|
* @example
|
|
@@ -706,8 +731,8 @@ export class DataDomain extends EventTarget {
|
|
|
706
731
|
* }
|
|
707
732
|
* ```
|
|
708
733
|
*/
|
|
709
|
-
findModel(key: string): DomainModel | undefined {
|
|
710
|
-
const value = this.graph.node(key) as DomainModel | undefined
|
|
734
|
+
findModel(key: string, namespace?: string): DomainModel | undefined {
|
|
735
|
+
const value = this.graph.node(this.buildReferenceKey(key, namespace)) as DomainModel | undefined
|
|
711
736
|
if (value && value.kind === DomainModelKind) {
|
|
712
737
|
return value
|
|
713
738
|
}
|
|
@@ -884,6 +909,7 @@ export class DataDomain extends EventTarget {
|
|
|
884
909
|
* Finds an entity by its key.
|
|
885
910
|
*
|
|
886
911
|
* @param key The key of the entity to find.
|
|
912
|
+
* @param namespace The namespace to search in. When different from the domain key, it looks for a foreign entity.
|
|
887
913
|
* @returns The entity instance or undefined if not found.
|
|
888
914
|
* @example
|
|
889
915
|
* ```typescript
|
|
@@ -893,8 +919,8 @@ export class DataDomain extends EventTarget {
|
|
|
893
919
|
* }
|
|
894
920
|
* ```
|
|
895
921
|
*/
|
|
896
|
-
findEntity(key: string): DomainEntity | undefined {
|
|
897
|
-
const node = this.graph.node(key) as DomainEntity | undefined
|
|
922
|
+
findEntity(key: string, namespace?: string): DomainEntity | undefined {
|
|
923
|
+
const node = this.graph.node(this.buildReferenceKey(key, namespace)) as DomainEntity | undefined
|
|
898
924
|
if (node && node.kind === DomainEntityKind) {
|
|
899
925
|
return node
|
|
900
926
|
}
|
|
@@ -1012,6 +1038,7 @@ export class DataDomain extends EventTarget {
|
|
|
1012
1038
|
* Finds an association by its key.
|
|
1013
1039
|
*
|
|
1014
1040
|
* @param key The key of the association to find.
|
|
1041
|
+
* @param namespace The namespace to search in. When different from the domain key, it looks for a foreign association
|
|
1015
1042
|
* @returns The association instance or undefined if not
|
|
1016
1043
|
* found.
|
|
1017
1044
|
* @example
|
|
@@ -1022,8 +1049,8 @@ export class DataDomain extends EventTarget {
|
|
|
1022
1049
|
* }
|
|
1023
1050
|
* ```
|
|
1024
1051
|
*/
|
|
1025
|
-
findAssociation(key: string): DomainAssociation | undefined {
|
|
1026
|
-
const node = this.graph.node(key) as DomainAssociation | undefined
|
|
1052
|
+
findAssociation(key: string, namespace?: string): DomainAssociation | undefined {
|
|
1053
|
+
const node = this.graph.node(this.buildReferenceKey(key, namespace)) as DomainAssociation | undefined
|
|
1027
1054
|
if (node && node.kind === DomainAssociationKind) {
|
|
1028
1055
|
return node
|
|
1029
1056
|
}
|
|
@@ -1097,6 +1124,7 @@ export class DataDomain extends EventTarget {
|
|
|
1097
1124
|
* Finds a property by its key.
|
|
1098
1125
|
*
|
|
1099
1126
|
* @param key The key of the property to find.
|
|
1127
|
+
* @param namespace The namespace to search in. When different from the domain key, it looks for a foreign property
|
|
1100
1128
|
* @returns The property instance or undefined if not
|
|
1101
1129
|
* found.
|
|
1102
1130
|
* @example
|
|
@@ -1107,8 +1135,8 @@ export class DataDomain extends EventTarget {
|
|
|
1107
1135
|
* }
|
|
1108
1136
|
* ```
|
|
1109
1137
|
*/
|
|
1110
|
-
findProperty(key: string): DomainProperty | undefined {
|
|
1111
|
-
const node = this.graph.node(key) as DomainProperty | undefined
|
|
1138
|
+
findProperty(key: string, namespace?: string): DomainProperty | undefined {
|
|
1139
|
+
const node = this.graph.node(this.buildReferenceKey(key, namespace)) as DomainProperty | undefined
|
|
1112
1140
|
if (node && node.kind === DomainPropertyKind) {
|
|
1113
1141
|
return node
|
|
1114
1142
|
}
|
|
@@ -1182,6 +1210,8 @@ export class DataDomain extends EventTarget {
|
|
|
1182
1210
|
* console.log(foreignUser.key);
|
|
1183
1211
|
* }
|
|
1184
1212
|
* ```
|
|
1213
|
+
* @deprecated Use `findEntity` with the `namespace` parameter instead.
|
|
1214
|
+
* This method is kept for backward compatibility but will be removed in the future.
|
|
1185
1215
|
*/
|
|
1186
1216
|
findForeignEntity(entityKey: string, domainKey: string): DomainEntity | undefined {
|
|
1187
1217
|
const foreignDomain = this.dependencies.get(domainKey)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DataDomain, DataDomainSchema } from './DataDomain.js'
|
|
2
|
+
import type { ForeignDomainDependency } from './types.js'
|
|
3
|
+
|
|
4
|
+
export type DomainDependency = DataDomain | DataDomainSchema
|
|
5
|
+
|
|
6
|
+
export interface DependentModelSchema {
|
|
7
|
+
/**
|
|
8
|
+
* A list of foreign domain dependencies.
|
|
9
|
+
*/
|
|
10
|
+
dependencyList?: ForeignDomainDependency[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A base model that has dependencies on foreign data domains.
|
|
15
|
+
*/
|
|
16
|
+
export class DependentModel extends EventTarget {
|
|
17
|
+
/**
|
|
18
|
+
* A map of foreign data domains.
|
|
19
|
+
* Key: The unique identifier of the foreign domain.
|
|
20
|
+
* Value: The foreign DataDomain instance.
|
|
21
|
+
*/
|
|
22
|
+
dependencies: Map<string, DataDomain> = new Map<string, DataDomain>()
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The list of foreign domain dependencies.
|
|
26
|
+
*/
|
|
27
|
+
dependencyList: ForeignDomainDependency[] = []
|
|
28
|
+
|
|
29
|
+
constructor(items: ForeignDomainDependency[] = [], instances: DataDomain[] = []) {
|
|
30
|
+
super()
|
|
31
|
+
this.dependencyList = [...items]
|
|
32
|
+
for (const dep of instances) {
|
|
33
|
+
this.dependencies.set(dep.key, dep)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/modeling/types.ts
CHANGED
|
@@ -337,6 +337,8 @@ export interface SessionConfiguration {
|
|
|
337
337
|
/**
|
|
338
338
|
* The properties from the `User` entity to be encoded into the session payload (JWT/cookie).
|
|
339
339
|
* These properties become available in the `request.auth` object at runtime.
|
|
340
|
+
*
|
|
341
|
+
* In practice, these are the ids of the properties in the `User` entity.
|
|
340
342
|
*/
|
|
341
343
|
properties: string[]
|
|
342
344
|
/**
|