[tslint] Fix violations in kbn-pm (#19335)

* [tslint/kbn-pm] apply autofixes

* [tslint/kbn-pm] whitelist all console.log calls for now

* [tslint/kbn-pm] sort object keys alphabetically

* [tslint/kbn-pm] use comments to "fill" empty blocks

* [tslint/kbn-pm] use I-prefix for interface names

* [tslint/kbn-pm] use arrow-functions where possible

* [tslint/kbn-pm] use lowerCamelCase for variable names

* [tslint/kbn-pm] prevent shadowed variable names

* [tslint/kbn-pm] avoid variable name and type clashes

* [tslint/kbn-pm] replace console.log statements with bare-bones logger
This commit is contained in:
Spencer 2018-05-23 14:50:02 -07:00 committed by GitHub
parent 3d08c5cb31
commit ce20463f59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 248 additions and 228 deletions

View file

@ -1,17 +1,18 @@
import getopts from 'getopts';
import dedent from 'dedent';
import chalk from 'chalk'; import chalk from 'chalk';
import dedent from 'dedent';
import getopts from 'getopts';
import { resolve } from 'path'; import { resolve } from 'path';
import { commands } from './commands'; import { commands } from './commands';
import { runCommand } from './run'; import { runCommand } from './run';
import { log } from './utils/log';
function help() { function help() {
const availableCommands = Object.keys(commands) const availableCommands = Object.keys(commands)
.map(commandName => commands[commandName]) .map(commandName => commands[commandName])
.map(command => `${command.name} - ${command.description}`); .map(command => `${command.name} - ${command.description}`);
console.log(dedent` log.write(dedent`
usage: kbn <command> [<args>] usage: kbn <command> [<args>]
By default commands are run for Kibana itself, all packages in the 'packages/' By default commands are run for Kibana itself, all packages in the 'packages/'
@ -35,7 +36,7 @@ export async function run(argv: string[]) {
// starts forwarding the `--` directly to this script, see // starts forwarding the `--` directly to this script, see
// https://github.com/yarnpkg/yarn/blob/b2d3e1a8fe45ef376b716d597cc79b38702a9320/src/cli/index.js#L174-L182 // https://github.com/yarnpkg/yarn/blob/b2d3e1a8fe45ef376b716d597cc79b38702a9320/src/cli/index.js#L174-L182
if (argv.includes('--')) { if (argv.includes('--')) {
console.log( log.write(
chalk.red( chalk.red(
`Using "--" is not allowed, as it doesn't work with 'yarn kbn'.` `Using "--" is not allowed, as it doesn't work with 'yarn kbn'.`
) )
@ -45,9 +46,9 @@ export async function run(argv: string[]) {
const options = getopts(argv, { const options = getopts(argv, {
alias: { alias: {
e: 'exclude',
h: 'help', h: 'help',
i: 'include', i: 'include',
e: 'exclude',
}, },
}); });
@ -69,7 +70,7 @@ export async function run(argv: string[]) {
const command = commands[commandName]; const command = commands[commandName];
if (command === undefined) { if (command === undefined) {
console.log( log.write(
chalk.red(`[${commandName}] is not a valid command, see 'kbn --help'`) chalk.red(`[${commandName}] is not a valid command, see 'kbn --help'`)
); );
process.exit(1); process.exit(1);

View file

@ -7,18 +7,18 @@ import {
absolutePathSnapshotSerializer, absolutePathSnapshotSerializer,
stripAnsiSnapshotSerializer, stripAnsiSnapshotSerializer,
} from '../test_helpers'; } from '../test_helpers';
import { BootstrapCommand } from './bootstrap'; import { linkProjectExecutables } from '../utils/link_project_executables';
import { PackageJson } from '../utils/package_json'; import { IPackageJson } from '../utils/package_json';
import { Project } from '../utils/project'; import { Project } from '../utils/project';
import { buildProjectGraph } from '../utils/projects'; import { buildProjectGraph } from '../utils/projects';
import { installInDir, runScriptInPackageStreaming } from '../utils/scripts'; import { installInDir, runScriptInPackageStreaming } from '../utils/scripts';
import { linkProjectExecutables } from '../utils/link_project_executables'; import { BootstrapCommand } from './bootstrap';
const mockInstallInDir = installInDir as jest.Mock; const mockInstallInDir = installInDir as jest.Mock;
const mockRunScriptInPackageStreaming = runScriptInPackageStreaming as jest.Mock; const mockRunScriptInPackageStreaming = runScriptInPackageStreaming as jest.Mock;
const mockLinkProjectExecutables = linkProjectExecutables as jest.Mock; const mockLinkProjectExecutables = linkProjectExecutables as jest.Mock;
const createProject = (packageJson: PackageJson, path = '.') => const createProject = (packageJson: IPackageJson, path = '.') =>
new Project( new Project(
{ {
name: 'kibana', name: 'kibana',
@ -31,7 +31,9 @@ const createProject = (packageJson: PackageJson, path = '.') =>
expect.addSnapshotSerializer(absolutePathSnapshotSerializer); expect.addSnapshotSerializer(absolutePathSnapshotSerializer);
expect.addSnapshotSerializer(stripAnsiSnapshotSerializer); expect.addSnapshotSerializer(stripAnsiSnapshotSerializer);
const noop = () => {}; const noop = () => {
// noop
};
afterEach(() => { afterEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
@ -45,19 +47,19 @@ test('handles dependencies of dependencies', async () => {
}); });
const foo = createProject( const foo = createProject(
{ {
name: 'foo',
dependencies: { dependencies: {
bar: 'link:../bar', bar: 'link:../bar',
}, },
name: 'foo',
}, },
'packages/foo' 'packages/foo'
); );
const bar = createProject( const bar = createProject(
{ {
name: 'bar',
dependencies: { dependencies: {
baz: 'link:../baz', baz: 'link:../baz',
}, },
name: 'bar',
}, },
'packages/bar' 'packages/bar'
); );

View file

@ -1,13 +1,14 @@
import chalk from 'chalk'; import chalk from 'chalk';
import { topologicallyBatchProjects } from '../utils/projects';
import { linkProjectExecutables } from '../utils/link_project_executables'; import { linkProjectExecutables } from '../utils/link_project_executables';
import { log } from '../utils/log';
import { parallelizeBatches } from '../utils/parallelize'; import { parallelizeBatches } from '../utils/parallelize';
import { Command } from './'; import { topologicallyBatchProjects } from '../utils/projects';
import { ICommand } from './';
export const BootstrapCommand: Command = { export const BootstrapCommand: ICommand = {
name: 'bootstrap',
description: 'Install dependencies and crosslink projects', description: 'Install dependencies and crosslink projects',
name: 'bootstrap',
async run(projects, projectGraph, { options }) { async run(projects, projectGraph, { options }) {
const batchedProjects = topologicallyBatchProjects(projects, projectGraph); const batchedProjects = topologicallyBatchProjects(projects, projectGraph);
@ -15,7 +16,7 @@ export const BootstrapCommand: Command = {
const frozenLockfile = options['frozen-lockfile'] === true; const frozenLockfile = options['frozen-lockfile'] === true;
const extraArgs = frozenLockfile ? ['--frozen-lockfile'] : []; const extraArgs = frozenLockfile ? ['--frozen-lockfile'] : [];
console.log(chalk.bold('\nRunning installs in topological order:')); log.write(chalk.bold('\nRunning installs in topological order:'));
for (const batch of batchedProjects) { for (const batch of batchedProjects) {
for (const project of batch) { for (const project of batch) {
@ -25,7 +26,7 @@ export const BootstrapCommand: Command = {
} }
} }
console.log( log.write(
chalk.bold('\nInstalls completed, linking package executables:\n') chalk.bold('\nInstalls completed, linking package executables:\n')
); );
await linkProjectExecutables(projects, projectGraph); await linkProjectExecutables(projects, projectGraph);
@ -36,7 +37,7 @@ export const BootstrapCommand: Command = {
* transpiled before they can be used. Ideally we shouldn't do this unless we * transpiled before they can be used. Ideally we shouldn't do this unless we
* have to, as it will slow down the bootstrapping process. * have to, as it will slow down the bootstrapping process.
*/ */
console.log( log.write(
chalk.bold( chalk.bold(
'\nLinking executables completed, running `kbn:bootstrap` scripts\n' '\nLinking executables completed, running `kbn:bootstrap` scripts\n'
) )
@ -47,6 +48,6 @@ export const BootstrapCommand: Command = {
} }
}); });
console.log(chalk.green.bold('\nBootstrapping completed!\n')); log.write(chalk.green.bold('\nBootstrapping completed!\n'));
}, },
}; };

View file

@ -1,15 +1,16 @@
import del from 'del';
import chalk from 'chalk'; import chalk from 'chalk';
import { relative } from 'path'; import del from 'del';
import ora from 'ora'; import ora from 'ora';
import { relative } from 'path';
import { isDirectory } from '../utils/fs'; import { isDirectory } from '../utils/fs';
import { Command } from './'; import { log } from '../utils/log';
import { ICommand } from './';
export const CleanCommand: Command = { export const CleanCommand: ICommand = {
name: 'clean',
description: description:
'Remove the node_modules and target directories from all projects.', 'Remove the node_modules and target directories from all projects.',
name: 'clean',
async run(projects, projectGraph, { rootPath }) { async run(projects, projectGraph, { rootPath }) {
const directoriesToDelete = []; const directoriesToDelete = [];
@ -24,9 +25,9 @@ export const CleanCommand: Command = {
} }
if (directoriesToDelete.length === 0) { if (directoriesToDelete.length === 0) {
console.log(chalk.bold.green('\n\nNo directories to delete')); log.write(chalk.bold.green('\n\nNo directories to delete'));
} else { } else {
console.log(chalk.bold.red('\n\nDeleting directories:\n')); log.write(chalk.bold.red('\n\nDeleting directories:\n'));
for (const dir of directoriesToDelete) { for (const dir of directoriesToDelete) {
const deleting = del(dir, { force: true }); const deleting = del(dir, { force: true });

View file

@ -1,19 +1,19 @@
import { ProjectGraph, ProjectMap } from '../utils/projects'; import { ProjectGraph, ProjectMap } from '../utils/projects';
export interface CommandConfig { export interface ICommandConfig {
extraArgs: string[]; extraArgs: string[];
options: { [key: string]: any }; options: { [key: string]: any };
rootPath: string; rootPath: string;
} }
export interface Command { export interface ICommand {
name: string; name: string;
description: string; description: string;
run: ( run: (
projects: ProjectMap, projects: ProjectMap,
projectGraph: ProjectGraph, projectGraph: ProjectGraph,
config: CommandConfig config: ICommandConfig
) => Promise<void>; ) => Promise<void>;
} }
@ -22,7 +22,7 @@ import { CleanCommand } from './clean';
import { RunCommand } from './run'; import { RunCommand } from './run';
import { WatchCommand } from './watch'; import { WatchCommand } from './watch';
export const commands: { [key: string]: Command } = { export const commands: { [key: string]: ICommand } = {
bootstrap: BootstrapCommand, bootstrap: BootstrapCommand,
clean: CleanCommand, clean: CleanCommand,
run: RunCommand, run: RunCommand,

View file

@ -1,26 +1,27 @@
import chalk from 'chalk'; import chalk from 'chalk';
import { topologicallyBatchProjects } from '../utils/projects'; import { log } from '../utils/log';
import { parallelizeBatches } from '../utils/parallelize'; import { parallelizeBatches } from '../utils/parallelize';
import { Command } from './'; import { topologicallyBatchProjects } from '../utils/projects';
import { ICommand } from './';
export const RunCommand: Command = { export const RunCommand: ICommand = {
name: 'run',
description: description:
'Run script defined in package.json in each package that contains that script.', 'Run script defined in package.json in each package that contains that script.',
name: 'run',
async run(projects, projectGraph, { extraArgs }) { async run(projects, projectGraph, { extraArgs }) {
const batchedProjects = topologicallyBatchProjects(projects, projectGraph); const batchedProjects = topologicallyBatchProjects(projects, projectGraph);
if (extraArgs.length === 0) { if (extraArgs.length === 0) {
console.log(chalk.red.bold('\nNo script specified')); log.write(chalk.red.bold('\nNo script specified'));
process.exit(1); process.exit(1);
} }
const scriptName = extraArgs[0]; const scriptName = extraArgs[0];
const scriptArgs = extraArgs.slice(1); const scriptArgs = extraArgs.slice(1);
console.log( log.write(
chalk.bold( chalk.bold(
`\nRunning script [${chalk.green( `\nRunning script [${chalk.green(
scriptName scriptName

View file

@ -1,8 +1,9 @@
import chalk from 'chalk'; import chalk from 'chalk';
import { topologicallyBatchProjects, ProjectMap } from '../utils/projects'; import { log } from '../utils/log';
import { parallelizeBatches } from '../utils/parallelize'; import { parallelizeBatches } from '../utils/parallelize';
import { ProjectMap, topologicallyBatchProjects } from '../utils/projects';
import { waitUntilWatchIsReady } from '../utils/watch'; import { waitUntilWatchIsReady } from '../utils/watch';
import { Command } from './'; import { ICommand } from './';
/** /**
* Name of the script in the package/project package.json file to run during `kbn watch`. * Name of the script in the package/project package.json file to run during `kbn watch`.
@ -24,9 +25,9 @@ const kibanaProjectName = 'kibana';
* the `kbn:watch` script and eventually for the entire batch. Currently we support completion "markers" for * the `kbn:watch` script and eventually for the entire batch. Currently we support completion "markers" for
* `webpack` and `tsc` only, for the rest we rely on predefined timeouts. * `webpack` and `tsc` only, for the rest we rely on predefined timeouts.
*/ */
export const WatchCommand: Command = { export const WatchCommand: ICommand = {
name: 'watch',
description: 'Runs `kbn:watch` script for every project.', description: 'Runs `kbn:watch` script for every project.',
name: 'watch',
async run(projects, projectGraph) { async run(projects, projectGraph) {
const projectsToWatch: ProjectMap = new Map(); const projectsToWatch: ProjectMap = new Map();
@ -38,7 +39,7 @@ export const WatchCommand: Command = {
} }
if (projectsToWatch.size === 0) { if (projectsToWatch.size === 0) {
console.log( log.write(
chalk.red( chalk.red(
`\nThere are no projects to watch found. Make sure that projects define 'kbn:watch' script in 'package.json'.\n` `\nThere are no projects to watch found. Make sure that projects define 'kbn:watch' script in 'package.json'.\n`
) )
@ -47,7 +48,7 @@ export const WatchCommand: Command = {
} }
const projectNames = Array.from(projectsToWatch.keys()); const projectNames = Array.from(projectsToWatch.keys());
console.log( log.write(
chalk.bold( chalk.bold(
chalk.green( chalk.green(
`Running ${watchScriptName} scripts for [${projectNames.join(', ')}].` `Running ${watchScriptName} scripts for [${projectNames.join(', ')}].`
@ -73,7 +74,7 @@ export const WatchCommand: Command = {
pkg.runScriptStreaming(watchScriptName).stdout pkg.runScriptStreaming(watchScriptName).stdout
); );
console.log( log.write(
chalk.bold( chalk.bold(
`[${chalk.green( `[${chalk.green(
pkg.name pkg.name

View file

@ -1,14 +1,17 @@
import { resolve } from 'path'; import { resolve } from 'path';
export type ProjectPathOptions = { export interface IProjectPathOptions {
'skip-kibana-extra'?: boolean; 'skip-kibana-extra'?: boolean;
'oss'?: boolean; oss?: boolean;
}; }
/** /**
* Returns all the paths where plugins are located * Returns all the paths where plugins are located
*/ */
export function getProjectPaths(rootPath: string, options: ProjectPathOptions) { export function getProjectPaths(
rootPath: string,
options: IProjectPathOptions
) {
const skipKibanaExtra = Boolean(options['skip-kibana-extra']); const skipKibanaExtra = Boolean(options['skip-kibana-extra']);
const ossOnly = Boolean(options.oss); const ossOnly = Boolean(options.oss);

View file

@ -1,22 +1,22 @@
import del from 'del';
import { relative, resolve, join } from 'path';
import copy from 'cpy'; import copy from 'cpy';
import del from 'del';
import { join, relative, resolve } from 'path';
import { getProjectPaths } from '../config'; import { getProjectPaths } from '../config';
import { import { isDirectory, isFile } from '../utils/fs';
getProjects, import { log } from '../utils/log';
buildProjectGraph,
topologicallyBatchProjects,
ProjectMap,
includeTransitiveProjects,
} from '../utils/projects';
import { import {
createProductionPackageJson, createProductionPackageJson,
writePackageJson,
readPackageJson, readPackageJson,
writePackageJson,
} from '../utils/package_json'; } from '../utils/package_json';
import { isDirectory, isFile } from '../utils/fs';
import { Project } from '../utils/project'; import { Project } from '../utils/project';
import {
buildProjectGraph,
getProjects,
includeTransitiveProjects,
topologicallyBatchProjects,
} from '../utils/projects';
export async function buildProductionProjects({ export async function buildProductionProjects({
kibanaRoot, kibanaRoot,
@ -30,7 +30,7 @@ export async function buildProductionProjects({
const batchedProjects = topologicallyBatchProjects(projects, projectGraph); const batchedProjects = topologicallyBatchProjects(projects, projectGraph);
const projectNames = [...projects.values()].map(project => project.name); const projectNames = [...projects.values()].map(project => project.name);
console.log(`Preparing production build for [${projectNames.join(', ')}]`); log.write(`Preparing production build for [${projectNames.join(', ')}]`);
for (const batch of batchedProjects) { for (const batch of batchedProjects) {
for (const project of batch) { for (const project of batch) {
@ -99,9 +99,9 @@ async function copyToBuild(
await copy(['**/*', '!node_modules/**'], buildProjectPath, { await copy(['**/*', '!node_modules/**'], buildProjectPath, {
cwd: project.getIntermediateBuildDirectory(), cwd: project.getIntermediateBuildDirectory(),
parents: true,
nodir: true,
dot: true, dot: true,
nodir: true,
parents: true,
}); });
// If a project is using an intermediate build directory, we special-case our // If a project is using an intermediate build directory, we special-case our

View file

@ -1,16 +1,16 @@
import tempy from 'tempy';
import copy from 'cpy'; import copy from 'cpy';
import { resolve, relative, join } from 'path';
import globby from 'globby'; import globby from 'globby';
import { join, resolve } from 'path';
import tempy from 'tempy';
import { buildProductionProjects } from '../build_production_projects';
import { getProjects } from '../../utils/projects';
import { readPackageJson } from '../../utils/package_json'; import { readPackageJson } from '../../utils/package_json';
import { getProjects } from '../../utils/projects';
import { buildProductionProjects } from '../build_production_projects';
describe('kbn-pm production', function() { describe('kbn-pm production', () => {
test( test(
'builds and copies projects for production', 'builds and copies projects for production',
async function() { async () => {
const tmpDir = tempy.directory(); const tmpDir = tempy.directory();
const buildRoot = tempy.directory(); const buildRoot = tempy.directory();
const fixturesPath = resolve(__dirname, '__fixtures__'); const fixturesPath = resolve(__dirname, '__fixtures__');
@ -18,9 +18,9 @@ describe('kbn-pm production', function() {
// Copy all the test fixtures into a tmp dir, as we will be mutating them // Copy all the test fixtures into a tmp dir, as we will be mutating them
await copy(['**/*'], tmpDir, { await copy(['**/*'], tmpDir, {
cwd: fixturesPath, cwd: fixturesPath,
parents: true,
nodir: true,
dot: true, dot: true,
nodir: true,
parents: true,
}); });
const projects = await getProjects(tmpDir, ['.', './packages/*']); const projects = await getProjects(tmpDir, ['.', './packages/*']);

View file

@ -1,4 +1,4 @@
import { resolve, join } from 'path'; import { join, resolve } from 'path';
import { prepareExternalProjectDependencies } from './prepare_project_dependencies'; import { prepareExternalProjectDependencies } from './prepare_project_dependencies';

View file

@ -1,5 +1,5 @@
import { Project } from '../utils/project';
import { isLinkDependency } from '../utils/package_json'; import { isLinkDependency } from '../utils/package_json';
import { Project } from '../utils/project';
/** /**
* All external projects are located within `../kibana-extra/{plugin}` relative * All external projects are located within `../kibana-extra/{plugin}` relative

View file

@ -1,7 +1,7 @@
import { resolve } from 'path'; import { resolve } from 'path';
import { ICommand, ICommandConfig } from './commands';
import { runCommand } from './run'; import { runCommand } from './run';
import { Project } from './utils/project'; import { Project } from './utils/project';
import { Command, CommandConfig } from './commands';
const rootPath = resolve(`${__dirname}/utils/__fixtures__/kibana`); const rootPath = resolve(`${__dirname}/utils/__fixtures__/kibana`);
@ -25,12 +25,12 @@ function getExpectedProjectsAndGraph(runMock: any) {
return { projects, graph }; return { projects, graph };
} }
let command: Command; let command: ICommand;
let config: CommandConfig; let config: ICommandConfig;
beforeEach(() => { beforeEach(() => {
command = { command = {
name: 'test name',
description: 'test description', description: 'test description',
name: 'test name',
run: jest.fn(), run: jest.fn(),
}; };
@ -41,7 +41,9 @@ beforeEach(() => {
}; };
// Reduce the noise that comes from the run command. // Reduce the noise that comes from the run command.
jest.spyOn(console, 'log').mockImplementation(() => {}); jest.spyOn(console, 'log').mockImplementation(() => {
// noop
});
}); });
test('passes all found projects to the command if no filter is specified', async () => { test('passes all found projects to the command if no filter is specified', async () => {
@ -102,9 +104,9 @@ test('respects both `include` and `exclude` filters if specified at the same tim
}); });
test('does not run command if all projects are filtered out', async () => { test('does not run command if all projects are filtered out', async () => {
let mockProcessExit = jest const mockProcessExit = jest.spyOn(process, 'exit').mockImplementation(() => {
.spyOn(process, 'exit') // noop
.mockImplementation(() => {}); });
await runCommand(command, { await runCommand(command, {
...config, ...config,

View file

@ -1,16 +1,17 @@
import chalk from 'chalk'; import chalk from 'chalk';
import wrapAnsi from 'wrap-ansi';
import indentString from 'indent-string'; import indentString from 'indent-string';
import wrapAnsi from 'wrap-ansi';
import { ICommand, ICommandConfig } from './commands';
import { getProjectPaths, IProjectPathOptions } from './config';
import { CliError } from './utils/errors'; import { CliError } from './utils/errors';
import { getProjects, buildProjectGraph } from './utils/projects'; import { log } from './utils/log';
import { buildProjectGraph, getProjects } from './utils/projects';
import { renderProjectsTree } from './utils/projects_tree'; import { renderProjectsTree } from './utils/projects_tree';
import { getProjectPaths, ProjectPathOptions } from './config';
import { Command, CommandConfig } from './commands';
export async function runCommand(command: Command, config: CommandConfig) { export async function runCommand(command: ICommand, config: ICommandConfig) {
try { try {
console.log( log.write(
chalk.bold( chalk.bold(
`Running [${chalk.green(command.name)}] command from [${chalk.yellow( `Running [${chalk.green(command.name)}] command from [${chalk.yellow(
config.rootPath config.rootPath
@ -20,7 +21,7 @@ export async function runCommand(command: Command, config: CommandConfig) {
const projectPaths = getProjectPaths( const projectPaths = getProjectPaths(
config.rootPath, config.rootPath,
config.options as ProjectPathOptions config.options as IProjectPathOptions
); );
const projects = await getProjects(config.rootPath, projectPaths, { const projects = await getProjects(config.rootPath, projectPaths, {
@ -29,7 +30,7 @@ export async function runCommand(command: Command, config: CommandConfig) {
}); });
if (projects.size === 0) { if (projects.size === 0) {
console.log( log.write(
chalk.red( chalk.red(
`There are no projects found. Double check project name(s) in '-i/--include' and '-e/--exclude' filters.\n` `There are no projects found. Double check project name(s) in '-i/--include' and '-e/--exclude' filters.\n`
) )
@ -39,18 +40,18 @@ export async function runCommand(command: Command, config: CommandConfig) {
const projectGraph = buildProjectGraph(projects); const projectGraph = buildProjectGraph(projects);
console.log( log.write(
chalk.bold(`Found [${chalk.green(projects.size.toString())}] projects:\n`) chalk.bold(`Found [${chalk.green(projects.size.toString())}] projects:\n`)
); );
console.log(renderProjectsTree(config.rootPath, projects)); log.write(renderProjectsTree(config.rootPath, projects));
await command.run(projects, projectGraph, config); await command.run(projects, projectGraph, config);
} catch (e) { } catch (e) {
console.log(chalk.bold.red(`\n[${command.name}] failed:\n`)); log.write(chalk.bold.red(`\n[${command.name}] failed:\n`));
if (e instanceof CliError) { if (e instanceof CliError) {
const msg = chalk.red(`CliError: ${e.message}\n`); const msg = chalk.red(`CliError: ${e.message}\n`);
console.log(wrapAnsi(msg, 80)); log.write(wrapAnsi(msg, 80));
const keys = Object.keys(e.meta); const keys = Object.keys(e.meta);
if (keys.length > 0) { if (keys.length > 0) {
@ -59,11 +60,11 @@ export async function runCommand(command: Command, config: CommandConfig) {
return `${key}: ${value}`; return `${key}: ${value}`;
}); });
console.log('Additional debugging info:\n'); log.write('Additional debugging info:\n');
console.log(indentString(metaOutput.join('\n'), 3)); log.write(indentString(metaOutput.join('\n'), 3));
} }
} else { } else {
console.log(e.stack); log.write(e.stack);
} }
process.exit(1); process.exit(1);

View file

@ -1,5 +1,5 @@
import { resolve, sep as pathSep } from 'path';
import cloneDeepWith from 'lodash.clonedeepwith'; import cloneDeepWith from 'lodash.clonedeepwith';
import { resolve, sep as pathSep } from 'path';
const repoRoot = resolve(__dirname, '../../../../'); const repoRoot = resolve(__dirname, '../../../../');
@ -16,8 +16,8 @@ const normalizePaths = (value: any) => {
}); });
return { return {
didReplacement,
clone, clone,
didReplacement,
}; };
}; };

View file

@ -1,7 +1,7 @@
import execa from 'execa';
import chalk from 'chalk'; import chalk from 'chalk';
import logTransformer from 'strong-log-transformer'; import execa from 'execa';
import logSymbols from 'log-symbols'; import logSymbols from 'log-symbols';
import logTransformer from 'strong-log-transformer';
function generateColors() { function generateColors() {
const colorWheel = [ const colorWheel = [
@ -42,8 +42,8 @@ export function spawnStreaming(
const color = nextColor(); const color = nextColor();
const prefixedStdout = logTransformer({ tag: `${color.bold(prefix)}:` }); const prefixedStdout = logTransformer({ tag: `${color.bold(prefix)}:` });
const prefixedStderr = logTransformer({ const prefixedStderr = logTransformer({
tag: `${logSymbols.error} ${color.bold(prefix)}:`,
mergeMultiline: true, mergeMultiline: true,
tag: `${logSymbols.error} ${color.bold(prefix)}:`,
}); });
spawned.stdout.pipe(prefixedStdout).pipe(process.stdout); spawned.stdout.pipe(prefixedStdout).pipe(process.stdout);

View file

@ -1,8 +1,8 @@
import fs from 'fs';
import { relative, dirname } from 'path';
import { promisify } from 'util';
import cmdShimCb from 'cmd-shim'; import cmdShimCb from 'cmd-shim';
import fs from 'fs';
import mkdirpCb from 'mkdirp'; import mkdirpCb from 'mkdirp';
import { dirname, relative } from 'path';
import { promisify } from 'util';
const stat = promisify(fs.stat); const stat = promisify(fs.stat);
const readFile = promisify(fs.readFile); const readFile = promisify(fs.readFile);

View file

@ -15,10 +15,10 @@ const projectsByName = new Map([
'foo', 'foo',
new Project( new Project(
{ {
name: 'foo',
dependencies: { dependencies: {
bar: 'link:../bar', bar: 'link:../bar',
}, },
name: 'foo',
}, },
resolve(__dirname, 'foo') resolve(__dirname, 'foo')
), ),
@ -27,8 +27,8 @@ const projectsByName = new Map([
'bar', 'bar',
new Project( new Project(
{ {
name: 'bar',
bin: 'bin/bar.js', bin: 'bin/bar.js',
name: 'bar',
}, },
resolve(__dirname, 'bar') resolve(__dirname, 'bar')
), ),
@ -37,10 +37,10 @@ const projectsByName = new Map([
'baz', 'baz',
new Project( new Project(
{ {
name: 'baz',
devDependencies: { devDependencies: {
bar: 'link:../bar', bar: 'link:../bar',
}, },
name: 'baz',
}, },
resolve(__dirname, 'baz') resolve(__dirname, 'baz')
), ),
@ -82,7 +82,9 @@ describe('bin script points to a file', () => {
const fs = require('./fs'); const fs = require('./fs');
fs.isFile.mockReturnValue(true); fs.isFile.mockReturnValue(true);
const logMock = jest.spyOn(console, 'log').mockImplementation(() => {}); const logMock = jest.spyOn(console, 'log').mockImplementation(() => {
// noop
});
await linkProjectExecutables(projectsByName, projectGraph); await linkProjectExecutables(projectsByName, projectGraph);
logMock.mockRestore(); logMock.mockRestore();

View file

@ -1,8 +1,9 @@
import { resolve, relative, dirname, sep } from 'path'; import { dirname, relative, resolve, sep } from 'path';
import chalk from 'chalk'; import chalk from 'chalk';
import { createSymlink, isFile, chmod, mkdirp } from './fs'; import { chmod, createSymlink, isFile, mkdirp } from './fs';
import { log } from './log';
import { ProjectGraph, ProjectMap } from './projects'; import { ProjectGraph, ProjectMap } from './projects';
/** /**
@ -39,7 +40,7 @@ export async function linkProjectExecutables(
.split(sep) .split(sep)
.join('/'); .join('/');
console.log( log.write(
chalk`{dim [${project.name}]} ${name} -> {dim ${projectRelativePath}}` chalk`{dim [${project.name}]} ${name} -> {dim ${projectRelativePath}}`
); );

View file

@ -0,0 +1,11 @@
export const log = {
/**
* Log something to the console. Ideally we would use a real logger in
* kbn-pm, but that's a pretty big change for now.
* @param ...args
*/
write(...args: any[]) {
// tslint:disable no-console
console.log(...args);
},
};

View file

@ -1,20 +1,25 @@
import readPkg from 'read-pkg'; import readPkg from 'read-pkg';
import writePkg from 'write-pkg'; import writePkg from 'write-pkg';
import path from 'path';
export type PackageJson = { [key: string]: any }; export interface IPackageJson {
export type PackageDependencies = { [key: string]: string }; [key: string]: any;
export type PackageScripts = { [key: string]: string }; }
export interface IPackageDependencies {
[key: string]: string;
}
export interface IPackageScripts {
[key: string]: string;
}
export function readPackageJson(dir: string) { export function readPackageJson(dir: string) {
return readPkg(dir, { normalize: false }); return readPkg(dir, { normalize: false });
} }
export function writePackageJson(path: string, json: PackageJson) { export function writePackageJson(path: string, json: IPackageJson) {
return writePkg(path, json); return writePkg(path, json);
} }
export const createProductionPackageJson = (pkgJson: PackageJson) => ({ export const createProductionPackageJson = (pkgJson: IPackageJson) => ({
...pkgJson, ...pkgJson,
dependencies: transformDependencies(pkgJson.dependencies), dependencies: transformDependencies(pkgJson.dependencies),
}); });
@ -31,8 +36,8 @@ export const isLinkDependency = (depVersion: string) =>
* will then _copy_ the `file:` dependencies into `node_modules` instead of * will then _copy_ the `file:` dependencies into `node_modules` instead of
* symlinking like we do in development. * symlinking like we do in development.
*/ */
export function transformDependencies(dependencies: PackageDependencies = {}) { export function transformDependencies(dependencies: IPackageDependencies = {}) {
const newDeps: PackageDependencies = {}; const newDeps: IPackageDependencies = {};
for (const name of Object.keys(dependencies)) { for (const name of Object.keys(dependencies)) {
const depVersion = dependencies[name]; const depVersion = dependencies[name];
if (isLinkDependency(depVersion)) { if (isLinkDependency(depVersion)) {

View file

@ -106,9 +106,9 @@ test('rejects if any promise rejects', async () => {
function createPromiseWithResolve() { function createPromiseWithResolve() {
let resolve: (val?: any) => void; let resolve: (val?: any) => void;
let reject: (err?: any) => void; let reject: (err?: any) => void;
const promise = new Promise((_resolve, _reject) => { const promise = new Promise((res, rej) => {
resolve = _resolve; resolve = res;
reject = _reject; reject = rej;
}); });
return { promise, resolve: resolve!, reject: reject!, called: false }; return { promise, resolve: resolve!, reject: reject!, called: false };
} }

View file

@ -1,11 +1,11 @@
import { resolve, join } from 'path'; import { join, resolve } from 'path';
import { PackageJson } from './package_json'; import { IPackageJson } from './package_json';
import { Project } from './project'; import { Project } from './project';
const rootPath = resolve(`${__dirname}/__fixtures__/kibana`); const rootPath = resolve(`${__dirname}/__fixtures__/kibana`);
const createProjectWith = (packageJson: PackageJson, path = '') => const createProjectWith = (packageJson: IPackageJson, path = '') =>
new Project( new Project(
{ {
name: 'kibana', name: 'kibana',
@ -25,12 +25,12 @@ describe('fromPath', () => {
test('fields', async () => { test('fields', async () => {
const kibana = createProjectWith({ const kibana = createProjectWith({
scripts: {
test: 'jest',
},
dependencies: { dependencies: {
foo: '1.2.3', foo: '1.2.3',
}, },
scripts: {
test: 'jest',
},
}); });
expect(kibana.name).toBe('kibana'); expect(kibana.name).toBe('kibana');

View file

@ -1,49 +1,50 @@
import path from 'path';
import { inspect } from 'util';
import chalk from 'chalk'; import chalk from 'chalk';
import { relative, resolve as resolvePath } from 'path';
import { inspect } from 'util';
import { CliError } from './errors';
import { log } from './log';
import {
IPackageDependencies,
IPackageJson,
IPackageScripts,
isLinkDependency,
readPackageJson,
} from './package_json';
import { import {
installInDir, installInDir,
runScriptInPackage, runScriptInPackage,
runScriptInPackageStreaming, runScriptInPackageStreaming,
} from './scripts'; } from './scripts';
import {
PackageJson,
PackageDependencies,
PackageScripts,
isLinkDependency,
readPackageJson,
} from './package_json';
import { CliError } from './errors';
interface BuildConfig { interface IBuildConfig {
skip?: boolean; skip?: boolean;
intermediateBuildDirectory?: string; intermediateBuildDirectory?: string;
} }
export class Project { export class Project {
static async fromPath(path: string) { public static async fromPath(path: string) {
const pkgJson = await readPackageJson(path); const pkgJson = await readPackageJson(path);
return new Project(pkgJson, path); return new Project(pkgJson, path);
} }
public readonly json: PackageJson; public readonly json: IPackageJson;
public readonly packageJsonLocation: string; public readonly packageJsonLocation: string;
public readonly nodeModulesLocation: string; public readonly nodeModulesLocation: string;
public readonly targetLocation: string; public readonly targetLocation: string;
public readonly path: string; public readonly path: string;
public readonly allDependencies: PackageDependencies; public readonly allDependencies: IPackageDependencies;
public readonly productionDependencies: PackageDependencies; public readonly productionDependencies: IPackageDependencies;
public readonly devDependencies: PackageDependencies; public readonly devDependencies: IPackageDependencies;
public readonly scripts: PackageScripts; public readonly scripts: IPackageScripts;
constructor(packageJson: PackageJson, projectPath: string) { constructor(packageJson: IPackageJson, projectPath: string) {
this.json = Object.freeze(packageJson); this.json = Object.freeze(packageJson);
this.path = projectPath; this.path = projectPath;
this.packageJsonLocation = path.resolve(this.path, 'package.json'); this.packageJsonLocation = resolvePath(this.path, 'package.json');
this.nodeModulesLocation = path.resolve(this.path, 'node_modules'); this.nodeModulesLocation = resolvePath(this.path, 'node_modules');
this.targetLocation = path.resolve(this.path, 'target'); this.targetLocation = resolvePath(this.path, 'target');
this.productionDependencies = this.json.dependencies || {}; this.productionDependencies = this.json.dependencies || {};
this.devDependencies = this.json.devDependencies || {}; this.devDependencies = this.json.devDependencies || {};
@ -59,9 +60,9 @@ export class Project {
return this.json.name; return this.json.name;
} }
ensureValidProjectDependency(project: Project) { public ensureValidProjectDependency(project: Project) {
const relativePathToProject = normalizePath( const relativePathToProject = normalizePath(
path.relative(this.path, project.path) relative(this.path, project.path)
); );
const versionInPackageJson = this.allDependencies[project.name]; const versionInPackageJson = this.allDependencies[project.name];
@ -73,9 +74,9 @@ export class Project {
const updateMsg = 'Update its package.json to the expected value below.'; const updateMsg = 'Update its package.json to the expected value below.';
const meta = { const meta = {
package: `${this.name} (${this.packageJsonLocation})`,
expected: `"${project.name}": "${expectedVersionInPackageJson}"`,
actual: `"${project.name}": "${versionInPackageJson}"`, actual: `"${project.name}": "${versionInPackageJson}"`,
expected: `"${project.name}": "${expectedVersionInPackageJson}"`,
package: `${this.name} (${this.packageJsonLocation})`,
}; };
if (isLinkDependency(versionInPackageJson)) { if (isLinkDependency(versionInPackageJson)) {
@ -95,7 +96,7 @@ export class Project {
); );
} }
getBuildConfig(): BuildConfig { public getBuildConfig(): IBuildConfig {
return (this.json.kibana && this.json.kibana.build) || {}; return (this.json.kibana && this.json.kibana.build) || {};
} }
@ -104,18 +105,18 @@ export class Project {
* This config can be specified to only include the project's build artifacts * This config can be specified to only include the project's build artifacts
* instead of everything located in the project directory. * instead of everything located in the project directory.
*/ */
getIntermediateBuildDirectory() { public getIntermediateBuildDirectory() {
return path.resolve( return resolvePath(
this.path, this.path,
this.getBuildConfig().intermediateBuildDirectory || '.' this.getBuildConfig().intermediateBuildDirectory || '.'
); );
} }
hasScript(name: string) { public hasScript(name: string) {
return name in this.scripts; return name in this.scripts;
} }
getExecutables(): { [key: string]: string } { public getExecutables(): { [key: string]: string } {
const raw = this.json.bin; const raw = this.json.bin;
if (!raw) { if (!raw) {
@ -124,14 +125,14 @@ export class Project {
if (typeof raw === 'string') { if (typeof raw === 'string') {
return { return {
[this.name]: path.resolve(this.path, raw), [this.name]: resolvePath(this.path, raw),
}; };
} }
if (typeof raw === 'object') { if (typeof raw === 'object') {
const binsConfig: { [k: string]: string } = {}; const binsConfig: { [k: string]: string } = {};
for (const binName of Object.keys(raw)) { for (const binName of Object.keys(raw)) {
binsConfig[binName] = path.resolve(this.path, raw[binName]); binsConfig[binName] = resolvePath(this.path, raw[binName]);
} }
return binsConfig; return binsConfig;
} }
@ -140,14 +141,14 @@ export class Project {
`[${this.name}] has an invalid "bin" field in its package.json, ` + `[${this.name}] has an invalid "bin" field in its package.json, ` +
`expected an object or a string`, `expected an object or a string`,
{ {
package: `${this.name} (${this.packageJsonLocation})`,
binConfig: inspect(raw), binConfig: inspect(raw),
package: `${this.name} (${this.packageJsonLocation})`,
} }
); );
} }
async runScript(scriptName: string, args: string[] = []) { public async runScript(scriptName: string, args: string[] = []) {
console.log( log.write(
chalk.bold( chalk.bold(
`\n\nRunning script [${chalk.green(scriptName)}] in [${chalk.green( `\n\nRunning script [${chalk.green(scriptName)}] in [${chalk.green(
this.name this.name
@ -157,16 +158,16 @@ export class Project {
return runScriptInPackage(scriptName, args, this); return runScriptInPackage(scriptName, args, this);
} }
runScriptStreaming(scriptName: string, args: string[] = []) { public runScriptStreaming(scriptName: string, args: string[] = []) {
return runScriptInPackageStreaming(scriptName, args, this); return runScriptInPackageStreaming(scriptName, args, this);
} }
hasDependencies() { public hasDependencies() {
return Object.keys(this.allDependencies).length > 0; return Object.keys(this.allDependencies).length > 0;
} }
async installDependencies({ extraArgs }: { extraArgs: string[] }) { public async installDependencies({ extraArgs }: { extraArgs: string[] }) {
console.log( log.write(
chalk.bold( chalk.bold(
`\n\nInstalling dependencies in [${chalk.green(this.name)}]:\n` `\n\nInstalling dependencies in [${chalk.green(this.name)}]:\n`
) )

View file

@ -1,15 +1,15 @@
import { resolve } from 'path'; import { resolve } from 'path';
import {
getProjects,
buildProjectGraph,
topologicallyBatchProjects,
includeTransitiveProjects,
ProjectMap,
ProjectGraph,
} from './projects';
import { Project } from './project';
import { getProjectPaths } from '../config'; import { getProjectPaths } from '../config';
import { Project } from './project';
import {
buildProjectGraph,
getProjects,
includeTransitiveProjects,
ProjectGraph,
ProjectMap,
topologicallyBatchProjects,
} from './projects';
const rootPath = resolve(`${__dirname}/__fixtures__/kibana`); const rootPath = resolve(`${__dirname}/__fixtures__/kibana`);
@ -164,12 +164,12 @@ describe('#getProjects', () => {
describe('#buildProjectGraph', () => { describe('#buildProjectGraph', () => {
test('builds full project graph', async () => { test('builds full project graph', async () => {
const projects = await getProjects(rootPath, [ const allProjects = await getProjects(rootPath, [
'.', '.',
'packages/*', 'packages/*',
'../plugins/*', '../plugins/*',
]); ]);
const graph = buildProjectGraph(projects); const graph = buildProjectGraph(allProjects);
const expected: { [k: string]: string[] } = {}; const expected: { [k: string]: string[] } = {};
for (const [projectName, projects] of graph.entries()) { for (const [projectName, projects] of graph.entries()) {

View file

@ -9,12 +9,15 @@ const glob = promisify(globSync);
export type ProjectMap = Map<string, Project>; export type ProjectMap = Map<string, Project>;
export type ProjectGraph = Map<string, Project[]>; export type ProjectGraph = Map<string, Project[]>;
export type ProjectsOptions = { include?: string[]; exclude?: string[] }; export interface IProjectsOptions {
include?: string[];
exclude?: string[];
}
export async function getProjects( export async function getProjects(
rootPath: string, rootPath: string,
projectsPathsPatterns: string[], projectsPathsPatterns: string[],
{ include = [], exclude = [] }: ProjectsOptions = {} { include = [], exclude = [] }: IProjectsOptions = {}
) { ) {
const projects: ProjectMap = new Map(); const projects: ProjectMap = new Map();

View file

@ -1,9 +1,9 @@
import { resolve } from 'path'; import { resolve } from 'path';
import { stripAnsiSnapshotSerializer } from '../test_helpers';
import { renderProjectsTree } from './projects_tree';
import { getProjects } from './projects';
import { getProjectPaths } from '../config'; import { getProjectPaths } from '../config';
import { stripAnsiSnapshotSerializer } from '../test_helpers';
import { getProjects } from './projects';
import { renderProjectsTree } from './projects_tree';
const rootPath = resolve(`${__dirname}/__fixtures__/kibana`); const rootPath = resolve(`${__dirname}/__fixtures__/kibana`);

View file

@ -1,5 +1,5 @@
import path from 'path';
import chalk from 'chalk'; import chalk from 'chalk';
import path from 'path';
import { Project } from './project'; import { Project } from './project';
@ -13,41 +13,44 @@ export function renderProjectsTree(
return treeToString(createTreeStructure(projectsTree)); return treeToString(createTreeStructure(projectsTree));
} }
type Tree = { interface ITree {
name?: string; name?: string;
children?: TreeChildren; children?: ITreeChildren;
}; }
interface TreeChildren extends Array<Tree> {} interface ITreeChildren extends Array<ITree> {}
type DirOrProjectName = string | typeof projectKey; type DirOrProjectName = string | typeof projectKey;
type ProjectsTree = Map<DirOrProjectName, ProjectsTreeValue | string>;
interface ProjectsTreeValue extends ProjectsTree {}
function treeToString(tree: Tree) { interface IProjectsTree extends Map<DirOrProjectName, string | IProjectsTree> {}
return [tree.name].concat(childrenToString(tree.children, '')).join('\n');
function treeToString(tree: ITree) {
return [tree.name].concat(childrenToStrings(tree.children, '')).join('\n');
} }
function childrenToString(tree: TreeChildren | undefined, treePrefix: string) { function childrenToStrings(
tree: ITreeChildren | undefined,
treePrefix: string
) {
if (tree === undefined) { if (tree === undefined) {
return []; return [];
} }
let string: string[] = []; let strings: string[] = [];
tree.forEach((node, index) => { tree.forEach((node, index) => {
const isLastNode = tree.length - 1 === index; const isLastNode = tree.length - 1 === index;
const nodePrefix = isLastNode ? '└── ' : '├── '; const nodePrefix = isLastNode ? '└── ' : '├── ';
const childPrefix = isLastNode ? ' ' : '│ '; const childPrefix = isLastNode ? ' ' : '│ ';
const childrenPrefix = treePrefix + childPrefix; const childrenPrefix = treePrefix + childPrefix;
string.push(`${treePrefix}${nodePrefix}${node.name}`); strings.push(`${treePrefix}${nodePrefix}${node.name}`);
string = string.concat(childrenToString(node.children, childrenPrefix)); strings = strings.concat(childrenToStrings(node.children, childrenPrefix));
}); });
return string; return strings;
} }
function createTreeStructure(tree: ProjectsTree): Tree { function createTreeStructure(tree: IProjectsTree): ITree {
let name: string | undefined; let name: string | undefined;
const children: TreeChildren = []; const children: ITreeChildren = [];
for (const [dir, project] of tree.entries()) { for (const [dir, project] of tree.entries()) {
// This is a leaf node (aka a project) // This is a leaf node (aka a project)
@ -63,8 +66,8 @@ function createTreeStructure(tree: ProjectsTree): Tree {
if (project.size === 1 && project.has(projectKey)) { if (project.size === 1 && project.has(projectKey)) {
const projectName = project.get(projectKey)! as string; const projectName = project.get(projectKey)! as string;
children.push({ children.push({
name: dirOrProjectName(dir, projectName),
children: [], children: [],
name: dirOrProjectName(dir, projectName),
}); });
continue; continue;
} }
@ -77,8 +80,8 @@ function createTreeStructure(tree: ProjectsTree): Tree {
const projectName = subtree.name; const projectName = subtree.name;
children.push({ children.push({
name: dirOrProjectName(dir, projectName),
children: subtree.children, children: subtree.children,
name: dirOrProjectName(dir, projectName),
}); });
continue; continue;
} }
@ -91,15 +94,15 @@ function createTreeStructure(tree: ProjectsTree): Tree {
const newName = chalk.dim(path.join(dir.toString(), child.name!)); const newName = chalk.dim(path.join(dir.toString(), child.name!));
children.push({ children.push({
name: newName,
children: child.children, children: child.children,
name: newName,
}); });
continue; continue;
} }
children.push({ children.push({
name: chalk.dim(dir.toString()),
children: subtree.children, children: subtree.children,
name: chalk.dim(dir.toString()),
}); });
} }
@ -113,7 +116,7 @@ function dirOrProjectName(dir: DirOrProjectName, projectName: string) {
} }
function buildProjectsTree(rootPath: string, projects: Map<string, Project>) { function buildProjectsTree(rootPath: string, projects: Map<string, Project>) {
const tree: ProjectsTree = new Map(); const tree: IProjectsTree = new Map();
for (const project of projects.values()) { for (const project of projects.values()) {
if (rootPath === project.path) { if (rootPath === project.path) {
@ -128,7 +131,7 @@ function buildProjectsTree(rootPath: string, projects: Map<string, Project>) {
} }
function addProjectToTree( function addProjectToTree(
tree: ProjectsTree, tree: IProjectsTree,
pathParts: string[], pathParts: string[],
project: Project project: Project
) { ) {
@ -141,7 +144,7 @@ function addProjectToTree(
tree.set(currentDir, new Map()); tree.set(currentDir, new Map());
} }
const subtree = tree.get(currentDir) as ProjectsTree; const subtree = tree.get(currentDir) as IProjectsTree;
addProjectToTree(subtree, rest, project); addProjectToTree(subtree, rest, project);
} }
} }

View file

@ -14,7 +14,7 @@ const defaultHandlerReadinessTimeout = 2000;
/** /**
* Describes configurable watch options. * Describes configurable watch options.
*/ */
interface WatchOptions { interface IWatchOptions {
/** /**
* Number of milliseconds to wait before we fall back to default watch handler. * Number of milliseconds to wait before we fall back to default watch handler.
*/ */
@ -33,7 +33,7 @@ function getWatchHandlers(
{ {
handlerDelay = defaultHandlerDelay, handlerDelay = defaultHandlerDelay,
handlerReadinessTimeout = defaultHandlerReadinessTimeout, handlerReadinessTimeout = defaultHandlerReadinessTimeout,
}: WatchOptions }: IWatchOptions
) { ) {
const typescriptHandler = buildOutput$ const typescriptHandler = buildOutput$
.first(data => data.includes('$ tsc')) .first(data => data.includes('$ tsc'))
@ -60,7 +60,7 @@ function getWatchHandlers(
export function waitUntilWatchIsReady( export function waitUntilWatchIsReady(
stream: NodeJS.EventEmitter, stream: NodeJS.EventEmitter,
opts: WatchOptions = {} opts: IWatchOptions = {}
) { ) {
const buildOutput$ = new Subject<string>(); const buildOutput$ = new Subject<string>();
const onDataListener = (data: Buffer) => const onDataListener = (data: Buffer) =>

View file

@ -1,19 +0,0 @@
extends: ../../tslint.yaml
rules:
max-classes-per-file: false
interface-name: false
variable-name: false
no-empty: false
object-literal-sort-keys: false
member-ordering: false
no-console: false
only-arrow-functions: false
no-shadowed-variable: false
no-empty-interface: false
ordered-imports: false
interface-over-type-literal: false
prettier: false
prefer-const: false
member-access: false
no-unused-variable: false