@api-client/core 0.14.10 → 0.15.0
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/RELEASE.md +163 -0
- package/RELEASE_SETUP.md +235 -0
- package/build/src/events/authorization/AuthorizationEvents.d.ts +1 -1
- package/build/src/events/authorization/AuthorizationEvents.d.ts.map +1 -1
- package/build/src/events/authorization/AuthorizationEvents.js +1 -1
- package/build/src/events/authorization/AuthorizationEvents.js.map +1 -1
- package/build/src/events/cookies/CookieEvents.d.ts +1 -1
- package/build/src/events/cookies/CookieEvents.d.ts.map +1 -1
- package/build/src/events/cookies/CookieEvents.js +1 -1
- package/build/src/events/cookies/CookieEvents.js.map +1 -1
- package/build/src/modeling/DomainImpactAnalysis.d.ts +22 -119
- package/build/src/modeling/DomainImpactAnalysis.d.ts.map +1 -1
- package/build/src/modeling/DomainImpactAnalysis.js +49 -155
- package/build/src/modeling/DomainImpactAnalysis.js.map +1 -1
- package/build/src/modeling/DomainValidation.d.ts +8 -0
- package/build/src/modeling/DomainValidation.d.ts.map +1 -0
- package/build/src/modeling/DomainValidation.js +99 -0
- package/build/src/modeling/DomainValidation.js.map +1 -0
- package/build/src/modeling/types.d.ts +70 -0
- package/build/src/modeling/types.d.ts.map +1 -1
- package/build/src/modeling/types.js.map +1 -1
- package/build/src/modeling/validation/rules.d.ts +2 -3
- package/build/src/modeling/validation/rules.d.ts.map +1 -1
- package/build/src/modeling/validation/rules.js.map +1 -1
- package/build/src/modeling/validation/semantic_validation.d.ts +31 -0
- package/build/src/modeling/validation/semantic_validation.d.ts.map +1 -0
- package/build/src/modeling/validation/semantic_validation.js +126 -0
- package/build/src/modeling/validation/semantic_validation.js.map +1 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/data/models/example-generator-api.json +6 -6
- package/noop.ts +3 -0
- package/package.json +9 -4
- package/src/events/authorization/AuthorizationEvents.ts +1 -1
- package/src/events/cookies/CookieEvents.ts +1 -1
- package/src/modeling/DomainImpactAnalysis.ts +54 -239
- package/src/modeling/DomainValidation.ts +105 -0
- package/src/modeling/types.ts +86 -0
- package/src/modeling/validation/rules.ts +2 -4
- package/src/modeling/validation/semantic_validation.ts +145 -0
- package/tests/unit/events/EventsTestHelpers.ts +16 -0
- package/tests/unit/events/amf.spec.ts +151 -0
- package/tests/unit/events/authorization.spec.ts +150 -0
- package/tests/unit/events/cookie.spec.ts +274 -0
- package/tests/unit/events/encryption.spec.ts +108 -0
- package/tests/unit/events/events_polyfills.ts +77 -0
- package/tests/unit/events/process.spec.ts +120 -0
- package/tests/unit/events/reporting.spec.ts +82 -0
- package/tests/unit/events/telemetry.spec.ts +224 -0
- package/tests/unit/events/transport.spec.ts +139 -0
- package/tests/unit/modeling/domain_impact_analysis.spec.ts +0 -110
- package/tests/unit/modeling/domain_validation.spec.ts +94 -0
- package/tests/unit/modeling/validation/semantic_validation.spec.ts +91 -0
- package/tests/unit/models/environment.spec.ts +574 -0
- package/tests/unit/models/error_response.spec.ts +183 -0
- package/tests/unit/models/headers_array.spec.ts +86 -0
- package/tests/unit/models/http-actions/assertion/equal_assertion.spec.ts +103 -0
- package/tests/unit/models/http-actions/assertion/greater_than_assertion.spec.ts +91 -0
- package/tests/unit/models/http-actions/assertion/includes_assertion.spec.ts +71 -0
- package/tests/unit/models/http-actions/assertion/less_than_assertion.spec.ts +91 -0
- package/tests/unit/models/http-actions/assertion/matches_assertion.spec.ts +71 -0
- package/tests/unit/models/http-actions/assertion/matches_schema_assertion.spec.ts +117 -0
- package/tests/unit/models/http-actions/assertion/not_equal_assertion.spec.ts +103 -0
- package/tests/unit/models/http-actions/assertion/not_includes_assertion.spec.ts +71 -0
- package/tests/unit/models/http-actions/assertion/not_ok_assertion.spec.ts +47 -0
- package/tests/unit/models/http-actions/assertion/not_to_be_assertion.spec.ts +72 -0
- package/tests/unit/models/http-actions/assertion/ok_assertion.spec.ts +44 -0
- package/tests/unit/models/http-actions/assertion/to_be_assertion.spec.ts +71 -0
- package/tests/unit/models/http-actions/transformation/as_lower_case_step.spec.ts +47 -0
- package/tests/unit/models/http-actions/transformation/as_number_step.spec.ts +47 -0
- package/tests/unit/models/http-actions/transformation/as_upper_case_step.spec.ts +47 -0
- package/tests/unit/models/http-actions/transformation/round_step.spec.ts +69 -0
- package/tests/unit/models/http-actions/transformation/substring_step.spec.ts +85 -0
- package/tests/unit/models/http-actions/transformation/trim_step.spec.ts +44 -0
- package/tests/unit/models/http_cookie.spec.ts +516 -0
- package/tests/unit/models/http_history.spec.ts +443 -0
- package/tests/unit/models/project_folder.spec.ts +926 -0
- package/tests/unit/models/project_item.spec.ts +137 -0
- package/tests/unit/models/project_request.spec.ts +1047 -0
- package/tests/unit/models/project_schema.spec.ts +236 -0
- package/tests/unit/models/property.spec.ts +625 -0
- package/tests/unit/models/provider.spec.ts +102 -0
- package/tests/unit/models/request.spec.ts +1206 -0
- package/tests/unit/models/request_log.spec.ts +308 -0
- package/tests/unit/models/request_time.spec.ts +138 -0
- package/tests/unit/models/response_redirect.spec.ts +303 -0
- package/tests/unit/models/sent_request.spec.ts +206 -0
- package/tests/unit/models/server.spec.ts +195 -0
- package/tests/unit/models/thing.spec.ts +154 -0
- package/build/oauth-popup.html +0 -33
- /package/tests/unit/models/{Certificate.spec.ts → certificate.spec.ts} +0 -0
- /package/tests/unit/models/{HostRule.spec.ts → host_rule.spec.ts} +0 -0
- /package/tests/unit/models/{HttpProject.spec.ts → http_project.spec.ts} +0 -0
- /package/tests/unit/models/{HttpRequest.spec.ts → http_request.spec.ts} +0 -0
- /package/tests/unit/models/{HttpResponse.spec.ts → http_response.spec.ts} +0 -0
- /package/tests/unit/models/{License.spec.ts → license.spec.ts} +0 -0
- /package/tests/unit/models/{Response.spec.ts → response.spec.ts} +0 -0
|
@@ -42065,10 +42065,10 @@
|
|
|
42065
42065
|
"@id": "#191"
|
|
42066
42066
|
},
|
|
42067
42067
|
{
|
|
42068
|
-
"@id": "#
|
|
42068
|
+
"@id": "#197"
|
|
42069
42069
|
},
|
|
42070
42070
|
{
|
|
42071
|
-
"@id": "#
|
|
42071
|
+
"@id": "#194"
|
|
42072
42072
|
},
|
|
42073
42073
|
{
|
|
42074
42074
|
"@id": "#200"
|
|
@@ -43457,7 +43457,7 @@
|
|
|
43457
43457
|
"doc:ExternalDomainElement",
|
|
43458
43458
|
"doc:DomainElement"
|
|
43459
43459
|
],
|
|
43460
|
-
"doc:raw": "
|
|
43460
|
+
"doc:raw": "code: '5'\ndescription: 'Limited company'\n",
|
|
43461
43461
|
"core:mediaType": "application/yaml",
|
|
43462
43462
|
"sourcemaps:sources": [
|
|
43463
43463
|
{
|
|
@@ -43478,7 +43478,7 @@
|
|
|
43478
43478
|
"doc:ExternalDomainElement",
|
|
43479
43479
|
"doc:DomainElement"
|
|
43480
43480
|
],
|
|
43481
|
-
"doc:raw": "
|
|
43481
|
+
"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",
|
|
43482
43482
|
"core:mediaType": "application/yaml",
|
|
43483
43483
|
"sourcemaps:sources": [
|
|
43484
43484
|
{
|
|
@@ -44761,12 +44761,12 @@
|
|
|
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)-(3,0)]"
|
|
44765
44765
|
},
|
|
44766
44766
|
{
|
|
44767
44767
|
"@id": "#199/source-map/lexical/element_0",
|
|
44768
44768
|
"sourcemaps:element": "amf://id#199",
|
|
44769
|
-
"sourcemaps:value": "[(1,0)-(
|
|
44769
|
+
"sourcemaps:value": "[(1,0)-(10,0)]"
|
|
44770
44770
|
},
|
|
44771
44771
|
{
|
|
44772
44772
|
"@id": "#202/source-map/lexical/element_0",
|
package/noop.ts
ADDED
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.
|
|
4
|
+
"version": "0.15.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./browser.js": {
|
|
@@ -106,6 +106,7 @@
|
|
|
106
106
|
"@japa/browser-client": "^2.1.1",
|
|
107
107
|
"@japa/expect-type": "^2.0.3",
|
|
108
108
|
"@japa/runner": "^4.2.0",
|
|
109
|
+
"@pawel-up/semver": "^0.1.4",
|
|
109
110
|
"@rollup/plugin-typescript": "^12.1.2",
|
|
110
111
|
"@types/cors": "^2.8.12",
|
|
111
112
|
"@types/express-ntlm": "^2.3.3",
|
|
@@ -119,6 +120,7 @@
|
|
|
119
120
|
"@web/test-runner-playwright": "^0.11.0",
|
|
120
121
|
"amf-client-js": "^5.7.0",
|
|
121
122
|
"c8": "^10.1.3",
|
|
123
|
+
"conventional-changelog-cli": "^5.0.0",
|
|
122
124
|
"cors": "^2.8.5",
|
|
123
125
|
"eslint": "^9.20.1",
|
|
124
126
|
"eslint-config-prettier": "^10.0.1",
|
|
@@ -133,7 +135,6 @@
|
|
|
133
135
|
"lint-staged": "^16.0.0",
|
|
134
136
|
"nock": "^14.0.1",
|
|
135
137
|
"oauth2-mock-server": "^8.0.0",
|
|
136
|
-
"playwright": "^1.50.1",
|
|
137
138
|
"prettier": "^3.5.1",
|
|
138
139
|
"sinon": "^21.0.0",
|
|
139
140
|
"ts-lit-plugin": "^2.0.2",
|
|
@@ -146,7 +147,7 @@
|
|
|
146
147
|
"build:browser": "wireit",
|
|
147
148
|
"build:ts": "wireit",
|
|
148
149
|
"build:node": "wireit",
|
|
149
|
-
"build": "npm run build:ts && npm run
|
|
150
|
+
"build": "npm run build:ts && npm run copy:assets",
|
|
150
151
|
"prepare": "husky && npm run fixes && npm run build:ts && npm run build:api-models",
|
|
151
152
|
"fixes": "node scripts/fix-rollup-plugin.js",
|
|
152
153
|
"tsc": "wireit",
|
|
@@ -165,7 +166,11 @@
|
|
|
165
166
|
"lint:prettier": "wireit",
|
|
166
167
|
"format": "npm run format:prettier && npm run format:prettier",
|
|
167
168
|
"format:prettier": "wireit",
|
|
168
|
-
"format:eslint": "wireit"
|
|
169
|
+
"format:eslint": "wireit",
|
|
170
|
+
"release": "node scripts/release.js",
|
|
171
|
+
"release:patch": "node scripts/release.js patch",
|
|
172
|
+
"release:minor": "node scripts/release.js minor",
|
|
173
|
+
"release:major": "node scripts/release.js major"
|
|
169
174
|
},
|
|
170
175
|
"wireit": {
|
|
171
176
|
"test": {
|
|
@@ -66,7 +66,7 @@ class OidcEvents {
|
|
|
66
66
|
* @param target A node on which to dispatch the event.
|
|
67
67
|
* @returns Promise resolved when the token is removed
|
|
68
68
|
*/
|
|
69
|
-
static async
|
|
69
|
+
static async removeTokens(config: ITokenRemoveOptions, target: EventTarget = window): Promise<void> {
|
|
70
70
|
const e = new ContextEvent<ITokenRemoveOptions, void>(AuthorizationEventTypes.Oidc.removeTokens, config)
|
|
71
71
|
target.dispatchEvent(e)
|
|
72
72
|
return e.detail.result
|
|
@@ -38,7 +38,7 @@ export class CookieEvents {
|
|
|
38
38
|
* @param target The target on which to dispatch the event
|
|
39
39
|
* @returns The list of project index objects.
|
|
40
40
|
*/
|
|
41
|
-
static async listAll(target: EventTarget): Promise<IHttpCookie[] | undefined> {
|
|
41
|
+
static async listAll(target: EventTarget = window): Promise<IHttpCookie[] | undefined> {
|
|
42
42
|
const detail: ContextEventDetailWithResult<IHttpCookie[]> = {}
|
|
43
43
|
const e = new CustomEvent(CookieEventTypes.listAll, {
|
|
44
44
|
bubbles: true,
|
|
@@ -4,96 +4,9 @@ import {
|
|
|
4
4
|
DomainModelKind,
|
|
5
5
|
DomainPropertyKind,
|
|
6
6
|
DomainAssociationKind,
|
|
7
|
-
DataDomainKind,
|
|
8
7
|
} from '../models/kinds.js'
|
|
9
8
|
import type { DataDomain } from './DataDomain.js'
|
|
10
|
-
import {
|
|
11
|
-
import { EntityValidation } from './validation/entity_validation.js'
|
|
12
|
-
import { PropertyValidation } from './validation/property_validation.js'
|
|
13
|
-
|
|
14
|
-
export type DomainImpactKinds =
|
|
15
|
-
| typeof DomainNamespaceKind
|
|
16
|
-
| typeof DomainEntityKind
|
|
17
|
-
| typeof DomainModelKind
|
|
18
|
-
| typeof DomainPropertyKind
|
|
19
|
-
| typeof DomainAssociationKind
|
|
20
|
-
| typeof DataDomainKind
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* The impact analysis report
|
|
24
|
-
*/
|
|
25
|
-
export interface DomainImpactReport {
|
|
26
|
-
/**
|
|
27
|
-
* The key of the impacted data object.
|
|
28
|
-
* This is the key of the object that is being changed.
|
|
29
|
-
*/
|
|
30
|
-
key: string
|
|
31
|
-
/**
|
|
32
|
-
* The kind of the impacted data object.
|
|
33
|
-
* This is the kind of the object that is being changed.
|
|
34
|
-
*/
|
|
35
|
-
kind: DomainImpactKinds
|
|
36
|
-
/**
|
|
37
|
-
* The list of impacted data objects.
|
|
38
|
-
*/
|
|
39
|
-
impact: DomainImpactItem[]
|
|
40
|
-
/**
|
|
41
|
-
* Whether it is possible to proceed with the change.
|
|
42
|
-
* If the change is not possible, the reason will be in the impact list.
|
|
43
|
-
*/
|
|
44
|
-
canProceed: boolean
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface DomainImpactItem {
|
|
48
|
-
/**
|
|
49
|
-
* The key of the impacted data object.
|
|
50
|
-
*/
|
|
51
|
-
key: string
|
|
52
|
-
/**
|
|
53
|
-
* The kind of the impacted data object.
|
|
54
|
-
*/
|
|
55
|
-
kind: string
|
|
56
|
-
/**
|
|
57
|
-
* The type of the impact.
|
|
58
|
-
*
|
|
59
|
-
* - `delete` - The data object would be deleted.
|
|
60
|
-
*/
|
|
61
|
-
type: 'delete' | 'publish'
|
|
62
|
-
/**
|
|
63
|
-
* The impact description.
|
|
64
|
-
* Explains what will happen to the impacted data object.
|
|
65
|
-
* This is a human-readable description of the impact.
|
|
66
|
-
* It should be clear and concise.
|
|
67
|
-
*/
|
|
68
|
-
impact: string
|
|
69
|
-
/**
|
|
70
|
-
* The severity of the impact.
|
|
71
|
-
*
|
|
72
|
-
* - `info` - The impact is informational.
|
|
73
|
-
* - `warning` - The impact can potentially cause problems but is not a blocker.
|
|
74
|
-
* - `error` - The impact is a blocker and needs to be resolved before proceeding.
|
|
75
|
-
*/
|
|
76
|
-
severity: 'info' | 'warning' | 'error'
|
|
77
|
-
/**
|
|
78
|
-
* Whether the impact is blocking the operation.
|
|
79
|
-
* If true, the operation cannot proceed.
|
|
80
|
-
* @deprecated Use `severity` instead.
|
|
81
|
-
*/
|
|
82
|
-
blocking: boolean
|
|
83
|
-
/**
|
|
84
|
-
* The type of the relationship between two impacted objects.
|
|
85
|
-
*/
|
|
86
|
-
relationship?: 'child'
|
|
87
|
-
/**
|
|
88
|
-
* The resolution of the conflict if the change will be forced.
|
|
89
|
-
*/
|
|
90
|
-
resolution?: string
|
|
91
|
-
/**
|
|
92
|
-
* The optional parent of the impacted data object.
|
|
93
|
-
* For example, if the impacted item is a property, this will be the entity it belongs to.
|
|
94
|
-
*/
|
|
95
|
-
parent?: string
|
|
96
|
-
}
|
|
9
|
+
import { DomainImpactItem, DomainImpactKinds, DomainImpactReport } from './types.js'
|
|
97
10
|
|
|
98
11
|
/**
|
|
99
12
|
* # DomainImpactAnalysis
|
|
@@ -116,13 +29,13 @@ export interface DomainImpactItem {
|
|
|
116
29
|
* - `kind`: The kind of the impacted object.
|
|
117
30
|
* - `type`: The type of impact (currently only `delete`).
|
|
118
31
|
* - `impact`: A human-readable description of the impact.
|
|
119
|
-
* - `blocking`: Whether this impact prevents the deletion from proceeding.
|
|
120
32
|
* - `relationship`: The type of relationship between the deleted object and the impacted object (e.g., `child`).
|
|
121
33
|
* - `resolution`: A description of how the impact will be resolved if the deletion is forced.
|
|
34
|
+
* - `severity`: The severity of the impact, which can be `info`, `warning`, or `error`.
|
|
122
35
|
*
|
|
123
36
|
* - **Blocking Impacts:** Some impacts are considered "blocking," meaning they prevent the deletion from proceeding
|
|
124
37
|
* without manual intervention. For example, deleting an entity that is a parent to other entities is
|
|
125
|
-
* a blocking impact.
|
|
38
|
+
* a blocking impact. Blocking impacts are indicated by the `severity` property set to `error`.
|
|
126
39
|
*
|
|
127
40
|
* - **Non-Blocking Impacts:** Some impacts are informational and do not prevent the deletion. For example, deleting a
|
|
128
41
|
* property is not a blocking impact.
|
|
@@ -154,7 +67,7 @@ export interface DomainImpactItem {
|
|
|
154
67
|
* 3. **Interpreting the Report:** Examine the `DomainImpactReport` to understand the consequences of the deletion.
|
|
155
68
|
* - Check `report.canProceed` to see if the deletion is safe.
|
|
156
69
|
* - Iterate through `report.impact` to understand each consequence.
|
|
157
|
-
* - Pay special attention to `impact.
|
|
70
|
+
* - Pay special attention to `impact.severity` to identify impacts that require manual resolution.
|
|
158
71
|
*
|
|
159
72
|
* ```typescript
|
|
160
73
|
* if (report.canProceed) {
|
|
@@ -163,7 +76,7 @@ export interface DomainImpactItem {
|
|
|
163
76
|
* console.warn('Deletion cannot proceed due to the following impacts:');
|
|
164
77
|
* report.impact.forEach((item) => {
|
|
165
78
|
* console.warn(`- ${item.impact}`);
|
|
166
|
-
* if (item.
|
|
79
|
+
* if (item.severity === 'error') {
|
|
167
80
|
* console.warn(` - This impact is blocking.`);
|
|
168
81
|
* if (item.resolution) {
|
|
169
82
|
* console.warn(` - Resolution: ${item.resolution}`);
|
|
@@ -215,7 +128,7 @@ export interface DomainImpactItem {
|
|
|
215
128
|
* "kind": "DomainEntityKind",
|
|
216
129
|
* "type": "delete",
|
|
217
130
|
* "impact": "The entity with key Product will be deleted.",
|
|
218
|
-
* "
|
|
131
|
+
* "severity": "warning"
|
|
219
132
|
* },
|
|
220
133
|
* {
|
|
221
134
|
* "key": "SpecialProduct",
|
|
@@ -223,7 +136,7 @@ export interface DomainImpactItem {
|
|
|
223
136
|
* "type": "delete",
|
|
224
137
|
* "impact": "The SpecialProduct entity will become an orphan because it is a child of Product.",
|
|
225
138
|
* "resolution": "The \"Product\" entity will be removed as the parent of the \"SpecialProduct\" entity.",
|
|
226
|
-
* "
|
|
139
|
+
* "severity": "error",
|
|
227
140
|
* "relationship": "child"
|
|
228
141
|
* },
|
|
229
142
|
* {
|
|
@@ -232,14 +145,14 @@ export interface DomainImpactItem {
|
|
|
232
145
|
* "type": "delete",
|
|
233
146
|
* "impact": "The association with key category will be broken because it has a target to Product.",
|
|
234
147
|
* "resolution": "The association with key category will be removed from Product.",
|
|
235
|
-
* "
|
|
148
|
+
* "severity": "error"
|
|
236
149
|
* },
|
|
237
150
|
* {
|
|
238
151
|
* "key": "name",
|
|
239
152
|
* "kind": "DomainPropertyKind",
|
|
240
153
|
* "type": "delete",
|
|
241
154
|
* "impact": "The property with key name will be deleted.",
|
|
242
|
-
* "
|
|
155
|
+
* "severity": "info"
|
|
243
156
|
* }
|
|
244
157
|
* ],
|
|
245
158
|
* "canProceed": false
|
|
@@ -267,27 +180,6 @@ export interface DomainImpactItem {
|
|
|
267
180
|
* - `DomainAssociationKind`
|
|
268
181
|
* - `DataDomainKind`
|
|
269
182
|
*
|
|
270
|
-
* ### `DomainImpactReport`
|
|
271
|
-
*
|
|
272
|
-
* - **Description:** The structure of the impact analysis report.
|
|
273
|
-
* - **Properties:**
|
|
274
|
-
* - `key` (`string`): The key of the object being deleted.
|
|
275
|
-
* - `kind` (`DomainImpactKinds`): The kind of the object being deleted.
|
|
276
|
-
* - `impact` (`DomainImpactItem[]`): The list of impacts.
|
|
277
|
-
* - `canProceed` (`boolean`): Whether the deletion can proceed.
|
|
278
|
-
*
|
|
279
|
-
* ### `DomainImpactItem`
|
|
280
|
-
*
|
|
281
|
-
* - **Description:** The structure of an individual impact item.
|
|
282
|
-
* - **Properties:**
|
|
283
|
-
* - `key` (`string`): The key of the impacted object.
|
|
284
|
-
* - `kind` (`string`): The kind of the impacted object.
|
|
285
|
-
* - `type` (`'delete'`): The type of impact.
|
|
286
|
-
* - `impact` (`string`): The impact description.
|
|
287
|
-
* - `blocking` (`boolean`): Whether the impact is blocking.
|
|
288
|
-
* - `relationship` (`'child'`, optional): The relationship type.
|
|
289
|
-
* - `resolution` (`string`, optional): The resolution description.
|
|
290
|
-
*
|
|
291
183
|
* ## Error Handling
|
|
292
184
|
*
|
|
293
185
|
* The `DomainImpactAnalysis` class does not throw errors. Instead, it uses the `DomainImpactReport` to communicate
|
|
@@ -297,7 +189,7 @@ export interface DomainImpactItem {
|
|
|
297
189
|
*
|
|
298
190
|
* - **Always Analyze Before Deleting:** Before deleting any data domain element, always use `DomainImpactAnalysis`
|
|
299
191
|
* to understand the consequences.
|
|
300
|
-
* - **Handle Blocking Impacts:** Pay close attention to `
|
|
192
|
+
* - **Handle Blocking Impacts:** Pay close attention to `severity = "error"` impacts and implement appropriate
|
|
301
193
|
* logic to handle them.
|
|
302
194
|
* - **Inform the User:** If a deletion cannot proceed, inform the user about the blocking impacts and provide
|
|
303
195
|
* guidance on how to resolve them.
|
|
@@ -311,17 +203,10 @@ export interface DomainImpactItem {
|
|
|
311
203
|
* about data deletion and prevent unintended consequences.
|
|
312
204
|
*/
|
|
313
205
|
export class DomainImpactAnalysis {
|
|
314
|
-
private report: DomainImpactReport
|
|
315
206
|
private root: DataDomain
|
|
316
207
|
|
|
317
208
|
constructor(root: DataDomain) {
|
|
318
209
|
this.root = root
|
|
319
|
-
this.report = {
|
|
320
|
-
key: '',
|
|
321
|
-
kind: DataDomainKind,
|
|
322
|
-
impact: [],
|
|
323
|
-
canProceed: false,
|
|
324
|
-
}
|
|
325
210
|
}
|
|
326
211
|
|
|
327
212
|
/**
|
|
@@ -331,14 +216,15 @@ export class DomainImpactAnalysis {
|
|
|
331
216
|
* @returns The delete impact analysis report.
|
|
332
217
|
*/
|
|
333
218
|
deleteAnalysis(key: string, kind: DomainImpactKinds): DomainImpactReport {
|
|
334
|
-
|
|
219
|
+
const report: DomainImpactReport = {
|
|
335
220
|
key,
|
|
336
221
|
kind,
|
|
337
222
|
impact: [],
|
|
338
223
|
canProceed: true,
|
|
339
224
|
}
|
|
340
|
-
this.createDeleteImpact(key, kind, key)
|
|
341
|
-
|
|
225
|
+
this.createDeleteImpact(key, kind, key, report.impact)
|
|
226
|
+
report.canProceed = this.computeCanProceed(report.impact)
|
|
227
|
+
return report
|
|
342
228
|
}
|
|
343
229
|
|
|
344
230
|
/**
|
|
@@ -347,161 +233,100 @@ export class DomainImpactAnalysis {
|
|
|
347
233
|
* @returns The delete impact analysis report.
|
|
348
234
|
*/
|
|
349
235
|
removeForeignNamespaceAnalysis(key: string): DomainImpactReport {
|
|
350
|
-
|
|
236
|
+
const report: DomainImpactReport = {
|
|
351
237
|
key,
|
|
352
238
|
kind: DomainNamespaceKind,
|
|
353
239
|
impact: [],
|
|
354
240
|
canProceed: true,
|
|
355
241
|
}
|
|
356
|
-
this.createRemoveForeignNamespaceImpact(key)
|
|
357
|
-
|
|
242
|
+
this.createRemoveForeignNamespaceImpact(key, report.impact)
|
|
243
|
+
report.canProceed = this.computeCanProceed(report.impact)
|
|
244
|
+
return report
|
|
358
245
|
}
|
|
359
246
|
|
|
360
247
|
/**
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
* @returns
|
|
248
|
+
* Computes whether the deletion can proceed based on the impact report.
|
|
249
|
+
* @param impact The list of impacts from the analysis.
|
|
250
|
+
* @returns `true` if the deletion can proceed, `false` otherwise.
|
|
364
251
|
*/
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
key: '',
|
|
368
|
-
kind: DataDomainKind,
|
|
369
|
-
impact: [],
|
|
370
|
-
canProceed: true,
|
|
371
|
-
}
|
|
372
|
-
const entityValidator = new EntityValidation(this.root)
|
|
373
|
-
const propertyValidator = new PropertyValidation(this.root)
|
|
374
|
-
const associationValidator = new AssociationValidation(this.root)
|
|
375
|
-
for (const entity of this.root.listEntities()) {
|
|
376
|
-
if (entity.domain.key !== this.root.key) {
|
|
377
|
-
// we don't need to validate foreign entities
|
|
378
|
-
continue
|
|
379
|
-
}
|
|
380
|
-
const report = entityValidator.validate(entity)
|
|
381
|
-
for (const item of report) {
|
|
382
|
-
const blocking = item.severity === 'error'
|
|
383
|
-
this.report.canProceed = this.report.canProceed && !blocking
|
|
384
|
-
this.report.impact.push({
|
|
385
|
-
key: item.key,
|
|
386
|
-
kind: item.kind,
|
|
387
|
-
type: 'publish',
|
|
388
|
-
impact: item.message,
|
|
389
|
-
blocking,
|
|
390
|
-
resolution: item.help,
|
|
391
|
-
severity: item.severity,
|
|
392
|
-
parent: item.parent,
|
|
393
|
-
})
|
|
394
|
-
}
|
|
395
|
-
for (const property of entity.properties) {
|
|
396
|
-
const report = propertyValidator.validate(property)
|
|
397
|
-
for (const item of report) {
|
|
398
|
-
const blocking = item.severity === 'error'
|
|
399
|
-
this.report.canProceed = this.report.canProceed && !blocking
|
|
400
|
-
this.report.impact.push({
|
|
401
|
-
key: item.key,
|
|
402
|
-
kind: item.kind,
|
|
403
|
-
type: 'publish',
|
|
404
|
-
impact: item.message,
|
|
405
|
-
blocking,
|
|
406
|
-
resolution: item.help,
|
|
407
|
-
severity: item.severity,
|
|
408
|
-
parent: item.parent,
|
|
409
|
-
})
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
for (const association of entity.associations) {
|
|
413
|
-
const report = associationValidator.validate(association)
|
|
414
|
-
for (const item of report) {
|
|
415
|
-
const blocking = item.severity === 'error'
|
|
416
|
-
this.report.canProceed = this.report.canProceed && !blocking
|
|
417
|
-
this.report.impact.push({
|
|
418
|
-
key: item.key,
|
|
419
|
-
kind: item.kind,
|
|
420
|
-
type: 'publish',
|
|
421
|
-
impact: item.message,
|
|
422
|
-
blocking,
|
|
423
|
-
resolution: item.help,
|
|
424
|
-
severity: item.severity,
|
|
425
|
-
parent: item.parent,
|
|
426
|
-
})
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
return this.report
|
|
252
|
+
protected computeCanProceed(impact: DomainImpactItem[]): boolean {
|
|
253
|
+
return !impact.some((item) => item.severity === 'error')
|
|
431
254
|
}
|
|
432
255
|
|
|
433
|
-
protected createDeleteImpact(
|
|
256
|
+
protected createDeleteImpact(
|
|
257
|
+
key: string,
|
|
258
|
+
kind: DomainImpactKinds,
|
|
259
|
+
rootKey: string,
|
|
260
|
+
impact: DomainImpactItem[]
|
|
261
|
+
): void {
|
|
434
262
|
switch (kind) {
|
|
435
263
|
case DomainNamespaceKind:
|
|
436
|
-
this.deleteNamespaceAnalysis(key, rootKey)
|
|
264
|
+
this.deleteNamespaceAnalysis(key, rootKey, impact)
|
|
437
265
|
break
|
|
438
266
|
case DomainModelKind:
|
|
439
|
-
this.deleteModelAnalysis(key, rootKey)
|
|
267
|
+
this.deleteModelAnalysis(key, rootKey, impact)
|
|
440
268
|
break
|
|
441
269
|
case DomainEntityKind:
|
|
442
|
-
this.deleteEntityAnalysis(key, rootKey)
|
|
270
|
+
this.deleteEntityAnalysis(key, rootKey, impact)
|
|
443
271
|
break
|
|
444
272
|
case DomainPropertyKind:
|
|
445
|
-
this.deletePropertyAnalysis(key)
|
|
273
|
+
this.deletePropertyAnalysis(key, impact)
|
|
446
274
|
break
|
|
447
275
|
case DomainAssociationKind:
|
|
448
|
-
this.deleteAssociationAnalysis(key)
|
|
276
|
+
this.deleteAssociationAnalysis(key, impact)
|
|
449
277
|
break
|
|
450
278
|
default:
|
|
451
279
|
// ignore unknown kinds
|
|
452
280
|
}
|
|
453
281
|
}
|
|
454
282
|
|
|
455
|
-
protected deleteNamespaceAnalysis(key: string, rootKey: string): void {
|
|
283
|
+
protected deleteNamespaceAnalysis(key: string, rootKey: string, impact: DomainImpactItem[]): void {
|
|
456
284
|
const ns = this.root.findNamespace(key)
|
|
457
285
|
if (!ns) {
|
|
458
286
|
return
|
|
459
287
|
}
|
|
460
|
-
|
|
288
|
+
impact.push({
|
|
461
289
|
key: ns.key,
|
|
462
290
|
kind: ns.kind,
|
|
463
291
|
type: 'delete',
|
|
464
292
|
impact: `The ${ns.info.getLabel()} ${this.kindToLabel(DomainNamespaceKind)} will be deleted.`,
|
|
465
|
-
blocking: false,
|
|
466
293
|
severity: 'info',
|
|
467
294
|
})
|
|
468
295
|
for (const child of ns.listNamespaces()) {
|
|
469
|
-
this.deleteNamespaceAnalysis(child.key, rootKey)
|
|
296
|
+
this.deleteNamespaceAnalysis(child.key, rootKey, impact)
|
|
470
297
|
}
|
|
471
298
|
for (const child of ns.listModels()) {
|
|
472
|
-
this.deleteModelAnalysis(child.key, rootKey)
|
|
299
|
+
this.deleteModelAnalysis(child.key, rootKey, impact)
|
|
473
300
|
}
|
|
474
301
|
}
|
|
475
302
|
|
|
476
|
-
protected deleteModelAnalysis(key: string, rootKey: string): void {
|
|
303
|
+
protected deleteModelAnalysis(key: string, rootKey: string, impact: DomainImpactItem[]): void {
|
|
477
304
|
const model = this.root.findModel(key)
|
|
478
305
|
if (!model) {
|
|
479
306
|
return
|
|
480
307
|
}
|
|
481
|
-
|
|
308
|
+
impact.push({
|
|
482
309
|
key: model.key,
|
|
483
310
|
kind: model.kind,
|
|
484
311
|
type: 'delete',
|
|
485
312
|
impact: `The ${model.info.getLabel()} ${this.kindToLabel(DomainModelKind)} will be deleted.`,
|
|
486
|
-
blocking: false,
|
|
487
313
|
severity: 'info',
|
|
488
314
|
})
|
|
489
315
|
for (const child of model.listEntities()) {
|
|
490
|
-
this.deleteEntityAnalysis(child.key, rootKey)
|
|
316
|
+
this.deleteEntityAnalysis(child.key, rootKey, impact)
|
|
491
317
|
}
|
|
492
318
|
}
|
|
493
319
|
|
|
494
|
-
protected deleteEntityAnalysis(key: string, rootKey: string): void {
|
|
320
|
+
protected deleteEntityAnalysis(key: string, rootKey: string, impact: DomainImpactItem[]): void {
|
|
495
321
|
const entity = this.root.findEntity(key)
|
|
496
322
|
if (!entity) {
|
|
497
323
|
return
|
|
498
324
|
}
|
|
499
|
-
|
|
325
|
+
impact.push({
|
|
500
326
|
key: entity.key,
|
|
501
327
|
kind: entity.kind,
|
|
502
328
|
type: 'delete',
|
|
503
329
|
impact: `The ${entity.info.getLabel()} ${this.kindToLabel(DomainEntityKind)} will be deleted.`,
|
|
504
|
-
blocking: false,
|
|
505
330
|
severity: 'info',
|
|
506
331
|
})
|
|
507
332
|
|
|
@@ -521,17 +346,15 @@ export class DomainImpactAnalysis {
|
|
|
521
346
|
}
|
|
522
347
|
const pLabel = entity.info.getLabel()
|
|
523
348
|
const cLabel = childEntity.info.getLabel()
|
|
524
|
-
|
|
349
|
+
impact.push({
|
|
525
350
|
key: childEntity.key,
|
|
526
351
|
kind: childEntity.kind,
|
|
527
352
|
type: 'delete',
|
|
528
353
|
impact: `The "${cLabel}" ${this.kindToLabel(DomainEntityKind)} will become an orphan because it is a child of the "${pLabel}" entity.`,
|
|
529
354
|
resolution: `The "${pLabel}" entity will be removed as the parent of the "${cLabel}" entity.`,
|
|
530
|
-
blocking: false,
|
|
531
355
|
relationship: 'child',
|
|
532
356
|
severity: 'error',
|
|
533
357
|
})
|
|
534
|
-
this.report.canProceed = false
|
|
535
358
|
}
|
|
536
359
|
// We need to know whether there's another entity that has an association to this entity.
|
|
537
360
|
for (const edgeInfo of this.root.graph.inEdges(entity.key)) {
|
|
@@ -554,51 +377,47 @@ export class DomainImpactAnalysis {
|
|
|
554
377
|
|
|
555
378
|
const aLabel = association.info.getLabel()
|
|
556
379
|
const eLabel = entity.info.getLabel()
|
|
557
|
-
|
|
380
|
+
impact.push({
|
|
558
381
|
key: association.key,
|
|
559
382
|
kind: association.kind,
|
|
560
383
|
type: 'delete',
|
|
561
384
|
impact: `The ${aLabel} ${this.kindToLabel(DomainAssociationKind)} will be broken because it has a target to ${eLabel}.`,
|
|
562
385
|
resolution: `The ${aLabel} ${this.kindToLabel(DomainAssociationKind)} will be removed from ${eLabel}.`,
|
|
563
|
-
blocking: true,
|
|
564
386
|
severity: 'error',
|
|
565
387
|
})
|
|
566
|
-
this.report.canProceed = false
|
|
567
388
|
}
|
|
568
389
|
for (const child of entity.listProperties()) {
|
|
569
|
-
this.deletePropertyAnalysis(child.key)
|
|
390
|
+
this.deletePropertyAnalysis(child.key, impact)
|
|
570
391
|
}
|
|
571
392
|
for (const child of entity.listAssociations()) {
|
|
572
|
-
this.deleteAssociationAnalysis(child.key)
|
|
393
|
+
this.deleteAssociationAnalysis(child.key, impact)
|
|
573
394
|
}
|
|
574
395
|
}
|
|
575
396
|
|
|
576
|
-
protected deletePropertyAnalysis(key: string): void {
|
|
397
|
+
protected deletePropertyAnalysis(key: string, impact: DomainImpactItem[]): void {
|
|
577
398
|
const property = this.root.findProperty(key)
|
|
578
399
|
if (!property) {
|
|
579
400
|
return
|
|
580
401
|
}
|
|
581
|
-
|
|
402
|
+
impact.push({
|
|
582
403
|
key: property.key,
|
|
583
404
|
kind: property.kind,
|
|
584
405
|
type: 'delete',
|
|
585
406
|
impact: `The ${property.info.getLabel()} ${this.kindToLabel(DomainPropertyKind)} will be deleted.`,
|
|
586
|
-
blocking: false,
|
|
587
407
|
severity: 'info',
|
|
588
408
|
})
|
|
589
409
|
}
|
|
590
410
|
|
|
591
|
-
protected deleteAssociationAnalysis(key: string): void {
|
|
411
|
+
protected deleteAssociationAnalysis(key: string, impact: DomainImpactItem[]): void {
|
|
592
412
|
const association = this.root.findAssociation(key)
|
|
593
413
|
if (!association) {
|
|
594
414
|
return
|
|
595
415
|
}
|
|
596
|
-
|
|
416
|
+
impact.push({
|
|
597
417
|
key: association.key,
|
|
598
418
|
kind: association.kind,
|
|
599
419
|
type: 'delete',
|
|
600
420
|
impact: `The ${association.info.getLabel()} ${this.kindToLabel(DomainAssociationKind)} will be deleted.`,
|
|
601
|
-
blocking: false,
|
|
602
421
|
severity: 'info',
|
|
603
422
|
})
|
|
604
423
|
}
|
|
@@ -620,7 +439,7 @@ export class DomainImpactAnalysis {
|
|
|
620
439
|
}
|
|
621
440
|
}
|
|
622
441
|
|
|
623
|
-
protected createRemoveForeignNamespaceImpact(key: string): void {
|
|
442
|
+
protected createRemoveForeignNamespaceImpact(key: string, impact: DomainImpactItem[]): void {
|
|
624
443
|
const foreignNamespace = this.root.dependencies.get(key)
|
|
625
444
|
if (!foreignNamespace) {
|
|
626
445
|
return
|
|
@@ -640,17 +459,15 @@ export class DomainImpactAnalysis {
|
|
|
640
459
|
}
|
|
641
460
|
const eLabel = entity.info.getLabel()
|
|
642
461
|
const pLabel = parentEntity.info.getLabel()
|
|
643
|
-
|
|
462
|
+
impact.push({
|
|
644
463
|
key: entity.key,
|
|
645
464
|
kind: entity.kind,
|
|
646
465
|
type: 'delete',
|
|
647
466
|
impact: `The "${eLabel}" ${this.kindToLabel(DomainEntityKind)} will become an orphan because its parent "${pLabel}" is in the foreign namespace "${foreignNamespace.key}".`,
|
|
648
467
|
resolution: `The "${pLabel}" entity will be removed as the parent of the "${eLabel}" entity.`,
|
|
649
|
-
blocking: true,
|
|
650
468
|
relationship: 'child',
|
|
651
469
|
severity: 'error',
|
|
652
470
|
})
|
|
653
|
-
this.report.canProceed = false
|
|
654
471
|
} else if (edge.type === 'association') {
|
|
655
472
|
const association = this.root.findAssociation(info.w)
|
|
656
473
|
if (!association) {
|
|
@@ -666,16 +483,14 @@ export class DomainImpactAnalysis {
|
|
|
666
483
|
const aLabel = association.info.getLabel()
|
|
667
484
|
const eLabel = entity.info.getLabel()
|
|
668
485
|
const tLabel = targetEntity.info.getLabel()
|
|
669
|
-
|
|
486
|
+
impact.push({
|
|
670
487
|
key: association.key,
|
|
671
488
|
kind: association.kind,
|
|
672
489
|
type: 'delete',
|
|
673
490
|
impact: `The "${aLabel}" ${this.kindToLabel(DomainAssociationKind)} from "${eLabel}" will be broken because it targets "${tLabel}" in the foreign namespace "${foreignNamespace.key}".`,
|
|
674
491
|
resolution: `The "${aLabel}" ${this.kindToLabel(DomainAssociationKind)} will be removed from "${eLabel}".`,
|
|
675
|
-
blocking: true,
|
|
676
492
|
severity: 'error',
|
|
677
493
|
})
|
|
678
|
-
this.report.canProceed = false
|
|
679
494
|
}
|
|
680
495
|
}
|
|
681
496
|
}
|