Generalized record dependency graph traversal, relationship collection resolution, topological sorting, link value encoding, and graph models for MemberJunction.
Shared across:
npm install @memberjunction/record-graph
DependencyGraphWalkerWalks an entity record's relationships to discover all dependent and referenced records.
import { CompositeKey } from '@memberjunction/core';
import { DependencyGraphWalker } from '@memberjunction/record-graph';
const walker = new DependencyGraphWalker(provider); // provider is optional; defaults to Metadata.Provider
const userKey = CompositeKey.FromID(userId);
const rootNode = await walker.WalkDependents(
'MJ: Users',
userKey,
{
MaxDepth: 3,
RequireTrackRecordChanges: false, // Set false for cloning, true for Version History
IncludeSubtypes: true, // Include IS-A subtype rows
FollowHierarchies: true, // Recurse self-referencing hierarchy fields
EdgePolicy: (candidate) => {
if (candidate.TargetEntityName === 'MJ: Audit Logs') return 'Skip';
if (candidate.Kind === 'ForwardFK') return 'Reference';
return 'Deep';
},
},
contextUser
);
const flatNodes = walker.FlattenTopological(rootNode);
EntityRelationshipInfo) are walked with full discovery (both reverse and forward), discovering all dependent child records.forward-only mode so referenced entities (e.g., shared lookup tables) do not traverse their own children, preventing graph explosion.IncludeSubtypes): Discovers IS-A subtype rows via FindISAChildEntities.FollowHierarchies): Allows controlled recursion on fields whose Configuration.Hierarchy.IsHierarchy is true.IncludeSoftLinks): Traverses polymorphic EntityID/RecordID pairs via EntityIDFieldName.ListNonCuratedInbound): Discovers database foreign keys pointing to the record that lack a curated EntityRelationship.EdgePolicy): Pre-traversal callback returning 'Deep', 'Reference', or 'Skip'.visited set and entity-type ancestorStack to prevent infinite loops and backtracking.sort.ts)SortByEntityDependencyOrder<T>(items, getEntityID, provider?):
Computes DAG levels from foreign keys and sorts parent entities before child entities. Handles cycles safely.SortEntitiesByDependency:
Backward-compatible alias for SortByEntityDependencyOrder.SortNodesTopologically(root: DependencyNode):
Breadth-first traversal flattening a dependency tree into an execution-safe array where parents precede children.links.ts)ResolveLinkValue(kindOrIsSoft, targetKey):
Resolves the value to write into a pointer or foreign key column:
'hard' or false): bare primary key value (targetKey.GetValueByIndex(0)).'soft' or true): canonical prefixed polymorphic encoding (targetKey.ToRecordID()).collection-resolver.ts)ResolveCollectionRelationship(entityInfo, colName) (resolveCollectionRelationship is a deprecated alias):
Resolves a collection name to its matching relationship on the entity using strict 4-tier rule strength:
RelatedRecordCollection JSON ("Name": "...")DisplayNameRelatedEntity full nameRelatedEntity name (with singular/plural tolerance)sql.ts, keys.ts)SqlEquals, SqlContains, SqlIn, SqlNotIn: Safe SQL filter builders (they escape with EscapeSQLString from @memberjunction/global).BuildCompositeKeyFromRecord, BuildPrimaryKeyForLoad, BuildIdKey: CompositeKey construction utilities.sqlEquals, buildIdKey, …) and escapeSqlString are deprecated aliases. Use EscapeSQLString from @memberjunction/global directly.