Compare commits
26 Commits
patch-error
...
12.0.7
| Author | SHA1 | Date | |
|---|---|---|---|
| c439504326 | |||
| 5cf27c611e | |||
| 7017669e52 | |||
| 51e99541cf | |||
| b15dd237fc | |||
| 704c3b7b43 | |||
| 6a17abb7b0 | |||
| b0151f8b50 | |||
| d9d7db8311 | |||
| 342b42b78f | |||
| f4c59dc96f | |||
| 1025d8a341 | |||
| f8adb9ca04 | |||
| 167c65a4a8 | |||
| ba0a94a84d | |||
| d03423df9a | |||
| b232f8a2c8 | |||
| df8060204a | |||
| 73ba102207 | |||
| b9d4cbb474 | |||
| 9bea63171c | |||
| 25143296b4 | |||
| 15fcbbae2b | |||
| a1fe84b66c | |||
| ebf969390e | |||
| b4dbb6b1c9 |
@@ -13,7 +13,7 @@ import {
|
||||
describe('dep-graph-client', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/');
|
||||
cy.get('[data-cy=project-select]').select('Medium');
|
||||
cy.get('[data-cy=project-select]').select('Ocean');
|
||||
});
|
||||
|
||||
it('should display message to select projects', () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BehaviorSubject, combineLatest, fromEvent, Subject } from 'rxjs';
|
||||
import { startWith, takeUntil } from 'rxjs/operators';
|
||||
import { startWith, takeUntil, throwIfEmpty } from 'rxjs/operators';
|
||||
import { projectGraphs } from '../graphs';
|
||||
import { DebuggerPanel } from './debugger-panel';
|
||||
import { GraphComponent } from './graph';
|
||||
@@ -28,9 +28,9 @@ export class AppComponent {
|
||||
}
|
||||
|
||||
private onProjectGraphChange(projectGraphId: string) {
|
||||
const projectGraph = projectGraphs.find(
|
||||
(graph) => graph.id === projectGraphId
|
||||
)?.graph;
|
||||
const project = projectGraphs.find((graph) => graph.id === projectGraphId);
|
||||
const projectGraph = project?.graph;
|
||||
const workspaceLayout = project?.workspaceLayout;
|
||||
|
||||
const nodes = Object.values(projectGraph.nodes).filter(
|
||||
(node) => node.type !== 'npm'
|
||||
@@ -43,6 +43,7 @@ export class AppComponent {
|
||||
window.focusedProject = null;
|
||||
window.projectGraphList = projectGraphs;
|
||||
window.selectedProjectGraph = projectGraphId;
|
||||
window.workspaceLayout = workspaceLayout;
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Subject } from 'rxjs';
|
||||
import { ProjectGraphList } from '../graphs';
|
||||
import { GraphPerfReport } from './graph';
|
||||
import { ProjectGraphList } from './models';
|
||||
import { removeChildrenFromContainer } from './util';
|
||||
|
||||
export class DebuggerPanel {
|
||||
|
||||
@@ -101,7 +101,12 @@ export class GraphComponent {
|
||||
> = {};
|
||||
|
||||
selectedProjects.forEach((project) => {
|
||||
const projectNode = new ProjectNode(project);
|
||||
const workspaceRoot =
|
||||
project.type === 'app' || project.type === 'e2e'
|
||||
? window.workspaceLayout.appsDir
|
||||
: window.workspaceLayout.libsDir;
|
||||
|
||||
const projectNode = new ProjectNode(project, workspaceRoot);
|
||||
projectNode.focused = project.name === window.focusedProject;
|
||||
projectNode.affected = this.affectedProjects.includes(project.name);
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { ProjectGraphCache } from '@nrwl/workspace';
|
||||
|
||||
export interface ProjectGraphList {
|
||||
id: string;
|
||||
label: string;
|
||||
graph: ProjectGraphCache;
|
||||
workspaceLayout: WorkspaceLayout;
|
||||
}
|
||||
|
||||
export interface WorkspaceLayout {
|
||||
libsDir: string;
|
||||
appsDir: string;
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
import { ProjectGraphNode } from '@nrwl/workspace';
|
||||
import { Subject } from 'rxjs';
|
||||
import { removeChildrenFromContainer } from '../util';
|
||||
import {
|
||||
parseParentDirectoriesFromPilePath,
|
||||
removeChildrenFromContainer,
|
||||
} from '../util';
|
||||
|
||||
export class ProjectList {
|
||||
private focusProjectSubject = new Subject<string>();
|
||||
@@ -54,25 +57,35 @@ export class ProjectList {
|
||||
const libProjects = this.getProjectsByType('lib');
|
||||
const e2eProjects = this.getProjectsByType('e2e');
|
||||
|
||||
const appDirectoryGroups = this.groupProjectsByDirectory(appProjects);
|
||||
const libDirectoryGroups = this.groupProjectsByDirectory(libProjects);
|
||||
const e2eDirectoryGroups = this.groupProjectsByDirectory(e2eProjects);
|
||||
|
||||
const sortedAppDirectories = Object.keys(appDirectoryGroups).sort();
|
||||
const sortedLibDirectories = Object.keys(libDirectoryGroups).sort();
|
||||
const sortedE2EDirectories = Object.keys(e2eDirectoryGroups).sort();
|
||||
|
||||
const appsHeader = document.createElement('h4');
|
||||
appsHeader.textContent = 'app projects';
|
||||
this.container.append(appsHeader);
|
||||
this.createProjectList('apps', appProjects);
|
||||
|
||||
sortedAppDirectories.forEach((directoryName) => {
|
||||
this.createProjectList(directoryName, appDirectoryGroups[directoryName]);
|
||||
});
|
||||
|
||||
const e2eHeader = document.createElement('h4');
|
||||
e2eHeader.textContent = 'e2e projects';
|
||||
this.container.append(e2eHeader);
|
||||
this.createProjectList('e2e', e2eProjects);
|
||||
|
||||
sortedE2EDirectories.forEach((directoryName) => {
|
||||
this.createProjectList(directoryName, e2eDirectoryGroups[directoryName]);
|
||||
});
|
||||
|
||||
const libHeader = document.createElement('h4');
|
||||
libHeader.textContent = 'lib projects';
|
||||
this.container.append(libHeader);
|
||||
|
||||
const sortedDirectories = Object.keys(libDirectoryGroups).sort();
|
||||
|
||||
sortedDirectories.forEach((directoryName) => {
|
||||
sortedLibDirectories.forEach((directoryName) => {
|
||||
this.createProjectList(directoryName, libDirectoryGroups[directoryName]);
|
||||
});
|
||||
}
|
||||
@@ -83,12 +96,19 @@ export class ProjectList {
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
|
||||
private groupProjectsByDirectory(projects) {
|
||||
private groupProjectsByDirectory(projects: ProjectGraphNode[]) {
|
||||
let groups = {};
|
||||
|
||||
projects.forEach((project) => {
|
||||
const split = project.data.root.split('/');
|
||||
const directory = split.slice(1, -1).join('/');
|
||||
const workspaceRoot =
|
||||
project.type === 'app' || project.type === 'e2e'
|
||||
? window.workspaceLayout.appsDir
|
||||
: window.workspaceLayout.libsDir;
|
||||
const directories = parseParentDirectoriesFromPilePath(
|
||||
project.data.root,
|
||||
workspaceRoot
|
||||
);
|
||||
const directory = directories.join('/');
|
||||
|
||||
if (!groups.hasOwnProperty(directory)) {
|
||||
groups[directory] = [];
|
||||
|
||||
@@ -3,18 +3,21 @@ import { ProjectNode } from './project-node';
|
||||
describe('ProjectNode', () => {
|
||||
describe('app nodes', () => {
|
||||
it('should not set parentId if groupByFolder is false', () => {
|
||||
const projectNode = new ProjectNode({
|
||||
name: 'sub-app',
|
||||
type: 'app',
|
||||
data: {
|
||||
projectType: 'application',
|
||||
root: 'apps/sub/app',
|
||||
sourceRoot: 'apps/sub/app/src',
|
||||
prefix: 'sub-app',
|
||||
tags: [],
|
||||
files: [],
|
||||
const projectNode = new ProjectNode(
|
||||
{
|
||||
name: 'sub-app',
|
||||
type: 'app',
|
||||
data: {
|
||||
projectType: 'application',
|
||||
root: 'apps/sub/app',
|
||||
sourceRoot: 'apps/sub/app/src',
|
||||
prefix: 'sub-app',
|
||||
tags: [],
|
||||
files: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
'apps'
|
||||
);
|
||||
|
||||
const result = projectNode.getCytoscapeNodeDef(false);
|
||||
|
||||
@@ -22,18 +25,21 @@ describe('ProjectNode', () => {
|
||||
});
|
||||
|
||||
it('should not set parentId if app is not nested', () => {
|
||||
const projectNode = new ProjectNode({
|
||||
name: 'app',
|
||||
type: 'app',
|
||||
data: {
|
||||
projectType: 'application',
|
||||
root: 'apps/app',
|
||||
sourceRoot: 'apps/app/src',
|
||||
prefix: 'app',
|
||||
tags: [],
|
||||
files: [],
|
||||
const projectNode = new ProjectNode(
|
||||
{
|
||||
name: 'app',
|
||||
type: 'app',
|
||||
data: {
|
||||
projectType: 'application',
|
||||
root: 'apps/app',
|
||||
sourceRoot: 'apps/app/src',
|
||||
prefix: 'app',
|
||||
tags: [],
|
||||
files: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
'apps'
|
||||
);
|
||||
|
||||
const result = projectNode.getCytoscapeNodeDef(false);
|
||||
|
||||
@@ -41,18 +47,21 @@ describe('ProjectNode', () => {
|
||||
});
|
||||
|
||||
it('should set parentId if the app is nested and groupByFolder is true', () => {
|
||||
const projectNode = new ProjectNode({
|
||||
name: 'sub-app',
|
||||
type: 'app',
|
||||
data: {
|
||||
projectType: 'application',
|
||||
root: 'apps/sub/app',
|
||||
sourceRoot: 'apps/sub/app/src',
|
||||
prefix: 'sub-app',
|
||||
tags: [],
|
||||
files: [],
|
||||
const projectNode = new ProjectNode(
|
||||
{
|
||||
name: 'sub-app',
|
||||
type: 'app',
|
||||
data: {
|
||||
projectType: 'application',
|
||||
root: 'apps/sub/app',
|
||||
sourceRoot: 'apps/sub/app/src',
|
||||
prefix: 'sub-app',
|
||||
tags: [],
|
||||
files: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
'apps'
|
||||
);
|
||||
|
||||
const result = projectNode.getCytoscapeNodeDef(true);
|
||||
|
||||
@@ -62,16 +71,19 @@ describe('ProjectNode', () => {
|
||||
|
||||
describe('lib nodes', () => {
|
||||
it('should not set parentId if groupByFolder is false', () => {
|
||||
const projectNode = new ProjectNode({
|
||||
name: 'sub-lib',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'libs/sub/lib',
|
||||
sourceRoot: 'libs/sub/lib/src',
|
||||
projectType: 'library',
|
||||
files: [],
|
||||
const projectNode = new ProjectNode(
|
||||
{
|
||||
name: 'sub-lib',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'libs/sub/lib',
|
||||
sourceRoot: 'libs/sub/lib/src',
|
||||
projectType: 'library',
|
||||
files: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
'libs'
|
||||
);
|
||||
|
||||
const result = projectNode.getCytoscapeNodeDef(false);
|
||||
|
||||
@@ -79,16 +91,19 @@ describe('ProjectNode', () => {
|
||||
});
|
||||
|
||||
it('should not set parentId if lib is not nested', () => {
|
||||
const projectNode = new ProjectNode({
|
||||
name: 'lib',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'libs/lib',
|
||||
sourceRoot: 'libs/lib/src',
|
||||
projectType: 'library',
|
||||
files: [],
|
||||
const projectNode = new ProjectNode(
|
||||
{
|
||||
name: 'lib',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'libs/lib',
|
||||
sourceRoot: 'libs/lib/src',
|
||||
projectType: 'library',
|
||||
files: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
'libs'
|
||||
);
|
||||
|
||||
const result = projectNode.getCytoscapeNodeDef(false);
|
||||
|
||||
@@ -96,16 +111,19 @@ describe('ProjectNode', () => {
|
||||
});
|
||||
|
||||
it('should set parentId if the lib is nested and groupByFolder is true', () => {
|
||||
const projectNode = new ProjectNode({
|
||||
name: 'sub-lib',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'libs/sub/lib',
|
||||
sourceRoot: 'libs/sub/lib/src',
|
||||
projectType: 'library',
|
||||
files: [],
|
||||
const projectNode = new ProjectNode(
|
||||
{
|
||||
name: 'sub-lib',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'libs/sub/lib',
|
||||
sourceRoot: 'libs/sub/lib/src',
|
||||
projectType: 'library',
|
||||
files: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
'libs'
|
||||
);
|
||||
|
||||
const result = projectNode.getCytoscapeNodeDef(true);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ProjectGraphNode } from '@nrwl/workspace';
|
||||
import * as cy from 'cytoscape';
|
||||
import { parseParentDirectoriesFromPilePath } from '../util';
|
||||
|
||||
interface NodeDataDefinition extends cy.NodeDataDefinition {
|
||||
id: string;
|
||||
@@ -7,11 +8,19 @@ interface NodeDataDefinition extends cy.NodeDataDefinition {
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
interface Ancestor {
|
||||
id: string;
|
||||
parentId: string;
|
||||
label: string;
|
||||
}
|
||||
export class ProjectNode {
|
||||
affected = false;
|
||||
focused = false;
|
||||
|
||||
constructor(private project: ProjectGraphNode) {}
|
||||
constructor(
|
||||
private project: ProjectGraphNode,
|
||||
private workspaceRoot: string
|
||||
) {}
|
||||
|
||||
getCytoscapeNodeDef(groupByFolder: boolean): cy.NodeDefinition {
|
||||
return {
|
||||
@@ -30,8 +39,8 @@ export class ProjectNode {
|
||||
type: this.project.type,
|
||||
tags: this.project.data.tags,
|
||||
parent:
|
||||
groupByFolder && this.project.data.hasOwnProperty('sourceRoot')
|
||||
? this.getParentId(this.project.data.sourceRoot)
|
||||
groupByFolder && this.project.data.hasOwnProperty('root')
|
||||
? this.getParentId()
|
||||
: null,
|
||||
};
|
||||
}
|
||||
@@ -50,62 +59,39 @@ export class ProjectNode {
|
||||
return classes;
|
||||
}
|
||||
|
||||
private getParentId(sourceRoot: string): string | null {
|
||||
const split = sourceRoot.split('/');
|
||||
let directories = split.slice(1, -2);
|
||||
private getParentId(): string | null {
|
||||
const ancestors = this.getAncestors();
|
||||
|
||||
if (directories.length > 0) {
|
||||
let directory = directories.join('/');
|
||||
return `dir-${directory}`;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private getGrandParentId(sourceRoot: string): string | null {
|
||||
const split = sourceRoot.split('/');
|
||||
let directories = split.slice(1, -3);
|
||||
|
||||
if (directories.length > 0) {
|
||||
let directory = directories.join('/');
|
||||
return `dir-${directory}`;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public getAncestors(): { id: string; parentId: string; label: string }[] {
|
||||
if (!this.project.data.sourceRoot) {
|
||||
return [];
|
||||
}
|
||||
const split = this.project.data.sourceRoot.split('/');
|
||||
let directories = split.slice(1, -2);
|
||||
|
||||
if (directories.length > 0) {
|
||||
const ancestors: { id: string; parentId: string; label: string }[] = [
|
||||
{
|
||||
label: directories.join('/'),
|
||||
id: this.getParentId(this.project.data.sourceRoot),
|
||||
parentId: this.getGrandParentId(this.project.data.sourceRoot),
|
||||
},
|
||||
];
|
||||
|
||||
while (directories.length > 1) {
|
||||
const sourceRoot = directories.join('/');
|
||||
const parentData = {
|
||||
id: this.getParentId(sourceRoot),
|
||||
parentId: this.getGrandParentId(this.project.data.sourceRoot),
|
||||
label: sourceRoot,
|
||||
};
|
||||
ancestors.push(parentData);
|
||||
|
||||
const split = sourceRoot.split('/');
|
||||
directories = split.slice(0, -1);
|
||||
}
|
||||
|
||||
return ancestors;
|
||||
if (ancestors.length > 0) {
|
||||
return ancestors[ancestors.length - 1].id;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public getAncestors(): Ancestor[] {
|
||||
// if there's no root, we can't figure out the parent
|
||||
if (!this.project.data.root) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const directories = parseParentDirectoriesFromPilePath(
|
||||
this.project.data.root,
|
||||
this.workspaceRoot
|
||||
);
|
||||
|
||||
return directories.map((directory, index, allDirectories) => {
|
||||
const label = [...allDirectories].slice(0, index + 1).join('/');
|
||||
const id = `dir-${label}`;
|
||||
const parentId =
|
||||
index > 0
|
||||
? `dir-${[...allDirectories].slice(0, index).join('/')}`
|
||||
: null;
|
||||
return {
|
||||
label,
|
||||
id,
|
||||
parentId,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { parseParentDirectoriesFromPilePath } from './util';
|
||||
|
||||
describe('parseParentDirectoriesFromPilePath', () => {
|
||||
// path, workspaceRoot, output
|
||||
const cases: [string, string, string[]][] = [
|
||||
['apps/app1', 'apps', []],
|
||||
['apps/app1', '', ['apps']],
|
||||
['apps/nested/app1', 'apps', ['nested']],
|
||||
['libs/scope/some-lib', 'libs', ['scope']],
|
||||
[
|
||||
'libs/very/very/very/deeply/nested/lib',
|
||||
'libs',
|
||||
['very', 'very', 'very', 'deeply', 'nested'],
|
||||
],
|
||||
['packages/published', 'packages', []],
|
||||
['packages/published', '', ['packages']],
|
||||
['packages/published', 'libs', ['packages']],
|
||||
['libs/trailing/slash/', 'libs', ['trailing']],
|
||||
['libs/trailing/slash', 'libs/', ['trailing']],
|
||||
];
|
||||
|
||||
test.each(cases)(
|
||||
'given filepath %p and workspaceRoot %p, parent directories are %p',
|
||||
(path, workspaceRoot, expected) => {
|
||||
const result = parseParentDirectoriesFromPilePath(path, workspaceRoot);
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -3,3 +3,27 @@ export function removeChildrenFromContainer(container: HTMLElement) {
|
||||
container.removeChild(child)
|
||||
);
|
||||
}
|
||||
|
||||
export function trimBackSlash(value: string): string {
|
||||
return value.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
export function parseParentDirectoriesFromPilePath(
|
||||
path: string,
|
||||
workspaceRoot: string
|
||||
) {
|
||||
const root = trimBackSlash(path);
|
||||
|
||||
// split the source root on directory separator
|
||||
const split: string[] = root.split('/');
|
||||
|
||||
// check the first part for libs or apps, depending on workspaceLayout
|
||||
if (split[0] === trimBackSlash(workspaceRoot)) {
|
||||
split.shift();
|
||||
}
|
||||
|
||||
// pop off the last element, which should be the lib name
|
||||
split.pop();
|
||||
|
||||
return split;
|
||||
}
|
||||
|
||||
Vendored
+5
@@ -1,3 +1,4 @@
|
||||
import { WorkspaceConfiguration } from '@nrwl/devkit';
|
||||
import { ProjectGraph, ProjectGraphNode } from '@nrwl/workspace';
|
||||
import { ProjectGraphList } from './graphs';
|
||||
|
||||
@@ -14,6 +15,10 @@ export declare global {
|
||||
excludeProject: Function;
|
||||
projectGraphList: ProjectGraphList[];
|
||||
selectedProjectGraph: string;
|
||||
workspaceLayout: {
|
||||
libsDir: string;
|
||||
appsDir: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,39 @@
|
||||
import { ProjectGraphCache } from '@nrwl/workspace';
|
||||
import { mediumGraph } from './medium';
|
||||
import { smallGraph } from './small';
|
||||
import { subAppsGraph } from './sub-apps';
|
||||
|
||||
export interface ProjectGraphList {
|
||||
id: string;
|
||||
label: string;
|
||||
graph: ProjectGraphCache;
|
||||
}
|
||||
import { ProjectGraphList } from '../app/models';
|
||||
import { oceanGraph, oceanWorkspaceLayout } from './ocean';
|
||||
import { nxGraph, nxWorkspaceLayout } from './nx';
|
||||
import { storybookGraph, storybookWorkspaceLayout } from './storybook';
|
||||
import { subAppsGraph, subAppsWorkspaceLayout } from './sub-apps';
|
||||
import { nxExamplesGraph, nxExamplesWorkspaceLayout } from './nx-examples';
|
||||
|
||||
export const projectGraphs: ProjectGraphList[] = [
|
||||
{
|
||||
id: 'small',
|
||||
label: 'Small',
|
||||
graph: smallGraph,
|
||||
id: 'nx',
|
||||
label: 'Nx',
|
||||
graph: nxGraph,
|
||||
workspaceLayout: nxWorkspaceLayout,
|
||||
},
|
||||
{
|
||||
id: 'medium',
|
||||
label: 'Medium',
|
||||
graph: mediumGraph,
|
||||
id: 'ocean',
|
||||
label: 'Ocean',
|
||||
graph: oceanGraph,
|
||||
workspaceLayout: oceanWorkspaceLayout,
|
||||
},
|
||||
{
|
||||
id: 'nx-examples',
|
||||
label: 'Nx Examples',
|
||||
graph: nxExamplesGraph,
|
||||
workspaceLayout: nxExamplesWorkspaceLayout,
|
||||
},
|
||||
{
|
||||
id: 'sub-apps',
|
||||
label: 'Sub Apps',
|
||||
graph: subAppsGraph,
|
||||
workspaceLayout: subAppsWorkspaceLayout,
|
||||
},
|
||||
{
|
||||
id: 'storybook',
|
||||
label: 'Storybook',
|
||||
graph: storybookGraph,
|
||||
workspaceLayout: storybookWorkspaceLayout,
|
||||
},
|
||||
];
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+6156
-4925
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,10 @@
|
||||
import { ProjectGraphCache } from '@nrwl/workspace';
|
||||
import { WorkspaceLayout } from '../app/models';
|
||||
|
||||
export const subAppsWorkspaceLayout: WorkspaceLayout = {
|
||||
appsDir: 'apps',
|
||||
libsDir: 'libs',
|
||||
};
|
||||
|
||||
export const subAppsGraph: ProjectGraphCache = {
|
||||
version: '2.0',
|
||||
|
||||
@@ -60,5 +60,6 @@
|
||||
window.filteredProjects = [];
|
||||
window.groupByFolder = false;
|
||||
window.exclude = [];
|
||||
window.workspaceLayout = null;
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { AppComponent } from './app/app';
|
||||
import { environment } from './environments/environment';
|
||||
import { projectGraphs } from './graphs';
|
||||
import { smallGraph } from './graphs/small';
|
||||
import { nxGraph } from './graphs/nx';
|
||||
|
||||
if (!environment.release) {
|
||||
const currentGraph = smallGraph;
|
||||
const currentGraph = nxGraph;
|
||||
|
||||
const nodes = Object.values(currentGraph.nodes).filter(
|
||||
(node) => node.type !== 'npm'
|
||||
@@ -16,5 +16,6 @@ if (!environment.release) {
|
||||
window.exclude = [];
|
||||
window.projectGraphList = projectGraphs;
|
||||
window.selectedProjectGraph = projectGraphs[0].id;
|
||||
window.workspaceLayout = projectGraphs[0].workspaceLayout;
|
||||
}
|
||||
setTimeout(() => new AppComponent(environment.appConfig));
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
"types": ["jest", "node"],
|
||||
"lib": ["DOM"]
|
||||
},
|
||||
"files": ["src/test-setup.ts"],
|
||||
"include": ["**/*.spec.ts", "**/*.d.ts"]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> This API is experimental and might change.
|
||||
|
||||
Nx views the workspace as a graph of projects that depend on one another. It's able to infer most projects and dependencies automatically. Currently, this works best within the Javascript ecosystem but it can be extended to other languages and technologies as well.
|
||||
Nx views the workspace as a graph of projects that depend on one another. It's able to infer most projects and dependencies automatically. Currently, this works best within the JavaScript ecosystem, but it can be extended to other languages and technologies as well. This is where project graph plugins come in.
|
||||
|
||||
## Defining Plugins to be used in a workspace
|
||||
|
||||
@@ -21,15 +21,17 @@ These plugins are used when running targets, linting, and sometimes when generat
|
||||
|
||||
## Implementing a Project Graph Processor
|
||||
|
||||
Project Graph Plugins are chained together to produce the final project graph. Each plugin may have a Project Graph Processor which iterates upon the project graph. Plugins should export a function named `processProjectGraph` that handles updating the project graph with new nodes and edges. This function receives two things:
|
||||
Project Graph Plugins are chained together to produce the final project graph. Each plugin may have a Project Graph Processor which iterates upon the project graph. Let's first take a look at the API of Project Graph Plugins. In later sections, we will go over some common use cases. Plugins should export a function named `processProjectGraph` that handles updating the project graph with new nodes and edges. This function receives two things:
|
||||
|
||||
- A `ProjectGraph`
|
||||
- Nodes in the project graph are the different projects currently in the graph.
|
||||
- Edges in the project graph are dependencies between different projects in the graph.
|
||||
- Some context is also passed into the function to use when processing the project graph. The context contains:
|
||||
- The `workspace` which contains both configuration as well as the different projects.
|
||||
- The `workspace` which contains both configuration and the different projects.
|
||||
- A `fileMap` which has a map of files by projects
|
||||
|
||||
> Note: The notion of a workspace is separate from the notion of the project graph. The workspace is first party code that is checked into git, targets are run on, etc. The project graph may include third party packages as well that is not checked into git, not run at all, etc.
|
||||
|
||||
The `processProjectGraph` function should return an updated `ProjectGraph`. This is most easily done using the `ProjectGraphBuilder` to iteratively add edges and nodes to the graph:
|
||||
|
||||
```typescript
|
||||
@@ -45,27 +47,47 @@ export function processProjectGraph(
|
||||
context: ProjectGraphProcessorContext
|
||||
): ProjectGraph {
|
||||
const builder = new ProjectGraphBuilder(graph);
|
||||
|
||||
// Add a new node
|
||||
builder.addNode({
|
||||
name: 'new-project',
|
||||
type: 'lib',
|
||||
data: {
|
||||
files: [],
|
||||
},
|
||||
});
|
||||
|
||||
// Add a new edge
|
||||
builder.addDependency(
|
||||
DependencyType.static,
|
||||
'existing-project',
|
||||
'new-project'
|
||||
);
|
||||
|
||||
// We will see how this is used below.
|
||||
return builder.getProjectGraph();
|
||||
}
|
||||
```
|
||||
|
||||
## Adding New Dependencies to the Project Graph
|
||||
|
||||
Project Graph Plugins can add smarter dependency resolution to projects already in the workspace. Projects in the workspace are first party code whose dependencies change as the code in the workspace changes and matter to Nx the most. Such projects should be defined in `workspace.json` and `nx.json` and will be automatically included as nodes in the project graph. However, when some projects are written in other languages, the relationships between these projects will not be clear to Nx out of the box. A Project Graph Plugin can add these relationships.
|
||||
|
||||
```typescript
|
||||
import { DependencyType } from '@nrwl/devkit';
|
||||
|
||||
// Add a new edge
|
||||
builder.addDependency(DependencyType.static, 'existing-project', 'new-project');
|
||||
```
|
||||
|
||||
> Note: Even though the plugin is written in JavaScript, resolving dependencies of different languages will probably be more easily written in their native language. Therefore, a common approach is to spawn a new process and communicate via IPC or `stdout`.
|
||||
|
||||
Dependencies can be one of the following types:
|
||||
|
||||
- `DependencyType.static` dependencies indicate that a dependency is imported directly into the code and would be present even without running the code.
|
||||
- `DependencyType.dynamic` dependencies indicate that a dependency _might be_ imported at runtime such as lazy loaded dependencies.
|
||||
- `DependencyType.implicit` dependencies indicate that one project affects another project's behavior or outcome even though there is no dependency in the code. For example, e2e tests or communication over HTTP.
|
||||
|
||||
## Adding New Nodes to the Project Graph
|
||||
|
||||
Sometimes it can be valuable to have third party packages as part of the project graph. A Project Graph Plugin can add these packages to the project graph. After these packages are added as nodes to the project graph, dependencies can then be drawn from the workspace projects to the third party packages as well as between the third party packages.
|
||||
|
||||
```typescript
|
||||
// Add a new node
|
||||
builder.addNode({
|
||||
name: 'new-project',
|
||||
type: 'npm',
|
||||
data: {
|
||||
files: [],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
> Note: You can designate any type for the node. This differentiates third party projects from projects in the workspace. Also, like before, retrieving these projects might be easiest within their native language. Therefore, spawning a new process may also be a common approach here.
|
||||
|
||||
## Visualizing the Project Graph
|
||||
|
||||
You can then visualize the project graph as described [here](dependency-graph).
|
||||
You can then visualize the project graph as described [here](/{{framework}}/structure/dependency-graph). However, there is a cache that Nx uses to avoid recalculating the project graph as much as possible. As you develop your project graph plugin, it might be a good idea to set the following environment variable to disable the project graph cache: `NX_CACHE_PROJECT_GRAPH=false`.
|
||||
|
||||
@@ -17,6 +17,42 @@ describe('Storybook schematics', () => {
|
||||
|
||||
afterEach(() => removeProject({ onlyOnCI: true }));
|
||||
|
||||
it('aaashould not overwrite global storybook config files', () => {
|
||||
const angularStorybookLib = uniq('test-ui-lib-angular');
|
||||
runCLI(
|
||||
`generate @nrwl/angular:lib ${angularStorybookLib} --no-interactive`
|
||||
);
|
||||
runCLI(
|
||||
`generate @nrwl/angular:storybook-configuration ${angularStorybookLib} --generateStories --no-interactive`
|
||||
);
|
||||
|
||||
checkFilesExist(`.storybook/main.js`);
|
||||
writeFileSync(
|
||||
tmpProjPath(`.storybook/main.js`),
|
||||
`
|
||||
module.exports = {
|
||||
stories: [],
|
||||
addons: ['@storybook/addon-knobs/register'],
|
||||
};
|
||||
|
||||
console.log('hi there');
|
||||
`
|
||||
);
|
||||
|
||||
// generate another lib with storybook config
|
||||
const anotherAngularStorybookLib = uniq('test-ui-lib-angular2');
|
||||
runCLI(
|
||||
`generate @nrwl/angular:lib ${anotherAngularStorybookLib} --no-interactive`
|
||||
);
|
||||
runCLI(
|
||||
`generate @nrwl/angular:storybook-configuration ${anotherAngularStorybookLib} --generateStories --no-interactive`
|
||||
);
|
||||
|
||||
expect(readFile(`.storybook/main.js`)).toContain(
|
||||
`console.log('hi there');`
|
||||
);
|
||||
});
|
||||
|
||||
describe('build storybook', () => {
|
||||
it('should execute e2e tests using Cypress running against Storybook', () => {
|
||||
const myapp = uniq('myapp');
|
||||
|
||||
@@ -153,6 +153,11 @@ describe('Next.js Applications', () => {
|
||||
export function testFn(): string {
|
||||
return 'Hello Nx';
|
||||
};
|
||||
|
||||
// testing whether async-await code in Node / Next.js api routes works as expected
|
||||
export async function testAsyncFn() {
|
||||
return await Promise.resolve('hell0');
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
@@ -165,7 +170,9 @@ describe('Next.js Applications', () => {
|
||||
}
|
||||
|
||||
export const TestComponent = ({ text }: TestComponentProps) => {
|
||||
return <span>{text}</span>;
|
||||
// testing whether modern languages features like nullish coalescing work
|
||||
const t = text ?? 'abc';
|
||||
return <span>{t}</span>;
|
||||
};
|
||||
|
||||
export default TestComponent;
|
||||
@@ -175,6 +182,18 @@ describe('Next.js Applications', () => {
|
||||
const mainPath = `apps/${appName}/pages/index.tsx`;
|
||||
const content = readFile(mainPath);
|
||||
|
||||
updateFile(
|
||||
`apps/${appName}/pages/api/hello.ts`,
|
||||
`
|
||||
import { testAsyncFn } from '@${proj}/${tsLibName}';
|
||||
|
||||
export default async function handler(_, res) {
|
||||
const value = await testAsyncFn();
|
||||
res.send(value);
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
updateFile(
|
||||
mainPath,
|
||||
`
|
||||
@@ -191,10 +210,26 @@ describe('Next.js Applications', () => {
|
||||
)}`
|
||||
);
|
||||
|
||||
const e2eTestPath = `apps/${appName}-e2e/src/integration/app.spec.ts`;
|
||||
const e2eContent = readFile(e2eTestPath);
|
||||
updateFile(
|
||||
e2eTestPath,
|
||||
`
|
||||
${
|
||||
e2eContent +
|
||||
`
|
||||
it('should successfully call async API route', () => {
|
||||
cy.request('/api/hello').its('body').should('include', 'hell0');
|
||||
});
|
||||
`
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
await checkApp(appName, {
|
||||
checkUnitTest: true,
|
||||
checkLint: true,
|
||||
checkE2E: false,
|
||||
checkE2E: true,
|
||||
});
|
||||
}, 120000);
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
updateFile,
|
||||
workspaceConfigName,
|
||||
} from '@nrwl/e2e/utils';
|
||||
import { TaskCacheStatus } from '@nrwl/workspace/src/utilities/output';
|
||||
|
||||
describe('run-one', () => {
|
||||
let proj: string;
|
||||
@@ -638,7 +637,7 @@ describe('cache', () => {
|
||||
});
|
||||
const outputWithBuildApp2Cached = runCLI(`affected:build ${files}`);
|
||||
expect(outputWithBuildApp2Cached).toContain('read the output from cache');
|
||||
expectMatchedOutput(outputWithBuildApp2Cached, [myapp2]);
|
||||
expectCached(outputWithBuildApp2Cached, [myapp2]);
|
||||
|
||||
// touch package.json
|
||||
// --------------------------------------------
|
||||
@@ -652,17 +651,13 @@ describe('cache', () => {
|
||||
|
||||
// build individual project with caching
|
||||
const individualBuildWithCache = runCLI(`build ${myapp1}`);
|
||||
expect(individualBuildWithCache).toContain(
|
||||
TaskCacheStatus.MatchedExistingOutput
|
||||
);
|
||||
expect(individualBuildWithCache).toContain('from cache');
|
||||
|
||||
// skip caching when building individual projects
|
||||
const individualBuildWithSkippedCache = runCLI(
|
||||
`build ${myapp1} --skip-nx-cache`
|
||||
);
|
||||
expect(individualBuildWithSkippedCache).not.toContain(
|
||||
TaskCacheStatus.MatchedExistingOutput
|
||||
);
|
||||
expect(individualBuildWithSkippedCache).not.toContain('from cache');
|
||||
|
||||
// run lint with caching
|
||||
// --------------------------------------------
|
||||
@@ -673,7 +668,7 @@ describe('cache', () => {
|
||||
expect(outputWithBothLintTasksCached).toContain(
|
||||
'read the output from cache'
|
||||
);
|
||||
expectMatchedOutput(outputWithBothLintTasksCached, [
|
||||
expectCached(outputWithBothLintTasksCached, [
|
||||
myapp1,
|
||||
myapp2,
|
||||
`${myapp1}-e2e`,
|
||||
@@ -752,38 +747,19 @@ describe('cache', () => {
|
||||
actualOutput: string,
|
||||
expectedCachedProjects: string[]
|
||||
) {
|
||||
expectProjectMatchTaskCacheStatus(actualOutput, expectedCachedProjects);
|
||||
}
|
||||
|
||||
function expectMatchedOutput(
|
||||
actualOutput: string,
|
||||
expectedMatchedOutputProjects: string[]
|
||||
) {
|
||||
expectProjectMatchTaskCacheStatus(
|
||||
actualOutput,
|
||||
expectedMatchedOutputProjects,
|
||||
TaskCacheStatus.MatchedExistingOutput
|
||||
);
|
||||
}
|
||||
|
||||
function expectProjectMatchTaskCacheStatus(
|
||||
actualOutput: string,
|
||||
expectedProjects: string[],
|
||||
cacheStatus: TaskCacheStatus = TaskCacheStatus.RetrievedFromCache
|
||||
) {
|
||||
const matchingProjects = [];
|
||||
const cachedProjects = [];
|
||||
const lines = actualOutput.split('\n');
|
||||
lines.forEach((s) => {
|
||||
lines.forEach((s, i) => {
|
||||
if (s.startsWith(`> nx run`)) {
|
||||
const projectName = s.split(`> nx run `)[1].split(':')[0].trim();
|
||||
if (s.indexOf(cacheStatus) > -1) {
|
||||
matchingProjects.push(projectName);
|
||||
if (s.indexOf('from cache') > -1) {
|
||||
cachedProjects.push(projectName);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
matchingProjects.sort((a, b) => a.localeCompare(b));
|
||||
expectedProjects.sort((a, b) => a.localeCompare(b));
|
||||
expect(matchingProjects).toEqual(expectedProjects);
|
||||
cachedProjects.sort((a, b) => a.localeCompare(b));
|
||||
expectedCachedProjects.sort((a, b) => a.localeCompare(b));
|
||||
expect(cachedProjects).toEqual(expectedCachedProjects);
|
||||
}
|
||||
});
|
||||
|
||||
+5
-15
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nrwl/nx-source",
|
||||
"version": "12.0.1",
|
||||
"version": "12.0.7",
|
||||
"description": "Powerful, Extensible Dev Tools",
|
||||
"homepage": "https://nx.dev",
|
||||
"private": true,
|
||||
@@ -59,7 +59,6 @@
|
||||
"@ngrx/schematics": "11.0.0",
|
||||
"@ngrx/store": "11.0.0",
|
||||
"@ngrx/store-devtools": "11.0.0",
|
||||
"@ngtools/webpack": "~10.1.3",
|
||||
"@nrwl/cli": "12.0.0",
|
||||
"@nrwl/cypress": "12.0.0",
|
||||
"@nrwl/eslint-plugin-nx": "12.0.0",
|
||||
@@ -100,24 +99,22 @@
|
||||
"@types/react": "17.0.3",
|
||||
"@types/react-dom": "17.0.3",
|
||||
"@types/react-router-dom": "5.1.7",
|
||||
"@types/tmp": "^0.2.0",
|
||||
"@types/webpack": "^4.4.24",
|
||||
"@types/webpack-dev-server": "^3.11.1",
|
||||
"@types/yargs": "^15.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "^4.3.0",
|
||||
"@typescript-eslint/experimental-utils": "^4.3.0",
|
||||
"@typescript-eslint/parser": "^4.3.0",
|
||||
"ajv": "6.10.2",
|
||||
"angular": "1.8.0",
|
||||
"app-root-path": "^2.0.1",
|
||||
"autoprefixer": "^10.2.5",
|
||||
"axios": "0.21.1",
|
||||
"babel-jest": "26.2.2",
|
||||
"cacache": "12.0.2",
|
||||
"caniuse-lite": "^1.0.30001030",
|
||||
"chalk": "4.1.0",
|
||||
"circular-dependency-plugin": "5.2.0",
|
||||
"clean-css": "4.2.1",
|
||||
"codelyzer": "~5.0.1",
|
||||
"commitizen": "^4.0.3",
|
||||
"confusing-browser-globals": "^1.0.9",
|
||||
"conventional-changelog-cli": "^2.0.23",
|
||||
@@ -146,7 +143,6 @@
|
||||
"express": "4.17.1",
|
||||
"file-loader": "4.2.0",
|
||||
"file-type": "^16.2.0",
|
||||
"find-cache-dir": "3.0.0",
|
||||
"flat": "^5.0.2",
|
||||
"fork-ts-checker-webpack-plugin": "^3.1.1",
|
||||
"fs-extra": "7.0.1",
|
||||
@@ -169,7 +165,6 @@
|
||||
"karma-coverage-istanbul-reporter": "~2.0.1",
|
||||
"karma-jasmine": "~1.1.1",
|
||||
"karma-jasmine-html-reporter": "^0.2.2",
|
||||
"karma-source-map-support": "1.4.0",
|
||||
"karma-webpack": "4.0.2",
|
||||
"less": "3.12.2",
|
||||
"less-loader": "5.0.0",
|
||||
@@ -186,8 +181,7 @@
|
||||
"ngrx-store-freeze": "0.2.4",
|
||||
"node-watch": "0.7.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"open": "6.4.0",
|
||||
"opn": "^5.3.0",
|
||||
"open": "^7.4.2",
|
||||
"parse-markdown-links": "^1.0.4",
|
||||
"parse5": "4.0.0",
|
||||
"postcss": "8.2.4",
|
||||
@@ -219,25 +213,22 @@
|
||||
"source-map": "0.7.3",
|
||||
"source-map-loader": "0.2.4",
|
||||
"source-map-support": "0.5.16",
|
||||
"speed-measure-webpack-plugin": "1.3.1",
|
||||
"strip-json-comments": "2.0.1",
|
||||
"strip-json-comments": "^3.1.1",
|
||||
"style-loader": "1.0.0",
|
||||
"styled-components": "5.0.0",
|
||||
"stylus": "0.54.5",
|
||||
"stylus-loader": "3.0.2",
|
||||
"tailwindcss": "^2.1.1",
|
||||
"tar": "5.0.5",
|
||||
"terser": "4.3.8",
|
||||
"terser-webpack-plugin": "2.3.7",
|
||||
"tippy.js": "5.2.1",
|
||||
"tmp": "0.0.33",
|
||||
"tmp": "~0.2.1",
|
||||
"tree-kill": "1.2.2",
|
||||
"ts-jest": "26.4.0",
|
||||
"ts-loader": "5.4.5",
|
||||
"ts-node": "9.1.1",
|
||||
"tsconfig-paths": "^3.9.0",
|
||||
"tsconfig-paths-webpack-plugin": "3.2.0",
|
||||
"tsickle": "^0.38.1",
|
||||
"tslib": "^2.0.0",
|
||||
"tslint": "6.1.3",
|
||||
"tslint-to-eslint-config": "2.2.0",
|
||||
@@ -245,7 +236,6 @@
|
||||
"url-loader": "^3.0.0",
|
||||
"verdaccio": "^4.11.1",
|
||||
"webpack": "4.42.0",
|
||||
"webpack-dev-middleware": "3.7.0",
|
||||
"webpack-dev-server": "3.11.0",
|
||||
"webpack-merge": "4.2.1",
|
||||
"webpack-node-externals": "1.7.2",
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ function addHTMLPatternToBuilderConfig(
|
||||
}
|
||||
|
||||
function updateProjectESLintConfigsAndBuilders(host: Tree): Rule {
|
||||
const graph = createProjectGraph(undefined, undefined, undefined, false);
|
||||
const graph = createProjectGraph(undefined, undefined, undefined);
|
||||
|
||||
/**
|
||||
* Make sure user is already using ESLint and is up to date with
|
||||
|
||||
@@ -8,11 +8,7 @@ import { Workspace } from './workspace';
|
||||
*
|
||||
* @param dir Directory to start searching with
|
||||
*/
|
||||
export function findWorkspaceRoot(dir: string): Workspace {
|
||||
if (path.dirname(dir) === dir) {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function findWorkspaceRoot(dir: string): Workspace | null {
|
||||
if (existsSync(path.join(dir, 'angular.json'))) {
|
||||
return { type: 'angular', dir };
|
||||
}
|
||||
@@ -21,5 +17,9 @@ export function findWorkspaceRoot(dir: string): Workspace {
|
||||
return { type: 'nx', dir };
|
||||
}
|
||||
|
||||
if (path.dirname(dir) === dir) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return findWorkspaceRoot(path.dirname(dir));
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
},
|
||||
"homepage": "https://nx.dev",
|
||||
"dependencies": {
|
||||
"tmp": "0.0.33",
|
||||
"yargs": "15.4.1",
|
||||
"yargs-parser": "20.0.0",
|
||||
"@nrwl/tao": "*",
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"homepage": "https://nx.dev",
|
||||
"dependencies": {
|
||||
"@nrwl/workspace": "*",
|
||||
"tmp": "0.0.33",
|
||||
"tmp": "~0.2.1",
|
||||
"yargs": "15.4.1",
|
||||
"yargs-parser": "20.0.0",
|
||||
"enquirer": "~2.3.6",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
},
|
||||
"homepage": "https://nx.dev",
|
||||
"dependencies": {
|
||||
"tmp": "0.0.33",
|
||||
"tmp": "~0.2.1",
|
||||
"yargs-parser": "20.0.0",
|
||||
"enquirer": "~2.3.6",
|
||||
"flat": "^5.0.2",
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
"@nrwl/linter": "*",
|
||||
"@nrwl/workspace": "*",
|
||||
"@cypress/webpack-preprocessor": "~4.1.2",
|
||||
"tree-kill": "1.2.2",
|
||||
"ts-loader": "5.4.5",
|
||||
"tsconfig-paths-webpack-plugin": "3.2.0",
|
||||
"webpack-node-externals": "1.7.2",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"ejs": "^3.1.5",
|
||||
"ignore": "^5.0.4",
|
||||
"semver": "7.3.4",
|
||||
"strip-json-comments": "2.0.1",
|
||||
"strip-json-comments": "^3.1.1",
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ import * as path from 'path';
|
||||
import { Tree } from '@nrwl/tao/src/shared/tree';
|
||||
import { join, relative } from 'path';
|
||||
|
||||
const ejs = require('ejs');
|
||||
|
||||
const binaryExts = new Set([
|
||||
// // Image types originally from https://github.com/sindresorhus/image-type/blob/5541b6a/index.js
|
||||
'.jpg',
|
||||
@@ -62,6 +60,7 @@ export function generateFiles(
|
||||
target: string,
|
||||
substitutions: { [k: string]: any }
|
||||
) {
|
||||
const ejs = require('ejs');
|
||||
allFilesInDir(srcFolder).forEach((filePath) => {
|
||||
let newContent: Buffer | string;
|
||||
const computedPath = computePath(
|
||||
|
||||
@@ -86,7 +86,11 @@ class DevkitTreeFromAngularDevkitTree {
|
||||
}
|
||||
|
||||
exists(filePath: string): boolean {
|
||||
return this.tree.exists(filePath);
|
||||
if (this.isFile(filePath)) {
|
||||
return this.tree.exists(filePath);
|
||||
} else {
|
||||
return this.children(filePath).length > 0;
|
||||
}
|
||||
}
|
||||
|
||||
isFile(filePath: string): boolean {
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"@nrwl/devkit": "*",
|
||||
"jest-resolve": "^26.6.2",
|
||||
"rxjs": "^6.5.4",
|
||||
"strip-json-comments": "2.0.1",
|
||||
"strip-json-comments": "^3.1.1",
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"@nrwl/devkit": "*",
|
||||
"glob": "7.1.4",
|
||||
"minimatch": "3.0.4",
|
||||
"tmp": "0.0.33",
|
||||
"tmp": "~0.2.1",
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
"tslib": "^2.0.0",
|
||||
"webpack": "4.42.0",
|
||||
"webpack-merge": "4.2.1",
|
||||
"webpack-dev-server": "3.11.0",
|
||||
"webpack-node-externals": "1.7.2",
|
||||
"rxjs-for-await": "0.0.2"
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
"@angular-devkit/schematics": "~11.2.0",
|
||||
"fs-extra": "7.0.1",
|
||||
"rxjs": "^6.5.4",
|
||||
"tmp": "0.0.33",
|
||||
"yargs": "15.4.1",
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export function normalizeOptions(
|
||||
options.project
|
||||
);
|
||||
|
||||
const npmPackageName = `@${npmScope}/${fileName}`;
|
||||
const npmPackageName = `@${npmScope}/${options.project}`;
|
||||
|
||||
const fileTemplate = getFileTemplate();
|
||||
|
||||
|
||||
@@ -184,6 +184,25 @@ describe('app', () => {
|
||||
).toContain('Welcome to my-app');
|
||||
});
|
||||
|
||||
it.each`
|
||||
style
|
||||
${'styled-components'}
|
||||
${'styled-jsx'}
|
||||
${'@emotion/styled'}
|
||||
`(
|
||||
'should generate valid .babelrc JSON config for CSS-in-JS solutions',
|
||||
async ({ style }) => {
|
||||
await applicationGenerator(appTree, {
|
||||
...schema,
|
||||
style,
|
||||
});
|
||||
|
||||
expect(() => {
|
||||
JSON.parse(appTree.read(`apps/my-app/.babelrc`).toString());
|
||||
}).not.toThrow();
|
||||
}
|
||||
);
|
||||
|
||||
describe('--style scss', () => {
|
||||
it('should generate scss styles', async () => {
|
||||
await applicationGenerator(appTree, { ...schema, style: 'scss' });
|
||||
|
||||
@@ -301,6 +301,38 @@ describe('react:component-story', () => {
|
||||
export default Test
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: 'direct export of component class new JSX transform',
|
||||
src: `
|
||||
export default class Test extends Component<TestProps> {
|
||||
render() {
|
||||
return <div><h1>Welcome to test component, {this.props.name}</h1></div>;
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: 'component class & then default export new JSX transform',
|
||||
src: `
|
||||
class Test extends Component<TestProps> {
|
||||
render() {
|
||||
return <div><h1>Welcome to test component, {this.props.name}</h1></div>;
|
||||
}
|
||||
}
|
||||
export default Test
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: 'PureComponent class & then default export new JSX transform',
|
||||
src: `
|
||||
class Test extends PureComponent<TestProps> {
|
||||
render() {
|
||||
return <div><h1>Welcome to test component, {this.props.name}</h1></div>;
|
||||
}
|
||||
}
|
||||
export default Test
|
||||
`,
|
||||
},
|
||||
].forEach((config) => {
|
||||
describe(`React component defined as:${config.name}`, () => {
|
||||
beforeEach(async () => {
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
"@nrwl/react/babel", {
|
||||
"runtime": "automatic",
|
||||
"useBuiltIns": "usage"
|
||||
<% if (style === '@emotion/styled') { %>,"importSource": "@emotion/react" }<% } %>
|
||||
<% if (style === '@emotion/styled') { %>,"importSource": "@emotion/react"<% } %>
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": [
|
||||
<% if (style === 'styled-components') { %>["styled-components", { "pure": true, "ssr": true }]<% } %>
|
||||
<% if (style === 'styled-jsx') { %>"styled-jsx/babel"<% } %>
|
||||
<% if (style === '@emotion/styled') { %>,"@emotion/babel-plugin"<% } %>
|
||||
<% if (style === '@emotion/styled') { %>"@emotion/babel-plugin"<% } %>
|
||||
]
|
||||
}
|
||||
|
||||
@@ -614,4 +614,24 @@ describe('lib', () => {
|
||||
).not.toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
it.each`
|
||||
style
|
||||
${'styled-components'}
|
||||
${'styled-jsx'}
|
||||
${'@emotion/styled'}
|
||||
`(
|
||||
'should generate valid .babelrc JSON config for CSS-in-JS solutions',
|
||||
async ({ style }) => {
|
||||
await libraryGenerator(appTree, {
|
||||
...defaultSchema,
|
||||
style,
|
||||
name: 'myLib',
|
||||
});
|
||||
|
||||
expect(() => {
|
||||
JSON.parse(appTree.read(`libs/my-lib/.babelrc`).toString());
|
||||
}).not.toThrow();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -199,7 +199,7 @@ function addProject(host: Tree, options: NormalizedSchema) {
|
||||
rollupConfig: `@nrwl/react/plugins/bundle-rollup`,
|
||||
assets: [
|
||||
{
|
||||
glob: 'README.md',
|
||||
glob: `${options.projectRoot}/README.md`,
|
||||
input: '.',
|
||||
output: '.',
|
||||
},
|
||||
|
||||
@@ -25,12 +25,7 @@ export default function update(): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const updates = [];
|
||||
const conflicts: Array<[string, string]> = [];
|
||||
const projectGraph = createProjectGraph(
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
false
|
||||
);
|
||||
const projectGraph = createProjectGraph(undefined, undefined, undefined);
|
||||
if (host.exists('/babel.config.json')) {
|
||||
context.logger.info(
|
||||
`
|
||||
|
||||
@@ -525,13 +525,12 @@ export function getComponentPropsInterface(
|
||||
const heritageClause = cmpDeclaration.heritageClauses[0];
|
||||
|
||||
if (heritageClause) {
|
||||
const propsTypeExpression = heritageClause.types.find(
|
||||
(x) =>
|
||||
(x.expression as ts.PropertyAccessExpression).name.text ===
|
||||
'Component' ||
|
||||
(x.expression as ts.PropertyAccessExpression).name.text ===
|
||||
'PureComponent'
|
||||
);
|
||||
const propsTypeExpression = heritageClause.types.find((x) => {
|
||||
const name =
|
||||
(x.expression as ts.Identifier).escapedText ||
|
||||
(x.expression as ts.PropertyAccessExpression).name.text;
|
||||
return name === 'Component' || name === 'PureComponent';
|
||||
});
|
||||
|
||||
if (propsTypeExpression && propsTypeExpression.typeArguments) {
|
||||
propsTypeName = (propsTypeExpression
|
||||
|
||||
@@ -34,9 +34,7 @@
|
||||
"@nrwl/workspace": "*",
|
||||
"core-js": "^3.6.5",
|
||||
"semver": "7.3.4",
|
||||
"tree-kill": "1.2.2",
|
||||
"ts-loader": "5.4.5",
|
||||
"tsconfig-paths-webpack-plugin": "3.2.0",
|
||||
"webpack-node-externals": "1.7.2"
|
||||
"tsconfig-paths-webpack-plugin": "3.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ export default async function* storybookExecutor(
|
||||
}
|
||||
|
||||
function runInstance(options: StorybookExecutorOptions) {
|
||||
process.env.NODE_ENV = process.env.NODE_ENV ?? 'development';
|
||||
return buildDevStandalone({ ...options, ci: true });
|
||||
}
|
||||
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
"enquirer": "~2.3.6",
|
||||
"minimist": "^1.2.5",
|
||||
"rxjs": "^6.5.4",
|
||||
"strip-json-comments": "2.0.1",
|
||||
"strip-json-comments": "^3.1.1",
|
||||
"semver": "7.3.4",
|
||||
"tmp": "0.0.33",
|
||||
"tmp": "~0.2.1",
|
||||
"tslib": "^2.0.0",
|
||||
"yargs-parser": "20.0.0",
|
||||
"fs-extra": "7.0.1",
|
||||
|
||||
@@ -20,9 +20,6 @@ module.exports = function (api: any, options: NxReactBabelPresetOptions = {}) {
|
||||
|
||||
const isModern = api.caller((caller) => caller?.isModern);
|
||||
|
||||
// `isServer` is passed from `next-babel-loader`, when it compiles for the server
|
||||
const isServer = api.caller((caller) => caller?.isServer);
|
||||
|
||||
// This is set by `@nrwl/web:package` executor
|
||||
const isNxPackage = api.caller((caller) => caller?.isNxPackage);
|
||||
|
||||
@@ -38,7 +35,7 @@ module.exports = function (api: any, options: NxReactBabelPresetOptions = {}) {
|
||||
// For Jest tests, NODE_ENV is set as 'test' and we only want to set target as Node.
|
||||
// All other options will fail in Jest since Node does not support some ES features
|
||||
// such as import syntax.
|
||||
isServer || process.env.NODE_ENV === 'test'
|
||||
process.env.NODE_ENV === 'test'
|
||||
? { targets: { node: 'current' } }
|
||||
: {
|
||||
// Allow importing core-js in entrypoint and use browserlist to select polyfills.
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
"@rollup/plugin-image": "2.0.4",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "7.1.1",
|
||||
"ajv": "6.10.2",
|
||||
"autoprefixer": "^10.2.5",
|
||||
"babel-loader": "8.1.0",
|
||||
"babel-plugin-const-enum": "^1.0.1",
|
||||
@@ -54,7 +53,6 @@
|
||||
"babel-plugin-transform-async-to-promises": "^0.8.15",
|
||||
"babel-plugin-transform-typescript-metadata": "^0.3.1",
|
||||
"browserslist": "^4.14.6",
|
||||
"cacache": "12.0.2",
|
||||
"caniuse-lite": "^1.0.30001030",
|
||||
"chalk": "4.1.0",
|
||||
"circular-dependency-plugin": "5.2.0",
|
||||
@@ -63,29 +61,22 @@
|
||||
"core-js": "^3.6.5",
|
||||
"css-loader": "3.4.2",
|
||||
"file-loader": "4.2.0",
|
||||
"find-cache-dir": "3.0.0",
|
||||
"fork-ts-checker-webpack-plugin": "^3.1.1",
|
||||
"fs-extra": "7.0.1",
|
||||
"glob": "7.1.4",
|
||||
"identity-obj-proxy": "3.0.0",
|
||||
"jest-worker": "25.1.0",
|
||||
"karma-source-map-support": "1.4.0",
|
||||
"less": "3.12.2",
|
||||
"less-loader": "5.0.0",
|
||||
"license-webpack-plugin": "2.1.2",
|
||||
"loader-utils": "1.2.3",
|
||||
"mini-css-extract-plugin": "0.8.0",
|
||||
"minimatch": "3.0.4",
|
||||
"parse5": "4.0.0",
|
||||
"open": "6.4.0",
|
||||
"opn": "^5.3.0",
|
||||
"open": "^7.4.2",
|
||||
"postcss": "8.2.4",
|
||||
"postcss-import": "14.0.0",
|
||||
"postcss-loader": "4.2.0",
|
||||
"raw-loader": "3.1.0",
|
||||
"rxjs": "^6.5.4",
|
||||
"rxjs-for-await": "0.0.2",
|
||||
"regenerator-runtime": "0.13.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "1.31.1",
|
||||
"rollup-plugin-copy": "^3.3.0",
|
||||
@@ -99,25 +90,20 @@
|
||||
"semver": "7.3.4",
|
||||
"source-map": "0.7.3",
|
||||
"source-map-loader": "0.2.4",
|
||||
"source-map-support": "0.5.16",
|
||||
"speed-measure-webpack-plugin": "1.3.1",
|
||||
"style-loader": "1.0.0",
|
||||
"stylus": "0.54.5",
|
||||
"stylus-loader": "3.0.2",
|
||||
"tree-kill": "1.2.2",
|
||||
"terser": "4.3.8",
|
||||
"terser-webpack-plugin": "2.3.7",
|
||||
"ts-loader": "5.4.5",
|
||||
"tsconfig-paths-webpack-plugin": "3.2.0",
|
||||
"tslib": "^2.0.0",
|
||||
"webpack": "4.42.0",
|
||||
"webpack-dev-middleware": "3.7.0",
|
||||
"webpack-merge": "4.2.1",
|
||||
"webpack-sources": "1.4.3",
|
||||
"webpack-subresource-integrity": "^1.5.1",
|
||||
"worker-plugin": "3.2.0",
|
||||
"webpack-dev-server": "3.11.0",
|
||||
"webpack-node-externals": "1.7.2",
|
||||
"node-watch": "0.7.0",
|
||||
"http-server": "0.12.3",
|
||||
"ignore": "^5.0.4"
|
||||
|
||||
@@ -7,9 +7,7 @@ import { hasDependentAppUsingWebBuild } from './utils';
|
||||
|
||||
export async function createBabelrcForWorkspaceLibs(host: Tree) {
|
||||
const projects = getProjects(host);
|
||||
const graph = reverse(
|
||||
createProjectGraph(undefined, undefined, undefined, false)
|
||||
);
|
||||
const graph = reverse(createProjectGraph(undefined, undefined, undefined));
|
||||
|
||||
for (const [name, p] of projects.entries()) {
|
||||
if (!hasDependentAppUsingWebBuild(name, graph, projects)) {
|
||||
|
||||
@@ -9,8 +9,9 @@ import { join } from 'path';
|
||||
jest.mock('tsconfig-paths-webpack-plugin');
|
||||
import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
import { logger } from '@nrwl/devkit';
|
||||
jest.mock('opn');
|
||||
import * as opn from 'opn';
|
||||
import open = require('open');
|
||||
|
||||
jest.mock('open');
|
||||
|
||||
describe('getDevServerConfig', () => {
|
||||
let buildInput: WebBuildBuilderOptions;
|
||||
@@ -135,7 +136,6 @@ describe('getDevServerConfig', () => {
|
||||
};
|
||||
|
||||
spyOn(logger, 'info');
|
||||
opn.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it('should print out the URL of the server', () => {
|
||||
@@ -163,7 +163,7 @@ describe('getDevServerConfig', () => {
|
||||
|
||||
result.onListening(mockServer);
|
||||
|
||||
expect(opn).not.toHaveBeenCalled();
|
||||
expect(open).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should open the url if --open is passed', () => {
|
||||
@@ -177,9 +177,7 @@ describe('getDevServerConfig', () => {
|
||||
|
||||
result.onListening(mockServer);
|
||||
|
||||
expect(opn).toHaveBeenCalledWith('http://example.com:9999/', {
|
||||
wait: false,
|
||||
});
|
||||
expect(open).toHaveBeenCalledWith('http://example.com:9999/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { logger } from '@nrwl/devkit';
|
||||
import { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server';
|
||||
|
||||
import * as opn from 'opn';
|
||||
import * as open from 'open';
|
||||
import * as url from 'url';
|
||||
import { readFileSync } from 'fs';
|
||||
import * as path from 'path';
|
||||
@@ -68,9 +68,7 @@ function getDevServerPartial(
|
||||
|
||||
logger.info(`NX Web Development Server is listening at ${serverUrl}`);
|
||||
if (options.open) {
|
||||
opn(serverUrl, {
|
||||
wait: false,
|
||||
});
|
||||
open(serverUrl);
|
||||
}
|
||||
},
|
||||
stats: false,
|
||||
|
||||
@@ -63,11 +63,11 @@
|
||||
"dotenv": "8.2.0",
|
||||
"ignore": "^5.0.4",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"opn": "^5.3.0",
|
||||
"open": "^7.4.2",
|
||||
"rxjs": "^6.5.4",
|
||||
"semver": "7.3.4",
|
||||
"strip-json-comments": "2.0.1",
|
||||
"tmp": "0.0.33",
|
||||
"strip-json-comments": "^3.1.1",
|
||||
"tmp": "~0.2.1",
|
||||
"yargs": "15.4.1",
|
||||
"yargs-parser": "20.0.0",
|
||||
"chalk": "4.1.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { exists, readFile, readFileSync, statSync, writeFileSync } from 'fs';
|
||||
import { copySync } from 'fs-extra';
|
||||
import * as http from 'http';
|
||||
import * as opn from 'opn';
|
||||
import * as open from 'open';
|
||||
import { join, normalize, parse, dirname } from 'path';
|
||||
import { ensureDirSync } from 'fs-extra';
|
||||
import * as url from 'url';
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from '../core/project-graph';
|
||||
import { appRootPath } from '../utilities/app-root';
|
||||
import { output } from '../utilities/output';
|
||||
import { workspaceLayout } from '../core/file-utils';
|
||||
|
||||
// maps file extention to MIME types
|
||||
const mimeType = {
|
||||
@@ -38,7 +39,8 @@ function projectsToHtml(
|
||||
affected: string[],
|
||||
focus: string,
|
||||
groupByFolder: boolean,
|
||||
exclude: string[]
|
||||
exclude: string[],
|
||||
layout: { appsDir: string; libsDir: string }
|
||||
) {
|
||||
let f = readFileSync(
|
||||
join(__dirname, '../core/dep-graph/index.html')
|
||||
@@ -61,6 +63,10 @@ function projectsToHtml(
|
||||
.replace(
|
||||
`window.exclude = []`,
|
||||
`window.exclude = ${JSON.stringify(exclude)}`
|
||||
)
|
||||
.replace(
|
||||
`window.workspaceLayout = null`,
|
||||
`window.workspaceLayout = ${JSON.stringify(layout)}`
|
||||
);
|
||||
|
||||
if (focus) {
|
||||
@@ -149,6 +155,7 @@ export function generateGraph(
|
||||
affectedProjects: string[]
|
||||
): void {
|
||||
let graph = onlyWorkspaceProjects(createProjectGraph());
|
||||
const layout = workspaceLayout();
|
||||
|
||||
const projects = Object.values(graph.nodes) as ProjectGraphNode[];
|
||||
projects.sort((a, b) => {
|
||||
@@ -192,7 +199,8 @@ export function generateGraph(
|
||||
affectedProjects,
|
||||
args.focus || null,
|
||||
args.groupByFolder || false,
|
||||
args.exclude || []
|
||||
args.exclude || [],
|
||||
layout
|
||||
);
|
||||
} else {
|
||||
graph = filterGraph(graph, args.focus || null, args.exclude || []);
|
||||
@@ -323,7 +331,5 @@ function startServer(html: string, host: string, port = 4211) {
|
||||
title: `Dep graph started at http://${host}:${port}`,
|
||||
});
|
||||
|
||||
opn(`http://${host}:${port}`, {
|
||||
wait: false,
|
||||
});
|
||||
open(`http://${host}:${port}`);
|
||||
}
|
||||
|
||||
@@ -45,19 +45,21 @@ function getUntrackedFiles(): string[] {
|
||||
function getFilesUsingBaseAndHead(base: string, head: string): string[] {
|
||||
let mergeBase;
|
||||
try {
|
||||
mergeBase = execSync(`git merge-base ${base} ${head}`, {
|
||||
mergeBase = execSync(`git merge-base "${base}" "${head}"`, {
|
||||
maxBuffer: TEN_MEGABYTES,
|
||||
})
|
||||
.toString()
|
||||
.trim();
|
||||
} catch {
|
||||
mergeBase = execSync(`git merge-base --fork-point ${base} ${head}`, {
|
||||
mergeBase = execSync(`git merge-base --fork-point "${base}" "${head}"`, {
|
||||
maxBuffer: TEN_MEGABYTES,
|
||||
})
|
||||
.toString()
|
||||
.trim();
|
||||
}
|
||||
return parseGitOutput(`git diff --name-only --relative ${mergeBase} ${head}`);
|
||||
return parseGitOutput(
|
||||
`git diff --name-only --relative "${mergeBase}" "${head}"`
|
||||
);
|
||||
}
|
||||
|
||||
function parseGitOutput(command: string): string[] {
|
||||
|
||||
@@ -160,13 +160,19 @@ function readFileIfExisting(path: string) {
|
||||
: '';
|
||||
}
|
||||
|
||||
export function readWorkspaceJson(): any {
|
||||
const ws = new Workspaces(appRootPath);
|
||||
return ws.readWorkspaceConfiguration();
|
||||
export function readWorkspaceJson() {
|
||||
return readWorkspaceConfig({
|
||||
format: 'nx',
|
||||
path: appRootPath,
|
||||
});
|
||||
}
|
||||
|
||||
export function readWorkspaceConfig(opts: { format: 'angularCli' | 'nx' }) {
|
||||
const json = readWorkspaceJson();
|
||||
export function readWorkspaceConfig(opts: {
|
||||
format: 'angularCli' | 'nx';
|
||||
path?: string;
|
||||
}) {
|
||||
const ws = new Workspaces(opts.path);
|
||||
const json = ws.readWorkspaceConfiguration();
|
||||
if (opts.format === 'angularCli') {
|
||||
const formatted = toOldFormatOrNull(json);
|
||||
return formatted ?? json;
|
||||
@@ -203,11 +209,10 @@ export function readNxJson(): NxJsonConfiguration {
|
||||
|
||||
export function workspaceLayout(): { appsDir: string; libsDir: string } {
|
||||
const nxJson = readNxJson();
|
||||
const appsDir =
|
||||
(nxJson.workspaceLayout && nxJson.workspaceLayout.appsDir) || 'apps';
|
||||
const libsDir =
|
||||
(nxJson.workspaceLayout && nxJson.workspaceLayout.libsDir) || 'libs';
|
||||
return { appsDir, libsDir };
|
||||
return {
|
||||
appsDir: nxJson.workspaceLayout?.appsDir ?? 'apps',
|
||||
libsDir: nxJson.workspaceLayout?.libsDir ?? 'libs',
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Make this list extensible
|
||||
|
||||
@@ -35,7 +35,6 @@ import {
|
||||
import { ProjectGraph } from './project-graph-models';
|
||||
import {
|
||||
differentFromCache,
|
||||
ProjectGraphCache,
|
||||
readCache,
|
||||
writeCache,
|
||||
} from '../nx-deps/nx-deps-cache';
|
||||
@@ -45,10 +44,10 @@ import { performance } from 'perf_hooks';
|
||||
export function createProjectGraph(
|
||||
workspaceJson = readWorkspaceJson(),
|
||||
nxJson = readNxJson(),
|
||||
workspaceFiles = readWorkspaceFiles(),
|
||||
cache: false | ProjectGraphCache = readCache(),
|
||||
shouldCache: boolean = true
|
||||
workspaceFiles = readWorkspaceFiles()
|
||||
): ProjectGraph {
|
||||
const cacheEnabled = process.env.NX_CACHE_PROJECT_GRAPH !== 'false';
|
||||
let cache = cacheEnabled ? readCache() : false;
|
||||
assertWorkspaceValidity(workspaceJson, nxJson);
|
||||
const normalizedNxJson = normalizeNxJson(nxJson);
|
||||
|
||||
@@ -73,7 +72,7 @@ export function createProjectGraph(
|
||||
ctx,
|
||||
diff.partiallyConstructedProjectGraph
|
||||
);
|
||||
if (shouldCache) {
|
||||
if (cacheEnabled) {
|
||||
writeCache(rootFiles, projectGraph);
|
||||
}
|
||||
return addWorkspaceFiles(projectGraph, workspaceFiles);
|
||||
@@ -84,7 +83,7 @@ export function createProjectGraph(
|
||||
fileMap: projectFileMap,
|
||||
};
|
||||
const projectGraph = buildProjectGraph(ctx, null);
|
||||
if (shouldCache) {
|
||||
if (cacheEnabled) {
|
||||
writeCache(rootFiles, projectGraph);
|
||||
}
|
||||
return addWorkspaceFiles(projectGraph, workspaceFiles);
|
||||
|
||||
@@ -106,4 +106,19 @@ describe('new', () => {
|
||||
expect(readJson(tree, 'package.json')).toEqual(packageJson);
|
||||
expect(readJson(tree, '.eslintrc.json')).toEqual(eslintConfig);
|
||||
});
|
||||
|
||||
it('should throw an error when the directory is not empty', async () => {
|
||||
tree.write('my-workspace/file.txt', '');
|
||||
|
||||
try {
|
||||
await newGenerator(tree, {
|
||||
...defaultOptions,
|
||||
name: 'my-workspace',
|
||||
directory: 'my-workspace',
|
||||
npmScope: 'npmScope',
|
||||
appName: 'app',
|
||||
});
|
||||
fail('Generating into a non-empty directory should error.');
|
||||
} catch (e) {}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -171,6 +171,16 @@ export async function newGenerator(host: Tree, options: Schema) {
|
||||
|
||||
options = normalizeOptions(options);
|
||||
|
||||
if (
|
||||
host.exists(options.name) &&
|
||||
!host.isFile(options.name) &&
|
||||
host.children(options.name).length > 0
|
||||
) {
|
||||
throw new Error(
|
||||
`${join(host.root, options.name)} is not an empty directory.`
|
||||
);
|
||||
}
|
||||
|
||||
const layout: 'packages' | 'apps-and-libs' =
|
||||
options.preset === 'oss' ? 'packages' : 'apps-and-libs';
|
||||
const workspaceOpts = {
|
||||
|
||||
@@ -19,8 +19,7 @@ export function checkDependencies(_, schema: Schema) {
|
||||
const graph: ProjectGraph = createProjectGraph(
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
false
|
||||
undefined
|
||||
);
|
||||
|
||||
const reverseGraph = onlyWorkspaceProjects(reverse(graph));
|
||||
|
||||
@@ -12,7 +12,6 @@ import * as fsExtra from 'fs-extra';
|
||||
import { DefaultTasksRunnerOptions } from './default-tasks-runner';
|
||||
import { spawn } from 'child_process';
|
||||
import { cacheDirectory } from '../utilities/cache-directory';
|
||||
import { readJsonFile, writeJsonFile } from '../utilities/fileutils';
|
||||
|
||||
export type CachedResult = { terminalOutput: string; outputsPath: string };
|
||||
export type TaskWithCachedResult = { task: Task; cachedResult: CachedResult };
|
||||
@@ -39,7 +38,6 @@ export class Cache {
|
||||
root = appRootPath;
|
||||
cachePath = this.createCacheDir();
|
||||
terminalOutputsDir = this.createTerminalOutputsDir();
|
||||
nxOutputsPath = this.ensureNxOutputsFile();
|
||||
cacheConfig = new CacheConfig(this.options);
|
||||
|
||||
constructor(private readonly options: DefaultTasksRunnerOptions) {}
|
||||
@@ -150,42 +148,6 @@ export class Cache {
|
||||
}
|
||||
}
|
||||
|
||||
removeOutputHashesFromNxOutputs(outputs: string[]): void {
|
||||
if (outputs.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nxOutputs = readJsonFile(this.nxOutputsPath);
|
||||
outputs.forEach((output) => {
|
||||
delete nxOutputs[output];
|
||||
});
|
||||
writeJsonFile(this.nxOutputsPath, nxOutputs);
|
||||
}
|
||||
|
||||
writeOutputHashesToNxOutputs(outputs: string[], hash: string): void {
|
||||
if (outputs.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nxOutputs = readJsonFile(this.nxOutputsPath);
|
||||
outputs.forEach((output) => {
|
||||
nxOutputs[output] = hash;
|
||||
});
|
||||
writeJsonFile(this.nxOutputsPath, nxOutputs);
|
||||
}
|
||||
|
||||
outputsMatchTask(task: Task, outputs: string[]): boolean {
|
||||
if (outputs.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const nxOutputs = readJsonFile(this.nxOutputsPath);
|
||||
return outputs.every(
|
||||
(output) =>
|
||||
existsSync(join(this.root, output)) && task.hash === nxOutputs[output]
|
||||
);
|
||||
}
|
||||
|
||||
private getFromLocalDir(task: Task) {
|
||||
const tdCommit = join(this.cachePath, `${task.hash}.commit`);
|
||||
const td = join(this.cachePath, task.hash);
|
||||
@@ -213,12 +175,4 @@ export class Cache {
|
||||
fsExtra.ensureDirSync(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
private ensureNxOutputsFile() {
|
||||
const path = join(this.cachePath, 'nx-outputs.json');
|
||||
if (!existsSync(path)) {
|
||||
writeJsonFile(path, {});
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as dotenv from 'dotenv';
|
||||
import * as fs from 'fs';
|
||||
import { ProjectGraph } from '../core/project-graph';
|
||||
import { appRootPath } from '../utilities/app-root';
|
||||
import { output, TaskCacheStatus } from '../utilities/output';
|
||||
import { output } from '../utilities/output';
|
||||
import { Cache, TaskWithCachedResult } from './cache';
|
||||
import { DefaultTasksRunnerOptions } from './default-tasks-runner';
|
||||
import { AffectedEventType, Task } from './tasks-runner';
|
||||
@@ -115,28 +115,18 @@ export class TaskOrchestrator {
|
||||
tasks.forEach((t) => {
|
||||
this.options.lifeCycle.startTask(t.task);
|
||||
|
||||
const outputs = getOutputs(this.projectGraph.nodes, t.task);
|
||||
const outputsMatchCache = this.cache.outputsMatchTask(t.task, outputs);
|
||||
if (!outputsMatchCache) {
|
||||
this.cache.removeOutputHashesFromNxOutputs(outputs);
|
||||
this.cache.copyFilesFromCache(t.cachedResult, outputs);
|
||||
this.cache.writeOutputHashesToNxOutputs(outputs, t.task.hash);
|
||||
}
|
||||
|
||||
if (
|
||||
!this.initiatingProject ||
|
||||
this.initiatingProject === t.task.target.project
|
||||
) {
|
||||
const args = this.getCommandArgs(t.task);
|
||||
output.logCommand(
|
||||
`nx ${args.join(' ')}`,
|
||||
outputsMatchCache
|
||||
? TaskCacheStatus.MatchedExistingOutput
|
||||
: TaskCacheStatus.RetrievedFromCache
|
||||
);
|
||||
output.logCommand(`nx ${args.join(' ')}`, true);
|
||||
process.stdout.write(t.cachedResult.terminalOutput);
|
||||
}
|
||||
|
||||
const outputs = getOutputs(this.projectGraph.nodes, t.task);
|
||||
this.cache.copyFilesFromCache(t.cachedResult, outputs);
|
||||
|
||||
this.options.lifeCycle.endTask(t.task, 0);
|
||||
});
|
||||
|
||||
@@ -185,7 +175,6 @@ export class TaskOrchestrator {
|
||||
if (forwardOutput) {
|
||||
output.logCommand(commandLine);
|
||||
}
|
||||
this.cache.removeOutputHashesFromNxOutputs(taskOutputs);
|
||||
const p = fork(this.getCommand(), args, {
|
||||
stdio: ['inherit', 'pipe', 'pipe', 'ipc'],
|
||||
env,
|
||||
@@ -221,10 +210,6 @@ export class TaskOrchestrator {
|
||||
this.cache
|
||||
.put(task, outputPath, taskOutputs)
|
||||
.then(() => {
|
||||
this.cache.writeOutputHashesToNxOutputs(
|
||||
taskOutputs,
|
||||
task.hash
|
||||
);
|
||||
this.options.lifeCycle.endTask(task, code);
|
||||
res(code);
|
||||
})
|
||||
@@ -232,12 +217,10 @@ export class TaskOrchestrator {
|
||||
rej(e);
|
||||
});
|
||||
} else {
|
||||
this.cache.writeOutputHashesToNxOutputs(taskOutputs, task.hash);
|
||||
this.options.lifeCycle.endTask(task, code);
|
||||
res(code);
|
||||
}
|
||||
} else {
|
||||
this.cache.writeOutputHashesToNxOutputs(taskOutputs, task.hash);
|
||||
this.options.lifeCycle.endTask(task, code);
|
||||
res(code);
|
||||
}
|
||||
@@ -268,7 +251,6 @@ export class TaskOrchestrator {
|
||||
if (forwardOutput) {
|
||||
output.logCommand(commandLine);
|
||||
}
|
||||
this.cache.removeOutputHashesFromNxOutputs(taskOutputs);
|
||||
const p = fork(this.getCommand(), args, {
|
||||
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
||||
env,
|
||||
@@ -293,7 +275,6 @@ export class TaskOrchestrator {
|
||||
this.cache
|
||||
.put(task, outputPath, taskOutputs)
|
||||
.then(() => {
|
||||
this.cache.writeOutputHashesToNxOutputs(taskOutputs, task.hash);
|
||||
this.options.lifeCycle.endTask(task, code);
|
||||
res(code);
|
||||
})
|
||||
@@ -301,7 +282,6 @@ export class TaskOrchestrator {
|
||||
rej(e);
|
||||
});
|
||||
} else {
|
||||
this.cache.writeOutputHashesToNxOutputs(taskOutputs, task.hash);
|
||||
this.options.lifeCycle.endTask(task, code);
|
||||
res(code);
|
||||
}
|
||||
|
||||
@@ -6,5 +6,5 @@ import { createProjectGraph } from '../core/project-graph/project-graph';
|
||||
* @deprecated This method is deprecated and is synonymous to {@link createProjectGraph}()
|
||||
*/
|
||||
export function createProjectGraphFromTree(tree: Tree) {
|
||||
return createProjectGraph(undefined, undefined, undefined, false);
|
||||
return createProjectGraph(undefined, undefined, undefined);
|
||||
}
|
||||
|
||||
@@ -22,12 +22,6 @@ export interface CLISuccessMessageConfig {
|
||||
bodyLines?: string[];
|
||||
}
|
||||
|
||||
export enum TaskCacheStatus {
|
||||
NoCache = '[no cache]',
|
||||
MatchedExistingOutput = '[existing outputs match the cache, left as is]',
|
||||
RetrievedFromCache = '[retrieved from cache]',
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically disable styling applied by chalk if CI=true
|
||||
*/
|
||||
@@ -183,16 +177,13 @@ class CLIOutput {
|
||||
this.addNewline();
|
||||
}
|
||||
|
||||
logCommand(
|
||||
message: string,
|
||||
cacheStatus: TaskCacheStatus = TaskCacheStatus.NoCache
|
||||
) {
|
||||
logCommand(message: string, isCached: boolean = false) {
|
||||
this.addNewline();
|
||||
|
||||
this.writeToStdOut(chalk.bold(`> ${message} `));
|
||||
|
||||
if (cacheStatus !== TaskCacheStatus.NoCache) {
|
||||
this.writeToStdOut(chalk.bold.grey(cacheStatus));
|
||||
if (isCached) {
|
||||
this.writeToStdOut(chalk.bold.grey(`[retrieved from cache]`));
|
||||
}
|
||||
|
||||
this.addNewline();
|
||||
|
||||
@@ -371,7 +371,7 @@ export function getProjectGraphFromHost(host: Tree): ProjectGraph {
|
||||
* @deprecated This method is deprecated and is synonymous to {@link createProjectGraph}()
|
||||
*/
|
||||
export function getFullProjectGraphFromHost(host: Tree): ProjectGraph {
|
||||
return createProjectGraph(undefined, undefined, undefined, false);
|
||||
return createProjectGraph(undefined, undefined, undefined);
|
||||
}
|
||||
|
||||
// TODO(v13): remove this deprecated method
|
||||
|
||||
@@ -12,6 +12,7 @@ if [[ $NX_VERSION == "--local" ]]; then
|
||||
NX_VERSION="*"
|
||||
fi
|
||||
|
||||
rm -rf build
|
||||
npx nx run-many --target=build --all --parallel || { echo 'Build failed' ; exit 1; }
|
||||
|
||||
cd build/packages
|
||||
|
||||
@@ -108,17 +108,6 @@
|
||||
"@angular-devkit/core" "11.2.4"
|
||||
rxjs "6.6.3"
|
||||
|
||||
"@angular-devkit/core@10.1.7":
|
||||
version "10.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.1.7.tgz#c4c4332d738075bf1346aa040c78756e3144ba4b"
|
||||
integrity sha512-RRyDkN2FByA+nlnRx/MzUMK1FXwj7+SsrzJcvZfWx4yA5rfKmJiJryXQEzL44GL1aoaXSuvOYu3H72wxZADN8Q==
|
||||
dependencies:
|
||||
ajv "6.12.4"
|
||||
fast-json-stable-stringify "2.1.0"
|
||||
magic-string "0.25.7"
|
||||
rxjs "6.6.2"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/core@11.2.3":
|
||||
version "11.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-11.2.3.tgz#322fb08f4e2683a37bd08edecb04ddafa42865d9"
|
||||
@@ -2301,15 +2290,6 @@
|
||||
enhanced-resolve "5.7.0"
|
||||
webpack-sources "2.2.0"
|
||||
|
||||
"@ngtools/webpack@~10.1.3":
|
||||
version "10.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-10.1.7.tgz#0778473a92f49ba72a56167104dcfb26ed7cebb0"
|
||||
integrity sha512-J/ePcuUfrh0tgnZ+Em4Rv0UYb8wBHARk//K0eVr/Qk5ziWEcYyOW3w3Hz6FbxwIElXvkj+/C9GOb1SapkzlEXg==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "10.1.7"
|
||||
enhanced-resolve "4.3.0"
|
||||
webpack-sources "1.4.3"
|
||||
|
||||
"@nodelib/fs.scandir@2.1.4":
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69"
|
||||
@@ -4015,6 +3995,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
|
||||
integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==
|
||||
|
||||
"@types/tmp@^0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.2.0.tgz#e3f52b4d7397eaa9193592ef3fdd44dc0af4298c"
|
||||
integrity sha512-flgpHJjntpBAdJD43ShRosQvNC0ME97DCfGvZEDlAThQmnerRXrLbX6YgzRBQCZTthET9eAWFAMaYP0m0Y4HzQ==
|
||||
|
||||
"@types/uglify-js@*":
|
||||
version "3.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.13.0.tgz#1cad8df1fb0b143c5aba08de5712ea9d1ff71124"
|
||||
@@ -4821,16 +4806,6 @@ ajv@6.10.2:
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ajv@6.12.4:
|
||||
version "6.12.4"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234"
|
||||
integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ajv@6.12.6, ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
|
||||
version "6.12.6"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||
@@ -4989,7 +4964,7 @@ app-root-dir@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/app-root-dir/-/app-root-dir-1.0.2.tgz#38187ec2dea7577fff033ffcb12172692ff6e118"
|
||||
integrity sha1-OBh+wt6nV3//Az/8sSFyaS/24Rg=
|
||||
|
||||
app-root-path@^2.0.1, app-root-path@^2.1.0:
|
||||
app-root-path@^2.0.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a"
|
||||
integrity sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==
|
||||
@@ -5044,14 +5019,6 @@ argparse@~0.1.15:
|
||||
underscore "~1.7.0"
|
||||
underscore.string "~2.4.0"
|
||||
|
||||
aria-query@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc"
|
||||
integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=
|
||||
dependencies:
|
||||
ast-types-flow "0.0.7"
|
||||
commander "^2.11.0"
|
||||
|
||||
aria-query@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
|
||||
@@ -5238,7 +5205,7 @@ assign-symbols@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
|
||||
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
|
||||
|
||||
ast-types-flow@0.0.7, ast-types-flow@^0.0.7:
|
||||
ast-types-flow@^0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
|
||||
integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0=
|
||||
@@ -5380,7 +5347,7 @@ axios@0.21.1, axios@^0.21.1:
|
||||
dependencies:
|
||||
follow-redirects "^1.10.0"
|
||||
|
||||
axobject-query@^2.0.2, axobject-query@^2.2.0:
|
||||
axobject-query@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
|
||||
integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==
|
||||
@@ -7475,21 +7442,6 @@ code-point-at@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||
|
||||
codelyzer@~5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-5.0.1.tgz#c52a593368269b791594603968eb82cbecae3cda"
|
||||
integrity sha512-UVV76+/y1RwaxzCeGPFE3G4GFtfV42r3x8EmRd7XMNFLlLC0ewdtCqWTbvhwPQMxFZZ+OTLEOJNWfyPPn3QFWg==
|
||||
dependencies:
|
||||
app-root-path "^2.1.0"
|
||||
aria-query "^3.0.0"
|
||||
axobject-query "^2.0.2"
|
||||
css-selector-tokenizer "^0.7.1"
|
||||
cssauron "^1.4.0"
|
||||
damerau-levenshtein "^1.0.4"
|
||||
semver-dsl "^1.0.1"
|
||||
source-map "^0.5.7"
|
||||
sprintf-js "^1.1.2"
|
||||
|
||||
coffeescript@1.12.7:
|
||||
version "1.12.7"
|
||||
resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.12.7.tgz#e57ee4c4867cf7f606bfc4a0f2d550c0981ddd27"
|
||||
@@ -7590,7 +7542,7 @@ commander@7.1.0, commander@^7.0.0:
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-7.1.0.tgz#f2eaecf131f10e36e07d894698226e36ae0eb5ff"
|
||||
integrity sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==
|
||||
|
||||
commander@^2.11.0, commander@^2.12.1, commander@^2.19.0, commander@^2.20.0:
|
||||
commander@^2.12.1, commander@^2.19.0, commander@^2.20.0:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
@@ -8505,14 +8457,6 @@ css-select@^2.0.0, css-select@^2.0.2:
|
||||
domutils "^1.7.0"
|
||||
nth-check "^1.0.2"
|
||||
|
||||
css-selector-tokenizer@^0.7.1:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz#735f26186e67c749aaf275783405cf0661fae8f1"
|
||||
integrity sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
fastparse "^1.1.2"
|
||||
|
||||
css-to-react-native@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756"
|
||||
@@ -8572,13 +8516,6 @@ css@^3.0.0:
|
||||
source-map "^0.6.1"
|
||||
source-map-resolve "^0.6.0"
|
||||
|
||||
cssauron@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/cssauron/-/cssauron-1.4.0.tgz#a6602dff7e04a8306dc0db9a551e92e8b5662ad8"
|
||||
integrity sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=
|
||||
dependencies:
|
||||
through X.X.X
|
||||
|
||||
cssesc@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||
@@ -8853,7 +8790,7 @@ dagre@^0.8.5:
|
||||
graphlib "^2.1.8"
|
||||
lodash "^4.17.15"
|
||||
|
||||
damerau-levenshtein@^1.0.4, damerau-levenshtein@^1.0.6:
|
||||
damerau-levenshtein@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz#143c1641cb3d85c60c32329e26899adea8701791"
|
||||
integrity sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==
|
||||
@@ -9772,15 +9709,6 @@ engine.io@~3.2.0:
|
||||
engine.io-parser "~2.1.0"
|
||||
ws "~3.3.1"
|
||||
|
||||
enhanced-resolve@4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126"
|
||||
integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.1.2"
|
||||
memory-fs "^0.5.0"
|
||||
tapable "^1.0.0"
|
||||
|
||||
enhanced-resolve@5.7.0:
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz#525c5d856680fbd5052de453ac83e32049958b5c"
|
||||
@@ -10547,11 +10475,6 @@ fast-safe-stringify@2.0.7:
|
||||
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
|
||||
integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
|
||||
|
||||
fastparse@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
|
||||
integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858"
|
||||
@@ -16196,7 +16119,7 @@ open@7.4.0:
|
||||
is-docker "^2.0.0"
|
||||
is-wsl "^2.1.1"
|
||||
|
||||
open@^7.0.2, open@^7.0.3:
|
||||
open@^7.0.2, open@^7.0.3, open@^7.4.2:
|
||||
version "7.4.2"
|
||||
resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321"
|
||||
integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==
|
||||
@@ -19166,13 +19089,6 @@ rxjs@6.5.5:
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
rxjs@6.6.2:
|
||||
version "6.6.2"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2"
|
||||
integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
rxjs@6.6.3, rxjs@^6.5.0:
|
||||
version "6.6.3"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552"
|
||||
@@ -19416,13 +19332,6 @@ semver-diff@^2.0.0:
|
||||
dependencies:
|
||||
semver "^5.0.3"
|
||||
|
||||
semver-dsl@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/semver-dsl/-/semver-dsl-1.0.1.tgz#d3678de5555e8a61f629eed025366ae5f27340a0"
|
||||
integrity sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=
|
||||
dependencies:
|
||||
semver "^5.3.0"
|
||||
|
||||
semver-intersect@1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-intersect/-/semver-intersect-1.4.0.tgz#bdd9c06bedcdd2fedb8cd352c3c43ee8c61321f3"
|
||||
@@ -20059,11 +19968,6 @@ split@^1.0.0:
|
||||
dependencies:
|
||||
through "2"
|
||||
|
||||
sprintf-js@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
|
||||
integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
|
||||
|
||||
sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
@@ -20954,7 +20858,7 @@ through2@^4.0.0:
|
||||
dependencies:
|
||||
readable-stream "3"
|
||||
|
||||
through@2, "through@>=2.2.7 <3", through@X.X.X, through@^2.3.6:
|
||||
through@2, "through@>=2.2.7 <3", through@^2.3.6:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
||||
@@ -21305,11 +21209,6 @@ tsconfig-paths@^3.4.0, tsconfig-paths@^3.9.0:
|
||||
minimist "^1.2.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tsickle@^0.38.1:
|
||||
version "0.38.1"
|
||||
resolved "https://registry.yarnpkg.com/tsickle/-/tsickle-0.38.1.tgz#30762db759d40c435943093b6972c7f2efb384ef"
|
||||
integrity sha512-4xZfvC6+etRu6ivKCNqMOd1FqcY/m6JY3Y+yr5+Xw+i751ciwrWINi6x/3l1ekcODH9GZhlf0ny2LpzWxnjWYA==
|
||||
|
||||
tslib@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
|
||||
|
||||
Reference in New Issue
Block a user