import type { KitType } from "@rnx-kit/config" ; import { error } from "@rnx-kit/console" ; import { hasProperty } from "@rnx-kit/tools-language/properties" ; import { findPackageDir } from "@rnx-kit/tools-node/package" ; import isString from "lodash/isString" ; import * as path from "path" ; import { getAllPackageJsonFiles , getWorkspaceRoot } from "workspace-tools" ; import { makeCheckCommand } from "./check" ; import { initializeConfig } from "./initialize" ; import { resolveCustomProfiles } from "./profiles" ; import { makeSetVersionCommand } from "./setVersion" ; import type { Args , Command } from "./types" ; import { makeVigilantCommand } from "./vigilant" ; function ensureKitType ( type ) { switch ( type ) { case "app" : case "library" : return type ; default : return undefined ; } } function getManifests ( packageJson ) { if ( isString ( packageJson ) && packageJson ) { return [ packageJson ] ; } const packageDir = findPackageDir ( ) ; if ( ! packageDir ) { return undefined ; } const currentPackageJson = path . join ( packageDir , "package.json" ) ; try { if ( getWorkspaceRoot ( packageDir ) !== packageDir ) { return [ currentPackageJson ] ; } } catch ( _ ) { return [ currentPackageJson ] ; } try { const allPackages = getAllPackageJsonFiles ( packageDir ) ?? [ ] ; allPackages . push ( currentPackageJson ) ; return allPackages ; } catch ( e ) { if ( hasProperty ( e , "message" ) ) { error ( e . message ) ; return undefined ; } throw e ; } } function makeInitializeCommand ( kitType ) { const verifiedKitType = ensureKitType ( kitType ) ; if ( ! verifiedKitType ) { error ( `Invalid kit type: '${ kitType }'` ) ; return undefined ; } const options = { kitType : verifiedKitType } ; return ( manifest ) => { initializeConfig ( manifest , options ) ; return 0 ; } ; } function reportConflicts ( conflicts , args ) { return conflicts . reduce < boolean > ( ( result , [ lhs , rhs ] ) => { if ( lhs in args && rhs in args ) { error ( `--${ lhs } and --${ rhs } cannot both be specified at the same time.` ) ; return true ; } return result ; } , false ) ; } async function makeCommand ( args ) { const conflicts = [ [ "init" , "vigilant" ] , [ "init" , args . write ? "write" : "no-write" ] , [ "set-version" , args . write ? "write" : "no-write" ] , ] ; if ( reportConflicts ( conflicts , args ) ) { return undefined ; } const { "custom-profiles" : customProfiles , "exclude-packages" : excludePackages , init , loose , "set-version" : setVersion , vigilant , write , } = args ; if ( isString ( init ) ) { return makeInitializeCommand ( init ) ; } if ( setVersion || isString ( setVersion ) ) { return makeSetVersionCommand ( setVersion ) ; } if ( isString ( vigilant ) ) { const customProfilesPath = resolveCustomProfiles ( process . cwd ( ) , customProfiles ?. toString ( ) ) ; return makeVigilantCommand ( { customProfiles : customProfilesPath , excludePackages : excludePackages ?. toString ( ) , loose , versions : vigilant . toString ( ) , write } ) ; } return makeCheckCommand ( { loose , write } ) ; } export async function cli ( { "package-json" : packageJson , ... args } ) { const command = await makeCommand ( args ) ; if ( ! command ) { process . exit ( 1 ) ; } const manifests = getManifests ( packageJson ) ; if ( ! manifests ) { error ( "Could not find package root" ) ; process . exit ( 1 ) ; } const exitCode = manifests . reduce ( ( exitCode , manifest ) => { try { return command ( manifest ) || exitCode ; } catch ( e ) { if ( hasProperty ( e , "message" ) ) { const currentPackageJson = path . relative ( process . cwd ( ) , manifest ) ; error ( `${ currentPackageJson }: ${ e . message }` ) ; return exitCode || 1 ; } throw e ; } } , 0 ) ; process . exit ( exitCode ) ; } if ( require . main === module ) { require ( "yargs" ) . usage ( "$0 [package-json]" , "Dependency checker for React Native apps" , { "custom-profiles" : { description : "Path to custom profiles. This can be a path to a JSON file, a `.js` file, or a module name." , type : "string" , requiresArg : true , implies : "vigilant" } , "exclude-packages" : { description : "Comma-separated list of package names to exclude from inspection." , type : "string" , requiresArg : true , implies : "vigilant" } , init : { description : "Writes an initial kit config to the specified 'package.json'." , choices : [ "app" , "library" ] , conflicts : [ "vigilant" ] } , loose : { default : false , description : "Determines how strict the React Native version requirement should be. Useful for apps that depend on a newer React Native version than their dependencies declare support for." , type : "boolean" } , "set-version" : { description : "Sets `reactNativeVersion` and `reactNativeDevVersion` for any configured package. There is an interactive prompt if no value is provided. The value should be a comma-separated list of `react-native` versions to set, where the first number specifies the development version. Example: `0.64,0.63`" , type : "string" , conflicts : [ "init" , "vigilant" ] } , vigilant : { description : "Inspects packages regardless of whether they've been configured. Specify a comma-separated list of profile versions to compare against, e.g. `0.63,0.64`. The first number specifies the target version." , type : "string" , requiresArg : true , conflicts : [ "init" ] } , write : { default : false , description : "Writes changes to the specified 'package.json'." , type : "boolean" } } , cli ) . argv ; }