@speclynx/apidom-overlay 6.0.1 → 6.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@speclynx/apidom-overlay",
3
- "version": "6.0.1",
3
+ "version": "6.1.0",
4
4
  "description": "Apply Overlay 1.x.y documents to API definitions.",
5
5
  "keywords": [
6
6
  "apidom",
@@ -18,7 +18,8 @@
18
18
  "publishConfig": {
19
19
  "access": "public",
20
20
  "registry": "https://registry.npmjs.org",
21
- "provenance": true
21
+ "provenance": true,
22
+ "timeout": 60000
22
23
  },
23
24
  "type": "module",
24
25
  "sideEffects": false,
@@ -53,12 +54,13 @@
53
54
  "license": "Apache-2.0",
54
55
  "dependencies": {
55
56
  "@babel/runtime-corejs3": "^8.0.5",
56
- "@speclynx/apidom-core": "6.0.1",
57
- "@speclynx/apidom-datamodel": "6.0.1",
58
- "@speclynx/apidom-error": "6.0.1",
59
- "@speclynx/apidom-json-path": "6.0.1",
60
- "@speclynx/apidom-ns-overlay-1": "6.0.1",
61
- "@speclynx/apidom-reference": "6.0.1",
57
+ "@speclynx/apidom-core": "6.1.0",
58
+ "@speclynx/apidom-datamodel": "6.1.0",
59
+ "@speclynx/apidom-error": "6.1.0",
60
+ "@speclynx/apidom-json-path": "6.1.0",
61
+ "@speclynx/apidom-ns-overlay-1": "6.1.0",
62
+ "@speclynx/apidom-reference": "6.1.0",
63
+ "ramda": "~0.32.0",
62
64
  "type-fest": "^5.10.0"
63
65
  },
64
66
  "files": [
@@ -71,5 +73,5 @@
71
73
  "README.md",
72
74
  "CHANGELOG.md"
73
75
  ],
74
- "gitHead": "d2ea4f01cac54a0d5e1030386e3b0b60664c9619"
76
+ "gitHead": "575dbf59cb58a6c57248bf2c027a5cbc99442a63"
75
77
  }
@@ -82,6 +82,20 @@ const mergeValue = (targetElement, sourceElement, options = defaultApplyOptions)
82
82
  throw new _OverlayError.default(`Incompatible types in overlay merge: cannot merge ` + `${targetIsObject ? 'object' : targetIsArray ? 'array' : 'primitive'} with ` + `${sourceIsObject ? 'object' : sourceIsArray ? 'array' : 'primitive'}`);
83
83
  };
84
84
 
85
+ /**
86
+ * Anchors, aliases and comments belong to the overlay document. Written in the
87
+ * target they'd clash with its anchor names (an overlay anchor taking a name
88
+ * the target's aliases refer to, an overlay alias referring to a target node)
89
+ * or carry notes meant for the overlay. How a value is written is kept.
90
+ */
91
+ const stripOverlayOnlyStyle = element => {
92
+ const yamlStyle = element.style?.yaml;
93
+ if (yamlStyle !== undefined) {
94
+ ['anchor', 'alias', 'comment', 'commentBefore'].forEach(name => delete yamlStyle[name]);
95
+ }
96
+ element.children.forEach(stripOverlayOnlyStyle);
97
+ };
98
+
85
99
  /**
86
100
  * Resolves a normalized path to its parent element and child key.
87
101
  */
