import { cwd , getWorkspaces , PackageJson , DependencyType } from './utils' ; import { cyan , green , yellow } from 'kleur' ; import { writeJson } from 'fs-extra' ; import { gt , satisfies } from 'semver' ; import latest from 'latest-version' ; import prompts from 'prompts' ; import pMap from 'p-map' ; import ora from 'ora' ; interface Workspace { dirty ? : boolean ; path : string ; meta : PackageJson ; } interface Dependency { version ? : string ; dependents : { name : string ; type : DependencyType ; } [ ] ; } ( async ( ) => { const workspaces = { } ; const dependencies = { } ; function loadPackage ( path ) { let meta ; try { meta = require ( `../${ path }/package` ) ; } catch { return ; } const { name } = meta ; workspaces [ name ] = { meta , path } ; delete dependencies [ name ] ; for ( const type of [ 'dependencies' , 'devDependencies' , 'peerDependencies' , 'optionalDependencies' ] as const ) { for ( const dep in meta [ type ] || { } ) { const version = meta [ type ] [ dep ] ; if ( workspaces [ dep ] || version === '*' || version . includes ( ':' ) ) continue ; if ( ! dependencies [ dep ] ) dependencies [ dep ] = { dependents : [ ] } ; dependencies [ dep ] . dependents . push ( { name , type } ) ; } } } loadPackage ( '' ) ; for ( const name of await getWorkspaces ( ) ) { loadPackage ( name ) ; } const depNames = Object . keys ( dependencies ) ; const spinner = ora ( `progress: 0/${ depNames . length }` ) . start ( ) ; let progress = 0 ; await pMap ( depNames , async ( dep ) => { const version = await latest ( dep ) ; progress ++ ; spinner . text = `progress: ${ progress }/${ depNames . length }` ; return dependencies [ dep ] . version = version . trim ( ) ; } , { concurrency : 10 } ) ; spinner . succeed ( ) ; const bumpMap = new Map < string , boolean > ( ) ; async function shouldBump ( name , dep , version , oldVersion ) { if ( ! gt ( version , oldVersion . replace ( /^[~^]/ , '' ) ) ) return ; const message = `${ name } > ${ yellow ( dep ) }: ${ cyan ( oldVersion ) } -> ${ green ( version ) }` ; if ( satisfies ( version , oldVersion ) ) return message ; let result = bumpMap . get ( dep ) ; if ( result === undefined ) { const data = await prompts ( { name : 'value' , type : 'confirm' , message , } ) ; result = data . value ; bumpMap . set ( dep , result ) ; } return result && message ; } const output = [ ] ; for ( const dep in dependencies ) { const { version , dependents } = dependencies [ dep ] ; for ( const { name , type } of dependents ) { const workspace = workspaces [ name ] ; const oldVersion = workspace . meta [ type ] [ dep ] ; const message = await shouldBump ( name , dep , version , oldVersion ) ; if ( message ) { workspace . dirty = true ; workspace . meta [ type ] [ dep ] = '^' + version ; output . push ( message ) ; } } } await pMap ( Object . keys ( workspaces ) , ( name ) => { const workspace = workspaces [ name ] ; if ( ! workspace . dirty ) return ; return writeJson ( `${ cwd }/${ workspace . path }/package.json` , workspace . meta , { spaces : 2 } ) ; } ) ; console . log ( output . sort ( ) . join ( '\n' ) ) ; } ) ( ) ;