diff --git a/app/components/Terminal/Install.vue b/app/components/Terminal/Install.vue index f1fbe7fd2f..38955234fb 100644 --- a/app/components/Terminal/Install.vue +++ b/app/components/Terminal/Install.vue @@ -60,22 +60,12 @@ function getRunPartsForPM(pmId: PackageManagerId, command?: string) { // Generate create command parts for a specific package manager function getCreatePartsForPM(pmId: PackageManagerId) { if (!props.createPackageInfo) return [] - const pm = packageManagers.find(p => p.id === pmId) - if (!pm) return [] - - const createPkgName = props.createPackageInfo.packageName - let shortName: string - if (createPkgName.startsWith('@')) { - const slashIndex = createPkgName.indexOf('/') - const name = createPkgName.slice(slashIndex + 1) - shortName = name.startsWith('create-') ? name.slice('create-'.length) : name - } else { - shortName = createPkgName.startsWith('create-') - ? createPkgName.slice('create-'.length) - : createPkgName - } - - return [...pm.create.split(' '), shortName] + return getExecuteCommandParts({ + packageName: props.createPackageInfo.packageName, + packageManager: pmId, + jsrInfo: null, + isCreatePackage: true, + }) } // Generate @types install command parts for a specific package manager @@ -102,7 +92,14 @@ function getFullRunCommand(command?: string) { // Full create command for copying (uses current selected PM) function getFullCreateCommand() { - return getCreatePartsForPM(selectedPM.value).join(' ') + if (!props.createPackageInfo) return '' + + return getExecuteCommand({ + packageName: props.createPackageInfo.packageName, + packageManager: selectedPM.value, + jsrInfo: null, + isCreatePackage: true, + }) } // Copy handlers diff --git a/app/utils/install-command.ts b/app/utils/install-command.ts index 857804cafa..3b656a74ce 100644 --- a/app/utils/install-command.ts +++ b/app/utils/install-command.ts @@ -47,7 +47,7 @@ export const packageManagers = [ action: 'add', executeLocal: 'deno run', executeRemote: 'deno run', - create: 'deno run', + create: 'deno create', icon: 'i-simple-icons:deno', }, { @@ -125,6 +125,24 @@ export interface ExecuteCommandOptions extends InstallCommandOptions { isCreatePackage?: boolean } +function getCreatePackageSpecifier(options: ExecuteCommandOptions): string | null { + if (!options.isCreatePackage) { + return null + } + + const shortName = getCreateShortName(options.packageName) + if (shortName === options.packageName) { + return null + } + + if (options.packageManager === 'deno') { + // npm compatibility: npm:package-name + return `npm:${shortName}` + } + + return shortName +} + export function getExecuteCommand(options: ExecuteCommandOptions): string { return getExecuteCommandParts(options).join(' ') } @@ -133,12 +151,10 @@ export function getExecuteCommandParts(options: ExecuteCommandOptions): string[] const pm = packageManagers.find(p => p.id === options.packageManager) if (!pm) return [] - // For create-* packages, use the shorthand create command - if (options.isCreatePackage) { - const shortName = getCreateShortName(options.packageName) - if (shortName !== options.packageName) { - return [...pm.create.split(' '), shortName] - } + // For create-* packages, use the shorthand create command. + const createSpecifier = getCreatePackageSpecifier(options) + if (createSpecifier) { + return [...pm.create.split(' '), createSpecifier] } // Choose remote or local execute based on package type diff --git a/test/unit/app/utils/install-command.spec.ts b/test/unit/app/utils/install-command.spec.ts index 8dd5c1bbab..9d69be4071 100644 --- a/test/unit/app/utils/install-command.spec.ts +++ b/test/unit/app/utils/install-command.spec.ts @@ -381,7 +381,7 @@ describe('install command generation', () => { ['pnpm', ['pnpm', 'create', 'vite']], ['yarn', ['yarn', 'create', 'vite']], ['bun', ['bun', 'create', 'vite']], - ['deno', ['deno', 'run', 'vite']], + ['deno', ['deno', 'create', 'npm:vite']], ['vlt', ['vlx', 'vite']], ] as const)('%s → %s', (pm, expected) => { expect(