1import JsonFile from '@expo/json-file';
2import chalk from 'chalk';
3import path from 'path';
4
5import logger from '../../Logger';
6import { getPackageByName, Package } from '../../Packages';
7import { Task } from '../../TasksRunner';
8import { Parcel, TaskArgs } from '../types';
9import { selectPackagesToPublish } from './selectPackagesToPublish';
10
11const { cyan, green } = chalk;
12const MODULE_TEMPLATE_PKG_NAME = 'expo-module-template';
13const TEMPLATE_PACKAGE_JSON_FILENAME = '$package.json';
14const PACKAGES_TO_UPDATE = ['expo-modules-core', 'expo-module-scripts'];
15
16/**
17 * Updates the module template if necessary.
18 */
19export const updateModuleTemplate = new Task<TaskArgs>(
20  {
21    name: 'updateModuleTemplate',
22    dependsOn: [selectPackagesToPublish],
23    filesToStage: [`packages/${MODULE_TEMPLATE_PKG_NAME}/${TEMPLATE_PACKAGE_JSON_FILENAME}`],
24  },
25  async (parcels: Parcel[]) => {
26    logger.info('\n�� Updating the module template...');
27
28    const dependencies = parcels.filter((parcel) =>
29      PACKAGES_TO_UPDATE.includes(parcel.pkg.packageName)
30    );
31
32    if (dependencies.length === 0) {
33      logger.debug('Yay, there is no need to update the module template ��');
34      return;
35    }
36
37    const moduleTemplatePkg = getPackageByName(MODULE_TEMPLATE_PKG_NAME);
38
39    if (!moduleTemplatePkg) {
40      logger.error(
41        `❗️ Unable to find the module template package: ${green(MODULE_TEMPLATE_PKG_NAME)}`
42      );
43      return;
44    }
45
46    await updateTemplatePackageJsonAsync(moduleTemplatePkg, dependencies);
47  }
48);
49
50async function updateTemplatePackageJsonAsync(
51  templatePkg: Package,
52  dependencies: Parcel[]
53): Promise<void> {
54  const packageJsonPath = path.join(templatePkg.path, TEMPLATE_PACKAGE_JSON_FILENAME);
55  const packageJson = await JsonFile.readAsync(packageJsonPath);
56
57  for (const { pkg, state } of dependencies) {
58    const newVersion = state.releaseVersion;
59    const oldVersion = packageJson.devDependencies?.[pkg.packageName];
60
61    if (!newVersion || !oldVersion || oldVersion === newVersion) {
62      continue;
63    }
64
65    const newVersionRange = '^' + newVersion;
66
67    logger.log(
68      `   Updating dev dependency on ${green(pkg.packageName)}:`,
69      `${cyan.bold(oldVersion)} -> ${cyan.bold(newVersionRange)}`
70    );
71
72    if (packageJson.devDependencies) {
73      packageJson.devDependencies[pkg.packageName] = newVersionRange;
74    }
75  }
76
77  // Save the template for package.json
78  await JsonFile.writeAsync(packageJsonPath, packageJson);
79}
80