feat(FN-3239): auto-install dependency graph plugin in CLI daemon, dashboar
Merged the three-step FN-3239 feature: auto-installing the dependency graph plugin on first run across the `daemon`, `dashboard`, and `serve` commands, with the core logic centralized in `bundled-plugin-install.ts`, bundling configuration in `tsup.config.ts`, and a documentation file for the default Fusion-Task-Id: FN-3239
This commit is contained in:
67
packages/cli/src/plugins/bundled-plugin-install.ts
Normal file
67
packages/cli/src/plugins/bundled-plugin-install.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { existsSync } from "node:fs";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { dirname, join, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { validatePluginManifest, type PluginLoader, type PluginManifest, type PluginStore } from "@fusion/core";
|
||||
|
||||
const DEPENDENCY_GRAPH_PLUGIN_ID = "fusion-plugin-dependency-graph";
|
||||
|
||||
function getCandidatePluginPaths(): string[] {
|
||||
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
||||
const cliPackageRoot = resolve(moduleDir, "..", "..");
|
||||
|
||||
return [
|
||||
join(cliPackageRoot, "dist", "plugins", DEPENDENCY_GRAPH_PLUGIN_ID),
|
||||
join(cliPackageRoot, "plugins", DEPENDENCY_GRAPH_PLUGIN_ID),
|
||||
join(cliPackageRoot, "..", "..", "plugins", DEPENDENCY_GRAPH_PLUGIN_ID),
|
||||
];
|
||||
}
|
||||
|
||||
async function loadManifest(pluginDir: string): Promise<PluginManifest> {
|
||||
const manifestPath = join(pluginDir, "manifest.json");
|
||||
const content = await readFile(manifestPath, "utf-8");
|
||||
const manifest = JSON.parse(content);
|
||||
const validation = validatePluginManifest(manifest);
|
||||
if (!validation.valid) {
|
||||
throw new Error(`Invalid plugin manifest: ${validation.errors.join(", ")}`);
|
||||
}
|
||||
return manifest;
|
||||
}
|
||||
|
||||
function resolveBundledDependencyGraphPath(): string | null {
|
||||
for (const path of getCandidatePluginPaths()) {
|
||||
if (existsSync(join(path, "manifest.json"))) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function ensureBundledDependencyGraphPluginInstalled(
|
||||
pluginStore: PluginStore,
|
||||
pluginLoader: PluginLoader,
|
||||
): Promise<"installed" | "already-installed" | "missing-bundle"> {
|
||||
try {
|
||||
await pluginStore.getPlugin(DEPENDENCY_GRAPH_PLUGIN_ID);
|
||||
return "already-installed";
|
||||
} catch {
|
||||
// Continue; plugin not installed yet.
|
||||
}
|
||||
|
||||
const bundledPath = resolveBundledDependencyGraphPath();
|
||||
if (!bundledPath) {
|
||||
return "missing-bundle";
|
||||
}
|
||||
|
||||
const manifest = await loadManifest(bundledPath);
|
||||
const plugin = await pluginStore.registerPlugin({
|
||||
manifest,
|
||||
path: bundledPath,
|
||||
});
|
||||
|
||||
if (plugin.enabled) {
|
||||
await pluginLoader.loadPlugin(plugin.id);
|
||||
}
|
||||
|
||||
return "installed";
|
||||
}
|
||||
Reference in New Issue
Block a user