feat(core): generate inputs configuration for new workspaces (#11856)
This commit is contained in:
parent
c334277a93
commit
292f0c14b1
@ -59,14 +59,14 @@ We can define a more precise configuration as follows:
|
||||
{
|
||||
"namedInputs": {
|
||||
"default": ["{projectRoot}/**/*"],
|
||||
"prod": ["!{projectRoot}/**/*.spec.tsx"]
|
||||
"production": ["!{projectRoot}/**/*.spec.tsx"]
|
||||
},
|
||||
"targetDefaults": {
|
||||
"build": {
|
||||
"inputs": ["prod", "^prod"]
|
||||
"inputs": ["production", "^production"]
|
||||
},
|
||||
"test": {
|
||||
"inputs": ["default", "^prod", "{workspaceRoot}/jest.config.ts"]
|
||||
"inputs": ["default", "^production", "{workspaceRoot}/jest.config.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,11 +25,11 @@ The following is an expanded version showing all options. Your `nx.json` will li
|
||||
},
|
||||
"namedInputs": {
|
||||
"default": ["{projectRoot}/**/*"],
|
||||
"prod": ["!{projectRoot}/**/*.spec.tsx"]
|
||||
"production": ["!{projectRoot}/**/*.spec.tsx"]
|
||||
},
|
||||
"targetDefaults": {
|
||||
"build": {
|
||||
"inputs": ["prod", "^prod"],
|
||||
"inputs": ["production", "^production"],
|
||||
"dependsOn": ["^build"]
|
||||
}
|
||||
},
|
||||
@ -127,7 +127,7 @@ like this (which applies to every project):
|
||||
"test": {
|
||||
"inputs": [
|
||||
"default",
|
||||
"^prod"
|
||||
"^production"
|
||||
]
|
||||
}
|
||||
```
|
||||
@ -137,7 +137,10 @@ And projects can define their prod fileset, without having to redefine the input
|
||||
```json title="project.json"
|
||||
{
|
||||
"namedInputs": {
|
||||
"prod": ["!{projectRoot}/**/*.test.js", "{workspacRoot}/jest.config.js"]
|
||||
"production": [
|
||||
"!{projectRoot}/**/*.test.js",
|
||||
"{workspacRoot}/jest.config.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -64,18 +64,18 @@ You can add Nx-specific configuration as follows:
|
||||
"default": [
|
||||
"{projectRoot}/**/*"
|
||||
],
|
||||
"prod": [
|
||||
"production": [
|
||||
"!{projectRoot}/**/*.spec.tsx"
|
||||
]
|
||||
},
|
||||
"targets": {
|
||||
"build": {
|
||||
"inputs": ["prod", "^prod"],
|
||||
"inputs": ["production", "^production"],
|
||||
"outputs": ["dist/libs/mylib"],
|
||||
"dependsOn": ["^build"]
|
||||
},
|
||||
"test": {
|
||||
"inputs": ["default", "^prod"],
|
||||
"inputs": ["default", "^production"],
|
||||
"outputs": [],
|
||||
"dependsOn": ["build"]
|
||||
}
|
||||
@ -94,19 +94,19 @@ You can add Nx-specific configuration as follows:
|
||||
"projectType": "library",
|
||||
"namedInputs": {
|
||||
"default": ["{projectRoot}/**/*"],
|
||||
"prod": ["!{projectRoot}/**/*.spec.tsx"]
|
||||
"production": ["!{projectRoot}/**/*.spec.tsx"]
|
||||
},
|
||||
"targets": {
|
||||
"test": {
|
||||
"executor": "@nrwl/jest:jest",
|
||||
"inputs": ["default", "^prod"],
|
||||
"inputs": ["default", "^production"],
|
||||
"outputs": [],
|
||||
"dependsOn": ["build"],
|
||||
"options": {}
|
||||
},
|
||||
"build": {
|
||||
"executor": "@nrwl/js:tsc",
|
||||
"inputs": ["prod", "^prod"],
|
||||
"inputs": ["production", "^production"],
|
||||
"outputs": ["dist/libs/mylib"],
|
||||
"dependsOn": ["^build"],
|
||||
"options": {}
|
||||
@ -154,8 +154,8 @@ _Named Inputs_
|
||||
|
||||
Examples:
|
||||
|
||||
- `inputs: ["prod"]`
|
||||
- same as `inputs: [{input: "prod", projects: "self"}]`
|
||||
- `inputs: ["production"]`
|
||||
- same as `inputs: [{input: "production", projects: "self"}]`
|
||||
|
||||
Often the same glob will appear in many places (e.g., prod fileset will exclude spec files for all projects). Because
|
||||
keeping them in sync is error-prone, we recommend defining named inputs, which you can then reference in all of those
|
||||
@ -165,15 +165,15 @@ places.
|
||||
|
||||
Examples:
|
||||
|
||||
- `inputs: ["^prod"]`
|
||||
- same as `inputs: [{input: "prod", projects: "dependencies"}]`
|
||||
- `inputs: ["^production"]`
|
||||
- same as `inputs: [{input: "production", projects: "dependencies"}]`
|
||||
|
||||
Similar to `dependsOn`, the "^" symbols means "dependencies". This is a very important idea, so let's illustrate it with
|
||||
an example.
|
||||
|
||||
```
|
||||
"test": {
|
||||
"inputs": [ "default", "^prod" ]
|
||||
"inputs": [ "default", "^production" ]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
13
nx.json
13
nx.json
@ -30,19 +30,22 @@
|
||||
},
|
||||
"namedInputs": {
|
||||
"default": ["{projectRoot}/**/*"],
|
||||
"prod": ["!{projectRoot}/**/*.spec.ts{,.snap}"]
|
||||
"production": [
|
||||
"default",
|
||||
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)"
|
||||
]
|
||||
},
|
||||
"targetDefaults": {
|
||||
"build": {
|
||||
"dependsOn": ["build-base"],
|
||||
"inputs": ["prod", "^prod"]
|
||||
"inputs": ["production", "^production"]
|
||||
},
|
||||
"build-base": {
|
||||
"dependsOn": ["^build-base"],
|
||||
"inputs": ["prod", "^prod"]
|
||||
"inputs": ["production", "^production"]
|
||||
},
|
||||
"test": {
|
||||
"inputs": ["default", "^prod", "{workspaceRoot}/jest.config.ts"]
|
||||
"inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"]
|
||||
},
|
||||
"lint": {
|
||||
"inputs": [
|
||||
@ -54,7 +57,7 @@
|
||||
"e2e": {
|
||||
"inputs": [
|
||||
"default",
|
||||
"^prod",
|
||||
"^production",
|
||||
{
|
||||
"env": "SELECTED_CLI"
|
||||
},
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import * as devkit from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import { karmaGenerator } from './karma';
|
||||
import { NxJsonConfiguration, readJson, updateJson } from '@nrwl/devkit';
|
||||
|
||||
describe('karma', () => {
|
||||
let tree: devkit.Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyV1Workspace();
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it('should do nothing when karma is already installed and karma.conf.js exists', () => {
|
||||
@ -57,4 +58,27 @@ describe('karma', () => {
|
||||
|
||||
expect(tree.exists('karma.conf.js')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should add inputs for test targets', () => {
|
||||
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
|
||||
json.namedInputs ??= {};
|
||||
json.namedInputs.production = ['default', '^production'];
|
||||
return json;
|
||||
});
|
||||
karmaGenerator(tree, {});
|
||||
|
||||
const nxJson = readJson<NxJsonConfiguration>(tree, 'nx.json');
|
||||
expect(nxJson.namedInputs.production).toContain(
|
||||
'!{projectRoot}/karma.conf.js'
|
||||
);
|
||||
expect(nxJson.namedInputs.production).toContain(
|
||||
'!{projectRoot}/tsconfig.spec.json'
|
||||
);
|
||||
expect(nxJson.namedInputs.production).toContain(
|
||||
'!{projectRoot}/**/*.spec.[jt]s'
|
||||
);
|
||||
expect(nxJson.targetDefaults.test).toEqual({
|
||||
inputs: ['default', '^production', '{workspaceRoot}/karma.conf.js'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -4,6 +4,8 @@ import {
|
||||
generateFiles,
|
||||
joinPathFragments,
|
||||
readJson,
|
||||
readWorkspaceConfiguration,
|
||||
updateWorkspaceConfiguration,
|
||||
} from '@nrwl/devkit';
|
||||
import {
|
||||
jasmineCoreVersion,
|
||||
@ -18,6 +20,39 @@ import {
|
||||
} from '../../utils/versions';
|
||||
import { GeneratorOptions } from './schema';
|
||||
|
||||
function addTestInputs(tree: Tree) {
|
||||
const workspaceConfiguration = readWorkspaceConfiguration(tree);
|
||||
|
||||
const productionFileSet = workspaceConfiguration.namedInputs?.production;
|
||||
if (productionFileSet) {
|
||||
productionFileSet.push(
|
||||
// Exclude spec files from production fileset
|
||||
'!{projectRoot}/**/*.spec.[jt]s',
|
||||
// Remove tsconfig.spec.json
|
||||
'!{projectRoot}/tsconfig.spec.json',
|
||||
// Remove karma.conf.js
|
||||
'!{projectRoot}/karma.conf.js'
|
||||
);
|
||||
// Dedupe and set
|
||||
workspaceConfiguration.namedInputs.production = Array.from(
|
||||
new Set(productionFileSet)
|
||||
);
|
||||
}
|
||||
|
||||
// Test targets depend on all their project's sources + production sources of dependencies
|
||||
workspaceConfiguration.targetDefaults ??= {};
|
||||
workspaceConfiguration.targetDefaults.test ??= {};
|
||||
workspaceConfiguration.targetDefaults.test.inputs ??= [
|
||||
'default',
|
||||
productionFileSet ? '^production' : '^default',
|
||||
];
|
||||
workspaceConfiguration.targetDefaults.test.inputs.push(
|
||||
'{workspaceRoot}/karma.conf.js'
|
||||
);
|
||||
|
||||
updateWorkspaceConfiguration(tree, workspaceConfiguration);
|
||||
}
|
||||
|
||||
export function karmaGenerator(tree: Tree, options: GeneratorOptions) {
|
||||
const packageJson = readJson(tree, 'package.json');
|
||||
|
||||
@ -25,11 +60,14 @@ export function karmaGenerator(tree: Tree, options: GeneratorOptions) {
|
||||
generateFiles(tree, joinPathFragments(__dirname, 'files'), '.', {
|
||||
tmpl: '',
|
||||
});
|
||||
|
||||
addTestInputs(tree);
|
||||
}
|
||||
|
||||
if (options.skipPackageJson || packageJson.devDependencies['karma']) {
|
||||
return () => {};
|
||||
}
|
||||
|
||||
return addDependenciesToPackageJson(
|
||||
tree,
|
||||
{},
|
||||
|
||||
@ -176,6 +176,12 @@ Object {
|
||||
"^build",
|
||||
],
|
||||
},
|
||||
"lint": Object {
|
||||
"inputs": Array [
|
||||
"default",
|
||||
"{workspaceRoot}/.eslintrc.json",
|
||||
],
|
||||
},
|
||||
},
|
||||
"tasksRunnerOptions": Object {
|
||||
"default": Object {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { readJson, Tree, updateJson } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
|
||||
import { NxJsonConfiguration, readJson, Tree, updateJson } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
|
||||
import { cypressVersion } from '../../utils/versions';
|
||||
import { cypressInitGenerator } from './init';
|
||||
@ -8,7 +8,7 @@ describe('init', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyV1Workspace();
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it('should add dependencies into `package.json` file', async () => {
|
||||
@ -31,4 +31,20 @@ describe('init', () => {
|
||||
expect(packageJson.dependencies['@nrwl/cypress']).toBeUndefined();
|
||||
expect(packageJson.dependencies[existing]).toBeDefined();
|
||||
});
|
||||
|
||||
it('should setup e2e target defaults', async () => {
|
||||
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
|
||||
json.namedInputs ??= {};
|
||||
json.namedInputs.production = ['default'];
|
||||
return json;
|
||||
});
|
||||
|
||||
cypressInitGenerator(tree, {});
|
||||
|
||||
expect(
|
||||
readJson<NxJsonConfiguration>(tree, 'nx.json').targetDefaults.e2e
|
||||
).toEqual({
|
||||
inputs: ['default', '^production'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
convertNxGenerator,
|
||||
readWorkspaceConfiguration,
|
||||
removeDependenciesFromPackageJson,
|
||||
Tree,
|
||||
updateWorkspaceConfiguration,
|
||||
} from '@nrwl/devkit';
|
||||
import {
|
||||
cypressVersion,
|
||||
@ -11,11 +13,27 @@ import {
|
||||
} from '../../utils/versions';
|
||||
import { Schema } from './schema';
|
||||
|
||||
function updateDependencies(host: Tree) {
|
||||
removeDependenciesFromPackageJson(host, ['@nrwl/cypress'], []);
|
||||
function setupE2ETargetDefaults(tree: Tree) {
|
||||
const workspaceConfiguration = readWorkspaceConfiguration(tree);
|
||||
|
||||
// E2e targets depend on all their project's sources + production sources of dependencies
|
||||
workspaceConfiguration.targetDefaults ??= {};
|
||||
|
||||
const productionFileSet = !!workspaceConfiguration.namedInputs?.production;
|
||||
workspaceConfiguration.targetDefaults.e2e ??= {};
|
||||
workspaceConfiguration.targetDefaults.e2e.inputs ??= [
|
||||
'default',
|
||||
productionFileSet ? '^production' : '^default',
|
||||
];
|
||||
|
||||
updateWorkspaceConfiguration(tree, workspaceConfiguration);
|
||||
}
|
||||
|
||||
function updateDependencies(tree: Tree) {
|
||||
removeDependenciesFromPackageJson(tree, ['@nrwl/cypress'], []);
|
||||
|
||||
return addDependenciesToPackageJson(
|
||||
host,
|
||||
tree,
|
||||
{},
|
||||
{
|
||||
['@nrwl/cypress']: nxVersion,
|
||||
@ -25,8 +43,9 @@ function updateDependencies(host: Tree) {
|
||||
);
|
||||
}
|
||||
|
||||
export function cypressInitGenerator(host: Tree, options: Schema) {
|
||||
return !options.skipPackageJson ? updateDependencies(host) : () => {};
|
||||
export function cypressInitGenerator(tree: Tree, options: Schema) {
|
||||
setupE2ETargetDefaults(tree);
|
||||
return !options.skipPackageJson ? updateDependencies(tree) : () => {};
|
||||
}
|
||||
|
||||
export default cypressInitGenerator;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
export const nxPreset = {
|
||||
testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
|
||||
// This is one of the patterns that jest finds by default https://jestjs.io/docs/configuration#testmatch-arraystring
|
||||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||
resolver: '@nrwl/jest/plugins/resolver',
|
||||
moduleFileExtensions: ['ts', 'js', 'mjs', 'html'],
|
||||
coverageReporters: ['html'],
|
||||
|
||||
@ -1,4 +1,11 @@
|
||||
import { readJson, stripIndents, Tree, writeJson } from '@nrwl/devkit';
|
||||
import {
|
||||
NxJsonConfiguration,
|
||||
readJson,
|
||||
stripIndents,
|
||||
Tree,
|
||||
updateJson,
|
||||
writeJson,
|
||||
} from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
|
||||
import { jestInitGenerator } from './init';
|
||||
|
||||
@ -39,6 +46,61 @@ describe('jest', () => {
|
||||
expect(tree.read('jest.config.ts', 'utf-8')).toEqual('test');
|
||||
});
|
||||
|
||||
it('should add target defaults for test', async () => {
|
||||
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
|
||||
json.namedInputs ??= {};
|
||||
json.namedInputs.production = ['default'];
|
||||
return json;
|
||||
});
|
||||
|
||||
jestInitGenerator(tree, {});
|
||||
|
||||
const productionFileSet = readJson<NxJsonConfiguration>(tree, 'nx.json')
|
||||
.namedInputs.production;
|
||||
const testDefaults = readJson<NxJsonConfiguration>(tree, 'nx.json')
|
||||
.targetDefaults.test;
|
||||
expect(productionFileSet).toContain(
|
||||
'!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)'
|
||||
);
|
||||
expect(productionFileSet).toContain('!{projectRoot}/tsconfig.spec.json');
|
||||
expect(productionFileSet).toContain('!{projectRoot}/jest.config.[jt]s');
|
||||
expect(testDefaults).toEqual({
|
||||
inputs: ['default', '^production', '{workspaceRoot}/jest.preset.js'],
|
||||
});
|
||||
});
|
||||
|
||||
it('should not alter target defaults if jest.preset.js already exists', async () => {
|
||||
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
|
||||
json.namedInputs ??= {};
|
||||
json.namedInputs.production = ['default', '^production'];
|
||||
return json;
|
||||
});
|
||||
|
||||
jestInitGenerator(tree, {});
|
||||
|
||||
let nxJson: NxJsonConfiguration;
|
||||
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
|
||||
json.namedInputs.production = [
|
||||
'default',
|
||||
'^production',
|
||||
'!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)',
|
||||
'!{projectRoot}/**/*.md',
|
||||
];
|
||||
json.targetDefaults.test = {
|
||||
inputs: [
|
||||
'default',
|
||||
'^production',
|
||||
'{workspaceRoot}/jest.preset.js',
|
||||
'{workspaceRoot}/testSetup.ts',
|
||||
],
|
||||
};
|
||||
nxJson = json;
|
||||
return json;
|
||||
});
|
||||
jestInitGenerator(tree, {});
|
||||
expect(readJson<NxJsonConfiguration>(tree, 'nx.json')).toEqual(nxJson);
|
||||
});
|
||||
|
||||
it('should add dependencies', async () => {
|
||||
jestInitGenerator(tree, {});
|
||||
const packageJson = readJson(tree, 'package.json');
|
||||
|
||||
@ -2,10 +2,12 @@ import {
|
||||
addDependenciesToPackageJson,
|
||||
convertNxGenerator,
|
||||
GeneratorCallback,
|
||||
readWorkspaceConfiguration,
|
||||
removeDependenciesFromPackageJson,
|
||||
stripIndents,
|
||||
Tree,
|
||||
updateJson,
|
||||
updateWorkspaceConfiguration,
|
||||
} from '@nrwl/devkit';
|
||||
import {
|
||||
babelJestVersion,
|
||||
@ -26,9 +28,9 @@ const schemaDefaults = {
|
||||
js: false,
|
||||
} as const;
|
||||
|
||||
function createJestConfig(host: Tree, js: boolean = false) {
|
||||
function createJestConfig(tree: Tree, js: boolean = false) {
|
||||
// if the root ts config already exists then don't make a js one or vice versa
|
||||
if (!host.exists('jest.config.ts') && !host.exists('jest.config.js')) {
|
||||
if (!tree.exists('jest.config.ts') && !tree.exists('jest.config.js')) {
|
||||
const contents = js
|
||||
? stripIndents`
|
||||
const { getJestProjects } = require('@nrwl/jest');
|
||||
@ -42,21 +44,57 @@ function createJestConfig(host: Tree, js: boolean = false) {
|
||||
export default {
|
||||
projects: getJestProjects()
|
||||
};`;
|
||||
host.write(`jest.config.${js ? 'js' : 'ts'}`, contents);
|
||||
tree.write(`jest.config.${js ? 'js' : 'ts'}`, contents);
|
||||
}
|
||||
|
||||
if (!host.exists('jest.preset.js')) {
|
||||
if (!tree.exists('jest.preset.js')) {
|
||||
// preset is always js file.
|
||||
host.write(
|
||||
tree.write(
|
||||
`jest.preset.js`,
|
||||
`
|
||||
const nxPreset = require('@nrwl/jest/preset').default;
|
||||
|
||||
module.exports = { ...nxPreset }`
|
||||
);
|
||||
|
||||
addTestInputs(tree);
|
||||
}
|
||||
}
|
||||
|
||||
function addTestInputs(tree: Tree) {
|
||||
const workspaceConfiguration = readWorkspaceConfiguration(tree);
|
||||
|
||||
const productionFileSet = workspaceConfiguration.namedInputs?.production;
|
||||
if (productionFileSet) {
|
||||
// This is one of the patterns in the default jest patterns
|
||||
productionFileSet.push(
|
||||
// Remove spec, test, and snapshots from the production fileset
|
||||
'!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)',
|
||||
// Remove tsconfig.spec.json
|
||||
'!{projectRoot}/tsconfig.spec.json',
|
||||
// Remove jest.config.js/ts
|
||||
'!{projectRoot}/jest.config.[jt]s'
|
||||
);
|
||||
// Dedupe and set
|
||||
workspaceConfiguration.namedInputs.production = Array.from(
|
||||
new Set(productionFileSet)
|
||||
);
|
||||
}
|
||||
|
||||
// Test targets depend on all their project's sources + production sources of dependencies
|
||||
workspaceConfiguration.targetDefaults ??= {};
|
||||
workspaceConfiguration.targetDefaults.test ??= {};
|
||||
workspaceConfiguration.targetDefaults.test.inputs ??= [
|
||||
'default',
|
||||
productionFileSet ? '^production' : '^default',
|
||||
];
|
||||
workspaceConfiguration.targetDefaults.test.inputs.push(
|
||||
'{workspaceRoot}/jest.preset.js'
|
||||
);
|
||||
|
||||
updateWorkspaceConfiguration(tree, workspaceConfiguration);
|
||||
}
|
||||
|
||||
function updateDependencies(tree: Tree, options: NormalizedSchema) {
|
||||
const dependencies = {
|
||||
tslib: tslibVersion,
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { Linter } from '../utils/linter';
|
||||
import { Tree } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
|
||||
import { readJson, Tree } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import { lintInitGenerator } from './init';
|
||||
|
||||
describe('@nrwl/linter:init', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyV1Workspace();
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
describe('--linter', () => {
|
||||
@ -20,6 +20,16 @@ describe('@nrwl/linter:init', () => {
|
||||
expect(tree.read('.eslintrc.json', 'utf-8')).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should add the root eslint config to the lint targetDefaults for lint', async () => {
|
||||
await lintInitGenerator(tree, {
|
||||
linter: Linter.EsLint,
|
||||
});
|
||||
|
||||
expect(readJson(tree, 'nx.json').targetDefaults.lint).toEqual({
|
||||
inputs: ['default', '{workspaceRoot}/.eslintrc.json'],
|
||||
});
|
||||
});
|
||||
|
||||
it('should not generate the global eslint config if it already exist', async () => {
|
||||
tree.write('.eslintrc.js', '{}');
|
||||
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import type { GeneratorCallback, Tree } from '@nrwl/devkit';
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
readWorkspaceConfiguration,
|
||||
removeDependenciesFromPackageJson,
|
||||
updateJson,
|
||||
updateWorkspaceConfiguration,
|
||||
writeJson,
|
||||
} from '@nrwl/devkit';
|
||||
import {
|
||||
@ -15,7 +17,7 @@ import {
|
||||
} from '../../utils/versions';
|
||||
|
||||
import { Linter } from '../utils/linter';
|
||||
import { containsEslint } from '../utils/eslint-file';
|
||||
import { findEslintFile } from '../utils/eslint-file';
|
||||
import { ESLint } from 'eslint';
|
||||
|
||||
export interface LinterInitOptions {
|
||||
@ -180,8 +182,31 @@ function initTsLint(tree: Tree, options: LinterInitOptions): GeneratorCallback {
|
||||
: () => {};
|
||||
}
|
||||
|
||||
function addTargetDefaults(tree: Tree) {
|
||||
const workspaceConfiguration = readWorkspaceConfiguration(tree);
|
||||
|
||||
const productionFileSet = workspaceConfiguration.namedInputs?.production;
|
||||
if (productionFileSet) {
|
||||
// Remove .eslintrc.json
|
||||
productionFileSet.push('!{projectRoot}/.eslintrc.json');
|
||||
// Dedupe and set
|
||||
workspaceConfiguration.namedInputs.production = Array.from(
|
||||
new Set(productionFileSet)
|
||||
);
|
||||
}
|
||||
|
||||
workspaceConfiguration.targetDefaults ??= {};
|
||||
|
||||
workspaceConfiguration.targetDefaults.lint ??= {};
|
||||
workspaceConfiguration.targetDefaults.lint.inputs ??= [
|
||||
'default',
|
||||
`{workspaceRoot}/.eslintrc.json`,
|
||||
];
|
||||
updateWorkspaceConfiguration(tree, workspaceConfiguration);
|
||||
}
|
||||
|
||||
function initEsLint(tree: Tree, options: LinterInitOptions): GeneratorCallback {
|
||||
if (containsEslint(tree)) {
|
||||
if (findEslintFile(tree)) {
|
||||
return () => {};
|
||||
}
|
||||
|
||||
@ -194,6 +219,7 @@ function initEsLint(tree: Tree, options: LinterInitOptions): GeneratorCallback {
|
||||
'.eslintrc.json',
|
||||
getGlobalEsLintConfiguration(options.unitTestRunner)
|
||||
);
|
||||
addTargetDefaults(tree);
|
||||
|
||||
if (tree.exists('.vscode/extensions.json')) {
|
||||
updateJson(tree, '.vscode/extensions.json', (json) => {
|
||||
|
||||
@ -42,8 +42,11 @@ function createEsLintConfiguration(
|
||||
projectConfig: ProjectConfiguration,
|
||||
setParserOptionsProject: boolean
|
||||
) {
|
||||
const eslintConfig = findEslintFile(tree);
|
||||
writeJson(tree, join(projectConfig.root, `.eslintrc.json`), {
|
||||
extends: [`${offsetFromRoot(projectConfig.root)}${findEslintFile(tree)}`],
|
||||
extends: eslintConfig
|
||||
? [`${offsetFromRoot(projectConfig.root)}${eslintConfig}`]
|
||||
: undefined,
|
||||
// Include project files to be linted since the global one excludes all files.
|
||||
ignorePatterns: ['!**/*'],
|
||||
overrides: [
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { containsEslint, findEslintFile } from './eslint-file';
|
||||
import { findEslintFile } from './eslint-file';
|
||||
|
||||
import { Tree } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
|
||||
@ -10,30 +10,9 @@ describe('@nrwl/linter:eslint-file', () => {
|
||||
tree = createTreeWithEmptyV1Workspace();
|
||||
});
|
||||
|
||||
describe('containsEslint', () => {
|
||||
it('should return false when calling containsEslint without a eslint config', () => {
|
||||
expect(containsEslint(tree)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when calling containsEslint with a .eslintrc.json config', () => {
|
||||
tree.write('.eslintrc.json', '{}');
|
||||
expect(containsEslint(tree)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when calling containsEslint with a .eslintrc.js config', () => {
|
||||
tree.write('.eslintrc.js', '{}');
|
||||
expect(containsEslint(tree)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when calling containsEslint witn an incorrect eslint file name', () => {
|
||||
tree.write('.eslintrc.yaml', '{}');
|
||||
expect(containsEslint(tree)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findEslintFile', () => {
|
||||
it('should return default name when calling findEslintFile when no eslint is found', () => {
|
||||
expect(findEslintFile(tree)).toBe('.eslintrc.json');
|
||||
it('should return null when calling findEslintFile when no eslint is found', () => {
|
||||
expect(findEslintFile(tree)).toBe(null);
|
||||
});
|
||||
|
||||
it('should return the name of the eslint config when calling findEslintFile', () => {
|
||||
@ -49,7 +28,7 @@ describe('@nrwl/linter:eslint-file', () => {
|
||||
it('should return default name when calling findEslintFile when no eslint is found', () => {
|
||||
tree.write('.eslintrc.yaml', '{}');
|
||||
|
||||
expect(findEslintFile(tree)).toBe('.eslintrc.json');
|
||||
expect(findEslintFile(tree)).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,21 +2,11 @@ import type { Tree } from '@nrwl/devkit';
|
||||
|
||||
const eslintFileList = ['.eslintrc.json', '.eslintrc.js'];
|
||||
|
||||
export function containsEslint(tree: Tree): boolean {
|
||||
for (const file of eslintFileList) {
|
||||
if (tree.exists(file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function findEslintFile(tree: Tree): string {
|
||||
export function findEslintFile(tree: Tree): string | null {
|
||||
for (const file of eslintFileList) {
|
||||
if (tree.exists(file)) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
// Default file
|
||||
return '.eslintrc.json';
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { Tree } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
|
||||
import { NxJsonConfiguration, readJson, Tree } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import { lintWorkspaceRuleGenerator } from './workspace-rule';
|
||||
|
||||
describe('@nrwl/linter:workspace-rule', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(async () => {
|
||||
tree = createTreeWithEmptyV1Workspace();
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it('should generate the required files', async () => {
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import {
|
||||
addProjectConfiguration,
|
||||
NxJsonConfiguration,
|
||||
readJson,
|
||||
readProjectConfiguration,
|
||||
Tree,
|
||||
updateJson,
|
||||
} from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import {
|
||||
lintWorkspaceRulesProjectGenerator,
|
||||
WORKSPACE_RULES_PROJECT_NAME,
|
||||
@ -14,22 +16,23 @@ describe('@nrwl/linter:workspace-rules-project', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyV1Workspace();
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it('should update implicitDependencies in nx.json', async () => {
|
||||
expect(
|
||||
readJson(tree, 'nx.json').implicitDependencies
|
||||
).toMatchInlineSnapshot(`undefined`);
|
||||
|
||||
it('should add lint project files to lint inputs', async () => {
|
||||
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
|
||||
json.targetDefaults = {
|
||||
lint: {
|
||||
inputs: ['default', '{workspaceRoot}/.eslintrc.json'],
|
||||
},
|
||||
};
|
||||
return json;
|
||||
});
|
||||
await lintWorkspaceRulesProjectGenerator(tree);
|
||||
|
||||
expect(readJson(tree, 'nx.json').implicitDependencies)
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"tools/eslint-rules/**/*": "*",
|
||||
}
|
||||
`);
|
||||
expect(
|
||||
readJson<NxJsonConfiguration>(tree, 'nx.json').targetDefaults.lint.inputs
|
||||
).toContain('{workspaceRoot}/tools/eslint-rules/**/*');
|
||||
});
|
||||
|
||||
it('should generate the required files', async () => {
|
||||
@ -72,6 +75,7 @@ describe('@nrwl/linter:workspace-rules-project', () => {
|
||||
expect(readProjectConfiguration(tree, WORKSPACE_RULES_PROJECT_NAME))
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"root": "tools/eslint-rules",
|
||||
"sourceRoot": "tools/eslint-rules",
|
||||
"targets": Object {
|
||||
|
||||
@ -47,13 +47,14 @@ export async function lintWorkspaceRulesProjectGenerator(tree: Tree) {
|
||||
* TODO: Explore writing a ProjectGraph plugin to make this more surgical.
|
||||
*/
|
||||
const workspaceConfig = readWorkspaceConfiguration(tree);
|
||||
updateWorkspaceConfiguration(tree, {
|
||||
...workspaceConfig,
|
||||
implicitDependencies: {
|
||||
...workspaceConfig.implicitDependencies,
|
||||
[`${WORKSPACE_PLUGIN_DIR}/**/*`]: '*',
|
||||
},
|
||||
});
|
||||
|
||||
if (workspaceConfig.targetDefaults?.lint?.inputs) {
|
||||
workspaceConfig.targetDefaults.lint.inputs.push(
|
||||
`{workspaceRoot}/${WORKSPACE_PLUGIN_DIR}/**/*`
|
||||
);
|
||||
|
||||
updateWorkspaceConfiguration(tree, workspaceConfig);
|
||||
}
|
||||
|
||||
// Add jest to the project and return installation task
|
||||
const installTask = await jestProjectGenerator(tree, {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { logger } from '@nrwl/devkit';
|
||||
import { NxJsonConfiguration } from '@nrwl/devkit';
|
||||
import { Tree, readJson, updateJson } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
|
||||
import { reactNativeInitGenerator } from './init';
|
||||
@ -38,11 +38,23 @@ describe('init', () => {
|
||||
|
||||
describe('babel config', () => {
|
||||
it('should create babel config if not present', async () => {
|
||||
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
|
||||
json.namedInputs = {
|
||||
sharedGlobals: ['{workspaceRoot}/exiting-file.json'],
|
||||
};
|
||||
return json;
|
||||
});
|
||||
|
||||
await reactNativeInitGenerator(tree, {
|
||||
unitTestRunner: 'none',
|
||||
e2eTestRunner: 'none',
|
||||
});
|
||||
|
||||
expect(tree.exists('babel.config.json')).toBe(true);
|
||||
const sharedGloabls = readJson<NxJsonConfiguration>(tree, 'nx.json')
|
||||
.namedInputs.sharedGlobals;
|
||||
expect(sharedGloabls).toContain('{workspaceRoot}/exiting-file.json');
|
||||
expect(sharedGloabls).toContain('{workspaceRoot}/babel.config.json');
|
||||
});
|
||||
|
||||
it('should not overwrite existing babel config', async () => {
|
||||
|
||||
@ -1,4 +1,9 @@
|
||||
import { Tree, writeJson } from '@nrwl/devkit';
|
||||
import {
|
||||
readWorkspaceConfiguration,
|
||||
Tree,
|
||||
updateWorkspaceConfiguration,
|
||||
writeJson,
|
||||
} from '@nrwl/devkit';
|
||||
|
||||
export function initRootBabelConfig(tree: Tree) {
|
||||
if (tree.exists('/babel.config.json') || tree.exists('/babel.config.js')) {
|
||||
@ -8,4 +13,13 @@ export function initRootBabelConfig(tree: Tree) {
|
||||
writeJson(tree, '/babel.config.json', {
|
||||
babelrcRoots: ['*'], // Make sure .babelrc files other than root can be loaded in a monorepo
|
||||
});
|
||||
|
||||
const workspaceConfiguration = readWorkspaceConfiguration(tree);
|
||||
|
||||
if (workspaceConfiguration.namedInputs?.sharedGlobals) {
|
||||
workspaceConfiguration.namedInputs.sharedGlobals.push(
|
||||
'{workspaceRoot}/babel.config.json'
|
||||
);
|
||||
}
|
||||
updateWorkspaceConfiguration(tree, workspaceConfiguration);
|
||||
}
|
||||
|
||||
@ -39,7 +39,46 @@ Object {
|
||||
"affected": Object {
|
||||
"defaultBase": "main",
|
||||
},
|
||||
"namedInputs": Object {
|
||||
"production": Array [
|
||||
"default",
|
||||
"!{projectRoot}/.eslintrc.json",
|
||||
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
|
||||
"!{projectRoot}/tsconfig.spec.json",
|
||||
"!{projectRoot}/jest.config.[jt]s",
|
||||
"!{projectRoot}/.storybook/**/*",
|
||||
"!{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)",
|
||||
],
|
||||
},
|
||||
"npmScope": "proj",
|
||||
"targetDefaults": Object {
|
||||
"build-storybook": Object {
|
||||
"inputs": Array [
|
||||
"default",
|
||||
"^production",
|
||||
"{workspaceRoot}/.storybook/**/*",
|
||||
],
|
||||
},
|
||||
"e2e": Object {
|
||||
"inputs": Array [
|
||||
"default",
|
||||
"^production",
|
||||
],
|
||||
},
|
||||
"lint": Object {
|
||||
"inputs": Array [
|
||||
"default",
|
||||
"{workspaceRoot}/.eslintrc.json",
|
||||
],
|
||||
},
|
||||
"test": Object {
|
||||
"inputs": Array [
|
||||
"default",
|
||||
"^production",
|
||||
"{workspaceRoot}/jest.preset.js",
|
||||
],
|
||||
},
|
||||
},
|
||||
"tasksRunnerOptions": Object {
|
||||
"default": Object {
|
||||
"options": Object {
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import {
|
||||
NxJsonConfiguration,
|
||||
readJson,
|
||||
readProjectConfiguration,
|
||||
Tree,
|
||||
updateJson,
|
||||
writeJson,
|
||||
} from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
|
||||
import { Linter } from '@nrwl/linter';
|
||||
import { libraryGenerator } from '@nrwl/workspace/generators';
|
||||
@ -18,7 +19,13 @@ describe('@nrwl/storybook:configuration', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(async () => {
|
||||
tree = createTreeWithEmptyV1Workspace();
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
|
||||
json.namedInputs = {
|
||||
production: ['default'],
|
||||
};
|
||||
return json;
|
||||
});
|
||||
await libraryGenerator(tree, {
|
||||
name: 'test-ui-lib',
|
||||
standaloneConfig: false,
|
||||
@ -425,7 +432,7 @@ describe('@nrwl/storybook:configuration', () => {
|
||||
describe('for js Storybook configurations', () => {
|
||||
let tree: Tree;
|
||||
beforeAll(async () => {
|
||||
tree = createTreeWithEmptyV1Workspace();
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
writeJson(tree, 'workspace.json', workspaceConfiguration);
|
||||
writeJson(tree, 'apps/nxapp/tsconfig.json', {});
|
||||
writeJson(tree, 'apps/reapp/tsconfig.json', {});
|
||||
@ -523,7 +530,7 @@ describe('@nrwl/storybook:configuration', () => {
|
||||
describe('for TypeScript Storybook configurations', () => {
|
||||
let tree: Tree;
|
||||
beforeAll(async () => {
|
||||
tree = createTreeWithEmptyV1Workspace();
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
writeJson(tree, 'workspace.json', workspaceConfiguration);
|
||||
writeJson(tree, 'apps/nxapp/tsconfig.json', {});
|
||||
writeJson(tree, 'apps/reapp/tsconfig.json', {});
|
||||
|
||||
@ -5,10 +5,12 @@ import {
|
||||
offsetFromRoot,
|
||||
readJson,
|
||||
readProjectConfiguration,
|
||||
readWorkspaceConfiguration,
|
||||
toJS,
|
||||
Tree,
|
||||
updateJson,
|
||||
updateProjectConfiguration,
|
||||
updateWorkspaceConfiguration,
|
||||
writeJson,
|
||||
} from '@nrwl/devkit';
|
||||
import { Linter } from '@nrwl/linter';
|
||||
@ -263,6 +265,31 @@ export function createRootStorybookDir(
|
||||
rootTsConfigPath: getRootTsConfigPathInTree(tree),
|
||||
});
|
||||
|
||||
const workspaceConfiguration = readWorkspaceConfiguration(tree);
|
||||
|
||||
const hasProductionFileset = !!workspaceConfiguration.namedInputs?.production;
|
||||
if (hasProductionFileset) {
|
||||
workspaceConfiguration.namedInputs.production.push(
|
||||
'!{projectRoot}/.storybook/**/*'
|
||||
);
|
||||
workspaceConfiguration.namedInputs.production.push(
|
||||
'!{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)'
|
||||
);
|
||||
}
|
||||
|
||||
workspaceConfiguration.targetDefaults ??= {};
|
||||
workspaceConfiguration.targetDefaults['build-storybook'] ??= {};
|
||||
workspaceConfiguration.targetDefaults['build-storybook'].inputs ??= [
|
||||
'default',
|
||||
hasProductionFileset ? '^production' : '^default',
|
||||
];
|
||||
|
||||
workspaceConfiguration.targetDefaults['build-storybook'].inputs.push(
|
||||
'{workspaceRoot}/.storybook/**/*'
|
||||
);
|
||||
|
||||
updateWorkspaceConfiguration(tree, workspaceConfiguration);
|
||||
|
||||
if (js) {
|
||||
toJS(tree);
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import {
|
||||
Tree,
|
||||
updateJson,
|
||||
} from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
|
||||
import { nxVersion } from '../../utils/versions';
|
||||
|
||||
@ -15,7 +15,7 @@ describe('init', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyV1Workspace();
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it('should add web dependencies', async () => {
|
||||
@ -48,10 +48,22 @@ describe('init', () => {
|
||||
|
||||
describe('babel config', () => {
|
||||
it('should create babel config if not present', async () => {
|
||||
updateJson<NxJsonConfiguration>(tree, 'nx.json', (json) => {
|
||||
json.namedInputs = {
|
||||
sharedGlobals: ['{workspaceRoot}/exiting-file.json'],
|
||||
};
|
||||
return json;
|
||||
});
|
||||
|
||||
await webInitGenerator(tree, {
|
||||
unitTestRunner: 'none',
|
||||
});
|
||||
|
||||
expect(tree.exists('babel.config.json')).toBe(true);
|
||||
const sharedGloabls = readJson<NxJsonConfiguration>(tree, 'nx.json')
|
||||
.namedInputs.sharedGlobals;
|
||||
expect(sharedGloabls).toContain('{workspaceRoot}/exiting-file.json');
|
||||
expect(sharedGloabls).toContain('{workspaceRoot}/babel.config.json');
|
||||
});
|
||||
|
||||
it('should not overwrite existing babel config', async () => {
|
||||
|
||||
@ -4,8 +4,10 @@ import {
|
||||
convertNxGenerator,
|
||||
formatFiles,
|
||||
GeneratorCallback,
|
||||
readWorkspaceConfiguration,
|
||||
removeDependenciesFromPackageJson,
|
||||
Tree,
|
||||
updateWorkspaceConfiguration,
|
||||
writeJson,
|
||||
} from '@nrwl/devkit';
|
||||
import { jestInitGenerator } from '@nrwl/jest';
|
||||
@ -42,6 +44,15 @@ function initRootBabelConfig(tree: Tree) {
|
||||
writeJson(tree, '/babel.config.json', {
|
||||
babelrcRoots: ['*'], // Make sure .babelrc files other than root can be loaded in a monorepo
|
||||
});
|
||||
|
||||
const workspaceConfiguration = readWorkspaceConfiguration(tree);
|
||||
|
||||
if (workspaceConfiguration.namedInputs?.sharedGlobals) {
|
||||
workspaceConfiguration.namedInputs.sharedGlobals.push(
|
||||
'{workspaceRoot}/babel.config.json'
|
||||
);
|
||||
}
|
||||
updateWorkspaceConfiguration(tree, workspaceConfiguration);
|
||||
}
|
||||
|
||||
export async function webInitGenerator(tree: Tree, schema: Schema) {
|
||||
|
||||
@ -75,12 +75,15 @@ Object {
|
||||
"affected": Object {
|
||||
"defaultBase": "main",
|
||||
},
|
||||
"implicitDependencies": Object {
|
||||
".eslintrc.json": "*",
|
||||
"package.json": Object {
|
||||
"dependencies": "*",
|
||||
"devDependencies": "*",
|
||||
},
|
||||
"namedInputs": Object {
|
||||
"default": Array [
|
||||
"{projectRoot}/**/*",
|
||||
"sharedGlobals",
|
||||
],
|
||||
"production": Array [
|
||||
"default",
|
||||
],
|
||||
"sharedGlobals": Array [],
|
||||
},
|
||||
"npmScope": "npmScope",
|
||||
"targetDefaults": Object {
|
||||
@ -88,6 +91,10 @@ Object {
|
||||
"dependsOn": Array [
|
||||
"^build",
|
||||
],
|
||||
"inputs": Array [
|
||||
"production",
|
||||
"^production",
|
||||
],
|
||||
},
|
||||
},
|
||||
"tasksRunnerOptions": Object {
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/nx/schemas/nx-schema.json",
|
||||
"npmScope": "<%= npmScope %>",
|
||||
"affected": {
|
||||
"defaultBase": "<%= defaultBase %>"
|
||||
},
|
||||
<% if (packageManager && cli === 'angular') { -%>
|
||||
"cli": {
|
||||
"packageManager": "<%=packageManager%>"
|
||||
},
|
||||
<% } -%>
|
||||
"implicitDependencies": {
|
||||
"package.json": {
|
||||
"dependencies": "*",
|
||||
"devDependencies": "*"
|
||||
},
|
||||
".eslintrc.json": "*"
|
||||
},
|
||||
"tasksRunnerOptions": {
|
||||
"default": {
|
||||
"runner": "nx/tasks-runners/default",
|
||||
"options": {
|
||||
"cacheableOperations": ["build", "lint", "test", "e2e"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"targetDefaults": {
|
||||
"build": {
|
||||
"dependsOn": ["^build"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
import { PackageManager } from '@nrwl/devkit';
|
||||
|
||||
export interface Schema {
|
||||
name: string;
|
||||
directory: string;
|
||||
@ -9,5 +11,5 @@ export interface Schema {
|
||||
cli: 'nx' | 'angular';
|
||||
preset: string;
|
||||
defaultBase: string;
|
||||
packageManager?: string;
|
||||
packageManager?: PackageManager;
|
||||
}
|
||||
|
||||
@ -45,13 +45,6 @@ describe('@nrwl/workspace:workspace', () => {
|
||||
affected: {
|
||||
defaultBase: 'main',
|
||||
},
|
||||
implicitDependencies: {
|
||||
'package.json': {
|
||||
dependencies: '*',
|
||||
devDependencies: '*',
|
||||
},
|
||||
'.eslintrc.json': '*',
|
||||
},
|
||||
tasksRunnerOptions: {
|
||||
default: {
|
||||
runner: 'nx/tasks-runners/default',
|
||||
@ -60,11 +53,6 @@ describe('@nrwl/workspace:workspace', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
targetDefaults: {
|
||||
build: {
|
||||
dependsOn: ['^build'],
|
||||
},
|
||||
},
|
||||
});
|
||||
const validateNxJson = ajv.compile(nxSchema);
|
||||
expect(validateNxJson(nxJson)).toEqual(true);
|
||||
@ -79,6 +67,43 @@ describe('@nrwl/workspace:workspace', () => {
|
||||
expect(validateWorkspaceJson(workspaceJson)).toEqual(true);
|
||||
});
|
||||
|
||||
it('should setup named inputs and target defaults for non-empty presets', async () => {
|
||||
await workspaceGenerator(tree, {
|
||||
name: 'proj',
|
||||
directory: 'proj',
|
||||
cli: 'nx',
|
||||
preset: Preset.React,
|
||||
defaultBase: 'main',
|
||||
});
|
||||
const nxJson = readJson<NxJsonConfiguration>(tree, '/proj/nx.json');
|
||||
expect(nxJson).toEqual({
|
||||
$schema: './node_modules/nx/schemas/nx-schema.json',
|
||||
npmScope: 'proj',
|
||||
affected: {
|
||||
defaultBase: 'main',
|
||||
},
|
||||
tasksRunnerOptions: {
|
||||
default: {
|
||||
runner: 'nx/tasks-runners/default',
|
||||
options: {
|
||||
cacheableOperations: ['build', 'lint', 'test', 'e2e'],
|
||||
},
|
||||
},
|
||||
},
|
||||
namedInputs: {
|
||||
default: ['{projectRoot}/**/*', 'sharedGlobals'],
|
||||
production: ['default'],
|
||||
sharedGlobals: [],
|
||||
},
|
||||
targetDefaults: {
|
||||
build: {
|
||||
dependsOn: ['^build'],
|
||||
inputs: ['production', '^production'],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a prettierrc file', async () => {
|
||||
await workspaceGenerator(tree, {
|
||||
name: 'proj',
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
formatFiles,
|
||||
getPackageManagerVersion,
|
||||
PackageManager,
|
||||
NxJsonConfiguration,
|
||||
} from '@nrwl/devkit';
|
||||
import { Schema } from './schema';
|
||||
import {
|
||||
@ -59,8 +60,54 @@ function createAppsAndLibsFolders(host: Tree, options: Schema) {
|
||||
}
|
||||
}
|
||||
|
||||
function createNxJson(
|
||||
host: Tree,
|
||||
{ directory, npmScope, cli, packageManager, defaultBase, preset }: Schema
|
||||
) {
|
||||
const nxJson: NxJsonConfiguration & { $schema: string } = {
|
||||
$schema: './node_modules/nx/schemas/nx-schema.json',
|
||||
npmScope: npmScope,
|
||||
affected: {
|
||||
defaultBase,
|
||||
},
|
||||
tasksRunnerOptions: {
|
||||
default: {
|
||||
runner: 'nx/tasks-runners/default',
|
||||
options: {
|
||||
cacheableOperations: ['build', 'lint', 'test', 'e2e'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (
|
||||
preset !== Preset.Core &&
|
||||
preset !== Preset.NPM &&
|
||||
preset !== Preset.Empty
|
||||
) {
|
||||
nxJson.namedInputs = {
|
||||
default: ['{projectRoot}/**/*', 'sharedGlobals'],
|
||||
production: ['default'],
|
||||
sharedGlobals: [],
|
||||
};
|
||||
nxJson.targetDefaults = {
|
||||
build: {
|
||||
dependsOn: ['^build'],
|
||||
inputs: ['production', '^production'],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (packageManager && cli === 'angular') {
|
||||
nxJson.cli = {
|
||||
packageManager: packageManager,
|
||||
};
|
||||
}
|
||||
|
||||
writeJson<NxJsonConfiguration>(host, join(directory, 'nx.json'), nxJson);
|
||||
}
|
||||
|
||||
function createFiles(host: Tree, options: Schema) {
|
||||
const npmScope = options.npmScope ?? options.name;
|
||||
const formattedNames = names(options.name);
|
||||
generateFiles(host, pathJoin(__dirname, './files'), options.directory, {
|
||||
formattedNames,
|
||||
@ -75,7 +122,6 @@ function createFiles(host: Tree, options: Schema) {
|
||||
angularCliVersion,
|
||||
...(options as object),
|
||||
nxVersion,
|
||||
npmScope,
|
||||
packageManager: options.packageManager,
|
||||
});
|
||||
}
|
||||
@ -157,6 +203,7 @@ export async function workspaceGenerator(host: Tree, options: Schema) {
|
||||
}
|
||||
options = normalizeOptions(options);
|
||||
createFiles(host, options);
|
||||
createNxJson(host, options);
|
||||
createPrettierrc(host, options);
|
||||
if (options.cli === 'angular') {
|
||||
decorateAngularClI(host, options);
|
||||
@ -193,6 +240,7 @@ function addPropertyWithStableKeys(obj: any, key: string, value: string) {
|
||||
function normalizeOptions(options: Schema) {
|
||||
let defaultBase = options.defaultBase || deduceDefaultBase();
|
||||
return {
|
||||
npmScope: options.name,
|
||||
...options,
|
||||
defaultBase,
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
import * as yargs from 'yargs';
|
||||
import { execSync } from 'child_process';
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
||||
import { URL } from 'url';
|
||||
import { join } from 'path';
|
||||
|
||||
@ -75,7 +75,8 @@ function hideFromGitIndex(uncommittedFiles: string[]) {
|
||||
const uncommittedFiles = execSync('git diff --name-only --relative HEAD .')
|
||||
.toString()
|
||||
.split('\n')
|
||||
.filter((i) => i.length > 0);
|
||||
.filter((i) => i.length > 0)
|
||||
.filter((f) => existsSync(f));
|
||||
const unhideFromGitIndex = hideFromGitIndex(uncommittedFiles);
|
||||
|
||||
process.on('exit', unhideFromGitIndex);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user