Spaces:
Runtime error
Runtime error
| import { readdirSync, existsSync, readFileSync } from "node:fs"; | |
| import { join } from "node:path"; | |
| import { homedir } from "node:os"; | |
| import { pathToFileURL } from "node:url"; | |
| const PLUGIN_PREFIX_RE = /^(@[^/]+\/)?omniroute-cmd-/; | |
| function getPluginDirs() { | |
| return [join(homedir(), ".omniroute", "plugins"), process.env.OMNIROUTE_PLUGIN_PATH].filter( | |
| Boolean | |
| ); | |
| } | |
| export async function discoverPlugins() { | |
| const found = []; | |
| for (const dir of getPluginDirs()) { | |
| if (!existsSync(dir)) continue; | |
| let entries; | |
| try { | |
| entries = readdirSync(dir, { withFileTypes: true }); | |
| } catch { | |
| continue; | |
| } | |
| for (const entry of entries) { | |
| if (!entry.isDirectory()) continue; | |
| const pkgPath = join(dir, entry.name, "package.json"); | |
| if (!existsSync(pkgPath)) continue; | |
| let pkg; | |
| try { | |
| pkg = JSON.parse(readFileSync(pkgPath, "utf8")); | |
| } catch { | |
| continue; | |
| } | |
| if (!pkg.name || !PLUGIN_PREFIX_RE.test(pkg.name)) continue; | |
| found.push({ | |
| name: pkg.name, | |
| version: pkg.version || "0.0.0", | |
| description: pkg.description || "", | |
| dir: join(dir, entry.name), | |
| pkg, | |
| }); | |
| } | |
| } | |
| return found; | |
| } | |
| export function buildPluginContext(opts = {}) { | |
| return { | |
| apiFetch: async (...args) => { | |
| const { apiFetch } = await import("./api.mjs"); | |
| return apiFetch(...args); | |
| }, | |
| emit: async (...args) => { | |
| const { emit } = await import("./output.mjs"); | |
| return emit(...args); | |
| }, | |
| t: async (...args) => { | |
| const { t } = await import("./i18n.mjs"); | |
| return t(...args); | |
| }, | |
| withSpinner: async (...args) => { | |
| const { withSpinner } = await import("./spinner.mjs"); | |
| return withSpinner(...args); | |
| }, | |
| baseUrl: opts.baseUrl, | |
| apiKey: opts.apiKey, | |
| }; | |
| } | |
| export async function loadPlugins(program, ctx = {}) { | |
| const plugins = await discoverPlugins(); | |
| for (const p of plugins) { | |
| try { | |
| const entryPath = join(p.dir, p.pkg.main || "index.mjs"); | |
| if (!existsSync(entryPath)) { | |
| process.stderr.write(`[plugin] ${p.name}: entry file not found (${entryPath})\n`); | |
| continue; | |
| } | |
| const mod = await import(pathToFileURL(entryPath).href); | |
| if (typeof mod.register === "function") { | |
| mod.register(program, buildPluginContext(ctx)); | |
| } else { | |
| process.stderr.write(`[plugin] ${p.name}: no register() export — skipping\n`); | |
| } | |
| } catch (err) { | |
| process.stderr.write(`[plugin] Failed to load ${p.name}: ${err.message}\n`); | |
| } | |
| } | |
| return plugins.length; | |
| } | |