From 10995da9705f60af0f397ebde40eeb660aea2f56 Mon Sep 17 00:00:00 2001 From: Damian Glowala Date: Wed, 8 Jan 2025 22:50:31 +0100 Subject: [PATCH 1/4] feat(add): skip installing already installed modules --- src/commands/module/add.ts | 107 +++++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 27 deletions(-) diff --git a/src/commands/module/add.ts b/src/commands/module/add.ts index 083e8db75..d7ea2b401 100644 --- a/src/commands/module/add.ts +++ b/src/commands/module/add.ts @@ -81,11 +81,15 @@ export default defineCommand({ } const maybeResolvedModules = await Promise.all(modules.map(moduleName => resolveModule(moduleName, cwd))) - const r = maybeResolvedModules.filter((x: ModuleResolution): x is ResolvedModule => x != null) + const resolvedModules = maybeResolvedModules.filter((x: ModuleResolution): x is ResolvedModule => x != null) - logger.info(`Resolved ${r.map(x => x.pkgName).join(', ')}, adding module(s)...`) + logger.info(`Resolved \`${ + resolvedModules.map(x => x.pkgName).join('\`, \`') + }\`, adding module${ + resolvedModules.length > 1 ? 's' : '' + }...`) - await addModule(r, { ...ctx.args, cwd }, projectPkg) + await addModules(resolvedModules, { ...ctx.args, cwd }, projectPkg) // update the types for new module const args = Object.entries(ctx.args).filter(([k]) => k in cwdArgs || k in logLevelArgs).map(([k, v]) => `--${k}=${v}`) @@ -94,25 +98,68 @@ export default defineCommand({ }) // -- Internal Utils -- -async function addModule(r: ResolvedModule[], { skipInstall, skipConfig, cwd, dev }: { skipInstall: boolean, skipConfig: boolean, cwd: string, dev: boolean }, projectPkg: any) { - // Add npm dependency +async function addModules(modules: ResolvedModule[], { skipInstall, skipConfig, cwd, dev }: { skipInstall: boolean, skipConfig: boolean, cwd: string, dev: boolean }, projectPkg: PackageJson) { + // Add dependencies if (!skipInstall) { - const isDev = Boolean(projectPkg.devDependencies?.nuxt) || dev - logger.info(`Installing \`${r.map(x => x.pkg).join(', ')}\`${isDev ? ' development' : ''} dep(s)`) - const res = await addDependency(r.map(x => x.pkg), { cwd, dev: isDev, installPeerDependencies: true }).catch( - (error) => { - logger.error(error) - return logger.prompt( - `Install failed for ${r.map(x => colors.cyan(x.pkg)).join(', ')}. Do you want to continue adding the module(s) to ${colors.cyan('nuxt.config')}?`, - { - type: 'confirm', - initial: false, - }, - ) - }, - ) - if (res === false) { - return + const modulesGrouppedByInstallationStatus = modules.reduce< + { installed: ResolvedModule[], notInstalled: ResolvedModule[] } + >((acc, module) => { + const isInstalled = (projectPkg.dependencies && module.pkgName in projectPkg.dependencies) + || (projectPkg.devDependencies && module.pkgName in projectPkg.devDependencies) + + if (isInstalled) { + acc.installed.push(module) + } + else { + acc.notInstalled.push(module) + } + + return acc + }, { installed: [], notInstalled: [] }) + + if (modulesGrouppedByInstallationStatus.installed.length > 0) { + logger.info(`\`${ + modulesGrouppedByInstallationStatus.installed.map(module => module.pkgName).join('\`, \`') + }\` ${ + modulesGrouppedByInstallationStatus.installed.length > 1 ? 'are' : 'is' + } already installed`) + } + + if (modulesGrouppedByInstallationStatus.notInstalled.length > 0) { + const isDev = Boolean(projectPkg.devDependencies?.nuxt) || dev + + logger.info(`Installing \`${ + modulesGrouppedByInstallationStatus.notInstalled.map(module => module.pkg).join('\`, \`') + }\`${ + isDev ? ' development' : '' + } ${ + modulesGrouppedByInstallationStatus.notInstalled.length > 1 ? 'dependencies' : 'dependency' + }`) + + const res = await addDependency( + modulesGrouppedByInstallationStatus.notInstalled.map(module => module.pkg), + { cwd, dev: isDev, installPeerDependencies: true }, + ).catch( + (error) => { + logger.error(error) + + return logger.prompt( + `Install failed for \`${ + modulesGrouppedByInstallationStatus.notInstalled.map(module => colors.cyan(module.pkg)).join('\`, \`') + }\`. Do you want to continue adding the module${ + modulesGrouppedByInstallationStatus.notInstalled.length > 1 ? 's' : '' + } to ${colors.cyan('nuxt.config')}?`, + { + type: 'confirm', + initial: false, + }, + ) + }, + ) + + if (res === false) { + return + } } } @@ -123,24 +170,30 @@ async function addModule(r: ResolvedModule[], { skipInstall, skipConfig, cwd, de configFile: 'nuxt.config', async onCreate() { logger.info(`Creating \`nuxt.config.ts\``) + return getDefaultNuxtConfig() }, async onUpdate(config) { - for (const resolved of r) { - if (!config.modules) { - config.modules = [] - } + if (!config.modules) { + config.modules = [] + } + + for (const resolved of modules) { if (config.modules.includes(resolved.pkgName)) { logger.info(`\`${resolved.pkgName}\` is already in the \`modules\``) - return + + continue } + logger.info(`Adding \`${resolved.pkgName}\` to the \`modules\``) + config.modules.push(resolved.pkgName) } }, }).catch((error) => { logger.error(`Failed to update \`nuxt.config\`: ${error.message}`) - logger.error(`Please manually add \`${r.map(x => x.pkgName).join(', ')}\` to the \`modules\` in \`nuxt.config.ts\``) + logger.error(`Please manually add \`${modules.map(x => x.pkgName).join(', ')}\` to the \`modules\` in \`nuxt.config.ts\``) + return null }) } From 127d2e4ba58b8dd4ac1031516cd6dbac9bdf5e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20G=C5=82owala?= Date: Thu, 9 Jan 2025 10:09:53 +0100 Subject: [PATCH 2/4] style: update error log formatting --- src/commands/module/add.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/module/add.ts b/src/commands/module/add.ts index d7ea2b401..d6f97a818 100644 --- a/src/commands/module/add.ts +++ b/src/commands/module/add.ts @@ -192,7 +192,7 @@ async function addModules(modules: ResolvedModule[], { skipInstall, skipConfig, }, }).catch((error) => { logger.error(`Failed to update \`nuxt.config\`: ${error.message}`) - logger.error(`Please manually add \`${modules.map(x => x.pkgName).join(', ')}\` to the \`modules\` in \`nuxt.config.ts\``) + logger.error(`Please manually add \`${modules.map(module => module.pkgName).join('\`, \`')}\` to the \`modules\` in \`nuxt.config.ts\``) return null }) From fbecb8de0bcaff00b4c6c64838a2246fd84169b5 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 9 Jan 2025 15:45:25 +0100 Subject: [PATCH 3/4] perf: some refactors --- src/commands/module/add.ts | 81 ++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 47 deletions(-) diff --git a/src/commands/module/add.ts b/src/commands/module/add.ts index d6f97a818..a66d40322 100644 --- a/src/commands/module/add.ts +++ b/src/commands/module/add.ts @@ -83,11 +83,7 @@ export default defineCommand({ const maybeResolvedModules = await Promise.all(modules.map(moduleName => resolveModule(moduleName, cwd))) const resolvedModules = maybeResolvedModules.filter((x: ModuleResolution): x is ResolvedModule => x != null) - logger.info(`Resolved \`${ - resolvedModules.map(x => x.pkgName).join('\`, \`') - }\`, adding module${ - resolvedModules.length > 1 ? 's' : '' - }...`) + logger.info(`Resolved \`${resolvedModules.map(x => x.pkgName).join('\`, \`')}\`, adding module${resolvedModules.length > 1 ? 's' : ''}...`) await addModules(resolvedModules, { ...ctx.args, cwd }, projectPkg) @@ -101,59 +97,50 @@ export default defineCommand({ async function addModules(modules: ResolvedModule[], { skipInstall, skipConfig, cwd, dev }: { skipInstall: boolean, skipConfig: boolean, cwd: string, dev: boolean }, projectPkg: PackageJson) { // Add dependencies if (!skipInstall) { - const modulesGrouppedByInstallationStatus = modules.reduce< - { installed: ResolvedModule[], notInstalled: ResolvedModule[] } - >((acc, module) => { - const isInstalled = (projectPkg.dependencies && module.pkgName in projectPkg.dependencies) - || (projectPkg.devDependencies && module.pkgName in projectPkg.devDependencies) - - if (isInstalled) { - acc.installed.push(module) + const installedModules: ResolvedModule[] = [] + const notInstalledModules: ResolvedModule[] = [] + + const dependencies = new Set([ + ...Object.keys(projectPkg.dependencies || {}), + ...Object.keys(projectPkg.devDependencies || {}), + ]) + + for (const module of modules) { + if (dependencies.has(module.pkgName)) { + installedModules.push(module) } else { - acc.notInstalled.push(module) + notInstalledModules.push(module) } + } - return acc - }, { installed: [], notInstalled: [] }) - - if (modulesGrouppedByInstallationStatus.installed.length > 0) { - logger.info(`\`${ - modulesGrouppedByInstallationStatus.installed.map(module => module.pkgName).join('\`, \`') - }\` ${ - modulesGrouppedByInstallationStatus.installed.length > 1 ? 'are' : 'is' - } already installed`) + if (installedModules.length > 0) { + const installedModulesList = installedModules.map(module => module.pkgName).join('\`, \`') + const are = installedModules.length > 1 ? 'are' : 'is' + logger.info(`\`${installedModulesList}\` ${are} already installed`) } - if (modulesGrouppedByInstallationStatus.notInstalled.length > 0) { + if (notInstalledModules.length > 0) { const isDev = Boolean(projectPkg.devDependencies?.nuxt) || dev - logger.info(`Installing \`${ - modulesGrouppedByInstallationStatus.notInstalled.map(module => module.pkg).join('\`, \`') - }\`${ - isDev ? ' development' : '' - } ${ - modulesGrouppedByInstallationStatus.notInstalled.length > 1 ? 'dependencies' : 'dependency' - }`) - - const res = await addDependency( - modulesGrouppedByInstallationStatus.notInstalled.map(module => module.pkg), - { cwd, dev: isDev, installPeerDependencies: true }, - ).catch( + const notInstalledModulesList = notInstalledModules.map(module => module.pkg).join('\`, \`') + const dependencies = notInstalledModules.length > 1 ? 'dependencies' : 'a dependency' + logger.info(`Installing \`${notInstalledModulesList} as\`${isDev ? ' development' : ''} ${dependencies}`) + + const res = await addDependency(notInstalledModules.map(module => module.pkg), { + cwd, + dev: isDev, + installPeerDependencies: true, + }).catch( (error) => { logger.error(error) - return logger.prompt( - `Install failed for \`${ - modulesGrouppedByInstallationStatus.notInstalled.map(module => colors.cyan(module.pkg)).join('\`, \`') - }\`. Do you want to continue adding the module${ - modulesGrouppedByInstallationStatus.notInstalled.length > 1 ? 's' : '' - } to ${colors.cyan('nuxt.config')}?`, - { - type: 'confirm', - initial: false, - }, - ) + const failedModulesList = notInstalledModules.map(module => colors.cyan(module.pkg)).join('\`, \`') + const s = notInstalledModules.length > 1 ? 's' : '' + return logger.prompt(`Install failed for \`${failedModulesList}\`. Do you want to continue adding the module${s} to ${colors.cyan('nuxt.config')}?`, { + type: 'confirm', + initial: false, + }) }, ) From 286767a00ad27f0f9790b331af92ef3499763bf4 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 9 Jan 2025 15:57:06 +0100 Subject: [PATCH 4/4] fix: move article to correct location --- src/commands/module/add.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/commands/module/add.ts b/src/commands/module/add.ts index a66d40322..e162014bf 100644 --- a/src/commands/module/add.ts +++ b/src/commands/module/add.ts @@ -124,8 +124,9 @@ async function addModules(modules: ResolvedModule[], { skipInstall, skipConfig, const isDev = Boolean(projectPkg.devDependencies?.nuxt) || dev const notInstalledModulesList = notInstalledModules.map(module => module.pkg).join('\`, \`') - const dependencies = notInstalledModules.length > 1 ? 'dependencies' : 'a dependency' - logger.info(`Installing \`${notInstalledModulesList} as\`${isDev ? ' development' : ''} ${dependencies}`) + const dependency = notInstalledModules.length > 1 ? 'dependencies' : 'dependency' + const a = notInstalledModules.length > 1 ? '' : ' a' + logger.info(`Installing \`${notInstalledModulesList} as${a}\`${isDev ? ' development' : ''} ${dependency}`) const res = await addDependency(notInstalledModules.map(module => module.pkg), { cwd,