import { loadConfig, readConfigFileSnapshot, replaceConfigFile } from "../config/config.js";import type { HookInstallRecord } from "../config/types.hooks.js";import type { PluginInstallRecord } from "../config/types.plugins.js";import { updateNpmInstalledHookPacks } from "../hooks/update.js";import { parseRegistryNpmSpec } from "../infra/npm-registry-spec.js";import { updateNpmInstalledPlugins } from "../plugins/update.js";import { defaultRuntime } from "../runtime.js";import { theme } from "../terminal/theme.js";import {extractInstalledNpmHookPackageName,extractInstalledNpmPackageName,} from "./plugins-command-helpers.js";import { promptYesNo } from "./prompt.js";function resolvePluginUpdateSelection(params: {installs: Record<string, PluginInstallRecord>;rawId?: string;all?: boolean;}): { pluginIds: string[]; specOverrides?: Record<string, string> } {if (params.all) {return { pluginIds: Object.keys(params.installs) };}if (!params.rawId) {return { pluginIds: [] };}const parsedSpec = parseRegistryNpmSpec(params.rawId);if (!parsedSpec || parsedSpec.selectorKind === "none") {return { pluginIds: [params.rawId] };}const matches = Object.entries(params.installs).filter(([, install]) => {return extractInstalledNpmPackageName(install) === parsedSpec.name;});if (matches.length !== 1) {return { pluginIds: [params.rawId] };}const [pluginId] = matches[0];if (!pluginId) {return { pluginIds: [params.rawId] };}return {pluginIds: [pluginId],specOverrides: {[pluginId]: parsedSpec.raw,},};}function resolveHookPackUpdateSelection(params: {installs: Record<string, HookInstallRecord>;rawId?: string;all?: boolean;}): { hookIds: string[]; specOverrides?: Record<string, string> } {if (params.all) {return { hookIds: Object.keys(params.installs) };}if (!params.rawId) {return { hookIds: [] };}if (params.rawId in params.installs) {return { hookIds: [params.rawId] };}const parsedSpec = parseRegistryNpmSpec(params.rawId);if (!parsedSpec || parsedSpec.selectorKind === "none") {return { hookIds: [] };}const matches = Object.entries(params.installs).filter(([, install]) => {return extractInstalledNpmHookPackageName(install) === parsedSpec.name;});if (matches.length !== 1) {return { hookIds: [] };}const [hookId] = matches[0];if (!hookId) {return { hookIds: [] };}return {hookIds: [hookId],specOverrides: {[hookId]: parsedSpec.raw,},};}export async function runPluginUpdateCommand(params: {id?: string;opts: { all?: boolean; dryRun?: boolean; dangerouslyForceUnsafeInstall?: boolean };}) {const sourceSnapshotPromise = readConfigFileSnapshot().catch(() => null);const cfg = loadConfig();const logger = {info: (msg: string) => defaultRuntime.log(msg),warn: (msg: string) => defaultRuntime.log(theme.warn(msg)),};const pluginSelection = resolvePluginUpdateSelection({installs: cfg.plugins?.installs ?? {},rawId: params.id,all: params.opts.all,});const hookSelection = resolveHookPackUpdateSelection({installs: cfg.hooks?.internal?.installs ?? {},rawId: params.id,all: params.opts.all,});if (pluginSelection.pluginIds.length === 0 && hookSelection.hookIds.length === 0) {if (params.opts.all) {defaultRuntime.log("No tracked plugins or hook packs to update.");return;}defaultRuntime.error("Provide a plugin or hook-pack id, or use --all.");return defaultRuntime.exit(1);}const pluginResult = await updateNpmInstalledPlugins({config: cfg,pluginIds: pluginSelection.pluginIds,specOverrides: pluginSelection.specOverrides,dryRun: params.opts.dryRun,dangerouslyForceUnsafeInstall: params.opts.dangerouslyForceUnsafeInstall,logger,onIntegrityDrift: async (drift) => {const specLabel = drift.resolvedSpec ?? drift.spec;defaultRuntime.log(theme.warn(`Integrity drift detected for "${drift.pluginId}" (${specLabel})` +`\nExpected: ${drift.expectedIntegrity}` +`\nActual: ${drift.actualIntegrity}`,),);if (drift.dryRun) {return true;}return await promptYesNo(`Continue updating "${drift.pluginId}" with this artifact?`);},});const hookResult = await updateNpmInstalledHookPacks({config: pluginResult.config,hookIds: hookSelection.hookIds,specOverrides: hookSelection.specOverrides,dryRun: params.opts.dryRun,logger,onIntegrityDrift: async (drift) => {const specLabel = drift.resolvedSpec ?? drift.spec;defaultRuntime.log(theme.warn(`Integrity drift detected for hook pack "${drift.hookId}" (${specLabel})` +`\nExpected: ${drift.expectedIntegrity}` +`\nActual: ${drift.actualIntegrity}`,),);if (drift.dryRun) {return true;}return await promptYesNo(`Continue updating hook pack "${drift.hookId}" with this artifact?`);},});for (const outcome of pluginResult.outcomes) {if (outcome.status === "error") {defaultRuntime.log(theme.error(outcome.message));continue;}if (outcome.status === "skipped") {defaultRuntime.log(theme.warn(outcome.message));continue;}defaultRuntime.log(outcome.message);}for (const outcome of hookResult.outcomes) {if (outcome.status === "error") {defaultRuntime.log(theme.error(outcome.message));continue;}if (outcome.status === "skipped") {defaultRuntime.log(theme.warn(outcome.message));continue;}defaultRuntime.log(outcome.message);}if (!params.opts.dryRun && (pluginResult.changed || hookResult.changed)) {await replaceConfigFile({nextConfig: hookResult.config,baseHash: (await sourceSnapshotPromise)?.hash,});defaultRuntime.log("Restart the gateway to load plugins and hooks.");}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。