Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29a7b8575e | |||
| 1f9dc40be2 | |||
| 21944222ca | |||
| a7bc9d3406 | |||
| 2e52c14cb8 | |||
| 655a0a71cc | |||
| ac2bea7d87 | |||
| 18acd9afec | |||
| 6ac6473129 | |||
| 58b13a26af | |||
| 143b2230b6 | |||
| 85b03c2bc4 | |||
| 2e0b09afc5 | |||
| 14a4ef4e93 | |||
| 22dadbc9b4 | |||
| 1f10398934 | |||
| 62f526aa0a | |||
| 24de089b74 | |||
| 4365c010e6 | |||
| 2e1d48e184 |
@@ -70,7 +70,7 @@ Now, let's continue by creating an empty Nx workspace.
|
||||
|
||||
```shell
|
||||
# Replace acme with desired scope
|
||||
npx create-nx-workspace acme --preset=empty
|
||||
npx create-nx-workspace acme --preset=apps
|
||||
cd acme
|
||||
```
|
||||
|
||||
|
||||
@@ -706,7 +706,6 @@ describe('Linter', () => {
|
||||
|
||||
// should have plugin extends
|
||||
expect(appEslint.overrides[1].extends).toBeDefined();
|
||||
expect(appEslint.overrides[2].extends).toBeDefined();
|
||||
expect(e2eEslint.overrides[0].extends).toBeDefined();
|
||||
|
||||
runCLI(`generate @nx/js:lib ${mylib} --no-interactive`);
|
||||
@@ -717,8 +716,7 @@ describe('Linter', () => {
|
||||
|
||||
// should have no plugin extends
|
||||
expect(appEslint.overrides[1].extends).toEqual([
|
||||
'plugin:@nx/angular',
|
||||
'plugin:@angular-eslint/template/process-inline-templates',
|
||||
'plugin:@nx/angular-template',
|
||||
]);
|
||||
expect(e2eEslint.overrides[0].extends).toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -142,7 +142,7 @@ describe('Node Applications', () => {
|
||||
}
|
||||
).toString();
|
||||
expect(additionalResult).toContain('Hello Additional World!');
|
||||
}, 60000);
|
||||
}, 300_000);
|
||||
|
||||
it('should be able to generate an empty application with variable in .env file', async () => {
|
||||
const originalEnvPort = process.env.PORT;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"packages": ["build/packages/*", "build/packages/nx/native-packages/*"],
|
||||
"version": "16.8.0",
|
||||
"version": "16.8.1",
|
||||
"granularPathspec": false,
|
||||
"command": {
|
||||
"publish": {
|
||||
|
||||
@@ -9,13 +9,6 @@ exports[`addLinting generator should correctly generate the .eslintrc.json file
|
||||
"!**/*",
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.json",
|
||||
],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {},
|
||||
},
|
||||
{
|
||||
"extends": [
|
||||
"plugin:@nx/angular",
|
||||
@@ -65,13 +58,6 @@ exports[`addLinting generator support angular v14 should correctly generate the
|
||||
"!**/*",
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.json",
|
||||
],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {},
|
||||
},
|
||||
{
|
||||
"extends": [
|
||||
"plugin:@nx/angular",
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
formatFiles,
|
||||
GeneratorCallback,
|
||||
joinPathFragments,
|
||||
readProjectConfiguration,
|
||||
runTasksInSerial,
|
||||
Tree,
|
||||
} from '@nx/devkit';
|
||||
@@ -47,11 +48,6 @@ export async function addLintingGenerator(
|
||||
.includes(`${options.projectRoot}/tsconfig.*?.json`);
|
||||
|
||||
replaceOverridesInLintConfig(tree, options.projectRoot, [
|
||||
{
|
||||
files: ['*.json'],
|
||||
parser: 'jsonc-eslint-parser',
|
||||
rules: {},
|
||||
},
|
||||
{
|
||||
files: ['*.ts'],
|
||||
...(hasParserOptions
|
||||
@@ -93,6 +89,17 @@ export async function addLintingGenerator(
|
||||
*/
|
||||
rules: {},
|
||||
},
|
||||
...(isBuildableLibraryProject(tree, options.projectName)
|
||||
? [
|
||||
{
|
||||
files: ['*.json'],
|
||||
parser: 'jsonc-eslint-parser',
|
||||
rules: {
|
||||
'@nx/dependency-checks': 'error',
|
||||
} as any,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -108,4 +115,13 @@ export async function addLintingGenerator(
|
||||
return runTasksInSerial(...tasks);
|
||||
}
|
||||
|
||||
function isBuildableLibraryProject(tree: Tree, projectName: string): boolean {
|
||||
const projectConfig = readProjectConfiguration(tree, projectName);
|
||||
return (
|
||||
projectConfig.projectType === 'library' &&
|
||||
projectConfig.targets?.build &&
|
||||
!!projectConfig.targets.build
|
||||
);
|
||||
}
|
||||
|
||||
export default addLintingGenerator;
|
||||
|
||||
@@ -512,13 +512,6 @@ describe('app', () => {
|
||||
"!**/*",
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.json",
|
||||
],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {},
|
||||
},
|
||||
{
|
||||
"extends": [
|
||||
"plugin:@nx/angular",
|
||||
|
||||
-21
@@ -253,13 +253,6 @@ exports[`convert-tslint-to-eslint should not override .eslint config if migratio
|
||||
"!**/*",
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.json",
|
||||
],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {},
|
||||
},
|
||||
{
|
||||
"extends": [
|
||||
"plugin:@nx/angular",
|
||||
@@ -851,13 +844,6 @@ exports[`convert-tslint-to-eslint should work for Angular applications 4`] = `
|
||||
"!**/*",
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.json",
|
||||
],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {},
|
||||
},
|
||||
{
|
||||
"extends": [
|
||||
"plugin:@nx/angular",
|
||||
@@ -1211,13 +1197,6 @@ exports[`convert-tslint-to-eslint should work for Angular libraries 4`] = `
|
||||
"!**/*",
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.json",
|
||||
],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {},
|
||||
},
|
||||
{
|
||||
"extends": [
|
||||
"plugin:@nx/angular",
|
||||
|
||||
@@ -597,11 +597,6 @@ describe('lib', () => {
|
||||
"extends": ["../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.json"],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts"],
|
||||
"extends": [
|
||||
@@ -631,6 +626,13 @@ describe('lib', () => {
|
||||
"files": ["*.html"],
|
||||
"extends": ["plugin:@nx/angular-template"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.json"],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {
|
||||
"@nx/dependency-checks": "error"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1158,12 +1160,65 @@ describe('lib', () => {
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.json",
|
||||
"extends": [
|
||||
"plugin:@nx/angular",
|
||||
"plugin:@angular-eslint/template/process-inline-templates",
|
||||
],
|
||||
"files": [
|
||||
"*.ts",
|
||||
],
|
||||
"rules": {
|
||||
"@angular-eslint/component-selector": [
|
||||
"error",
|
||||
{
|
||||
"prefix": "proj",
|
||||
"style": "kebab-case",
|
||||
"type": "element",
|
||||
},
|
||||
],
|
||||
"@angular-eslint/directive-selector": [
|
||||
"error",
|
||||
{
|
||||
"prefix": "proj",
|
||||
"style": "camelCase",
|
||||
"type": "attribute",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"extends": [
|
||||
"plugin:@nx/angular-template",
|
||||
],
|
||||
"files": [
|
||||
"*.html",
|
||||
],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {},
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should add dependency checks to buildable libs', async () => {
|
||||
// ACT
|
||||
await runLibraryGeneratorWithOpts({
|
||||
linter: Linter.EsLint,
|
||||
buildable: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
|
||||
const eslintConfig = readJson(tree, 'my-lib/.eslintrc.json');
|
||||
expect(eslintConfig).toMatchInlineSnapshot(`
|
||||
{
|
||||
"extends": [
|
||||
"../.eslintrc.json",
|
||||
],
|
||||
"ignorePatterns": [
|
||||
"!**/*",
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"extends": [
|
||||
"plugin:@nx/angular",
|
||||
@@ -1200,6 +1255,15 @@ describe('lib', () => {
|
||||
],
|
||||
"rules": {},
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.json",
|
||||
],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {
|
||||
"@nx/dependency-checks": "error",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
|
||||
@@ -57,6 +57,6 @@ export function readTargetOptions<T = any>(
|
||||
targetConfiguration,
|
||||
schema,
|
||||
defaultProject,
|
||||
relative(context.cwd, context.root)
|
||||
relative(context.root, context.cwd)
|
||||
) as T;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,10 @@ type ProjectNameAndRootFormats = {
|
||||
derived?: ProjectNameAndRootOptions;
|
||||
};
|
||||
|
||||
const deprecationWarning = stripIndents`
|
||||
In Nx 18, generating projects will no longer derive the name and root.
|
||||
Please provide the exact project name and root in the future.`;
|
||||
|
||||
export async function determineProjectNameAndRootOptions(
|
||||
tree: Tree,
|
||||
options: ProjectGenerationOptions
|
||||
@@ -73,11 +77,18 @@ export async function determineProjectNameAndRootOptions(
|
||||
> {
|
||||
validateName(options.name, options.projectNameAndRootFormat);
|
||||
const formats = getProjectNameAndRootFormats(tree, options);
|
||||
const configuredDefault = getDefaultProjectNameAndRootFormat(tree);
|
||||
|
||||
if (configuredDefault === 'derived') {
|
||||
logger.warn(
|
||||
deprecationWarning + '\n' + getExample(options.callingGenerator, formats)
|
||||
);
|
||||
}
|
||||
|
||||
const format =
|
||||
options.projectNameAndRootFormat ??
|
||||
(getDefaultProjectNameAndRootFormat(tree) === 'as-provided'
|
||||
? 'as-provided'
|
||||
: await determineFormat(tree, formats, options.callingGenerator));
|
||||
configuredDefault ??
|
||||
(await determineFormat(tree, formats, options.callingGenerator));
|
||||
|
||||
return {
|
||||
...formats[format],
|
||||
@@ -115,6 +126,13 @@ function validateName(
|
||||
}
|
||||
}
|
||||
|
||||
function getExample(
|
||||
callingGenerator: string,
|
||||
formats: ProjectNameAndRootFormats
|
||||
) {
|
||||
return `Example: nx g ${callingGenerator} ${formats['as-provided'].projectName} --directory ${formats['as-provided'].projectRoot}`;
|
||||
}
|
||||
|
||||
async function determineFormat(
|
||||
tree: Tree,
|
||||
formats: ProjectNameAndRootFormats,
|
||||
@@ -157,10 +175,6 @@ async function determineFormat(
|
||||
format === asProvidedSelectedValue ? 'as-provided' : 'derived'
|
||||
);
|
||||
|
||||
const deprecationWarning = stripIndents`
|
||||
In Nx 18, generating projects will no longer derive the name and root.
|
||||
Please provide the exact project name and root in the future.`;
|
||||
|
||||
if (result === 'as-provided' && callingGenerator) {
|
||||
const { saveDefault } = await prompt<{ saveDefault: boolean }>({
|
||||
type: 'confirm',
|
||||
@@ -174,7 +188,7 @@ async function determineFormat(
|
||||
logger.warn(deprecationWarning);
|
||||
}
|
||||
} else {
|
||||
const example = `Example: nx g ${callingGenerator} ${formats[result].projectName} --directory ${formats[result].projectRoot}`;
|
||||
const example = getExample(callingGenerator, formats);
|
||||
logger.warn(deprecationWarning + '\n' + example);
|
||||
}
|
||||
|
||||
@@ -190,7 +204,7 @@ function setProjectNameAndRootFormatDefault(tree: Tree) {
|
||||
|
||||
function getDefaultProjectNameAndRootFormat(tree: Tree) {
|
||||
const nxJson = readNxJson(tree);
|
||||
return nxJson.workspaceLayout?.projectNameAndRootFormat ?? 'derived';
|
||||
return nxJson.workspaceLayout?.projectNameAndRootFormat;
|
||||
}
|
||||
|
||||
function getProjectNameAndRootFormats(
|
||||
|
||||
@@ -148,11 +148,8 @@ export default createESLintRule<Options, MessageIds>({
|
||||
'package.json'
|
||||
);
|
||||
|
||||
globalThis.projPackageJsonDeps ??= getProductionDependencies(
|
||||
getPackageJson(projPackageJsonPath)
|
||||
);
|
||||
const projPackageJsonDeps: Record<string, string> =
|
||||
globalThis.projPackageJsonDeps;
|
||||
getProductionDependencies(projPackageJsonPath);
|
||||
const rootPackageJsonDeps = getAllDependencies(rootPackageJson);
|
||||
|
||||
function validateMissingDependencies(node: AST.JSONProperty) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ProjectFileMap, readJsonFile } from '@nx/devkit';
|
||||
import { readJsonFile } from '@nx/devkit';
|
||||
import { existsSync } from 'fs';
|
||||
import { PackageJson } from 'nx/src/utils/package-json';
|
||||
import { isTerminalRun } from './runtime-lint-utils';
|
||||
|
||||
export function getAllDependencies(
|
||||
packageJson: PackageJson
|
||||
@@ -14,13 +15,18 @@ export function getAllDependencies(
|
||||
}
|
||||
|
||||
export function getProductionDependencies(
|
||||
packageJson: PackageJson
|
||||
packageJsonPath: string
|
||||
): Record<string, string> {
|
||||
return {
|
||||
...packageJson.dependencies,
|
||||
...packageJson.peerDependencies,
|
||||
...packageJson.optionalDependencies,
|
||||
};
|
||||
if (!globalThis.projPackageJsonDeps || !isTerminalRun()) {
|
||||
const packageJson = getPackageJson(packageJsonPath);
|
||||
globalThis.projPackageJsonDeps = {
|
||||
...packageJson.dependencies,
|
||||
...packageJson.peerDependencies,
|
||||
...packageJson.optionalDependencies,
|
||||
};
|
||||
}
|
||||
|
||||
return globalThis.projPackageJsonDeps;
|
||||
}
|
||||
|
||||
export function getPackageJson(path: string): PackageJson {
|
||||
|
||||
@@ -19,13 +19,13 @@ export function ensureGlobalProjectGraph(ruleName: string) {
|
||||
* Enforce every IDE change to get a fresh nxdeps.json
|
||||
*/
|
||||
if (
|
||||
!(global as any).projectGraph ||
|
||||
!(global as any).projectRootMappings ||
|
||||
!(global as any).projectFileMap ||
|
||||
!globalThis.projectGraph ||
|
||||
!globalThis.projectRootMappings ||
|
||||
!globalThis.projectFileMap ||
|
||||
!isTerminalRun()
|
||||
) {
|
||||
const nxJson = readNxJson();
|
||||
(global as any).workspaceLayout = nxJson.workspaceLayout;
|
||||
globalThis.workspaceLayout = nxJson.workspaceLayout;
|
||||
|
||||
/**
|
||||
* Because there are a number of ways in which the rule can be invoked (executor vs ESLint CLI vs IDE Plugin),
|
||||
@@ -33,12 +33,12 @@ export function ensureGlobalProjectGraph(ruleName: string) {
|
||||
*/
|
||||
try {
|
||||
const projectGraph = readCachedProjectGraph();
|
||||
(global as any).projectGraph = projectGraph;
|
||||
(global as any).projectRootMappings = createProjectRootMappings(
|
||||
globalThis.projectGraph = projectGraph;
|
||||
globalThis.projectRootMappings = createProjectRootMappings(
|
||||
projectGraph.nodes
|
||||
);
|
||||
(global as any).projectFileMap = readProjectFileMapCache().projectFileMap;
|
||||
(global as any).targetProjectLocator = new TargetProjectLocator(
|
||||
globalThis.projectFileMap = readProjectFileMapCache().projectFileMap;
|
||||
globalThis.targetProjectLocator = new TargetProjectLocator(
|
||||
projectGraph.nodes,
|
||||
projectGraph.externalNodes
|
||||
);
|
||||
@@ -61,9 +61,9 @@ export function readProjectGraph(ruleName: string): {
|
||||
} {
|
||||
ensureGlobalProjectGraph(ruleName);
|
||||
return {
|
||||
projectGraph: (global as any).projectGraph,
|
||||
projectFileMap: (global as any).projectFileMap,
|
||||
projectRootMappings: (global as any).projectRootMappings,
|
||||
targetProjectLocator: (global as any).targetProjectLocator,
|
||||
projectGraph: globalThis.projectGraph,
|
||||
projectFileMap: globalThis.projectFileMap,
|
||||
projectRootMappings: globalThis.projectRootMappings,
|
||||
targetProjectLocator: globalThis.targetProjectLocator,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -267,18 +267,21 @@ export async function addLint(
|
||||
// nx-ignore-next-line
|
||||
} = require('@nx/linter/src/generators/utils/eslint-file');
|
||||
|
||||
// if config is not supported, we don't need to do anything
|
||||
if (!isEslintConfigSupported(tree)) {
|
||||
return task;
|
||||
}
|
||||
|
||||
// Also update the root ESLint config. The lintProjectGenerator will not generate it for root projects.
|
||||
// But we need to set the package.json checks.
|
||||
if (options.rootProject) {
|
||||
if (isEslintConfigSupported(tree)) {
|
||||
addOverrideToLintConfig(tree, '', {
|
||||
files: ['*.json'],
|
||||
parser: 'jsonc-eslint-parser',
|
||||
rules: {
|
||||
'@nx/dependency-checks': 'error',
|
||||
},
|
||||
});
|
||||
}
|
||||
addOverrideToLintConfig(tree, '', {
|
||||
files: ['*.json'],
|
||||
parser: 'jsonc-eslint-parser',
|
||||
rules: {
|
||||
'@nx/dependency-checks': 'error',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// If project lints package.json with @nx/dependency-checks, then add ignore files for
|
||||
|
||||
@@ -144,8 +144,13 @@ function addMissingDependencies(
|
||||
packageJson[propType][packageName] = version;
|
||||
} else {
|
||||
const packageName = entry.name;
|
||||
if (!!workspacePackageJson.devDependencies?.[packageName]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!packageJson.dependencies?.[packageName] &&
|
||||
!packageJson.devDependencies?.[packageName] &&
|
||||
!packageJson.peerDependencies?.[packageName]
|
||||
) {
|
||||
const outputs = getOutputsForTargetAndConfiguration(
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
baseEsLintConfigFile,
|
||||
eslintConfigFileWhitelist,
|
||||
findEslintFile,
|
||||
lintConfigHasOverride,
|
||||
} from './eslint-file';
|
||||
|
||||
import { Tree } from '@nx/devkit';
|
||||
@@ -36,4 +37,40 @@ describe('@nx/linter:eslint-file', () => {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('lintConfigHasOverride', () => {
|
||||
it('should return true when override exists in eslintrc format', () => {
|
||||
tree.write(
|
||||
'.eslintrc.json',
|
||||
'{"overrides": [{ "files": ["*.ts"], "rules": {} }]}'
|
||||
);
|
||||
expect(
|
||||
lintConfigHasOverride(
|
||||
tree,
|
||||
'.',
|
||||
(o) => {
|
||||
return o.files?.includes('*.ts');
|
||||
},
|
||||
false
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when eslintrc is not in JSON format', () => {
|
||||
tree.write(
|
||||
'.eslintrc.js',
|
||||
'module.exports = {overrides: [{ files: ["*.ts"], rules: {} }]};'
|
||||
);
|
||||
expect(
|
||||
lintConfigHasOverride(
|
||||
tree,
|
||||
'.',
|
||||
(o) => {
|
||||
return o.files?.includes('*.ts');
|
||||
},
|
||||
false
|
||||
)
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -55,7 +55,7 @@ export function findEslintFile(tree: Tree, projectRoot = ''): string | null {
|
||||
export function isEslintConfigSupported(tree: Tree, projectRoot = ''): boolean {
|
||||
const eslintFile = findEslintFile(tree, projectRoot);
|
||||
if (!eslintFile) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
return eslintFile.endsWith('.json') || eslintFile.endsWith('.config.js');
|
||||
}
|
||||
@@ -233,6 +233,9 @@ export function lintConfigHasOverride(
|
||||
lookup: (override: Linter.ConfigOverride<Linter.RulesRecord>) => boolean,
|
||||
checkBaseConfig = false
|
||||
): boolean {
|
||||
if (!isEslintConfigSupported(tree, root)) {
|
||||
return false;
|
||||
}
|
||||
const isBase =
|
||||
checkBaseConfig && findEslintFile(tree, root).includes('.base');
|
||||
if (useFlatConfig(tree)) {
|
||||
@@ -247,6 +250,7 @@ export function lintConfigHasOverride(
|
||||
root,
|
||||
isBase ? baseEsLintConfigFile : '.eslintrc.json'
|
||||
);
|
||||
|
||||
return readJson(tree, fileName).overrides?.some(lookup) || false;
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -8,6 +8,7 @@ describe('update-16-8-0-add-ignored-files migration', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
tree.write('.eslintrc.json', '{}');
|
||||
});
|
||||
|
||||
it('should run successfully when eslint config is not present', async () => {
|
||||
|
||||
+7
-1
@@ -2,6 +2,7 @@ import { getProjects, Tree } from '@nx/devkit';
|
||||
import { forEachExecutorOptions } from '@nx/devkit/src/generators/executor-options-utils';
|
||||
import {
|
||||
findEslintFile,
|
||||
isEslintConfigSupported,
|
||||
lintConfigHasOverride,
|
||||
updateOverrideInLintConfig,
|
||||
} from '../../generators/utils/eslint-file';
|
||||
@@ -16,7 +17,12 @@ export default function update(tree: Tree) {
|
||||
const addIgnorePattern =
|
||||
(ignorePattern: string) => (_options: unknown, projectName: string) => {
|
||||
const project = projects.get(projectName);
|
||||
if (!findEslintFile(tree, project.root)) return;
|
||||
if (
|
||||
!findEslintFile(tree, project.root) ||
|
||||
!isEslintConfigSupported(tree)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
lintConfigHasOverride(
|
||||
tree,
|
||||
|
||||
@@ -45,6 +45,7 @@ export async function e2eProjectGeneratorInternal(
|
||||
addProjectConfiguration(host, options.e2eProjectName, {
|
||||
root: options.e2eProjectRoot,
|
||||
implicitDependencies: [options.project],
|
||||
projectType: 'application',
|
||||
targets: {
|
||||
e2e: {
|
||||
executor: '@nx/jest:jest',
|
||||
|
||||
+11
-1
@@ -51,7 +51,17 @@ function main() {
|
||||
process.env.NX_DAEMON = 'false';
|
||||
require('nx/src/command-line/nx-commands').commandsObject.argv;
|
||||
} else {
|
||||
if (workspace && workspace.type === 'nx') {
|
||||
// v8-compile-cache doesn't support ESM. Attempting to import ESM
|
||||
// with it enabled results in an error that reads "Invalid host options".
|
||||
//
|
||||
// Angular CLI, and prettier both use ESM so we need to disable it in these cases.
|
||||
if (
|
||||
workspace &&
|
||||
workspace.type === 'nx' &&
|
||||
!['format', 'format:check', 'format:write', 'g', 'generate'].some(
|
||||
(cmd) => process.argv[3] === cmd
|
||||
)
|
||||
) {
|
||||
require('v8-compile-cache');
|
||||
}
|
||||
// polyfill rxjs observable to avoid issues with multiple version of Observable installed in node_modules
|
||||
|
||||
@@ -5,60 +5,68 @@ import { output } from '../../utils/output';
|
||||
import { runNxSync } from '../../utils/child-process';
|
||||
|
||||
export async function viewLogs(): Promise<number> {
|
||||
const cloudUsed = isNxCloudUsed();
|
||||
if (cloudUsed) {
|
||||
output.error({
|
||||
title: 'Your workspace is already connected to Nx Cloud',
|
||||
bodyLines: [
|
||||
`Refer to the output of the last command to find the Nx Cloud link to view the run details.`,
|
||||
],
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
|
||||
const installCloud = await (
|
||||
await import('enquirer')
|
||||
)
|
||||
.prompt([
|
||||
{
|
||||
name: 'NxCloud',
|
||||
message: `To view the logs, Nx needs to connect your workspace to Nx Cloud and upload the most recent run details.`,
|
||||
type: 'autocomplete',
|
||||
choices: [
|
||||
{
|
||||
name: 'Yes',
|
||||
hint: 'Connect to Nx Cloud and upload the run details',
|
||||
},
|
||||
{
|
||||
name: 'No',
|
||||
},
|
||||
],
|
||||
initial: 'Yes' as any,
|
||||
},
|
||||
])
|
||||
.then((a: { NxCloud: 'Yes' | 'No' }) => a.NxCloud === 'Yes');
|
||||
|
||||
if (!installCloud) return;
|
||||
|
||||
const pmc = getPackageManagerCommand();
|
||||
const cloudUsed = isNxCloudUsed() && false;
|
||||
if (!cloudUsed) {
|
||||
const installCloud = await (
|
||||
await import('enquirer')
|
||||
)
|
||||
.prompt([
|
||||
{
|
||||
name: 'NxCloud',
|
||||
message: `To view the logs, Nx needs to connect your workspace to Nx Cloud and upload the most recent run details.`,
|
||||
type: 'autocomplete',
|
||||
choices: [
|
||||
{
|
||||
name: 'Yes',
|
||||
hint: 'Connect to Nx Cloud and upload the run details',
|
||||
},
|
||||
{
|
||||
name: 'No',
|
||||
},
|
||||
],
|
||||
initial: 'Yes' as any,
|
||||
},
|
||||
])
|
||||
.then((a: { NxCloud: 'Yes' | 'No' }) => a.NxCloud === 'Yes');
|
||||
try {
|
||||
output.log({
|
||||
title: 'Installing nx-cloud',
|
||||
});
|
||||
execSync(`${pmc.addDev} nx-cloud@latest`, { stdio: 'ignore' });
|
||||
} catch (e) {
|
||||
output.log({
|
||||
title: 'Installation failed',
|
||||
});
|
||||
console.log(e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!installCloud) return;
|
||||
|
||||
try {
|
||||
output.log({
|
||||
title: 'Installing nx-cloud',
|
||||
});
|
||||
execSync(`${pmc.addDev} nx-cloud@latest`, { stdio: 'ignore' });
|
||||
} catch (e) {
|
||||
output.log({
|
||||
title: 'Installation failed',
|
||||
});
|
||||
console.log(e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
output.log({
|
||||
title: 'Connecting to Nx Cloud',
|
||||
});
|
||||
runNxSync(`g nx-cloud:init --installation-source=view-logs`, {
|
||||
stdio: 'ignore',
|
||||
});
|
||||
} catch (e) {
|
||||
output.log({
|
||||
title: 'Failed to connect to Nx Cloud',
|
||||
});
|
||||
console.log(e);
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
output.log({
|
||||
title: 'Connecting to Nx Cloud',
|
||||
});
|
||||
runNxSync(`g nx-cloud:init --installation-source=view-logs`, {
|
||||
stdio: 'ignore',
|
||||
});
|
||||
} catch (e) {
|
||||
output.log({
|
||||
title: 'Failed to connect to Nx Cloud',
|
||||
});
|
||||
console.log(e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
execSync(`${pmc.exec} nx-cloud upload-and-show-run-details`, {
|
||||
|
||||
@@ -364,7 +364,7 @@ export async function generate(cwd: string, args: { [k: string]: any }) {
|
||||
projectsConfigurations,
|
||||
nxJsonConfiguration
|
||||
),
|
||||
relative(cwd, workspaceRoot),
|
||||
relative(workspaceRoot, cwd),
|
||||
verbose
|
||||
);
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ async function runExecutorInternal<T extends { success: boolean }>(
|
||||
targetConfig,
|
||||
schema,
|
||||
project,
|
||||
relative(cwd, root),
|
||||
relative(root, cwd),
|
||||
isVerbose
|
||||
);
|
||||
|
||||
|
||||
+49
-118
@@ -1,4 +1,8 @@
|
||||
import { vol } from 'memfs';
|
||||
jest.mock('../../../../utils/workspace-root', () => ({
|
||||
workspaceRoot: '/root',
|
||||
}));
|
||||
jest.mock('fs', () => require('memfs').fs);
|
||||
import { TargetProjectLocator } from './target-project-locator';
|
||||
import {
|
||||
ProjectGraphExternalNode,
|
||||
@@ -6,22 +10,12 @@ import {
|
||||
ProjectGraphProjectNode,
|
||||
} from '../../../../config/project-graph';
|
||||
|
||||
jest.mock('nx/src/utils/workspace-root', () => ({
|
||||
workspaceRoot: '/root',
|
||||
}));
|
||||
jest.mock('fs', () => require('memfs').fs);
|
||||
|
||||
describe('findTargetProjectWithImport', () => {
|
||||
let projects: Record<string, ProjectGraphProjectNode>;
|
||||
let npmProjects: Record<string, ProjectGraphExternalNode>;
|
||||
let fsJson;
|
||||
let targetProjectLocator: TargetProjectLocator;
|
||||
beforeEach(() => {
|
||||
const projecstConfigurations = {
|
||||
projects: {
|
||||
proj1: {},
|
||||
},
|
||||
};
|
||||
const nxJson = {
|
||||
npmScope: 'proj',
|
||||
};
|
||||
@@ -44,109 +38,16 @@ describe('findTargetProjectWithImport', () => {
|
||||
'@proj/proj1234/*': ['libs/proj1234/*'],
|
||||
'@proj/proj1234-child': ['libs/proj1234-child'],
|
||||
'@proj/proj1234-child/*': ['libs/proj1234-child/*'],
|
||||
'#hash-path': ['libs/hash-project/src/index.ts'],
|
||||
'parent-path/*': ['libs/parent-path/*'],
|
||||
},
|
||||
},
|
||||
};
|
||||
fsJson = {
|
||||
'./workspace.json': JSON.stringify(projecstConfigurations),
|
||||
'./nx.json': JSON.stringify(nxJson),
|
||||
'./tsconfig.base.json': JSON.stringify(tsConfig),
|
||||
'./libs/proj/index.ts': `import {a} from '@proj/my-second-proj';
|
||||
import('@proj/project-3');
|
||||
const a = { loadChildren: '@proj/proj4ab#a' };
|
||||
`,
|
||||
'./libs/proj2/index.ts': `export const a = 2;`,
|
||||
'./libs/proj2/deep/index.ts': `export const a = 22;`,
|
||||
'./libs/proj3a/index.ts': `export const a = 3;`,
|
||||
'./libs/proj4ab/index.ts': `export const a = 4;`,
|
||||
'./libs/proj5/index.ts': `export const a = 5;`,
|
||||
'./libs/proj6/index.ts': `export const a = 6;`,
|
||||
'./libs/proj7/index.ts': `export const a = 7;`,
|
||||
'./libs/proj123/index.ts': 'export const a = 123',
|
||||
'./libs/proj1234/index.ts': 'export const a = 1234',
|
||||
'./libs/proj1234-child/index.ts': 'export const a = 12345',
|
||||
};
|
||||
vol.fromJSON(fsJson, '/root');
|
||||
|
||||
const ctx = {
|
||||
workspace: {
|
||||
...projecstConfigurations,
|
||||
...nxJson,
|
||||
} as any,
|
||||
fileMap: {
|
||||
rootProj: [
|
||||
{
|
||||
file: 'index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
],
|
||||
proj: [
|
||||
{
|
||||
file: 'libs/proj/index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
],
|
||||
proj2: [
|
||||
{
|
||||
file: 'libs/proj2/index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
{
|
||||
file: 'libs/proj2/deep/index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
],
|
||||
proj3a: [
|
||||
{
|
||||
file: 'libs/proj3a/index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
],
|
||||
proj4ab: [
|
||||
{
|
||||
file: 'libs/proj4ab/index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
],
|
||||
proj5: [
|
||||
{
|
||||
file: 'libs/proj5/index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
],
|
||||
proj6: [
|
||||
{
|
||||
file: 'libs/proj6/index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
],
|
||||
proj7: [
|
||||
{
|
||||
file: 'libs/proj7/index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
],
|
||||
proj123: [
|
||||
{
|
||||
file: 'libs/proj123/index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
],
|
||||
proj1234: [
|
||||
{
|
||||
file: 'libs/proj1234/index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
],
|
||||
'proj1234-child': [
|
||||
{
|
||||
file: 'libs/proj1234-child/index.ts',
|
||||
hash: 'some-hash',
|
||||
},
|
||||
],
|
||||
},
|
||||
} as any;
|
||||
|
||||
projects = {
|
||||
rootProj: {
|
||||
name: 'rootProj',
|
||||
@@ -225,6 +126,27 @@ describe('findTargetProjectWithImport', () => {
|
||||
root: 'libs/proj1234-child',
|
||||
},
|
||||
},
|
||||
'hash-project': {
|
||||
name: 'hash-project',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'libs/hash-project',
|
||||
},
|
||||
},
|
||||
'parent-project': {
|
||||
name: 'parent-project',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'libs/parent-path',
|
||||
},
|
||||
},
|
||||
'child-project': {
|
||||
name: 'child-project',
|
||||
type: 'lib',
|
||||
data: {
|
||||
root: 'libs/parent-path/child-path',
|
||||
},
|
||||
},
|
||||
};
|
||||
npmProjects = {
|
||||
'npm:@ng/core': {
|
||||
@@ -380,7 +302,7 @@ describe('findTargetProjectWithImport', () => {
|
||||
expect(parentProj).toEqual('proj1234');
|
||||
});
|
||||
|
||||
it('should be able to npm dependencies', () => {
|
||||
it('should be able to locate npm dependencies', () => {
|
||||
const result1 = targetProjectLocator.findProjectWithImport(
|
||||
'@ng/core',
|
||||
'libs/proj1/index.ts'
|
||||
@@ -394,14 +316,31 @@ describe('findTargetProjectWithImport', () => {
|
||||
expect(result2).toEqual('npm:npm-package');
|
||||
});
|
||||
|
||||
it('should be able to resolve a module using a normalized path', () => {
|
||||
const proj4ab = targetProjectLocator.findProjectWithImport(
|
||||
'@proj/proj4ab#a',
|
||||
it('should be able to resolve wildcard paths', () => {
|
||||
const parentProject = targetProjectLocator.findProjectWithImport(
|
||||
'parent-path',
|
||||
'libs/proj1/index.ts'
|
||||
);
|
||||
|
||||
expect(proj4ab).toEqual('proj4ab');
|
||||
expect(parentProject).toEqual('parent-project');
|
||||
|
||||
const childProject = targetProjectLocator.findProjectWithImport(
|
||||
'parent-path/child-path',
|
||||
'libs/proj1/index.ts'
|
||||
);
|
||||
|
||||
expect(childProject).toEqual('child-project');
|
||||
});
|
||||
|
||||
it('should be able to resolve paths that start with a #', () => {
|
||||
const proj = targetProjectLocator.findProjectWithImport(
|
||||
'#hash-path',
|
||||
'libs/proj1/index.ts'
|
||||
);
|
||||
|
||||
expect(proj).toEqual('hash-project');
|
||||
});
|
||||
|
||||
it('should be able to resolve a modules when npm packages exist', () => {
|
||||
const proj5 = targetProjectLocator.findProjectWithImport(
|
||||
'@proj/proj5',
|
||||
@@ -785,14 +724,6 @@ describe('findTargetProjectWithImport (without tsconfig.json)', () => {
|
||||
expect(result2).toEqual('npm:npm-package');
|
||||
});
|
||||
|
||||
it('should be able to resolve a module using a normalized path', () => {
|
||||
const proj4ab = targetProjectLocator.findProjectWithImport(
|
||||
'@proj/proj4ab#a',
|
||||
'libs/proj1/index.ts'
|
||||
);
|
||||
|
||||
expect(proj4ab).toEqual('proj4ab');
|
||||
});
|
||||
it('should be able to resolve paths that have similar names', () => {
|
||||
const proj = targetProjectLocator.findProjectWithImport(
|
||||
'@proj/proj123',
|
||||
|
||||
+18
-18
@@ -3,7 +3,7 @@ import {
|
||||
resolveModuleByImport,
|
||||
} from '../../utils/typescript';
|
||||
import { isRelativePath, readJsonFile } from '../../../../utils/fileutils';
|
||||
import { dirname, join, posix } from 'path';
|
||||
import { dirname, join, posix, relative, resolve } from 'path';
|
||||
import { workspaceRoot } from '../../../../utils/workspace-root';
|
||||
import {
|
||||
ProjectGraphExternalNode,
|
||||
@@ -40,33 +40,33 @@ export class TargetProjectLocator {
|
||||
* @param filePath
|
||||
*/
|
||||
findProjectWithImport(importExpr: string, filePath: string): string {
|
||||
const normalizedImportExpr = importExpr.split('#')[0];
|
||||
if (isRelativePath(normalizedImportExpr)) {
|
||||
const resolvedModule = posix.join(
|
||||
dirname(filePath),
|
||||
normalizedImportExpr
|
||||
);
|
||||
if (isRelativePath(importExpr)) {
|
||||
const resolvedModule = posix.join(dirname(filePath), importExpr);
|
||||
return this.findProjectOfResolvedModule(resolvedModule);
|
||||
}
|
||||
|
||||
// find project using tsconfig paths
|
||||
const paths = this.findPaths(normalizedImportExpr);
|
||||
if (paths) {
|
||||
const results = this.findPaths(importExpr);
|
||||
if (results) {
|
||||
const [path, paths] = results;
|
||||
for (let p of paths) {
|
||||
const maybeResolvedProject = this.findProjectOfResolvedModule(p);
|
||||
const r = p.endsWith('/*')
|
||||
? join(dirname(p), relative(path.replace(/\*$/, ''), importExpr))
|
||||
: p;
|
||||
const maybeResolvedProject = this.findProjectOfResolvedModule(r);
|
||||
if (maybeResolvedProject) {
|
||||
return maybeResolvedProject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (builtInModuleSet.has(normalizedImportExpr)) {
|
||||
this.npmResolutionCache.set(normalizedImportExpr, null);
|
||||
if (builtInModuleSet.has(importExpr)) {
|
||||
this.npmResolutionCache.set(importExpr, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
// try to find npm package before using expensive typescript resolution
|
||||
const npmProject = this.findNpmPackage(normalizedImportExpr);
|
||||
const npmProject = this.findNpmPackage(importExpr);
|
||||
if (npmProject) {
|
||||
return npmProject;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ export class TargetProjectLocator {
|
||||
// and existed only because of the incomplete `paths` matching
|
||||
// if import cannot be matched using tsconfig `paths` the compilation would fail anyway
|
||||
const resolvedProject = this.resolveImportWithTypescript(
|
||||
normalizedImportExpr,
|
||||
importExpr,
|
||||
filePath
|
||||
);
|
||||
if (resolvedProject) {
|
||||
@@ -86,7 +86,7 @@ export class TargetProjectLocator {
|
||||
|
||||
try {
|
||||
const resolvedModule = this.resolveImportWithRequire(
|
||||
normalizedImportExpr,
|
||||
importExpr,
|
||||
filePath
|
||||
);
|
||||
|
||||
@@ -94,7 +94,7 @@ export class TargetProjectLocator {
|
||||
} catch {}
|
||||
|
||||
// nothing found, cache for later
|
||||
this.npmResolutionCache.set(normalizedImportExpr, null);
|
||||
this.npmResolutionCache.set(importExpr, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ export class TargetProjectLocator {
|
||||
return undefined;
|
||||
}
|
||||
if (this.paths[normalizedImportExpr]) {
|
||||
return this.paths[normalizedImportExpr];
|
||||
return [normalizedImportExpr, this.paths[normalizedImportExpr]];
|
||||
}
|
||||
const wildcardPath = Object.keys(this.paths).find(
|
||||
(path) =>
|
||||
@@ -117,7 +117,7 @@ export class TargetProjectLocator {
|
||||
normalizedImportExpr === path.replace(/\/\*$/, ''))
|
||||
);
|
||||
if (wildcardPath) {
|
||||
return this.paths[wildcardPath];
|
||||
return [wildcardPath, this.paths[wildcardPath]];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ export class Cache {
|
||||
const res = await this.getFromLocalDir(task);
|
||||
|
||||
if (res) {
|
||||
await this.assertLocalCacheValidity(task);
|
||||
return { ...res, remote: false };
|
||||
} else if (this.options.remoteCache) {
|
||||
// didn't find it locally but we have a remote cache
|
||||
@@ -227,31 +228,6 @@ export class Cache {
|
||||
code = Number(await readFile(join(td, 'code'), 'utf-8'));
|
||||
} catch {}
|
||||
|
||||
let sourceMachineId = null;
|
||||
try {
|
||||
sourceMachineId = await readFile(join(td, 'source'), 'utf-8');
|
||||
} catch {}
|
||||
|
||||
if (
|
||||
sourceMachineId &&
|
||||
sourceMachineId != (await this.currentMachineId())
|
||||
) {
|
||||
if (
|
||||
process.env.NX_REJECT_UNKNOWN_LOCAL_CACHE != '0' &&
|
||||
process.env.NX_REJECT_UNKNOWN_LOCAL_CACHE != 'false'
|
||||
) {
|
||||
const error = [
|
||||
`Invalid Cache Directory for Task "${task.id}"`,
|
||||
`The local cache artifact in "${td}" was not been generated on this machine.`,
|
||||
`As a result, the cache's content integrity cannot be confirmed, which may make cache restoration potentially unsafe.`,
|
||||
`If your machine ID has changed since the artifact was cached, run "nx reset" to fix this issue.`,
|
||||
`Read about the error and how to address it here: https://nx.dev/recipes/troubleshooting/unknown-local-cache`,
|
||||
``,
|
||||
].join('\n');
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
terminalOutput,
|
||||
outputsPath: join(td, 'outputs'),
|
||||
@@ -262,6 +238,31 @@ export class Cache {
|
||||
}
|
||||
}
|
||||
|
||||
private async assertLocalCacheValidity(task: Task) {
|
||||
const td = join(this.cachePath, task.hash);
|
||||
let sourceMachineId = null;
|
||||
try {
|
||||
sourceMachineId = await readFile(join(td, 'source'), 'utf-8');
|
||||
} catch {}
|
||||
|
||||
if (sourceMachineId && sourceMachineId != (await this.currentMachineId())) {
|
||||
if (
|
||||
process.env.NX_REJECT_UNKNOWN_LOCAL_CACHE != '0' &&
|
||||
process.env.NX_REJECT_UNKNOWN_LOCAL_CACHE != 'false'
|
||||
) {
|
||||
const error = [
|
||||
`Invalid Cache Directory for Task "${task.id}"`,
|
||||
`The local cache artifact in "${td}" was not been generated on this machine.`,
|
||||
`As a result, the cache's content integrity cannot be confirmed, which may make cache restoration potentially unsafe.`,
|
||||
`If your machine ID has changed since the artifact was cached, run "nx reset" to fix this issue.`,
|
||||
`Read about the error and how to address it here: https://nx.dev/recipes/troubleshooting/unknown-local-cache`,
|
||||
``,
|
||||
].join('\n');
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private createCacheDir() {
|
||||
mkdirSync(cacheDir, { recursive: true });
|
||||
return cacheDir;
|
||||
|
||||
@@ -172,8 +172,16 @@ function getPluginPathAndName(
|
||||
}
|
||||
const packageJsonPath = path.join(pluginPath, 'package.json');
|
||||
|
||||
const extension = path.extname(pluginPath);
|
||||
|
||||
// Register the ts-transpiler if we are pointing to a
|
||||
// plain ts file that's not part of a plugin project
|
||||
if (extension === '.ts' && !tsNodeAndPathsRegistered) {
|
||||
registerPluginTSTranspiler();
|
||||
}
|
||||
|
||||
const { name } =
|
||||
!['.ts', '.js'].some((x) => x === path.extname(pluginPath)) && // Not trying to point to a ts or js file
|
||||
!['.ts', '.js'].some((x) => x === extension) && // Not trying to point to a ts or js file
|
||||
existsSync(packageJsonPath) // plugin has a package.json
|
||||
? readJsonFile(packageJsonPath) // read name from package.json
|
||||
: { name: moduleName };
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ function createTestProject() {
|
||||
});
|
||||
|
||||
execSync(
|
||||
`<%= packageManagerCommands.exec %> --yes create-nx-workspace@latest ${projectName} --preset empty --no-nxCloud --no-interactive`,
|
||||
`<%= packageManagerCommands.exec %> --yes create-nx-workspace@latest ${projectName} --preset apps --no-nxCloud --no-interactive`,
|
||||
{
|
||||
cwd: dirname(projectDirectory),
|
||||
stdio: 'inherit',
|
||||
|
||||
@@ -15,7 +15,7 @@ function runNxNewCommand(args?: string, silent?: boolean) {
|
||||
return execSync(
|
||||
`node ${require.resolve(
|
||||
'nx'
|
||||
)} new proj --nx-workspace-root=${localTmpDir} --no-interactive --skip-install --collection=@nx/workspace --npmScope=proj --preset=empty ${
|
||||
)} new proj --nx-workspace-root=${localTmpDir} --no-interactive --skip-install --collection=@nx/workspace --npmScope=proj --preset=apps ${
|
||||
args || ''
|
||||
}`,
|
||||
{
|
||||
|
||||
@@ -38,6 +38,7 @@ export function updateModuleFederationProject(
|
||||
defaultConfiguration: 'production',
|
||||
options: {
|
||||
buildTarget: `${options.projectName}:build`,
|
||||
watch: false,
|
||||
port: options.devServerPort,
|
||||
},
|
||||
configurations: {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { createGlobPatternsForDependencies as jsGenerateGlobs } from '@nx/js/src
|
||||
*/
|
||||
export function createGlobPatternsForDependencies(
|
||||
dirPath: string,
|
||||
fileGlobPattern: string = '/**/!(*.stories|*.spec).{tsx,ts,jsx,js,html}'
|
||||
fileGlobPattern: string = '/**/*!(*.stories|*.spec).{tsx,ts,jsx,js,html}'
|
||||
) {
|
||||
try {
|
||||
return jsGenerateGlobs(dirPath, fileGlobPattern);
|
||||
|
||||
@@ -179,6 +179,12 @@ export async function viteConfigurationGenerator(
|
||||
if (projectType === 'library') {
|
||||
// update tsconfig.lib.json to include vite/client
|
||||
updateJson(tree, joinPathFragments(root, 'tsconfig.lib.json'), (json) => {
|
||||
if (!json.compilerOptions) {
|
||||
json.compilerOptions = {};
|
||||
}
|
||||
if (!json.compilerOptions.types) {
|
||||
json.compilerOptions.types = [];
|
||||
}
|
||||
if (!json.compilerOptions.types.includes('vite/client')) {
|
||||
return {
|
||||
...json,
|
||||
|
||||
@@ -191,6 +191,12 @@ export function withNx(pluginOptions?: WithNxOptions): NxWebpackPlugin {
|
||||
process.env.NODE_ENV === 'production'
|
||||
? (process.env.NODE_ENV as 'development' | 'production')
|
||||
: ('none' as const),
|
||||
// When target is Node, the Webpack mode will be set to 'none' which disables in memory caching and causes a full rebuild on every change.
|
||||
// So to mitigate this we enable in memory caching when target is Node and in watch mode.
|
||||
cache:
|
||||
options.target === ('node' as const) && options.watch
|
||||
? { type: 'memory' as const }
|
||||
: undefined,
|
||||
devtool:
|
||||
options.sourceMap === 'hidden'
|
||||
? 'hidden-source-map'
|
||||
|
||||
@@ -34,7 +34,7 @@ export function updateImports(
|
||||
schema: NormalizedSchema,
|
||||
project: ProjectConfiguration
|
||||
) {
|
||||
if (project.projectType === 'application') {
|
||||
if (project.projectType !== 'library') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user