@api-client/core 0.14.2 → 0.14.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/build/src/index.d.ts +1 -0
- package/build/src/index.d.ts.map +1 -1
- package/build/src/index.js +1 -0
- package/build/src/index.js.map +1 -1
- package/build/src/modeling/ApiFile.d.ts +23 -0
- package/build/src/modeling/ApiFile.d.ts.map +1 -0
- package/build/src/modeling/ApiFile.js +44 -0
- package/build/src/modeling/ApiFile.js.map +1 -0
- package/build/src/modeling/ApiModel.d.ts +159 -0
- package/build/src/modeling/ApiModel.d.ts.map +1 -0
- package/build/src/modeling/ApiModel.js +237 -0
- package/build/src/modeling/ApiModel.js.map +1 -0
- package/build/src/modeling/DataDomain.d.ts +1 -1
- package/build/src/modeling/DataDomain.d.ts.map +1 -1
- package/build/src/modeling/DataDomain.js +1 -3
- package/build/src/modeling/DataDomain.js.map +1 -1
- package/build/src/modeling/DomainEntity.js +1 -1
- package/build/src/modeling/DomainEntity.js.map +1 -1
- package/build/src/modeling/DomainFile.d.ts +1 -2
- package/build/src/modeling/DomainFile.d.ts.map +1 -1
- package/build/src/modeling/DomainFile.js +3 -41
- package/build/src/modeling/DomainFile.js.map +1 -1
- package/build/src/modeling/Semantics.d.ts +55 -8
- package/build/src/modeling/Semantics.d.ts.map +1 -1
- package/build/src/modeling/Semantics.js +62 -8
- package/build/src/modeling/Semantics.js.map +1 -1
- package/build/src/modeling/amf/ShapeGenerator.d.ts.map +1 -1
- package/build/src/modeling/amf/ShapeGenerator.js.map +1 -1
- package/build/src/modeling/types.d.ts +491 -0
- package/build/src/modeling/types.d.ts.map +1 -1
- package/build/src/modeling/types.js.map +1 -1
- package/build/src/models/kinds.d.ts +2 -0
- package/build/src/models/kinds.d.ts.map +1 -1
- package/build/src/models/kinds.js +2 -0
- package/build/src/models/kinds.js.map +1 -1
- package/build/src/models/store/File.d.ts +19 -2
- package/build/src/models/store/File.d.ts.map +1 -1
- package/build/src/models/store/File.js +100 -13
- package/build/src/models/store/File.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/data/models/example-generator-api.json +19 -19
- package/package.json +2 -3
- package/src/modeling/ApiFile.ts +53 -0
- package/src/modeling/ApiModel.ts +327 -0
- package/src/modeling/DataDomain.ts +1 -1
- package/src/modeling/DomainEntity.ts +1 -1
- package/src/modeling/DomainFile.ts +3 -40
- package/src/modeling/Semantics.ts +63 -8
- package/src/modeling/amf/ShapeGenerator.ts +1 -1
- package/src/modeling/types.ts +545 -0
- package/src/models/kinds.ts +2 -0
- package/src/models/store/File.ts +100 -13
- package/tests/unit/modeling/api_model.spec.ts +291 -0
- package/tests/unit/modeling/domain_entity.spec.ts +15 -15
- package/tests/unit/modeling/domain_file.spec.ts +1 -11
- package/tests/unit/modeling/domain_model_entities.spec.ts +2 -2
- package/tests/unit/modeling/semantics.spec.ts +8 -11
- package/tests/unit/models/File/constructor.spec.ts +3 -2
- package/tests/unit/models/File/shortcutTo.spec.ts +1 -1
|
@@ -42071,13 +42071,13 @@
|
|
|
42071
42071
|
"@id": "#197"
|
|
42072
42072
|
},
|
|
42073
42073
|
{
|
|
42074
|
-
"@id": "#
|
|
42074
|
+
"@id": "#206"
|
|
42075
42075
|
},
|
|
42076
42076
|
{
|
|
42077
|
-
"@id": "#
|
|
42077
|
+
"@id": "#200"
|
|
42078
42078
|
},
|
|
42079
42079
|
{
|
|
42080
|
-
"@id": "#
|
|
42080
|
+
"@id": "#203"
|
|
42081
42081
|
},
|
|
42082
42082
|
{
|
|
42083
42083
|
"@id": "#209"
|
|
@@ -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": "#216"
|
|
42820
|
-
},
|
|
42821
|
-
{
|
|
42822
|
-
"@id": "#219"
|
|
42823
42823
|
}
|
|
42824
42824
|
],
|
|
42825
42825
|
"doc:root": false,
|
|
@@ -43499,7 +43499,7 @@
|
|
|
43499
43499
|
"doc:ExternalDomainElement",
|
|
43500
43500
|
"doc:DomainElement"
|
|
43501
43501
|
],
|
|
43502
|
-
"doc:raw": "
|
|
43502
|
+
"doc:raw": "code: 'J'\ndescription: 'Information and communication'\n",
|
|
43503
43503
|
"core:mediaType": "application/yaml",
|
|
43504
43504
|
"sourcemaps:sources": [
|
|
43505
43505
|
{
|
|
@@ -43520,7 +43520,7 @@
|
|
|
43520
43520
|
"doc:ExternalDomainElement",
|
|
43521
43521
|
"doc:DomainElement"
|
|
43522
43522
|
],
|
|
43523
|
-
"doc:raw": "code: '
|
|
43523
|
+
"doc:raw": "code: '7487'\ndescription: 'Financial and insurance activities'\ntype: \"PRIMARY\"\nclassificationCode: 'BE_NACEBEL2008'\nactivityGroupCode: 'ABCDE'\n",
|
|
43524
43524
|
"core:mediaType": "application/yaml",
|
|
43525
43525
|
"sourcemaps:sources": [
|
|
43526
43526
|
{
|
|
@@ -43541,7 +43541,7 @@
|
|
|
43541
43541
|
"doc:ExternalDomainElement",
|
|
43542
43542
|
"doc:DomainElement"
|
|
43543
43543
|
],
|
|
43544
|
-
"doc:raw": "
|
|
43544
|
+
"doc:raw": "class: '3'\ndescription: '150 - 300'\nnumberOfFte: 5500\nnumberOfEmployees: 5232\n",
|
|
43545
43545
|
"core:mediaType": "application/yaml",
|
|
43546
43546
|
"sourcemaps:sources": [
|
|
43547
43547
|
{
|
|
@@ -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": "type: 'GENERAL'\
|
|
44256
|
+
"doc:raw": "-\n type: 'GENERAL'\n value: 'info@company.be'\n-\n type: 'IT_DEPT'\n value: 'it-service@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": "
|
|
44277
|
+
"doc:raw": "type: \"GENERAL\"\nvalue: \"www.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
|
{
|
|
@@ -44771,17 +44771,17 @@
|
|
|
44771
44771
|
{
|
|
44772
44772
|
"@id": "#202/source-map/lexical/element_0",
|
|
44773
44773
|
"sourcemaps:element": "amf://id#202",
|
|
44774
|
-
"sourcemaps:value": "[(1,0)-(
|
|
44774
|
+
"sourcemaps:value": "[(1,0)-(3,0)]"
|
|
44775
44775
|
},
|
|
44776
44776
|
{
|
|
44777
44777
|
"@id": "#205/source-map/lexical/element_0",
|
|
44778
44778
|
"sourcemaps:element": "amf://id#205",
|
|
44779
|
-
"sourcemaps:value": "[(1,0)-(
|
|
44779
|
+
"sourcemaps:value": "[(1,0)-(6,0)]"
|
|
44780
44780
|
},
|
|
44781
44781
|
{
|
|
44782
44782
|
"@id": "#208/source-map/lexical/element_0",
|
|
44783
44783
|
"sourcemaps:element": "amf://id#208",
|
|
44784
|
-
"sourcemaps:value": "[(1,0)-(
|
|
44784
|
+
"sourcemaps:value": "[(1,0)-(5,0)]"
|
|
44785
44785
|
},
|
|
44786
44786
|
{
|
|
44787
44787
|
"@id": "#223/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)-(7,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)-(3,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
|
@@ -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.14.
|
|
4
|
+
"version": "0.14.3",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./browser.js": {
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
"oauth2-mock-server": "^8.0.0",
|
|
136
136
|
"playwright": "^1.50.1",
|
|
137
137
|
"prettier": "^3.5.1",
|
|
138
|
-
"sinon": "^
|
|
138
|
+
"sinon": "^21.0.0",
|
|
139
139
|
"ts-lit-plugin": "^2.0.2",
|
|
140
140
|
"ts-node-maintained": "^10.9.5",
|
|
141
141
|
"typescript": "^5.5.2",
|
|
@@ -157,7 +157,6 @@
|
|
|
157
157
|
"test:coverage": "wireit",
|
|
158
158
|
"test:node": "node --import ts-node-maintained/register/esm --enable-source-maps bin/test.ts",
|
|
159
159
|
"test:node:coverage": "c8 --reporter lcov --reporter text node --import ts-node-maintained/register/esm --enable-source-maps bin/test.ts",
|
|
160
|
-
"test:node:watch": "node --import ts-node-maintained/register/esm --enable-source-maps bin/test.ts --watch",
|
|
161
160
|
"build:api-models": "node data/model.js",
|
|
162
161
|
"copy:assets": "cp -f ./oauth-popup.html ./build/oauth-popup.html",
|
|
163
162
|
"start": "echo \"Use the npm run dev instead\"",
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { File, type IFile } from '../models/store/File.js'
|
|
2
|
+
import { ApiFileKind } from '../models/kinds.js'
|
|
3
|
+
import { ApiModel, ApiModelSchema } from './ApiModel.js'
|
|
4
|
+
|
|
5
|
+
export interface IApiFile extends IFile {
|
|
6
|
+
kind: typeof ApiFileKind
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Used by the store. A file definition for the ApiModel.
|
|
11
|
+
*/
|
|
12
|
+
export class ApiFile extends File {
|
|
13
|
+
override kind = ApiFileKind
|
|
14
|
+
|
|
15
|
+
static override fromName(name: string): ApiFile {
|
|
16
|
+
return super.fromName(name, ApiFileKind) as ApiFile
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Creates the file definition for a DomainNamespace contents.
|
|
21
|
+
*
|
|
22
|
+
* @param input The data namespace instance or schema.
|
|
23
|
+
*/
|
|
24
|
+
static fromApiModel(input: ApiModel | ApiModelSchema): ApiFile {
|
|
25
|
+
let final: ApiModelSchema
|
|
26
|
+
if (typeof (input as ApiModel).toJSON === 'function') {
|
|
27
|
+
final = (input as ApiModel).toJSON()
|
|
28
|
+
} else {
|
|
29
|
+
final = input as ApiModelSchema
|
|
30
|
+
}
|
|
31
|
+
return new ApiFile({ key: final.key, info: final.info })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
constructor(state: Partial<IApiFile> = {}) {
|
|
35
|
+
super({ ...state, kind: ApiFileKind })
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static isApiFile(input: unknown): boolean {
|
|
39
|
+
const typed = input as IApiFile
|
|
40
|
+
if (!input || typed.kind !== ApiFileKind) {
|
|
41
|
+
return false
|
|
42
|
+
}
|
|
43
|
+
return true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
override toJSON(): IApiFile {
|
|
47
|
+
const result: IApiFile = {
|
|
48
|
+
...super.toJSON(),
|
|
49
|
+
kind: ApiFileKind,
|
|
50
|
+
}
|
|
51
|
+
return result
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { nanoid } from '../nanoid.js'
|
|
2
|
+
import { ApiModelKind } from '../models/kinds.js'
|
|
3
|
+
import { type IThing, Thing } from '../models/Thing.js'
|
|
4
|
+
import type {
|
|
5
|
+
AccessRule,
|
|
6
|
+
AuthenticationConfiguration,
|
|
7
|
+
AuthorizationConfiguration,
|
|
8
|
+
ExposedEntity,
|
|
9
|
+
ForeignDomainDependency,
|
|
10
|
+
RateLimitingConfiguration,
|
|
11
|
+
SessionConfiguration,
|
|
12
|
+
} from './types.js'
|
|
13
|
+
import { DataDomain, type DataDomainSchema } from './DataDomain.js'
|
|
14
|
+
|
|
15
|
+
export interface ApiModelSchema {
|
|
16
|
+
/**
|
|
17
|
+
* The data domain kind recognizable by the ecosystem.
|
|
18
|
+
*/
|
|
19
|
+
kind: typeof ApiModelKind
|
|
20
|
+
/**
|
|
21
|
+
* The unique key of the data domain schema.
|
|
22
|
+
* This is a stable identifier that does not change across versions.
|
|
23
|
+
*/
|
|
24
|
+
key: string
|
|
25
|
+
/**
|
|
26
|
+
* Contains the name, display name, description, and the version of the data domain schema.
|
|
27
|
+
*/
|
|
28
|
+
info: IThing
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The designated Data Entity that represents a "User".
|
|
32
|
+
* This entity must be marked with the "User" semantic in the Data Modeler.
|
|
33
|
+
*
|
|
34
|
+
* This property is required to publish the API.
|
|
35
|
+
*/
|
|
36
|
+
userKey?: string
|
|
37
|
+
|
|
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
|
+
/**
|
|
45
|
+
* Configuration for how users prove their identity.
|
|
46
|
+
* The API model is invalid if this is not set.
|
|
47
|
+
*/
|
|
48
|
+
authentication?: AuthenticationConfiguration
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Configuration for what authenticated users are allowed to do.
|
|
52
|
+
* The API model is invalid if this is not set.
|
|
53
|
+
*/
|
|
54
|
+
authorization?: AuthorizationConfiguration
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Configuration for the transport and payload of the user session.
|
|
58
|
+
* The API model is invalid if this is not set.
|
|
59
|
+
*/
|
|
60
|
+
session?: SessionConfiguration
|
|
61
|
+
/**
|
|
62
|
+
* The specific subset of Data Entities to be exposed by this API.
|
|
63
|
+
* These are the entities that are included in the data domain schema.
|
|
64
|
+
*/
|
|
65
|
+
exposes: ExposedEntity[]
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Optional array of access rules that define the access control policies
|
|
69
|
+
* for the API. These rules are used to enforce security and permissions
|
|
70
|
+
* on the exposed entities.
|
|
71
|
+
*
|
|
72
|
+
* These rules apply to all exposed entities and actions. An API action
|
|
73
|
+
* can declare its own access rules, which will override these.
|
|
74
|
+
*/
|
|
75
|
+
accessRule?: AccessRule[]
|
|
76
|
+
/**
|
|
77
|
+
* Optional configuration for API-wide rate limiting and throttling.
|
|
78
|
+
* Defines rules to protect the API from overuse.
|
|
79
|
+
*/
|
|
80
|
+
rateLimiting?: RateLimitingConfiguration
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export class ApiModel extends EventTarget {
|
|
84
|
+
/**
|
|
85
|
+
* The data domain kind recognizable by the ecosystem.
|
|
86
|
+
*/
|
|
87
|
+
kind: typeof ApiModelKind
|
|
88
|
+
/**
|
|
89
|
+
* The unique key of the data domain schema.
|
|
90
|
+
* This is a stable identifier that does not change across versions.
|
|
91
|
+
*/
|
|
92
|
+
key: string
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The description of the domain property.
|
|
96
|
+
*/
|
|
97
|
+
info: Thing
|
|
98
|
+
/**
|
|
99
|
+
* The designated Data Entity that represents a "User".
|
|
100
|
+
* This entity must be marked with the "User" semantic in the Data Modeler.
|
|
101
|
+
*
|
|
102
|
+
* This property is required to publish the API.
|
|
103
|
+
*/
|
|
104
|
+
userKey?: string
|
|
105
|
+
|
|
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
|
+
/**
|
|
113
|
+
* Configuration for how users prove their identity.
|
|
114
|
+
* The API model is invalid if this is not set.
|
|
115
|
+
*/
|
|
116
|
+
authentication?: AuthenticationConfiguration
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Configuration for what authenticated users are allowed to do.
|
|
120
|
+
* The API model is invalid if this is not set.
|
|
121
|
+
*/
|
|
122
|
+
authorization?: AuthorizationConfiguration
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Configuration for the transport and payload of the user session.
|
|
126
|
+
* The API model is invalid if this is not set.
|
|
127
|
+
*/
|
|
128
|
+
session?: SessionConfiguration
|
|
129
|
+
/**
|
|
130
|
+
* The specific subset of Data Entities to be exposed by this API.
|
|
131
|
+
* These are the entities that are included in the data domain schema.
|
|
132
|
+
*/
|
|
133
|
+
exposes: ExposedEntity[]
|
|
134
|
+
/**
|
|
135
|
+
* Optional array of access rules that define the access control policies
|
|
136
|
+
* for the API. These rules are used to enforce security and permissions
|
|
137
|
+
* on the exposed entities.
|
|
138
|
+
*
|
|
139
|
+
* These rules apply to all exposed entities and actions. An API action
|
|
140
|
+
* can declare its own access rules, which will override these.
|
|
141
|
+
*/
|
|
142
|
+
accessRule?: AccessRule[]
|
|
143
|
+
/**
|
|
144
|
+
* Optional configuration for API-wide rate limiting and throttling.
|
|
145
|
+
* Defines rules to protect the API from overuse.
|
|
146
|
+
*/
|
|
147
|
+
rateLimiting?: RateLimitingConfiguration
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* When the initializing flag is set to true,
|
|
151
|
+
* the domain is not notified of changes.
|
|
152
|
+
*/
|
|
153
|
+
#initializing = true
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* When the notifying flag is set to true,
|
|
157
|
+
* the domain is pending a notification.
|
|
158
|
+
* No other notifications will be sent until
|
|
159
|
+
* the current notification is sent.
|
|
160
|
+
*/
|
|
161
|
+
#notifying = false
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* A reference to the published data domain.
|
|
165
|
+
*/
|
|
166
|
+
dataDomain?: DataDomain
|
|
167
|
+
|
|
168
|
+
static createSchema(input: Partial<ApiModelSchema> = {}): ApiModelSchema {
|
|
169
|
+
const { key = nanoid(), exposes = [] } = input
|
|
170
|
+
const info = Thing.fromJSON(input.info, { name: 'Unnamed API' }).toJSON()
|
|
171
|
+
const result: ApiModelSchema = {
|
|
172
|
+
kind: ApiModelKind,
|
|
173
|
+
key,
|
|
174
|
+
info,
|
|
175
|
+
exposes,
|
|
176
|
+
}
|
|
177
|
+
if (input.userKey) {
|
|
178
|
+
result.userKey = input.userKey
|
|
179
|
+
}
|
|
180
|
+
if (input.domain) {
|
|
181
|
+
result.domain = input.domain
|
|
182
|
+
}
|
|
183
|
+
if (input.authentication) {
|
|
184
|
+
result.authentication = input.authentication
|
|
185
|
+
}
|
|
186
|
+
if (input.authorization) {
|
|
187
|
+
result.authorization = input.authorization
|
|
188
|
+
}
|
|
189
|
+
if (input.session) {
|
|
190
|
+
result.session = input.session
|
|
191
|
+
}
|
|
192
|
+
if (input.accessRule) {
|
|
193
|
+
result.accessRule = input.accessRule
|
|
194
|
+
}
|
|
195
|
+
if (input.rateLimiting) {
|
|
196
|
+
result.rateLimiting = input.rateLimiting
|
|
197
|
+
}
|
|
198
|
+
return result
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
constructor(state?: Partial<ApiModelSchema>, domain?: DataDomainSchema) {
|
|
202
|
+
super()
|
|
203
|
+
const init = ApiModel.createSchema(state)
|
|
204
|
+
this.kind = init.kind
|
|
205
|
+
this.key = init.key
|
|
206
|
+
this.info = new Thing(init.info)
|
|
207
|
+
this.userKey = init.userKey
|
|
208
|
+
if (init.domain) {
|
|
209
|
+
this.domain = structuredClone(init.domain)
|
|
210
|
+
}
|
|
211
|
+
if (init.authentication) {
|
|
212
|
+
this.authentication = structuredClone(init.authentication)
|
|
213
|
+
}
|
|
214
|
+
if (init.authorization) {
|
|
215
|
+
this.authorization = structuredClone(init.authorization)
|
|
216
|
+
}
|
|
217
|
+
if (init.session) {
|
|
218
|
+
this.session = structuredClone(init.session)
|
|
219
|
+
}
|
|
220
|
+
if (Array.isArray(init.exposes)) {
|
|
221
|
+
this.exposes = structuredClone(init.exposes)
|
|
222
|
+
} else {
|
|
223
|
+
this.exposes = []
|
|
224
|
+
}
|
|
225
|
+
if (init.accessRule) {
|
|
226
|
+
this.accessRule = structuredClone(init.accessRule)
|
|
227
|
+
}
|
|
228
|
+
if (init.rateLimiting) {
|
|
229
|
+
this.rateLimiting = structuredClone(init.rateLimiting)
|
|
230
|
+
}
|
|
231
|
+
if (domain) {
|
|
232
|
+
this.dataDomain = new DataDomain(domain)
|
|
233
|
+
}
|
|
234
|
+
this.#initializing = false
|
|
235
|
+
this.info.addEventListener('change', () => {
|
|
236
|
+
this.notifyChange()
|
|
237
|
+
})
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
toJSON(): ApiModelSchema {
|
|
241
|
+
const result: ApiModelSchema = {
|
|
242
|
+
kind: this.kind,
|
|
243
|
+
key: this.key,
|
|
244
|
+
info: this.info.toJSON(),
|
|
245
|
+
exposes: structuredClone(this.exposes),
|
|
246
|
+
}
|
|
247
|
+
if (this.userKey) {
|
|
248
|
+
result.userKey = this.userKey
|
|
249
|
+
}
|
|
250
|
+
if (this.domain) {
|
|
251
|
+
result.domain = structuredClone(this.domain)
|
|
252
|
+
}
|
|
253
|
+
if (this.authentication) {
|
|
254
|
+
result.authentication = structuredClone(this.authentication)
|
|
255
|
+
}
|
|
256
|
+
if (this.authorization) {
|
|
257
|
+
result.authorization = structuredClone(this.authorization)
|
|
258
|
+
}
|
|
259
|
+
if (this.session) {
|
|
260
|
+
result.session = structuredClone(this.session)
|
|
261
|
+
}
|
|
262
|
+
if (this.accessRule) {
|
|
263
|
+
result.accessRule = structuredClone(this.accessRule)
|
|
264
|
+
}
|
|
265
|
+
if (this.rateLimiting) {
|
|
266
|
+
result.rateLimiting = structuredClone(this.rateLimiting)
|
|
267
|
+
}
|
|
268
|
+
return result
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* This function is used internally by all domain elements to notify that something has changed.
|
|
273
|
+
* Since we want to notify listeners after the operation commits, we use microtask
|
|
274
|
+
* to ensure that the event is dispatched after the current operation.
|
|
275
|
+
*/
|
|
276
|
+
notifyChange() {
|
|
277
|
+
if (this.#notifying || this.#initializing) {
|
|
278
|
+
return
|
|
279
|
+
}
|
|
280
|
+
this.#notifying = true
|
|
281
|
+
queueMicrotask(() => {
|
|
282
|
+
this.#notifying = false
|
|
283
|
+
const event = new Event('change')
|
|
284
|
+
this.dispatchEvent(event)
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Exposes a new entity in the API model.
|
|
290
|
+
* If the entity already exists, it returns the existing one.
|
|
291
|
+
* @param entityKey The key of the entity to expose.
|
|
292
|
+
* @returns The exposed entity.
|
|
293
|
+
*/
|
|
294
|
+
exposeEntity(entityKey: string): ExposedEntity {
|
|
295
|
+
const existing = this.exposes.find((e) => e.key === entityKey)
|
|
296
|
+
if (existing) {
|
|
297
|
+
return existing
|
|
298
|
+
}
|
|
299
|
+
const newEntity: ExposedEntity = {
|
|
300
|
+
key: entityKey,
|
|
301
|
+
actions: [],
|
|
302
|
+
}
|
|
303
|
+
this.exposes.push(newEntity)
|
|
304
|
+
this.notifyChange()
|
|
305
|
+
return newEntity
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Removes an entity from the API model.
|
|
310
|
+
* @param entityKey The key of the entity to remove.
|
|
311
|
+
*/
|
|
312
|
+
removeEntity(entityKey: string): void {
|
|
313
|
+
const index = this.exposes.findIndex((e) => e.key === entityKey)
|
|
314
|
+
if (index !== -1) {
|
|
315
|
+
this.exposes.splice(index, 1)
|
|
316
|
+
this.notifyChange()
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Returns the exposed entity by its key.
|
|
321
|
+
* @param entityKey The key of the entity to find.
|
|
322
|
+
* @returns The exposed entity or undefined if not found.
|
|
323
|
+
*/
|
|
324
|
+
getExposedEntity(entityKey: string): ExposedEntity | undefined {
|
|
325
|
+
return this.exposes.find((e) => e.key === entityKey)
|
|
326
|
+
}
|
|
327
|
+
}
|
|
@@ -165,7 +165,7 @@ export class DomainEntity extends DomainElement {
|
|
|
165
165
|
*/
|
|
166
166
|
static createSchema(input: Partial<DomainEntitySchema> = {}): DomainEntitySchema {
|
|
167
167
|
const { key = nanoid(), tags, semantics, fields, deprecated } = input
|
|
168
|
-
const info = Thing.fromJSON(input.info, { name: '
|
|
168
|
+
const info = Thing.fromJSON(input.info, { name: 'new_entity' }).toJSON()
|
|
169
169
|
const result: DomainEntitySchema = {
|
|
170
170
|
kind: DomainEntityKind,
|
|
171
171
|
key,
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { nanoid } from '../nanoid.js'
|
|
2
1
|
import { File, type IFile } from '../models/store/File.js'
|
|
3
|
-
import { Thing } from '../models/Thing.js'
|
|
4
2
|
import type { DataDomain, DataDomainSchema } from './DataDomain.js'
|
|
5
3
|
import { DomainFileKind } from '../models/kinds.js'
|
|
6
4
|
|
|
@@ -30,46 +28,11 @@ export class DomainFile extends File {
|
|
|
30
28
|
} else {
|
|
31
29
|
final = input as DataDomainSchema
|
|
32
30
|
}
|
|
33
|
-
|
|
34
|
-
kind: DomainFileKind,
|
|
35
|
-
key: final.key,
|
|
36
|
-
info: { ...final.info },
|
|
37
|
-
lastModified: { user: '', time: 0, byMe: false },
|
|
38
|
-
parents: [],
|
|
39
|
-
permissionIds: [],
|
|
40
|
-
permissions: [],
|
|
41
|
-
}
|
|
42
|
-
return new DomainFile(init)
|
|
31
|
+
return new DomainFile({ key: final.key, info: final.info })
|
|
43
32
|
}
|
|
44
33
|
|
|
45
|
-
constructor(
|
|
46
|
-
super()
|
|
47
|
-
let init: IDomainFile
|
|
48
|
-
if (typeof input === 'string') {
|
|
49
|
-
init = JSON.parse(input)
|
|
50
|
-
} else if (typeof input === 'object') {
|
|
51
|
-
init = input
|
|
52
|
-
} else {
|
|
53
|
-
init = {
|
|
54
|
-
kind: DomainFileKind,
|
|
55
|
-
key: nanoid(),
|
|
56
|
-
info: Thing.fromName('').toJSON(),
|
|
57
|
-
parents: [],
|
|
58
|
-
permissionIds: [],
|
|
59
|
-
permissions: [],
|
|
60
|
-
lastModified: { user: '', time: 0, byMe: false },
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
this.new(init)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
override new(init: IDomainFile): this {
|
|
67
|
-
if (!DomainFile.isDomainFile(init)) {
|
|
68
|
-
throw new Error(`Not a data file.`)
|
|
69
|
-
}
|
|
70
|
-
super.new(init)
|
|
71
|
-
this.kind = DomainFileKind
|
|
72
|
-
return this
|
|
34
|
+
constructor(state: Partial<IDomainFile> = {}) {
|
|
35
|
+
super({ ...state, kind: DomainFileKind })
|
|
73
36
|
}
|
|
74
37
|
|
|
75
38
|
static isDomainFile(input: unknown): boolean {
|