fix(plugin-inventory): rename install Remote to installPlugin
The RemoteNamespaceService reserves `install` as its private registration method, so a Remote method also named `install` collided at client-api boot (`pluginInventory/install conflicts with its namespace service`). Rename the plugin-install Remote to `installPlugin` across host, client, and tests. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+3
-3
@@ -22,7 +22,7 @@ export interface PluginInventorySettingsTabInjected {
|
||||
/** List the offline-installable optional bundles. */
|
||||
availableBundles: () => Promise<AvailableBundlesSnapshot>
|
||||
/** Install a bundle or registry plugin; the host persists the change. */
|
||||
install: (spec: InstallSpec) => Promise<InstallResult>
|
||||
installPlugin: (spec: InstallSpec) => Promise<InstallResult>
|
||||
/** Un-compose an offline optional bundle. */
|
||||
uninstall: (name: string) => Promise<InstallResult>
|
||||
}
|
||||
@@ -80,7 +80,7 @@ type BundleState =
|
||||
|
||||
/** Render the current Loader inventory with per-plugin enable/disable and install. */
|
||||
export function PluginInventorySettingsTab({
|
||||
list, setEnabled, availableBundles, install, uninstall, t,
|
||||
list, setEnabled, availableBundles, installPlugin, uninstall, t,
|
||||
}: PluginInventorySettingsTabProps): ReactNode {
|
||||
const catalogId = useId()
|
||||
const [request, setRequest] = useState(0)
|
||||
@@ -126,7 +126,7 @@ export function PluginInventorySettingsTab({
|
||||
setInstallBusy(name)
|
||||
setInstallNote(null)
|
||||
const action = mode === 'install'
|
||||
? install({ type: 'bundle', name })
|
||||
? installPlugin({ type: 'bundle', name })
|
||||
: uninstall(name)
|
||||
void action.then(
|
||||
() => {
|
||||
|
||||
@@ -47,10 +47,10 @@ export function apply(ctx: ClientContext): void {
|
||||
}
|
||||
return result.value
|
||||
}
|
||||
const install: PluginInventorySettingsTabInjected['install'] = async (spec) => {
|
||||
const result = await ctx.remote.pluginInventory.install(spec)
|
||||
const installPlugin: PluginInventorySettingsTabInjected['installPlugin'] = async (spec) => {
|
||||
const result = await ctx.remote.pluginInventory.installPlugin(spec)
|
||||
if (!result.ok) {
|
||||
throw new Error(`pluginInventory.install failed: ${result.error.code}: ${result.error.message}`)
|
||||
throw new Error(`pluginInventory.installPlugin failed: ${result.error.code}: ${result.error.message}`)
|
||||
}
|
||||
return result.value
|
||||
}
|
||||
@@ -62,7 +62,7 @@ export function apply(ctx: ClientContext): void {
|
||||
return result.value
|
||||
}
|
||||
const injected = (): PluginInventorySettingsTabInjected => ({
|
||||
list, setEnabled, availableBundles, install, uninstall,
|
||||
list, setEnabled, availableBundles, installPlugin, uninstall,
|
||||
})
|
||||
|
||||
ctx.slots.inject('settings.plugins.tab', () => ctx.slots.register({
|
||||
|
||||
@@ -16,14 +16,14 @@ const t = ((key: PluginInventoryLocaleKey): string => en[key]) as PluginInventor
|
||||
function props(
|
||||
list: PluginInventorySettingsTabInjected['list'],
|
||||
bundles: PluginInventorySettingsTabInjected['availableBundles'] = async () => ({ available: [] }),
|
||||
install: PluginInventorySettingsTabInjected['install'] = async () => ({ ok: true as const, restartRequired: true }),
|
||||
installPlugin: PluginInventorySettingsTabInjected['installPlugin'] = async () => ({ ok: true as const, restartRequired: true }),
|
||||
uninstall: PluginInventorySettingsTabInjected['uninstall'] = async () => ({ ok: true as const, restartRequired: true }),
|
||||
): PluginInventorySettingsTabProps {
|
||||
return {
|
||||
t,
|
||||
list,
|
||||
availableBundles: bundles,
|
||||
install,
|
||||
installPlugin,
|
||||
uninstall,
|
||||
} as PluginInventorySettingsTabProps
|
||||
}
|
||||
@@ -163,7 +163,7 @@ describe('PluginInventorySettingsTab', () => {
|
||||
})
|
||||
|
||||
it('renders the installable bundles with install and uninstall actions', async () => {
|
||||
const install = vi.fn<PluginInventorySettingsTabInjected['install']>(async () => ({ ok: true, restartRequired: true }))
|
||||
const installPlugin = vi.fn<PluginInventorySettingsTabInjected['installPlugin']>(async () => ({ ok: true, restartRequired: true }))
|
||||
const uninstall = vi.fn<PluginInventorySettingsTabInjected['uninstall']>(async () => ({ ok: true, restartRequired: true }))
|
||||
const bundles: PluginInventorySettingsTabInjected['availableBundles'] = async () => ({
|
||||
available: [
|
||||
@@ -171,7 +171,7 @@ describe('PluginInventorySettingsTab', () => {
|
||||
{ name: '@deepseek-ai/dsh-installed-bundle', installed: true },
|
||||
],
|
||||
})
|
||||
render(<PluginInventorySettingsTab {...props(async () => SNAPSHOT, bundles, install, uninstall)} />)
|
||||
render(<PluginInventorySettingsTab {...props(async () => SNAPSHOT, bundles, installPlugin, uninstall)} />)
|
||||
|
||||
expect(await screen.findByText(en.available)).toBeTruthy()
|
||||
expect(screen.getByText('@deepseek-ai/dsh-new-bundle')).toBeTruthy()
|
||||
@@ -179,7 +179,7 @@ describe('PluginInventorySettingsTab', () => {
|
||||
|
||||
// Install a not-installed bundle.
|
||||
fireEvent.click(screen.getByRole('button', { name: en.install }))
|
||||
expect(install).toHaveBeenCalledWith({ type: 'bundle', name: '@deepseek-ai/dsh-new-bundle' })
|
||||
expect(installPlugin).toHaveBeenCalledWith({ type: 'bundle', name: '@deepseek-ai/dsh-new-bundle' })
|
||||
expect(await screen.findByText(en.restartRequired)).toBeTruthy()
|
||||
|
||||
// Uninstall an installed bundle.
|
||||
|
||||
@@ -138,8 +138,8 @@ export class PluginInventoryGateway extends TypertRemoteService {
|
||||
* @param spec - the bundle name or registry package spec to install.
|
||||
* @returns a confirmation; `restartRequired` tells the caller to restart.
|
||||
*/
|
||||
@Remote('install')
|
||||
install(spec: InstallSpec): InstallResult {
|
||||
@Remote('installPlugin')
|
||||
installPlugin(spec: InstallSpec): InstallResult {
|
||||
const profileDir = this.profileDir()
|
||||
const anchor = this.ctx.get('dshInstallAnchor') as string | undefined
|
||||
if (anchor === undefined) {
|
||||
|
||||
@@ -49,7 +49,7 @@ describe('PluginInventoryGateway', () => {
|
||||
{ method: 'list', invocation: { kind: 'direct' } },
|
||||
{ method: 'setEnabled', invocation: { kind: 'direct' } },
|
||||
{ method: 'availableBundles', invocation: { kind: 'direct' } },
|
||||
{ method: 'install', invocation: { kind: 'direct' } },
|
||||
{ method: 'installPlugin', invocation: { kind: 'direct' } },
|
||||
{ method: 'uninstall', invocation: { kind: 'direct' } },
|
||||
])
|
||||
})
|
||||
@@ -151,9 +151,9 @@ describe('PluginInventoryGateway', () => {
|
||||
ctx.baseUrl = pathToFileURL(dir + '/').href
|
||||
writeFileSync(join(dir, 'package.json'), JSON.stringify({ name: 'dsh-profile-test', dsh: { profile: { bundles: [] } } }))
|
||||
try {
|
||||
expect(() => inventory.install({ type: 'bundle', name: 'x' })).toThrow(/install anchor is unavailable/)
|
||||
expect(() => inventory.installPlugin({ type: 'bundle', name: 'x' })).toThrow(/install anchor is unavailable/)
|
||||
ctx.provide('dshInstallAnchor', join(dir, 'package.json'))
|
||||
expect(() => inventory.install({ type: 'registry', spec: 'x' })).toThrow(/not permitted/)
|
||||
expect(() => inventory.installPlugin({ type: 'registry', spec: 'x' })).toThrow(/not permitted/)
|
||||
} finally {
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
}
|
||||
@@ -185,7 +185,7 @@ describe('PluginInventoryGateway', () => {
|
||||
writeFileSync(join(dir, 'node_modules', 'b', 'cordis.patch.yml'), '[]\n')
|
||||
ctx.provide('dshInstallAnchor', join(dir, 'package.json'))
|
||||
try {
|
||||
inventory.install({ type: 'bundle', name: 'b' })
|
||||
inventory.installPlugin({ type: 'bundle', name: 'b' })
|
||||
expect(readProfileManifest('dsh', dir).dsh?.profile?.bundles).toEqual(['b'])
|
||||
} finally {
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
@@ -203,7 +203,7 @@ describe('PluginInventoryGateway', () => {
|
||||
try {
|
||||
ctx.provide('dshInstallAnchor', join(dir, 'package.json'))
|
||||
ctx.provide('dshAllowPluginInstall', true)
|
||||
expect(inventory.install({ type: 'registry', spec: 'some-pkg' }).restartRequired).toBe(true)
|
||||
expect(inventory.installPlugin({ type: 'registry', spec: 'some-pkg' }).restartRequired).toBe(true)
|
||||
} finally {
|
||||
delete process.env.DSH_PNPM
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
@@ -260,7 +260,7 @@ describe('PluginInventoryGateway', () => {
|
||||
try {
|
||||
ctx.provide('dshInstallAnchor', join(dir, 'package.json'))
|
||||
ctx.provide('dshAllowPluginInstall', true)
|
||||
expect(() => inventory.install({ type: 'registry', spec: 'x' })).toThrow(/bundled pnpm is unavailable/)
|
||||
expect(() => inventory.installPlugin({ type: 'registry', spec: 'x' })).toThrow(/bundled pnpm is unavailable/)
|
||||
} finally {
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
}
|
||||
@@ -276,7 +276,7 @@ describe('PluginInventoryGateway', () => {
|
||||
try {
|
||||
ctx.provide('dshInstallAnchor', join(dir, 'package.json'))
|
||||
ctx.provide('dshAllowPluginInstall', true)
|
||||
expect(() => inventory.install({ type: 'registry', spec: 'x' })).toThrow(/failed to read profile manifest/)
|
||||
expect(() => inventory.installPlugin({ type: 'registry', spec: 'x' })).toThrow(/failed to read profile manifest/)
|
||||
} finally {
|
||||
delete process.env.DSH_PNPM
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
|
||||
Reference in New Issue
Block a user