fork of hey-api/openapi-ts because I need some additional things
at feat/skip-token 91 lines 2.4 kB view raw
1import type { StructureItem, StructureShell } from './types'; 2 3export class StructureNode { 4 /** Nested nodes within this node. */ 5 children: Map<string, StructureNode> = new Map(); 6 /** Items contained in this node. */ 7 items: Array<StructureItem> = []; 8 /** The name of this node (e.g., "Users", "Accounts"). */ 9 name: string; 10 /** Parent node in the hierarchy. Undefined if this is the root node. */ 11 parent?: StructureNode; 12 /** Shell claimed for this node. */ 13 shell?: StructureShell; 14 /** Source of the claimed shell. */ 15 shellSource?: symbol; 16 /** True if this is a virtual root. */ 17 virtual: boolean; 18 19 constructor( 20 name: string, 21 parent?: StructureNode, 22 options?: { 23 virtual?: boolean; 24 }, 25 ) { 26 this.name = name; 27 this.parent = parent; 28 this.virtual = options?.virtual ?? false; 29 } 30 31 get isRoot(): boolean { 32 return !this.parent; 33 } 34 35 /** 36 * Gets or creates a child node. 37 * 38 * If the child doesn't exist, it's created automatically. 39 * 40 * @param name - The name of the child node 41 * @returns The child node instance 42 */ 43 child(name: string): StructureNode { 44 if (!this.children.has(name)) { 45 this.children.set(name, new StructureNode(name, this)); 46 } 47 return this.children.get(name)!; 48 } 49 50 /** 51 * Gets the full path of this node in the hierarchy. 52 * 53 * @returns An array of node names from the root to this node 54 */ 55 getPath(): ReadonlyArray<string> { 56 const path: Array<string> = []; 57 // eslint-disable-next-line @typescript-eslint/no-this-alias 58 let cursor: StructureNode | undefined = this; 59 while (cursor) { 60 path.unshift(cursor.name); 61 cursor = cursor.parent; 62 } 63 return path; 64 } 65 66 /** 67 * Yields items from a specific source with typed data. 68 * 69 * @param source - The source symbol to filter by 70 * @returns Generator of items from that source 71 */ 72 *itemsFrom<T = unknown>(source: symbol): Generator<StructureItem & { data: T }> { 73 for (const item of this.items) { 74 if (item.source === source) { 75 yield item as StructureItem & { data: T }; 76 } 77 } 78 } 79 80 /** 81 * Walk all nodes in the structure (depth-first, post-order). 82 * 83 * @returns Generator of all structure nodes 84 */ 85 *walk(): Generator<StructureNode> { 86 for (const node of this.children.values()) { 87 yield* node.walk(); 88 } 89 yield this; 90 } 91}