@speclynx/apidom-traverse 3.2.1 → 4.0.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/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [4.0.0](https://github.com/speclynx/apidom/compare/v3.2.1...v4.0.0) (2026-03-11)
7
+
8
+ ### Features
9
+
10
+ - **traverse:** all traverse operations work on Path and not Element ([#153](https://github.com/speclynx/apidom/issues/153)) ([67d244c](https://github.com/speclynx/apidom/commit/67d244cfd3e77f6a9db704cede50ba8e45d10b11))
11
+
12
+ ### BREAKING CHANGES
13
+
14
+ - **traverse:** This is a breaking change as operation callbacks
15
+ now accept Path instead of Element. By accepting Path, full
16
+ context of traversal is exposed to consumer instead of just Element.
17
+
6
18
  ## [3.2.1](https://github.com/speclynx/apidom/compare/v3.2.0...v3.2.1) (2026-03-09)
7
19
 
8
20
  **Note:** Version bump only for package @speclynx/apidom-traverse
package/README.md CHANGED
@@ -58,7 +58,7 @@ All operations use **data-first** signatures: the element comes before the predi
58
58
 
59
59
  ### filter
60
60
 
61
- Finds all elements matching the predicate.
61
+ Finds all paths whose elements match the predicate.
62
62
 
63
63
  ```js
64
64
  import { ObjectElement, isNumberElement } from '@speclynx/apidom-datamodel';
@@ -66,12 +66,14 @@ import { filter } from '@speclynx/apidom-traverse';
66
66
 
67
67
  const element = new ObjectElement({ a: 'b', c: 2 });
68
68
 
69
- filter(element, isNumberElement); // => [NumberElement<2>]
69
+ const paths = filter(element, (path) => isNumberElement(path.node)); // => [Path<NumberElement<2>>]
70
+ paths[0].node; // => NumberElement<2>
71
+ paths[0].formatPath(); // => '/c'
70
72
  ```
71
73
 
72
74
  ### find
73
75
 
74
- Find first element that satisfies the provided predicate.
76
+ Finds first path whose element satisfies the provided predicate.
75
77
 
76
78
  ```js
77
79
  import { ObjectElement, isNumberElement } from '@speclynx/apidom-datamodel';
@@ -79,24 +81,29 @@ import { find } from '@speclynx/apidom-traverse';
79
81
 
80
82
  const element = new ObjectElement({ a: 'b', c: 2 });
81
83
 
82
- find(element, isNumberElement); // => NumberElement<2>
84
+ const path = find(element, (path) => isNumberElement(path.node)); // => Path<NumberElement<2>>
85
+ path.node; // => NumberElement<2>
86
+ path.formatPath(); // => '/c'
83
87
  ```
84
88
 
85
89
  ### findAtOffset
86
90
 
87
- ApiDOM nodes can be associated with source maps. This function finds the most inner node at the given offset.
91
+ ApiDOM nodes can be associated with source maps. This function finds the path of the most inner node at the given offset.
88
92
  If includeRightBound is set, also finds nodes that end at the given offset.
89
93
 
90
94
  ```js
91
95
  import { findAtOffset } from '@speclynx/apidom-traverse';
92
96
 
93
- findAtOffset(elementWithSourceMaps, 3); // => returns most inner node at offset 3
97
+ const path = findAtOffset(elementWithSourceMaps, 3); // => Path of most inner node at offset 3
98
+ path.node; // => the element at that offset
99
+ path.formatPath(); // => JSON Pointer to the element
100
+
94
101
  findAtOffset(elementWithSourceMaps, { offset: 3, includeRightBound: true });
95
102
  ```
96
103
 
97
104
  ### reject
98
105
 
99
- Complement of [filter](#filter). Finds all elements NOT matching the predicate.
106
+ Complement of [filter](#filter). Finds all paths whose elements do NOT match the predicate.
100
107
 
101
108
  ```js
102
109
  import { ArrayElement, isNumberElement } from '@speclynx/apidom-datamodel';
@@ -104,12 +111,13 @@ import { reject } from '@speclynx/apidom-traverse';
104
111
 
105
112
  const element = new ArrayElement([1, 'a']);
106
113
 
107
- reject(element, isNumberElement); // => [ArrayElement, StringElement<'a'>]
114
+ const paths = reject(element, (path) => isNumberElement(path.node)); // => [Path<ArrayElement>, Path<StringElement<'a'>>]
115
+ paths.map((p) => p.node); // => [ArrayElement, StringElement<'a'>]
108
116
  ```
109
117
 
110
118
  ### some
111
119
 
112
- Tests whether at least one element passes the predicate.
120
+ Tests whether at least one path's element passes the predicate.
113
121
 
114
122
  ```js
115
123
  import { ArrayElement, isNumberElement } from '@speclynx/apidom-datamodel';
@@ -117,12 +125,12 @@ import { some } from '@speclynx/apidom-traverse';
117
125
 
118
126
  const element = new ArrayElement([1, 'a']);
119
127
 
120
- some(element, isNumberElement); // => true
128
+ some(element, (path) => isNumberElement(path.node)); // => true
121
129
  ```
122
130
 
123
131
  ### forEach
124
132
 
125
- Executes the callback on this element and all descendants.
133
+ Executes the callback on this element's path and all descendant paths.
126
134
 
127
135
  ```js
128
136
  import { ArrayElement } from '@speclynx/apidom-datamodel';
@@ -130,7 +138,7 @@ import { forEach } from '@speclynx/apidom-traverse';
130
138
 
131
139
  const element = new ArrayElement([1, 'a']);
132
140
 
133
- forEach(element, console.dir); // => prints ArrayElement, NumberElement, StringElement in this order
141
+ forEach(element, (path) => console.dir(path.node)); // => prints ArrayElement, NumberElement, StringElement
134
142
  ```
135
143
 
136
144
  The execution of the callback can be controlled further by providing a predicate.
@@ -141,7 +149,10 @@ import { forEach } from '@speclynx/apidom-traverse';
141
149
 
142
150
  const element = new ArrayElement([1, 'a']);
143
151
 
144
- forEach(element, { callback: console.dir, predicate: isNumberElement }); // => prints NumberElement<1>
152
+ forEach(element, {
153
+ callback: (path) => console.dir(path.node),
154
+ predicate: (path) => isNumberElement(path.node),
155
+ }); // => prints NumberElement<1>
145
156
  ```
146
157
 
147
158
  ### parents
@@ -170,7 +170,9 @@ class Path {
170
170
  *
171
171
  * @example
172
172
  * // For a path to $.paths['/pets'].get in an OpenAPI document:
173
+ * ```
173
174
  * path.getPathKeys(); // => ['paths', '/pets', 'get']
175
+ * ```
174
176
  */
175
177
  getPathKeys() {
176
178
  const keys = [];
@@ -205,18 +207,22 @@ class Path {
205
207
  * or Normalized JSONPath like "$['paths']['/pets']['get']['responses']['200']"
206
208
  *
207
209
  * @example
210
+ * ```
208
211
  * // JSON Pointer examples:
209
212
  * path.formatPath(); // "" (root)
210
213
  * path.formatPath(); // "/info"
211
214
  * path.formatPath(); // "/paths/~1pets/get"
212
215
  * path.formatPath(); // "/paths/~1users~1{id}/parameters/0"
216
+ * ```
213
217
  *
214
218
  * @example
219
+ * ```
215
220
  * // JSONPath examples:
216
221
  * path.formatPath('jsonpath'); // "$" (root)
217
222
  * path.formatPath('jsonpath'); // "$['info']"
218
223
  * path.formatPath('jsonpath'); // "$['paths']['/pets']['get']"
219
224
  * path.formatPath('jsonpath'); // "$['paths']['/users/{id}']['parameters'][0]"
225
+ * ```
220
226
  */
221
227
  formatPath(pathFormat = 'jsonpointer') {
222
228
  const parts = this.getPathKeys();
@@ -367,15 +373,15 @@ __webpack_require__.r(__webpack_exports__);
367
373
  /* harmony import */ var _traversal_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9761);
368
374
 
369
375
  /**
370
- * Finds all elements matching the predicate.
376
+ * Finds all paths whose elements match the predicate.
371
377
  * @public
372
378
  */
373
379
  const filter = (element, predicate) => {
374
380
  const result = [];
375
381
  (0,_traversal_ts__WEBPACK_IMPORTED_MODULE_0__.traverse)(element, {
376
382
  enter(path) {
377
- if (predicate(path.node)) {
378
- result.push(path.node);
383
+ if (predicate(path)) {
384
+ result.push(path);
379
385
  }
380
386
  }
381
387
  });
@@ -402,7 +408,7 @@ __webpack_require__.r(__webpack_exports__);
402
408
  */
403
409
 
404
410
  /**
405
- * Finds the most inner node at the given offset.
411
+ * Finds the path of the most inner node at the given offset.
406
412
  * If includeRightBound is set, also finds nodes that end at the given offset.
407
413
  * @public
408
414
  */
@@ -427,7 +433,7 @@ const findAtOffset = (element, options) => {
427
433
  const endOffset = node.endOffset;
428
434
  const isWithinOffsetRange = offset >= startOffset && (offset < endOffset || includeRightBound && offset <= endOffset);
429
435
  if (isWithinOffsetRange) {
430
- result.push(node);
436
+ result.push(path);
431
437
  return; // push to stack and dive in
432
438
  }
433
439
  path.skip(); // skip entire sub-tree
@@ -449,15 +455,15 @@ __webpack_require__.r(__webpack_exports__);
449
455
  /* harmony import */ var _traversal_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9761);
450
456
 
451
457
  /**
452
- * Find first element that satisfies the provided predicate.
458
+ * Finds first path whose element satisfies the provided predicate.
453
459
  * @public
454
460
  */
455
461
  const find = (element, predicate) => {
456
462
  let result;
457
463
  (0,_traversal_ts__WEBPACK_IMPORTED_MODULE_0__.traverse)(element, {
458
464
  enter(path) {
459
- if (predicate(path.node)) {
460
- result = path.node;
465
+ if (predicate(path)) {
466
+ result = path;
461
467
  path.stop();
462
468
  }
463
469
  }
@@ -475,9 +481,7 @@ __webpack_require__.r(__webpack_exports__);
475
481
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
476
482
  /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
477
483
  /* harmony export */ });
478
- /* harmony import */ var _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5162);
479
- /* harmony import */ var _traversal_ts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9761);
480
-
484
+ /* harmony import */ var _traversal_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9761);
481
485
 
482
486
 
483
487
  /**
@@ -489,7 +493,7 @@ __webpack_require__.r(__webpack_exports__);
489
493
  */
490
494
 
491
495
  /**
492
- * Executes the callback on this element and all descendants.
496
+ * Executes the callback on this element's path and all descendant paths.
493
497
  * @public
494
498
  */
495
499
  const forEach = (element, options) => {
@@ -497,15 +501,15 @@ const forEach = (element, options) => {
497
501
  let predicate;
498
502
  if (typeof options === 'function') {
499
503
  callback = options;
500
- predicate = _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_0__.isElement;
504
+ predicate = () => true;
501
505
  } else {
502
506
  callback = options.callback ?? (() => {});
503
- predicate = options.predicate ?? _speclynx_apidom_datamodel__WEBPACK_IMPORTED_MODULE_0__.isElement;
507
+ predicate = options.predicate ?? (() => true);
504
508
  }
505
- (0,_traversal_ts__WEBPACK_IMPORTED_MODULE_1__.traverse)(element, {
509
+ (0,_traversal_ts__WEBPACK_IMPORTED_MODULE_0__.traverse)(element, {
506
510
  enter(path) {
507
- if (predicate(path.node)) {
508
- callback(path.node);
511
+ if (predicate(path)) {
512
+ callback(path);
509
513
  }
510
514
  }
511
515
  });
@@ -551,13 +555,12 @@ __webpack_require__.r(__webpack_exports__);
551
555
  /* harmony export */ });
552
556
  /* harmony import */ var _filter_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(706);
553
557
 
554
-
555
558
  /**
556
- * Complement of filter. Finds all elements NOT matching the predicate.
559
+ * Complement of filter. Finds all paths whose elements do NOT match the predicate.
557
560
  * @public
558
561
  */
559
562
  const reject = (element, predicate) => {
560
- return (0,_filter_ts__WEBPACK_IMPORTED_MODULE_0__["default"])(element, el => !predicate(el));
563
+ return (0,_filter_ts__WEBPACK_IMPORTED_MODULE_0__["default"])(element, path => !predicate(path));
561
564
  };
562
565
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (reject);
563
566
 
@@ -572,9 +575,8 @@ __webpack_require__.r(__webpack_exports__);
572
575
  /* harmony export */ });
573
576
  /* harmony import */ var _find_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9068);
574
577
 
575
-
576
578
  /**
577
- * Tests whether at least one element passes the predicate.
579
+ * Tests whether at least one path's element passes the predicate.
578
580
  * @public
579
581
  */
580
582
  const some = (element, predicate) => {