xref: /expo/tools/src/Workspace.ts (revision a272999e)
19657025fSTomasz Sapetaimport JsonFile from '@expo/json-file';
2eeffdb10STomasz Sapetaimport path from 'path';
3eeffdb10STomasz Sapeta
4*a272999eSBartosz Kaszubowskiimport { EXPO_DIR } from './Constants';
5eeffdb10STomasz Sapetaimport { Package } from './Packages';
6eeffdb10STomasz Sapetaimport { spawnAsync, spawnJSONCommandAsync } from './Utils';
7eeffdb10STomasz Sapeta
8eeffdb10STomasz Sapetaconst NATIVE_APPS_PATHS = [EXPO_DIR, path.join(EXPO_DIR, 'apps/bare-expo')];
9eeffdb10STomasz Sapeta
10eeffdb10STomasz Sapeta/**
11eeffdb10STomasz Sapeta * Workspace info for the single project.
12eeffdb10STomasz Sapeta */
13eeffdb10STomasz Sapetaexport type WorkspaceProjectInfo = {
14eeffdb10STomasz Sapeta  location: string;
15eeffdb10STomasz Sapeta  workspaceDependencies: string[];
16eeffdb10STomasz Sapeta  mismatchedWorkspaceDependencies: string[];
17eeffdb10STomasz Sapeta};
18eeffdb10STomasz Sapeta
19eeffdb10STomasz Sapeta/**
20eeffdb10STomasz Sapeta * An object with workspace's projects info.
21eeffdb10STomasz Sapeta */
22eeffdb10STomasz Sapetaexport type WorkspacesInfo = Record<string, WorkspaceProjectInfo>;
23eeffdb10STomasz Sapeta
24eeffdb10STomasz Sapeta/**
25eeffdb10STomasz Sapeta * Returns an object containing info for all projects in the workspace.
26eeffdb10STomasz Sapeta */
27eeffdb10STomasz Sapetaexport async function getInfoAsync(): Promise<WorkspacesInfo> {
28eeffdb10STomasz Sapeta  const info = await spawnJSONCommandAsync<{ data: string }>('yarn', [
29eeffdb10STomasz Sapeta    '--json',
30eeffdb10STomasz Sapeta    'workspaces',
31eeffdb10STomasz Sapeta    'info',
32eeffdb10STomasz Sapeta  ]);
33eeffdb10STomasz Sapeta  return JSON.parse(info.data);
34eeffdb10STomasz Sapeta}
35eeffdb10STomasz Sapeta
36eeffdb10STomasz Sapeta/**
37eeffdb10STomasz Sapeta * Runs yarn in the root workspace directory.
38eeffdb10STomasz Sapeta */
39eeffdb10STomasz Sapetaexport async function installAsync(): Promise<void> {
40eeffdb10STomasz Sapeta  await spawnAsync('yarn');
41eeffdb10STomasz Sapeta}
42eeffdb10STomasz Sapeta
43eeffdb10STomasz Sapeta/**
44eeffdb10STomasz Sapeta * Returns an array of workspace's native apps, like Expo Client or BareExpo.
45eeffdb10STomasz Sapeta */
46eeffdb10STomasz Sapetaexport function getNativeApps(): Package[] {
47eeffdb10STomasz Sapeta  return NATIVE_APPS_PATHS.map((appPath) => new Package(appPath));
48eeffdb10STomasz Sapeta}
499657025fSTomasz Sapeta
509657025fSTomasz Sapeta/**
519657025fSTomasz Sapeta * Updates the dependency across all workspace projects to given version range.
529657025fSTomasz Sapeta */
539657025fSTomasz Sapetaexport async function updateDependencyAsync(dependencyName: string, versionRange: string) {
549657025fSTomasz Sapeta  const projectLocations = Object.values(await getInfoAsync()).map(
559657025fSTomasz Sapeta    (projectInfo) => projectInfo.location
569657025fSTomasz Sapeta  );
579657025fSTomasz Sapeta
589657025fSTomasz Sapeta  await Promise.all(
599657025fSTomasz Sapeta    projectLocations.map(async (location) => {
609657025fSTomasz Sapeta      const jsonFile = new JsonFile(path.join(EXPO_DIR, location, 'package.json'));
619657025fSTomasz Sapeta      const packageJson = await jsonFile.readAsync();
629657025fSTomasz Sapeta
639657025fSTomasz Sapeta      for (const dependencyType of ['dependencies', 'devDependencies', 'peerDependencies']) {
649657025fSTomasz Sapeta        const dependencies = packageJson[dependencyType];
659657025fSTomasz Sapeta        const currentVersion = dependencies?.[dependencyName];
669657025fSTomasz Sapeta
679657025fSTomasz Sapeta        if (dependencies && currentVersion && currentVersion !== '*') {
689657025fSTomasz Sapeta          dependencies[dependencyName] = versionRange;
699657025fSTomasz Sapeta        }
709657025fSTomasz Sapeta      }
719657025fSTomasz Sapeta      await jsonFile.writeAsync(packageJson);
729657025fSTomasz Sapeta    })
739657025fSTomasz Sapeta  );
749657025fSTomasz Sapeta}
75