import type { SObjectDescribe } from "../describe/types.ts"; import { type FieldFilterOptions } from "./filters.ts"; import { type RequiredField } from "./required.ts"; export type NodeRole = "root" | "parent" | "child" | "standard-root"; export type SensitiveField = { name: string; label?: string; type: string; }; export type NodeAttrs = { label: string; custom: boolean; isStandardRoot: boolean; /** Present when we have a full describe for this object. False if referenced-only. */ described: boolean; /** Role relative to the focus root. Root is the `--object`, parents are walked up, children down. */ role: NodeRole; /** Distance from the root in the walked graph. 0 = root itself. */ distanceFromRoot: number; /** Required-field classification (only populated for described nodes). */ requiredFields: RequiredField[]; /** Sensitive-looking fields by name pattern (only populated for described nodes). */ sensitiveFields: SensitiveField[]; /** Count of fields filtered by the default filters; populated for described nodes. */ droppedFieldCounts: { formula: number; audit: number; nonCreateable: number; }; /** Total field count (pre-filter), for reporting. */ totalFieldCount: number; /** If --include-counts was passed, row count from SELECT COUNT(). null otherwise. */ rowCount: number | null; /** Requested record-type developer name, if scoped. */ recordType?: string; }; export type EdgeKind = "parent" | "child" | "self"; export type EdgeAttrs = { /** Field name on `source` that references `target`. */ fieldName: string; nillable: boolean; custom: boolean; /** True if source field's referenceTo[] has more than one entry. */ polymorphic: boolean; /** True for master-detail (cascadeDelete). Master-detail edges are never breakable. */ masterDetail: boolean; /** Relative to the focus root: "parent" = edge goes up the FK chain, "child" = down. */ kind: EdgeKind; }; export type DependencyGraph = { nodes: Map; /** * Flat edge list. Multiple edges allowed between same node pair (different fields) * and from a single field to multiple targets (polymorphic). */ edges: Array<{ source: string; target: string; } & EdgeAttrs>; }; export type BuildOptions = { /** The single object the user is focusing on. */ rootObject: string; /** * Describes for the root AND any transitively-referenced parents AND any 1-level * children we fetched. Missing entries render as "referenced-only" nodes. */ describes: Map; /** Which object names were walked as parents of the root (via reference fields). */ parentObjects: Set; /** Which object names were walked as 1-level children of the root (via childRelationships). */ childObjects: Set; /** Distance-from-root map (0 for root, 1+ for parents & children). */ distances: Map; /** Row counts keyed by object name, from the opt-in counts query. */ rowCounts?: Map; /** Record-type developer name, if scoped. */ recordType?: string; /** Field filter options; defaults to {formula:false, audit:false, nonCreateable:false}. */ fieldFilters?: FieldFilterOptions; }; /** * Build a dependency graph focused on one root object. * * Contract: * - Every object with a describe becomes a described node. * - Referenced objects without describes become referenced-only nodes. * - Each reference field emits one edge per target in referenceTo[]. * - Edges are tagged parent/child/self based on how they relate to the root. * - Fields are filtered per opts before classification; dropped counts are recorded. */ export declare function buildGraph(opts: BuildOptions): DependencyGraph; /** * Collect the set of referenced parent object names from a describe, * respecting the same field filters used by the graph build so we don't walk * up through formula/audit/non-createable edges. */ export declare function collectReferencedObjects(describe: SObjectDescribe, filters?: FieldFilterOptions): Set; /** Collect 1-level children from childRelationships, dropping read-only system tables. */ export declare function collectChildObjects(describe: SObjectDescribe): Set;