@speclynx/apidom-traverse 3.2.0 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@speclynx/apidom-traverse",
3
- "version": "3.2.0",
3
+ "version": "4.0.0",
4
4
  "description": "Traversal and visitor utilities for walking and transforming ApiDOM structures.",
5
5
  "keywords": [
6
6
  "apidom",
@@ -61,10 +61,10 @@
61
61
  "license": "Apache-2.0",
62
62
  "dependencies": {
63
63
  "@babel/runtime-corejs3": "^7.28.4",
64
- "@speclynx/apidom-datamodel": "3.2.0",
65
- "@speclynx/apidom-error": "3.2.0",
66
- "@speclynx/apidom-json-path": "3.2.0",
67
- "@speclynx/apidom-json-pointer": "3.2.0",
64
+ "@speclynx/apidom-datamodel": "4.0.0",
65
+ "@speclynx/apidom-error": "4.0.0",
66
+ "@speclynx/apidom-json-path": "4.0.0",
67
+ "@speclynx/apidom-json-pointer": "4.0.0",
68
68
  "ramda-adjunct": "^6.0.0"
69
69
  },
70
70
  "files": [
@@ -77,5 +77,5 @@
77
77
  "README.md",
78
78
  "CHANGELOG.md"
79
79
  ],
80
- "gitHead": "eeb2f01cd34fb0a95617f02bc1b6683aefc028f2"
80
+ "gitHead": "384ff82a1bb68d015fd6801de641898b4b582876"
81
81
  }
@@ -8,23 +8,23 @@ import { Element as Element_2 } from '@speclynx/apidom-datamodel';
8
8
  export declare const cloneNode: <TNode>(node: TNode) => TNode;
9
9
 
10
10
  /**
11
- * Finds all elements matching the predicate.
11
+ * Finds all paths whose elements match the predicate.
12
12
  * @public
13
13
  */
14
- export declare const filter: <T extends Element_2>(element: T, predicate: (element: Element_2) => boolean) => Element_2[];
14
+ export declare const filter: <T extends Element_2>(element: T, predicate: (path: Path<Element_2>) => boolean) => Path<Element_2>[];
15
15
 
16
16
  /**
17
- * Find first element that satisfies the provided predicate.
17
+ * Finds first path whose element satisfies the provided predicate.
18
18
  * @public
19
19
  */
20
- export declare const find: <T extends Element_2>(element: T, predicate: (element: Element_2) => boolean) => Element_2 | undefined;
20
+ export declare const find: <T extends Element_2>(element: T, predicate: (path: Path<Element_2>) => boolean) => Path<Element_2> | undefined;
21
21
 
22
22
  /**
23
- * Finds the most inner node at the given offset.
23
+ * Finds the path of the most inner node at the given offset.
24
24
  * If includeRightBound is set, also finds nodes that end at the given offset.
25
25
  * @public
26
26
  */
27
- export declare const findAtOffset: <T extends Element_2>(element: T, options: number | FindAtOffsetOptions) => T | undefined;
27
+ export declare const findAtOffset: <T extends Element_2>(element: T, options: number | FindAtOffsetOptions) => Path<Element_2> | undefined;
28
28
 
29
29
  /**
30
30
  * @public
@@ -35,7 +35,7 @@ export declare interface FindAtOffsetOptions {
35
35
  }
36
36
 
37
37
  /**
38
- * Executes the callback on this element and all descendants.
38
+ * Executes the callback on this element's path and all descendant paths.
39
39
  * @public
40
40
  */
41
41
  export declare const forEach: <T extends Element_2>(element: T, options: ForEachCallback | ForEachOptions) => void;
