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:
parent
1a9429643f
commit
51f5fe4434
@ -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';
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
export * from './create-nodes';
|
||||
export const name = 'nx/core/package-json-workspaces';
|
||||
@ -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,12 +231,20 @@ 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(`
|
||||
expect(
|
||||
await createNodesV2[1](
|
||||
['packages/vite/package.json'],
|
||||
undefined,
|
||||
context
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
"packages/vite/package.json",
|
||||
{
|
||||
"projects": {
|
||||
"packages/vite": {
|
||||
@ -261,34 +269,36 @@ describe('nx package.json workspaces plugin', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
|
||||
// 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,12 +329,20 @@ 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(`
|
||||
expect(
|
||||
await createNodesV2[1](
|
||||
['packages/vite/package.json'],
|
||||
undefined,
|
||||
context
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
"packages/vite/package.json",
|
||||
{
|
||||
"projects": {
|
||||
"packages/vite": {
|
||||
@ -349,34 +367,36 @@ describe('nx package.json workspaces plugin', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
|
||||
// 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,12 +423,20 @@ 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(`
|
||||
expect(
|
||||
await createNodesV2[1](
|
||||
['packages/vite/package.json'],
|
||||
undefined,
|
||||
context
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
"packages/vite/package.json",
|
||||
{
|
||||
"projects": {
|
||||
"packages/vite": {
|
||||
@ -433,36 +461,38 @@ describe('nx package.json workspaces plugin', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
|
||||
// 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,8 +509,12 @@ describe('nx package.json workspaces plugin', () => {
|
||||
'/root'
|
||||
);
|
||||
|
||||
expect(createNodes[1]('packages/a/package.json', undefined, context))
|
||||
.toMatchInlineSnapshot(`
|
||||
expect(
|
||||
await createNodesV2[1](['packages/a/package.json'], undefined, context)
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
"packages/a/package.json",
|
||||
{
|
||||
"projects": {
|
||||
"packages/a": {
|
||||
@ -519,11 +553,13 @@ describe('nx package.json workspaces plugin', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
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,8 +583,12 @@ describe('nx package.json workspaces plugin', () => {
|
||||
'/root'
|
||||
);
|
||||
|
||||
expect(createNodes[1]('packages/a/package.json', undefined, context))
|
||||
.toMatchInlineSnapshot(`
|
||||
expect(
|
||||
await createNodesV2[1](['packages/a/package.json'], undefined, context)
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
"packages/a/package.json",
|
||||
{
|
||||
"projects": {
|
||||
"packages/a": {
|
||||
@ -587,11 +627,13 @@ describe('nx package.json workspaces plugin', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
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,8 +657,12 @@ describe('nx package.json workspaces plugin', () => {
|
||||
'/root'
|
||||
);
|
||||
|
||||
expect(createNodes[1]('packages/a/package.json', undefined, context))
|
||||
.toMatchInlineSnapshot(`
|
||||
expect(
|
||||
await createNodesV2[1](['packages/a/package.json'], undefined, context)
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
"packages/a/package.json",
|
||||
{
|
||||
"projects": {
|
||||
"packages/a": {
|
||||
@ -641,7 +687,9 @@ describe('nx package.json workspaces plugin', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
@ -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);
|
||||
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;
|
||||
}
|
||||
// The given package.json is not part of the workspaces configuration.
|
||||
return {};
|
||||
|
||||
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
|
||||
2
packages/nx/src/plugins/package-json/index.ts
Normal file
2
packages/nx/src/plugins/package-json/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './create-nodes';
|
||||
export const name = 'nx/core/package-json';
|
||||
@ -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(`{}`);
|
||||
});
|
||||
});
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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,8 +36,16 @@ describe('nx project.json plugin', () => {
|
||||
'/root'
|
||||
);
|
||||
|
||||
expect(createNodes[1]('project.json', undefined, context))
|
||||
.toMatchInlineSnapshot(`
|
||||
expect(
|
||||
await createNodesV2[1](
|
||||
['project.json', 'packages/lib-a/project.json'],
|
||||
undefined,
|
||||
context
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
"project.json",
|
||||
{
|
||||
"projects": {
|
||||
".": {
|
||||
@ -48,10 +56,10 @@ describe('nx project.json plugin', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`);
|
||||
expect(createNodes[1]('packages/lib-a/project.json', undefined, context))
|
||||
.toMatchInlineSnapshot(`
|
||||
},
|
||||
],
|
||||
[
|
||||
"packages/lib-a/project.json",
|
||||
{
|
||||
"projects": {
|
||||
"packages/lib-a": {
|
||||
@ -65,7 +73,9 @@ describe('nx project.json plugin', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
@ -3,16 +3,21 @@ 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 }) => {
|
||||
(configFiles, _, context) => {
|
||||
return createNodesFromFiles(
|
||||
(file) => {
|
||||
const json = readJsonFile<ProjectConfiguration>(
|
||||
join(workspaceRoot, file)
|
||||
join(context.workspaceRoot, file)
|
||||
);
|
||||
|
||||
const project = buildProjectFromProjectJson(json, file);
|
||||
@ -23,6 +28,11 @@ export const ProjectJsonProjectsPlugin: NxPluginV2 = {
|
||||
},
|
||||
};
|
||||
},
|
||||
configFiles,
|
||||
_,
|
||||
context
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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'),
|
||||
];
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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([]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -73,7 +73,9 @@ export async function createNodesFromFiles<T = unknown>(
|
||||
...context,
|
||||
configFiles,
|
||||
});
|
||||
if (value) {
|
||||
results.push([file, value] as const);
|
||||
}
|
||||
} catch (e) {
|
||||
errors.push([file, e] as const);
|
||||
}
|
||||
|
||||
@ -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';
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user