mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(cli): a missing registry item names the closest ones, and a blocked browser says how to allow it
This commit is contained in:
@@ -278,6 +278,14 @@ describe("registry resolver", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("names the closest items when the requested one is not in the registry", async () => {
|
||||
mockFetch();
|
||||
const baseUrl = uniqueBaseUrl();
|
||||
await expect(resolveItemWithDependencies("alpha-gamma-reveal", { baseUrl })).rejects.toThrow(
|
||||
/Item "alpha-gamma-reveal" not found in registry\. Closest: alpha, gamma\. Available: /,
|
||||
);
|
||||
});
|
||||
|
||||
it("throws a clear cycle error for circular dependencies", async () => {
|
||||
mockFetch({ dependencies: { alpha: ["gamma"], beta: ["alpha"], gamma: ["beta"] } });
|
||||
const baseUrl = uniqueBaseUrl();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import type { ItemType, RegistryItem, RegistryManifestEntry } from "@hyperframes/core";
|
||||
import { fetchItemManifest, fetchRegistryManifest, DEFAULT_REGISTRY_URL } from "./remote.js";
|
||||
import { runWithConcurrencyLimit } from "../utils/concurrency.js";
|
||||
import { closestNames } from "../utils/didYouMean.js";
|
||||
|
||||
export interface ResolveOptions {
|
||||
baseUrl?: string;
|
||||
@@ -145,9 +146,13 @@ export async function resolveItemWithDependencies(
|
||||
const entry = entries.find((e) => e.name === name);
|
||||
if (!entry) {
|
||||
const available = entries.map((e) => e.name).join(", ");
|
||||
const close = closestNames(
|
||||
name,
|
||||
entries.map((e) => e.name),
|
||||
);
|
||||
throw new Error(
|
||||
available.length > 0
|
||||
? `Item "${name}" not found in registry. Available: ${available}`
|
||||
? `Item "${name}" not found in registry.${close.length > 0 ? ` Closest: ${close.join(", ")}.` : ""} Available: ${available}`
|
||||
: unreachableRegistryMessage(name, options.baseUrl),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,21 @@ export function closestMatch(input: string, candidates: Iterable<string>): strin
|
||||
return best;
|
||||
}
|
||||
|
||||
/** Up to `limit` candidates sharing a dash-separated word with `input`, most shared words first, then nearest spelling. */
|
||||
export function closestNames(input: string, candidates: Iterable<string>, limit = 5): string[] {
|
||||
const words = new Set(input.split("-"));
|
||||
return [...candidates]
|
||||
.map((name) => ({
|
||||
name,
|
||||
shared: name.split("-").filter((word) => words.has(word)).length,
|
||||
distance: editDistance(input, name),
|
||||
}))
|
||||
.filter(({ shared }) => shared > 0)
|
||||
.sort((a, b) => b.shared - a.shared || a.distance - b.distance || a.name.localeCompare(b.name))
|
||||
.slice(0, limit)
|
||||
.map(({ name }) => name);
|
||||
}
|
||||
|
||||
const COMMAND_SYNONYMS: Record<string, string> = {
|
||||
search: "catalog",
|
||||
find: "catalog",
|
||||
|
||||
@@ -102,6 +102,8 @@ describe("explainChromeLaunchFailure for a browser Windows refuses to run", () =
|
||||
expect(explained.message).toContain(executablePath);
|
||||
expect(explained.message).toContain("error -4094");
|
||||
expect(explained.message).toContain("browser ensure --force");
|
||||
expect(explained.message).toContain("Application Control");
|
||||
expect(explained.message).toContain("HYPERFRAMES_BROWSER_PATH");
|
||||
expect(explained.cause).toBe(refused);
|
||||
expect(existsSync(marker)).toBe(false);
|
||||
});
|
||||
|
||||
@@ -109,8 +109,9 @@ export async function explainChromeLaunchFailure(
|
||||
if (code === "UNKNOWN" && syscall === "spawn")
|
||||
return new Error(
|
||||
`Windows refused to start the browser${executablePath ? ` at ${executablePath}` : ""} (error ${errno ?? "unknown"}, spawn UNKNOWN). ` +
|
||||
"Security software may be blocking it, or the computer may be out of memory. " +
|
||||
"Close other apps and retry; if it persists, run `hyperframes browser ensure --force` to download it again.",
|
||||
"Windows Application Control or security software may be blocking it, or the computer may be out of memory. " +
|
||||
"Close other apps and retry. If a policy blocks the file, allow that path or set HYPERFRAMES_BROWSER_PATH to a Chrome or Edge your policy allows; " +
|
||||
"if the file is damaged, run `hyperframes browser ensure --force` to download it again.",
|
||||
{ cause: error },
|
||||
);
|
||||
if (!executablePath) return error;
|
||||
|
||||
Reference in New Issue
Block a user