@@ -43,14 +43,14 @@ export declare const forEach: <T extends Element_2>(element: T, options: ForEach
43
43
  /**
44
44
  * @public
45
45
  */
46
- export declare type ForEachCallback = <T extends Element_2>(element: T) => void;
46
+ export declare type ForEachCallback = (path: Path<Element_2>) => void;
47
47
 
48
48
  /**
49
49
  * @public
50
50
  */
51
51
  export declare interface ForEachOptions {
52
52
  callback?: ForEachCallback;
53
- predicate?: (element: Element_2) => boolean;
53
+ predicate?: (path: Path<Element_2>) => boolean;
54
54
  }
55
55
 
56
56
  /**
@@ -232,7 +232,9 @@ export declare class Path<TNode = Element_2> {
232
232
  *
233
233
  * @example
234
234
  * // For a path to $.paths['/pets'].get in an OpenAPI document:
235
+ * ```
235
236
  * path.getPathKeys(); // => ['paths', '/pets', 'get']
237
+ * ```
236
238
  */
237
239
  getPathKeys(): PropertyKey[];
238
240
  /**
@@ -243,18 +245,22 @@ export declare class Path<TNode = Element_2> {
243
245
  * or Normalized JSONPath like "$['paths']['/pets']['get']['responses']['200']"
244
246
  *
245
247
  * @example
248
+ * ```
246
249
  * // JSON Pointer examples:
247
250
  * path.formatPath(); // "" (root)
248
251
  * path.formatPath(); // "/info"
249
252
  * path.formatPath(); // "/paths/~1pets/get"
250
253
  * path.formatPath(); // "/paths/~1users~1{id}/parameters/0"
254
+ * ```
251
255
  *
252
256
  * @example
257
+ * ```
253
258
  * // JSONPath examples:
254
259
  * path.formatPath('jsonpath'); // "$" (root)
255
260
  * path.formatPath('jsonpath'); // "$['info']"
256
261
  * path.formatPath('jsonpath'); // "$['paths']['/pets']['get']"
257
262
  * path.formatPath('jsonpath'); // "$['paths']['/users/{id}']['parameters'][0]"
263
+ * ```
258
264
  */
259
265
  formatPath(pathFormat?: 'jsonpointer' | 'jsonpath'): string;
260
266
  /**
@@ -310,16 +316,16 @@ export declare class Path<TNode = Element_2> {
310
316
  }
311
317
 
312
318
  /**
313
- * Complement of filter. Finds all elements NOT matching the predicate.
319
+ * Complement of filter. Finds all paths whose elements do NOT match the predicate.
314
320
  * @public
315
321
  */
316
- export declare const reject: <T extends Element_2>(element: T, predicate: (element: Element_2) => boolean) => Element_2[];
322
+ export declare const reject: <T extends Element_2>(element: T, predicate: (path: Path<Element_2>) => boolean) => Path<Element_2>[];
317
323
 
318
324
  /**
319
- * Tests whether at least one element passes the predicate.
325
+ * Tests whether at least one path's element passes the predicate.
320
326
  * @public
321
327
  */
322
- export declare const some: <T extends Element_2>(element: T, predicate: (element: Element_2) => boolean) => boolean;
328
+ export declare const some: <T extends Element_2>(element: T, predicate: (path: Path<Element_2>) => boolean) => boolean;
323
329
 
324
330
  /**
325
331
  * traverse() walks through a tree using preorder depth-first traversal, calling
package/src/Path.cjs DELETED
@@ -1,336 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.Path = void 0;
5
- var _apidomDatamodel = require("@speclynx/apidom-datamodel");
6
- var _apidomJsonPointer = require("@speclynx/apidom-json-pointer");
7
- var _apidomJsonPath = require("@speclynx/apidom-json-path");
8
- /**
9
- * Possible return values from a visitor function.
10
- * @public
11
- */
12
-
13
- /**
14
- * Visitor function signature - receives a Path object.
15
- * @public
16
- */
17
-
18
- /**
19
- * Path represents a node's position in the tree during traversal.
20
- * Inspired by Babel's NodePath API.
21
- * @public
22
- */
23
- class Path {
24
- /**
25
- * The current AST node.
26
- */
27
- node;
28
-
29
- /**
30
- * The key of this node in its parent.
31
- * `undefined` for the root node.
32
- */
33
- key;
34
-
35
- /**
36
- * The index if this node is in an array.
37
- * Same as `key` when parent property is an array, `undefined` otherwise.
38
- */
39
- index;
40
-
41
- /**
42
- * The parent node.
43
- * `undefined` for the root node.
44
- */
45
- parent;
46
-
47
- /**
48
- * The parent Path.
49
- * `null` for the root node.
50
- */
51
- parentPath;
52
-
53
- /**
54
- * Whether this node is inside an array in the parent.
55
- */
56
- inList;
57
-
58
- /**
59
- * Internal state for traversal control.
60
- */
61
- #shouldSkip = false;
62
- #shouldStop = false;
63
- #removed = false;
64
- #replaced = false;
65
- #replacementNode;
66
- #stale = false;
67
- constructor(node, parent, parentPath, key, inList) {
68
- this.node = node;
69
- this.parent = parent;
70
- this.parentPath = parentPath;
71
- this.key = key;
72
- this.index = inList && typeof key === 'number' ? key : undefined;
73
- this.inList = inList;
74
- }
75
-
76
- // ===========================================================================
77
- // Traversal state
78
- // ===========================================================================
79
-
80
- /**
81
- * Whether skip() was called on this path.
82
- */
83
- get shouldSkip() {
84
- return this.#shouldSkip;
85
- }
86
-
87
- /**
88
- * Whether stop() was called on this path.
89
- */
90
- get shouldStop() {
91
- return this.#shouldStop;
92
- }
93
-
94
- /**
95
- * Whether this node was removed.
96
- */
97
- get removed() {
98
- return this.#removed;
99
- }
100
-
101
- // ===========================================================================
102
- // Ancestry
103
- // ===========================================================================
104
-
105
- /**
106
- * Returns true if this is the root path.
107
- */
108
- isRoot() {
109
- return this.parentPath === null;
110
- }
111
-
112
- /**
113
- * Get the depth of this path (0 for root).
114
- */
115
- get depth() {
116
- let depth = 0;
117
- let current = this.parentPath;
118
- while (current !== null) {
119
- depth += 1;
120
- current = current.parentPath;
121
- }
122
- return depth;
123
- }
124
-
125
- /**
126
- * Get all ancestor paths from immediate parent to root.
127
- */
128
- getAncestry() {
129
- const ancestry = [];
130
- let current = this.parentPath;
131
- while (current !== null) {
132
- ancestry.push(current);
133
- current = current.parentPath;
134
- }
135
- return ancestry;
136
- }
137
-
138
- /**
139
- * Get all ancestor nodes from immediate parent to root.
140
- */
141
- getAncestorNodes() {
142
- return this.getAncestry().map(p => p.node);
143
- }
144
-
145
- /**
146
- * Get the semantic path from root as an array of keys.
147
- * Returns logical document keys (property names, array indices) rather than
148
- * internal ApiDOM structure keys.
149
- *
150
- * @example
151
- * // For a path to $.paths['/pets'].get in an OpenAPI document:
152
- * path.getPathKeys(); // => ['paths', '/pets', 'get']
153
- */
154
- getPathKeys() {
155
- const keys = [];
156
- // eslint-disable-next-line @typescript-eslint/no-this-alias
157
- let current = this;
158
- while (current !== null && current.key !== undefined) {
159
- const {
160
- key,
161
- parent,
162
- parentPath
163
- } = current;
164
- if ((0, _apidomDatamodel.isMemberElement)(parent) && key === 'value') {
165
- // Inside MemberElement.value → push the member's key
166
- if (!(0, _apidomDatamodel.isStringElement)(parent.key)) {
167
- throw new TypeError('MemberElement.key must be a StringElement');
168
- }
169
- keys.unshift(parent.key.toValue());
170
- } else if ((0, _apidomDatamodel.isArrayElement)(parentPath?.node) && typeof key === 'number') {
171
- // Inside ArrayElement → push the numeric index
172
- keys.unshift(key);
173
- }
174
- current = current.parentPath;
175
- }
176
- return keys;
177
- }
178
-
179
- /**
180
- * Format path as RFC 6901 JSON Pointer or RFC 9535 Normalized JSONPath.
181
- *
182
- * @param pathFormat - Output format: "jsonpointer" (default) or "jsonpath"
183
- * @returns JSONPointer string like "/paths/~1pets/get/responses/200"
184
- * or Normalized JSONPath like "$['paths']['/pets']['get']['responses']['200']"
185
- *
186
- * @example
187
- * // JSON Pointer examples:
188
- * path.formatPath(); // "" (root)
189
- * path.formatPath(); // "/info"
190
- * path.formatPath(); // "/paths/~1pets/get"
191
- * path.formatPath(); // "/paths/~1users~1{id}/parameters/0"
192
- *
193
- * @example
194
- * // JSONPath examples:
195
- * path.formatPath('jsonpath'); // "$" (root)
196
- * path.formatPath('jsonpath'); // "$['info']"
197
- * path.formatPath('jsonpath'); // "$['paths']['/pets']['get']"
198
- * path.formatPath('jsonpath'); // "$['paths']['/users/{id}']['parameters'][0]"
199
- */
200
- formatPath(pathFormat = 'jsonpointer') {
201
- const parts = this.getPathKeys();
202
-
203
- // Root node
204
- if (parts.length === 0) {
205
- return pathFormat === 'jsonpath' ? '$' : '';
206
- }
207
- if (pathFormat === 'jsonpath') {
208
- // RFC 9535 Normalized JSONPath
209
- return _apidomJsonPath.NormalizedPath.from(parts);
210
- }
211
-
212
- // RFC 6901 JSON Pointer
213
- return (0, _apidomJsonPointer.compile)(parts);
214
- }
215
-
216
- /**
217
- * Find the closest ancestor path that satisfies the predicate.
218
- */
219
- findParent(predicate) {
220
- let current = this.parentPath;
221
- while (current !== null) {
222
- if (predicate(current)) {
223
- return current;
224
- }
225
- current = current.parentPath;
226
- }
227
- return null;
228
- }
229
-
230
- /**
231
- * Find the closest path (including this one) that satisfies the predicate.
232
- */
233
- find(predicate) {
234
- if (predicate(this)) {
235
- return this;
236
- }
237
- return this.findParent(predicate);
238
- }
239
-
240
- // ===========================================================================
241
- // Nested traversal
242
- // ===========================================================================
243
-
244
- /**
245
- * Traverse into the current node with a new visitor.
246
- * Populated by the traversal module to avoid circular imports.
247
- */
248
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
249
-
250
- /**
251
- * Async version of traverse.
252
- */
253
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
254
-
255
- // ===========================================================================
256
- // Traversal control
257
- // ===========================================================================
258
-
259
- /**
260
- * Skip traversing the children of this node.
261
- */
262
- skip() {
263
- this.#shouldSkip = true;
264
- }
265
-
266
- /**
267
- * Stop all traversal completely.
268
- */
269
- stop() {
270
- this.#shouldStop = true;
271
- }
272
-
273
- // ===========================================================================
274
- // Modification
275
- // ===========================================================================
276
-
277
- /**
278
- * Replace this node with a new node.
279
- */
280
- replaceWith(replacement) {
281
- if (this.#stale) {
282
- console.warn('Warning: replaceWith() called on a stale Path. ' + 'This path belongs to a node whose visit has already completed. ' + 'The replacement will have no effect. ' + "To replace a parent node, do so from the parent's own visitor.");
283
- }
284
- this.#replaced = true;
285
- this.#replacementNode = replacement;
286
- this.node = replacement;
287
- }
288
-
289
- /**
290
- * Remove this node from the tree.
291
- */
292
- remove() {
293
- if (this.#stale) {
294
- console.warn('Warning: remove() called on a stale Path. ' + 'This path belongs to a node whose visit has already completed. ' + 'The removal will have no effect. ' + "To remove a parent node, do so from the parent's own visitor.");
295
- }
296
- this.#removed = true;
297
- }
298
-
299
- // ===========================================================================
300
- // Internal methods for traversal engine
301
- // ===========================================================================
302
-
303
- /**
304
- * @internal
305
- */
306
- _getReplacementNode() {
307
- return this.#replacementNode;
308
- }
309
-
310
- /**
311
- * @internal
312
- */
313
- _wasReplaced() {
314
- return this.#replaced;
315
- }
316
-
317
- /**
318
- * @internal
319
- */
320
- _reset() {
321
- this.#shouldSkip = false;
322
- this.#shouldStop = false;
323
- this.#removed = false;
324
- this.#replaced = false;
325
- this.#replacementNode = undefined;
326
- }
327
-
328
- /**
329
- * Mark this path as stale (visit completed).
330
- * @internal
331
- */
332
- _markStale() {
333
- this.#stale = true;
334
- }
335
- }
336
- exports.Path = Path;