import { BaseContext , Builtins , Cli , Command , Option , UsageError } from 'clipanion' ; import { Engine } from './Engine' ; import { DisableCommand } from './commands/Disable' ; import { EnableCommand } from './commands/Enable' ; import { HydrateCommand } from './commands/Hydrate' ; import { PrepareCommand } from './commands/Prepare' ; import * as miscUtils from './miscUtils' ; import * as corepackUtils from './corepackUtils' ; import * as specUtils from './specUtils' ; import { Locator , SupportedPackageManagers , Descriptor } from './types' ; export type CustomContext = { cwd : string ; engine : Engine ; } ; export type Context = BaseContext & CustomContext ; type PackageManagerRequest = { packageManager : SupportedPackageManagers ; binaryName : string ; binaryVersion : string | null ; } ; function getPackageManagerRequestFromCli ( parameter , context ) { if ( ! parameter ) return null ; const match = parameter . match ( /^([^@]*)(?:@(.*))?$/ ) ; if ( ! match ) return null ; const [ , binaryName , binaryVersion ] = match ; const packageManager = context . engine . getPackageManagerFor ( binaryName ) ; if ( ! packageManager ) return null ; return { packageManager , binaryName , binaryVersion : binaryVersion || null , } ; } async function executePackageManagerRequest ( { packageManager , binaryName , binaryVersion } , args , context ) { const defaultVersion = await context . engine . getDefaultVersion ( packageManager ) ; const definition = context . engine . config . definitions [ packageManager ] ! ; let isTransparentCommand = false ; for ( const transparentPath of definition . transparent . commands ) { if ( transparentPath [ 0 ] === binaryName && transparentPath . slice ( 1 ) . every ( ( segment , index ) => segment === args [ index ] ) ) { isTransparentCommand = true ; break ; } } const fallbackReference = isTransparentCommand ? definition . transparent . default ?? defaultVersion : defaultVersion ; const fallbackLocator = { name : packageManager , reference : fallbackReference , } ; let descriptor ; try { descriptor = await specUtils . findProjectSpec ( context . cwd , fallbackLocator , { transparent : isTransparentCommand } ) ; } catch ( err ) { if ( err instanceof miscUtils . Cancellation ) { return 1 ; } else { throw err ; } } if ( binaryVersion ) descriptor . range = binaryVersion ; const resolved = await context . engine . resolveDescriptor ( descriptor , { allowTags : true } ) ; if ( resolved === null ) throw new UsageError ( `Failed to successfully resolve '${ descriptor . range }' to a valid ${ descriptor . name } release` ) ; const installSpec = await context . engine . ensurePackageManager ( resolved ) ; const exitCode = await corepackUtils . runVersion ( installSpec , resolved , binaryName , args , context ) ; return exitCode ; } export async function main ( argv , context ) { const corepackVersion = require ( `../package.json` ) . version ; const [ firstArg , ... restArgs ] = argv ; const request = getPackageManagerRequestFromCli ( firstArg , context ) ; let cli ; if ( ! request ) { cli = new Cli ( { binaryLabel : `Corepack` , binaryName : `corepack` , binaryVersion : corepackVersion , } ) ; cli . register ( Builtins . HelpCommand ) ; cli . register ( Builtins . VersionCommand ) ; cli . register ( EnableCommand ) ; cli . register ( DisableCommand ) ; cli . register ( HydrateCommand ) ; cli . register ( PrepareCommand ) ; return await cli . run ( argv , { ... Cli . defaultContext , ... context , } ) ; } else { const cli = new Cli ( { binaryLabel : `'${ request . binaryName }', via Corepack` , binaryName : request . binaryName , binaryVersion : `corepack/${ corepackVersion }` , } ) ; cli . register ( class BinaryCommand extends Command < Context > { proxy = Option . Proxy ( ) ; async execute ( ) { return executePackageManagerRequest ( request , this . proxy , this . context ) ; } } ) ; return await cli . run ( restArgs , { ... Cli . defaultContext , ... context , } ) ; } } export function runMain ( argv ) { main ( argv , { cwd : process . cwd ( ) , engine : new Engine ( ) , } ) . then ( exitCode => { process . exitCode = exitCode ; } , err => { console . error ( err . stack ) ; process . exitCode = 1 ; } ) ; } if ( process . mainModule === eval ( `module` ) ) runMain ( process . argv . slice ( 2 ) ) ;