1 | import { debounceTime, filter } from 'rxjs/operators';
|
2 | import { exec, constants, copy, dependsOn, elapsed, file, filter as filterUtil, fs, listr, loadSettings, log, moment, updatePackageRef, util, } from '../common';
|
3 | import * as listCommand from './ls.cmd';
|
4 | export const name = 'sync';
|
5 | export const alias = ['s', 'sl'];
|
6 | export const description = `Syncs each module's dependency tree within the workspace.`;
|
7 | export const args = {
|
8 | '-i': 'Include ignored modules.',
|
9 | '-w': 'Sync on changes to files.',
|
10 | '-v': 'Update version reference in package.json files.',
|
11 | };
|
12 | export async function cmd(args) {
|
13 | const options = (args && args.options) || {};
|
14 | const watch = options.w || false;
|
15 | const includeIgnored = options.i || false;
|
16 | const updateVersions = options.v || false;
|
17 | const config = { includeIgnored, updateVersions };
|
18 | if (watch) {
|
19 | await syncWatch(config);
|
20 | }
|
21 | else {
|
22 | await sync(config);
|
23 | }
|
24 | }
|
25 | export async function sync(options = {}) {
|
26 | const { includeIgnored = false } = options;
|
27 | const write = (msg) => util.write(msg, options.silent);
|
28 | const settings = await loadSettings();
|
29 | if (!settings) {
|
30 | write(log.yellow(constants.CONFIG_NOT_FOUND_ERROR));
|
31 | return;
|
32 | }
|
33 | const modules = settings.modules
|
34 | .filter((pkg) => filterUtil.localDeps(pkg).length > 0)
|
35 | .filter((pkg) => filterUtil.includeIgnored(pkg, includeIgnored));
|
36 | await syncModules(modules, options);
|
37 | return {
|
38 | settings: settings,
|
39 | modules,
|
40 | };
|
41 | }
|
42 | export async function syncModules(modules, options = {}) {
|
43 | const startedAt = new Date();
|
44 | const { includeIgnored = false, updateVersions = false, silent = false } = options;
|
45 | const write = (msg) => util.write(msg, options.silent);
|
46 | const sync = async (sources, target) => {
|
47 | for (const source of sources) {
|
48 | if (source.package) {
|
49 | await copy.module(source.package, target);
|
50 | await copy.logUpdate(target);
|
51 | await chmod(target);
|
52 | if (updateVersions) {
|
53 | await updatePackageRef(target, source.package.name, source.package.version, {
|
54 | save: true,
|
55 | });
|
56 | }
|
57 | }
|
58 | }
|
59 | };
|
60 | const tasks = modules.map((target) => {
|
61 | const sources = filterUtil
|
62 | .localDeps(target)
|
63 | .filter((dep) => filterUtil.includeIgnored(dep.package, includeIgnored));
|
64 | const sourceNames = sources.map((dep) => ` ${log.cyan(dep.name)}`);
|
65 | const title = `${log.magenta(target.name)} ${log.cyan(sourceNames.length > 0 ? '⬅' : '')}${sourceNames}`;
|
66 | return {
|
67 | title,
|
68 | task: () => sync(sources, target),
|
69 | };
|
70 | });
|
71 | try {
|
72 | if (silent) {
|
73 | for (const item of tasks) {
|
74 | await item.task();
|
75 | }
|
76 | }
|
77 | else {
|
78 | const taskList = listr(tasks, { concurrent: false });
|
79 | await taskList.run();
|
80 | write(log.gray(` ${elapsed(startedAt)}, ${moment().format('h:mm:ssa')}`));
|
81 | write('');
|
82 | }
|
83 | }
|
84 | catch (error) {
|
85 | write(log.yellow(`\nFailed while syncing module '${error.message}'.`));
|
86 | }
|
87 | return modules;
|
88 | }
|
89 | export async function chmod(module) {
|
90 | const dir = fs.join(module.dir, 'node_modules/.bin');
|
91 | if (!(await fs.pathExistsSync(dir))) {
|
92 | return [];
|
93 | }
|
94 | const cmd = exec.command(`chmod 777`);
|
95 | const files = (await fs.readdir(dir)).map((name) => fs.join(dir, name));
|
96 | const wait = files.map((path) => {
|
97 | return cmd.clone().add(path).run({ silent: true });
|
98 | });
|
99 | await Promise.all(wait);
|
100 | return files;
|
101 | }
|
102 | export async function syncWatch(options = {}) {
|
103 | const { includeIgnored = false, silent = false } = options;
|
104 | const write = (msg) => util.write(msg, options.silent);
|
105 | write(log.magenta('\nSync watching:'));
|
106 | const result = await listCommand.ls({
|
107 | dependencies: 'local',
|
108 | includeIgnored,
|
109 | });
|
110 | if (!result) {
|
111 | return;
|
112 | }
|
113 | const { modules, settings } = result;
|
114 | modules.forEach((pkg) => watch(pkg, modules, settings.watchPattern, includeIgnored, silent));
|
115 | }
|
116 | function watch(pkg, modules, watchPattern, includeIgnored, silent) {
|
117 | const sync = () => {
|
118 | const dependants = dependsOn(pkg, modules);
|
119 | if (dependants.length > 0) {
|
120 | util.write(log.green(`${pkg.name} changed: `), silent);
|
121 | syncModules(dependants, { includeIgnored });
|
122 | }
|
123 | };
|
124 | file
|
125 | .watch(fs.join(pkg.dir, watchPattern))
|
126 | .pipe(filter((path) => !path.includes('node_modules/')), debounceTime(1000))
|
127 | .subscribe(() => sync());
|
128 | }
|