1import JsonFile from '@expo/json-file';
2import chalk from 'chalk';
3import fs from 'fs';
4
5import * as Log from '../../../log';
6
7export const baseTSConfigName = 'expo/tsconfig.base';
8
9export async function updateTSConfigAsync({
10  tsConfigPath,
11}: {
12  tsConfigPath: string;
13}): Promise<void> {
14  const shouldGenerate = !fs.existsSync(tsConfigPath) || fs.statSync(tsConfigPath).size === 0;
15  if (shouldGenerate) {
16    await JsonFile.writeAsync(tsConfigPath, { compilerOptions: {} });
17  }
18
19  const projectTSConfig = JsonFile.read(tsConfigPath, {
20    // Some tsconfig.json files have a generated comment in the file.
21    json5: true,
22  });
23
24  projectTSConfig.compilerOptions ??= {};
25
26  const modifications: [string, string][] = [];
27
28  // If the extends field isn't defined, set it to the expo default
29  if (!projectTSConfig.extends) {
30    // if (projectTSConfig.extends !== baseTSConfigName) {
31    projectTSConfig.extends = baseTSConfigName;
32    modifications.push(['extends', baseTSConfigName]);
33  }
34
35  // If no changes, then quietly bail out
36  if (!modifications.length) {
37    return;
38  }
39
40  // Write changes and log out a summary of what changed
41  await JsonFile.writeAsync(tsConfigPath, projectTSConfig);
42
43  // If no changes, then quietly bail out
44  if (modifications.length === 0) {
45    return;
46  }
47
48  Log.log();
49
50  if (shouldGenerate) {
51    Log.log(chalk`{bold TypeScript}: A {cyan tsconfig.json} has been auto-generated`);
52  } else {
53    Log.log(
54      chalk`{bold TypeScript}: The {cyan tsconfig.json} has been updated {dim (Use EXPO_NO_TYPESCRIPT_SETUP to skip)}`
55    );
56    logModifications(modifications);
57  }
58  Log.log();
59}
60
61function logModifications(modifications: string[][]) {
62  Log.log();
63
64  Log.log(chalk`\u203A {bold Required} modifications made to the {cyan tsconfig.json}:`);
65
66  Log.log();
67
68  // Sort the items based on key name length
69  printTable(modifications.sort((a, b) => a[0].length - b[0].length));
70
71  Log.log();
72}
73
74function printTable(items: string[][]) {
75  const tableFormat = (name: string, msg: string) =>
76    `  ${chalk.bold`${name}`} is now ${chalk.cyan(msg)}`;
77  for (const [key, value] of items) {
78    Log.log(tableFormat(key, value));
79  }
80}
81