@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.
Files changed (96) hide show
  1. package/RELEASE.md +163 -0
  2. package/RELEASE_SETUP.md +235 -0
  3. package/build/src/events/authorization/AuthorizationEvents.d.ts +1 -1
  4. package/build/src/events/authorization/AuthorizationEvents.d.ts.map +1 -1
  5. package/build/src/events/authorization/AuthorizationEvents.js +1 -1
  6. package/build/src/events/authorization/AuthorizationEvents.js.map +1 -1
  7. package/build/src/events/cookies/CookieEvents.d.ts +1 -1
  8. package/build/src/events/cookies/CookieEvents.d.ts.map +1 -1
  9. package/build/src/events/cookies/CookieEvents.js +1 -1
  10. package/build/src/events/cookies/CookieEvents.js.map +1 -1
  11. package/build/src/modeling/DomainImpactAnalysis.d.ts +22 -119
  12. package/build/src/modeling/DomainImpactAnalysis.d.ts.map +1 -1
  13. package/build/src/modeling/DomainImpactAnalysis.js +49 -155
  14. package/build/src/modeling/DomainImpactAnalysis.js.map +1 -1
  15. package/build/src/modeling/DomainValidation.d.ts +8 -0
  16. package/build/src/modeling/DomainValidation.d.ts.map +1 -0
  17. package/build/src/modeling/DomainValidation.js +99 -0
  18. package/build/src/modeling/DomainValidation.js.map +1 -0
  19. package/build/src/modeling/types.d.ts +70 -0
  20. package/build/src/modeling/types.d.ts.map +1 -1
  21. package/build/src/modeling/types.js.map +1 -1
  22. package/build/src/modeling/validation/rules.d.ts +2 -3
  23. package/build/src/modeling/validation/rules.d.ts.map +1 -1
  24. package/build/src/modeling/validation/rules.js.map +1 -1
  25. package/build/src/modeling/validation/semantic_validation.d.ts +31 -0
  26. package/build/src/modeling/validation/semantic_validation.d.ts.map +1 -0
  27. package/build/src/modeling/validation/semantic_validation.js +126 -0
  28. package/build/src/modeling/validation/semantic_validation.js.map +1 -0
  29. package/build/tsconfig.tsbuildinfo +1 -1
  30. package/data/models/example-generator-api.json +6 -6
  31. package/noop.ts +3 -0
  32. package/package.json +9 -4
  33. package/src/events/authorization/AuthorizationEvents.ts +1 -1
  34. package/src/events/cookies/CookieEvents.ts +1 -1
  35. package/src/modeling/DomainImpactAnalysis.ts +54 -239
  36. package/src/modeling/DomainValidation.ts +105 -0
  37. package/src/modeling/types.ts +86 -0
  38. package/src/modeling/validation/rules.ts +2 -4
  39. package/src/modeling/validation/semantic_validation.ts +145 -0
  40. package/tests/unit/events/EventsTestHelpers.ts +16 -0
  41. package/tests/unit/events/amf.spec.ts +151 -0
  42. package/tests/unit/events/authorization.spec.ts +150 -0
  43. package/tests/unit/events/cookie.spec.ts +274 -0
  44. package/tests/unit/events/encryption.spec.ts +108 -0
  45. package/tests/unit/events/events_polyfills.ts +77 -0
  46. package/tests/unit/events/process.spec.ts +120 -0
  47. package/tests/unit/events/reporting.spec.ts +82 -0
  48. package/tests/unit/events/telemetry.spec.ts +224 -0
  49. package/tests/unit/events/transport.spec.ts +139 -0
  50. package/tests/unit/modeling/domain_impact_analysis.spec.ts +0 -110
  51. package/tests/unit/modeling/domain_validation.spec.ts +94 -0
  52. package/tests/unit/modeling/validation/semantic_validation.spec.ts +91 -0
  53. package/tests/unit/models/environment.spec.ts +574 -0
  54. package/tests/unit/models/error_response.spec.ts +183 -0
  55. package/tests/unit/models/headers_array.spec.ts +86 -0
  56. package/tests/unit/models/http-actions/assertion/equal_assertion.spec.ts +103 -0
  57. package/tests/unit/models/http-actions/assertion/greater_than_assertion.spec.ts +91 -0
  58. package/tests/unit/models/http-actions/assertion/includes_assertion.spec.ts +71 -0
  59. package/tests/unit/models/http-actions/assertion/less_than_assertion.spec.ts +91 -0
  60. package/tests/unit/models/http-actions/assertion/matches_assertion.spec.ts +71 -0
  61. package/tests/unit/models/http-actions/assertion/matches_schema_assertion.spec.ts +117 -0
  62. package/tests/unit/models/http-actions/assertion/not_equal_assertion.spec.ts +103 -0
  63. package/tests/unit/models/http-actions/assertion/not_includes_assertion.spec.ts +71 -0
  64. package/tests/unit/models/http-actions/assertion/not_ok_assertion.spec.ts +47 -0
  65. package/tests/unit/models/http-actions/assertion/not_to_be_assertion.spec.ts +72 -0
  66. package/tests/unit/models/http-actions/assertion/ok_assertion.spec.ts +44 -0
  67. package/tests/unit/models/http-actions/assertion/to_be_assertion.spec.ts +71 -0
  68. package/tests/unit/models/http-actions/transformation/as_lower_case_step.spec.ts +47 -0
  69. package/tests/unit/models/http-actions/transformation/as_number_step.spec.ts +47 -0
  70. package/tests/unit/models/http-actions/transformation/as_upper_case_step.spec.ts +47 -0
  71. package/tests/unit/models/http-actions/transformation/round_step.spec.ts +69 -0
  72. package/tests/unit/models/http-actions/transformation/substring_step.spec.ts +85 -0
  73. package/tests/unit/models/http-actions/transformation/trim_step.spec.ts +44 -0
  74. package/tests/unit/models/http_cookie.spec.ts +516 -0
  75. package/tests/unit/models/http_history.spec.ts +443 -0
  76. package/tests/unit/models/project_folder.spec.ts +926 -0
  77. package/tests/unit/models/project_item.spec.ts +137 -0
  78. package/tests/unit/models/project_request.spec.ts +1047 -0
  79. package/tests/unit/models/project_schema.spec.ts +236 -0
  80. package/tests/unit/models/property.spec.ts +625 -0
  81. package/tests/unit/models/provider.spec.ts +102 -0
  82. package/tests/unit/models/request.spec.ts +1206 -0
  83. package/tests/unit/models/request_log.spec.ts +308 -0
  84. package/tests/unit/models/request_time.spec.ts +138 -0
  85. package/tests/unit/models/response_redirect.spec.ts +303 -0
  86. package/tests/unit/models/sent_request.spec.ts +206 -0
  87. package/tests/unit/models/server.spec.ts +195 -0
  88. package/tests/unit/models/thing.spec.ts +154 -0
  89. package/build/oauth-popup.html +0 -33
  90. /package/tests/unit/models/{Certificate.spec.ts → certificate.spec.ts} +0 -0
  91. /package/tests/unit/models/{HostRule.spec.ts → host_rule.spec.ts} +0 -0
  92. /package/tests/unit/models/{HttpProject.spec.ts → http_project.spec.ts} +0 -0
  93. /package/tests/unit/models/{HttpRequest.spec.ts → http_request.spec.ts} +0 -0
  94. /package/tests/unit/models/{HttpResponse.spec.ts → http_response.spec.ts} +0 -0
  95. /package/tests/unit/models/{License.spec.ts → license.spec.ts} +0 -0
  96. /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": "#194"
