mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 10:23:14 -04:00
[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:
parent
3d08c5cb31
commit
ce20463f59
30 changed files with 248 additions and 228 deletions
|
@ -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);
|
||||||
|
|
|
@ -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'
|
||||||
);
|
);
|
||||||
|
|
|
@ -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'));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 });
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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/*']);
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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}}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
11
packages/kbn-pm/src/utils/log.ts
Normal file
11
packages/kbn-pm/src/utils/log.ts
Normal 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);
|
||||||
|
},
|
||||||
|
};
|
|
@ -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)) {
|
||||||
|
|
|
@ -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 };
|
||||||
}
|
}
|
||||||
|
|
|
@ -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');
|
||||||
|
|
|
@ -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`
|
||||||
)
|
)
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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`);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) =>
|
||||||
|
|
|
@ -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
|
|
Loading…
Add table
Add a link
Reference in a new issue