@@ -280,7 +294,9 @@ const applyAction = (actionElement, targetElement, options = defaultApplyOptions
280
294
  if (actionElement.update !== undefined) {
281
295
  const nodesValidation = (0, _validate.validateTargetNodes)(matches);
282
296
  if (!nodesValidation.valid) throw nodesValidation.error;
283
- const result = applyUpdateAction(normalizedPaths, actionElement.update, workingElement, mutatingOptions);
297
+ const updateValue = (0, _apidomDatamodel.cloneDeep)(actionElement.update);
298
+ stripOverlayOnlyStyle(updateValue);
299
+ const result = applyUpdateAction(normalizedPaths, updateValue, workingElement, mutatingOptions);
284
300
  tracer?.action({
285
301
  target: targetExpression,
286
302
  type: 'update',
@@ -72,6 +72,20 @@ const mergeValue = (targetElement, sourceElement, options = defaultApplyOptions)
72
72
  throw new OverlayError(`Incompatible types in overlay merge: cannot merge ` + `${targetIsObject ? 'object' : targetIsArray ? 'array' : 'primitive'} with ` + `${sourceIsObject ? 'object' : sourceIsArray ? 'array' : 'primitive'}`);
73
73
  };
74
74
 
75
+ /**
76
+ * Anchors, aliases and comments belong to the overlay document. Written in the
77
+ * target they'd clash with its anchor names (an overlay anchor taking a name
78
+ * the target's aliases refer to, an overlay alias referring to a target node)
79
+ * or carry notes meant for the overlay. How a value is written is kept.
80
+ */
81
+ const stripOverlayOnlyStyle = element => {
82
+ const yamlStyle = element.style?.yaml;
83
+ if (yamlStyle !== undefined) {
84
+ ['anchor', 'alias', 'comment', 'commentBefore'].forEach(name => delete yamlStyle[name]);
85
+ }
86
+ element.children.forEach(stripOverlayOnlyStyle);
87
+ };
88
+
75
89
  /**
76
90
  * Resolves a normalized path to its parent element and child key.
77
91
  */
@@ -267,7 +281,9 @@ export const applyAction = (actionElement, targetElement, options = defaultApply
267
281
  if (actionElement.update !== undefined) {
268
282
  const nodesValidation = validateTargetNodes(matches);
269
283
  if (!nodesValidation.valid) throw nodesValidation.error;
270
- const result = applyUpdateAction(normalizedPaths, actionElement.update, workingElement, mutatingOptions);
284
+ const updateValue = cloneDeep(actionElement.update);
285
+ stripOverlayOnlyStyle(updateValue);
286
+ const result = applyUpdateAction(normalizedPaths, updateValue, workingElement, mutatingOptions);
271
287
  tracer?.action({
272
288
  target: targetExpression,
273
289
  type: 'update',
@@ -17,12 +17,12 @@ const defaultReferenceOptions = {
17
17
  style: true,
18
18
  'overlay-json-1': {
19
19
  sourceMap: true,
20
- style: false,
20
+ style: true,
21
21
  extends: true
22
22
  },
23
23
  'overlay-yaml-1': {
24
24
  sourceMap: true,
25
- style: false,
25
+ style: true,
26
26
  extends: true
27
27
  }
28
28
  }
@@ -47,8 +47,10 @@ const defaultOptions = exports.defaultOptions = {
47
47
  * Applies an overlay document from a file/URL to its target document.
48
48
  *
49
49
  * Parses the overlay, resolves the target from `targetURI` or the overlay's
50
- * `extends` field, parses the target with style preservation for round-trip fidelity,
51
- * and applies all overlay actions.
50
+ * `extends` field, and applies all overlay actions. Both documents are parsed with
51
+ * style preservation for round-trip fidelity, so values added by the overlay are
52
+ * written as they're written in the overlay when both are in the same format.
53
+ * Anchors, aliases and comments in the overlay aren't written to the target.
52
54
  *
53
55
  * @param overlayURI - URI to the overlay document (file path or URL)
54
56
  * @param targetURI - URI to the target document; if omitted, uses the overlay's `extends` field
@@ -10,12 +10,12 @@ const defaultReferenceOptions = {
10
10
  style: true,
11
11
  'overlay-json-1': {
12
12
  sourceMap: true,
13
- style: false,
13
+ style: true,
14
14
  extends: true
15
15
  },
16
16
  'overlay-yaml-1': {
17
17
  sourceMap: true,
18
- style: false,
18
+ style: true,
19
19
  extends: true
20
20
  }
21
21
  }
@@ -40,8 +40,10 @@ export const defaultOptions = {
40
40
  * Applies an overlay document from a file/URL to its target document.
41
41
  *
42
42
  * Parses the overlay, resolves the target from `targetURI` or the overlay's
43
- * `extends` field, parses the target with style preservation for round-trip fidelity,
44
- * and applies all overlay actions.
43
+ * `extends` field, and applies all overlay actions. Both documents are parsed with
44
+ * style preservation for round-trip fidelity, so values added by the overlay are
45
+ * written as they're written in the overlay when both are in the same format.
46
+ * Anchors, aliases and comments in the overlay aren't written to the target.
45
47
  *
46
48
  * @param overlayURI - URI to the overlay document (file path or URL)
47
49
  * @param targetURI - URI to the target document; if omitted, uses the overlay's `extends` field
@@ -5,7 +5,9 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.diff = void 0;
8
+ var _ramda = require("ramda");
8
9
  var _apidomDatamodel = require("@speclynx/apidom-datamodel");
10
+ var _apidomCore = require("@speclynx/apidom-core");
9
11
  var _apidomJsonPath = require("@speclynx/apidom-json-path");
10
12
  var _apidomNsOverlay = require("@speclynx/apidom-ns-overlay-1");
11
13
  var _OverlayError = _interopRequireDefault(require("../../errors/OverlayError.cjs"));
@@ -38,8 +40,12 @@ const createRemoveAction = segments => {
38
40
  action.removeField = new _apidomDatamodel.BooleanElement(true);
39
41
  return action;
40
42
  };
43
+
44
+ // elements are compared by their serialized values, which tell an empty YAML node (null) from an
45
+ // empty string; Element#equals compares the elements' own values, where both are an empty string
46
+ const isEqual = (left, right) => (0, _ramda.equals)((0, _apidomCore.toValue)(left), (0, _apidomCore.toValue)(right));
41
47
  const diffElements = (left, right, segments, actions) => {
42
- if (left.equals(right)) return;
48
+ if (isEqual(left, right)) return;
43
49
  const leftKind = left.primitive();
44
50
  const rightKind = right.primitive();
45
51
  if (leftKind !== rightKind) {
@@ -104,7 +110,7 @@ const diffArrays = (left, right, segments, actions) => {
104
110
  for (let i = 0; i < minLen; i++) {
105
111
  const leftItem = left.get(i);
106
112
  const rightItem = right.get(i);
107
- if (leftItem.equals(rightItem)) continue;
113
+ if (isEqual(leftItem, rightItem)) continue;
108
114
  if (leftItem.primitive() !== rightItem.primitive()) {
109
115
  // structural type change at index i — reconstruct tail:
110
116
  // remove from end down to i (reverse order preserves index stability),
@@ -1,4 +1,6 @@
1
+ import { equals } from 'ramda';
1
2
  import { ObjectElement, ArrayElement, StringElement, BooleanElement, isObjectElement, isArrayElement, cloneDeep } from '@speclynx/apidom-datamodel';
3
+ import { toValue } from '@speclynx/apidom-core';
2
4
  import { NormalizedPath } from '@speclynx/apidom-json-path';
3
5
  import { ActionElement, Overlay1Element, InfoElement, OverlayElement, ActionsElement } from '@speclynx/apidom-ns-overlay-1';
4
6
  import OverlayError from "../../errors/OverlayError.mjs";
@@ -30,8 +32,12 @@ const createRemoveAction = segments => {
30
32
  action.removeField = new BooleanElement(true);
31
33
  return action;
32
34
  };
35
+
36
+ // elements are compared by their serialized values, which tell an empty YAML node (null) from an
37
+ // empty string; Element#equals compares the elements' own values, where both are an empty string
38
+ const isEqual = (left, right) => equals(toValue(left), toValue(right));
33
39
  const diffElements = (left, right, segments, actions) => {
34
- if (left.equals(right)) return;
40
+ if (isEqual(left, right)) return;
35
41
  const leftKind = left.primitive();
36
42
  const rightKind = right.primitive();
37
43
  if (leftKind !== rightKind) {
@@ -96,7 +102,7 @@ const diffArrays = (left, right, segments, actions) => {
96
102
  for (let i = 0; i < minLen; i++) {
97
103
  const leftItem = left.get(i);
98
104
  const rightItem = right.get(i);
99
- if (leftItem.equals(rightItem)) continue;
105
+ if (isEqual(leftItem, rightItem)) continue;
100
106
  if (leftItem.primitive() !== rightItem.primitive()) {
101
107
  // structural type change at index i — reconstruct tail:
102
108
  // remove from end down to i (reverse order preserves index stability),
@@ -65,8 +65,10 @@ export declare interface ApplyOptions {
65
65
  * Applies an overlay document from a file/URL to its target document.
66
66
  *
67
67
  * Parses the overlay, resolves the target from `targetURI` or the overlay's
68
- * `extends` field, parses the target with style preservation for round-trip fidelity,
69
- * and applies all overlay actions.
68
+ * `extends` field, and applies all overlay actions. Both documents are parsed with
69
+ * style preservation for round-trip fidelity, so values added by the overlay are
70
+ * written as they're written in the overlay when both are in the same format.
71
+ * Anchors, aliases and comments in the overlay aren't written to the target.
70
72
  *
71
73
  * @param overlayURI - URI to the overlay document (file path or URL)
72
74
  * @param targetURI - URI to the target document; if omitted, uses the overlay's `extends` field