74 lines
2.5 KiB
TypeScript
74 lines
2.5 KiB
TypeScript
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
import type { PluginInstallRecord } from "../config/types.plugins.js";
|
|
|
|
export type PluginInstallPathIssue = {
|
|
kind: "custom-path" | "missing-path";
|
|
pluginId: string;
|
|
path: string;
|
|
};
|
|
|
|
function resolvePluginInstallCandidatePaths(
|
|
install: PluginInstallRecord | null | undefined,
|
|
): string[] {
|
|
if (!install || install.source !== "path") {
|
|
return [];
|
|
}
|
|
|
|
return [install.sourcePath, install.installPath]
|
|
.map((value) => (typeof value === "string" ? value.trim() : ""))
|
|
.filter(Boolean);
|
|
}
|
|
|
|
export async function detectPluginInstallPathIssue(params: {
|
|
pluginId: string;
|
|
install: PluginInstallRecord | null | undefined;
|
|
}): Promise<PluginInstallPathIssue | null> {
|
|
const candidatePaths = resolvePluginInstallCandidatePaths(params.install);
|
|
if (candidatePaths.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
for (const candidatePath of candidatePaths) {
|
|
try {
|
|
await fs.access(path.resolve(candidatePath));
|
|
return {
|
|
kind: "custom-path",
|
|
pluginId: params.pluginId,
|
|
path: candidatePath,
|
|
};
|
|
} catch {
|
|
// Keep checking remaining candidate paths before warning about a stale install.
|
|
}
|
|
}
|
|
|
|
return {
|
|
kind: "missing-path",
|
|
pluginId: params.pluginId,
|
|
path: candidatePaths[0] ?? "(unknown)",
|
|
};
|
|
}
|
|
|
|
export function formatPluginInstallPathIssue(params: {
|
|
issue: PluginInstallPathIssue;
|
|
pluginLabel: string;
|
|
defaultInstallCommand: string;
|
|
repoInstallCommand: string;
|
|
formatCommand?: (command: string) => string;
|
|
}): string[] {
|
|
const formatCommand = params.formatCommand ?? ((command: string) => command);
|
|
if (params.issue.kind === "custom-path") {
|
|
return [
|
|
`${params.pluginLabel} is installed from a custom path: ${params.issue.path}`,
|
|
`Main updates will not automatically replace that plugin with the repo's default ${params.pluginLabel} package.`,
|
|
`Reinstall with "${formatCommand(params.defaultInstallCommand)}" when you want to return to the standard ${params.pluginLabel} plugin.`,
|
|
`If you are intentionally running from a repo checkout, reinstall that checkout explicitly with "${formatCommand(params.repoInstallCommand)}" after updates.`,
|
|
];
|
|
}
|
|
return [
|
|
`${params.pluginLabel} is installed from a custom path that no longer exists: ${params.issue.path}`,
|
|
`Reinstall with "${formatCommand(params.defaultInstallCommand)}".`,
|
|
`If you are running from a repo checkout, you can also use "${formatCommand(params.repoInstallCommand)}".`,
|
|
];
|
|
}
|