feat(core): consolidate nx.json and workspace.json (#6642)

* feat(core): consolidate settings between workspace.json + nx.json

workspace.json (and linked project.json files) now contain all project specific settings.
nx.json now contains all settings that affect the whole workspace.

* chore(core): fix angular unit tests w/ new config

* chore(core): fix failing tests

* chore(core): fix formatting

* chore(core): fix more tests

* chore(core): normalize-nx-json feedback

* chore(core): Fix more unit tests

* chore(core): fix remaining tests in workspace

* chore(linter): fix remaining linter tests

* chore(core): fix remaining spec + build issues

* chore(core): formatting fixes

* feat(core): migration script to move config options to new locations

* chore(core): fix e2e tests

* chore(core): run format

* chore(react-native): fix failing tests

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* feat(core): move properties to new location during format step

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* feat(core): initial pass on ngcli-adapter for property consolidation

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* chore(misc): fix tests

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* docs(core): update docs with changes

* chore(misc): fix tests

* chore(core): code review changes

updateWorkspaceJson -> updateWorkspace, no longer uses updater function

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* chore(core): fix bug in ngcli impl

* fix(core): fix bug in ngcli-adapter

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* fix(core): fix ngcli-adapter

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* chore(core): fix workspace e2e

* chore(core): fix nx-plugin e2e

* fix(core): move defaultProject to nx.json

* chore(core): fix broken workspace test

* chore(core): formatting

* chore(core): fix workspace format

* chore(core): add nxJson to ExecutorContext

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* chore(core): remove all references ot `NxProjectConfiguration` from our code

* chore(core): Review Changes

* fix(core): update new config locations v13 migration
This commit is contained in:
Craigory Coppola 2021-10-14 09:42:47 -05:00 committed by GitHub
parent 0a9b8e5a44
commit 79cf69b4e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
137 changed files with 1411 additions and 1709 deletions

View File

@ -346,7 +346,7 @@ It only uses language primitives and immutable objects
### WorkspaceConfiguration
Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../angular/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<`Omit`<[`NxJsonConfiguration`](../../angular/nx-devkit/index#nxjsonconfiguration), `"projects"`\>\>
Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../angular/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<[`NxJsonConfiguration`](../../angular/nx-devkit/index#nxjsonconfiguration)\>
---
@ -549,17 +549,17 @@ Callback to install dependencies only if necessary. undefined is returned if cha
Adds project configuration to the Nx workspace.
The project configuration is stored in workspace.json and nx.json. The utility will update
both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will update either files.
#### Parameters
| Name | Type | Default value | Description |
| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------ | :----------------------------------------------------------------------------------------- |
| `tree` | [`Tree`](../../angular/nx-devkit/index#tree) | `undefined` | the file system tree |
| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration) | `undefined` | project configuration |
| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json |
| Name | Type | Default value | Description |
| :--------------------- | :--------------------------------------------------------------------------- | :------------ | :----------------------------------------------------------------------------------------- |
| `tree` | [`Tree`](../../angular/nx-devkit/index#tree) | `undefined` | the file system tree |
| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) | `undefined` | project configuration |
| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json |
#### Returns
@ -808,7 +808,7 @@ but it can also be passed in explicitly.
### getProjects
**getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration)\>
**getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration)\>
Get a map of all projects in a workspace.
@ -822,7 +822,7 @@ Use [readProjectConfiguration](../../angular/nx-devkit/index#readprojectconfigur
#### Returns
`Map`<`string`, [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration)\>
`Map`<`string`, [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration)\>
---
@ -1135,12 +1135,12 @@ Object the JSON content of the file represents
### readProjectConfiguration
**readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration)
**readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration)
Reads a project configuration.
The project configuration is stored in workspace.json and nx.json. The utility will read
both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will read from either file.
**`throws`** If supplied projectName cannot be found
@ -1153,7 +1153,7 @@ both files.
#### Returns
[`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration)
[`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration)
---
@ -1241,8 +1241,8 @@ Callback to uninstall dependencies only if necessary. undefined is returned if c
Removes the configuration of an existing project.
The project configuration is stored in workspace.json and nx.json.
The utility will update both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will update either file.
#### Parameters
@ -1460,16 +1460,16 @@ Updates a JSON value to the file system tree
Updates the configuration of an existing project.
The project configuration is stored in workspace.json and nx.json. The utility will update
both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will update either files.
#### Parameters
| Name | Type | Description |
| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------- |
| `tree` | [`Tree`](../../angular/nx-devkit/index#tree) | the file system tree |
| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../angular/nx-devkit/index#nxjsonprojectconfiguration) | project configuration |
| Name | Type | Description |
| :--------------------- | :--------------------------------------------------------------------------- | :---------------------------------------------------------------------- |
| `tree` | [`Tree`](../../angular/nx-devkit/index#tree) | the file system tree |
| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../angular/nx-devkit/index#projectconfiguration) | project configuration |
#### Returns

View File

@ -346,7 +346,7 @@ It only uses language primitives and immutable objects
### WorkspaceConfiguration
Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../node/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<`Omit`<[`NxJsonConfiguration`](../../node/nx-devkit/index#nxjsonconfiguration), `"projects"`\>\>
Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../node/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<[`NxJsonConfiguration`](../../node/nx-devkit/index#nxjsonconfiguration)\>
---
@ -549,17 +549,17 @@ Callback to install dependencies only if necessary. undefined is returned if cha
Adds project configuration to the Nx workspace.
The project configuration is stored in workspace.json and nx.json. The utility will update
both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will update either files.
#### Parameters
| Name | Type | Default value | Description |
| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------ | :----------------------------------------------------------------------------------------- |
| `tree` | [`Tree`](../../node/nx-devkit/index#tree) | `undefined` | the file system tree |
| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration) | `undefined` | project configuration |
| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json |
| Name | Type | Default value | Description |
| :--------------------- | :------------------------------------------------------------------------ | :------------ | :----------------------------------------------------------------------------------------- |
| `tree` | [`Tree`](../../node/nx-devkit/index#tree) | `undefined` | the file system tree |
| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) | `undefined` | project configuration |
| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json |
#### Returns
@ -808,7 +808,7 @@ but it can also be passed in explicitly.
### getProjects
**getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration)\>
**getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration)\>
Get a map of all projects in a workspace.
@ -822,7 +822,7 @@ Use [readProjectConfiguration](../../node/nx-devkit/index#readprojectconfigurati
#### Returns
`Map`<`string`, [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration)\>
`Map`<`string`, [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration)\>
---
@ -1135,12 +1135,12 @@ Object the JSON content of the file represents
### readProjectConfiguration
**readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration)
**readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration)
Reads a project configuration.
The project configuration is stored in workspace.json and nx.json. The utility will read
both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will read from either file.
**`throws`** If supplied projectName cannot be found
@ -1153,7 +1153,7 @@ both files.
#### Returns
[`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration)
[`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration)
---
@ -1241,8 +1241,8 @@ Callback to uninstall dependencies only if necessary. undefined is returned if c
Removes the configuration of an existing project.
The project configuration is stored in workspace.json and nx.json.
The utility will update both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will update either file.
#### Parameters
@ -1460,16 +1460,16 @@ Updates a JSON value to the file system tree
Updates the configuration of an existing project.
The project configuration is stored in workspace.json and nx.json. The utility will update
both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will update either files.
#### Parameters
| Name | Type | Description |
| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------- |
| `tree` | [`Tree`](../../node/nx-devkit/index#tree) | the file system tree |
| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../node/nx-devkit/index#nxjsonprojectconfiguration) | project configuration |
| Name | Type | Description |
| :--------------------- | :------------------------------------------------------------------------ | :---------------------------------------------------------------------- |
| `tree` | [`Tree`](../../node/nx-devkit/index#tree) | the file system tree |
| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../node/nx-devkit/index#projectconfiguration) | project configuration |
#### Returns

View File

@ -346,7 +346,7 @@ It only uses language primitives and immutable objects
### WorkspaceConfiguration
Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../react/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<`Omit`<[`NxJsonConfiguration`](../../react/nx-devkit/index#nxjsonconfiguration), `"projects"`\>\>
Ƭ **WorkspaceConfiguration**: `Omit`<[`WorkspaceJsonConfiguration`](../../react/nx-devkit/index#workspacejsonconfiguration), `"projects"`\> & `Partial`<[`NxJsonConfiguration`](../../react/nx-devkit/index#nxjsonconfiguration)\>
---
@ -549,17 +549,17 @@ Callback to install dependencies only if necessary. undefined is returned if cha
Adds project configuration to the Nx workspace.
The project configuration is stored in workspace.json and nx.json. The utility will update
both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will update either files.
#### Parameters
| Name | Type | Default value | Description |
| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------ | :----------------------------------------------------------------------------------------- |
| `tree` | [`Tree`](../../react/nx-devkit/index#tree) | `undefined` | the file system tree |
| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration) | `undefined` | project configuration |
| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json |
| Name | Type | Default value | Description |
| :--------------------- | :------------------------------------------------------------------------- | :------------ | :----------------------------------------------------------------------------------------- |
| `tree` | [`Tree`](../../react/nx-devkit/index#tree) | `undefined` | the file system tree |
| `projectName` | `string` | `undefined` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) | `undefined` | project configuration |
| `standalone` | `boolean` | `false` | should the project use package.json? If false, the project config is inside workspace.json |
#### Returns
@ -808,7 +808,7 @@ but it can also be passed in explicitly.
### getProjects
**getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration)\>
**getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration)\>
Get a map of all projects in a workspace.
@ -822,7 +822,7 @@ Use [readProjectConfiguration](../../react/nx-devkit/index#readprojectconfigurat
#### Returns
`Map`<`string`, [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration)\>
`Map`<`string`, [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration)\>
---
@ -1135,12 +1135,12 @@ Object the JSON content of the file represents
### readProjectConfiguration
**readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration)
**readProjectConfiguration**(`tree`, `projectName`): [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration)
Reads a project configuration.
The project configuration is stored in workspace.json and nx.json. The utility will read
both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will read from either file.
**`throws`** If supplied projectName cannot be found
@ -1153,7 +1153,7 @@ both files.
#### Returns
[`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration)
[`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration)
---
@ -1241,8 +1241,8 @@ Callback to uninstall dependencies only if necessary. undefined is returned if c
Removes the configuration of an existing project.
The project configuration is stored in workspace.json and nx.json.
The utility will update both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will update either file.
#### Parameters
@ -1460,16 +1460,16 @@ Updates a JSON value to the file system tree
Updates the configuration of an existing project.
The project configuration is stored in workspace.json and nx.json. The utility will update
both files.
The project configuration is stored in workspace.json or the associated project.json file.
The utility will update either files.
#### Parameters
| Name | Type | Description |
| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------- |
| `tree` | [`Tree`](../../react/nx-devkit/index#tree) | the file system tree |
| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) & [`NxJsonProjectConfiguration`](../../react/nx-devkit/index#nxjsonprojectconfiguration) | project configuration |
| Name | Type | Description |
| :--------------------- | :------------------------------------------------------------------------- | :---------------------------------------------------------------------- |
| `tree` | [`Tree`](../../react/nx-devkit/index#tree) | the file system tree |
| `projectName` | `string` | unique name. Often directories are part of the name (e.g., mydir-mylib) |
| `projectConfiguration` | [`ProjectConfiguration`](../../react/nx-devkit/index#projectconfiguration) | project configuration |
#### Returns

View File

@ -38,9 +38,9 @@ describe('Nx Plugin', () => {
`dist/libs/${plugin}/src/executors/build/schema.d.ts`,
`dist/libs/${plugin}/src/executors/build/schema.json`
);
const nxJson = readJson('nx.json');
const nxJson = readJson('workspace.json');
expect(nxJson).toMatchObject({
projects: expect.objectContaining({
projects: {
[plugin]: {
tags: [],
},
@ -48,7 +48,7 @@ describe('Nx Plugin', () => {
tags: [],
implicitDependencies: [`${plugin}`],
},
}),
},
});
}, 90000);
@ -188,13 +188,16 @@ describe('Nx Plugin', () => {
}, 90000);
});
describe('--tags', () => {
it('should add tags to nx.json', async () => {
it('should add tags to workspace.json', async () => {
const plugin = uniq('plugin');
runCLI(
`generate @nrwl/nx-plugin:plugin ${plugin} --linter=eslint --tags=e2etag,e2ePackage`
);
const nxJson = readJson('nx.json');
expect(nxJson.projects[plugin].tags).toEqual(['e2etag', 'e2ePackage']);
const workspaceJson = readJson('workspace.json');
expect(workspaceJson.projects[plugin].tags).toEqual([
'e2etag',
'e2ePackage',
]);
}, 90000);
});
});

View File

@ -1,4 +1,3 @@
import { NxJsonConfiguration } from '@nrwl/devkit';
import {
checkFilesExist,
exists,
@ -12,7 +11,7 @@ import {
updateFile,
workspaceConfigName,
} from '@nrwl/e2e/utils';
import type { WorkspaceJsonConfiguration } from '@nrwl/devkit';
let proj;
beforeAll(() => {
@ -107,14 +106,13 @@ describe('workspace-generator', () => {
);
expect(exists(`libs/dir/${workspace}/src/index.ts`)).toEqual(false);
expect(dryRunOutput).toContain(`UPDATE ${workspaceConfigName()}`);
expect(dryRunOutput).toContain('UPDATE nx.json');
const output = runCLI(
`workspace-generator ${custom} ${workspace} --no-interactive --directory=dir`
);
checkFilesExist(`libs/dir/${workspace}/src/index.ts`);
expect(output).toContain(`UPDATE ${workspaceConfigName()}`);
expect(output).toContain('UPDATE nx.json');
expect(output).not.toContain('UPDATE nx.json');
const jsonFailing = readJson(`tools/generators/${failing}/schema.json`);
jsonFailing.properties = {};
@ -234,9 +232,11 @@ describe('move project', () => {
*/
runCLI(`generate @nrwl/workspace:lib ${lib3}`);
let nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration;
nxJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`];
updateFile(`nx.json`, JSON.stringify(nxJson));
let workspaceJson = JSON.parse(
readFile('workspace.json')
) as WorkspaceJsonConfiguration;
workspaceJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`];
updateFile(`workspace.json`, JSON.stringify(workspaceJson));
/**
* Now try to move lib1
@ -292,13 +292,14 @@ describe('move project', () => {
expect(moveOutput).toContain(`CREATE ${rootClassPath}`);
checkFilesExist(rootClassPath);
expect(moveOutput).toContain('UPDATE nx.json');
nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration;
expect(nxJson.projects[`${lib1}-data-access`]).toBeUndefined();
expect(nxJson.projects[newName]).toEqual({
workspaceJson = JSON.parse(
readFile('workspace.json')
) as WorkspaceJsonConfiguration;
expect(workspaceJson.projects[`${lib1}-data-access`]).toBeUndefined();
expect(workspaceJson.projects[newName]).toMatchObject({
tags: [],
});
expect(nxJson.projects[lib3].implicitDependencies).toEqual([
expect(workspaceJson.projects[lib3].implicitDependencies).toEqual([
`shared-${lib1}-data-access`,
]);
@ -312,7 +313,7 @@ describe('move project', () => {
).toEqual([`libs/shared/${lib1}/data-access/src/index.ts`]);
expect(moveOutput).toContain(`UPDATE workspace.json`);
const workspaceJson = readJson(`workspace.json`);
workspaceJson = readJson(`workspace.json`);
expect(workspaceJson.projects[`${lib1}-data-access`]).toBeUndefined();
const project = workspaceJson.projects[newName];
expect(project).toBeTruthy();
@ -370,9 +371,11 @@ describe('move project', () => {
*/
runCLI(`generate @nrwl/workspace:lib ${lib3}`);
let nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration;
nxJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`];
updateFile(`nx.json`, JSON.stringify(nxJson));
let workspaceJson = JSON.parse(
readFile('workspace.json')
) as WorkspaceJsonConfiguration;
workspaceJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`];
updateFile(`workspace.json`, JSON.stringify(workspaceJson));
/**
* Now try to move lib1
@ -428,16 +431,6 @@ describe('move project', () => {
expect(moveOutput).toContain(`CREATE ${rootClassPath}`);
checkFilesExist(rootClassPath);
expect(moveOutput).toContain('UPDATE nx.json');
nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration;
expect(nxJson.projects[`${lib1}-data-access`]).toBeUndefined();
expect(nxJson.projects[newName]).toEqual({
tags: [],
});
expect(nxJson.projects[lib3].implicitDependencies).toEqual([
`shared-${lib1}-data-access`,
]);
expect(moveOutput).toContain('UPDATE tsconfig.base.json');
const rootTsConfig = readJson('tsconfig.base.json');
expect(
@ -448,12 +441,16 @@ describe('move project', () => {
).toEqual([`libs/shared/${lib1}/data-access/src/index.ts`]);
expect(moveOutput).toContain(`UPDATE workspace.json`);
const workspaceJson = readJson(`workspace.json`);
workspaceJson = readJson(`workspace.json`);
expect(workspaceJson.projects[`${lib1}-data-access`]).toBeUndefined();
const project = workspaceJson.projects[newName];
expect(project).toBeTruthy();
expect(project.root).toBe(newPath);
expect(project.sourceRoot).toBe(`${newPath}/src`);
expect(project.tags).toEqual([]);
expect(workspaceJson.projects[lib3].implicitDependencies).toEqual([
newName,
]);
expect(project.targets.lint.options.lintFilePatterns).toEqual([
`libs/shared/${lib1}/data-access/**/*.ts`,
@ -509,9 +506,11 @@ describe('move project', () => {
*/
runCLI(`generate @nrwl/workspace:lib ${lib3}`);
nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration;
nxJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`];
updateFile(`nx.json`, JSON.stringify(nxJson));
let workspaceJson = JSON.parse(
readFile('workspace.json')
) as WorkspaceJsonConfiguration;
workspaceJson.projects[lib3].implicitDependencies = [`${lib1}-data-access`];
updateFile(`workspace.json`, JSON.stringify(workspaceJson));
/**
* Now try to move lib1
@ -567,16 +566,6 @@ describe('move project', () => {
expect(moveOutput).toContain(`CREATE ${rootClassPath}`);
checkFilesExist(rootClassPath);
expect(moveOutput).toContain('UPDATE nx.json');
nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration;
expect(nxJson.projects[`${lib1}-data-access`]).toBeUndefined();
expect(nxJson.projects[newName]).toEqual({
tags: [],
});
expect(nxJson.projects[lib3].implicitDependencies).toEqual([
`shared-${lib1}-data-access`,
]);
expect(moveOutput).toContain('UPDATE tsconfig.base.json');
const rootTsConfig = readJson('tsconfig.base.json');
expect(
@ -587,7 +576,7 @@ describe('move project', () => {
).toEqual([`packages/shared/${lib1}/data-access/src/index.ts`]);
expect(moveOutput).toContain(`UPDATE workspace.json`);
const workspaceJson = readJson(`workspace.json`);
workspaceJson = readJson(`workspace.json`);
expect(workspaceJson.projects[`${lib1}-data-access`]).toBeUndefined();
const project = workspaceJson.projects[newName];
expect(project).toBeTruthy();
@ -596,6 +585,7 @@ describe('move project', () => {
expect(project.targets.lint.options.lintFilePatterns).toEqual([
`packages/shared/${lib1}/data-access/**/*.ts`,
]);
expect(project.tags).toEqual([]);
/**
* Check that the import in lib2 has been updated
@ -629,9 +619,11 @@ describe('remove project', () => {
*/
runCLI(`generate @nrwl/workspace:lib ${lib2}`);
let nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration;
nxJson.projects[lib2].implicitDependencies = [lib1];
updateFile(`nx.json`, JSON.stringify(nxJson));
let workspaceJson = JSON.parse(
readFile('workspace.json')
) as WorkspaceJsonConfiguration;
workspaceJson.projects[lib2].implicitDependencies = [lib1];
updateFile(`workspace.json`, JSON.stringify(workspaceJson));
/**
* Try removing the project (should fail)
@ -661,13 +653,14 @@ describe('remove project', () => {
expect(removeOutputForced).toContain(`DELETE libs/${lib1}`);
expect(exists(tmpProjPath(`libs/${lib1}`))).toBeFalsy();
expect(removeOutputForced).toContain(`UPDATE nx.json`);
nxJson = JSON.parse(readFile('nx.json')) as NxJsonConfiguration;
expect(nxJson.projects[`${lib1}`]).toBeUndefined();
expect(nxJson.projects[lib2].implicitDependencies).toEqual([]);
expect(removeOutputForced).not.toContain(`UPDATE nx.json`);
workspaceJson = JSON.parse(
readFile('workspace.json')
) as WorkspaceJsonConfiguration;
expect(workspaceJson.projects[`${lib1}`]).toBeUndefined();
expect(workspaceJson.projects[lib2].implicitDependencies).toEqual([]);
expect(removeOutputForced).toContain(`UPDATE workspace.json`);
const workspaceJson = readJson(`workspace.json`);
expect(workspaceJson.projects[`${lib1}`]).toBeUndefined();
});
});

View File

@ -236,8 +236,8 @@ describe('create-nx-workspace', () => {
cli: 'angular',
});
const workspaceJson = readJson('angular.json');
expect(workspaceJson.cli.packageManager).toEqual('yarn');
const nxJson = readJson('nx.json');
expect(nxJson.cli.packageManager).toEqual('yarn');
checkFilesExist('yarn.lock');
checkFilesDoNotExist('package-lock.json');
process.env.SELECTED_PM = packageManager;

View File

@ -1,7 +1,6 @@
import * as path from 'path';
import {
checkFilesExist,
exists,
isNotWindows,
isWindows,
newProject,
@ -10,11 +9,9 @@ import {
removeProject,
runCLI,
runCLIAsync,
tmpProjPath,
uniq,
updateFile,
} from '@nrwl/e2e/utils';
import type { NxJsonConfiguration } from '@nrwl/devkit';
import { classify } from '@nrwl/workspace/src/utils/strings';
let proj: string;

View File

@ -1,4 +1,7 @@
import type { NxJsonConfiguration } from '@nrwl/devkit';
import type {
NxJsonConfiguration,
WorkspaceJsonConfiguration,
} from '@nrwl/devkit';
import {
getPackageManagerCommand,
isNotWindows,
@ -534,14 +537,15 @@ describe('affected (with git)', () => {
}
}, 1000000);
it('should detect changes to projects based on the nx.json', () => {
it('should detect changes to projects based on tags changes', () => {
// TODO: investigate why affected gives different results on windows
if (isNotWindows()) {
generateAll();
const nxJson: NxJsonConfiguration = readJson('nx.json');
const workspaceJson: WorkspaceJsonConfiguration =
readJson('workspace.json');
nxJson.projects[myapp].tags = ['tag'];
updateFile('nx.json', JSON.stringify(nxJson));
workspaceJson.projects[myapp].tags = ['tag'];
updateFile('workspace.json', JSON.stringify(workspaceJson));
expect(runCLI('affected:apps')).toContain(myapp);
expect(runCLI('affected:apps')).not.toContain(myapp2);
@ -571,8 +575,6 @@ describe('affected (with git)', () => {
delete workspaceJson.projects[mylib];
updateFile(workspaceConfigName(), JSON.stringify(workspaceJson));
delete nxJson.projects[mylib];
updateFile('nx.json', JSON.stringify(nxJson));
expect(runCLI('affected:apps')).toContain(myapp);
expect(runCLI('affected:apps')).toContain(myapp2);

View File

@ -327,6 +327,7 @@ Object {
"projectType": "application",
"root": "apps/my-dir/my-app",
"sourceRoot": "apps/my-dir/my-app/src",
"tags": Array [],
}
`;
@ -357,9 +358,13 @@ Object {
],
},
},
"implicitDependencies": Array [
"my-dir-my-app",
],
"projectType": "application",
"root": "apps/my-dir/my-app-e2e",
"sourceRoot": "apps/my-dir/my-app-e2e/src",
"tags": Array [],
}
`;
@ -489,6 +494,7 @@ Object {
"projectType": "application",
"root": "apps/my-app",
"sourceRoot": "apps/my-app/src",
"tags": Array [],
}
`;
@ -519,8 +525,12 @@ Object {
],
},
},
"implicitDependencies": Array [
"my-app",
],
"projectType": "application",
"root": "apps/my-app-e2e",
"sourceRoot": "apps/my-app-e2e/src",
"tags": Array [],
}
`;

View File

@ -42,21 +42,25 @@ describe('app', () => {
expect(workspaceJson.projects['my-app'].architect.e2e).not.toBeDefined();
});
it('should update nx.json', async () => {
it('should update tags + implicit dependencies', async () => {
// ACT
await generateApp(appTree, 'myApp', { tags: 'one,two,my-app' });
// ASSERT
const nxJson = readJson<NxJsonConfiguration>(appTree, '/nx.json');
expect(nxJson.projects).toEqual({
'my-app': {
tags: ['one', 'two', 'my-app'],
},
'my-app-e2e': {
implicitDependencies: ['my-app'],
tags: [],
},
});
const projects = devkit.getProjects(appTree);
expect(projects).toEqual(
new Map(
Object.entries({
'my-app': expect.objectContaining({
tags: ['one', 'two', 'my-app'],
}),
'my-app-e2e': expect.objectContaining({
implicitDependencies: ['my-app'],
tags: [],
}),
})
)
);
});
it('should generate files', async () => {
@ -187,21 +191,25 @@ describe('app', () => {
expect(workspaceJson.projects['my-dir-my-app-e2e']).toMatchSnapshot();
});
it('should update nx.json', async () => {
it('should update tags + implicit dependencies', async () => {
await generateApp(appTree, 'myApp', {
directory: 'myDir',
tags: 'one,two,my-dir-my-app',
});
const nxJson = readJson<NxJsonConfiguration>(appTree, '/nx.json');
expect(nxJson.projects).toEqual({
'my-dir-my-app': {
tags: ['one', 'two', 'my-dir-my-app'],
},
'my-dir-my-app-e2e': {
implicitDependencies: ['my-dir-my-app'],
tags: [],
},
});
const projects = devkit.getProjects(appTree);
expect(projects).toEqual(
new Map(
Object.entries({
'my-dir-my-app': expect.objectContaining({
tags: ['one', 'two', 'my-dir-my-app'],
}),
'my-dir-my-app-e2e': expect.objectContaining({
implicitDependencies: ['my-dir-my-app'],
tags: [],
}),
})
)
);
});
it('should generate files', async () => {
@ -596,6 +604,8 @@ describe('app', () => {
},
},
},
implicitDependencies: ['my-app'],
tags: [],
});
});
@ -720,9 +730,9 @@ describe('app', () => {
}
// should not update workspace configuration since --strict=true is the default
const workspaceJson = readJson(appTree, 'workspace.json');
const nxJson = readJson<NxJsonConfiguration>(appTree, 'nx.json');
expect(
workspaceJson.schematics['@nrwl/angular:application'].strict
nxJson.generators['@nrwl/angular:application'].strict
).not.toBeDefined();
});
@ -731,10 +741,8 @@ describe('app', () => {
// check to see if the workspace configuration has been updated to turn off
// strict mode by default in future applications
const workspaceJson = readJson(appTree, 'workspace.json');
expect(workspaceJson.schematics['@nrwl/angular:application'].strict).toBe(
false
);
const nxJson = readJson<NxJsonConfiguration>(appTree, 'nx.json');
expect(nxJson.generators['@nrwl/angular:application'].strict).toBe(false);
});
});

View File

@ -1,17 +1,10 @@
import type { Tree } from '@nrwl/devkit';
import { Tree } from '@nrwl/devkit';
import type { NormalizedSchema } from './normalized-schema';
import {
moveFilesToNewDirectory,
getWorkspaceLayout,
joinPathFragments,
} from '@nrwl/devkit';
import { moveFilesToNewDirectory, joinPathFragments } from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import { convertToNxProjectGenerator } from '@nrwl/workspace';
export async function addProtractor(host: Tree, options: NormalizedSchema) {
const { standaloneAsDefault } = getWorkspaceLayout(host);
const protractorSchematic = wrapAngularDevkitSchematic(
'@schematics/angular',
'e2e'
@ -22,12 +15,6 @@ export async function addProtractor(host: Tree, options: NormalizedSchema) {
rootSelector: `${options.prefix}-root`,
});
if (options.standaloneConfig || standaloneAsDefault) {
await convertToNxProjectGenerator(host, {
project: options.e2eProjectName,
});
}
moveFilesToNewDirectory(
host,
joinPathFragments(options.appProjectRoot, 'e2e'),

View File

@ -19,23 +19,13 @@ export function updateConfigFiles(host: Tree, options: NormalizedSchema) {
}
function addProjectToNx(host: Tree, options: NormalizedSchema) {
// nx.json
updateJson(host, '/nx.json', (json) => {
const resultJson = {
...json,
projects: {
...json.projects,
[options.name]: { tags: options.parsedTags },
},
};
if (options.e2eTestRunner === 'protractor') {
resultJson.projects[options.e2eProjectName] = { tags: [] };
resultJson.projects[options.e2eProjectName].implicitDependencies = [
options.name,
];
}
return resultJson;
});
// tags, implicit dependencies
const projectConfig = readProjectConfiguration(host, options.name);
const resultJson = {
...projectConfig,
tags: options.parsedTags,
};
updateProjectConfiguration(host, options.name, resultJson);
}
function updateTsConfigCompilerOptions(host: Tree, options: NormalizedSchema) {

View File

@ -30,6 +30,8 @@ export function updateE2eProject(tree: Tree, options: NormalizedSchema) {
targets: {
e2e: proj.targets.e2e,
},
implicitDependencies: [options.name],
tags: [],
};
project.targets.e2e.options.protractorConfig = `${options.e2eProjectRoot}/protractor.conf.js`;
// update workspace.json / angular.json

View File

@ -1,4 +1,4 @@
import { readJson, Tree } from '@nrwl/devkit';
import { NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { Linter } from '@nrwl/linter';
@ -104,13 +104,13 @@ describe('init', () => {
skipFormat: false,
});
const { schematics } = readJson(host, 'workspace.json');
const { generators } = readJson<NxJsonConfiguration>(host, 'nx.json');
// ASSERT
expect(schematics['@nrwl/angular:application'].unitTestRunner).toEqual(
expect(generators['@nrwl/angular:application'].unitTestRunner).toEqual(
'karma'
);
expect(schematics['@nrwl/angular:library'].unitTestRunner).toEqual(
expect(generators['@nrwl/angular:library'].unitTestRunner).toEqual(
'karma'
);
});
@ -155,13 +155,13 @@ describe('init', () => {
skipFormat: false,
});
const { schematics } = readJson(host, 'workspace.json');
const { generators } = readJson<NxJsonConfiguration>(host, 'nx.json');
// ASSERT
expect(schematics['@nrwl/angular:application'].unitTestRunner).toEqual(
expect(generators['@nrwl/angular:application'].unitTestRunner).toEqual(
'jest'
);
expect(schematics['@nrwl/angular:library'].unitTestRunner).toEqual(
expect(generators['@nrwl/angular:library'].unitTestRunner).toEqual(
'jest'
);
});
@ -195,10 +195,10 @@ describe('init', () => {
skipFormat: false,
});
const { schematics } = readJson(host, 'workspace.json');
const { generators } = readJson<NxJsonConfiguration>(host, 'nx.json');
// ASSERT
expect(schematics['@nrwl/angular:application'].e2eTestRunner).toEqual(
expect(generators['@nrwl/angular:application'].e2eTestRunner).toEqual(
'cypress'
);
});
@ -233,10 +233,10 @@ describe('init', () => {
skipFormat: false,
});
const { schematics } = readJson(host, 'workspace.json');
const { generators } = readJson<NxJsonConfiguration>(host, 'nx.json');
// ASSERT
expect(schematics['@nrwl/angular:application'].e2eTestRunner).toEqual(
expect(generators['@nrwl/angular:application'].e2eTestRunner).toEqual(
'protractor'
);
});
@ -253,15 +253,13 @@ describe('init', () => {
skipFormat: false,
});
const workspaceJson = readJson(host, 'workspace.json');
const { generators } = readJson<NxJsonConfiguration>(host, 'nx.json');
// ASSERT
expect(
workspaceJson.schematics['@nrwl/angular:application'].linter
).toEqual('eslint');
expect(
workspaceJson.schematics['@nrwl/angular:library'].linter
).toEqual('eslint');
expect(generators['@nrwl/angular:application'].linter).toEqual(
'eslint'
);
expect(generators['@nrwl/angular:library'].linter).toEqual('eslint');
});
});
@ -274,15 +272,11 @@ describe('init', () => {
skipFormat: false,
});
const workspaceJson = readJson(host, 'workspace.json');
const { generators } = readJson<NxJsonConfiguration>(host, 'nx.json');
// ASSERT
expect(
workspaceJson.schematics['@nrwl/angular:application'].linter
).toEqual('none');
expect(
workspaceJson.schematics['@nrwl/angular:library'].linter
).toEqual('none');
expect(generators['@nrwl/angular:application'].linter).toEqual('none');
expect(generators['@nrwl/angular:library'].linter).toEqual('none');
});
});
});
@ -297,10 +291,10 @@ describe('init', () => {
skipFormat: false,
});
const workspaceJson = readJson(host, 'workspace.json');
const { cli } = readJson<NxJsonConfiguration>(host, 'nx.json');
// ASSERT
expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/angular');
expect(cli.defaultCollection).toEqual('@nrwl/angular');
});
it.each(['css', 'scss', 'less'])(
@ -315,12 +309,10 @@ describe('init', () => {
style,
});
const workspaceJson = readJson(host, 'workspace.json');
const { generators } = readJson<NxJsonConfiguration>(host, 'nx.json');
// ASSERT
expect(
workspaceJson.schematics['@nrwl/angular:component']['style']
).toBe(style);
expect(generators['@nrwl/angular:component']['style']).toBe(style);
}
);
});

View File

@ -13,7 +13,6 @@ import { NormalizedSchema } from './normalized-schema';
import { updateNgPackage } from './update-ng-package';
export async function updateProject(host: Tree, options: NormalizedSchema) {
updateNxConfigWithProject(host, options);
createFiles(host, options);
updateProjectTsConfig(host, options);
fixProjectWorkspaceConfig(host, options);
@ -119,6 +118,7 @@ function createFiles(host: Tree, options: NormalizedSchema) {
function fixProjectWorkspaceConfig(host: Tree, options: NormalizedSchema) {
const project = readProjectConfiguration(host, options.name);
project.tags = options.parsedTags;
const fixedProject = replaceAppNameWithPath(
project,
@ -172,13 +172,3 @@ function updateProjectTsConfig(host: Tree, options: NormalizedSchema) {
};
});
}
function updateNxConfigWithProject(host: Tree, options: NormalizedSchema) {
updateJson(host, `/nx.json`, (json) => ({
...json,
projects: {
...json.projects,
[options.name]: { tags: options.parsedTags },
},
}));
}

View File

@ -1,9 +1,10 @@
import {
NxJsonConfiguration,
readJson,
Tree,
updateJson,
parseJson,
getProjects,
NxJsonConfiguration,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { Linter } from '@nrwl/linter';
@ -153,7 +154,7 @@ describe('lib', () => {
expect(libProdConfig).toBeFalsy();
});
it('should update nx.json', async () => {
it('should update tags', async () => {
// ACT
await runLibraryGeneratorWithOpts({
publishable: false,
@ -162,11 +163,11 @@ describe('lib', () => {
});
// ASSERT
const nxJson = readJson<NxJsonConfiguration>(appTree, '/nx.json');
expect(nxJson.projects).toEqual({
'my-lib': {
const projects = Object.fromEntries(getProjects(appTree));
expect(projects).toEqual({
'my-lib': expect.objectContaining({
tags: ['one', 'two'],
},
}),
});
});
@ -213,20 +214,24 @@ describe('lib', () => {
});
});
it('should check for existance of spec files before deleting them', async () => {
it('should check for existence of spec files before deleting them', async () => {
// ARRANGE
updateJson(appTree, '/workspace.json', (workspaceJSON) => {
workspaceJSON.schematics = {
'@schematics/angular:service': {
skipTests: true,
},
'@schematics/angular:component': {
skipTests: true,
},
};
updateJson<NxJsonConfiguration, NxJsonConfiguration>(
appTree,
'/nx.json',
(nxJson) => {
nxJson.generators = {
'@schematics/angular:service': {
skipTests: true,
},
'@schematics/angular:component': {
skipTests: true,
},
};
return workspaceJSON;
});
return nxJson;
}
);
// ACT
await runLibraryGeneratorWithOpts();
@ -371,7 +376,7 @@ describe('lib', () => {
});
describe('nested', () => {
it('should update nx.json', async () => {
it('should update tags', async () => {
// ACT
await runLibraryGeneratorWithOpts({ tags: 'one', directory: 'my-dir' });
await runLibraryGeneratorWithOpts({
@ -381,15 +386,15 @@ describe('lib', () => {
});
// ASSERT
const nxJson = readJson<NxJsonConfiguration>(appTree, '/nx.json');
const projects = Object.fromEntries(getProjects(appTree));
expect(nxJson.projects).toEqual({
'my-dir-my-lib': {
expect(projects).toEqual({
'my-dir-my-lib': expect.objectContaining({
tags: ['one'],
},
'my-dir-my-lib2': {
}),
'my-dir-my-lib2': expect.objectContaining({
tags: ['one', 'two'],
},
}),
});
});
@ -1020,7 +1025,7 @@ describe('lib', () => {
appTree,
'libs/my-lib/tsconfig.json'
);
const workspaceJson = readJson(appTree, 'workspace.json');
const { generators } = readJson<NxJsonConfiguration>(appTree, 'nx.json');
// check that the TypeScript compiler options have been updated
expect(compilerOptions.forceConsistentCasingInFileNames).toBe(true);
@ -1034,9 +1039,7 @@ describe('lib', () => {
// check to see if the workspace configuration has been updated to use strict
// mode by default in future libraries
expect(
workspaceJson.schematics['@nrwl/angular:library'].strict
).not.toBeDefined();
expect(generators['@nrwl/angular:library'].strict).not.toBeDefined();
});
it('should set defaults when --strict=false', async () => {
@ -1050,10 +1053,8 @@ describe('lib', () => {
// ASSERT
// check to see if the workspace configuration has been updated to turn off
// strict mode by default in future libraries
const workspaceJson = readJson(appTree, 'workspace.json');
expect(workspaceJson.schematics['@nrwl/angular:library'].strict).toBe(
false
);
const { generators } = readJson<NxJsonConfiguration>(appTree, 'nx.json');
expect(generators['@nrwl/angular:library'].strict).toBe(false);
});
});

View File

@ -1,4 +1,4 @@
import type { NxJsonConfiguration, Tree } from '@nrwl/devkit';
import type { ProjectConfiguration, Tree } from '@nrwl/devkit';
import { readJson, readProjectConfiguration } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
@ -163,9 +163,12 @@ describe('Init MFE', () => {
});
// ASSERT
const nxJson: NxJsonConfiguration = readJson(host, 'nx.json');
const projectConfig: ProjectConfiguration = readProjectConfiguration(
host,
'app1'
);
expect(nxJson.projects['app1'].implicitDependencies).toContain('remote1');
expect(projectConfig.implicitDependencies).toContain('remote1');
});
it('should add a remote application and add it to a specified host applications webpack config when no other remote has been added to it', async () => {

View File

@ -8,8 +8,8 @@ import { readProjectConfiguration } from '@nrwl/devkit';
export function getE2EProject(
tree: Tree,
e2eProjectName: string
): ProjectConfiguration & NxJsonProjectConfiguration {
let e2eProject: ProjectConfiguration & NxJsonProjectConfiguration;
): ProjectConfiguration {
let e2eProject: ProjectConfiguration;
try {
e2eProject = readProjectConfiguration(tree, e2eProjectName);
} catch {

View File

@ -1,7 +1,6 @@
import {
formatFiles,
getProjects,
NxJsonProjectConfiguration,
parseTargetString,
ProjectConfiguration,
Target,
@ -104,7 +103,7 @@ function getTargetConfigurationOptions(
}
function updateTargetsConfigurations(
project: ProjectConfiguration & NxJsonProjectConfiguration,
project: ProjectConfiguration,
projectName: string,
target: TargetConfiguration,
buildTargetName: string,
@ -144,7 +143,7 @@ function updateTargetsConfigurations(
}
function updateTargetsOptions(
project: ProjectConfiguration & NxJsonProjectConfiguration,
project: ProjectConfiguration,
target: TargetConfiguration,
buildTargetName: string
) {

View File

@ -1,8 +1,4 @@
import type {
NxJsonProjectConfiguration,
ProjectConfiguration,
Tree,
} from '@nrwl/devkit';
import type { ProjectConfiguration, Tree } from '@nrwl/devkit';
import {
formatFiles,
getProjects,
@ -12,7 +8,7 @@ import {
logger,
} from '@nrwl/devkit';
type AffectedLib = ProjectConfiguration & NxJsonProjectConfiguration;
type AffectedLib = ProjectConfiguration;
type InvalidLibs = {
buildableLibs: AffectedLib[];
publishableLibs: AffectedLib[];

View File

@ -97,17 +97,11 @@ export function createApp(
options: {},
},
},
tags: [],
},
},
})
);
updateJson(tree, './nx.json', (json) => ({
...json,
projects: {
...json.projects,
[appName]: { tags: [] },
},
}));
}
export function createLib(tree: Tree, libName: string) {

View File

@ -89,10 +89,12 @@ function runOneOptions(
workspace.type === 'nx' ? 'workspace.json' : 'angular.json'
)
);
const nxJson = readJsonFile(path.join(workspace.dir, 'nx.json'));
return parseRunOneOptions(
workspace.dir,
workspaceConfigJson,
nxJson,
process.argv.slice(2)
);
} catch {

View File

@ -8,10 +8,11 @@ describe('parseRunOneOptions', () => {
},
},
};
const nxJson = {};
const args = ['build', 'myproj', '--configuration=production', '--flag=true'];
it('should work', () => {
expect(parseRunOneOptions('root', workspaceJson, args)).toEqual({
expect(parseRunOneOptions('root', workspaceJson, nxJson, args)).toEqual({
project: 'myproj',
target: 'build',
configuration: 'production',
@ -21,7 +22,7 @@ describe('parseRunOneOptions', () => {
it('should work with --prod', () => {
expect(
parseRunOneOptions('root', workspaceJson, [
parseRunOneOptions('root', workspaceJson, nxJson, [
'build',
'myproj',
'--prod',
@ -37,7 +38,7 @@ describe('parseRunOneOptions', () => {
it('should override --prod with --configuration', () => {
expect(
parseRunOneOptions('root', workspaceJson, [
parseRunOneOptions('root', workspaceJson, nxJson, [
'build',
'myproj',
'--prod',
@ -55,7 +56,7 @@ describe('parseRunOneOptions', () => {
it('should work with run syntax', () => {
expect(
parseRunOneOptions('root', workspaceJson, [
parseRunOneOptions('root', workspaceJson, nxJson, [
'run',
'myproj:build:staging',
'--flag=true',
@ -72,7 +73,8 @@ describe('parseRunOneOptions', () => {
expect(
parseRunOneOptions(
'root',
{ ...workspaceJson, cli: { defaultProjectName: 'myproj' } },
{ ...workspaceJson },
{ cli: { defaultProjectName: 'myproj' } },
['build', '--flag=true']
)
).toEqual({
@ -85,7 +87,7 @@ describe('parseRunOneOptions', () => {
it('should use defaultConfiguration when no provided', () => {
expect(
parseRunOneOptions('root', workspaceJson, [
parseRunOneOptions('root', workspaceJson, nxJson, [
'run',
'myproj:build',
'--flag=true',
@ -99,20 +101,24 @@ describe('parseRunOneOptions', () => {
});
it('should return false when the task is not recognized', () => {
expect(parseRunOneOptions('root', {}, args)).toBe(false);
expect(parseRunOneOptions('root', { projects: {} }, args)).toBe(false);
expect(parseRunOneOptions('root', {}, nxJson, args)).toBe(false);
expect(parseRunOneOptions('root', { projects: {} }, nxJson, args)).toBe(
false
);
expect(
parseRunOneOptions('root', { projects: { architect: {} } }, args)
parseRunOneOptions('root', { projects: { architect: {} } }, nxJson, args)
).toBe(false);
});
it('should return false when cannot find the right project', () => {
expect(
parseRunOneOptions('root', workspaceJson, ['build', 'wrongproj'])
parseRunOneOptions('root', workspaceJson, nxJson, ['build', 'wrongproj'])
).toBe(false);
});
it('should return false when no project specified', () => {
expect(parseRunOneOptions('root', workspaceJson, ['build'])).toBe(false);
expect(parseRunOneOptions('root', workspaceJson, nxJson, ['build'])).toBe(
false
);
});
});

View File

@ -1,30 +1,33 @@
import yargsParser = require('yargs-parser');
import * as fs from 'fs';
function calculateDefaultProjectName(cwd: string, root: string, wc: any) {
function calculateDefaultProjectName(
cwd: string,
root: string,
workspaceConfiguration: any,
nxJson
) {
let relativeCwd = cwd.replace(/\\/g, '/').split(root.replace(/\\/g, '/'))[1];
if (relativeCwd) {
relativeCwd = relativeCwd.startsWith('/')
? relativeCwd.substring(1)
: relativeCwd;
const matchingProject = Object.keys(wc.projects).find((p) => {
const projectRoot = wc.projects[p].root;
return (
relativeCwd == projectRoot || relativeCwd.startsWith(`${projectRoot}/`)
);
});
const matchingProject = Object.keys(workspaceConfiguration.projects).find(
(p) => {
const projectRoot = workspaceConfiguration.projects[p].root;
return (
relativeCwd == projectRoot ||
relativeCwd.startsWith(`${projectRoot}/`)
);
}
);
if (matchingProject) return matchingProject;
}
let defaultProjectName = null;
try {
defaultProjectName = wc.cli.defaultProjectName;
} catch (e) {}
try {
if (!defaultProjectName) {
defaultProjectName = wc.defaultProject;
}
} catch (e) {}
return defaultProjectName;
return (
nxJson.cli?.defaultProjectName ||
nxJson.defaultProject ||
workspaceConfiguration.defaultProject
);
}
const invalidTargetNames = [
@ -60,13 +63,15 @@ const invalidTargetNames = [
export function parseRunOneOptions(
root: string,
workspaceConfigJson: any,
workspaceJsonConfiguration: any,
nxJson: any,
args: string[]
): false | { project; target; configuration; parsedArgs } {
const defaultProjectName = calculateDefaultProjectName(
process.cwd(),
root,
workspaceConfigJson
workspaceJsonConfiguration,
nxJson
);
const parsedArgs = yargsParser(args, {
@ -105,7 +110,6 @@ export function parseRunOneOptions(
if (parsedArgs.project) {
project = parsedArgs.project;
}
// we need both to be able to run a target, no tasks runner
if (!project || !target) {
return false;
@ -113,7 +117,8 @@ export function parseRunOneOptions(
// we need both to be able to run a target, no tasks runner
const p =
workspaceConfigJson.projects && workspaceConfigJson.projects[project];
workspaceJsonConfiguration.projects &&
workspaceJsonConfiguration.projects[project];
if (!p) return false;
let targets;

View File

@ -4,6 +4,7 @@ import {
readProjectConfiguration,
updateProjectConfiguration,
Tree,
WorkspaceJsonConfiguration,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { cypressProjectGenerator } from './cypress-project';
@ -189,7 +190,7 @@ describe('schematic:cypress-project', () => {
expect(project.architect.lint).toBeUndefined();
});
it('should update nx.json', async () => {
it('should update tags and implicit dependencies', async () => {
await cypressProjectGenerator(tree, {
name: 'my-app-e2e',
project: 'my-app',
@ -322,8 +323,13 @@ describe('schematic:cypress-project', () => {
name: 'my-app-e2e',
});
const nxJson = readJson(tree, 'nx.json');
expect(nxJson.projects['my-app-e2e']).toEqual({ tags: [] });
const workspaceJson = readJson<WorkspaceJsonConfiguration>(
tree,
'workspace.json'
);
const projectConfig = workspaceJson.projects['my-app-e2e'];
expect(projectConfig.implicitDependencies).not.toBeDefined();
expect(projectConfig.tags).toEqual([]);
});
});
});

View File

@ -13,7 +13,6 @@ import {
Tree,
updateJson,
ProjectConfiguration,
NxJsonProjectConfiguration,
} from '@nrwl/devkit';
import { Linter, lintProjectGenerator } from '@nrwl/linter';
import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial';
@ -64,7 +63,7 @@ function addProject(tree: Tree, options: CypressProjectSchema) {
: devServerTarget;
}
const project: ProjectConfiguration & NxJsonProjectConfiguration = {
const project: ProjectConfiguration = {
root: options.projectRoot,
sourceRoot: joinPathFragments(options.projectRoot, 'src'),
projectType: 'application',

View File

@ -2,8 +2,13 @@ import type { Tree } from '@nrwl/tao/src/shared/tree';
import * as path from 'path';
import type * as Prettier from 'prettier';
import { getWorkspacePath } from '../utils/get-workspace-layout';
import { readJson, writeJson } from '../utils/json';
import { readJson, updateJson, writeJson } from '../utils/json';
import { sortObjectByKeys } from '@nrwl/tao/src/utils/object-sort';
import {
readWorkspaceConfiguration,
updateWorkspaceConfiguration,
WorkspaceConfiguration,
} from './project-configuration';
/**
* Formats all the created or updated files using Prettier
@ -15,8 +20,8 @@ export async function formatFiles(tree: Tree): Promise<void> {
prettier = await import('prettier');
} catch {}
ensurePropertiesAreInNewLocations(tree);
sortWorkspaceJson(tree);
sortNxJson(tree);
sortTsConfig(tree);
if (!prettier) return;
@ -61,7 +66,7 @@ export async function formatFiles(tree: Tree): Promise<void> {
function sortWorkspaceJson(tree: Tree) {
const workspaceJsonPath = getWorkspacePath(tree);
if (!path) {
if (!workspaceJsonPath) {
return;
}
@ -79,17 +84,26 @@ function sortWorkspaceJson(tree: Tree) {
}
}
function sortNxJson(tree: Tree) {
try {
const nxJson = readJson(tree, 'nx.json');
const sortedProjects = sortObjectByKeys(nxJson.projects);
writeJson(tree, 'nx.json', {
...nxJson,
projects: sortedProjects,
});
} catch (e) {
// catch noop
/**
* `updateWorkspaceConfiguration` already handles
* placing properties in their new locations, so
* reading + updating it ensures that props are placed
* correctly.
*/
function ensurePropertiesAreInNewLocations(tree: Tree) {
const workspacePath = getWorkspacePath(tree);
if (!workspacePath) {
return;
}
const wc = readWorkspaceConfiguration(tree);
updateWorkspaceConfiguration(tree, wc);
updateJson<WorkspaceConfiguration>(tree, workspacePath, (json) => {
delete json.cli;
delete json.defaultProject;
delete (json as any).schematics;
delete json.generators;
return json;
});
}
function sortTsConfig(tree: Tree) {

View File

@ -60,27 +60,6 @@ describe('project configuration', () => {
});
});
it('should get info from nx.json', () => {
updateJson(tree, getWorkspacePath(tree), (json) => {
json.projects['proj1'] = {
root: 'proj1',
};
return json;
});
updateJson(tree, 'nx.json', (json) => {
json.projects['proj1'] = {
tags: ['tag1'],
};
return json;
});
const config = readProjectConfiguration(tree, 'proj1');
expect(config).toEqual({
root: 'proj1',
tags: ['tag1'],
});
});
it('should should not fail if projects is not defined in nx.json', () => {
updateJson(tree, getWorkspacePath(tree), (json) => {
json.projects['proj1'] = {
@ -223,27 +202,6 @@ describe('project configuration', () => {
});
});
it('should get info from nx.json', () => {
updateJson(tree, getWorkspacePath(tree), (json) => {
json.projects['proj1'] = {
root: 'proj1',
};
return json;
});
updateJson(tree, 'nx.json', (json) => {
json.projects['proj1'] = {
tags: ['tag1'],
};
return json;
});
const config = readProjectConfiguration(tree, 'proj1');
expect(config).toEqual({
root: 'proj1',
tags: ['tag1'],
});
});
it('should should not fail if projects is not defined in nx.json', () => {
updateJson(tree, getWorkspacePath(tree), (json) => {
json.projects['proj1'] = {

View File

@ -14,22 +14,19 @@ import { readJson, updateJson, writeJson } from '../utils/json';
import { joinPathFragments } from '../utils/path';
import type { Tree } from '@nrwl/tao/src/shared/tree';
import type {
NxJsonConfiguration,
NxJsonProjectConfiguration,
} from '@nrwl/tao/src/shared/nx';
import type { NxJsonConfiguration } from '@nrwl/tao/src/shared/nx';
export type WorkspaceConfiguration = Omit<
WorkspaceJsonConfiguration,
'projects'
> &
Partial<Omit<NxJsonConfiguration, 'projects'>>;
Partial<NxJsonConfiguration>;
/**
* Adds project configuration to the Nx workspace.
*
* The project configuration is stored in workspace.json and nx.json. The utility will update
* both files.
* The project configuration is stored in workspace.json or the associated project.json file.
* The utility will update either files.
*
* @param tree - the file system tree
* @param projectName - unique name. Often directories are part of the name (e.g., mydir-mylib)
@ -39,7 +36,7 @@ export type WorkspaceConfiguration = Omit<
export function addProjectConfiguration(
tree: Tree,
projectName: string,
projectConfiguration: ProjectConfiguration & NxJsonProjectConfiguration,
projectConfiguration: ProjectConfiguration,
standalone: boolean = false
): void {
standalone = standalone || getWorkspaceLayout(tree).standaloneAsDefault;
@ -55,8 +52,8 @@ export function addProjectConfiguration(
/**
* Updates the configuration of an existing project.
*
* The project configuration is stored in workspace.json and nx.json. The utility will update
* both files.
* The project configuration is stored in workspace.json or the associated project.json file.
* The utility will update either files.
*
* @param tree - the file system tree
* @param projectName - unique name. Often directories are part of the name (e.g., mydir-mylib)
@ -65,7 +62,7 @@ export function addProjectConfiguration(
export function updateProjectConfiguration(
tree: Tree,
projectName: string,
projectConfiguration: ProjectConfiguration & NxJsonProjectConfiguration
projectConfiguration: ProjectConfiguration
): void {
setProjectConfiguration(tree, projectName, projectConfiguration, 'update');
}
@ -73,8 +70,8 @@ export function updateProjectConfiguration(
/**
* Removes the configuration of an existing project.
*
* The project configuration is stored in workspace.json and nx.json.
* The utility will update both files.
* The project configuration is stored in workspace.json or the associated project.json file.
* The utility will update either file.
*/
export function removeProjectConfiguration(
tree: Tree,
@ -88,18 +85,12 @@ export function removeProjectConfiguration(
*
* Use {@link readProjectConfiguration} if only one project is needed.
*/
export function getProjects(
tree: Tree
): Map<string, ProjectConfiguration & NxJsonProjectConfiguration> {
export function getProjects(tree: Tree): Map<string, ProjectConfiguration> {
const workspace = readWorkspace(tree);
const nxJson = readNxJson(tree);
return new Map(
Object.keys(workspace.projects || {}).map((projectName) => {
return [
projectName,
getProjectConfiguration(projectName, workspace, nxJson),
];
return [projectName, getProjectConfiguration(projectName, workspace)];
})
);
}
@ -110,7 +101,7 @@ export function getProjects(
* This does _not_ provide projects configuration, use {@link readProjectConfiguration} instead.
*/
export function readWorkspaceConfiguration(tree: Tree): WorkspaceConfiguration {
const workspace = readWorkspace(tree);
const workspace = readRawWorkspaceJson(tree);
delete workspace.projects;
let nxJson = readNxJson(tree);
@ -141,11 +132,11 @@ export function updateWorkspaceConfiguration(
const {
// Workspace Json Properties
version,
// Nx Json Properties
cli,
defaultProject,
generators,
// Nx Json Properties
implicitDependencies,
plugins,
npmScope,
@ -156,11 +147,8 @@ export function updateWorkspaceConfiguration(
} = workspaceConfig;
const workspace: Omit<Required<WorkspaceJsonConfiguration>, 'projects'> = {
version,
cli,
defaultProject,
generators,
};
const nxJson: Omit<Required<NxJsonConfiguration>, 'projects'> = {
const nxJson: Required<NxJsonConfiguration> = {
implicitDependencies,
plugins,
npmScope,
@ -168,6 +156,9 @@ export function updateWorkspaceConfiguration(
workspaceLayout,
tasksRunnerOptions,
affected,
cli,
generators,
defaultProject,
};
updateJson<WorkspaceJsonConfiguration>(
@ -220,8 +211,8 @@ function readNxJsonExtends(tree: Tree, nxJson: { extends?: string }) {
/**
* Reads a project configuration.
*
* The project configuration is stored in workspace.json and nx.json. The utility will read
* both files.
* The project configuration is stored in workspace.json or the associated project.json file.
* The utility will read from either file.
*
* @param tree - the file system tree
* @param projectName - unique name. Often directories are part of the name (e.g., mydir-mylib)
@ -230,7 +221,7 @@ function readNxJsonExtends(tree: Tree, nxJson: { extends?: string }) {
export function readProjectConfiguration(
tree: Tree,
projectName: string
): ProjectConfiguration & NxJsonProjectConfiguration {
): ProjectConfiguration {
const workspace = readWorkspace(tree);
if (!workspace.projects[projectName]) {
throw new Error(
@ -242,7 +233,7 @@ export function readProjectConfiguration(
const nxJson = readNxJson(tree);
return getProjectConfiguration(projectName, workspace, nxJson);
return getProjectConfiguration(projectName, workspace);
}
export function readNxJson(tree: Tree): NxJsonConfiguration | null {
@ -275,12 +266,10 @@ export function isStandaloneProject(tree: Tree, project: string): boolean {
function getProjectConfiguration(
projectName: string,
workspace: WorkspaceJsonConfiguration,
nxJson: NxJsonConfiguration | null
): ProjectConfiguration & NxJsonProjectConfiguration {
workspace: WorkspaceJsonConfiguration
): ProjectConfiguration {
return {
...readWorkspaceSection(workspace, projectName),
...(nxJson === null ? {} : readNxJsonSection(nxJson, projectName)),
};
}
@ -291,23 +280,14 @@ function readWorkspaceSection(
return workspace.projects[projectName];
}
function readNxJsonSection(nxJson: NxJsonConfiguration, projectName: string) {
return nxJson.projects?.[projectName];
}
function setProjectConfiguration(
tree: Tree,
projectName: string,
projectConfiguration: ProjectConfiguration & NxJsonProjectConfiguration,
projectConfiguration: ProjectConfiguration,
mode: 'create' | 'update' | 'delete',
standalone: boolean = false
): void {
const hasNxJson = tree.exists('nx.json');
if (mode === 'delete') {
if (hasNxJson) {
addProjectToNxJson(tree, projectName, undefined, mode);
}
addProjectToWorkspaceJson(tree, projectName, undefined, mode);
return;
}
@ -325,25 +305,12 @@ function setProjectConfiguration(
mode,
standalone
);
if (hasNxJson) {
const { tags, implicitDependencies } = projectConfiguration;
addProjectToNxJson(
tree,
projectName,
{
tags,
implicitDependencies,
},
mode
);
}
}
function addProjectToWorkspaceJson(
tree: Tree,
projectName: string,
project: ProjectConfiguration & NxJsonProjectConfiguration,
project: ProjectConfiguration,
mode: 'create' | 'update' | 'delete',
standalone: boolean = false
) {
@ -370,12 +337,7 @@ function addProjectToWorkspaceJson(
} else if (mode === 'delete') {
delete workspaceJson.projects[projectName];
} else {
let projectConfiguration: ProjectConfiguration;
if (project) {
const { tags, implicitDependencies, ...c } = project;
projectConfiguration = c;
}
workspaceJson.projects[projectName] = projectConfiguration;
workspaceJson.projects[projectName] = project;
}
writeJson(
tree,
@ -384,31 +346,10 @@ function addProjectToWorkspaceJson(
);
}
function addProjectToNxJson(
tree: Tree,
projectName: string,
config: NxJsonProjectConfiguration,
mode: 'create' | 'update' | 'delete'
) {
// distributed project files do not use nx.json,
// so only proceed if the project does not use them.
if (!getProjectFileLocation(tree, projectName)) {
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
if (mode === 'delete') {
delete nxJson.projects[projectName];
} else {
nxJson.projects[projectName] = {
...{
tags: [],
},
...(config || {}),
};
}
writeJson(tree, 'nx.json', nxJson);
}
}
function readWorkspace(tree: Tree): WorkspaceJsonConfiguration {
/**
* Read the workspace configuration, including projects.
*/
export function readWorkspace(tree: Tree): WorkspaceJsonConfiguration {
const workspaceJson = inlineProjectConfigurationsWithTree(tree);
const originalVersion = workspaceJson.version;
return {
@ -426,28 +367,30 @@ function readWorkspace(tree: Tree): WorkspaceJsonConfiguration {
function inlineProjectConfigurationsWithTree(
tree: Tree
): WorkspaceJsonConfiguration {
const path = getWorkspacePath(tree);
const workspaceJson = readJson<RawWorkspaceJsonConfiguration>(tree, path);
const workspaceJson = readRawWorkspaceJson(tree);
Object.entries(workspaceJson.projects || {}).forEach(([project, config]) => {
if (typeof config === 'string') {
const configFileLocation = joinPathFragments(config, 'project.json');
workspaceJson.projects[project] = readJson<
ProjectConfiguration & NxJsonProjectConfiguration
>(tree, configFileLocation);
workspaceJson.projects[project] = readJson<ProjectConfiguration>(
tree,
configFileLocation
);
}
});
return workspaceJson as WorkspaceJsonConfiguration;
}
function readRawWorkspaceJson(tree: Tree): RawWorkspaceJsonConfiguration {
const path = getWorkspacePath(tree);
return readJson<RawWorkspaceJsonConfiguration>(tree, path);
}
/**
* @description Determine where a project's configuration is located.
* @returns file path if separate from root config, null otherwise.
*/
function getProjectFileLocation(tree: Tree, project: string): string | null {
const rawWorkspace = readJson<RawWorkspaceJsonConfiguration>(
tree,
getWorkspacePath(tree)
);
const rawWorkspace = readRawWorkspaceJson(tree);
const projectConfig = rawWorkspace.projects?.[project];
return typeof projectConfig === 'string'
? joinPathFragments(projectConfig, 'project.json')

View File

@ -21,7 +21,6 @@ export function createTreeWithEmptyWorkspace(version = 1): Tree {
'/nx.json',
JSON.stringify({
npmScope: 'proj',
projects: {},
affected: {
defaultBase: 'main',
},

View File

@ -10,9 +10,8 @@ import { Workspaces } from '@nrwl/tao/src/shared/workspace';
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function convertNxExecutor(executor: Executor) {
const builderFunction = (options, builderContext) => {
const workspaceConfig = new Workspaces(
builderContext.workspaceRoot
).readWorkspaceConfiguration();
const workspaces = new Workspaces(builderContext.workspaceRoot);
const workspaceConfig = workspaces.readWorkspaceConfiguration();
const context: ExecutorContext = {
root: builderContext.workspaceRoot,
projectName: builderContext.target.project,

View File

@ -1,4 +1,8 @@
import { addDependenciesToPackageJson, Tree } from '@nrwl/devkit';
import {
addDependenciesToPackageJson,
NxJsonConfiguration,
Tree,
} from '@nrwl/devkit';
import { expressVersion } from '../../utils/versions';
import initGenerator from './init';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
@ -36,8 +40,8 @@ describe('init', () => {
describe('defaultCollection', () => {
it('should be set if none was set before', async () => {
await initGenerator(tree, {});
const workspaceJson = readJson(tree, 'workspace.json');
expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/express');
const { cli } = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(cli.defaultCollection).toEqual('@nrwl/express');
});
});

View File

@ -1,4 +1,4 @@
import { NxJsonConfiguration } from '@nrwl/devkit';
import { NxJsonConfiguration, readProjectConfiguration } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { applicationGenerator } from './application';
import { readJson, Tree } from '@nrwl/devkit';
@ -19,23 +19,31 @@ describe('app', () => {
standaloneConfig: false,
});
const workspaceJson = readJson(tree, '/workspace.json');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(workspaceJson.projects['my-app'].root).toEqual('apps/my-app');
expect(workspaceJson.projects['my-app-e2e'].root).toEqual(
'apps/my-app-e2e'
);
expect(workspaceJson.defaultProject).toEqual('my-app');
expect(nxJson.defaultProject).toEqual('my-app');
});
it('should update nx.json', async () => {
it('should update tags + implicitDependencies', async () => {
await applicationGenerator(tree, {
name: 'myApp',
style: 'css',
tags: 'one,two',
standaloneConfig: false,
});
const nxJson = readJson<NxJsonConfiguration>(tree, '/nx.json');
expect(nxJson.projects).toEqual({
const myAppConfig = readProjectConfiguration(tree, 'my-app');
const myAppConfigE2E = readProjectConfiguration(tree, 'my-app-e2e');
expect({
'my-app': { tags: myAppConfig.tags },
'my-app-e2e': {
tags: myAppConfigE2E.tags,
implicitDependencies: myAppConfigE2E.implicitDependencies,
},
}).toEqual({
'my-app': {
tags: ['one', 'two'],
},
@ -77,10 +85,10 @@ describe('app', () => {
`import * as styles from './index.module.scss'`
);
const workspaceJson = readJson(tree, '/workspace.json');
expect(
workspaceJson.schematics['@nrwl/gatsby'].application.style
).toEqual('scss');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual(
'scss'
);
});
});
@ -102,10 +110,10 @@ describe('app', () => {
`import * as styles from './index.module.less'`
);
const workspaceJson = readJson(tree, '/workspace.json');
expect(
workspaceJson.schematics['@nrwl/gatsby'].application.style
).toEqual('less');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual(
'less'
);
});
});
@ -127,10 +135,10 @@ describe('app', () => {
`import * as styles from './index.module.styl'`
);
const workspaceJson = readJson(tree, '/workspace.json');
expect(
workspaceJson.schematics['@nrwl/gatsby'].application.style
).toEqual('styl');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual(
'styl'
);
});
});
@ -153,10 +161,10 @@ describe('app', () => {
);
expect(indexContent).toContain(`import styled from 'styled-components'`);
const workspaceJson = readJson(tree, '/workspace.json');
expect(
workspaceJson.schematics['@nrwl/gatsby'].application.style
).toEqual('styled-components');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual(
'styled-components'
);
});
});
@ -179,10 +187,10 @@ describe('app', () => {
);
expect(indexContent).toContain(`import styled from '@emotion/styled'`);
const workspaceJson = readJson(tree, '/workspace.json');
expect(
workspaceJson.schematics['@nrwl/gatsby'].application.style
).toEqual('@emotion/styled');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual(
'@emotion/styled'
);
});
});
@ -210,10 +218,10 @@ describe('app', () => {
`import styled from 'styled-components'`
);
const workspaceJson = readJson(tree, '/workspace.json');
expect(
workspaceJson.schematics['@nrwl/gatsby'].application.style
).toEqual('styled-jsx');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(nxJson.generators['@nrwl/gatsby'].application.style).toEqual(
'styled-jsx'
);
});
});

View File

@ -2,16 +2,11 @@ import { NormalizedSchema } from './normalize-options';
import {
addProjectConfiguration,
joinPathFragments,
NxJsonProjectConfiguration,
ProjectConfiguration,
Tree,
} from '@nrwl/devkit';
export function addProject(host: Tree, options: NormalizedSchema) {
const nxConfig: NxJsonProjectConfiguration = {
tags: options.parsedTags,
};
const targets: Record<string, any> = {};
targets.build = {
@ -44,15 +39,13 @@ export function addProject(host: Tree, options: NormalizedSchema) {
sourceRoot: joinPathFragments(options.projectRoot, 'src'),
projectType: 'application',
targets,
tags: options.parsedTags,
};
addProjectConfiguration(
host,
options.projectName,
{
...project,
...nxConfig,
},
project,
options.standaloneConfig
);
}

View File

@ -1,5 +1,5 @@
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { readJson, Tree } from '@nrwl/devkit';
import { NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit';
import { gatsbyInitGenerator } from './init';
@ -21,8 +21,8 @@ describe('init', () => {
describe('defaultCollection', () => {
it('should be set if none was set before', async () => {
await gatsbyInitGenerator(tree, {});
const workspaceJson = readJson(tree, 'workspace.json');
expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/gatsby');
const { cli } = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(cli.defaultCollection).toEqual('@nrwl/gatsby');
});
});

View File

@ -49,6 +49,7 @@ describe('Jest Executor', () => {
},
},
},
npmScope: 'test',
},
target: {
executor: '@nrwl/jest:jest',

View File

@ -3,6 +3,7 @@ import { Hash, Hasher } from '@nrwl/workspace/src/core/hasher/hasher';
import { readJsonFile } from '@nrwl/workspace/src/utilities/fileutils';
import { appRootPath } from '@nrwl/tao/src/utils/app-root';
import { join } from 'path';
import { Workspaces } from '@nrwl/tao/src/shared/workspace';
export default async function run(
task: Task,
@ -15,9 +16,9 @@ export default async function run(
const command = hasher.hashCommand(task);
const sources = await hasher.hashSource(task);
const deps = allDeps(task.id, taskGraph);
const nxJson = readJsonFile(join(appRootPath, 'nx.json'));
const workspace = new Workspaces(appRootPath).readWorkspaceConfiguration();
const tags = hasher.hashArray(
deps.map((d) => (nxJson.projects[d].tags || []).join('|'))
deps.map((d) => (workspace.projects[d].tags || []).join('|'))
);
const context = await hasher.hashContext();
return {

View File

@ -89,6 +89,7 @@ describe('Linter Builder', () => {
targets: {},
},
},
npmScope: 'test',
},
isVerbose: false,
};

View File

@ -72,6 +72,7 @@ describe('Linter Builder', () => {
workspace: {
version: 2,
projects: {},
npmScope: 'test',
},
isVerbose: false,
};

View File

@ -26,7 +26,6 @@ describe('Update implicitDependencies within nx.json to include root .eslintrc.j
workspaceLayout: {
libsDir: 'packages',
},
projects: {},
affected: {
defaultBase: 'main',
},

View File

@ -56,37 +56,10 @@ Object {
exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 2`] = `
Object {
"projects": Object {
"foo": Object {
"architect": Object {
"lint": Object {
"builder": "@angular-devkit/build-angular:tslint",
"options": Object {
"exclude": Array [
"**/node_modules/**",
"!apps/foo/**/*",
],
"tsConfig": Array [
"apps/foo/tsconfig.app.json",
],
},
},
},
"projectType": "application",
"root": "apps/foo",
"schematics": Object {
"@nrwl/angular:application": Object {
"e2eTestRunner": "cypress",
"linter": "eslint",
"unitTestRunner": "jest",
},
"@nrwl/angular:library": Object {
"linter": "tslint",
},
},
},
"affected": Object {
"defaultBase": "main",
},
"schematics": Object {
"generators": Object {
"@nrwl/angular": Object {
"application": Object {
"linter": "tslint",
@ -96,11 +69,55 @@ Object {
},
},
},
"version": 1,
"npmScope": "proj",
"tasksRunnerOptions": Object {
"default": Object {
"options": Object {
"cacheableOperations": Array [
"build",
"lint",
"test",
"e2e",
],
},
"runner": "@nrwl/workspace/tasks-runners/default",
},
},
}
`;
exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 3`] = `
Object {
"generators": Object {
"@nrwl/angular:application": Object {
"e2eTestRunner": "cypress",
"linter": "eslint",
"unitTestRunner": "jest",
},
"@nrwl/angular:library": Object {
"linter": "tslint",
},
},
"projectType": "application",
"root": "apps/foo",
"targets": Object {
"lint": Object {
"executor": "@angular-devkit/build-angular:tslint",
"options": Object {
"exclude": Array [
"**/node_modules/**",
"!apps/foo/**/*",
],
"tsConfig": Array [
"apps/foo/tsconfig.app.json",
],
},
},
},
}
`;
exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 4`] = `
Object {
"dependencies": Object {},
"devDependencies": Object {},
@ -108,163 +125,112 @@ Object {
}
`;
exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 4`] = `
exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 5`] = `
Object {
"projects": Object {
"foo": Object {
"architect": Object {
"lint": Object {
"builder": "@angular-devkit/build-angular:tslint",
"options": Object {
"exclude": Array [
"**/node_modules/**",
"!apps/foo/**/*",
],
"tsConfig": Array [
"apps/foo/tsconfig.app.json",
],
},
},
"affected": Object {
"defaultBase": "main",
},
"npmScope": "proj",
"tasksRunnerOptions": Object {
"default": Object {
"options": Object {
"cacheableOperations": Array [
"build",
"lint",
"test",
"e2e",
],
},
"projectType": "application",
"root": "apps/foo",
"schematics": Object {
"@nrwl/angular:application": Object {
"e2eTestRunner": "cypress",
"unitTestRunner": "jest",
},
"runner": "@nrwl/workspace/tasks-runners/default",
},
},
}
`;
exports[`ProjectConverter removeTSLintFromWorkspace() should remove all relevant traces of TSLint from the workspace 6`] = `
Object {
"generators": Object {
"@nrwl/angular:application": Object {
"e2eTestRunner": "cypress",
"unitTestRunner": "jest",
},
},
"projectType": "application",
"root": "apps/foo",
"targets": Object {
"lint": Object {
"executor": "@angular-devkit/build-angular:tslint",
"options": Object {
"exclude": Array [
"**/node_modules/**",
"!apps/foo/**/*",
],
"tsConfig": Array [
"apps/foo/tsconfig.app.json",
],
},
},
},
"schematics": Object {
"@nrwl/angular": Object {
"application": Object {
"linter": "tslint",
},
"library": Object {
"linter": "tslint",
},
},
},
"version": 1,
}
`;
exports[`ProjectConverter removeTSLintFromWorkspace() should remove the entry in generators for convert-tslint-to-eslint because it is no longer needed 1`] = `
Object {
"projects": Object {
"foo": Object {
"architect": Object {
"lint": Object {
"builder": "@angular-devkit/build-angular:tslint",
"options": Object {
"exclude": Array [
"**/node_modules/**",
"!apps/foo/**/*",
],
"tsConfig": Array [
"apps/foo/tsconfig.app.json",
],
},
},
},
"projectType": "application",
"root": "apps/foo",
"schematics": Object {
"@nrwl/angular:application": Object {
"e2eTestRunner": "cypress",
"linter": "eslint",
"unitTestRunner": "jest",
},
"@nrwl/angular:library": Object {
"linter": "tslint",
},
},
},
"affected": Object {
"defaultBase": "main",
},
"schematics": Object {
"generators": Object {
"@nrwl/angular": Object {
"convert-tslint-to-eslint": Object {
"removeTSLintIfNoMoreTSLintTargets": true,
},
},
},
"version": 1,
"npmScope": "proj",
"tasksRunnerOptions": Object {
"default": Object {
"options": Object {
"cacheableOperations": Array [
"build",
"lint",
"test",
"e2e",
],
},
"runner": "@nrwl/workspace/tasks-runners/default",
},
},
}
`;
exports[`ProjectConverter removeTSLintFromWorkspace() should remove the entry in generators for convert-tslint-to-eslint because it is no longer needed 2`] = `
Object {
"projects": Object {
"foo": Object {
"architect": Object {
"lint": Object {
"builder": "@angular-devkit/build-angular:tslint",
"options": Object {
"exclude": Array [
"**/node_modules/**",
"!apps/foo/**/*",
],
"tsConfig": Array [
"apps/foo/tsconfig.app.json",
],
},
},
},
"projectType": "application",
"root": "apps/foo",
"schematics": Object {
"@nrwl/angular:application": Object {
"e2eTestRunner": "cypress",
"unitTestRunner": "jest",
},
"affected": Object {
"defaultBase": "main",
},
"npmScope": "proj",
"tasksRunnerOptions": Object {
"default": Object {
"options": Object {
"cacheableOperations": Array [
"build",
"lint",
"test",
"e2e",
],
},
"runner": "@nrwl/workspace/tasks-runners/default",
},
},
"schematics": Object {
"@nrwl/angular": Object {
"convert-tslint-to-eslint": Object {
"removeTSLintIfNoMoreTSLintTargets": true,
},
},
},
"version": 1,
}
`;
exports[`ProjectConverter setDefaults() should save in workspace.json 1`] = `
exports[`ProjectConverter setDefaults() should save in nx.json 1`] = `
Object {
"projects": Object {
"foo": Object {
"architect": Object {
"lint": Object {
"builder": "@angular-devkit/build-angular:tslint",
"options": Object {
"exclude": Array [
"**/node_modules/**",
"!apps/foo/**/*",
],
"tsConfig": Array [
"apps/foo/tsconfig.app.json",
],
},
},
},
"projectType": "application",
"root": "apps/foo",
"schematics": Object {
"@nrwl/angular:application": Object {
"e2eTestRunner": "cypress",
"linter": "eslint",
"unitTestRunner": "jest",
},
"@nrwl/angular:library": Object {
"linter": "tslint",
},
},
},
"affected": Object {
"defaultBase": "main",
},
"schematics": Object {
"generators": Object {
"@nrwl/angular": Object {
"application": Object {
"linter": "tslint",
@ -274,43 +240,29 @@ Object {
},
},
},
"version": 1,
"npmScope": "proj",
"tasksRunnerOptions": Object {
"default": Object {
"options": Object {
"cacheableOperations": Array [
"build",
"lint",
"test",
"e2e",
],
},
"runner": "@nrwl/workspace/tasks-runners/default",
},
},
}
`;
exports[`ProjectConverter setDefaults() should save in workspace.json 2`] = `
exports[`ProjectConverter setDefaults() should save in nx.json 2`] = `
Object {
"projects": Object {
"foo": Object {
"architect": Object {
"lint": Object {
"builder": "@angular-devkit/build-angular:tslint",
"options": Object {
"exclude": Array [
"**/node_modules/**",
"!apps/foo/**/*",
],
"tsConfig": Array [
"apps/foo/tsconfig.app.json",
],
},
},
},
"projectType": "application",
"root": "apps/foo",
"schematics": Object {
"@nrwl/angular:application": Object {
"e2eTestRunner": "cypress",
"linter": "eslint",
"unitTestRunner": "jest",
},
"@nrwl/angular:library": Object {
"linter": "tslint",
},
},
},
"affected": Object {
"defaultBase": "main",
},
"schematics": Object {
"generators": Object {
"@nrwl/angular": Object {
"application": Object {
"linter": "tslint",
@ -324,43 +276,29 @@ Object {
},
},
},
"version": 1,
"npmScope": "proj",
"tasksRunnerOptions": Object {
"default": Object {
"options": Object {
"cacheableOperations": Array [
"build",
"lint",
"test",
"e2e",
],
},
"runner": "@nrwl/workspace/tasks-runners/default",
},
},
}
`;
exports[`ProjectConverter setDefaults() should save in workspace.json 3`] = `
exports[`ProjectConverter setDefaults() should save in nx.json 3`] = `
Object {
"projects": Object {
"foo": Object {
"architect": Object {
"lint": Object {
"builder": "@angular-devkit/build-angular:tslint",
"options": Object {
"exclude": Array [
"**/node_modules/**",
"!apps/foo/**/*",
],
"tsConfig": Array [
"apps/foo/tsconfig.app.json",
],
},
},
},
"projectType": "application",
"root": "apps/foo",
"schematics": Object {
"@nrwl/angular:application": Object {
"e2eTestRunner": "cypress",
"linter": "eslint",
"unitTestRunner": "jest",
},
"@nrwl/angular:library": Object {
"linter": "tslint",
},
},
},
"affected": Object {
"defaultBase": "main",
},
"schematics": Object {
"generators": Object {
"@nrwl/angular": Object {
"application": Object {
"linter": "tslint",
@ -374,7 +312,20 @@ Object {
},
},
},
"version": 1,
"npmScope": "proj",
"tasksRunnerOptions": Object {
"default": Object {
"options": Object {
"cacheableOperations": Array [
"build",
"lint",
"test",
"e2e",
],
},
"runner": "@nrwl/workspace/tasks-runners/default",
},
},
}
`;

View File

@ -1,10 +1,10 @@
import {
addDependenciesToPackageJson,
addProjectConfiguration,
NxJsonConfiguration,
readJson,
readWorkspaceConfiguration,
readProjectConfiguration,
Tree,
updateWorkspaceConfiguration,
writeJson,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
@ -262,7 +262,7 @@ describe('ProjectConverter', () => {
});
describe('setDefaults()', () => {
it('should save in workspace.json', async () => {
it('should save in nx.json', async () => {
writeJson(host, 'tslint.json', {});
writeJson(host, `${projectRoot}/tslint.json`, {});
@ -273,8 +273,8 @@ describe('ProjectConverter', () => {
eslintInitializer: () => undefined,
});
const workspace = readWorkspaceConfiguration(host);
workspace.generators = {
const nxJson = readJson<NxJsonConfiguration>(host, 'nx.json');
nxJson.generators = {
'@nrwl/angular': {
application: {
linter: 'tslint',
@ -284,10 +284,10 @@ describe('ProjectConverter', () => {
},
},
};
updateWorkspaceConfiguration(host, workspace);
writeJson(host, 'nx.json', nxJson);
// BEFORE - no entry for convert-tslint-to-eslint wthin @nrwl/angular generators
expect(readJson(host, 'workspace.json')).toMatchSnapshot();
expect(readJson(host, 'nx.json')).toMatchSnapshot();
projectConverter.setDefaults('@nrwl/angular', {
ignoreExistingTslintConfig: true,
@ -295,7 +295,7 @@ describe('ProjectConverter', () => {
});
// AFTER (1) - convert-tslint-to-eslint wthin @nrwl/angular generators has removeTSLintIfNoMoreTSLintTargets set to true
expect(readJson(host, 'workspace.json')).toMatchSnapshot();
expect(readJson(host, 'nx.json')).toMatchSnapshot();
projectConverter.setDefaults('@nrwl/angular', {
ignoreExistingTslintConfig: false,
@ -303,7 +303,7 @@ describe('ProjectConverter', () => {
});
// AFTER (2) - convert-tslint-to-eslint wthin @nrwl/angular generators has removeTSLintIfNoMoreTSLintTargets set to false
expect(readJson(host, 'workspace.json')).toMatchSnapshot();
expect(readJson(host, 'nx.json')).toMatchSnapshot();
});
});
@ -328,9 +328,9 @@ describe('ProjectConverter', () => {
}
)();
const workspace = readWorkspaceConfiguration(host);
const nxJson = readJson<NxJsonConfiguration>(host, 'nx.json');
// Not using shorthand syntax this time
workspace.generators = {
nxJson.generators = {
'@nrwl/angular': {
application: {
linter: 'tslint',
@ -340,21 +340,26 @@ describe('ProjectConverter', () => {
},
},
};
updateWorkspaceConfiguration(host, workspace);
writeJson(host, 'nx.json', nxJson);
// BEFORE - tslint and codelyzer are present
expect(readJson(host, 'package.json')).toMatchSnapshot();
// BEFORE - tslint set as both global and project-level default linter for @nrwl/angular generators
expect(readJson(host, 'workspace.json')).toMatchSnapshot();
// BEFORE - tslint set as both global linter for @nrwl/angular generators
expect(readJson(host, 'nx.json')).toMatchSnapshot();
expect(readProjectConfiguration(host, projectName)).toMatchSnapshot();
await projectConverter.removeTSLintFromWorkspace()();
// AFTER - it should remove tslint and codelyzer
expect(readJson(host, 'package.json')).toMatchSnapshot();
// AFTER - generators config from global and project-level settings removed (because eslint is always default)
expect(readJson(host, 'workspace.json')).toMatchSnapshot();
// AFTER - generators config from global project-level settings removed (because eslint is always default)
expect(readJson(host, 'nx.json')).toMatchSnapshot();
// AFTER - generators config from project-level settings removed (because eslint is always default)
expect(readProjectConfiguration(host, projectName)).toMatchSnapshot();
});
it('should remove the entry in generators for convert-tslint-to-eslint because it is no longer needed', async () => {
@ -368,23 +373,23 @@ describe('ProjectConverter', () => {
eslintInitializer: () => undefined,
});
const workspace = readWorkspaceConfiguration(host);
workspace.generators = {
const nxJson = readJson<NxJsonConfiguration>(host, 'nx.json');
nxJson.generators = {
'@nrwl/angular': {
'convert-tslint-to-eslint': {
removeTSLintIfNoMoreTSLintTargets: true,
},
},
};
updateWorkspaceConfiguration(host, workspace);
writeJson(host, 'nx.json', nxJson);
// BEFORE - convert-tslint-to-eslint wthin @nrwl/angular generators has a value for removeTSLintIfNoMoreTSLintTargets
expect(readJson(host, 'workspace.json')).toMatchSnapshot();
expect(readJson(host, 'nx.json')).toMatchSnapshot();
await projectConverter.removeTSLintFromWorkspace()();
// AFTER - generators config no longer has a reference to convert-tslint-to-eslint
expect(readJson(host, 'workspace.json')).toMatchSnapshot();
expect(readJson(host, 'nx.json')).toMatchSnapshot();
});
});
});

View File

@ -15,7 +15,6 @@ import {
import type {
Tree,
GeneratorCallback,
NxJsonProjectConfiguration,
ProjectConfiguration,
} from '@nrwl/devkit';
import type { Linter } from 'eslint';
@ -56,8 +55,7 @@ export interface ConvertTSLintToESLintSchema {
* and it will extend from the root workspace .eslintrc.json file as normal.
*/
export class ProjectConverter {
private readonly projectConfig: ProjectConfiguration &
NxJsonProjectConfiguration;
private readonly projectConfig: ProjectConfiguration;
private readonly rootTSLintJsonPath = 'tslint.json';
private readonly rootTSLintJson: Record<string, unknown>;
private readonly projectTSLintJsonPath: string;
@ -67,7 +65,7 @@ export class ProjectConverter {
private readonly ignoreExistingTslintConfig: boolean;
private readonly eslintInitializer: (projectInfo: {
projectName: string;
projectConfig: ProjectConfiguration & NxJsonProjectConfiguration;
projectConfig: ProjectConfiguration;
}) => Promise<void>;
/**
@ -86,7 +84,7 @@ export class ProjectConverter {
ignoreExistingTslintConfig: boolean;
eslintInitializer: (projectInfo: {
projectName: string;
projectConfig: ProjectConfiguration & NxJsonProjectConfiguration;
projectConfig: ProjectConfiguration;
}) => Promise<void>;
}) {
this.host = host;

View File

@ -39,19 +39,22 @@ describe('init generator', () => {
it('should set @nrwl/nest as the default collection when none was set before', async () => {
await initGenerator(tree, {});
const workspaceJson = devkit.readJson(tree, 'workspace.json');
expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/nest');
const { cli } = devkit.readJson<devkit.NxJsonConfiguration>(
tree,
'nx.json'
);
expect(cli.defaultCollection).toEqual('@nrwl/nest');
});
it('should not set @nrwl/nest as the default collection when another one was set before', async () => {
devkit.updateJson(tree, 'workspace.json', (json) => ({
devkit.updateJson(tree, 'nx.json', (json) => ({
...json,
cli: { defaultCollection: '@nrwl/node' },
}));
await initGenerator(tree, {});
const workspaceJson = devkit.readJson(tree, 'workspace.json');
const workspaceJson = devkit.readJson(tree, 'nx.json');
expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/node');
});

View File

@ -111,14 +111,14 @@ describe('lib', () => {
).toMatchSnapshot();
});
it('should update nx.json', async () => {
it('should update tags', async () => {
await libraryGenerator(tree, { name: libName, tags: 'one,two' });
const nxJson = readJson<NxJsonConfiguration>(tree, '/nx.json');
expect(nxJson.projects).toEqual({
[libFileName]: {
const projects = Object.fromEntries(devkit.getProjects(tree));
expect(projects).toEqual({
[libFileName]: expect.objectContaining({
tags: ['one', 'two'],
},
}),
});
});
@ -177,16 +177,16 @@ describe('lib', () => {
const dirFileName = 'my-dir';
const nestedLibFileName = `${dirFileName}-${libFileName}`;
it('should update nx.json', async () => {
it('should update tags', async () => {
await libraryGenerator(tree, {
name: libName,
directory: dirName,
tags: 'one,two',
});
const nxJson = readJson<NxJsonConfiguration>(tree, '/nx.json');
expect(nxJson.projects).toEqual({
[nestedLibFileName]: { tags: ['one', 'two'] },
const projects = Object.fromEntries(devkit.getProjects(tree));
expect(projects).toEqual({
[nestedLibFileName]: expect.objectContaining({ tags: ['one', 'two'] }),
});
});

View File

@ -1,6 +1,6 @@
import { Linter } from '@nrwl/linter';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { readJson, Tree } from '@nrwl/devkit';
import { getProjects, readJson, NxJsonConfiguration, Tree } from '@nrwl/devkit';
import { applicationGenerator } from './application';
@ -12,7 +12,7 @@ describe('app', () => {
});
describe('not nested', () => {
it('should update workspace.json', async () => {
it('should update workspace.json and set defaultProject', async () => {
await applicationGenerator(tree, {
name: 'myApp',
style: 'css',
@ -20,15 +20,16 @@ describe('app', () => {
});
const workspaceJson = readJson(tree, 'workspace.json');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(workspaceJson.projects['my-app'].root).toEqual('apps/my-app');
expect(workspaceJson.projects['my-app-e2e'].root).toEqual(
'apps/my-app-e2e'
);
expect(workspaceJson.defaultProject).toEqual('my-app');
expect(nxJson.defaultProject).toEqual('my-app');
});
it('should update nx.json', async () => {
it('should update tags and implicit dependencies', async () => {
await applicationGenerator(tree, {
name: 'myApp',
style: 'css',
@ -36,9 +37,9 @@ describe('app', () => {
standaloneConfig: false,
});
const nxJson = readJson(tree, 'nx.json');
const projects = Object.fromEntries(getProjects(tree));
expect(nxJson.projects).toMatchObject({
expect(projects).toMatchObject({
'my-app': {
tags: ['one', 'two'],
},

View File

@ -2,16 +2,11 @@ import { NormalizedSchema } from './normalize-options';
import {
addProjectConfiguration,
joinPathFragments,
NxJsonProjectConfiguration,
ProjectConfiguration,
Tree,
} from '@nrwl/devkit';
export function addProject(host: Tree, options: NormalizedSchema) {
const nxConfig: NxJsonProjectConfiguration = {
tags: options.parsedTags,
};
const targets: Record<string, any> = {};
targets.build = {
@ -61,6 +56,7 @@ export function addProject(host: Tree, options: NormalizedSchema) {
sourceRoot: options.appProjectRoot,
projectType: 'application',
targets,
tags: options.parsedTags,
};
addProjectConfiguration(
@ -68,7 +64,6 @@ export function addProject(host: Tree, options: NormalizedSchema) {
options.projectName,
{
...project,
...nxConfig,
},
options.standaloneConfig
);

View File

@ -1,5 +1,5 @@
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { readJson, Tree } from '@nrwl/devkit';
import { readJson, NxJsonConfiguration, Tree } from '@nrwl/devkit';
import { nextInitGenerator } from './init';
@ -21,8 +21,8 @@ describe('init', () => {
describe('defaultCollection', () => {
it('should be set if none was set before', async () => {
await nextInitGenerator(tree, {});
const workspaceJson = readJson(tree, 'workspace.json');
expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/next');
const { cli } = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(cli.defaultCollection).toEqual('@nrwl/next');
});
});

View File

@ -35,6 +35,7 @@ describe('Node Build Executor', () => {
sourceRoot: 'apps/wibble',
},
},
npmScope: 'test',
},
isVerbose: false,
};

View File

@ -62,6 +62,7 @@ describe('NodeExecuteBuilder', () => {
},
},
},
npmScope: 'test',
},
isVerbose: false,
};

View File

@ -71,6 +71,7 @@ describe('NodePackageBuilder', () => {
targets: {},
},
},
npmScope: 'test',
},
isVerbose: false,
};

View File

@ -1,4 +1,4 @@
import { NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit';
import { NxJsonConfiguration, readJson, Tree, getProjects } from '@nrwl/devkit';
import * as devkit from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
@ -38,6 +38,7 @@ describe('app', () => {
standaloneConfig: false,
});
const workspaceJson = readJson(tree, '/workspace.json');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
const project = workspaceJson.projects['my-node-app'];
expect(project.root).toEqual('apps/my-node-app');
expect(project.architect).toEqual(
@ -81,17 +82,17 @@ describe('app', () => {
},
});
expect(workspaceJson.projects['my-node-app-e2e']).toBeUndefined();
expect(workspaceJson.defaultProject).toEqual('my-node-app');
expect(nxJson.defaultProject).toEqual('my-node-app');
});
it('should update nx.json', async () => {
it('should update tags', async () => {
await applicationGenerator(tree, {
name: 'myNodeApp',
tags: 'one,two',
standaloneConfig: false,
});
const nxJson = readJson<NxJsonConfiguration>(tree, '/nx.json');
expect(nxJson.projects).toEqual({
const projects = Object.fromEntries(getProjects(tree));
expect(projects).toMatchObject({
'my-node-app': {
tags: ['one', 'two'],
},
@ -174,6 +175,7 @@ describe('app', () => {
standaloneConfig: false,
});
const workspaceJson = readJson(tree, '/workspace.json');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(workspaceJson.projects['my-dir-my-node-app'].root).toEqual(
'apps/my-dir/my-node-app'
@ -190,18 +192,18 @@ describe('app', () => {
});
expect(workspaceJson.projects['my-dir-my-node-app-e2e']).toBeUndefined();
expect(workspaceJson.defaultProject).toEqual('my-dir-my-node-app');
expect(nxJson.defaultProject).toEqual('my-dir-my-node-app');
});
it('should update nx.json', async () => {
it('should update tags', async () => {
await applicationGenerator(tree, {
name: 'myNodeApp',
directory: 'myDir',
tags: 'one,two',
standaloneConfig: false,
});
const nxJson = readJson<NxJsonConfiguration>(tree, '/nx.json');
expect(nxJson.projects).toEqual({
const projects = Object.fromEntries(getProjects(tree));
expect(projects).toMatchObject({
'my-dir-my-node-app': {
tags: ['one', 'two'],
},

View File

@ -8,7 +8,6 @@ import {
joinPathFragments,
logger,
names,
NxJsonProjectConfiguration,
offsetFromRoot,
ProjectConfiguration,
readProjectConfiguration,
@ -83,7 +82,7 @@ function getServeConfig(options: NormalizedSchema): TargetConfiguration {
}
function addProject(tree: Tree, options: NormalizedSchema) {
const project: ProjectConfiguration & NxJsonProjectConfiguration = {
const project: ProjectConfiguration = {
root: options.appProjectRoot,
sourceRoot: joinPathFragments(options.appProjectRoot, 'src'),
projectType: 'application',

View File

@ -1,4 +1,9 @@
import { addDependenciesToPackageJson, readJson, Tree } from '@nrwl/devkit';
import {
addDependenciesToPackageJson,
NxJsonConfiguration,
readJson,
Tree,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { nxVersion } from '../../utils/versions';
@ -38,8 +43,8 @@ describe('init', () => {
describe('defaultCollection', () => {
it('should be set if none was set before', async () => {
await initGenerator(tree, {});
const workspaceJson = readJson(tree, 'workspace.json');
expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/node');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(nxJson.cli.defaultCollection).toEqual('@nrwl/node');
});
});

View File

@ -1,4 +1,4 @@
import { NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit';
import { getProjects, NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { Schema } from './schema.d';
@ -48,14 +48,14 @@ describe('lib', () => {
).toEqual('./src');
});
it('should update nx.json', async () => {
it('should update tags', async () => {
await libraryGenerator(tree, {
name: 'myLib',
tags: 'one,two',
standaloneConfig: false,
});
const nxJson = readJson<NxJsonConfiguration>(tree, '/nx.json');
expect(nxJson.projects).toEqual({
const projects = Object.fromEntries(getProjects(tree));
expect(projects).toMatchObject({
'my-lib': {
tags: ['one', 'two'],
},
@ -148,15 +148,15 @@ describe('lib', () => {
});
describe('nested', () => {
it('should update nx.json', async () => {
it('should update tags', async () => {
await libraryGenerator(tree, {
name: 'myLib',
directory: 'myDir',
tags: 'one',
standaloneConfig: false,
});
const nxJson = readJson<NxJsonConfiguration>(tree, '/nx.json');
expect(nxJson.projects).toEqual({
let projects = Object.fromEntries(getProjects(tree));
expect(projects).toMatchObject({
'my-dir-my-lib': {
tags: ['one'],
},
@ -168,8 +168,8 @@ describe('lib', () => {
tags: 'one,two',
standaloneConfig: false,
});
const nxJson2 = readJson<NxJsonConfiguration>(tree, '/nx.json');
expect(nxJson2.projects).toEqual({
projects = Object.fromEntries(getProjects(tree));
expect(projects).toMatchObject({
'my-dir-my-lib': {
tags: ['one'],
},

View File

@ -3,6 +3,7 @@ import {
addProjectConfiguration,
readProjectConfiguration,
readJson,
getProjects,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { e2eProjectGenerator } from './e2e';
@ -66,20 +67,18 @@ describe('NxPlugin e2e-project Generator', () => {
expect(project.root).toBe('apps/namespace/my-plugin-e2e');
});
it('should update the nxJson', async () => {
it('should update the tags and implicit dependencies', async () => {
await e2eProjectGenerator(tree, {
pluginName: 'my-plugin',
pluginOutputPath: `dist/libs/my-plugin`,
npmPackageName: '@proj/my-plugin',
standaloneConfig: false,
});
expect(readJson(tree, 'nx.json')).toMatchObject({
projects: {
'my-plugin-e2e': {
tags: [],
implicitDependencies: ['my-plugin'],
},
const projects = Object.fromEntries(getProjects(tree));
expect(projects).toMatchObject({
'my-plugin-e2e': {
tags: [],
implicitDependencies: ['my-plugin'],
},
});
});

View File

@ -27,14 +27,14 @@ describe('<%= pluginName %> e2e', () => {
});
describe('--tags', () => {
it('should add tags to nx.json', async () => {
it('should add tags to the project', async () => {
const plugin = uniq('<%= pluginName %>');
ensureNxProject('<%= npmPackageName %>', '<%= pluginOutputPath %>');
await runNxCommandAsync(
`generate <%=npmPackageName%>:<%= pluginName %> ${plugin} --tags e2etag,e2ePackage`
);
const nxJson = readJson('nx.json');
expect(nxJson.projects[plugin].tags).toEqual(['e2etag', 'e2ePackage']);
const workspace = readJson('workspace.json');
expect(workspace.projects[plugin].tags).toEqual(['e2etag', 'e2ePackage']);
}, 120000);
});
})

View File

@ -39,13 +39,10 @@ describe('app', () => {
e2eTestRunner: 'none',
});
const nxJson = readJson(appTree, '/nx.json');
expect(nxJson).toMatchObject({
npmScope: 'proj',
projects: {
'my-app': {
tags: ['one', 'two'],
},
const { projects } = readJson(appTree, '/workspace.json');
expect(projects).toMatchObject({
'my-app': {
tags: ['one', 'two'],
},
});
});

View File

@ -1,6 +1,5 @@
import {
addProjectConfiguration,
NxJsonProjectConfiguration,
ProjectConfiguration,
readWorkspaceConfiguration,
TargetConfiguration,
@ -10,20 +9,16 @@ import {
import { NormalizedSchema } from './normalize-options';
export function addProject(host: Tree, options: NormalizedSchema) {
const nxConfig: NxJsonProjectConfiguration = {
tags: options.parsedTags,
};
const project: ProjectConfiguration = {
root: options.appProjectRoot,
sourceRoot: `${options.appProjectRoot}/src`,
projectType: 'application',
targets: { ...getTargets(options) },
tags: options.parsedTags,
};
addProjectConfiguration(host, options.projectName, {
...project,
...nxConfig,
});
const workspace = readWorkspaceConfiguration(host);

View File

@ -37,12 +37,12 @@ describe('init', () => {
describe('defaultCollection', () => {
it('should be set if none was set before', async () => {
await reactNativeInitGenerator(tree, { e2eTestRunner: 'none' });
const workspaceJson = readJson(tree, 'workspace.json');
expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/react-native');
const { cli } = readJson(tree, 'nx.json');
expect(cli.defaultCollection).toEqual('@nrwl/react-native');
});
it('should not be set if something else was set before', async () => {
updateJson(tree, 'workspace.json', (json) => {
updateJson(tree, 'nx.json', (json) => {
json.cli = {
defaultCollection: '@nrwl/react',
};
@ -52,8 +52,8 @@ describe('init', () => {
return json;
});
await reactNativeInitGenerator(tree, { e2eTestRunner: 'none' });
const workspaceJson = readJson(tree, 'workspace.json');
expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/react');
const { cli } = readJson(tree, 'nx.json');
expect(cli.defaultCollection).toEqual('@nrwl/react');
});
});
});

View File

@ -23,7 +23,7 @@ describe('lib', () => {
describe('not nested', () => {
it('should update workspace.json', async () => {
await libraryGenerator(appTree, defaultSchema);
await libraryGenerator(appTree, { ...defaultSchema, tags: 'one,two' });
const workspaceJson = readJson(appTree, '/workspace.json');
expect(workspaceJson.projects['my-lib'].root).toEqual('libs/my-lib');
expect(workspaceJson.projects['my-lib'].architect.build).toBeUndefined();
@ -34,16 +34,7 @@ describe('lib', () => {
lintFilePatterns: ['libs/my-lib/**/*.{ts,tsx,js,jsx}'],
},
});
});
it('should update nx.json', async () => {
await libraryGenerator(appTree, { ...defaultSchema, tags: 'one,two' });
const nxJson = readJson(appTree, '/nx.json');
expect(nxJson.projects).toEqual({
'my-lib': {
tags: ['one', 'two'],
},
});
expect(workspaceJson.projects['my-lib'].tags).toEqual(['one', 'two']);
});
it('should update tsconfig.base.json', async () => {
@ -108,8 +99,8 @@ describe('lib', () => {
directory: 'myDir',
tags: 'one',
});
const nxJson = readJson(appTree, '/nx.json');
expect(nxJson.projects).toEqual({
const workspaceJson = readJson(appTree, '/workspace.json');
expect(workspaceJson.projects).toMatchObject({
'my-dir-my-lib': {
tags: ['one'],
},
@ -122,8 +113,8 @@ describe('lib', () => {
tags: 'one,two',
});
const nxJson2 = readJson(appTree, '/nx.json');
expect(nxJson2.projects).toEqual({
const workspaceJson2 = readJson(appTree, '/workspace.json');
expect(workspaceJson2.projects).toMatchObject({
'my-dir-my-lib': {
tags: ['one'],
},

View File

@ -39,11 +39,11 @@ describe('app', () => {
expect(workspaceJson.defaultProject).toEqual('my-app');
});
it('should update nx.json', async () => {
it('should update tags and implicit dependencies', async () => {
await applicationGenerator(appTree, { ...schema, tags: 'one,two' });
const nxJson = readJson(appTree, './nx.json');
expect(nxJson.projects).toEqual({
const projects = Object.fromEntries(getProjects(appTree));
expect(projects).toMatchObject({
'my-app': {
tags: ['one', 'two'],
},
@ -132,15 +132,15 @@ Object {
);
});
it('should update nx.json', async () => {
it('should update tags and implicit deps', async () => {
await applicationGenerator(appTree, {
...schema,
directory: 'myDir',
tags: 'one,two',
});
const nxJson = readJson(appTree, '/nx.json');
expect(nxJson.projects).toEqual({
const projects = Object.fromEntries(getProjects(appTree));
expect(projects).toMatchObject({
'my-dir-my-app': {
tags: ['one', 'two'],
},

View File

@ -2,16 +2,11 @@ import { NormalizedSchema } from '../schema';
import {
joinPathFragments,
addProjectConfiguration,
NxJsonProjectConfiguration,
ProjectConfiguration,
TargetConfiguration,
} from '@nrwl/devkit';
export function addProject(host, options: NormalizedSchema) {
const nxConfig: NxJsonProjectConfiguration = {
tags: options.parsedTags,
};
const project: ProjectConfiguration = {
root: options.appProjectRoot,
sourceRoot: `${options.appProjectRoot}/src`,
@ -20,6 +15,7 @@ export function addProject(host, options: NormalizedSchema) {
build: createBuildTarget(options),
serve: createServeTarget(options),
},
tags: options.parsedTags,
};
addProjectConfiguration(
@ -27,7 +23,6 @@ export function addProject(host, options: NormalizedSchema) {
options.projectName,
{
...project,
...nxConfig,
},
options.standaloneConfig
);

View File

@ -1,4 +1,4 @@
import { readJson, readWorkspaceConfiguration, Tree } from '@nrwl/devkit';
import { NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import reactInitGenerator from './init';
import { InitSchema } from './schema';
@ -28,9 +28,12 @@ describe('init', () => {
describe('defaultCollection', () => {
it('should be set if none was set before', async () => {
await reactInitGenerator(tree, schema);
const workspace = readWorkspaceConfiguration(tree);
expect(workspace.cli.defaultCollection).toEqual('@nrwl/react');
expect(workspace.generators['@nrwl/react'].application.babel).toBe(true);
const { cli, generators } = readJson<NxJsonConfiguration>(
tree,
'nx.json'
);
expect(cli.defaultCollection).toEqual('@nrwl/react');
expect(generators['@nrwl/react'].application.babel).toBe(true);
});
});

View File

@ -1,4 +1,10 @@
import { getProjects, readJson, Tree, updateJson } from '@nrwl/devkit';
import {
getProjects,
readJson,
readProjectConfiguration,
Tree,
updateJson,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import libraryGenerator from './library';
import { Linter } from '@nrwl/linter';
@ -39,14 +45,14 @@ describe('lib', () => {
});
});
it('should update nx.json', async () => {
it('should update tags', async () => {
await libraryGenerator(appTree, { ...defaultSchema, tags: 'one,two' });
const nxJson = readJson(appTree, '/nx.json');
expect(nxJson.projects).toEqual({
'my-lib': {
const project = readProjectConfiguration(appTree, 'my-lib');
expect(project).toEqual(
expect.objectContaining({
tags: ['one', 'two'],
},
});
})
);
});
it('should add react and react-dom packages to package.json if not already present', async () => {
@ -170,18 +176,18 @@ describe('lib', () => {
});
describe('nested', () => {
it('should update nx.json', async () => {
it('should update tags and implicitDependencies', async () => {
await libraryGenerator(appTree, {
...defaultSchema,
directory: 'myDir',
tags: 'one',
});
const nxJson = readJson(appTree, '/nx.json');
expect(nxJson.projects).toEqual({
'my-dir-my-lib': {
const myLib = readProjectConfiguration(appTree, 'my-dir-my-lib');
expect(myLib).toEqual(
expect.objectContaining({
tags: ['one'],
},
});
})
);
await libraryGenerator(appTree, {
...defaultSchema,
@ -190,15 +196,12 @@ describe('lib', () => {
tags: 'one,two',
});
const nxJson2 = readJson(appTree, '/nx.json');
expect(nxJson2.projects).toEqual({
'my-dir-my-lib': {
tags: ['one'],
},
'my-dir-my-lib2': {
const myLib2 = readProjectConfiguration(appTree, 'my-dir-my-lib2');
expect(myLib2).toEqual(
expect.objectContaining({
tags: ['one', 'two'],
},
});
})
);
});
it('should generate files', async () => {

View File

@ -33,6 +33,7 @@ describe('Build storybook', () => {
targets: {},
},
},
npmScope: 'test',
},
isVerbose: false,
};

View File

@ -59,6 +59,7 @@ describe('@nrwl/storybook:storybook', () => {
targets: {},
},
},
npmScope: 'test',
},
isVerbose: false,
};

View File

@ -1,4 +1,9 @@
import { addDependenciesToPackageJson, readJson, Tree } from '@nrwl/devkit';
import {
addDependenciesToPackageJson,
NxJsonConfiguration,
readJson,
Tree,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { storybookVersion } from '../../utils/versions';
@ -258,7 +263,7 @@ describe('@nrwl/storybook:init', () => {
await initGenerator(tree, {
uiFramework: '@storybook/html',
});
const nxJson = readJson(tree, 'nx.json');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(
nxJson.tasksRunnerOptions.default.options.cacheableOperations
).toContain('build-storybook');
@ -268,7 +273,7 @@ describe('@nrwl/storybook:init', () => {
await initGenerator(tree, {
uiFramework: '@storybook/web-components',
});
const nxJson = readJson(tree, 'nx.json');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(
nxJson.tasksRunnerOptions.default.options.cacheableOperations
).toContain('build-storybook');
@ -278,7 +283,7 @@ describe('@nrwl/storybook:init', () => {
await initGenerator(tree, {
uiFramework: '@storybook/vue',
});
const nxJson = readJson(tree, 'nx.json');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(
nxJson.tasksRunnerOptions.default.options.cacheableOperations
).toContain('build-storybook');

View File

@ -7,10 +7,11 @@ import {
Schema,
} from '../shared/params';
import { printHelp } from '../shared/print-help';
import { WorkspaceJsonConfiguration, Workspaces } from '../shared/workspace';
import { Workspaces } from '../shared/workspace';
import { FileChange, flushChanges, FsTree } from '../shared/tree';
import { logger } from '../shared/logger';
import * as chalk from 'chalk';
import { NxJsonConfiguration } from '../shared/nx';
export interface GenerateOptions {
collectionName: string;
@ -125,8 +126,8 @@ export function printGenHelp(opts: GenerateOptions, schema: Schema) {
});
}
function readDefaultCollection(workspace: WorkspaceJsonConfiguration) {
return workspace.cli ? workspace.cli.defaultCollection : null;
function readDefaultCollection(nxConfig: NxJsonConfiguration) {
return nxConfig.cli ? nxConfig.cli.defaultCollection : null;
}
function printChanges(fileChanges: FileChange[]) {

View File

@ -14,6 +14,7 @@ import {
writeJsonFile,
} from '../utils/fileutils';
import { appRootPath } from '../utils/app-root';
import { NxJsonConfiguration } from '../shared/nx';
type Dependencies = 'dependencies' | 'devDependencies';
@ -618,7 +619,7 @@ async function generateMigrationsJsonAndUpdatePackageJson(
function showConnectToCloudMessage() {
try {
const nxJson = readJsonFile('nx.json');
const nxJson = readJsonFile<NxJsonConfiguration>('nx.json');
const defaultRunnerIsUsed = Object.values(nxJson.tasksRunnerOptions).find(
(r: any) => r.runner == '@nrwl/workspace/tasks-runners/default'
);

View File

@ -15,21 +15,24 @@ import { createConsoleLogger, NodeJsSyncHost } from '@angular-devkit/core/node';
import { Stats } from 'fs';
import { detectPackageManager } from '../shared/package-manager';
import { GenerateOptions } from './generate';
import { Tree } from '../shared/tree';
import { FileChange, Tree } from '../shared/tree';
import {
inlineProjectConfigurations,
ProjectConfiguration,
RawWorkspaceJsonConfiguration,
toNewFormat,
toNewFormatOrNull,
toOldFormatOrNull,
workspaceConfigName,
WorkspaceJsonConfiguration,
} from '../shared/workspace';
import { dirname, extname, resolve, join, basename } from 'path';
import { FileBuffer } from '@angular-devkit/core/src/virtual-fs/host/interface';
import { EMPTY, Observable, of, concat } from 'rxjs';
import { EMPTY, Observable, of, concat, combineLatest } from 'rxjs';
import { catchError, map, switchMap, tap, toArray } from 'rxjs/operators';
import { NX_ERROR, NX_PREFIX } from '../shared/logger';
import { readJsonFile } from '../utils/fileutils';
import { parseJson, serializeJson } from '../utils/json';
import { NxJsonConfiguration } from '../shared/nx';
export async function scheduleTarget(
root: string,
@ -191,43 +194,77 @@ async function runSchematic(
return { status: 0, loggingQueue: record.loggingQueue };
}
type AngularJsonConfiguration = WorkspaceJsonConfiguration &
Pick<NxJsonConfiguration, 'cli' | 'defaultProject' | 'generators'> & {
schematics?: NxJsonConfiguration['generators'];
};
export class NxScopedHost extends virtualFs.ScopedHost<any> {
constructor(root: Path) {
super(new NodeJsSyncHost(), root);
}
protected __readWorkspaceConfiguration = (
configFileName: ('workspace.json' | 'angular.json') & Path,
overrides?: {
workspace?: Observable<FileBuffer>;
nx?: Observable<FileBuffer>;
}
): Observable<FileBuffer> => {
return super.exists('nx.json' as Path).pipe(
switchMap((nxJsonExists) =>
(!nxJsonExists // if no nxJson, let it be undefined
? (overrides?.workspace || super.read(configFileName)).pipe(
map((x) => [x])
)
: combineLatest([
// read both values
overrides?.workspace || super.read(configFileName),
overrides?.nx || super.read('nx.json' as Path),
])
).pipe(
switchMap(([w, n]) => {
try {
// parse both from json, nxJson may be null
const workspaceJson: AngularJsonConfiguration = parseJson(
Buffer.from(w).toString()
);
const nxJson: NxJsonConfiguration | null = n
? parseJson(Buffer.from(n).toString())
: null;
// assign props ng cli expects from nx json, if it exists
workspaceJson.cli ??= nxJson?.cli;
workspaceJson.generators ??= nxJson?.generators;
workspaceJson.defaultProject ??= nxJson?.defaultProject;
// resolve inline configurations and downlevel format
return this.resolveInlineProjectConfigurations(
workspaceJson
).pipe(
map((x) => {
if (workspaceJson.version === 2) {
const formatted = toOldFormatOrNull(workspaceJson);
return formatted
? Buffer.from(serializeJson(formatted))
: Buffer.from(serializeJson(x));
}
return Buffer.from(serializeJson(x));
})
);
} catch {
return of(w);
}
})
)
)
);
};
read(path: Path): Observable<FileBuffer> {
return this.context(path).pipe(
switchMap((r) => {
if (r.isWorkspaceConfig) {
if (r.isNewFormat) {
return super.read(r.actualConfigFileName).pipe(
switchMap((r) => {
try {
const w = parseJson(Buffer.from(r).toString());
return this.resolveInlineProjectConfigurations(w).pipe(
map((w) => {
const formatted = toOldFormatOrNull(w);
return formatted
? Buffer.from(serializeJson(formatted))
: Buffer.from(serializeJson(w));
})
);
} catch (ex) {
return of(r);
}
})
);
} else {
return super.read(r.actualConfigFileName).pipe(
map((r) => {
const w = parseJson(Buffer.from(r).toString());
return Buffer.from(
serializeJson(inlineProjectConfigurations(w))
);
})
);
}
return this.__readWorkspaceConfiguration(r.actualConfigFileName);
} else {
return super.read(path);
}
@ -326,18 +363,63 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
if (context.isNewFormat) {
try {
const w = parseJson(Buffer.from(content).toString());
const formatted = toNewFormatOrNull(w);
const formatted: AngularJsonConfiguration = toNewFormatOrNull(w);
if (formatted) {
return this.writeWorkspaceConfigFiles(context, formatted);
const { cli, generators, defaultProject, ...workspaceJson } =
formatted;
return concat(
this.writeWorkspaceConfigFiles(context, workspaceJson),
cli || generators || defaultProject
? this.__saveNxJsonProps({ cli, generators, defaultProject })
: of(null)
);
} else {
return this.writeWorkspaceConfigFiles(context, config);
const {
cli,
schematics,
generators,
defaultProject,
...angularJson
} = w;
return concat(
this.writeWorkspaceConfigFiles(
context.actualConfigFileName,
angularJson
),
cli || schematics
? this.__saveNxJsonProps({
cli,
defaultProject,
generators: schematics || generators,
})
: of(null)
);
}
} catch (e) {
return this.writeWorkspaceConfigFiles(context, config);
}
} else {
return this.writeWorkspaceConfigFiles(context, config);
} catch (e) {}
}
const { cli, schematics, generators, defaultProject, ...angularJson } =
config;
return concat(
this.writeWorkspaceConfigFiles(context, angularJson),
this.__saveNxJsonProps({
cli,
defaultProject,
generators: schematics || generators,
})
);
}
private __saveNxJsonProps(
props: Partial<NxJsonConfiguration>
): Observable<void> {
const nxJsonPath = 'nx.json' as Path;
return super.read(nxJsonPath).pipe(
switchMap((buf) => {
const nxJson = parseJson(Buffer.from(buf).toString());
Object.assign(nxJson, props);
return super.write(nxJsonPath, Buffer.from(serializeJson(nxJson)));
})
);
}
private writeWorkspaceConfigFiles(
@ -381,9 +463,9 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
: workspaceJsonWrite;
}
protected resolveInlineProjectConfigurations(config: {
projects: Record<string, any>;
}): Observable<Object> {
protected resolveInlineProjectConfigurations(
config: RawWorkspaceJsonConfiguration
): Observable<WorkspaceJsonConfiguration> {
// Creates an observable where each emission is a project configuration
// that is not listed inside workspace.json. Each time it encounters a
// standalone config, observable is updated by concatenating the new
@ -419,7 +501,7 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
x.forEach(({ project, projectConfig }) => {
config.projects[project] = projectConfig;
});
return config;
return config as WorkspaceJsonConfiguration;
})
);
}
@ -464,6 +546,7 @@ export class NxScopeHostUsedForWrappedSchematics extends NxScopedHost {
read(path: Path): Observable<FileBuffer> {
if (isWorkspaceConfigPath(path)) {
const match = findWorkspaceConfigFileChange(this.host);
const nxJsonChange = findMatchingFileChange(this.host, 'nx.json' as Path);
// no match, default to existing behavior
if (!match) {
return super.read(path);
@ -471,15 +554,10 @@ export class NxScopeHostUsedForWrappedSchematics extends NxScopedHost {
// we try to format it, if it changes, return it, otherwise return the original change
try {
const w = parseJson(Buffer.from(match.content).toString());
return this.resolveInlineProjectConfigurations(w).pipe(
map((x) => {
const formatted = toOldFormatOrNull(w);
return formatted
? Buffer.from(serializeJson(formatted))
: Buffer.from(serializeJson(x));
})
);
return this.__readWorkspaceConfiguration(match.path, {
workspace: of(match.content),
nx: nxJsonChange ? of(nxJsonChange.content) : null,
});
} catch (e) {
return super.read(path);
}
@ -542,10 +620,15 @@ export class NxScopeHostUsedForWrappedSchematics extends NxScopedHost {
}
}
function findWorkspaceConfigFileChange(host: Tree) {
type WorkspaceConfigFileChange = FileChange & {
path: ('workspace.json' | 'angular.json') & Path;
};
function findWorkspaceConfigFileChange(host: Tree): WorkspaceConfigFileChange {
return host
.listChanges()
.find((f) => f.path == 'workspace.json' || f.path == 'angular.json');
.find(
(f) => f.path == 'workspace.json' || f.path == 'angular.json'
) as WorkspaceConfigFileChange;
}
function findMatchingFileChange(host: Tree, path: Path) {
@ -897,7 +980,7 @@ export function wrapAngularDevkitSchematic(
r.eventPath === 'angular.json' ||
r.eventPath === 'workspace.json'
) {
splitProjectFileUpdatesFromWorkspaceUpdate(host, r);
saveWorkspaceConfigurationInWrappedSchematic(host, r);
}
host.write(r.eventPath, r.content);
} else if (event.kind === 'create') {
@ -1045,11 +1128,11 @@ const getTargetLogger = (
return tslintExecutorLogger;
};
function splitProjectFileUpdatesFromWorkspaceUpdate(
function saveWorkspaceConfigurationInWrappedSchematic(
host: Tree,
r: { eventPath: string; content: Buffer }
) {
const workspace: {
const workspace: Omit<AngularJsonConfiguration, 'projects'> & {
projects: { [key: string]: string | { configFilePath?: string } };
} = parseJson(r.content.toString());
for (const [project, config] of Object.entries(workspace.projects)) {
@ -1058,7 +1141,16 @@ function splitProjectFileUpdatesFromWorkspaceUpdate(
workspace.projects[project] = normalize(dirname(path));
delete config.configFilePath;
host.write(path, serializeJson(config));
r.content = Buffer.from(serializeJson(workspace));
}
}
const nxJson: NxJsonConfiguration = parseJson(
host.read('nx.json').toString()
);
nxJson.generators = workspace.generators || workspace.schematics;
nxJson.cli = workspace.cli || nxJson.cli;
nxJson.defaultProject = workspace.defaultProject;
delete workspace.cli;
delete workspace.generators;
delete workspace.schematics;
r.content = Buffer.from(serializeJson(workspace));
}

View File

@ -18,6 +18,7 @@ import {
import * as chalk from 'chalk';
import { logger } from '../shared/logger';
import { NxJsonConfiguration } from '../shared/nx';
export interface Target {
project: string;
@ -179,7 +180,7 @@ async function runExecutorInternal<T extends { success: boolean }>(
options: { [k: string]: any },
root: string,
cwd: string,
workspace: WorkspaceJsonConfiguration,
workspace: WorkspaceJsonConfiguration & NxJsonConfiguration,
isVerbose: boolean,
printHelp: boolean
): Promise<AsyncIterableIterator<T>> {

View File

@ -1,3 +1,4 @@
import { PackageManager } from './package-manager';
import { TargetDependencyConfig } from './workspace';
export type ImplicitDependencyEntry<T = '*' | string[]> = {
@ -36,11 +37,8 @@ export interface NxJsonConfiguration<T = '*' | string[]> {
*/
affected?: NxAffectedConfig;
/**
* Configuration for projects
* Where new apps + libs should be placed
*/
projects: {
[projectName: string]: NxJsonProjectConfiguration;
};
workspaceLayout?: {
libsDir: string;
appsDir: string;
@ -60,12 +58,46 @@ export interface NxJsonConfiguration<T = '*' | string[]> {
options?: any;
};
};
/**
* List of default values used by generators.
*
* These defaults are global. They are used when no other defaults are configured.
*
* Example:
*
* ```
* {
* "@nrwl/react": {
* "library": {
* "style": "scss"
* }
* }
* }
* ```
*/
generators?: { [collectionName: string]: { [generatorName: string]: any } };
/**
* Default generator collection. It is used when no collection is provided.
*/
cli?: {
packageManager?: PackageManager;
defaultCollection?: string;
};
/**
* Plugins for extending the project graph
*/
plugins?: string[];
/**
* Default project. When project isn't provided, the default project
* will be used. Convenient for small workspaces with one main application.
*/
defaultProject?: string;
}
/**
* @deprecated(v14): nx.json no longer contains projects
*/
export interface NxJsonProjectConfiguration {
implicitDependencies?: string[];
tags?: string[];

View File

@ -1,6 +1,7 @@
import type { Arguments } from 'yargs-parser';
import { TargetConfiguration, WorkspaceJsonConfiguration } from './workspace';
import { logger } from './logger';
import { NxJsonConfiguration } from './nx';
type PropertyDescription = {
type?: string;
@ -518,7 +519,7 @@ export async function combineOptionsForGenerator(
commandLineOpts: Options,
collectionName: string,
generatorName: string,
wc: WorkspaceJsonConfiguration | null,
wc: (WorkspaceJsonConfiguration & NxJsonConfiguration) | null,
schema: Schema,
isInteractive: boolean,
defaultProjectName: string | null,
@ -610,12 +611,12 @@ export function convertSmartDefaultsIntoNamedParams(
function getGeneratorDefaults(
projectName: string | null,
wc: WorkspaceJsonConfiguration,
wc: (WorkspaceJsonConfiguration & NxJsonConfiguration) | null,
collectionName: string,
generatorName: string
) {
let defaults = {};
if (wc.generators) {
if (wc?.generators) {
if (
wc.generators[collectionName] &&
wc.generators[collectionName][generatorName]
@ -634,6 +635,7 @@ function getGeneratorDefaults(
}
if (
projectName &&
wc &&
wc.projects[projectName] &&
wc.projects[projectName].generators
) {

View File

@ -2,14 +2,13 @@ import { existsSync } from 'fs';
import * as path from 'path';
import { appRootPath } from '../utils/app-root';
import { readJsonFile } from '../utils/fileutils';
import type { NxJsonConfiguration, NxJsonProjectConfiguration } from './nx';
import type { PackageManager } from './package-manager';
import type { NxJsonConfiguration } from './nx';
import { TaskGraph } from './tasks';
export interface Workspace
extends WorkspaceJsonConfiguration,
NxJsonConfiguration {
projects: Record<string, ProjectConfiguration & NxJsonProjectConfiguration>;
projects: Record<string, ProjectConfiguration>;
}
/**
@ -23,39 +22,8 @@ export interface WorkspaceJsonConfiguration {
/**
* Projects' configurations
*/
projects: { [projectName: string]: ProjectConfiguration };
/**
* Default project. When project isn't provided, the default project
* will be used. Convenient for small workspaces with one main application.
*/
defaultProject?: string;
/**
* List of default values used by generators.
*
* These defaults are global. They are used when no other defaults are configured.
*
* Example:
*
* ```
* {
* "@nrwl/react": {
* "library": {
* "style": "scss"
* }
* }
* }
* ```
*/
generators?: { [collectionName: string]: { [generatorName: string]: any } };
/**
* Default generator collection. It is used when no collection is provided.
*/
cli?: {
packageManager?: PackageManager;
defaultCollection?: string;
projects: {
[projectName: string]: ProjectConfiguration;
};
}
@ -111,6 +79,16 @@ export interface ProjectConfiguration {
* ```
*/
generators?: { [collectionName: string]: { [generatorName: string]: any } };
/**
* List of projects which are added as a dependency
*/
implicitDependencies?: string[];
/**
* List of tags used by nx-enforce-module-boundaries / dep-graph
*/
tags?: string[];
}
export interface TargetDependencyConfig {
@ -258,7 +236,7 @@ export interface ExecutorContext {
/**
* The full workspace configuration
*/
workspace: WorkspaceJsonConfiguration;
workspace: WorkspaceJsonConfiguration & NxJsonConfiguration;
/**
* The current working directory
@ -278,7 +256,10 @@ export class Workspaces {
return path.relative(this.root, cwd) || null;
}
calculateDefaultProjectName(cwd: string, wc: WorkspaceJsonConfiguration) {
calculateDefaultProjectName(
cwd: string,
wc: WorkspaceJsonConfiguration & NxJsonConfiguration
) {
const relativeCwd = this.relativeCwd(cwd);
if (relativeCwd) {
const matchingProject = Object.keys(wc.projects).find((p) => {
@ -293,11 +274,19 @@ export class Workspaces {
return wc.defaultProject;
}
readWorkspaceConfiguration(): WorkspaceJsonConfiguration {
const w = readJsonFile(
readWorkspaceConfiguration(): WorkspaceJsonConfiguration &
NxJsonConfiguration {
const rawWorkspace = readJsonFile(
path.join(this.root, workspaceConfigName(this.root))
);
return resolveNewFormatWithInlineProjects(w, this.root);
const parsedWorkspace = resolveNewFormatWithInlineProjects(
rawWorkspace,
this.root
);
const nxJson = readJsonFile<NxJsonConfiguration>(
path.join(this.root, 'nx.json')
);
return { ...parsedWorkspace, ...nxJson };
}
isNxExecutor(nodeModule: string, executor: string) {

View File

@ -18,6 +18,7 @@ describe('packageExecutor', () => {
workspace: {
version: 2,
projects: {},
npmScope: 'test',
},
isVerbose: false,
projectName: 'example',

View File

@ -1,4 +1,4 @@
import { readJson } from '@nrwl/devkit';
import { getProjects, readJson } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import type { Tree, NxJsonConfiguration } from '@nrwl/devkit';
@ -19,22 +19,23 @@ describe('app', () => {
standaloneConfig: false,
});
const workspaceJson = readJson(tree, '/workspace.json');
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(workspaceJson.projects['my-app'].root).toEqual('apps/my-app');
expect(workspaceJson.projects['my-app-e2e'].root).toEqual(
'apps/my-app-e2e'
);
expect(workspaceJson.defaultProject).toEqual('my-app');
expect(nxJson.defaultProject).toEqual('my-app');
});
it('should update nx.json', async () => {
it('should update tags and implicit dependencies', async () => {
await applicationGenerator(tree, {
name: 'myApp',
tags: 'one,two',
standaloneConfig: false,
});
const nxJson = readJson<NxJsonConfiguration>(tree, '/nx.json');
expect(nxJson.projects).toEqual({
const projects = Object.fromEntries(getProjects(tree));
expect(projects).toMatchObject({
'my-app': {
tags: ['one', 'two'],
},
@ -148,15 +149,15 @@ describe('app', () => {
);
});
it('should update nx.json', async () => {
it('should update tags and implicit dependencies', async () => {
await applicationGenerator(tree, {
name: 'myApp',
directory: 'myDir',
tags: 'one,two',
standaloneConfig: false,
});
const nxJson = readJson<NxJsonConfiguration>(tree, '/nx.json');
expect(nxJson.projects).toEqual({
const projects = Object.fromEntries(getProjects(tree));
expect(projects).toMatchObject({
'my-dir-my-app': {
tags: ['one', 'two'],
},

View File

@ -7,7 +7,6 @@ import {
getWorkspaceLayout,
joinPathFragments,
names,
NxJsonProjectConfiguration,
offsetFromRoot,
ProjectConfiguration,
readWorkspaceConfiguration,
@ -132,7 +131,7 @@ function addServeTarget(
function addProject(tree: Tree, options: NormalizedSchema) {
const targets: Record<string, TargetConfiguration> = {};
let project: ProjectConfiguration & NxJsonProjectConfiguration = {
let project: ProjectConfiguration = {
projectType: 'application',
root: options.appProjectRoot,
sourceRoot: joinPathFragments(options.appProjectRoot, 'src'),

View File

@ -1,4 +1,9 @@
import { addDependenciesToPackageJson, readJson, Tree } from '@nrwl/devkit';
import {
addDependenciesToPackageJson,
NxJsonConfiguration,
readJson,
Tree,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { nxVersion } from '../../utils/versions';
@ -36,8 +41,8 @@ describe('init', () => {
describe('defaultCollection', () => {
it('should be set if none was set before', async () => {
await webInitGenerator(tree, {});
const workspaceJson = readJson(tree, 'workspace.json');
expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/web');
const { cli } = readJson<NxJsonConfiguration>(tree, 'nx.json');
expect(cli.defaultCollection).toEqual('@nrwl/web');
});
});

View File

@ -181,6 +181,12 @@
"description": "Add default base to nx.json if its not currently set",
"factory": "./src/migrations/update-13-0-0/set-default-base-if-not-set",
"cli": "nx"
},
"13-0-0-config-locations": {
"version": "13.0.0-beta.4",
"description": "Move global settings into nx.json, and project specific settings into workspace.json",
"cli": "nx",
"implementation": "./src/migrations/update-13-0-0/config-locations/config-locations"
}
},
"packageJsonUpdates": {

View File

@ -81,5 +81,8 @@
"minimatch": "3.0.4",
"enquirer": "~2.3.6",
"tslib": "^2.0.0"
},
"nx-migrations": {
"migrations": "./migrations.json"
}
}

View File

@ -1,6 +1,6 @@
{
"root": "packages/workspace",
"sourceRoot": "packages/workspace",
"sourceRoot": "packages/workspace/src",
"projectType": "library",
"implicitDependencies": ["dep-graph-dep-graph"],
"targets": {

View File

@ -13,10 +13,16 @@ import { NxArgs, splitArgsIntoNxArgsAndOverrides } from './utils';
import {
reformattedWorkspaceJsonOrNull,
workspaceConfigName,
WorkspaceJsonConfiguration,
} from '@nrwl/tao/src/shared/workspace';
import { appRootPath } from '@nrwl/tao/src/utils/app-root';
import * as prettier from 'prettier';
import { readJsonFile, writeJsonFile } from '@nrwl/devkit';
import {
NxJsonConfiguration,
ProjectConfiguration,
readJsonFile,
writeJsonFile,
} from '@nrwl/devkit';
import { sortObjectByKeys } from '@nrwl/tao/src/utils/object-sort';
const PRETTIER_PATH = require.resolve('prettier/bin-prettier');
@ -38,8 +44,8 @@ export async function format(
case 'write':
updateWorkspaceJsonToMatchFormatVersion();
sortWorkspaceJson();
sortNxJson();
sortTsConfig();
movePropertiesToNewLocations();
chunkList.push([workspaceJsonPath, 'nx.json', 'tsconfig.base.json']);
chunkList.forEach((chunk) => write(chunk));
break;
@ -163,18 +169,6 @@ function sortWorkspaceJson() {
}
}
function sortNxJson() {
try {
const nxJsonPath = path.join(appRootPath, 'nx.json');
const nxJson = readJsonFile(nxJsonPath);
const sortedProjects = sortObjectByKeys(nxJson.projects);
nxJson.projects = sortedProjects;
writeJsonFile(nxJsonPath, nxJson);
} catch (e) {
// catch noop
}
}
function sortTsConfig() {
try {
const tsconfigPath = path.join(appRootPath, 'tsconfig.base.json');
@ -186,3 +180,57 @@ function sortTsConfig() {
// catch noop
}
}
function movePropertiesToNewLocations() {
const workspaceConfig = workspaceConfigName(appRootPath);
try {
const workspaceJson = readJsonFile<
NxJsonConfiguration & WorkspaceJsonConfiguration
>(workspaceConfig);
const nxJson = readJsonFile<
NxJsonConfiguration & WorkspaceJsonConfiguration
>('nx.json');
if (
workspaceJson.cli ||
workspaceJson.generators ||
nxJson.projects ||
nxJson.defaultProject
) {
nxJson.cli ??= workspaceJson.cli;
nxJson.generators ??= workspaceJson.generators;
nxJson.defaultProject ??= workspaceJson.defaultProject;
delete workspaceJson['cli'];
delete workspaceJson['generators'];
delete workspaceJson['defaultProject'];
moveTagsAndImplicitDepsFromNxJsonToWorkspaceJson(workspaceJson, nxJson);
writeJsonFile(workspaceConfig, workspaceJson);
writeJsonFile('nx.json', nxJson);
}
} catch (e) {
console.error(
`Error moving properties between Nx.Json + ${workspaceConfig}`
);
console.error(e);
}
}
export function moveTagsAndImplicitDepsFromNxJsonToWorkspaceJson(
workspaceJson: WorkspaceJsonConfiguration,
nxJson: NxJsonConfiguration & {
projects: Record<
string,
Pick<ProjectConfiguration, 'tags' | 'implicitDependencies'>
>;
}
) {
if (!nxJson.projects) {
return;
}
Object.entries(nxJson.projects).forEach(([project, config]) => {
workspaceJson.projects[project] = {
...workspaceJson.projects[project],
...config,
};
});
delete nxJson.projects;
}

View File

@ -62,7 +62,6 @@ describe('splitArgs', () => {
affected: {
defaultBase: 'develop',
},
projects: {},
});
expect(
splitArgsIntoNxArgsAndOverrides(
@ -82,7 +81,6 @@ describe('splitArgs', () => {
it('should return a default base branch if not configured in nx.json', () => {
jest.spyOn(fileUtils, 'readNxJson').mockReturnValue({
npmScope: 'testing',
projects: {},
});
expect(
splitArgsIntoNxArgsAndOverrides(
@ -229,7 +227,6 @@ describe('getAffectedConfig', () => {
affected: {
defaultBase: 'testing',
},
projects: {},
});
expect(getAffectedConfig().defaultBase).toEqual('testing');

View File

@ -3,8 +3,11 @@ import { vol } from 'memfs';
import { stripIndents } from '@angular-devkit/core/src/utils/literals';
import { filterAffected } from './affected-project-graph';
import { WholeFileChange } from '../file-utils';
import type { NxJsonConfiguration } from '@nrwl/devkit';
import { buildProjectGraph } from '../project-graph/build-project-graph';
import type {
NxJsonConfiguration,
WorkspaceJsonConfiguration,
} from '@nrwl/devkit';
jest.mock('fs', () => require('memfs').fs);
jest.mock('@nrwl/tao/src/utils/app-root', () => ({
@ -13,7 +16,7 @@ jest.mock('@nrwl/tao/src/utils/app-root', () => ({
describe('project graph', () => {
let packageJson: any;
let workspaceJson: any;
let workspaceJson: WorkspaceJsonConfiguration;
let tsConfigJson: any;
let nxJson: NxJsonConfiguration;
let filesJson: any;
@ -33,31 +36,38 @@ describe('project graph', () => {
},
};
workspaceJson = {
version: 2,
projects: {
demo: {
root: 'apps/demo/',
sourceRoot: 'apps/demo/src',
projectType: 'application',
implicitDependencies: ['api'],
targets: {},
},
'demo-e2e': {
root: 'apps/demo-e2e/',
sourceRoot: 'apps/demo-e2e/src',
projectType: 'application',
targets: {},
},
ui: {
root: 'libs/ui/',
sourceRoot: 'libs/ui/src',
projectType: 'library',
targets: {},
},
util: {
root: 'libs/util/',
sourceRoot: 'libs/util/src',
projectType: 'library',
targets: {},
},
api: {
root: 'apps/api/',
sourceRoot: 'apps/api/src',
projectType: 'application',
targets: {},
},
},
};
@ -74,13 +84,6 @@ describe('project graph', () => {
},
'something-for-api.txt': ['api'],
},
projects: {
api: { tags: [] },
demo: { tags: [], implicitDependencies: ['api'] },
'demo-e2e': { tags: [] },
ui: { tags: [] },
util: { tags: [] },
},
};
tsConfigJson = {
compilerOptions: {
@ -262,11 +265,11 @@ describe('project graph', () => {
expect(Object.keys(affected.nodes)).toEqual([
'npm:@nrwl/workspace',
'api',
'demo',
'demo-e2e',
'ui',
'util',
'api',
]);
});
});

View File

@ -5,7 +5,11 @@ import {
readPackageJson,
readWorkspaceJson,
} from '../file-utils';
import type { NxJsonConfiguration, ProjectGraph } from '@nrwl/devkit';
import type {
NxJsonConfiguration,
ProjectGraph,
WorkspaceJsonConfiguration,
} from '@nrwl/devkit';
import {
getImplicitlyTouchedProjects,
getTouchedProjects,
@ -17,25 +21,26 @@ import {
TouchedProjectLocator,
} from './affected-project-graph-models';
import { normalizeNxJson } from '../normalize-nx-json';
import { getTouchedProjectsInNxJson } from './locators/nx-json-changes';
import { getTouchedProjectsInWorkspaceJson } from './locators/workspace-json-changes';
import { getTouchedProjectsFromTsConfig } from './locators/tsconfig-json-changes';
export function filterAffected(
graph: ProjectGraph,
touchedFiles: FileChange[],
workspaceJson: any = readWorkspaceJson(),
workspaceJson: WorkspaceJsonConfiguration = readWorkspaceJson(),
nxJson: NxJsonConfiguration = readNxJson(),
packageJson: any = readPackageJson()
): ProjectGraph {
const normalizedNxJson = normalizeNxJson(nxJson);
const normalizedNxJson = normalizeNxJson(
nxJson,
Object.keys(workspaceJson.projects)
);
// Additional affected logic should be in this array.
const touchedProjectLocators: TouchedProjectLocator[] = [
getTouchedProjects,
getImplicitlyTouchedProjects,
getTouchedNpmPackages,
getImplicitlyTouchedProjectsByJsonChanges,
getTouchedProjectsInNxJson,
getTouchedProjectsInWorkspaceJson,
getTouchedProjectsFromTsConfig,
];

View File

@ -31,7 +31,6 @@ describe('getImplicitlyTouchedProjectsByJsonChanges', () => {
},
},
npmScope: 'scope',
projects: {},
};
});

View File

@ -24,10 +24,6 @@ describe('getTouchedNpmPackages', () => {
},
},
npmScope: 'scope',
projects: {
proj1: {},
proj2: {},
},
};
projectGraph = {
nodes: {

View File

@ -1,218 +0,0 @@
import { getTouchedProjectsInNxJson } from './nx-json-changes';
import { WholeFileChange } from '../../file-utils';
import { DiffType } from '../../../utilities/json-diff';
describe('getTouchedProjectsInNxJson', () => {
it('should not return changes when nx.json is not touched', () => {
const result = getTouchedProjectsInNxJson(
[
{
file: 'source.ts',
hash: 'some-hash',
getChanges: () => [new WholeFileChange()],
},
],
{},
{
npmScope: 'proj',
projects: {
proj1: {
tags: [],
},
},
}
);
expect(result).toEqual([]);
});
it('should return all projects for a whole file change', () => {
const result = getTouchedProjectsInNxJson(
[
{
file: 'nx.json',
hash: 'some-hash',
getChanges: () => [new WholeFileChange()],
},
],
{},
{
npmScope: 'proj',
projects: {
proj1: {
tags: [],
},
proj2: {
tags: [],
},
},
}
);
expect(result).toEqual(['proj1', 'proj2']);
});
it('should return all projects for changes to npmScope', () => {
const result = getTouchedProjectsInNxJson(
[
{
file: 'nx.json',
hash: 'some-hash',
getChanges: () => [
{
type: DiffType.Modified,
path: ['npmScope'],
value: {
lhs: 'proj',
rhs: 'awesome-proj',
},
},
],
},
],
{},
{
npmScope: 'proj',
projects: {
proj1: {
tags: [],
},
proj2: {
tags: [],
},
},
}
);
expect(result).toEqual(['proj1', 'proj2']);
});
it('should return projects added in nx.json', () => {
const result = getTouchedProjectsInNxJson(
[
{
file: 'nx.json',
hash: 'some-hash',
getChanges: () => [
{
type: DiffType.Added,
path: ['projects', 'proj1'],
value: {
lhs: undefined,
rhs: {
tags: [],
},
},
},
{
type: DiffType.Added,
path: ['projects', 'proj1', 'tags'],
value: {
lhs: undefined,
rhs: [],
},
},
],
},
],
{},
{
npmScope: 'proj',
projects: {
proj1: {
tags: [],
},
proj2: {
tags: [],
},
},
}
);
expect(result).toEqual(['proj1']);
});
it('should return all projects when a project is removed', () => {
const result = getTouchedProjectsInNxJson(
[
{
file: 'nx.json',
hash: 'some-hash',
getChanges: () => [
{
type: DiffType.Deleted,
path: ['projects', 'proj3'],
value: {
lhs: {
tags: [],
},
rhs: undefined,
},
},
],
},
],
{},
{
npmScope: 'proj',
projects: {
proj1: {
tags: [],
},
proj2: {
tags: [],
},
},
}
);
expect(result).toEqual(['proj1', 'proj2']);
});
it('should return projects modified in nx.json', () => {
const result = getTouchedProjectsInNxJson(
[
{
file: 'nx.json',
hash: 'some-hash',
getChanges: () => [
{
type: DiffType.Modified,
path: ['projects', 'proj1'],
value: {
lhs: { tags: ['scope:feat'] },
rhs: {
tags: ['scope:shared'],
},
},
},
{
type: DiffType.Modified,
path: ['projects', 'proj1', 'tags'],
value: {
lhs: ['scope:feat'],
rhs: ['scope:shared'],
},
},
{
type: DiffType.Modified,
path: ['projects', 'proj1', 'tags', '0'],
value: {
lhs: 'scope:feat',
rhs: 'scope:shared',
},
},
],
},
],
{},
{
npmScope: 'proj',
projects: {
proj1: {
tags: [],
},
proj2: {
tags: [],
},
},
}
);
expect(result).toEqual(['proj1']);
});
});

View File

@ -1,58 +0,0 @@
import { isWholeFileChange, WholeFileChange } from '../../file-utils';
import {
DiffType,
isJsonChange,
JsonChange,
} from '../../../utilities/json-diff';
import { TouchedProjectLocator } from '../affected-project-graph-models';
export const getTouchedProjectsInNxJson: TouchedProjectLocator<
WholeFileChange | JsonChange
> = (touchedFiles, workspaceJson, nxJson): string[] => {
const nxJsonChange = touchedFiles.find((change) => change.file === 'nx.json');
if (!nxJsonChange) {
return [];
}
const changes = nxJsonChange.getChanges();
if (
changes.some((change) => {
if (isJsonChange(change)) {
return change.path[0] !== 'projects';
}
if (isWholeFileChange(change)) {
return true;
}
return false;
})
) {
return Object.keys(nxJson.projects);
}
const touched = [];
for (let i = 0; i < changes.length; i++) {
const change = changes[i];
if (!isJsonChange(change) || change.path[0] !== 'projects') {
continue;
}
// Only look for changes that are changes to the whole project definition
if (change.path.length !== 2) {
continue;
}
switch (change.type) {
case DiffType.Deleted: {
// We are not sure which projects used to depend on a deleted project
// so return all projects to be safe
return Object.keys(nxJson.projects);
}
default: {
// Add the project name
touched.push(change.path[1]);
}
}
}
return touched;
};

View File

@ -52,11 +52,6 @@ describe('getTouchedProjectsFromTsConfig', () => {
{},
{
npmScope: 'proj',
projects: {
proj1: {
tags: [],
},
},
}
);
expect(result).toEqual([]);

View File

@ -15,11 +15,6 @@ describe('getTouchedProjectsInWorkspaceJson', () => {
{},
{
npmScope: 'proj',
projects: {
proj1: {
tags: [],
},
},
}
);
expect(result).toEqual([]);

View File

@ -10,26 +10,6 @@ describe('assertWorkspaceValidity', () => {
implicitDependencies: {
'nx.json': '*',
},
projects: {
app1: {
tags: [],
},
'app1-e2e': {
tags: [],
},
app2: {
tags: [],
},
'app2-e2e': {
tags: [],
},
lib1: {
tags: [],
},
lib2: {
tags: [],
},
},
};
mockWorkspaceJson = {
projects: {
@ -47,45 +27,6 @@ describe('assertWorkspaceValidity', () => {
assertWorkspaceValidity(mockWorkspaceJson, mockNxJson);
});
it('should throw for a missing project in workspace.json', () => {
jest.spyOn(output, 'error');
delete mockWorkspaceJson.projects.app1;
const mockExit = jest
.spyOn(process, 'exit')
.mockImplementation(((code?: number) => {}) as any);
assertWorkspaceValidity(mockWorkspaceJson, mockNxJson);
expect(output.error).toHaveBeenCalledWith({
title: 'Configuration Error',
bodyLines: [
`workspace.json and nx.json are out of sync. The following projects are missing in workspace.json: app1`,
],
});
expect(mockExit).toHaveBeenCalledWith(1);
mockExit.mockRestore();
});
// it('should throw for a missing project in nx.json', () => {
// jest.spyOn(output, 'error');
// delete mockNxJson.projects.app1;
// const mockExit = jest
// .spyOn(process, 'exit')
// .mockImplementation(((code?: number) => {}) as any);
// assertWorkspaceValidity(mockWorkspaceJson, mockNxJson);
// expect(mockExit).toHaveBeenCalledWith(1);
// expect(output.error).toHaveBeenCalledWith({
// title: 'Configuration Error',
// bodyLines: [
// `workspace.json and nx.json are out of sync. The following projects are missing in nx.json: app1`,
// ],
// });
// mockExit.mockRestore();
// });
it('should throw for an invalid top-level implicit dependency', () => {
jest.spyOn(output, 'error');
mockNxJson.implicitDependencies = {
@ -101,7 +42,7 @@ describe('assertWorkspaceValidity', () => {
expect(output.error).toHaveBeenCalledWith({
title: 'Configuration Error',
bodyLines: [
`The following implicitDependencies specified in nx.json are invalid:
`The following implicitDependencies specified in project configurations are invalid:
README.md
invalidproj`,
],
@ -111,7 +52,7 @@ describe('assertWorkspaceValidity', () => {
it('should throw for an invalid project-level implicit dependency', () => {
jest.spyOn(output, 'error');
mockNxJson.projects.app2.implicitDependencies = ['invalidproj'];
mockWorkspaceJson.projects.app2.implicitDependencies = ['invalidproj'];
const mockExit = jest
.spyOn(process, 'exit')
@ -122,7 +63,7 @@ describe('assertWorkspaceValidity', () => {
expect(output.error).toHaveBeenCalledWith({
title: 'Configuration Error',
bodyLines: [
`The following implicitDependencies specified in nx.json are invalid:
`The following implicitDependencies specified in project configurations are invalid:
app2
invalidproj`,
],

View File

@ -10,25 +10,9 @@ export function assertWorkspaceValidity(
nxJson: NxJsonConfiguration
) {
const workspaceJsonProjects = Object.keys(workspaceJson.projects);
const nxJsonProjects = Object.keys(nxJson.projects);
if (minus(nxJsonProjects, workspaceJsonProjects).length > 0) {
output.error({
title: 'Configuration Error',
bodyLines: [
`${workspaceFileName()} and nx.json are out of sync. The following projects are missing in ${workspaceFileName()}: ${minus(
nxJsonProjects,
workspaceJsonProjects
).join(', ')}`,
],
});
process.exit(1);
}
const projects = {
...workspaceJson.projects,
...nxJson.projects,
};
const invalidImplicitDependencies = new Map<string, string[]>();
@ -68,16 +52,16 @@ export function assertWorkspaceValidity(
return map;
}, invalidImplicitDependencies);
nxJsonProjects
.filter((nxJsonProjectName) => {
const project = nxJson.projects[nxJsonProjectName];
workspaceJsonProjects
.filter((projectName) => {
const project = projects[projectName];
return !!project.implicitDependencies;
})
.reduce((map, nxJsonProjectName) => {
const project = nxJson.projects[nxJsonProjectName];
.reduce((map, projectName) => {
const project = projects[projectName];
detectAndSetInvalidProjectValues(
map,
nxJsonProjectName,
projectName,
project.implicitDependencies,
projects
);
@ -88,7 +72,7 @@ export function assertWorkspaceValidity(
return;
}
let message = `The following implicitDependencies specified in nx.json are invalid:
let message = `The following implicitDependencies specified in project configurations are invalid:
`;
invalidImplicitDependencies.forEach((projectNames, key) => {
const str = ` ${key}

View File

@ -6,7 +6,6 @@ import {
import type {
FileData,
NxJsonConfiguration,
NxJsonProjectConfiguration,
ProjectGraphNode,
} from '@nrwl/devkit';
import { ProjectFileMap } from '@nrwl/devkit';
@ -209,20 +208,6 @@ export function readNxJson(
throw new Error(`nx.json must define the npmScope property.`);
}
// NOTE: As we work towards removing nx.json, some settings are now found in
// the workspace.json file. Currently this is only supported for projects
// with separated configs, as they list tags / implicit deps inside the project.json file.
const workspace = readWorkspaceConfig({ format: 'nx', path: appRootPath });
Object.entries(workspace.projects).forEach(
([project, projectConfig]: [string, NxJsonProjectConfiguration]) => {
config.projects ??= {};
if (!config.projects[project]) {
const { tags, implicitDependencies } = projectConfig;
config.projects[project] = { tags, implicitDependencies };
}
}
);
const nxJsonExtends = readNxJsonExtends(config as any);
if (nxJsonExtends) {
return { ...nxJsonExtends, ...config };

View File

@ -16,10 +16,6 @@ fs.existsSync = () => true;
describe('Hasher', () => {
const nxJson = {
npmScope: 'nrwl',
projects: {
parent: { implicitDependencies: [], tags: [] },
child: { implicitDependencies: [], tags: [] },
},
};
const workSpaceJson = {
@ -113,7 +109,7 @@ describe('Hasher', () => {
expect(hash.details.command).toEqual('parent|build||{"prop":"prop-value"}');
expect(hash.details.nodes).toEqual({
parent:
'/file|file.hash|{"root":"libs/parent"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
'/file|file.hash|{"root":"libs/parent"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
});
expect(hash.details.implicitDeps).toEqual({
'nx.json': '{"npmScope":"nrwl"}',
@ -170,7 +166,7 @@ describe('Hasher', () => {
expect(hash.details.command).toEqual('parent|build||{"prop":"prop-value"}');
expect(hash.details.nodes).toEqual({
parent:
'/file.ts|file.hash|{"root":"libs/parent"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"]}}}',
'/file.ts|file.hash|{"root":"libs/parent"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"]}}}',
});
expect(hash.details.implicitDeps).toEqual({
'nx.json': '{"npmScope":"nrwl"}',
@ -267,9 +263,9 @@ describe('Hasher', () => {
// note that the parent hash is based on parent source files only!
expect(hash.details.nodes).toEqual({
child:
'/fileb.ts|b.hash|{"root":"libs/child"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
'/fileb.ts|b.hash|{"root":"libs/child"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
parent:
'/filea.ts|a.hash|{"root":"libs/parent"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
'/filea.ts|a.hash|{"root":"libs/parent"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
});
});
@ -315,7 +311,7 @@ describe('Hasher', () => {
// note that the parent hash is based on parent source files only!
expect(hash.details.nodes).toEqual({
app: '/filea.ts|a.hash|""|""|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
app: '/filea.ts|a.hash|""|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
'npm:react': '17.0.0',
});
});
@ -367,9 +363,9 @@ describe('Hasher', () => {
expect(tasksHash.value).toContain('build'); //target
expect(tasksHash.details.nodes).toEqual({
child:
'/fileb.ts|b.hash|{"root":"libs/child"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
'/fileb.ts|b.hash|{"root":"libs/child"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
parent:
'/filea.ts|a.hash|{"root":"libs/parent"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
'/filea.ts|a.hash|{"root":"libs/parent"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
});
const hashb = await hasher.hashTaskWithDepsAndContext({
@ -386,9 +382,9 @@ describe('Hasher', () => {
expect(hashb.value).toContain('build'); //target
expect(hashb.details.nodes).toEqual({
child:
'/fileb.ts|b.hash|{"root":"libs/child"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
'/fileb.ts|b.hash|{"root":"libs/child"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
parent:
'/filea.ts|a.hash|{"root":"libs/parent"}|{"implicitDependencies":[],"tags":[]}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
'/filea.ts|a.hash|{"root":"libs/parent"}|{"compilerOptions":{"paths":{"@nrwl/parent":["libs/parent/src/index.ts"],"@nrwl/child":["libs/child/src/index.ts"]}}}',
});
});

View File

@ -354,7 +354,6 @@ class ProjectHasher {
const workspaceJson = JSON.stringify(
this.workspaceJson.projects[projectName] ?? ''
);
const nxJson = JSON.stringify(this.nxJson.projects[projectName] ?? '');
let tsConfig: string;
@ -369,7 +368,6 @@ class ProjectHasher {
...fileNames,
...values,
workspaceJson,
nxJson,
tsConfig,
])
);
@ -423,7 +421,7 @@ class ProjectHasher {
res.projects ??= {};
return res;
} catch {
return { projects: {}, npmScope: '' };
return { npmScope: '' };
}
}
}

View File

@ -1,28 +1,27 @@
import { ProjectConfiguration } from '@nrwl/devkit';
import { normalizeNxJson } from './normalize-nx-json';
describe('normalizeNxJson', () => {
it('should expand projects array', () => {
const result = normalizeNxJson({
npmScope: 'nrwl',
projects: {
demo: { tags: [] },
ui: { tags: [] },
util: { tags: [] },
},
implicitDependencies: {
'package.json': '*',
'whatever.json': {
a: {
b: {
c: ['demo'],
d: {
e: '*',
const result = normalizeNxJson(
{
npmScope: 'nrwl',
implicitDependencies: {
'package.json': '*',
'whatever.json': {
a: {
b: {
c: ['demo'],
d: {
e: '*',
},
},
},
},
},
},
});
['demo', 'ui', 'util']
);
expect(result.implicitDependencies).toEqual({
'package.json': ['demo', 'ui', 'util'],

View File

@ -1,4 +1,4 @@
import { NxJsonConfiguration } from '@nrwl/devkit';
import { NxJsonConfiguration, WorkspaceJsonConfiguration } from '@nrwl/devkit';
/**
* Normalize nx json by replacing wildcard `*` implicit dependencies
@ -7,7 +7,8 @@ import { NxJsonConfiguration } from '@nrwl/devkit';
* @returns {NxJsonConfiguration<string[]>}
*/
export function normalizeNxJson(
nxJson: NxJsonConfiguration
nxJson: NxJsonConfiguration,
projects: string[]
): NxJsonConfiguration<string[]> {
return nxJson.implicitDependencies
? {
@ -15,7 +16,7 @@ export function normalizeNxJson(
implicitDependencies: Object.entries(
nxJson.implicitDependencies
).reduce((acc, [key, val]) => {
acc[key] = recur(nxJson, val);
acc[key] = recur(projects, val);
return acc;
}, {}),
}
@ -28,17 +29,14 @@ export function normalizeNxJson(
* @param {'*' | string[] | {}} v
* @returns {string[] | {}}
*/
function recur(
nxJson: NxJsonConfiguration,
v: '*' | string[] | {}
): string[] | {} {
function recur(projects: string[], v: '*' | string[] | {}): string[] | {} {
if (v === '*') {
return Object.keys(nxJson.projects);
return projects;
} else if (Array.isArray(v)) {
return v;
} else {
return Object.keys(v).reduce((acc, key) => {
acc[key] = recur(nxJson, v[key]);
acc[key] = recur(projects, v[key]);
return acc;
}, {});
}

View File

@ -304,7 +304,6 @@ describe('nx deps utils', () => {
function createNxJson(p: Partial<NxJsonConfiguration>): NxJsonConfiguration {
const defaults: NxJsonConfiguration = {
npmScope: '',
projects: { mylib: {} },
workspaceLayout: {} as any,
targetDependencies: {},
plugins: ['plugin'],

Some files were not shown because too many files have changed in this diff Show More