1import JsonFile from '@expo/json-file'; 2import chalk from 'chalk'; 3import path from 'path'; 4 5import { EXPO_DIR } from '../../Constants'; 6import logger from '../../Logger'; 7import { Task } from '../../TasksRunner'; 8import * as Workspace from '../../Workspace'; 9import { Parcel, TaskArgs } from '../types'; 10 11const { green, yellow, cyan } = chalk; 12 13/** 14 * Updates versions of packages to be published in other workspace projects depending on them. 15 */ 16export const updateWorkspaceProjects = new Task<TaskArgs>( 17 { 18 name: 'updateWorkspaceProjects', 19 filesToStage: ['**/package.json', 'yarn.lock'], 20 }, 21 async (parcels: Parcel[]) => { 22 logger.info('\n Updating workspace projects...'); 23 24 const workspaceInfo = await Workspace.getInfoAsync(); 25 const dependenciesKeys = ['dependencies', 'devDependencies', 'peerDependencies']; 26 27 const parcelsObject = parcels.reduce((acc, parcel) => { 28 acc[parcel.pkg.packageName] = parcel; 29 return acc; 30 }, {}); 31 32 await Promise.all( 33 Object.entries(workspaceInfo).map(async ([projectName, projectInfo]) => { 34 const projectDependencies = [ 35 ...projectInfo.workspaceDependencies, 36 ...projectInfo.mismatchedWorkspaceDependencies, 37 ] 38 .map((dependencyName) => parcelsObject[dependencyName]) 39 .filter(Boolean); 40 41 // If this project doesn't depend on any package we're going to publish. 42 if (projectDependencies.length === 0) { 43 return; 44 } 45 46 // Get copy of project's `package.json`. 47 const projectPackageJsonPath = path.join(EXPO_DIR, projectInfo.location, 'package.json'); 48 const projectPackageJson = await JsonFile.readAsync(projectPackageJsonPath); 49 const batch = logger.batch(); 50 51 batch.log(' ', green(projectName)); 52 53 // Iterate through different dependencies types. 54 for (const dependenciesKey of dependenciesKeys) { 55 const dependenciesObject = projectPackageJson[dependenciesKey]; 56 57 if (!dependenciesObject) { 58 continue; 59 } 60 61 for (const { pkg, state } of projectDependencies) { 62 const currentVersionRange = dependenciesObject[pkg.packageName]; 63 64 if (!currentVersionRange) { 65 continue; 66 } 67 68 // Leave tilde and caret as they are, just replace the version. 69 const newVersionRange = currentVersionRange.replace( 70 /([\^~]?).*/, 71 `$1${state.releaseVersion}` 72 ); 73 dependenciesObject[pkg.packageName] = newVersionRange; 74 75 batch.log( 76 ' ', 77 `Updating ${yellow(`${dependenciesKey}.${pkg.packageName}`)}`, 78 `from ${cyan(currentVersionRange)} to ${cyan(newVersionRange)}` 79 ); 80 } 81 } 82 83 // Save project's `package.json`. 84 await JsonFile.writeAsync(projectPackageJsonPath, projectPackageJson); 85 86 // Flush batched logs. 87 batch.flush(); 88 }) 89 ); 90 } 91); 92