packages/cli: most of watch-deps into lib and re-use from there instead

This commit is contained in:
Patrik Oldsberg
2020-04-18 02:51:32 +02:00
parent 921beb792d
commit 2c095442ed
8 changed files with 97 additions and 83 deletions
+1 -1
View File
@@ -16,8 +16,8 @@
import { spawn } from 'child_process';
import { waitForExit } from 'lib/run';
import { watchDeps } from 'commands/watch-deps';
import { createLogFunc } from 'lib/logging';
import { watchDeps } from 'lib/watchDeps';
export default async () => {
// Start dynamic watch and build of dependencies, then serve the app
+16 -65
View File
@@ -14,71 +14,11 @@
* limitations under the License.
*/
import chalk from 'chalk';
import fs from 'fs-extra';
import { createLogPipeFactory } from './logger';
import { findAllDeps } from './packages';
import { startWatcher, startPackageWatcher } from './watcher';
import { startCompiler } from './compiler';
import { startChild } from './child';
import { waitForExit, run } from 'lib/run';
import { paths } from 'lib/paths';
import { spawn } from 'child_process';
import { Command } from 'commander';
const PACKAGE_BLACKLIST = [
// We never want to watch for changes in the cli, but all packages will depend on it.
'@backstage/cli',
];
const WATCH_LOCATIONS = ['package.json', 'src', 'assets'];
export type Options = {
build?: boolean;
};
// Start watching for dependency changes.
// The returned promise resolves when watchers have started for all current dependencies.
export async function watchDeps(options: Options = {}) {
const localPackagePath = paths.resolveTarget('package.json');
// Rotate through different prefix colors to make it easier to differenciate between different deps
const createLogPipe = createLogPipeFactory([
chalk.yellow,
chalk.blue,
chalk.magenta,
chalk.green,
chalk.cyan,
]);
// Find all direct and transitive local dependencies of the current package.
const packageData = await fs.readFile(localPackagePath, 'utf8');
const packageJson = JSON.parse(packageData);
const packageName = packageJson.name;
const deps = await findAllDeps(packageName, PACKAGE_BLACKLIST);
if (options.build) {
await run('lerna', [
'run',
'--scope',
packageName,
'--include-dependencies',
'build',
]);
}
// We lazily watch all our deps, as in we don't start the actual watch compiler until a change is detected
const watcher = await startWatcher(deps, WATCH_LOCATIONS, pkg => {
startCompiler(pkg, createLogPipe(pkg.name)).promise.catch(error => {
process.stderr.write(`${error}\n`);
});
});
await startPackageWatcher(localPackagePath, async () => {
const newDeps = await findAllDeps(packageName, PACKAGE_BLACKLIST);
await watcher.update(newDeps);
});
}
import { waitForExit } from 'lib/run';
import { createLogPipe } from 'lib/logging';
import { watchDeps, Options } from 'lib/watchDeps';
/*
* The watch-deps command is meant to improve iteration speed while working in a large monorepo
@@ -99,6 +39,17 @@ export default async (cmd: Command, args: string[]) => {
await watchDeps(options);
if (args?.length) {
await waitForExit(startChild(args));
const child = spawn(args[0], args.slice(1), {
env: { FORCE_COLOR: 'true', ...process.env },
stdio: ['inherit', 'pipe', 'pipe'],
shell: true,
});
// Use log pipe to avoid clearing the terminal
const logPipe = createLogPipe();
child.stdout.on('data', logPipe(process.stdout));
child.stderr.on('data', logPipe(process.stderr));
await waitForExit(child);
}
};
@@ -14,20 +14,4 @@
* limitations under the License.
*/
import { spawn } from 'child_process';
import { createLogPipe } from 'lib/logging';
export function startChild(args: string[]) {
const [command, ...commandArgs] = args;
const child = spawn(command, commandArgs, {
env: { FORCE_COLOR: 'true', ...process.env },
stdio: ['inherit', 'pipe', 'pipe'],
shell: true,
});
// We need to avoid clearing the terminal, or the build feedback of dependencies will be lost
const logPipe = createLogPipe();
child.stdout.on('data', logPipe(process.stdout));
child.stderr.on('data', logPipe(process.stderr));
return child;
}
export * from './watchDeps';
@@ -0,0 +1,79 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import chalk from 'chalk';
import fs from 'fs-extra';
import { createLogPipeFactory } from './logger';
import { findAllDeps } from './packages';
import { startWatcher, startPackageWatcher } from './watcher';
import { startCompiler } from './compiler';
import { run } from 'lib/run';
import { paths } from 'lib/paths';
const PACKAGE_BLACKLIST = [
// We never want to watch for changes in the cli, but all packages will depend on it.
'@backstage/cli',
];
const WATCH_LOCATIONS = ['package.json', 'src', 'assets'];
export type Options = {
build?: boolean;
};
// Start watching for dependency changes.
// The returned promise resolves when watchers have started for all current dependencies.
export async function watchDeps(options: Options = {}) {
const localPackagePath = paths.resolveTarget('package.json');
// Rotate through different prefix colors to make it easier to differenciate between different deps
const createLogPipe = createLogPipeFactory([
chalk.yellow,
chalk.blue,
chalk.magenta,
chalk.green,
chalk.cyan,
]);
// Find all direct and transitive local dependencies of the current package.
const packageData = await fs.readFile(localPackagePath, 'utf8');
const packageJson = JSON.parse(packageData);
const packageName = packageJson.name;
const deps = await findAllDeps(packageName, PACKAGE_BLACKLIST);
if (options.build) {
await run('lerna', [
'run',
'--scope',
packageName,
'--include-dependencies',
'build',
]);
}
// We lazily watch all our deps, as in we don't start the actual watch compiler until a change is detected
const watcher = await startWatcher(deps, WATCH_LOCATIONS, pkg => {
startCompiler(pkg, createLogPipe(pkg.name)).promise.catch(error => {
process.stderr.write(`${error}\n`);
});
});
await startPackageWatcher(localPackagePath, async () => {
const newDeps = await findAllDeps(packageName, PACKAGE_BLACKLIST);
await watcher.update(newDeps);
});
}