import type { Capability , KitCapabilities } from "@rnx-kit/config" ; import type { PackageManifest } from "@rnx-kit/tools-node/package" ; import semver from "semver" ; import { getProfilesFor , getProfileVersionsFor } from "./profiles" ; import { concatVersionRanges , keysOf } from "./helpers" ; import type { CapabilitiesOptions , MetaPackage , Package , Profile , } from "./types" ; export function capabilitiesFor ( { dependencies , devDependencies , peerDependencies } , { kitType = "library" , customProfilesPath } = { } ) { const targetReactNativeVersion = peerDependencies ?. [ "react-native" ] || dependencies ?. [ "react-native" ] ; if ( ! targetReactNativeVersion ) { return undefined ; } const profiles = getProfilesFor ( targetReactNativeVersion , customProfilesPath ) ; const packageToCapabilityMap = { } ; profiles . forEach ( ( profile ) => { keysOf ( profile ) . reduce ( ( result , capability ) => { const { name } = profile [ capability ] ; if ( ! result [ name ] ) { result [ name ] = [ capability ] ; } else { result [ name ] . push ( capability ) ; } return result ; } , packageToCapabilityMap ) ; } ) ; const reactNativeVersion = concatVersionRanges ( getProfileVersionsFor ( targetReactNativeVersion ) ) ; return { reactNativeVersion , ... ( kitType === "library" ? { reactNativeDevVersion : devDependencies ?. [ "react-native" ] || semver . minVersion ( reactNativeVersion ) ?. version } : undefined ) , kitType , capabilities : Array . from ( keysOf ( { ... dependencies , ... peerDependencies , ... devDependencies } ) . reduce < Set < Capability > > ( ( result , dependency ) => { if ( dependency in packageToCapabilityMap ) { packageToCapabilityMap [ dependency ] . forEach ( ( capability ) => { result . add ( capability ) ; } ) ; } return result ; } , new Set < Capability > ( ) ) ) . sort ( ) } ; } export function isMetaPackage ( pkg ) { return pkg . name === "#meta" && Array . isArray ( pkg . capabilities ) ; } function resolveCapability ( capability , profile , dependencies , unresolvedCapabilities , resolved = new Set < string > ( ) ) { if ( resolved . has ( capability ) ) { return ; } resolved . add ( capability ) ; const pkg = profile [ capability ] ; if ( ! pkg ) { unresolvedCapabilities . add ( capability ) ; return ; } pkg . capabilities ?. forEach ( ( capability ) => resolveCapability ( capability , profile , dependencies , unresolvedCapabilities , resolved ) ) ; if ( ! isMetaPackage ( pkg ) ) { const { name , version } = pkg ; if ( name in dependencies ) { const versions = dependencies [ name ] ; if ( ! versions . find ( ( current ) => current . version === version ) ) { versions . push ( pkg ) ; } } else { dependencies [ name ] = [ pkg ] ; } } } export function resolveCapabilities ( capabilities , profiles ) { const unresolvedCapabilities = new Set < string > ( ) ; const packages = capabilities . reduce < Record < string , Package [ ] > > ( ( dependencies , capability ) => { profiles . forEach ( ( profile ) => { resolveCapability ( capability , profile , dependencies , unresolvedCapabilities ) ; } ) ; return dependencies ; } , { } ) ; if ( unresolvedCapabilities . size > 0 ) { const message = Array . from ( unresolvedCapabilities ) . reduce ( ( lines , capability ) => ( lines += `\n    ${ capability }` ) , "The following capabilities could not be resolved for one or more profiles:" ) ; console . warn ( message ) ; } return packages ; }