feat(core): switch default config to v2

This commit is contained in:
Victor Savkin 2020-12-04 16:10:16 -05:00
parent 438d26b828
commit 8224a1029e
23 changed files with 347 additions and 267 deletions

View File

@ -17,6 +17,7 @@ describe('new config format', () => {
// update the angular.json
const workspaceJson = readJson(`angular.json`);
workspaceJson.version = 2;
workspaceJson.projects[myapp].targets = updateConfig(
workspaceJson.projects[myapp].architect
);
@ -34,9 +35,7 @@ function updateConfig(targets: any) {
const res = {};
Object.entries(targets).forEach(([name, t]: any) => {
t.executor = t.builder;
t.generators = t.schematics;
delete t.builder;
delete t.schematics;
res[name] = t;
});
return res;

View File

@ -0,0 +1,267 @@
import {
checkFilesExist,
newProject,
readFile,
runCLI,
supportUi,
tmpProjPath,
uniq,
} from '@nrwl/e2e/utils';
import { mkdirSync, writeFileSync } from 'fs';
describe('Storybook schematics', () => {
describe('build storybook', () => {
it('should execute e2e tests using Cypress running against Storybook', () => {
newProject();
const myapp = uniq('myapp');
runCLI(`generate @nrwl/angular:app ${myapp} --no-interactive`);
const mylib = uniq('test-ui-lib');
createTestUILib(mylib);
const mylib2 = uniq('test-ui-lib-react');
runCLI(`generate @nrwl/react:lib ${mylib2} --no-interactive`);
runCLI(
`generate @nrwl/react:component Button --project=${mylib2} --no-interactive`
);
writeFileSync(
tmpProjPath(`libs/${mylib2}/src/lib/button.tsx`),
`
import React from 'react';
import './button.css';
export type ButtonStyle = 'default' | 'primary' | 'warning';
/* eslint-disable-next-line */
export interface ButtonProps {
text?: string;
style?: ButtonStyle;
padding?: number;
}
export const Button = (props: ButtonProps) => {
return (
<button className={props.style} style={{ padding: \`\${props.padding}px\` }}>
{props.text}
</button>
);
};
export default Button;
`
);
writeFileSync(
tmpProjPath(`libs/${mylib2}/src/lib/button.stories.tsx`),
`
import React from 'react';
import { Button, ButtonStyle } from './button';
import { text, number } from '@storybook/addon-knobs';
export default { title: 'Button' };
export const primary = () => (
<Button
padding={number('Padding', 0)}
style={text('Style', 'default') as ButtonStyle}
text={text('Text', 'Click me')}
// padding='0'
// style='default'
// text='Click me'
/>
);
`
);
runCLI(
`generate @nrwl/angular:storybook-configuration ${mylib} --configureCypress --generateStories --generateCypressSpecs --no-interactive`
);
runCLI(
`generate @nrwl/angular:stories ${mylib} --generateCypressSpecs --no-interactive`
);
writeFileSync(
tmpProjPath(
`apps/${mylib}-e2e/src/integration/test-button/test-button.component.spec.ts`
),
`
describe('test-ui-lib3726865', () => {
it('should render the component', () => {
cy.visit('/iframe.html?id=testbuttoncomponent--primary&knob-buttonType=button&knob-style=default&knob-age&knob-isDisabled=false');
cy.get('proj-test-button').should('exist');
cy.get('button').should('not.be.disabled');
cy.get('button').should('have.class', 'default');
cy.contains('You are 0 years old.');
});
it('should adjust the knobs', () => {
cy.visit('/iframe.html?id=testbuttoncomponent--primary&knob-buttonType=button&knob-style=primary&knob-age=10&knob-isDisabled=true');
cy.get('button').should('be.disabled');
cy.get('button').should('have.class', 'primary');
cy.contains('You are 10 years old.');
});
});
`
);
runCLI(
`generate @nrwl/react:storybook-configuration ${mylib2} --configureCypress --no-interactive`
);
mkdirSync(tmpProjPath(`apps/${mylib2}-e2e/src/integration`));
writeFileSync(
tmpProjPath(`apps/${mylib2}-e2e/src/integration/button.spec.ts`),
`
describe('react-ui', () => {
it('should render the component', () => {
cy.visit(
'/iframe.html?id=button--primary&knob-Style=default&knob-Padding&knob-Text=Click%20me'
);
cy.get('button').should('exist');
cy.get('button').should('have.class', 'default');
});
it('should adjust the knobs', () => {
cy.visit(
'/iframe.html?id=button--primary&knob-Style=primary&knob-Padding=10&knob-Text=Other'
);
cy.get('button').should('have.class', 'primary');
});
});
`
);
if (supportUi()) {
expect(runCLI(`run ${mylib}-e2e:e2e --no-watch`)).toContain(
'All specs passed!'
);
}
runCLI(`run ${mylib}:build-storybook`);
checkFilesExist(`dist/storybook/${mylib}/index.html`);
expect(readFile(`dist/storybook/${mylib}/index.html`)).toContain(
`<title>Storybook</title>`
);
}, 1000000);
it('should build an Angular based storybook', () => {
newProject();
const angularStorybookLib = uniq('test-ui-lib');
createTestUILib(angularStorybookLib);
runCLI(
`generate @nrwl/angular:storybook-configuration ${angularStorybookLib} --generateStories --no-interactive`
);
// build Angular lib
runCLI(`run ${angularStorybookLib}:build-storybook`);
checkFilesExist(`dist/storybook/${angularStorybookLib}/index.html`);
expect(
readFile(`dist/storybook/${angularStorybookLib}/index.html`)
).toContain(`<title>Storybook</title>`);
}, 1000000);
it('should build an Angular based storybook that references another lib', () => {
newProject();
const angularStorybookLib = uniq('test-ui-lib');
createTestUILib(angularStorybookLib);
runCLI(
`generate @nrwl/angular:storybook-configuration ${angularStorybookLib} --generateStories --no-interactive`
);
// create another lib with a component
const anotherTestLib = uniq('test-another-lib');
runCLI(`g @nrwl/angular:library ${anotherTestLib} --no-interactive`);
runCLI(
`g @nrwl/angular:component my-test-cmp --project=${anotherTestLib} --no-interactive`
);
// update index.ts and export it
writeFileSync(
tmpProjPath(`libs/${anotherTestLib}/src/index.ts`),
`
export * from './lib/my-test-cmp/my-test-cmp.component';
`
);
// create a story in the first lib to reference the cmp from the 2nd lib
writeFileSync(
tmpProjPath(
`libs/${angularStorybookLib}/src/lib/myteststory.stories.ts`
),
`
import { MyTestCmpComponent } from '@proj/${anotherTestLib}';
export default {
title: 'My Test Cmp',
};
let x = 'hi';
export const primary = () => ({
moduleMetadata: {
imports: [],
},
component: MyTestCmpComponent,
props: {},
});
`
);
// build Angular lib
runCLI(`run ${angularStorybookLib}:build-storybook`);
checkFilesExist(`dist/storybook/${angularStorybookLib}/index.html`);
expect(
readFile(`dist/storybook/${angularStorybookLib}/index.html`)
).toContain(`<title>Storybook</title>`);
}, 1000000);
});
});
export function createTestUILib(libName: string): void {
runCLI(`g @nrwl/angular:library ${libName} --no-interactive`);
runCLI(
`g @nrwl/angular:component test-button --project=${libName} --no-interactive`
);
writeFileSync(
tmpProjPath(`libs/${libName}/src/lib/test-button/test-button.component.ts`),
`
import { Component, OnInit, Input } from '@angular/core';
export type ButtonStyle = 'default' | 'primary' | 'accent';
@Component({
selector: 'proj-test-button',
templateUrl: './test-button.component.html',
styleUrls: ['./test-button.component.css']
})
export class TestButtonComponent implements OnInit {
@Input('buttonType') type = 'button';
@Input() style: ButtonStyle = 'default';
@Input() age: number;
@Input() isDisabled = false;
constructor() { }
ngOnInit() {
}
}
`
);
writeFileSync(
tmpProjPath(
`libs/${libName}/src/lib/test-button/test-button.component.html`
),
`
<button [disabled]="isDisabled" [attr.type]="type" [ngClass]="style">Click me</button>
<p>You are {{age}} years old.</p>
`
);
runCLI(
`g @nrwl/angular:component test-other --project=${libName} --no-interactive`
);
}

View File

@ -12,7 +12,7 @@ import {
} from '@nrwl/e2e/utils';
describe('Help', () => {
it('should show help', async () => {
it('gggshould show help', async () => {
newProject();
const myapp = uniq('myapp');
runCLI(`generate @nrwl/web:app ${myapp}`);

View File

@ -77,8 +77,8 @@ describe('Linter', () => {
// This test is only relevant for the deprecated lint builder,
// so we need to patch the workspace.json to use it
const workspaceJson = readJson(`workspace.json`);
workspaceJson.projects[myapp].architect.lint = {
builder: '@nrwl/linter:lint',
workspaceJson.projects[myapp].targets.lint = {
executor: '@nrwl/linter:lint',
options: {
linter: 'eslint',
tsConfig: [

View File

@ -282,7 +282,7 @@ describe('Node Libraries', () => {
`generate @nrwl/angular:lib ${nglib} --publishable --importPath=@proj/${nglib}`
);
const workspace = readJson(workspaceConfigName());
workspace.projects[nodelib].architect.build.options.assets.push({
workspace.projects[nodelib].targets.build.options.assets.push({
input: `./dist/libs/${nglib}`,
glob: '**/*',
output: '.',

View File

@ -88,7 +88,7 @@ describe('Build React libraries and apps', () => {
// Add assets to child lib
updateFile('workspace.json', (c) => {
const json = JSON.parse(c);
json.projects[childLib].architect.build.options.assets = [
json.projects[childLib].targets.build.options.assets = [
`libs/${childLib}/src/assets`,
];
return JSON.stringify(json, null, 2);

View File

@ -53,7 +53,7 @@ describe('React Applications', () => {
// Turn vendor sourcemaps on
updateFile(`workspace.json`, (content) => {
const json = JSON.parse(content);
json.projects[appName].architect.build.options.sourceMap = {
json.projects[appName].targets.build.options.sourceMap = {
scripts: true,
vendor: true,
};
@ -314,10 +314,10 @@ describe('React Applications', () => {
angularJson.projects[
appName
].architect.build.options.main = `apps/${appName}/src/main.jsx`;
].targets.build.options.main = `apps/${appName}/src/main.jsx`;
angularJson.projects[
appName
].architect.build.options.polyfills = `apps/${appName}/src/polyfills.js`;
].targets.build.options.polyfills = `apps/${appName}/src/polyfills.js`;
updateFile(workspaceConfigName(), serializeJson(angularJson));
const mainPath = `apps/${appName}/src/main.jsx`;

View File

@ -3,166 +3,13 @@ import {
newProject,
readFile,
runCLI,
supportUi,
tmpProjPath,
uniq,
} from '@nrwl/e2e/utils';
import { mkdirSync, writeFileSync } from 'fs';
import { writeFileSync } from 'fs';
describe('Storybook schematics', () => {
describe('running Storybook and Cypress', () => {
it('should execute e2e tests using Cypress running against Storybook', () => {
newProject();
const myapp = uniq('myapp');
runCLI(`generate @nrwl/angular:app ${myapp} --no-interactive`);
const mylib = uniq('test-ui-lib');
createTestUILib(mylib);
const mylib2 = uniq('test-ui-lib-react');
runCLI(`generate @nrwl/react:lib ${mylib2} --no-interactive`);
runCLI(
`generate @nrwl/react:component Button --project=${mylib2} --no-interactive`
);
writeFileSync(
tmpProjPath(`libs/${mylib2}/src/lib/button.tsx`),
`
import React from 'react';
import './button.css';
export type ButtonStyle = 'default' | 'primary' | 'warning';
/* eslint-disable-next-line */
export interface ButtonProps {
text?: string;
style?: ButtonStyle;
padding?: number;
}
export const Button = (props: ButtonProps) => {
return (
<button className={props.style} style={{ padding: \`\${props.padding}px\` }}>
{props.text}
</button>
);
};
export default Button;
`
);
writeFileSync(
tmpProjPath(`libs/${mylib2}/src/lib/button.stories.tsx`),
`
import React from 'react';
import { Button, ButtonStyle } from './button';
import { text, number } from '@storybook/addon-knobs';
export default { title: 'Button' };
export const primary = () => (
<Button
padding={number('Padding', 0)}
style={text('Style', 'default') as ButtonStyle}
text={text('Text', 'Click me')}
// padding='0'
// style='default'
// text='Click me'
/>
);
`
);
runCLI(
`generate @nrwl/angular:storybook-configuration ${mylib} --configureCypress --generateStories --generateCypressSpecs --no-interactive`
);
runCLI(
`generate @nrwl/angular:stories ${mylib} --generateCypressSpecs --no-interactive`
);
writeFileSync(
tmpProjPath(
`apps/${mylib}-e2e/src/integration/test-button/test-button.component.spec.ts`
),
`
describe('test-ui-lib3726865', () => {
it('should render the component', () => {
cy.visit('/iframe.html?id=testbuttoncomponent--primary&knob-buttonType=button&knob-style=default&knob-age&knob-isDisabled=false');
cy.get('proj-test-button').should('exist');
cy.get('button').should('not.be.disabled');
cy.get('button').should('have.class', 'default');
cy.contains('You are 0 years old.');
});
it('should adjust the knobs', () => {
cy.visit('/iframe.html?id=testbuttoncomponent--primary&knob-buttonType=button&knob-style=primary&knob-age=10&knob-isDisabled=true');
cy.get('button').should('be.disabled');
cy.get('button').should('have.class', 'primary');
cy.contains('You are 10 years old.');
});
});
`
);
runCLI(
`generate @nrwl/react:storybook-configuration ${mylib2} --configureCypress --no-interactive`
);
mkdirSync(tmpProjPath(`apps/${mylib2}-e2e/src/integration`));
writeFileSync(
tmpProjPath(`apps/${mylib2}-e2e/src/integration/button.spec.ts`),
`
describe('react-ui', () => {
it('should render the component', () => {
cy.visit(
'/iframe.html?id=button--primary&knob-Style=default&knob-Padding&knob-Text=Click%20me'
);
cy.get('button').should('exist');
cy.get('button').should('have.class', 'default');
});
it('should adjust the knobs', () => {
cy.visit(
'/iframe.html?id=button--primary&knob-Style=primary&knob-Padding=10&knob-Text=Other'
);
cy.get('button').should('have.class', 'primary');
});
});
`
);
if (supportUi()) {
expect(runCLI(`run ${mylib}-e2e:e2e --no-watch`)).toContain(
'All specs passed!'
);
}
runCLI(`run ${mylib}:build-storybook`);
checkFilesExist(`dist/storybook/${mylib}/index.html`);
expect(readFile(`dist/storybook/${mylib}/index.html`)).toContain(
`<title>Storybook</title>`
);
}, 1000000);
});
describe('build storybook', () => {
it('should build an Angular based storybook', () => {
newProject();
const angularStorybookLib = uniq('test-ui-lib');
createTestUILib(angularStorybookLib);
runCLI(
`generate @nrwl/angular:storybook-configuration ${angularStorybookLib} --generateStories --no-interactive`
);
// build Angular lib
runCLI(`run ${angularStorybookLib}:build-storybook`);
checkFilesExist(`dist/storybook/${angularStorybookLib}/index.html`);
expect(
readFile(`dist/storybook/${angularStorybookLib}/index.html`)
).toContain(`<title>Storybook</title>`);
}, 1000000);
it('should build a React based storybook', () => {
newProject();
@ -250,62 +97,6 @@ describe('Storybook schematics', () => {
readFile(`dist/storybook/${reactStorybookLib}/index.html`)
).toContain(`<title>Storybook</title>`);
}, 1000000);
it('should build an Angular based storybook that references another lib', () => {
newProject();
const angularStorybookLib = uniq('test-ui-lib');
createTestUILib(angularStorybookLib);
runCLI(
`generate @nrwl/angular:storybook-configuration ${angularStorybookLib} --generateStories --no-interactive`
);
// create another lib with a component
const anotherTestLib = uniq('test-another-lib');
runCLI(`g @nrwl/angular:library ${anotherTestLib} --no-interactive`);
runCLI(
`g @nrwl/angular:component my-test-cmp --project=${anotherTestLib} --no-interactive`
);
// update index.ts and export it
writeFileSync(
tmpProjPath(`libs/${anotherTestLib}/src/index.ts`),
`
export * from './lib/my-test-cmp/my-test-cmp.component';
`
);
// create a story in the first lib to reference the cmp from the 2nd lib
writeFileSync(
tmpProjPath(
`libs/${angularStorybookLib}/src/lib/myteststory.stories.ts`
),
`
import { MyTestCmpComponent } from '@proj/${anotherTestLib}';
export default {
title: 'My Test Cmp',
};
let x = 'hi';
export const primary = () => ({
moduleMetadata: {
imports: [],
},
component: MyTestCmpComponent,
props: {},
});
`
);
// build Angular lib
runCLI(`run ${angularStorybookLib}:build-storybook`);
checkFilesExist(`dist/storybook/${angularStorybookLib}/index.html`);
expect(
readFile(`dist/storybook/${angularStorybookLib}/index.html`)
).toContain(`<title>Storybook</title>`);
}, 1000000);
});
});

View File

@ -16,7 +16,7 @@ describe('file-server', () => {
runCLI(`generate @nrwl/web:app ${appName} --no-interactive`);
const workspaceJson = readJson(workspaceConfigName());
workspaceJson.projects[appName].architect['serve'].builder =
workspaceJson.projects[appName].targets['serve'].executor =
'@nrwl/web:file-server';
updateFile(workspaceConfigName(), serializeJson(workspaceJson));

View File

@ -10,7 +10,7 @@ import {
} from '@nrwl/e2e/utils';
describe('custom workspace layout', () => {
it('should work', async () => {
it('vvvshould work', async () => {
const proj = uniq('custom-layout-proj');
runCreateWorkspace(proj, { preset: 'oss' });
yarnAdd('@nrwl/react @nrwl/angular @nrwl/express');

View File

@ -42,8 +42,8 @@ describe('Run Commands', () => {
runCLI(`generate @nrwl/web:app ${myapp}`);
const config = readJson(workspaceConfigName());
config.projects[myapp].architect.echo = {
builder: '@nrwl/workspace:run-commands',
config.projects[myapp].targets.echo = {
executor: '@nrwl/workspace:run-commands',
options: {
commands: [`echo 'print: {args.var1}'`, `echo 'print: {args.var2}'`],
},

View File

@ -532,6 +532,7 @@ describe('Move Angular Project', () => {
let newPath: string;
beforeEach(() => {
newProject();
app1 = uniq('app1');
app2 = uniq('app2');
newPath = `subfolder/${app2}`;
@ -659,6 +660,7 @@ describe('Move Project', () => {
* Tries moving a library from ${lib}/data-access -> shared/${lib}/data-access
*/
it('should work for libraries', () => {
newProject();
const lib1 = uniq('mylib');
const lib2 = uniq('mylib');
const lib3 = uniq('mylib');
@ -778,7 +780,7 @@ describe('Move Project', () => {
expect(project).toBeTruthy();
expect(project.root).toBe(newPath);
expect(project.sourceRoot).toBe(`${newPath}/src`);
expect(project.architect.lint.options.lintFilePatterns).toEqual([
expect(project.targets.lint.options.lintFilePatterns).toEqual([
`libs/shared/${lib1}/data-access/**/*.ts`,
]);
@ -793,6 +795,7 @@ describe('Move Project', () => {
});
it('should work for libs created with --importPath', () => {
newProject();
const importPath = '@wibble/fish';
const lib1 = uniq('mylib');
const lib2 = uniq('mylib');
@ -915,7 +918,8 @@ describe('Move Project', () => {
expect(project).toBeTruthy();
expect(project.root).toBe(newPath);
expect(project.sourceRoot).toBe(`${newPath}/src`);
expect(project.architect.lint.options.lintFilePatterns).toEqual([
expect(project.targets.lint.options.lintFilePatterns).toEqual([
`libs/shared/${lib1}/data-access/**/*.ts`,
]);
@ -930,6 +934,7 @@ describe('Move Project', () => {
});
it('should work for custom workspace layouts', () => {
newProject();
const lib1 = uniq('mylib');
const lib2 = uniq('mylib');
const lib3 = uniq('mylib');
@ -1054,7 +1059,7 @@ describe('Move Project', () => {
expect(project).toBeTruthy();
expect(project.root).toBe(newPath);
expect(project.sourceRoot).toBe(`${newPath}/src`);
expect(project.architect.lint.options.lintFilePatterns).toEqual([
expect(project.targets.lint.options.lintFilePatterns).toEqual([
`packages/shared/${lib1}/data-access/**/*.ts`,
]);
@ -1078,6 +1083,7 @@ describe('Remove Project', () => {
* Tries creating then deleting a lib
*/
it('should work', () => {
newProject();
const lib1 = uniq('mylib');
const lib2 = uniq('mylib');

View File

@ -685,11 +685,11 @@ describe('cache', () => {
// Update outputs in workspace.json to just be a particular file
const workspaceJson = readJson(workspaceConfigName());
workspaceJson.projects[mylib1].architect['build-base'] = {
...workspaceJson.projects[mylib1].architect.build,
workspaceJson.projects[mylib1].targets['build-base'] = {
...workspaceJson.projects[mylib1].targets.build,
};
workspaceJson.projects[mylib1].architect.build = {
builder: '@nrwl/workspace:run-commands',
workspaceJson.projects[mylib1].targets.build = {
executor: '@nrwl/workspace:run-commands',
outputs: [`dist/libs/${mylib1}/${mylib1}.esm.js`],
options: {
commands: [

View File

@ -1,6 +1,6 @@
{
"name": "@nrwl/nx-source",
"version": "10.4.4",
"version": "11.0.0-beta.12",
"description": "Extensible Dev Tools for Monorepos",
"homepage": "https://nx.dev",
"main": "index.js",

View File

@ -1 +1,4 @@
export { wrapAngularDevkitSchematic } from '@nrwl/tao/src/commands/ngcli-adapter';
export {
wrapAngularDevkitSchematic,
NxScopedHost,
} from '@nrwl/tao/src/commands/ngcli-adapter';

View File

@ -1,21 +1,21 @@
import { BuilderContext, createBuilder } from '@angular-devkit/architect';
import { JsonObject, workspaces } from '@angular-devkit/core';
import { runWebpack, BuildResult } from '@angular-devkit/build-webpack';
import { JsonObject, normalize, workspaces } from '@angular-devkit/core';
import { BuildResult, runWebpack } from '@angular-devkit/build-webpack';
import { Observable, from, of } from 'rxjs';
import { from, Observable } from 'rxjs';
import { join, resolve } from 'path';
import { concatMap, map, tap } from 'rxjs/operators';
import { getNodeWebpackConfig } from '../../utils/node.config';
import { OUT_FILENAME } from '../../utils/config';
import { BuildNodeBuilderOptions } from '../../utils/types';
import { normalizeBuildOptions } from '../../utils/normalize';
import { NodeJsSyncHost } from '@angular-devkit/core/node';
import { createProjectGraph } from '@nrwl/workspace/src/core/project-graph';
import {
calculateProjectDependencies,
checkDependentProjectsHaveBeenBuilt,
createTmpTsConfig,
} from '@nrwl/workspace/src/utils/buildable-libs-utils';
import { NxScopedHost } from '@nrwl/devkit/ngcli-adapter';
import { generatePackageJson } from '../../utils/generate-package-json';
try {
@ -100,11 +100,10 @@ function run(
async function getRoots(
context: BuilderContext
): Promise<{ sourceRoot: string; projectRoot: string }> {
const workspaceHost = workspaces.createWorkspaceHost(new NodeJsSyncHost());
const { workspace } = await workspaces.readWorkspace(
context.workspaceRoot,
workspaceHost
const workspaceHost = workspaces.createWorkspaceHost(
new NxScopedHost(normalize(context.workspaceRoot))
);
const { workspace } = await workspaces.readWorkspace('', workspaceHost);
const project = workspace.projects.get(context.target.project);
if (project.sourceRoot && project.root) {
return { sourceRoot: project.sourceRoot, projectRoot: project.root };

View File

@ -46,6 +46,7 @@ describe('Update 8-5-0', () => {
const config = readWorkspace(tree);
expect(config).toEqual({
version: 1,
schematics: {
'@nrwl/react': {
application: {},

View File

@ -110,8 +110,7 @@ async function findOrCreateConfig(
config.srcRoot
);
} else {
const host = new NodeJsSyncHost();
const sourceRoot = await getRoot(context, host);
const sourceRoot = await getRoot(context);
if (
statSync(
join(context.workspaceRoot, sourceRoot, '.storybook')

View File

@ -96,8 +96,7 @@ async function findOrCreateConfig(
config: StorybookConfig,
context: BuilderContext
): Promise<string> {
const host = new NodeJsSyncHost();
const sourceRoot = await getRoot(context, host);
const sourceRoot = await getRoot(context);
if (config.configFolder && statSync(config.configFolder).isDirectory()) {
return config.configFolder;

View File

@ -1,13 +1,12 @@
import { BuilderContext } from '@angular-devkit/architect';
import { workspaces } from '@angular-devkit/core';
import { Host } from '@angular-devkit/core/src/virtual-fs/host';
import { normalize, workspaces } from '@angular-devkit/core';
import { NxScopedHost } from '@nrwl/devkit/ngcli-adapter';
export async function getRoot(context: BuilderContext, host: Host<{}>) {
const workspaceHost = workspaces.createWorkspaceHost(host);
const { workspace } = await workspaces.readWorkspace(
context.workspaceRoot,
workspaceHost
export async function getRoot(context: BuilderContext) {
const workspaceHost = workspaces.createWorkspaceHost(
new NxScopedHost(normalize(context.workspaceRoot))
);
const { workspace } = await workspaces.readWorkspace('', workspaceHost);
if (workspace.projects.get(context.target.project).root) {
return workspace.projects.get(context.target.project).root;
} else {

View File

@ -255,7 +255,7 @@ class MigrationsWorkflow extends BaseWorkflow {
}
}
class NxScopedHost extends virtualFs.ScopedHost<any> {
export class NxScopedHost extends virtualFs.ScopedHost<any> {
constructor(root: Path) {
super(new NodeJsSyncHost(), root);
}

View File

@ -127,27 +127,25 @@ export class Workspaces {
let formatted = false;
Object.values(w.projects || {}).forEach((project: any) => {
if (project.architect) {
project.targets = project.architect;
delete project.architect;
renameProperty(project, 'architect', 'targets');
formatted = true;
}
Object.values(project.targets || {}).forEach((target: any) => {
if (target.builder) {
target.executor = target.builder;
delete target.builder;
renameProperty(target, 'builder', 'executor');
formatted = true;
}
});
});
if (w.schematics) {
w.generators = w.schematics;
delete w.schematics;
renameProperty(w, 'schematics', 'generators');
formatted = true;
}
if (formatted) {
if (w.version !== 2) {
w.version = 2;
formatted = true;
}
return formatted ? w : null;
}
@ -156,27 +154,25 @@ export class Workspaces {
let formatted = false;
Object.values(w.projects || {}).forEach((project: any) => {
if (project.targets) {
project.architect = project.targets;
delete project.targets;
renameProperty(project, 'targets', 'architect');
formatted = true;
}
Object.values(project.architect || {}).forEach((target: any) => {
if (target.executor) {
target.builder = target.executor;
delete target.executor;
renameProperty(target, 'executor', 'builder');
formatted = true;
}
});
});
if (w.generators) {
w.schematics = w.generators;
delete w.generators;
renameProperty(w, 'generators', 'schematics');
formatted = true;
}
if (formatted) {
if (w.version !== 1) {
w.version = 1;
formatted = true;
}
return formatted ? w : null;
}
@ -311,3 +307,19 @@ export class Workspaces {
return { generatorsFilePath, generatorsJson, normalizedGeneratorName };
}
}
// we have to do it this way to preserve the order of properties
// not to screw up the formatting
function renameProperty(obj: any, from: string, to: string) {
const copy = { ...obj };
Object.keys(obj).forEach((k) => {
delete obj[k];
});
Object.keys(copy).forEach((k) => {
if (k === from) {
obj[to] = copy[k];
} else {
obj[k] = copy[k];
}
});
}

View File

@ -1,5 +1,10 @@
{
<% if(cli === 'angular') { %>
"version": 1,
<% } %>
<% if(cli === 'nx') { %>
"version": 2,
<% } %>
"projects": {},
"cli": {
"defaultCollection": "@nrwl/workspace"