Compare commits

...

26 Commits

Author SHA1 Message Date
Jason Jean c439504326 Release 12.0.7 2021-04-16 17:08:32 -04:00
vsavkin 5cf27c611e cleanup(misc): require ejs lazily to speed up load time 2021-04-16 10:30:53 -04:00
Tuan Dang 7017669e52 fix(storybook): generate story file in new jsx transform (#5369)
fix(storybook): generate story file in new jsx transform
2021-04-16 10:30:53 -04:00
Phillip Barta 51e99541cf chore(repo): updated dependency 'strip-json-comments' 2021-04-16 10:30:30 -04:00
Divlo b15dd237fc fix(storybook): incorrect environment in dev (#5313) 2021-04-16 10:30:30 -04:00
Phillip Barta 704c3b7b43 cleanup(repo): removed unused dependecies from @nrwl/web migration in #2004 (#5344) 2021-04-16 10:29:27 -04:00
Tuan Dang 6a17abb7b0 fix(react): fix react publish library copy readme (#5345) 2021-04-16 10:29:27 -04:00
Phillip Barta b0151f8b50 cleanup(repo): updated dependency 'tmp' (#5340) 2021-04-16 10:29:26 -04:00
Phillip Barta d9d7db8311 cleanup(repo): replaced deprecated opn package with open (#5236) 2021-04-16 10:28:46 -04:00
Jason Jean 342b42b78f fix(devkit): add env variable to disable project graph cache (#5297) 2021-04-15 10:49:21 -04:00
Jason Jean f4c59dc96f fix(core): throw an error if generating a new workspace into a non-empty directory (#5296) 2021-04-15 10:48:58 -04:00
Bruno Baia 1025d8a341 fix(nx-plugin): fix package name when generating generators (#5320) 2021-04-14 21:43:20 -04:00
Juri f8adb9ca04 fix(devkit): devkitTreeFromAngularDevkitTree exists function should also work on dirs
ISSUES CLOSED: #5318
2021-04-14 21:42:54 -04:00
Jason Jean 167c65a4a8 feat(core): allow passing a path into read workspace config (#5337) 2021-04-14 21:41:59 -04:00
Jason Jean ba0a94a84d fix(repo): clear output before building packages again (#5342) 2021-04-14 15:29:35 -04:00
Jason Jean d03423df9a Release 12.0.6 2021-04-14 15:07:51 -04:00
Jason Jean b232f8a2c8 Release 12.0.5 2021-04-14 13:41:39 -04:00
Jason Jean df8060204a Revert "cleanup(core): copy from cache only when needed"
This reverts commit 4dac0a2122.
2021-04-14 13:25:19 -04:00
Jason Jean 73ba102207 Release 12.0.4 2021-04-13 18:32:02 -04:00
Craigory V Coppola b9d4cbb474 fix(core): Wrap head + base arguments in quotes in execSyn (#5240)
On windows caret symbols are removed from command line args unless wrapped in double quotes, causing an error in this case.

Closes #4828.
2021-04-13 16:51:33 -04:00
Stuart Taylor 9bea63171c fix(core): allow building of workspaces when hosted at / (#5252)
Building a project in the node:14-alpine docker image requires the workspace to be copied in
to directory other than /.
The proposed change allows workspaces to be hosted at / and not force the developer to create a directory inside a docker image just to build the project.

Co-authored-by: Stuart Taylor <stuart@chargifi.com>
2021-04-13 16:51:33 -04:00
Phillip Barta 25143296b4 cleanup(repo): removed leftover angular dependencies (#5326)
removed tsickle, codelyzer and @ngtools/webpack
2021-04-13 16:51:32 -04:00
Jack Hsu 15fcbbae2b fix(react): generate apps/libs using Emotion CSS with valid .babelrc files (#5336) 2021-04-13 16:51:32 -04:00
Jason Jean a1fe84b66c Release 12.0.2 2021-04-12 17:22:50 -04:00
Kirils L ebf969390e fix(nextjs): remove isServer flag from web babel preset (#5322) 2021-04-12 16:05:47 -04:00
Philip Fulcher b4dbb6b1c9 fix(misc): fix grouping problem in dep-graph client (#5279) 2021-04-12 16:05:47 -04:00
70 changed files with 54267 additions and 18298 deletions
@@ -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', () => {
+5 -4
View File
@@ -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 {
+6 -1
View File
@@ -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);
+13
View File
@@ -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,
};
});
}
}
+30
View File
@@ -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);
}
);
});
+24
View File
@@ -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;
}
+5
View File
@@ -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;
};
}
}
+27 -16
View File
@@ -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
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',
+1
View File
@@ -60,5 +60,6 @@
window.filteredProjects = [];
window.groupByFolder = false;
window.exclude = [];
window.workspaceLayout = null;
</script>
</body>
+3 -2
View File
@@ -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));
+2 -1
View File
@@ -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"]
+43 -21
View File
@@ -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`.
+36
View File
@@ -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');
+37 -2
View File
@@ -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);
+11 -35
View File
@@ -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
View File
@@ -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",
@@ -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
+5 -5
View File
@@ -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));
}
-1
View File
@@ -27,7 +27,6 @@
},
"homepage": "https://nx.dev",
"dependencies": {
"tmp": "0.0.33",
"yargs": "15.4.1",
"yargs-parser": "20.0.0",
"@nrwl/tao": "*",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
-1
View File
@@ -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",
+1 -1
View File
@@ -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 {
+1 -1
View File
@@ -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"
}
}
+1 -1
View File
@@ -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"
}
}
-1
View File
@@ -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"
}
-1
View File
@@ -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(
`
+6 -7
View File
@@ -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
+1 -3
View File
@@ -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 });
}
+2 -2
View File
@@ -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",
+1 -4
View File
@@ -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.
+1 -15
View File
@@ -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/');
});
});
});
+2 -4
View File
@@ -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,
+3 -3
View File
@@ -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[] {
+15 -10
View File
@@ -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);
}
+3 -12
View File
@@ -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();
+1 -1
View File
@@ -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
+1
View File
@@ -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
+12 -113
View File
@@ -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"