1#!/usr/bin/env node
2
3const fs = require('fs');
4const path = require('path');
5
6function symlinkPackages(expoDirectory, projectDirectory, packageNames) {
7  const pkgJson = require(path.resolve(projectDirectory, './package.json'));
8  const symlinks = pkgJson.expo.symlinks;
9
10  packageNames.forEach((packageName) => {
11    if (!symlinks.includes(packageName)) {
12      symlinks.push(packageName);
13    }
14
15    // add any dependencies of the specified packages if they are not already symlinked
16    const dependencies = getPackageDependencies({ packageName });
17    dependencies.forEach((dependency) => {
18      if (!symlinks.includes(dependency)) {
19        symlinks.push(dependency);
20      }
21    });
22  });
23
24  symlinks.forEach((packageName) => {
25    const pathToPackage = path.resolve(expoDirectory, 'packages', packageName);
26
27    const nodeModulesPackage = path.resolve(projectDirectory, 'node_modules', packageName);
28
29    const pkg = require(path.resolve(pathToPackage, 'package.json'));
30    const version = pkg.version || '*';
31
32    pkgJson.dependencies[packageName] = version;
33
34    if (fs.existsSync(nodeModulesPackage)) {
35      fs.rmSync(nodeModulesPackage, { recursive: true });
36    }
37
38    fs.symlinkSync(pathToPackage, nodeModulesPackage);
39  });
40
41  fs.writeFileSync(
42    path.resolve(projectDirectory, './package.json'),
43    JSON.stringify(pkgJson, null, 2),
44    { encoding: 'utf-8' }
45  );
46
47  function getPackageDependencies({ packageName }) {
48    const packagePath = path.resolve(expoDirectory, 'packages', packageName, 'package.json');
49
50    if (!fs.existsSync(packagePath)) {
51      return [];
52    }
53
54    const dependencies = new Set([packageName]);
55
56    const pkg = require(packagePath);
57
58    if (pkg.dependencies) {
59      Object.keys(pkg.dependencies).forEach((dependency) => {
60        const deps = getPackageDependencies({ packageName: dependency });
61        deps.forEach((dep) => dependencies.add(dep));
62      });
63    }
64
65    return Array.from(dependencies);
66  }
67
68  console.log('Symlinking packages complete');
69}
70
71const [expoDirectory, projectDirectory, ...packageNames] = process.argv.slice(2);
72symlinkPackages(expoDirectory, projectDirectory, packageNames);
73