MCPcopy Create free account
hub / github.com/heygen-com/hyperframes / resolveItemWithDependencies

Function resolveItemWithDependencies

packages/cli/src/registry/resolver.ts:114–178  ·  view source on GitHub ↗
(
  name: string,
  options: ResolveOptions = {},
)

Source from the content-addressed store, hash-verified

112 * parallel sibling fetches only if graph depth ever becomes a real cost.
113 */
114export async function resolveItemWithDependencies(
115 name: string,
116 options: ResolveOptions = {},
117): Promise<RegistryItem[]> {
118 const entries = await listRegistryItems(undefined, options);
119 const entry = entries.find((e) => e.name === name);
120 if (!entry) {
121 const available = entries.map((e) => e.name).join(", ");
122 throw new Error(
123 available.length > 0
124 ? `Item "${name}" not found in registry. Available: ${available}`
125 : `Item "${name}" not found — registry unreachable or empty.`,
126 );
127 }
128
129 const entryByName = new Map(entries.map((e) => [e.name, e]));
130 const visiting = new Set<string>();
131 const visited = new Set<string>();
132 const ordered: RegistryItem[] = [];
133 const itemCache = new Map<string, Promise<RegistryItem>>();
134
135 // `async` so the missing-dependency path surfaces as a promise rejection
136 // rather than a synchronous throw, keeping the control flow consistent with
137 // the `Promise<RegistryItem>` return type. The body has no `await`, so the
138 // cache is still populated synchronously on first request (dedup intact).
139 const getItem = async (itemName: string): Promise<RegistryItem> => {
140 const existing = itemCache.get(itemName);
141 if (existing) return existing;
142
143 const registryEntry = entryByName.get(itemName);
144 if (!registryEntry) {
145 const available = entries.map((e) => e.name).join(", ");
146 throw new Error(
147 available.length > 0
148 ? `Dependency "${itemName}" not found in registry. Available: ${available}`
149 : `Dependency "${itemName}" not found — registry unreachable or empty.`,
150 );
151 }
152
153 const pending = fetchItemManifest(registryEntry.name, registryEntry.type, options.baseUrl);
154 itemCache.set(itemName, pending);
155 return pending;
156 };
157
158 const visit = async (itemName: string, path: string[]): Promise<void> => {
159 if (visited.has(itemName)) return;
160 if (visiting.has(itemName)) {
161 const cycleStart = path.indexOf(itemName);
162 const cyclePath = [...path.slice(cycleStart), itemName].join(" -> ");
163 throw new Error(`Circular registryDependencies detected: ${cyclePath}`);
164 }
165
166 visiting.add(itemName);
167 const item = await getItem(itemName);
168 for (const dep of item.registryDependencies ?? []) {
169 await visit(dep, [...path, itemName]);
170 }
171 visiting.delete(itemName);

Callers 5

resolveItemFunction · 0.85
resolver.test.tsFile · 0.85
runAddFunction · 0.85
fetchRemoteTemplateFunction · 0.85
installRegistryBlockFunction · 0.85

Calls 3

listRegistryItemsFunction · 0.85
visitFunction · 0.70
findMethod · 0.65

Tested by

no test coverage detected