import type { Plugin } from '@servicenow/sdk-build-core'; import type { Project } from '../../project'; type Via = { type: 'string'; value: string; } | { type: 'object'; value: Record; } | { type: 'regex'; value: { parent: [string, string]; child: [string, string]; }[]; } | { type: 'unknown'; value: unknown; }; /** * Represents a descendant relationship in the hierarchy tree with metadata. * Includes node identification, relationship type, and potential cyclic references. */ type DescendantRelationship = { nodeId: string; table: string; via: Via; inverse: boolean; composite: boolean; cycleTargetNodeId?: string; cyclicReferences?: string[]; relationships?: DescendantRelationships; }; /** * A map of descendant table names to their relationship metadata. */ type DescendantRelationships = { [descendantTable: string]: DescendantRelationship; }; /** * Represents the complete relationship hierarchy for a given table. * @template T - The table name type */ export type RelationshipHierarchy = Record; /** * Collects every table name in a relationship hierarchy (the root plus all * descendants, recursively). */ export declare function collectTablesFromHierarchy(hierarchy: RelationshipHierarchy): Set; /** * Returns root tables for a plugin — tables from getTables() that are not * marked as descendants in any relationship. */ export declare function getRootTables(plugin: Plugin): Set; /** * Resolves and manages table relationships spread across plugins. * Builds hierarchical relationship trees, detects cycles, and identifies root tables. */ export declare class RelationshipResolver { private readonly project; private readonly descendantParents; private readonly parentDescendantRelations; private readonly pluginRoots; private nodeIdCounter; /** * Creates a new RelationshipResolver instance. * @param project - The project containing the table relationships to resolve */ constructor(project: Project); /** * Generates a unique node identifier for the relationship tree. * @returns A unique node ID string */ private generateNodeId; /** * Initializes the resolver by processing all relationships from project plugins. * Populates internal maps tracking parent-descendant relationships. * Also identifies plugin entry-point tables: tables with toShape that are not * descendants within that same plugin. These are treated as roots even if * another plugin claims them as descendants. */ private init; /** * Normalizes the 'via' field of a relationship into a consistent format. * @param via - The relationship via field (string, object, or regex) * @returns A normalized Via object with type and value */ private normalizeVia; private isComposite; /** * Recursively processes relationships for a parent table. * Updates internal maps tracking descendant-parent relationships. * @param parent - The parent table name * @param relationships - The relationships configuration for the parent table */ private processRelationship; /** * Finds all root tables (tables with no parents) for a given table. * Uses depth-first search with cycle detection. * A table is considered a root if it has no parents in the merged graph, * or if it is an entry-point table declared by any plugin (appears in a * plugin's relationship graph but not as a descendant within that plugin). * @param table - The table to find roots for * @param visited - Set of already visited tables to prevent infinite loops * @returns Set of root table names */ private findAllRoots; /** * Adds cyclic reference metadata to the relationship tree. * @param relationships - The relationship tree to annotate * @param cyclicRefs - Map of node IDs to their cyclic reference node IDs */ private addCyclicReferencesToTree; /** * Recursively builds the relationship tree for a table. * Detects and marks cyclic relationships during traversal. * @param table - The table to build relationships for * @param visitedPath - Map of visited tables to their node IDs in current path * @param cyclicRefs - Map collecting cyclic references by node ID * @returns The descendant relationships tree, or undefined if no relationships exist */ private buildRelationship; /** * Generates the complete relationship hierarchy for a given table. * @template T - The table name type * @param table - The root table to generate hierarchy for * @returns The complete relationship hierarchy including cyclic references */ private generateRelationshipHierarchy; /** * Checks if a table is a root table (has no parent tables). * Assumption: Root table doesn't have any parent table even via cylic references. * @param table - The table name to check * @returns True if the table is a root, false otherwise */ private isRoot; /** * Validates that all 'via' fields in the hierarchy are supported types. * Currently rejects hierarchies containing unknown type relationships. * @param hierarchy - The relationship hierarchy to validate * @returns True if all via fields are supported, false otherwise */ private validateViaInHierarchy; /** * Resolves all possible relationship hierarchies for a given table. * Finds all root tables and generates hierarchies from each root. * Filters out hierarchies with unsupported relationship types. * @param table - The table to resolve relationships for * @returns Array of all valid relationship hierarchies */ resolveRelationship(table: string): RelationshipHierarchy[]; } export {};