fix(core): merge package.json plugins and updated project.json plugin… (#26952)

… using v2

## Current Behavior
<!-- This is the behavior we have today -->

The `package.json` handling is split between before and after plugins so
it's confusing. Also, `package.json` nodes will get overwritten by
plugins while others won't.

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

The `package.json` handling is merged. Also, the `package.json` nodes
will always overwrite plugins as intended.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
This commit is contained in:
Jason Jean 2024-07-16 12:46:57 -05:00 committed by GitHub
parent 1a9429643f
commit 51f5fe4434
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 395 additions and 467 deletions

View File

@ -25,7 +25,7 @@ import {
clearRequireCache,
loadConfigFile,
} from '@nx/devkit/src/utils/config-utils';
import { getGlobPatternsFromPackageManagerWorkspaces } from 'nx/src/plugins/package-json-workspaces';
import { getGlobPatternsFromPackageManagerWorkspaces } from 'nx/src/plugins/package-json';
import { combineGlobPatterns } from 'nx/src/utils/globs';
import { minimatch } from 'minimatch';
import { hashObject } from 'nx/src/devkit-internals';

View File

@ -1,6 +1,6 @@
import type { NxPluginV2 } from '../src/project-graph/plugins';
import { workspaceRoot } from '../src/utils/workspace-root';
import { createNodeFromPackageJson } from '../src/plugins/package-json-workspaces';
import { createNodeFromPackageJson } from '../src/plugins/package-json';
const plugin: NxPluginV2 = {
name: 'nx-all-package-jsons-plugin',

View File

@ -4,7 +4,7 @@ import { basename, join, relative } from 'path';
import {
buildProjectConfigurationFromPackageJson,
getGlobPatternsFromPackageManagerWorkspaces,
} from '../../plugins/package-json-workspaces';
} from '../../plugins/package-json';
import { buildProjectFromProjectJson } from '../../plugins/project-json/build-nodes/project-json';
import { renamePropertyWithStableKeys } from '../../adapter/angular-json';
import {

View File

@ -1,2 +0,0 @@
export * from './create-nodes';
export const name = 'nx/core/package-json-workspaces';

View File

@ -1,7 +1,7 @@
import '../../internal-testing-utils/mock-fs';
import { vol } from 'memfs';
import { createNodeFromPackageJson, createNodes } from './create-nodes';
import { createNodeFromPackageJson, createNodesV2 } from './create-nodes';
describe('nx package.json workspaces plugin', () => {
const context = {
@ -198,7 +198,7 @@ describe('nx package.json workspaces plugin', () => {
});
describe('negative patterns', () => {
it('should work based on negative patterns defined in package.json workspaces', () => {
it('should work based on negative patterns defined in package.json workspaces', async () => {
vol.fromJSON(
{
'package.json': JSON.stringify({
@ -231,64 +231,74 @@ describe('nx package.json workspaces plugin', () => {
// No matching project based on the package.json "workspace" config
expect(
createNodes[1]('package.json', undefined, context)
).toMatchInlineSnapshot(`{}`);
await createNodesV2[1](['package.json'], undefined, context)
).toMatchInlineSnapshot(`[]`);
// Matching project based on the package.json "workspace" config
expect(createNodes[1]('packages/vite/package.json', undefined, context))
.toMatchInlineSnapshot(`
{
"projects": {
"packages/vite": {
"metadata": {
"description": undefined,
"targetGroups": {},
},
"name": "vite",
"root": "packages/vite",
"sourceRoot": "packages/vite",
"tags": [
"npm:public",
],
"targets": {
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
expect(
await createNodesV2[1](
['packages/vite/package.json'],
undefined,
context
)
).toMatchInlineSnapshot(`
[
[
"packages/vite/package.json",
{
"projects": {
"packages/vite": {
"metadata": {
"description": undefined,
"targetGroups": {},
},
"name": "vite",
"root": "packages/vite",
"sourceRoot": "packages/vite",
"tags": [
"npm:public",
],
"executor": "@nx/js:release-publish",
"options": {},
"targets": {
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
],
"executor": "@nx/js:release-publish",
"options": {},
},
},
},
},
},
},
}
],
]
`);
// No matching project based on the package.json "workspace" config
expect(
createNodes[1]('packages/fs/package.json', undefined, context)
).toMatchInlineSnapshot(`{}`);
await createNodesV2[1](['packages/fs/package.json'], undefined, context)
).toMatchInlineSnapshot(`[]`);
// No matching project based on the package.json "workspace" config
expect(
createNodes[1](
'packages/orm-browser-example/package.json',
await createNodesV2[1](
['packages/orm-browser-example/package.json'],
undefined,
context
)
).toMatchInlineSnapshot(`{}`);
).toMatchInlineSnapshot(`[]`);
// No matching project based on the package.json "workspace" config
expect(
createNodes[1](
'packages/framework-examples/package.json',
await createNodesV2[1](
['packages/framework-examples/package.json'],
undefined,
context
)
).toMatchInlineSnapshot(`{}`);
).toMatchInlineSnapshot(`[]`);
});
it('should work based on negative patterns defined in pnpm-workspace.yaml', () => {
it('should work based on negative patterns defined in pnpm-workspace.yaml', async () => {
vol.fromJSON(
{
'package.json': JSON.stringify({ name: 'root' }),
@ -319,64 +329,74 @@ describe('nx package.json workspaces plugin', () => {
// No matching project based on the pnpm-workspace.yaml "packages" config
expect(
createNodes[1]('package.json', undefined, context)
).toMatchInlineSnapshot(`{}`);
await createNodesV2[1](['package.json'], undefined, context)
).toMatchInlineSnapshot(`[]`);
// Matching project based on the pnpm-workspace.yaml "packages" config
expect(createNodes[1]('packages/vite/package.json', undefined, context))
.toMatchInlineSnapshot(`
{
"projects": {
"packages/vite": {
"metadata": {
"description": undefined,
"targetGroups": {},
},
"name": "vite",
"root": "packages/vite",
"sourceRoot": "packages/vite",
"tags": [
"npm:public",
],
"targets": {
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
expect(
await createNodesV2[1](
['packages/vite/package.json'],
undefined,
context
)
).toMatchInlineSnapshot(`
[
[
"packages/vite/package.json",
{
"projects": {
"packages/vite": {
"metadata": {
"description": undefined,
"targetGroups": {},
},
"name": "vite",
"root": "packages/vite",
"sourceRoot": "packages/vite",
"tags": [
"npm:public",
],
"executor": "@nx/js:release-publish",
"options": {},
"targets": {
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
],
"executor": "@nx/js:release-publish",
"options": {},
},
},
},
},
},
},
}
],
]
`);
// No matching project based on the pnpm-workspace.yaml "packages" config
expect(
createNodes[1]('packages/fs/package.json', undefined, context)
).toMatchInlineSnapshot(`{}`);
await createNodesV2[1](['packages/fs/package.json'], undefined, context)
).toMatchInlineSnapshot(`[]`);
// No matching project based on the pnpm-workspace.yaml "packages" config
expect(
createNodes[1](
'packages/orm-browser-example/package.json',
await createNodesV2[1](
['packages/orm-browser-example/package.json'],
undefined,
context
)
).toMatchInlineSnapshot(`{}`);
).toMatchInlineSnapshot(`[]`);
// No matching project based on the pnpm-workspace.yaml "packages" config
expect(
createNodes[1](
'packages/framework-examples/package.json',
await createNodesV2[1](
['packages/framework-examples/package.json'],
undefined,
context
)
).toMatchInlineSnapshot(`{}`);
).toMatchInlineSnapshot(`[]`);
});
it('should work based on negative patterns defined in lerna.json', () => {
it('should work based on negative patterns defined in lerna.json', async () => {
vol.fromJSON(
{
'package.json': JSON.stringify({ name: 'root' }),
@ -403,66 +423,76 @@ describe('nx package.json workspaces plugin', () => {
// No matching project based on the lerna.json "packages" config
expect(
createNodes[1]('package.json', undefined, context)
).toMatchInlineSnapshot(`{}`);
await createNodesV2[1](['package.json'], undefined, context)
).toMatchInlineSnapshot(`[]`);
// Matching project based on the lerna.json "packages" config
expect(createNodes[1]('packages/vite/package.json', undefined, context))
.toMatchInlineSnapshot(`
{
"projects": {
"packages/vite": {
"metadata": {
"description": undefined,
"targetGroups": {},
},
"name": "vite",
"root": "packages/vite",
"sourceRoot": "packages/vite",
"tags": [
"npm:public",
],
"targets": {
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
expect(
await createNodesV2[1](
['packages/vite/package.json'],
undefined,
context
)
).toMatchInlineSnapshot(`
[
[
"packages/vite/package.json",
{
"projects": {
"packages/vite": {
"metadata": {
"description": undefined,
"targetGroups": {},
},
"name": "vite",
"root": "packages/vite",
"sourceRoot": "packages/vite",
"tags": [
"npm:public",
],
"executor": "@nx/js:release-publish",
"options": {},
"targets": {
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
],
"executor": "@nx/js:release-publish",
"options": {},
},
},
},
},
},
},
}
],
]
`);
// No matching project based on the lerna.json "packages" config
expect(
createNodes[1]('packages/fs/package.json', undefined, context)
).toMatchInlineSnapshot(`{}`);
await createNodesV2[1](['packages/fs/package.json'], undefined, context)
).toMatchInlineSnapshot(`[]`);
// No matching project based on the lerna.json "packages" config
expect(
createNodes[1](
'packages/orm-browser-example/package.json',
await createNodesV2[1](
['packages/orm-browser-example/package.json'],
undefined,
context
)
).toMatchInlineSnapshot(`{}`);
).toMatchInlineSnapshot(`[]`);
// No matching project based on the lerna.json "packages" config
expect(
createNodes[1](
'packages/framework-examples/package.json',
await createNodesV2[1](
['packages/framework-examples/package.json'],
undefined,
context
)
).toMatchInlineSnapshot(`{}`);
).toMatchInlineSnapshot(`[]`);
});
});
describe('sibling project.json files', () => {
it('should add a script target if the sibling project.json file does not exist', () => {
it('should add a script target if the sibling project.json file does not exist', async () => {
vol.fromJSON(
{
'package.json': JSON.stringify({
@ -479,51 +509,57 @@ describe('nx package.json workspaces plugin', () => {
'/root'
);
expect(createNodes[1]('packages/a/package.json', undefined, context))
.toMatchInlineSnapshot(`
{
"projects": {
"packages/a": {
"metadata": {
"description": undefined,
"targetGroups": {
"NPM Scripts": [
"build",
],
},
},
"name": "root",
"root": "packages/a",
"sourceRoot": "packages/a",
"tags": [
"npm:public",
],
"targets": {
"build": {
"executor": "nx:run-script",
expect(
await createNodesV2[1](['packages/a/package.json'], undefined, context)
).toMatchInlineSnapshot(`
[
[
"packages/a/package.json",
{
"projects": {
"packages/a": {
"metadata": {
"runCommand": "npm run build",
"scriptContent": "echo build",
"description": undefined,
"targetGroups": {
"NPM Scripts": [
"build",
],
},
},
"options": {
"script": "build",
},
},
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
"name": "root",
"root": "packages/a",
"sourceRoot": "packages/a",
"tags": [
"npm:public",
],
"executor": "@nx/js:release-publish",
"options": {},
"targets": {
"build": {
"executor": "nx:run-script",
"metadata": {
"runCommand": "npm run build",
"scriptContent": "echo build",
},
"options": {
"script": "build",
},
},
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
],
"executor": "@nx/js:release-publish",
"options": {},
},
},
},
},
},
},
}
],
]
`);
});
it('should add a script target if the sibling project.json exists but does not have a conflicting target', () => {
it('should add a script target if the sibling project.json exists but does not have a conflicting target', async () => {
vol.fromJSON(
{
'package.json': JSON.stringify({
@ -547,51 +583,57 @@ describe('nx package.json workspaces plugin', () => {
'/root'
);
expect(createNodes[1]('packages/a/package.json', undefined, context))
.toMatchInlineSnapshot(`
{
"projects": {
"packages/a": {
"metadata": {
"description": undefined,
"targetGroups": {
"NPM Scripts": [
"build",
],
},
},
"name": "root",
"root": "packages/a",
"sourceRoot": "packages/a",
"tags": [
"npm:public",
],
"targets": {
"build": {
"executor": "nx:run-script",
expect(
await createNodesV2[1](['packages/a/package.json'], undefined, context)
).toMatchInlineSnapshot(`
[
[
"packages/a/package.json",
{
"projects": {
"packages/a": {
"metadata": {
"runCommand": "npm run build",
"scriptContent": "echo build",
"description": undefined,
"targetGroups": {
"NPM Scripts": [
"build",
],
},
},
"options": {
"script": "build",
},
},
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
"name": "root",
"root": "packages/a",
"sourceRoot": "packages/a",
"tags": [
"npm:public",
],
"executor": "@nx/js:release-publish",
"options": {},
"targets": {
"build": {
"executor": "nx:run-script",
"metadata": {
"runCommand": "npm run build",
"scriptContent": "echo build",
},
"options": {
"script": "build",
},
},
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
],
"executor": "@nx/js:release-publish",
"options": {},
},
},
},
},
},
},
}
],
]
`);
});
it('should not add a script target if the sibling project.json exists and has a conflicting target', () => {
it('should not add a script target if the sibling project.json exists and has a conflicting target', async () => {
vol.fromJSON(
{
'package.json': JSON.stringify({
@ -615,33 +657,39 @@ describe('nx package.json workspaces plugin', () => {
'/root'
);
expect(createNodes[1]('packages/a/package.json', undefined, context))
.toMatchInlineSnapshot(`
{
"projects": {
"packages/a": {
"metadata": {
"description": undefined,
"targetGroups": {},
},
"name": "root",
"root": "packages/a",
"sourceRoot": "packages/a",
"tags": [
"npm:public",
],
"targets": {
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
expect(
await createNodesV2[1](['packages/a/package.json'], undefined, context)
).toMatchInlineSnapshot(`
[
[
"packages/a/package.json",
{
"projects": {
"packages/a": {
"metadata": {
"description": undefined,
"targetGroups": {},
},
"name": "root",
"root": "packages/a",
"sourceRoot": "packages/a",
"tags": [
"npm:public",
],
"executor": "@nx/js:release-publish",
"options": {},
"targets": {
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
],
"executor": "@nx/js:release-publish",
"options": {},
},
},
},
},
},
},
}
],
]
`);
});
});

View File

@ -16,22 +16,71 @@ import {
readTargetsFromPackageJson,
} from '../../utils/package-json';
import { joinPathFragments } from '../../utils/path';
import { CreateNodes } from '../../project-graph/plugins';
import {
createNodesFromFiles,
CreateNodesV2,
} from '../../project-graph/plugins';
import { basename } from 'path';
export const createNodes: CreateNodes = [
combineGlobPatterns('package.json', '**/package.json'),
(p, _, { workspaceRoot }) => {
const readJson = (f) => readJsonFile(join(workspaceRoot, f));
const matcher = buildPackageJsonWorkspacesMatcher(workspaceRoot, readJson);
export const createNodesV2: CreateNodesV2 = [
combineGlobPatterns(
'package.json',
'**/package.json',
'project.json',
'**/project.json'
),
(configFiles, _, context) => {
const { packageJsons, projectJsonRoots } = splitConfigFiles(configFiles);
if (matcher(p)) {
return createNodeFromPackageJson(p, workspaceRoot);
}
// The given package.json is not part of the workspaces configuration.
return {};
const readJson = (f) => readJsonFile(join(context.workspaceRoot, f));
const isInPackageJsonWorkspaces = buildPackageJsonWorkspacesMatcher(
context.workspaceRoot,
readJson
);
const isNextToProjectJson = (packageJsonPath: string) => {
return projectJsonRoots.has(dirname(packageJsonPath));
};
return createNodesFromFiles(
(packageJsonPath, options, context) => {
if (
!isInPackageJsonWorkspaces(packageJsonPath) &&
!isNextToProjectJson(packageJsonPath)
) {
// Skip if package.json is not part of the package.json workspaces and not next to a project.json.
return null;
}
return createNodeFromPackageJson(
packageJsonPath,
context.workspaceRoot
);
},
packageJsons,
_,
context
);
},
];
function splitConfigFiles(configFiles: readonly string[]): {
packageJsons: string[];
projectJsonRoots: Set<string>;
} {
const packageJsons = [];
const projectJsonRoots = new Set<string>();
for (const configFile of configFiles) {
if (basename(configFile) === 'package.json') {
packageJsons.push(configFile);
} else {
projectJsonRoots.add(dirname(configFile));
}
}
return { packageJsons, projectJsonRoots };
}
export function buildPackageJsonWorkspacesMatcher(
workspaceRoot: string,
readJson: (string) => any

View File

@ -0,0 +1,2 @@
export * from './create-nodes';
export const name = 'nx/core/package-json';

View File

@ -1,126 +0,0 @@
import * as memfs from 'memfs';
import '../../../internal-testing-utils/mock-fs';
import { PackageJsonProjectsNextToProjectJsonPlugin } from './package-json-next-to-project-json';
import { CreateNodesContext } from '../../../project-graph/plugins';
const { createNodes } = PackageJsonProjectsNextToProjectJsonPlugin;
describe('nx project.json plugin', () => {
let context: CreateNodesContext;
let createNodesFunction = createNodes[1];
beforeEach(() => {
context = {
nxJsonConfiguration: {},
workspaceRoot: '/root',
configFiles: [],
};
});
it('should build projects from package.json next to project.json', () => {
memfs.vol.fromJSON(
{
'package.json': JSON.stringify({
name: 'lib-a',
description: 'lib-a project description',
}),
'packages/lib-a/project.json': JSON.stringify({
name: 'lib-a',
description: 'lib-a project description',
targets: {
build: {
executor: 'nx:run-commands',
options: {},
},
},
}),
'packages/lib-a/package.json': JSON.stringify({
name: 'lib-a',
description: 'lib-a package description',
scripts: {
test: 'jest',
},
}),
},
'/root'
);
expect(
createNodesFunction('packages/lib-a/project.json', undefined, context)
).toMatchInlineSnapshot(`
{
"projects": {
"lib-a": {
"metadata": {
"description": "lib-a package description",
"targetGroups": {
"NPM Scripts": [
"test",
],
},
},
"name": "lib-a",
"root": "packages/lib-a",
"tags": [
"npm:public",
],
"targets": {
"nx-release-publish": {
"dependsOn": [
"^nx-release-publish",
],
"executor": "@nx/js:release-publish",
"options": {},
},
"test": {
"executor": "nx:run-script",
"metadata": {
"runCommand": "npm run test",
"scriptContent": "jest",
},
"options": {
"script": "test",
},
},
},
},
},
}
`);
});
it('should not build package manager workspace projects from package.json next to project.json', () => {
memfs.vol.fromJSON(
{
'package.json': JSON.stringify({
name: 'lib-a',
description: 'lib-a project description',
workspaces: ['packages/lib-a'],
}),
'packages/lib-a/project.json': JSON.stringify({
name: 'lib-a',
description: 'lib-a project description',
targets: {
build: {
executor: 'nx:run-commands',
options: {},
},
},
}),
'packages/lib-a/package.json': JSON.stringify({
name: 'lib-a',
description: 'lib-a package description',
scripts: {
test: 'jest',
},
}),
},
'/root'
);
expect(
createNodesFunction('packages/lib-a/project.json', undefined, context)
).toMatchInlineSnapshot(`{}`);
});
});

View File

@ -1,75 +0,0 @@
import { dirname, join } from 'path';
import { existsSync } from 'fs';
import { NxPluginV2 } from '../../../project-graph/plugins';
import { readJsonFile } from '../../../utils/fileutils';
import { ProjectConfiguration } from '../../../config/workspace-json-project-json';
import {
PackageJson,
getMetadataFromPackageJson,
getTagsFromPackageJson,
readTargetsFromPackageJson,
} from '../../../utils/package-json';
import { buildPackageJsonWorkspacesMatcher } from '../../package-json-workspaces';
// TODO: Remove this one day, this should not need to be done.
export const PackageJsonProjectsNextToProjectJsonPlugin: NxPluginV2 = {
// Its not a problem if plugins happen to have same name, and this
// will look least confusing in the source map.
name: 'nx/core/package-json',
createNodes: [
'{project.json,**/project.json}',
(file, _, { workspaceRoot }) => {
const project = createProjectFromPackageJsonNextToProjectJson(
file,
workspaceRoot
);
return project
? {
projects: {
[project.name]: project,
},
}
: {};
},
],
};
export default PackageJsonProjectsNextToProjectJsonPlugin;
function createProjectFromPackageJsonNextToProjectJson(
projectJsonPath: string,
workspaceRoot: string
): ProjectConfiguration | null {
const root = dirname(projectJsonPath);
const relativePackageJsonPath = join(root, 'package.json');
const packageJsonPath = join(workspaceRoot, relativePackageJsonPath);
const readJson = (f) => readJsonFile(join(workspaceRoot, f));
// Do not create projects for package.json files
// that are part of the package manager workspaces
// Those package.json files will be processed later on
const matcher = buildPackageJsonWorkspacesMatcher(workspaceRoot, readJson);
if (!existsSync(packageJsonPath) || matcher(relativePackageJsonPath)) {
return null;
}
try {
const packageJson: PackageJson = readJsonFile(packageJsonPath);
let { nx, name } = packageJson;
return {
...nx,
name,
root,
targets: readTargetsFromPackageJson(packageJson),
metadata: getMetadataFromPackageJson(packageJson),
tags: getTagsFromPackageJson(packageJson),
} as ProjectConfiguration;
} catch (e) {
console.log(e);
return null;
}
}

View File

@ -4,7 +4,7 @@ import '../../../internal-testing-utils/mock-fs';
import { ProjectJsonProjectsPlugin } from './project-json';
import { CreateNodesContext } from '../../../project-graph/plugins';
const { createNodes } = ProjectJsonProjectsPlugin;
const { createNodesV2 } = ProjectJsonProjectsPlugin;
describe('nx project.json plugin', () => {
let context: CreateNodesContext;
@ -16,7 +16,7 @@ describe('nx project.json plugin', () => {
};
});
it('should build projects from project.json', () => {
it('should build projects from project.json', async () => {
memfs.vol.fromJSON(
{
'project.json': JSON.stringify({
@ -36,36 +36,46 @@ describe('nx project.json plugin', () => {
'/root'
);
expect(createNodes[1]('project.json', undefined, context))
.toMatchInlineSnapshot(`
{
"projects": {
".": {
"name": "root",
"root": ".",
"targets": {
"command": "echo root project",
},
},
},
}
`);
expect(createNodes[1]('packages/lib-a/project.json', undefined, context))
.toMatchInlineSnapshot(`
{
"projects": {
"packages/lib-a": {
"name": "lib-a",
"root": "packages/lib-a",
"targets": {
"build": {
"executor": "nx:run-commands",
"options": {},
expect(
await createNodesV2[1](
['project.json', 'packages/lib-a/project.json'],
undefined,
context
)
).toMatchInlineSnapshot(`
[
[
"project.json",
{
"projects": {
".": {
"name": "root",
"root": ".",
"targets": {
"command": "echo root project",
},
},
},
},
},
}
],
[
"packages/lib-a/project.json",
{
"projects": {
"packages/lib-a": {
"name": "lib-a",
"root": "packages/lib-a",
"targets": {
"build": {
"executor": "nx:run-commands",
"options": {},
},
},
},
},
},
],
]
`);
});
});

View File

@ -3,25 +3,35 @@ import { dirname, join } from 'node:path';
import { ProjectConfiguration } from '../../../config/workspace-json-project-json';
import { toProjectName } from '../../../config/to-project-name';
import { readJsonFile } from '../../../utils/fileutils';
import { NxPluginV2 } from '../../../project-graph/plugins';
import {
createNodesFromFiles,
NxPluginV2,
} from '../../../project-graph/plugins';
import { PackageJson } from '../../../utils/package-json';
export const ProjectJsonProjectsPlugin: NxPluginV2 = {
name: 'nx/core/project-json',
createNodes: [
createNodesV2: [
'{project.json,**/project.json}',
(file, _, { workspaceRoot }) => {
const json = readJsonFile<ProjectConfiguration>(
join(workspaceRoot, file)
);
(configFiles, _, context) => {
return createNodesFromFiles(
(file) => {
const json = readJsonFile<ProjectConfiguration>(
join(context.workspaceRoot, file)
);
const project = buildProjectFromProjectJson(json, file);
const project = buildProjectFromProjectJson(json, file);
return {
projects: {
[project.root]: project,
return {
projects: {
[project.root]: project,
},
};
},
};
configFiles,
_,
context
);
},
],
};

View File

@ -24,7 +24,7 @@ import {
import {
buildProjectConfigurationFromPackageJson,
getGlobPatternsFromPackageManagerWorkspaces,
} from '../plugins/package-json-workspaces';
} from '../plugins/package-json';
import { globWithWorkspaceContextSync } from '../utils/workspace-context';
import { buildProjectFromProjectJson } from '../plugins/project-json/build-nodes/project-json';
import { PackageJson } from '../utils/package-json';

View File

@ -192,12 +192,6 @@ async function normalizePlugins(plugins: PluginConfiguration[], root: string) {
plugins ??= [];
return [
// This plugin adds targets that we want to be able to overwrite
// in any user-land plugin, so it has to be first :).
join(
__dirname,
'../../plugins/project-json/build-nodes/package-json-next-to-project-json'
),
...plugins,
// Most of the nx core node plugins go on the end, s.t. it overwrites any other plugins
...(await getDefaultPlugins(root)),
@ -210,7 +204,7 @@ export async function getDefaultPlugins(root: string) {
...(shouldMergeAngularProjects(root, false)
? [join(__dirname, '../../adapter/angular-json')]
: []),
join(__dirname, '../../plugins/package-json-workspaces'),
join(__dirname, '../../plugins/package-json'),
join(__dirname, '../../plugins/project-json/build-nodes/project-json'),
];
}

View File

@ -293,7 +293,9 @@ async function importPluginModule(pluginPath: string): Promise<NxPlugin> {
const m = await import(pluginPath);
if (
m.default &&
('createNodes' in m.default || 'createDependencies' in m.default)
('createNodes' in m.default ||
'createNodesV2' in m.default ||
'createDependencies' in m.default)
) {
return m.default;
}

View File

@ -183,4 +183,18 @@ describe('createNodesFromFiles', () => {
`);
}
});
it('should filter out null results', async () => {
const createNodes = [
'**/*',
() => {
return null;
},
] as const;
const options = {};
expect(
await createNodesFromFiles(createNodes[1], configFiles, options, context)
).toEqual([]);
});
});

View File

@ -73,7 +73,9 @@ export async function createNodesFromFiles<T = unknown>(
...context,
configFiles,
});
results.push([file, value] as const);
if (value) {
results.push([file, value] as const);
}
} catch (e) {
errors.push([file, e] as const);
}

View File

@ -2,7 +2,7 @@ import { shouldMergeAngularProjects } from '../adapter/angular-json';
import { ProjectGraphProcessor } from '../config/project-graph';
import { TargetConfiguration } from '../config/workspace-json-project-json';
import ProjectJsonProjectsPlugin from '../plugins/project-json/build-nodes/project-json';
import * as PackageJsonWorkspacesPlugin from '../plugins/package-json-workspaces';
import * as PackageJsonWorkspacesPlugin from '../plugins/package-json';
import { NxPluginV2 } from '../project-graph/plugins';
/**