From 6d921296f697c9eadbcc7003b1972671ad844a56 Mon Sep 17 00:00:00 2001 From: Wojciech Maj Date: Thu, 5 Feb 2026 23:12:54 +0100 Subject: [PATCH 1/4] feat: suggest installing dependency as devDependency when appropriate Closes #530 --- app/components/Terminal/Install.vue | 64 ++++++++++- app/pages/package/[[org]]/[name].vue | 1 + app/utils/install-command.ts | 114 +++++++++++++++++++- i18n/locales/en.json | 2 + i18n/locales/pl-PL.json | 2 + lunaria/files/en-GB.json | 2 + lunaria/files/en-US.json | 2 + lunaria/files/pl-PL.json | 2 + test/unit/app/utils/install-command.spec.ts | 90 ++++++++++++++++ 9 files changed, 277 insertions(+), 2 deletions(-) diff --git a/app/components/Terminal/Install.vue b/app/components/Terminal/Install.vue index 5fe249ea0..7699feda7 100644 --- a/app/components/Terminal/Install.vue +++ b/app/components/Terminal/Install.vue @@ -6,6 +6,7 @@ const props = defineProps<{ packageName: string requestedVersion?: string | null jsrInfo?: JsrPackageInfo | null + readmeHtml?: string | null typesPackageName?: string | null executableInfo?: { hasExecutable: boolean; primaryCommand?: string } | null createPackageInfo?: { packageName: string } | null @@ -28,6 +29,20 @@ function getInstallPartsForPM(pmId: PackageManagerId) { }) } +const devDependencySuggestion = computed(() => + getDevDependencySuggestion(props.packageName, props.readmeHtml), +) + +function getDevInstallPartsForPM(pmId: PackageManagerId) { + return getInstallCommandParts({ + packageName: props.packageName, + packageManager: pmId, + version: props.requestedVersion, + jsrInfo: props.jsrInfo, + dev: true, + }) +} + // Generate run command parts for a specific package manager function getRunPartsForPM(pmId: PackageManagerId, command?: string) { return getRunCommandParts({ @@ -66,7 +81,7 @@ function getTypesInstallPartsForPM(pmId: PackageManagerId) { const pm = packageManagers.find(p => p.id === pmId) if (!pm) return [] - const devFlag = pmId === 'bun' ? '-d' : '-D' + const devFlag = getDevDependencyFlag(pmId) const pkgSpec = pmId === 'deno' ? `npm:${props.typesPackageName}` : props.typesPackageName return [pm.label, pm.action, devFlag, pkgSpec] @@ -93,6 +108,18 @@ const copyRunCommand = (command?: string) => copyRun(getFullRunCommand(command)) const { copied: createCopied, copy: copyCreate } = useClipboard({ copiedDuring: 2000 }) const copyCreateCommand = () => copyCreate(getFullCreateCommand()) + +const { copied: devInstallCopied, copy: copyDevInstall } = useClipboard({ copiedDuring: 2000 }) +const copyDevInstallCommand = () => + copyDevInstall( + getInstallCommand({ + packageName: props.packageName, + packageManager: selectedPM.value, + version: props.requestedVersion, + jsrInfo: props.jsrInfo, + dev: true, + }), + )