feat(core): hash only relevant parts of global config files
This commit is contained in:
parent
76bc890f34
commit
b5efa6bfee
@ -787,19 +787,3 @@ describe('cache', () => {
|
|||||||
expect(matchingProjects).toEqual(expectedProjects);
|
expect(matchingProjects).toEqual(expectedProjects);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('workspace structure', () => {
|
|
||||||
beforeEach(() => newProject());
|
|
||||||
|
|
||||||
afterEach(() => removeProject({ onlyOnCI: true }));
|
|
||||||
|
|
||||||
it('should have a vscode/extensions.json file created', () => {
|
|
||||||
const extensions = readJson('.vscode/extensions.json');
|
|
||||||
expect(extensions).toEqual({
|
|
||||||
recommendations: [
|
|
||||||
'ms-vscode.vscode-typescript-tslint-plugin',
|
|
||||||
'esbenp.prettier-vscode',
|
|
||||||
],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nrwl/nx-source",
|
"name": "@nrwl/nx-source",
|
||||||
"version": "11.6.0",
|
"version": "12.0.0-beta.1",
|
||||||
"description": "Powerful, Extensible Dev Tools",
|
"description": "Powerful, Extensible Dev Tools",
|
||||||
"homepage": "https://nx.dev",
|
"homepage": "https://nx.dev",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import {
|
|||||||
} from '@nrwl/workspace/src/core/file-utils';
|
} from '@nrwl/workspace/src/core/file-utils';
|
||||||
import { TargetProjectLocator } from '@nrwl/workspace/src/core/target-project-locator';
|
import { TargetProjectLocator } from '@nrwl/workspace/src/core/target-project-locator';
|
||||||
import { checkCircularPath } from '@nrwl/workspace/src/utils/graph-utils';
|
import { checkCircularPath } from '@nrwl/workspace/src/utils/graph-utils';
|
||||||
|
import { readCurrentProjectGraph } from '@nrwl/workspace/src/core/project-graph/project-graph';
|
||||||
|
|
||||||
type Options = [
|
type Options = [
|
||||||
{
|
{
|
||||||
@ -106,10 +107,9 @@ export default createESLintRule<Options, MessageIds>({
|
|||||||
(global as any).projectPath || appRootPath
|
(global as any).projectPath || appRootPath
|
||||||
);
|
);
|
||||||
if (!(global as any).projectGraph) {
|
if (!(global as any).projectGraph) {
|
||||||
const workspaceJson = readWorkspaceJson();
|
|
||||||
const nxJson = readNxJson();
|
const nxJson = readNxJson();
|
||||||
(global as any).npmScope = nxJson.npmScope;
|
(global as any).npmScope = nxJson.npmScope;
|
||||||
(global as any).projectGraph = createProjectGraph(workspaceJson, nxJson);
|
(global as any).projectGraph = readCurrentProjectGraph();
|
||||||
}
|
}
|
||||||
const npmScope = (global as any).npmScope;
|
const npmScope = (global as any).npmScope;
|
||||||
const projectGraph = (global as any).projectGraph as ProjectGraph;
|
const projectGraph = (global as any).projectGraph as ProjectGraph;
|
||||||
@ -123,6 +123,8 @@ export default createESLintRule<Options, MessageIds>({
|
|||||||
.targetProjectLocator as TargetProjectLocator;
|
.targetProjectLocator as TargetProjectLocator;
|
||||||
|
|
||||||
function run(node: TSESTree.ImportDeclaration | TSESTree.ImportExpression) {
|
function run(node: TSESTree.ImportDeclaration | TSESTree.ImportExpression) {
|
||||||
|
if (!projectGraph) return;
|
||||||
|
|
||||||
// accept only literals because template literals have no value
|
// accept only literals because template literals have no value
|
||||||
if (node.source.type !== AST_NODE_TYPES.Literal) {
|
if (node.source.type !== AST_NODE_TYPES.Literal) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { dirname, extname } from 'path';
|
import { dirname, extname } from 'path';
|
||||||
import * as ts from 'typescript';
|
|
||||||
import defaultResolver from 'jest-resolve/build/defaultResolver';
|
import defaultResolver from 'jest-resolve/build/defaultResolver';
|
||||||
|
|
||||||
interface ResolveOptions {
|
interface ResolveOptions {
|
||||||
@ -12,6 +11,9 @@ interface ResolveOptions {
|
|||||||
defaultResolver: typeof defaultResolver;
|
defaultResolver: typeof defaultResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let compilerSetup;
|
||||||
|
let ts;
|
||||||
|
|
||||||
function getCompilerSetup(rootDir: string) {
|
function getCompilerSetup(rootDir: string) {
|
||||||
const tsConfigPath =
|
const tsConfigPath =
|
||||||
ts.findConfigFile(rootDir, ts.sys.fileExists, 'tsconfig.spec.json') ||
|
ts.findConfigFile(rootDir, ts.sys.fileExists, 'tsconfig.spec.json') ||
|
||||||
@ -35,8 +37,6 @@ function getCompilerSetup(rootDir: string) {
|
|||||||
return { compilerOptions, host };
|
return { compilerOptions, host };
|
||||||
}
|
}
|
||||||
|
|
||||||
let compilerSetup;
|
|
||||||
|
|
||||||
module.exports = function (path: string, options: ResolveOptions) {
|
module.exports = function (path: string, options: ResolveOptions) {
|
||||||
const ext = extname(path);
|
const ext = extname(path);
|
||||||
if (
|
if (
|
||||||
@ -52,7 +52,14 @@ module.exports = function (path: string, options: ResolveOptions) {
|
|||||||
try {
|
try {
|
||||||
return defaultResolver(path, options);
|
return defaultResolver(path, options);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (
|
||||||
|
path === 'jest-sequencer-@jest/test-sequencer' ||
|
||||||
|
path === '@jest/test-sequencer'
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Fallback to using typescript
|
// Fallback to using typescript
|
||||||
|
ts = ts || require('typescript');
|
||||||
compilerSetup = compilerSetup || getCompilerSetup(options.rootDir);
|
compilerSetup = compilerSetup || getCompilerSetup(options.rootDir);
|
||||||
const { compilerOptions, host } = compilerSetup;
|
const { compilerOptions, host } = compilerSetup;
|
||||||
return ts.resolveModuleName(path, options.basedir, compilerOptions, host)
|
return ts.resolveModuleName(path, options.basedir, compilerOptions, host)
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
# Nx CLI
|
# Nx CLI
|
||||||
|
|
||||||
|
This is an alias of the [@nrwl/cli](https://www.npmjs.com/package/@nrwl/cli) package. Please see [@nrwl/cli](https://www.npmjs.com/package/@nrwl/cli) for more information.
|
||||||
|
|
||||||
{{what-is-nx}}
|
{{what-is-nx}}
|
||||||
|
|
||||||
{{getting-started}}
|
{{getting-started}}
|
||||||
|
|||||||
@ -25,6 +25,17 @@ describe('Hasher', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it('should create project hash', async (done) => {
|
it('should create project hash', async (done) => {
|
||||||
|
fs.readFileSync = (file) => {
|
||||||
|
if (file === 'workspace.json') {
|
||||||
|
return JSON.stringify({
|
||||||
|
projects: { proj: 'proj-from-workspace.json' },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (file === 'nx.json') {
|
||||||
|
return JSON.stringify({ projects: { proj: 'proj-from-nx.json' } });
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
};
|
||||||
hashes['/file'] = 'file.hash';
|
hashes['/file'] = 'file.hash';
|
||||||
const hasher = new Hasher(
|
const hasher = new Hasher(
|
||||||
{
|
{
|
||||||
@ -69,16 +80,14 @@ describe('Hasher', () => {
|
|||||||
|
|
||||||
expect(hash.details.command).toEqual('proj|build||{"prop":"prop-value"}');
|
expect(hash.details.command).toEqual('proj|build||{"prop":"prop-value"}');
|
||||||
expect(hash.details.sources).toEqual({
|
expect(hash.details.sources).toEqual({
|
||||||
proj: '/file|file.hash',
|
proj: '/file|file.hash|"proj-from-workspace.json"|"proj-from-nx.json"',
|
||||||
});
|
});
|
||||||
expect(hash.details.implicitDeps).toEqual({
|
expect(hash.details.implicitDeps).toEqual({
|
||||||
'yarn.lock': 'yarn.lock.hash',
|
'yarn.lock': 'yarn.lock.hash',
|
||||||
'nx.json': 'nx.json.hash',
|
'nx.json': '{}',
|
||||||
'package-lock.json': 'package-lock.json.hash',
|
'package-lock.json': 'package-lock.json.hash',
|
||||||
'package.json': 'package.json.hash',
|
|
||||||
'pnpm-lock.yaml': 'pnpm-lock.yaml.hash',
|
'pnpm-lock.yaml': 'pnpm-lock.yaml.hash',
|
||||||
'tsconfig.base.json': 'tsconfig.base.json.hash',
|
'tsconfig.base.json': 'tsconfig.base.json.hash',
|
||||||
'workspace.json': 'workspace.json.hash',
|
|
||||||
});
|
});
|
||||||
expect(hash.details.runtime).toEqual({
|
expect(hash.details.runtime).toEqual({
|
||||||
'echo runtime123': 'runtime123',
|
'echo runtime123': 'runtime123',
|
||||||
@ -175,8 +184,8 @@ describe('Hasher', () => {
|
|||||||
|
|
||||||
// note that the parent hash is based on parent source files only!
|
// note that the parent hash is based on parent source files only!
|
||||||
expect(hash.details.sources).toEqual({
|
expect(hash.details.sources).toEqual({
|
||||||
parent: '/filea|a.hash',
|
parent: '/filea|a.hash|""|""',
|
||||||
child: '/fileb|b.hash',
|
child: '/fileb|b.hash|""|""',
|
||||||
});
|
});
|
||||||
|
|
||||||
done();
|
done();
|
||||||
@ -232,8 +241,8 @@ describe('Hasher', () => {
|
|||||||
expect(tasksHash.value).toContain('proj'); //project
|
expect(tasksHash.value).toContain('proj'); //project
|
||||||
expect(tasksHash.value).toContain('build'); //target
|
expect(tasksHash.value).toContain('build'); //target
|
||||||
expect(tasksHash.details.sources).toEqual({
|
expect(tasksHash.details.sources).toEqual({
|
||||||
proja: '/filea|a.hash',
|
proja: '/filea|a.hash|""|""',
|
||||||
projb: '/fileb|b.hash',
|
projb: '/fileb|b.hash|""|""',
|
||||||
});
|
});
|
||||||
|
|
||||||
const hashb = (
|
const hashb = (
|
||||||
@ -253,8 +262,8 @@ describe('Hasher', () => {
|
|||||||
expect(hashb.value).toContain('proj'); //project
|
expect(hashb.value).toContain('proj'); //project
|
||||||
expect(hashb.value).toContain('build'); //target
|
expect(hashb.value).toContain('build'); //target
|
||||||
expect(hashb.details.sources).toEqual({
|
expect(hashb.details.sources).toEqual({
|
||||||
proja: '/filea|a.hash',
|
proja: '/filea|a.hash|""|""',
|
||||||
projb: '/fileb|b.hash',
|
projb: '/fileb|b.hash|""|""',
|
||||||
});
|
});
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
|||||||
@ -2,18 +2,13 @@ import { ProjectGraph } from '../project-graph';
|
|||||||
import { NxJson } from '../shared-interfaces';
|
import { NxJson } from '../shared-interfaces';
|
||||||
import { Task } from '../../tasks-runner/tasks-runner';
|
import { Task } from '../../tasks-runner/tasks-runner';
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { rootWorkspaceFileNames } from '../file-utils';
|
import { workspaceFileName } from '../file-utils';
|
||||||
import { exec, execSync } from 'child_process';
|
import { exec } from 'child_process';
|
||||||
import {
|
import { defaultFileHasher, FileHasher } from './file-hasher';
|
||||||
defaultFileHasher,
|
|
||||||
extractNameAndVersion,
|
|
||||||
FileHasher,
|
|
||||||
} from './file-hasher';
|
|
||||||
import { defaultHashing, HashingImp } from './hashing-impl';
|
import { defaultHashing, HashingImp } from './hashing-impl';
|
||||||
import * as minimatch from 'minimatch';
|
import * as minimatch from 'minimatch';
|
||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
|
import * as stripJsonComments from 'strip-json-comments';
|
||||||
const resolve = require('resolve');
|
|
||||||
|
|
||||||
export interface Hash {
|
export interface Hash {
|
||||||
value: string;
|
value: string;
|
||||||
@ -47,7 +42,6 @@ interface NodeModulesResult {
|
|||||||
export class Hasher {
|
export class Hasher {
|
||||||
static version = '1.0';
|
static version = '1.0';
|
||||||
private implicitDependencies: Promise<ImplicitHashResult>;
|
private implicitDependencies: Promise<ImplicitHashResult>;
|
||||||
private nodeModules: Promise<NodeModulesResult>;
|
|
||||||
private runtimeInputs: Promise<RuntimeHashResult>;
|
private runtimeInputs: Promise<RuntimeHashResult>;
|
||||||
private fileHasher: FileHasher;
|
private fileHasher: FileHasher;
|
||||||
private projectHashes: ProjectHasher;
|
private projectHashes: ProjectHasher;
|
||||||
@ -93,7 +87,6 @@ export class Hasher {
|
|||||||
]),
|
]),
|
||||||
this.implicitDepsHash(),
|
this.implicitDepsHash(),
|
||||||
this.runtimeInputsHash(),
|
this.runtimeInputsHash(),
|
||||||
// this.nodeModulesHash(),
|
|
||||||
])) as [
|
])) as [
|
||||||
ProjectHashResult,
|
ProjectHashResult,
|
||||||
ImplicitHashResult,
|
ImplicitHashResult,
|
||||||
@ -192,18 +185,22 @@ export class Hasher {
|
|||||||
const fileNames = [
|
const fileNames = [
|
||||||
...filesWithoutPatterns,
|
...filesWithoutPatterns,
|
||||||
...implicitDepsFromPatterns,
|
...implicitDepsFromPatterns,
|
||||||
...rootWorkspaceFileNames(),
|
|
||||||
|
//TODO: vsavkin move the special cases into explicit ts support
|
||||||
|
'tsconfig.base.json',
|
||||||
'package-lock.json',
|
'package-lock.json',
|
||||||
'yarn.lock',
|
'yarn.lock',
|
||||||
'pnpm-lock.yaml',
|
'pnpm-lock.yaml',
|
||||||
];
|
];
|
||||||
|
|
||||||
this.implicitDependencies = Promise.resolve().then(async () => {
|
this.implicitDependencies = Promise.resolve().then(async () => {
|
||||||
const fileHashes = fileNames.map((file) => {
|
const fileHashes = [
|
||||||
const hash = this.fileHasher.hashFile(file);
|
...fileNames.map((file) => {
|
||||||
return { file, hash };
|
const hash = this.fileHasher.hashFile(file);
|
||||||
});
|
return { file, hash };
|
||||||
|
}),
|
||||||
|
...this.hashGlobalConfig(),
|
||||||
|
];
|
||||||
const combinedHash = this.hashing.hashArray(
|
const combinedHash = this.hashing.hashArray(
|
||||||
fileHashes.map((v) => v.hash)
|
fileHashes.map((v) => v.hash)
|
||||||
);
|
);
|
||||||
@ -214,6 +211,7 @@ export class Hasher {
|
|||||||
'hasher:implicit deps hash:start',
|
'hasher:implicit deps hash:start',
|
||||||
'hasher:implicit deps hash:end'
|
'hasher:implicit deps hash:end'
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
value: combinedHash,
|
value: combinedHash,
|
||||||
sources: fileHashes.reduce((m, c) => ((m[c.file] = c.hash), m), {}),
|
sources: fileHashes.reduce((m, c) => ((m[c.file] = c.hash), m), {}),
|
||||||
@ -222,43 +220,36 @@ export class Hasher {
|
|||||||
return this.implicitDependencies;
|
return this.implicitDependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async nodeModulesHash() {
|
private hashGlobalConfig() {
|
||||||
if (this.nodeModules) return this.nodeModules;
|
return [
|
||||||
|
{
|
||||||
this.nodeModules = Promise.resolve().then(async () => {
|
hash: this.fileHasher.hashFile('nx.json', (file) => {
|
||||||
try {
|
|
||||||
const j = JSON.parse(readFileSync('package.json').toString());
|
|
||||||
const allPackages = [
|
|
||||||
...Object.keys(j.dependencies),
|
|
||||||
...Object.keys(j.devDependencies),
|
|
||||||
];
|
|
||||||
const packageJsonHashes = allPackages.map((d) => {
|
|
||||||
try {
|
try {
|
||||||
const path = resolve.sync(`${d}/package.json`, {
|
const r = JSON.parse(stripJsonComments(file));
|
||||||
basedir: process.cwd(),
|
delete r.projects;
|
||||||
});
|
return JSON.stringify(r);
|
||||||
return this.fileHasher.hashFile(path, extractNameAndVersion);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
});
|
}),
|
||||||
return { value: this.hashing.hashArray(packageJsonHashes) };
|
file: 'nx.json',
|
||||||
} catch (e) {
|
},
|
||||||
return { value: '' };
|
];
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.nodeModules;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProjectHasher {
|
class ProjectHasher {
|
||||||
private sourceHashes: { [projectName: string]: Promise<string> } = {};
|
private sourceHashes: { [projectName: string]: Promise<string> } = {};
|
||||||
|
private workspaceJson: any;
|
||||||
|
private nxJson: any;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly projectGraph: ProjectGraph,
|
private readonly projectGraph: ProjectGraph,
|
||||||
private readonly hashing: HashingImp
|
private readonly hashing: HashingImp
|
||||||
) {}
|
) {
|
||||||
|
this.workspaceJson = this.readConfigFile(workspaceFileName());
|
||||||
|
this.nxJson = this.readConfigFile('nx.json');
|
||||||
|
}
|
||||||
|
|
||||||
async hashProject(
|
async hashProject(
|
||||||
projectName: string,
|
projectName: string,
|
||||||
@ -299,9 +290,32 @@ class ProjectHasher {
|
|||||||
const p = this.projectGraph.nodes[projectName];
|
const p = this.projectGraph.nodes[projectName];
|
||||||
const fileNames = p.data.files.map((f) => f.file);
|
const fileNames = p.data.files.map((f) => f.file);
|
||||||
const values = p.data.files.map((f) => f.hash);
|
const values = p.data.files.map((f) => f.hash);
|
||||||
res(this.hashing.hashArray([...fileNames, ...values]));
|
|
||||||
|
const workspaceJson = JSON.stringify(
|
||||||
|
this.workspaceJson.projects[projectName] || ''
|
||||||
|
);
|
||||||
|
const nxJson = JSON.stringify(this.nxJson.projects[projectName] || '');
|
||||||
|
|
||||||
|
res(
|
||||||
|
this.hashing.hashArray([
|
||||||
|
...fileNames,
|
||||||
|
...values,
|
||||||
|
workspaceJson,
|
||||||
|
nxJson,
|
||||||
|
])
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return this.sourceHashes[projectName];
|
return this.sourceHashes[projectName];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readConfigFile(name: string) {
|
||||||
|
try {
|
||||||
|
const res = JSON.parse(stripJsonComments(readFileSync(name).toString()));
|
||||||
|
if (!res.projects) res.projects = {};
|
||||||
|
return res;
|
||||||
|
} catch (e) {
|
||||||
|
return { projects: {} };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,6 +80,11 @@ export function createProjectGraph(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function readCurrentProjectGraph(): ProjectGraph | null {
|
||||||
|
const cache = readCache();
|
||||||
|
return cache === false ? null : cache;
|
||||||
|
}
|
||||||
|
|
||||||
function addWorkspaceFiles(
|
function addWorkspaceFiles(
|
||||||
projectGraph: ProjectGraph,
|
projectGraph: ProjectGraph,
|
||||||
allWorkspaceFiles: FileData[]
|
allWorkspaceFiles: FileData[]
|
||||||
|
|||||||
@ -3,6 +3,9 @@ import { relative } from 'path';
|
|||||||
import { dirSync, fileSync } from 'tmp';
|
import { dirSync, fileSync } from 'tmp';
|
||||||
import runCommands, { LARGE_BUFFER } from './run-commands.impl';
|
import runCommands, { LARGE_BUFFER } from './run-commands.impl';
|
||||||
|
|
||||||
|
function normalize(p: string) {
|
||||||
|
return p.startsWith('/private') ? p.substring(8) : p;
|
||||||
|
}
|
||||||
function readFile(f: string) {
|
function readFile(f: string) {
|
||||||
return readFileSync(f).toString().replace(/\s/g, '');
|
return readFileSync(f).toString().replace(/\s/g, '');
|
||||||
}
|
}
|
||||||
@ -59,7 +62,7 @@ describe('Command Runner Builder', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('ssss should forward args by default when using commands (plural)', async () => {
|
it('should forward args by default when using commands (plural)', async () => {
|
||||||
const exec = spyOn(require('child_process'), 'exec').and.callThrough();
|
const exec = spyOn(require('child_process'), 'exec').and.callThrough();
|
||||||
|
|
||||||
await runCommands(
|
await runCommands(
|
||||||
@ -285,7 +288,7 @@ describe('Command Runner Builder', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(result).toEqual(jasmine.objectContaining({ success: true }));
|
expect(result).toEqual(jasmine.objectContaining({ success: true }));
|
||||||
expect(readFile(f)).toBe(root);
|
expect(normalize(readFile(f))).toBe(root);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should run the task in the specified cwd relative to the workspace root when cwd is not an absolute path', async () => {
|
it('should run the task in the specified cwd relative to the workspace root when cwd is not an absolute path', async () => {
|
||||||
@ -308,7 +311,7 @@ describe('Command Runner Builder', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(result).toEqual(jasmine.objectContaining({ success: true }));
|
expect(result).toEqual(jasmine.objectContaining({ success: true }));
|
||||||
expect(readFile(f)).toBe(childFolder);
|
expect(normalize(readFile(f))).toBe(childFolder);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should run the task in the specified absolute cwd', async () => {
|
it('should run the task in the specified absolute cwd', async () => {
|
||||||
@ -330,7 +333,7 @@ describe('Command Runner Builder', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(result).toEqual(jasmine.objectContaining({ success: true }));
|
expect(result).toEqual(jasmine.objectContaining({ success: true }));
|
||||||
expect(readFile(f)).toBe(childFolder);
|
expect(normalize(readFile(f))).toBe(childFolder);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -148,7 +148,6 @@ Object {
|
|||||||
"dependencies": "*",
|
"dependencies": "*",
|
||||||
"devDependencies": "*",
|
"devDependencies": "*",
|
||||||
},
|
},
|
||||||
"tslint.json": "*",
|
|
||||||
},
|
},
|
||||||
"npmScope": "npmScope",
|
"npmScope": "npmScope",
|
||||||
"projects": Object {},
|
"projects": Object {},
|
||||||
|
|||||||
@ -5,3 +5,18 @@ exports[`@nrwl/workspace:workspace should create a prettierrc file 1`] = `
|
|||||||
\\"singleQuote\\": true
|
\\"singleQuote\\": true
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`@nrwl/workspace:workspace should recommend vscode extensions (angular) 1`] = `
|
||||||
|
Array [
|
||||||
|
"angular.ng-template",
|
||||||
|
"nrwl.angular-console",
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`@nrwl/workspace:workspace should recommend vscode extensions 1`] = `
|
||||||
|
Array [
|
||||||
|
"nrwl.angular-console",
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
<% if(cli === 'angular') { %>
|
<% if(cli === 'angular') { %>
|
||||||
"nrwl.angular-console",
|
|
||||||
"angular.ng-template",<% }
|
"angular.ng-template",<% }
|
||||||
%>
|
%>
|
||||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
"nrwl.angular-console",
|
||||||
"esbenp.prettier-vscode"
|
"esbenp.prettier-vscode"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
"dependencies": "*",
|
"dependencies": "*",
|
||||||
"devDependencies": "*"
|
"devDependencies": "*"
|
||||||
},
|
},
|
||||||
"tslint.json": "*",
|
|
||||||
".eslintrc.json": "*"
|
".eslintrc.json": "*"
|
||||||
},
|
},
|
||||||
"tasksRunnerOptions": {
|
"tasksRunnerOptions": {
|
||||||
|
|||||||
@ -43,7 +43,6 @@ describe('@nrwl/workspace:workspace', () => {
|
|||||||
dependencies: '*',
|
dependencies: '*',
|
||||||
devDependencies: '*',
|
devDependencies: '*',
|
||||||
},
|
},
|
||||||
'tslint.json': '*',
|
|
||||||
'.eslintrc.json': '*',
|
'.eslintrc.json': '*',
|
||||||
},
|
},
|
||||||
tasksRunnerOptions: {
|
tasksRunnerOptions: {
|
||||||
@ -82,10 +81,7 @@ describe('@nrwl/workspace:workspace', () => {
|
|||||||
'proj/.vscode/extensions.json'
|
'proj/.vscode/extensions.json'
|
||||||
).recommendations;
|
).recommendations;
|
||||||
|
|
||||||
expect(recommendations).toEqual([
|
expect(recommendations).toMatchSnapshot();
|
||||||
'ms-vscode.vscode-typescript-tslint-plugin',
|
|
||||||
'esbenp.prettier-vscode',
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should recommend vscode extensions (angular)', async () => {
|
it('should recommend vscode extensions (angular)', async () => {
|
||||||
@ -101,12 +97,7 @@ describe('@nrwl/workspace:workspace', () => {
|
|||||||
'proj/.vscode/extensions.json'
|
'proj/.vscode/extensions.json'
|
||||||
).recommendations;
|
).recommendations;
|
||||||
|
|
||||||
expect(recommendations).toEqual([
|
expect(recommendations).toMatchSnapshot();
|
||||||
'nrwl.angular-console',
|
|
||||||
'angular.ng-template',
|
|
||||||
'ms-vscode.vscode-typescript-tslint-plugin',
|
|
||||||
'esbenp.prettier-vscode',
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add decorate-angular-cli when used with angular cli', async () => {
|
it('should add decorate-angular-cli when used with angular cli', async () => {
|
||||||
|
|||||||
@ -22,12 +22,10 @@ import {
|
|||||||
onlyLoadChildren,
|
onlyLoadChildren,
|
||||||
} from '../utils/runtime-lint-utils';
|
} from '../utils/runtime-lint-utils';
|
||||||
import { normalize } from 'path';
|
import { normalize } from 'path';
|
||||||
import {
|
import { readNxJson } from '@nrwl/workspace/src/core/file-utils';
|
||||||
readNxJson,
|
|
||||||
readWorkspaceJson,
|
|
||||||
} from '@nrwl/workspace/src/core/file-utils';
|
|
||||||
import { TargetProjectLocator } from '../core/target-project-locator';
|
import { TargetProjectLocator } from '../core/target-project-locator';
|
||||||
import { checkCircularPath } from '@nrwl/workspace/src/utils/graph-utils';
|
import { checkCircularPath } from '@nrwl/workspace/src/utils/graph-utils';
|
||||||
|
import { readCurrentProjectGraph } from '@nrwl/workspace/src/core/project-graph/project-graph';
|
||||||
|
|
||||||
export class Rule extends Lint.Rules.AbstractRule {
|
export class Rule extends Lint.Rules.AbstractRule {
|
||||||
constructor(
|
constructor(
|
||||||
@ -42,13 +40,9 @@ export class Rule extends Lint.Rules.AbstractRule {
|
|||||||
if (!projectPath) {
|
if (!projectPath) {
|
||||||
this.projectPath = normalize(appRootPath);
|
this.projectPath = normalize(appRootPath);
|
||||||
if (!(global as any).projectGraph) {
|
if (!(global as any).projectGraph) {
|
||||||
const workspaceJson = readWorkspaceJson();
|
|
||||||
const nxJson = readNxJson();
|
const nxJson = readNxJson();
|
||||||
(global as any).npmScope = nxJson.npmScope;
|
(global as any).npmScope = nxJson.npmScope;
|
||||||
(global as any).projectGraph = createProjectGraph(
|
(global as any).projectGraph = readCurrentProjectGraph();
|
||||||
workspaceJson,
|
|
||||||
nxJson
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
this.npmScope = (global as any).npmScope;
|
this.npmScope = (global as any).npmScope;
|
||||||
this.projectGraph = (global as any).projectGraph;
|
this.projectGraph = (global as any).projectGraph;
|
||||||
@ -63,6 +57,7 @@ export class Rule extends Lint.Rules.AbstractRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||||
|
if (!this.projectGraph) return [];
|
||||||
return this.applyWithWalker(
|
return this.applyWithWalker(
|
||||||
new EnforceModuleBoundariesWalker(
|
new EnforceModuleBoundariesWalker(
|
||||||
sourceFile,
|
sourceFile,
|
||||||
|
|||||||
@ -38,6 +38,7 @@ if (
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function (path, options) {
|
module.exports = function (path, options) {
|
||||||
|
if (path === 'jest-sequencer-@jest/test-sequencer') return;
|
||||||
const ext = path_1.extname(path);
|
const ext = path_1.extname(path);
|
||||||
if (
|
if (
|
||||||
ext === '.css' ||
|
ext === '.css' ||
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user