diff --git a/app/components/ConnectorModal.vue b/app/components/ConnectorModal.vue index 5feb6620ae..de81b419f7 100644 --- a/app/components/ConnectorModal.vue +++ b/app/components/ConnectorModal.vue @@ -6,6 +6,7 @@ const { isConnected, isConnecting, npmUser, error, hasOperations, connect, disco const tokenInput = ref('') const portInput = ref('31415') +const copied = ref(false) async function handleConnect() { const port = Number.parseInt(portInput.value, 10) || 31415 @@ -20,6 +21,27 @@ function handleDisconnect() { disconnect() } +function copyCommand() { + let command = executeNpmxConnectorCommand.value + if (portInput.value !== '31415') { + command += ` --port ${portInput.value}` + } + navigator.clipboard.writeText(command) + copied.value = true + setTimeout(() => { + copied.value = false + }, 2000) +} + +const selectedPM = useSelectedPackageManager() + +const executeNpmxConnectorCommand = computed(() => { + return getExecuteCommand({ + packageName: 'npmx-connector', + packageManager: selectedPM.value, + }) +}) + // Reset form when modal opens watch(open, isOpen => { if (isOpen) { @@ -103,9 +125,24 @@ watch(open, isOpen => { Run the connector on your machine to enable admin features:

-
+
$ - npx npmx-connector + {{ executeNpmxConnectorCommand }} +

Then paste the token shown in your terminal:

diff --git a/app/composables/useSelectedPackageManager.ts b/app/composables/useSelectedPackageManager.ts new file mode 100644 index 0000000000..f4062b201e --- /dev/null +++ b/app/composables/useSelectedPackageManager.ts @@ -0,0 +1,5 @@ +import { useLocalStorage } from '@vueuse/core' + +export function useSelectedPackageManager() { + return useLocalStorage('npmx-pm', 'npm') +} diff --git a/app/pages/[...package].vue b/app/pages/[...package].vue index 85a0449622..b11e0abc41 100644 --- a/app/pages/[...package].vue +++ b/app/pages/[...package].vue @@ -190,19 +190,7 @@ function hasProvenance(version: PackumentVersion | null): boolean { return !!dist.attestations } -// Persist package manager preference in localStorage -const selectedPM = ref('npm') - -onMounted(() => { - const stored = localStorage.getItem('npmx-pm') - if (stored && packageManagers.some(pm => pm.id === stored)) { - selectedPM.value = stored as PackageManagerId - } -}) - -watch(selectedPM, value => { - localStorage.setItem('npmx-pm', value) -}) +const selectedPM = useSelectedPackageManager() const installCommandParts = computed(() => { if (!pkg.value) return [] diff --git a/app/utils/install-command.ts b/app/utils/install-command.ts index 0d42feb0d8..a27d98f0ae 100644 --- a/app/utils/install-command.ts +++ b/app/utils/install-command.ts @@ -1,12 +1,12 @@ import type { JsrPackageInfo } from '#shared/types/jsr' export const packageManagers = [ - { id: 'npm', label: 'npm', action: 'install' }, - { id: 'pnpm', label: 'pnpm', action: 'add' }, - { id: 'yarn', label: 'yarn', action: 'add' }, - { id: 'bun', label: 'bun', action: 'add' }, - { id: 'deno', label: 'deno', action: 'add' }, - { id: 'vlt', label: 'vlt', action: 'install' }, + { id: 'npm', label: 'npm', action: 'install', execute: 'npx' }, + { id: 'pnpm', label: 'pnpm', action: 'add', execute: 'pnpm dlx' }, + { id: 'yarn', label: 'yarn', action: 'add', execute: 'yarn dlx' }, + { id: 'bun', label: 'bun', action: 'add', execute: 'bunx' }, + { id: 'deno', label: 'deno', action: 'add', execute: 'deno run' }, + { id: 'vlt', label: 'vlt', action: 'install', execute: 'vlt x' }, ] as const export type PackageManagerId = (typeof packageManagers)[number]['id'] @@ -59,3 +59,13 @@ export function getInstallCommandParts(options: InstallCommandOptions): string[] return [pm.label, pm.action, `${spec}${version}`] } + +export function getExecuteCommand(options: InstallCommandOptions): string { + return getExecuteCommandParts(options).join(' ') +} + +export function getExecuteCommandParts(options: InstallCommandOptions): string[] { + const pm = packageManagers.find(p => p.id === options.packageManager) + if (!pm) return [] + return [pm.execute, getPackageSpecifier(options)] +}