1082815dcSEvan Baconimport { ExpoConfig } from '@expo/config-types'; 2082815dcSEvan Bacon 3082815dcSEvan Baconimport { InfoPlist, URLScheme } from './IosConfig.types'; 4*8a424bebSJames Ideimport { createInfoPlistPluginWithPropertyGuard } from '../plugins/ios-plugins'; 5082815dcSEvan Bacon 6082815dcSEvan Baconexport const withScheme = createInfoPlistPluginWithPropertyGuard( 7082815dcSEvan Bacon setScheme, 8082815dcSEvan Bacon { 9082815dcSEvan Bacon infoPlistProperty: 'CFBundleURLTypes', 10082815dcSEvan Bacon expoConfigProperty: 'scheme', 11082815dcSEvan Bacon }, 12082815dcSEvan Bacon 'withScheme' 13082815dcSEvan Bacon); 14082815dcSEvan Bacon 15082815dcSEvan Baconexport function getScheme(config: { scheme?: string | string[] }): string[] { 16082815dcSEvan Bacon if (Array.isArray(config.scheme)) { 17082815dcSEvan Bacon const validate = (value: any): value is string => { 18082815dcSEvan Bacon return typeof value === 'string'; 19082815dcSEvan Bacon }; 20082815dcSEvan Bacon return config.scheme.filter<string>(validate); 21082815dcSEvan Bacon } else if (typeof config.scheme === 'string') { 22082815dcSEvan Bacon return [config.scheme]; 23082815dcSEvan Bacon } 24082815dcSEvan Bacon return []; 25082815dcSEvan Bacon} 26082815dcSEvan Bacon 27082815dcSEvan Baconexport function setScheme( 28082815dcSEvan Bacon config: Partial<Pick<ExpoConfig, 'scheme' | 'ios'>>, 29082815dcSEvan Bacon infoPlist: InfoPlist 30082815dcSEvan Bacon): InfoPlist { 31082815dcSEvan Bacon const scheme = [ 32082815dcSEvan Bacon ...getScheme(config), 33082815dcSEvan Bacon // @ts-ignore: TODO: ios.scheme is an unreleased -- harder to add to turtle v1. 34082815dcSEvan Bacon ...getScheme(config.ios ?? {}), 35082815dcSEvan Bacon ]; 36082815dcSEvan Bacon // Add the bundle identifier to the list of schemes for easier Google auth and parity with Turtle v1. 37082815dcSEvan Bacon if (config.ios?.bundleIdentifier) { 38082815dcSEvan Bacon scheme.push(config.ios.bundleIdentifier); 39082815dcSEvan Bacon } 40082815dcSEvan Bacon if (scheme.length === 0) { 41082815dcSEvan Bacon return infoPlist; 42082815dcSEvan Bacon } 43082815dcSEvan Bacon 44082815dcSEvan Bacon return { 45082815dcSEvan Bacon ...infoPlist, 46082815dcSEvan Bacon CFBundleURLTypes: [{ CFBundleURLSchemes: scheme }], 47082815dcSEvan Bacon }; 48082815dcSEvan Bacon} 49082815dcSEvan Bacon 50082815dcSEvan Baconexport function appendScheme(scheme: string | null, infoPlist: InfoPlist): InfoPlist { 51082815dcSEvan Bacon if (!scheme) { 52082815dcSEvan Bacon return infoPlist; 53082815dcSEvan Bacon } 54082815dcSEvan Bacon 55082815dcSEvan Bacon const existingSchemes = infoPlist.CFBundleURLTypes ?? []; 56e9630418SEvan Bacon if (existingSchemes?.some(({ CFBundleURLSchemes }) => CFBundleURLSchemes.includes(scheme))) { 57082815dcSEvan Bacon return infoPlist; 58082815dcSEvan Bacon } 59082815dcSEvan Bacon 60082815dcSEvan Bacon return { 61082815dcSEvan Bacon ...infoPlist, 62082815dcSEvan Bacon CFBundleURLTypes: [ 63082815dcSEvan Bacon ...existingSchemes, 64082815dcSEvan Bacon { 65082815dcSEvan Bacon CFBundleURLSchemes: [scheme], 66082815dcSEvan Bacon }, 67082815dcSEvan Bacon ], 68082815dcSEvan Bacon }; 69082815dcSEvan Bacon} 70082815dcSEvan Bacon 71082815dcSEvan Baconexport function removeScheme(scheme: string | null, infoPlist: InfoPlist): InfoPlist { 72082815dcSEvan Bacon if (!scheme) { 73082815dcSEvan Bacon return infoPlist; 74082815dcSEvan Bacon } 75082815dcSEvan Bacon 76082815dcSEvan Bacon // No need to remove if we don't have any 77082815dcSEvan Bacon if (!infoPlist.CFBundleURLTypes) { 78082815dcSEvan Bacon return infoPlist; 79082815dcSEvan Bacon } 80082815dcSEvan Bacon 81082815dcSEvan Bacon infoPlist.CFBundleURLTypes = infoPlist.CFBundleURLTypes.map((bundleUrlType) => { 82082815dcSEvan Bacon const index = bundleUrlType.CFBundleURLSchemes.indexOf(scheme); 83082815dcSEvan Bacon if (index > -1) { 84082815dcSEvan Bacon bundleUrlType.CFBundleURLSchemes.splice(index, 1); 85082815dcSEvan Bacon if (bundleUrlType.CFBundleURLSchemes.length === 0) { 86082815dcSEvan Bacon return undefined; 87082815dcSEvan Bacon } 88082815dcSEvan Bacon } 89082815dcSEvan Bacon return bundleUrlType; 90082815dcSEvan Bacon }).filter(Boolean) as URLScheme[]; 91082815dcSEvan Bacon 92082815dcSEvan Bacon return infoPlist; 93082815dcSEvan Bacon} 94082815dcSEvan Bacon 95082815dcSEvan Baconexport function hasScheme(scheme: string, infoPlist: InfoPlist): boolean { 96082815dcSEvan Bacon const existingSchemes = infoPlist.CFBundleURLTypes; 97082815dcSEvan Bacon 98082815dcSEvan Bacon if (!Array.isArray(existingSchemes)) return false; 99082815dcSEvan Bacon 100e9630418SEvan Bacon return existingSchemes?.some(({ CFBundleURLSchemes: schemes }: any) => 101082815dcSEvan Bacon Array.isArray(schemes) ? schemes.includes(scheme) : false 102082815dcSEvan Bacon ); 103082815dcSEvan Bacon} 104082815dcSEvan Bacon 105082815dcSEvan Baconexport function getSchemesFromPlist(infoPlist: InfoPlist): string[] { 106082815dcSEvan Bacon if (Array.isArray(infoPlist.CFBundleURLTypes)) { 107082815dcSEvan Bacon return infoPlist.CFBundleURLTypes.reduce<string[]>((schemes, { CFBundleURLSchemes }) => { 108082815dcSEvan Bacon if (Array.isArray(CFBundleURLSchemes)) { 109082815dcSEvan Bacon return [...schemes, ...CFBundleURLSchemes]; 110082815dcSEvan Bacon } 111082815dcSEvan Bacon return schemes; 112082815dcSEvan Bacon }, []); 113082815dcSEvan Bacon } 114082815dcSEvan Bacon return []; 115082815dcSEvan Bacon} 116