1import JsonFile, { JSONObject } from '@expo/json-file'; 2import chalk from 'chalk'; 3import path from 'path'; 4 5import { Log } from '../../../log'; 6 7/** 8 * Force updates a project tsconfig with Expo values. 9 */ 10export async function forceUpdateTSConfig(projectRoot: string) { 11 // This runs after the TypeScript prerequisite, so we know the tsconfig.json exists 12 const tsConfigPath = path.join(projectRoot, 'tsconfig.json'); 13 const { tsConfig, updates } = getTSConfigUpdates( 14 JsonFile.read(tsConfigPath, { 15 json5: true, 16 }) 17 ); 18 19 await writeUpdates(tsConfigPath, tsConfig, updates); 20} 21 22export function getTSConfigUpdates(tsConfig: JSONObject) { 23 const updates = new Set<string>(); 24 25 if (!tsConfig.include) { 26 tsConfig.include = ['**/*.ts', '**/*.tsx', '.expo/types/**/*.ts', 'expo-env.d.ts']; 27 updates.add('include'); 28 } else if (Array.isArray(tsConfig.include)) { 29 if (!tsConfig.include.includes('.expo/types/**/*.ts')) { 30 tsConfig.include = [...tsConfig.include, '.expo/types/**/*.ts']; 31 updates.add('include'); 32 } 33 34 if (!tsConfig.include.includes('expo-env.d.ts')) { 35 tsConfig.include = [...tsConfig.include, 'expo-env.d.ts']; 36 updates.add('include'); 37 } 38 } 39 40 return { tsConfig, updates }; 41} 42 43export async function forceRemovalTSConfig(projectRoot: string) { 44 // This runs after the TypeScript prerequisite, so we know the tsconfig.json exists 45 const tsConfigPath = path.join(projectRoot, 'tsconfig.json'); 46 const { tsConfig, updates } = getTSConfigRemoveUpdates( 47 JsonFile.read(tsConfigPath, { 48 json5: true, 49 }) 50 ); 51 52 await writeUpdates(tsConfigPath, tsConfig, updates); 53} 54 55export function getTSConfigRemoveUpdates(tsConfig: JSONObject) { 56 const updates = new Set<string>(); 57 58 if (Array.isArray(tsConfig.include)) { 59 const filtered = (tsConfig.include as string[]).filter( 60 (i) => i !== 'expo-env.d.ts' && i !== '.expo/types/**/*.ts' 61 ); 62 63 if (filtered.length !== tsConfig.include.length) { 64 updates.add('include'); 65 } 66 67 tsConfig.include = filtered; 68 } 69 70 return { tsConfig, updates }; 71} 72 73async function writeUpdates(tsConfigPath: string, tsConfig: JSONObject, updates: Set<string>) { 74 if (updates.size) { 75 await JsonFile.writeAsync(tsConfigPath, tsConfig); 76 for (const update of updates) { 77 Log.log( 78 chalk`{bold TypeScript}: The {cyan tsconfig.json#${update}} property has been updated` 79 ); 80 } 81 } 82} 83