cleanup(core): remove all deps on angular-devkit from tao

This commit is contained in:
victor savkin 2020-12-02 14:56:29 -05:00 committed by Victor Savkin
parent 86c0eef9cc
commit ae397d2d10
12 changed files with 199 additions and 159 deletions

View File

@ -4,7 +4,7 @@ import { FsTree } from '@nrwl/tao/src/shared/tree';
* Creates a host for testing.
*/
export function createTreeWithEmptyWorkspace() {
const tree = new FsTree('/virtual', false, console);
const tree = new FsTree('/virtual', false);
tree.write(
'/workspace.json',

View File

@ -20,7 +20,6 @@ import {
isStringLiteral,
ScriptTarget,
} from 'typescript';
import { getLogger } from '@nrwl/tao/src/shared/logger';
const ignore = require('ignore');
export default function update(): Rule {
@ -33,8 +32,7 @@ export default function update(): Rule {
updateImports,
removeObsoletePackages,
(_, context: SchematicContext) => {
const logger = getLogger();
logger.info(
console.info(
'NX We upgraded Nest.js to v7. Make sure to read the migration guide: https://docs.nestjs.com/migration-guide'
);
},

View File

@ -1,5 +1,4 @@
import * as minimist from 'minimist';
import { getLogger } from '../shared/logger';
import {
combineOptionsForGenerator,
convertToCamelCase,
@ -13,6 +12,7 @@ import { statSync, unlinkSync, writeFileSync } from 'fs';
import { mkdirpSync, rmdirSync } from 'fs-extra';
import * as path from 'path';
import { FileChange, FsTree } from '../shared/tree';
import { logger } from '../shared/logger';
const chalk = require('chalk');
@ -103,26 +103,18 @@ function parseGenerateOpts(
return res;
}
export function printGenHelp(
opts: GenerateOptions,
schema: Schema,
logger: Console
) {
printHelp(
`nx generate ${opts.collectionName}:${opts.generatorName}`,
{
...schema,
properties: {
...schema.properties,
dryRun: {
type: 'boolean',
default: false,
description: `Runs through and reports activity without writing to disk.`,
},
export function printGenHelp(opts: GenerateOptions, schema: Schema) {
printHelp(`nx generate ${opts.collectionName}:${opts.generatorName}`, {
...schema,
properties: {
...schema.properties,
dryRun: {
type: 'boolean',
default: false,
description: `Runs through and reports activity without writing to disk.`,
},
},
logger as any
);
});
}
function readDefaultCollection(workspace: WorkspaceConfiguration) {
@ -163,9 +155,8 @@ function printChanges(fileChanges: FileChange[]) {
}
export async function taoNew(root: string, args: string[], isVerbose = false) {
const logger = getLogger(isVerbose);
const ws = new Workspaces();
return handleErrors(logger, isVerbose, async () => {
return handleErrors(isVerbose, async () => {
const opts = parseGenerateOpts(args, 'new', null);
const { schema, implementation } = ws.readGenerator(
@ -181,10 +172,14 @@ export async function taoNew(root: string, args: string[], isVerbose = false) {
schema,
opts.interactive
);
return (await import('./ngcli-adapter')).invokeNew(logger, root, {
...opts,
generatorOptions: combinedOpts,
});
return (await import('./ngcli-adapter')).invokeNew(
root,
{
...opts,
generatorOptions: combinedOpts,
},
isVerbose
);
});
}
@ -193,10 +188,9 @@ export async function generate(
args: string[],
isVerbose = false
) {
const logger = getLogger(isVerbose);
const ws = new Workspaces();
return handleErrors(logger, isVerbose, async () => {
return handleErrors(isVerbose, async () => {
const workspaceDefinition = ws.readWorkspaceConfiguration(root);
const opts = parseGenerateOpts(
args,
@ -210,7 +204,7 @@ export async function generate(
);
if (opts.help) {
printGenHelp(opts, schema, logger as any);
printGenHelp(opts, schema);
return 0;
}
const combinedOpts = await combineOptionsForGenerator(
@ -223,7 +217,7 @@ export async function generate(
);
if (ws.isNxGenerator(opts.collectionName, opts.generatorName)) {
const host = new FsTree(root, isVerbose, logger);
const host = new FsTree(root, isVerbose);
const task = await implementation(host, combinedOpts);
const changes = host.listChanges();
@ -237,10 +231,14 @@ export async function generate(
logger.warn(`\nNOTE: The "dryRun" flag means no changes were made.`);
}
} else {
return (await import('./ngcli-adapter')).generate(logger, root, {
...opts,
generatorOptions: combinedOpts,
});
return (await import('./ngcli-adapter')).generate(
root,
{
...opts,
generatorOptions: combinedOpts,
},
isVerbose
);
}
});
}

View File

@ -1,11 +1,9 @@
import { tags } from '@angular-devkit/core';
import * as chalk from 'chalk';
import { getLogger } from '../shared/logger';
import { logger, stripIndent } from '../shared/logger';
export function help() {
const logger = getLogger(true);
logger.info(tags.stripIndent`
logger.info(
stripIndent(`
${chalk.bold('Nx - Extensible Dev Tools for Monorepos.')}
${chalk.bold('Create a new project.')}
@ -30,6 +28,7 @@ export function help() {
${chalk.bold('Run migrations.')}
nx migrate ${chalk.grey('--run-migrations=[filename]')}
`);
`)
);
return 0;
}

View File

@ -1,4 +1,3 @@
import { logging } from '@angular-devkit/core';
import { execSync } from 'child_process';
import * as fs from 'fs';
import { readFileSync, writeFileSync } from 'fs';
@ -7,14 +6,15 @@ import { dirname, join } from 'path';
import { gt, lte } from 'semver';
import * as stripJsonComments from 'strip-json-comments';
import { dirSync } from 'tmp';
import { getLogger } from '../shared/logger';
import { logger } from '../shared/logger';
import { convertToCamelCase, handleErrors } from '../shared/params';
import {
detectPackageManager,
getPackageManagerCommand,
} from '@nrwl/tao/src/shared/package-manager';
import { FsTree } from '@nrwl/tao/src/shared/tree';
import { flushChanges } from '@nrwl/tao/src/commands/generate';
} from '../shared/package-manager';
import { FsTree } from '../shared/tree';
import { flushChanges } from './generate';
import * as fsExtra from 'fs-extra';
export type MigrationsJson = {
version: string;
@ -414,7 +414,7 @@ function versions(root: string, from: { [p: string]: string }) {
}
// testing-fetch-start
function createFetcher(packageManager: string, logger: logging.Logger) {
function createFetcher(packageManager: string) {
const cache = {};
return async function f(
packageName: string,
@ -429,11 +429,7 @@ function createFetcher(packageManager: string, logger: logging.Logger) {
cwd: dir,
});
const migrationsFilePath = packageToMigrationsFilePath(
logger,
packageName,
dir
);
const migrationsFilePath = packageToMigrationsFilePath(packageName, dir);
const packageJsonPath = require.resolve(`${packageName}/package.json`, {
paths: [dir],
});
@ -463,11 +459,7 @@ function createFetcher(packageManager: string, logger: logging.Logger) {
}
// testing-fetch-end
function packageToMigrationsFilePath(
logger: logging.Logger,
packageName: string,
dir: string
) {
function packageToMigrationsFilePath(packageName: string, dir: string) {
const packageJsonPath = require.resolve(`${packageName}/package.json`, {
paths: [dir],
});
@ -536,7 +528,6 @@ function updatePackageJson(
}
async function generateMigrationsJsonAndUpdatePackageJson(
logger: logging.Logger,
root: string,
opts: {
targetPackage: string;
@ -552,7 +543,7 @@ async function generateMigrationsJsonAndUpdatePackageJson(
logger.info(`It may take a few minutes.`);
const migrator = new Migrator({
versions: versions(root, opts.from),
fetch: createFetcher(packageManager, logger),
fetch: createFetcher(packageManager),
from: opts.from,
to: opts.to,
});
@ -603,11 +594,7 @@ async function generateMigrationsJsonAndUpdatePackageJson(
}
}
async function runMigrations(
logger: logging.Logger,
root: string,
opts: { runMigrations: string }
) {
async function runMigrations(root: string, opts: { runMigrations: string }) {
const migrations: {
package: string;
name: string;
@ -620,10 +607,9 @@ async function runMigrations(
for (let m of migrations) {
logger.info(`Running migration ${m.name}`);
if (m.cli === 'nx') {
await runNxMigration(logger, root, m.package, m.name);
await runNxMigration(root, m.package, m.name);
} else {
await (await import('./ngcli-adapter')).runMigration(
logger,
root,
m.package,
m.name
@ -634,13 +620,8 @@ async function runMigrations(
}
}
async function runNxMigration(
logger: logging.Logger,
root: string,
packageName: string,
name: string
) {
const collectionPath = packageToMigrationsFilePath(logger, packageName, root);
async function runNxMigration(root: string, packageName: string, name: string) {
const collectionPath = packageToMigrationsFilePath(packageName, root);
const collection = JSON.parse(fs.readFileSync(collectionPath).toString());
const g = collection.generators || collection.schematics;
const implRelativePath = g[name].implementation || g[name].factory;
@ -648,21 +629,28 @@ async function runNxMigration(
paths: [dirname(collectionPath)],
});
const fn = require(implPath).default;
const host = new FsTree(root, false, logger as any);
const host = new FsTree(root, false);
await fn(host, {});
const changes = host.listChanges();
flushChanges(root, changes);
}
export async function migrate(root: string, args: string[], isVerbose = false) {
const logger = getLogger(isVerbose);
function removeNxDepsIfCaseItsFormatChanged(root: string) {
try {
fsExtra.unlinkSync(
join(root, 'node_modules', '.cache', 'nx', 'nxdeps.json')
);
} catch (e) {}
}
return handleErrors(logger, isVerbose, async () => {
export async function migrate(root: string, args: string[], isVerbose = false) {
return handleErrors(isVerbose, async () => {
removeNxDepsIfCaseItsFormatChanged(root);
const opts = parseMigrationsOptions(args);
if (opts.type === 'generateMigrations') {
await generateMigrationsJsonAndUpdatePackageJson(logger, root, opts);
await generateMigrationsJsonAndUpdatePackageJson(root, opts);
} else {
await runMigrations(logger, root, opts);
await runMigrations(root, opts);
}
});
}

View File

@ -11,7 +11,7 @@ import {
workspaces,
} from '@angular-devkit/core';
import * as chalk from 'chalk';
import { NodeJsSyncHost } from '@angular-devkit/core/node';
import { createConsoleLogger, NodeJsSyncHost } from '@angular-devkit/core/node';
import { RunOptions } from './run';
import {
FileSystemCollectionDescription,
@ -43,8 +43,10 @@ import * as stripJsonComments from 'strip-json-comments';
import { FileBuffer } from '@angular-devkit/core/src/virtual-fs/host/interface';
import { Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { NX_ERROR, NX_PREFIX } from '../shared/logger';
export async function run(logger: any, root: string, opts: RunOptions) {
export async function run(root: string, opts: RunOptions, verbose: boolean) {
const logger = getLogger(verbose);
const fsHost = new NxScopedHost(normalize(root));
const { workspace } = await workspaces.readWorkspace(
workspaceConfigName(root),
@ -341,10 +343,11 @@ class NxScopedHost extends virtualFs.ScopedHost<any> {
}
export async function generate(
logger: logging.Logger,
root: string,
opts: GenerateOptions
opts: GenerateOptions,
verbose: boolean
) {
const logger = getLogger(verbose);
const fsHost = new NxScopedHost(normalize(root));
const workflow = createWorkflow(fsHost, root, opts);
const collection = getCollection(workflow, opts.collectionName);
@ -353,7 +356,7 @@ export async function generate(
await runSchematic(
root,
workflow,
logger,
logger as any,
{ ...opts, generatorName: schematic.description.name },
schematic
)
@ -361,20 +364,19 @@ export async function generate(
}
export async function runMigration(
logger: logging.Logger,
root: string,
collection: string,
schematic: string
) {
const host = new NxScopedHost(normalize(root));
const workflow = new MigrationsWorkflow(host, logger);
const workflow = new MigrationsWorkflow(host, logger as any);
return workflow
.execute({
collection,
schematic,
options: {},
debug: false,
logger,
logger: logger as any,
})
.toPromise();
}
@ -452,10 +454,11 @@ export function wrapAngularDevkitSchematic(
}
export async function invokeNew(
logger: logging.Logger,
root: string,
opts: GenerateOptions
opts: GenerateOptions,
verbose: boolean
) {
const logger = getLogger(verbose);
const fsHost = new NxScopedHost(normalize(root));
const workflow = createWorkflow(fsHost, root, opts);
const collection = getCollection(workflow, opts.collectionName);
@ -464,9 +467,33 @@ export async function invokeNew(
await runSchematic(
root,
workflow,
logger,
logger as any,
{ ...opts, generatorName: schematic.description.name },
schematic
)
).status;
}
let logger: logging.Logger;
export const getLogger = (isVerbose = false): any => {
if (!logger) {
logger = createConsoleLogger(isVerbose, process.stdout, process.stderr, {
warn: (s) => chalk.bold(chalk.yellow(s)),
error: (s) => {
if (s.startsWith('NX ')) {
return `\n${NX_ERROR} ${chalk.bold(chalk.red(s.substr(3)))}\n`;
}
return chalk.bold(chalk.red(s));
},
info: (s) => {
if (s.startsWith('NX ')) {
return `\n${NX_PREFIX} ${chalk.bold(s.substr(3))}\n`;
}
return chalk.white(s);
},
});
}
return logger;
};

View File

@ -1,5 +1,4 @@
import * as minimist from 'minimist';
import { getLogger } from '../shared/logger';
import {
combineOptionsForExecutor,
convertToCamelCase,
@ -15,6 +14,7 @@ import {
} from '../shared/workspace';
import * as chalk from 'chalk';
import { logger } from '../shared/logger';
export interface RunOptions {
project: string;
@ -32,8 +32,7 @@ function throwInvalidInvocation() {
function parseRunOpts(
args: string[],
defaultProjectName: string | null,
logger: Console
defaultProjectName: string | null
): RunOptions {
const runOptions = convertToCamelCase(
minimist(args, {
@ -81,12 +80,8 @@ function parseRunOpts(
return res;
}
export function printRunHelp(
opts: RunOptions,
schema: Schema,
logger: Console
) {
printHelp(`nx run ${opts.project}:${opts.target}`, schema, logger as any);
export function printRunHelp(opts: RunOptions, schema: Schema) {
printHelp(`nx run ${opts.project}:${opts.target}`, schema);
}
export function validateTargetAndConfiguration(
@ -136,12 +131,11 @@ export interface TargetContext {
}
export async function run(root: string, args: string[], isVerbose: boolean) {
const logger = getLogger(isVerbose) as any;
const ws = new Workspaces();
return handleErrors(logger, isVerbose, async () => {
return handleErrors(isVerbose, async () => {
const workspace = ws.readWorkspaceConfiguration(root);
const opts = parseRunOpts(args, workspace.defaultProject, logger);
const opts = parseRunOpts(args, workspace.defaultProject);
validateTargetAndConfiguration(workspace, opts);
const target = workspace.projects[opts.project].targets[opts.target];
@ -154,17 +148,21 @@ export async function run(root: string, args: string[], isVerbose: boolean) {
schema
);
if (opts.help) {
printRunHelp(opts, schema, logger);
printRunHelp(opts, schema);
return 0;
}
if (ws.isNxExecutor(nodeModule, executor)) {
return await implementation(combinedOptions, { root, target, workspace });
} else {
return (await import('./ngcli-adapter')).run(logger, root, {
...opts,
runOptions: combinedOptions,
});
return (await import('./ngcli-adapter')).run(
root,
{
...opts,
runOptions: combinedOptions,
},
isVerbose
);
}
});
}

View File

@ -1,34 +1,44 @@
import { logging } from '@angular-devkit/core';
import * as chalk from 'chalk';
import { createConsoleLogger } from '@angular-devkit/core/node';
const NX_PREFIX = `${chalk.cyan('>')} ${chalk.inverse(
export const NX_PREFIX = `${chalk.cyan('>')} ${chalk.inverse(
chalk.bold(chalk.cyan(' NX '))
)}`;
const NX_ERROR = chalk.inverse(chalk.bold(chalk.red(' ERROR ')));
export const NX_ERROR = chalk.inverse(chalk.bold(chalk.red(' ERROR ')));
let logger: logging.Logger;
export const getLogger = (isVerbose = false): any => {
if (!logger) {
logger = createConsoleLogger(isVerbose, process.stdout, process.stderr, {
warn: (s) => chalk.bold(chalk.yellow(s)),
error: (s) => {
if (s.startsWith('NX ')) {
return `\n${NX_ERROR} ${chalk.bold(chalk.red(s.substr(3)))}\n`;
}
return chalk.bold(chalk.red(s));
},
info: (s) => {
if (s.startsWith('NX ')) {
return `\n${NX_PREFIX} ${chalk.bold(s.substr(3))}\n`;
}
return chalk.white(s);
},
});
}
return logger;
export const logger = {
warn: (s) => console.warn(chalk.bold(chalk.yellow(s))),
error: (s) => {
if (s.startsWith('NX ')) {
console.error(`\n${NX_ERROR} ${chalk.bold(chalk.red(s.substr(3)))}\n`);
} else {
console.error(chalk.bold(chalk.red(s)));
}
},
info: (s) => {
if (s.startsWith('NX ')) {
console.info(`\n${NX_PREFIX} ${chalk.bold(s.substr(3))}\n`);
} else {
console.info(chalk.white(s));
}
},
log: (...s) => {
console.log(...s);
},
debug: (...s) => {
console.debug(...s);
},
fatal: (...s) => {
console.error(...s);
},
};
export function stripIndent(str: string): string {
const match = str.match(/^[ \t]*(?=\S)/gm);
if (!match) {
return str;
}
const indent = match.reduce((r, a) => Math.min(r, a.length), Infinity);
const regex = new RegExp(`^[ \\t]{${indent}}`, 'gm');
return str.replace(regex, '');
}

View File

@ -1,7 +1,7 @@
import { strings } from '@angular-devkit/core';
import { ParsedArgs } from 'minimist';
import { TargetConfiguration, WorkspaceConfiguration } from './workspace';
import * as inquirer from 'inquirer';
import { logger } from './logger';
type Properties = {
[p: string]: {
@ -34,11 +34,7 @@ export type Options = {
[k: string]: string | number | boolean | string[] | Unmatched[];
};
export async function handleErrors(
logger: Console,
isVerbose: boolean,
fn: Function
) {
export async function handleErrors(isVerbose: boolean, fn: Function) {
try {
return await fn();
} catch (err) {
@ -434,13 +430,44 @@ export function lookupUnmatched(opts: Options, schema: Schema): Options {
opts['--'].forEach((unmatched) => {
unmatched.possible = props.filter(
(p) => strings.levenshtein(p, unmatched.name) < 3
(p) => levenshtein(p, unmatched.name) < 3
);
});
}
return opts;
}
function levenshtein(a: string, b: string) {
if (a.length == 0) {
return b.length;
}
if (b.length == 0) {
return a.length;
}
const matrix = [];
for (let i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
for (let j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
for (let i = 1; i <= b.length; i++) {
for (let j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) == a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1,
matrix[i][j - 1] + 1,
matrix[i - 1][j] + 1
);
}
}
}
return matrix[b.length][a.length];
}
function isTTY(): boolean {
return !!process.stdout.isTTY && process.env['CI'] !== 'true';
}

View File

@ -1,6 +1,6 @@
import { logging, tags } from '@angular-devkit/core';
import { Schema } from './params';
import * as chalk from 'chalk';
import { logger, stripIndent } from '../shared/logger';
function formatOption(name: string, description: string) {
return ` --${(name + ' ').substr(0, 22)}${chalk.grey(
@ -8,11 +8,7 @@ function formatOption(name: string, description: string) {
)}`;
}
export function printHelp(
header: string,
schema: Schema,
logger: logging.Logger
) {
export function printHelp(header: string, schema: Schema) {
const allPositional = Object.keys(schema.properties).filter((key) => {
const p = schema.properties[key];
return p['$default'] && p['$default']['$source'] === 'argv';
@ -26,11 +22,13 @@ export function printHelp(
})
.join('\n');
logger.info(tags.stripIndent`
logger.info(
stripIndent(`
${chalk.bold(header + positional + ' [options,...]')}
${chalk.bold('Options')}:
${args}
${formatOption('help', 'Show available options for project target.')}
`);
`)
);
}

View File

@ -22,7 +22,7 @@ describe('tree', () => {
'child content'
);
tree = new FsTree(dir, false, console);
tree = new FsTree(dir, false);
});
afterEach(() => {

View File

@ -7,6 +7,7 @@ import {
writeFileSync,
} from 'fs';
import { mkdirpSync, rmdirSync } from 'fs-extra';
import { logger } from './logger';
const chalk = require('chalk');
/**
@ -84,11 +85,7 @@ export class FsTree implements Tree {
[path: string]: { content: Buffer | null; isDeleted: boolean };
} = {};
constructor(
readonly root: string,
private readonly isVerbose: boolean,
private readonly logger: Console
) {}
constructor(readonly root: string, private readonly isVerbose: boolean) {}
read(filePath: string): Buffer | null {
try {
@ -99,7 +96,7 @@ export class FsTree implements Tree {
}
} catch (e) {
if (this.isVerbose) {
this.logger.error(e);
logger.error(e);
}
return null;
}
@ -113,7 +110,7 @@ export class FsTree implements Tree {
};
} catch (e) {
if (this.isVerbose) {
this.logger.error(e);
logger.error(e);
}
}
}