42068
+ "@id": "#197"
42069
42069
  },
42070
42070
  {
42071
- "@id": "#197"
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": "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",
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": "code: '5'\ndescription: 'Limited company'\n",
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)-(10,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)-(3,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
@@ -0,0 +1,3 @@
1
+ // Dummy file to satisfy @web/dev-server-rollup plugin requirements
2
+ // This file is used as a placeholder input for rollup configuration
3
+ export default {}
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.10",
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 lint && npm run copy:assets",
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 removeToken(config: ITokenRemoveOptions, target: EventTarget = window): Promise<void> {
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 { AssociationValidation } from './validation/association_validation.js'
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.blocking` to identify impacts that require manual resolution.
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.blocking) {
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
- * "blocking": false
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
- * "blocking": true,
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
- * "blocking": true
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
- * "blocking": false
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 `blocking` impacts and implement appropriate
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
- this.report = {
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
- return this.report
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
- this.report = {
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
- return this.report
242
+ this.createRemoveForeignNamespaceImpact(key, report.impact)
243
+ report.canProceed = this.computeCanProceed(report.impact)
244
+ return report
358
245
  }
359
246
 
360
247
  /**
361
- * Analyzes the data domain for publishing. Essentially, it performs a validation of the data domain
362
- * and returns a report of the impact.
363
- * @returns The publish impact analysis report.
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
- publishAnalysis(): DomainImpactReport {
366
- this.report = {
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(key: string, kind: DomainImpactKinds, rootKey: string): void {
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
- this.report.impact.push({
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
- this.report.impact.push({
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
- this.report.impact.push({
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
- this.report.impact.push({
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
- this.report.impact.push({
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
- this.report.impact.push({
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
- this.report.impact.push({
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
- this.report.impact.push({
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
- this.report.impact.push({
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
  }