UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

162 lines (137 loc) 5.61 kB
import { buildSchema, SchemaValues } from '@sprucelabs/schema' import { diskUtil } from '@sprucelabs/spruce-skill-utils' import { uniqBy } from 'lodash' import InFlightEntertainment from '../../../InFlightEntertainment' import PkgService from '../../../services/PkgService' import { NpmPackage } from '../../../types/cli.types' import AbstractAction from '../../AbstractAction' import { FeatureActionResponse } from '../../features.types' const optionsSchema = buildSchema({ id: 'updateDependenciesAction', description: 'Clear lock files and node_modules and then reinstalls all modules.', fields: {}, }) type OptionsSchema = typeof optionsSchema type Options = SchemaValues<OptionsSchema> export default class UpdateDependenciesAction extends AbstractAction<OptionsSchema> { public code = 'updateDependencies' public optionsSchema = optionsSchema public commandAliases = ['update.dependencies', 'upgrade.dependencies'] public invocationMessage = 'Updating dependencies... 💪' public async execute(_options: Options): Promise<FeatureActionResponse> { const files = ['package-lock.json', 'yarn.lock', 'node_modules'] for (const file of files) { diskUtil.deleteFile(diskUtil.resolvePath(this.cwd, file)) } try { InFlightEntertainment.start(['Here we go!', 'Good luck!']) const { totalDependencies, totalDevDependencies } = await this.installDependencies() return { headline: 'Update Complete!', summaryLines: [ `${totalDependencies} dependencie${ totalDependencies === 1 ? '' : 's' } updated! 💪`, `${totalDevDependencies} dev dependencie${ totalDevDependencies === 1 ? '' : 's' } updated! 💪`, ], } } finally { InFlightEntertainment.stop() } } private async installDependencies() { const features = this.features.isInSpruceModule() ? await this.features.getInstalledFeatures() : [] const pkg = this.Service('pkg') pkg.unset(['dependencies', '@sprucelabs/resolve-path-aliases']) const pkgContents = pkg.readPackage() let dependencies: { stripped: string; name: string }[] = Object.keys(pkgContents.dependencies ?? {}).map((d) => ({ stripped: d, name: d, })) ?? [] let devDependencies: { stripped: string; name: string }[] = Object.keys(pkgContents.devDependencies ?? {}).map((d) => ({ stripped: d, name: d, })) ?? [] for (const feature of features) { for (const dep of feature.packageDependencies as NpmPackage[]) { const stripped = pkg.stripLatest(dep.name) const name = pkg.buildPackageName(dep) const isDev = (dep.isDev || devDependencies.find((d) => d.stripped === stripped)) && !dependencies.find((d) => d.stripped === stripped) if (isDev) { devDependencies.unshift({ stripped, name, }) } else { dependencies.unshift({ stripped, name, }) } } } dependencies = uniqBy(dependencies, 'stripped').filter( (d) => !this.isBlockedFromUpgrade(d.stripped, pkg) ) devDependencies = uniqBy(devDependencies, 'stripped').filter( (d) => !this.isBlockedFromUpgrade(d.stripped, pkg) ) pkg.deleteLockFile() const namespace = pkg.getSkillNamespace() if (dependencies.length > 0) { InFlightEntertainment.writeStatus( `Installing ${dependencies.length} dependenc${ dependencies.length === 1 ? 'y' : 'ies' } for ${namespace}.` ) await pkg.install( dependencies.map((d) => d.name), { shouldForceInstall: true, shouldCleanupLockFiles: false, } ) } if (devDependencies.length > 0) { InFlightEntertainment.writeStatus( `Installing ${devDependencies.length} dev dependenc${ dependencies.length === 1 ? 'y' : 'ies' } for ${namespace}.` ) await pkg.install( devDependencies.map((d) => d.name), { shouldForceInstall: true, isDev: true, shouldCleanupLockFiles: false, } ) } pkg.deleteLockFile() return { totalDependencies: dependencies.length, totalDevDependencies: devDependencies.length, } } public blockUpgrade(name: string, pkg: PkgService) { const content = pkg.get('skill.upgradeIgnoreList') ?? [] content.push(name) pkg.set({ path: 'skill.upgradeIgnoreList', value: content }) } public isBlockedFromUpgrade(name: string, pkg: PkgService) { const content = pkg.get('skill.upgradeIgnoreList') ?? [] const isBlocked = content.indexOf(name) > -1 return isBlocked } }