|
1 | | -import { JsonPath } from '@stoplight/types'; |
2 | | - |
3 | | -export const traverse = ( |
4 | | - obj: unknown, |
5 | | - func: (opts: { parent: unknown; parentPath: JsonPath; property: string | number; propertyValue: unknown }) => void, |
6 | | - path: JsonPath = [], |
7 | | -) => { |
8 | | - if (!obj || typeof obj !== 'object') return; |
9 | | - |
10 | | - for (const i in obj) { |
11 | | - if (!obj.hasOwnProperty(i)) continue; |
12 | | - func({ parent: obj, parentPath: path, property: i, propertyValue: obj[i] }); |
13 | | - if (obj[i] && typeof obj[i] === 'object') { |
14 | | - traverse(obj[i], func, path.concat(i)); |
| 1 | +import { JsonPath, Segment } from '@stoplight/types'; |
| 2 | + |
| 3 | +type Hooks = { |
| 4 | + onEnter(ctx: Readonly<{ value: object; path: JsonPath }>): void; |
| 5 | + onLeave(ctx: Readonly<{ value: object; path: JsonPath }>): void; |
| 6 | + onProperty(ctx: Readonly<{ parent: object; parentPath: JsonPath; property: Segment; propertyValue: unknown }>): void; |
| 7 | +}; |
| 8 | + |
| 9 | +const _traverse = (obj: object, hooks: Partial<Hooks>, path: JsonPath) => { |
| 10 | + const ctx = { value: obj, path }; |
| 11 | + |
| 12 | + if (hooks.onEnter) { |
| 13 | + hooks.onEnter(ctx); |
| 14 | + } |
| 15 | + |
| 16 | + for (const i of Object.keys(obj)) { |
| 17 | + const value = obj[i]; |
| 18 | + |
| 19 | + if (hooks.onProperty) { |
| 20 | + hooks.onProperty({ parent: obj, parentPath: path, property: i, propertyValue: value }); |
15 | 21 | } |
| 22 | + |
| 23 | + if (typeof value === 'object' && value !== null) { |
| 24 | + _traverse(value, hooks, path.concat(i)); |
| 25 | + } |
| 26 | + } |
| 27 | + |
| 28 | + if (hooks.onLeave) { |
| 29 | + hooks.onLeave(ctx); |
| 30 | + } |
| 31 | +}; |
| 32 | + |
| 33 | +export const traverse = (obj: unknown, hooks: Partial<Hooks> | Hooks['onProperty']) => { |
| 34 | + if (typeof obj === 'object' && obj !== null) { |
| 35 | + _traverse(obj, typeof hooks === 'function' ? { onProperty: hooks } : hooks, []); |
16 | 36 | } |
17 | 37 | }; |
0 commit comments