feat(core): add standard way to pass plugin options (#19589)
Co-authored-by: FrozenPandaz <jasonjean1993@gmail.com>
This commit is contained in:
parent
7ea2374caa
commit
f918a72307
@ -1,10 +1,16 @@
|
|||||||
# Type alias: CreateDependencies
|
# Type alias: CreateDependencies<T\>
|
||||||
|
|
||||||
Ƭ **CreateDependencies**: (`context`: [`CreateDependenciesContext`](../../devkit/documents/CreateDependenciesContext)) => [`RawProjectGraphDependency`](../../devkit/documents/RawProjectGraphDependency)[] \| `Promise`<[`RawProjectGraphDependency`](../../devkit/documents/RawProjectGraphDependency)[]\>
|
Ƭ **CreateDependencies**<`T`\>: (`options`: `T` \| `undefined`, `context`: [`CreateDependenciesContext`](../../devkit/documents/CreateDependenciesContext)) => [`RawProjectGraphDependency`](../../devkit/documents/RawProjectGraphDependency)[] \| `Promise`<[`RawProjectGraphDependency`](../../devkit/documents/RawProjectGraphDependency)[]\>
|
||||||
|
|
||||||
|
#### Type parameters
|
||||||
|
|
||||||
|
| Name | Type |
|
||||||
|
| :--- | :---------------------------------------------------------------------- |
|
||||||
|
| `T` | extends `Record`<`string`, `unknown`\> = `Record`<`string`, `unknown`\> |
|
||||||
|
|
||||||
#### Type declaration
|
#### Type declaration
|
||||||
|
|
||||||
▸ (`context`): [`RawProjectGraphDependency`](../../devkit/documents/RawProjectGraphDependency)[] \| `Promise`<[`RawProjectGraphDependency`](../../devkit/documents/RawProjectGraphDependency)[]\>
|
▸ (`options`, `context`): [`RawProjectGraphDependency`](../../devkit/documents/RawProjectGraphDependency)[] \| `Promise`<[`RawProjectGraphDependency`](../../devkit/documents/RawProjectGraphDependency)[]\>
|
||||||
|
|
||||||
A function which parses files in the workspace to create dependencies in the [ProjectGraph](../../devkit/documents/ProjectGraph)
|
A function which parses files in the workspace to create dependencies in the [ProjectGraph](../../devkit/documents/ProjectGraph)
|
||||||
Use [validateDependency](../../devkit/documents/validateDependency) to validate dependencies
|
Use [validateDependency](../../devkit/documents/validateDependency) to validate dependencies
|
||||||
@ -13,6 +19,7 @@ Use [validateDependency](../../devkit/documents/validateDependency) to validate
|
|||||||
|
|
||||||
| Name | Type |
|
| Name | Type |
|
||||||
| :-------- | :------------------------------------------------------------------------------ |
|
| :-------- | :------------------------------------------------------------------------------ |
|
||||||
|
| `options` | `T` \| `undefined` |
|
||||||
| `context` | [`CreateDependenciesContext`](../../devkit/documents/CreateDependenciesContext) |
|
| `context` | [`CreateDependenciesContext`](../../devkit/documents/CreateDependenciesContext) |
|
||||||
|
|
||||||
##### Returns
|
##### Returns
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
# Type alias: CreateNodes
|
# Type alias: CreateNodes<T\>
|
||||||
|
|
||||||
Ƭ **CreateNodes**: readonly [projectFilePattern: string, createNodesFunction: CreateNodesFunction]
|
Ƭ **CreateNodes**<`T`\>: readonly [projectFilePattern: string, createNodesFunction: CreateNodesFunction<T\>]
|
||||||
|
|
||||||
A pair of file patterns and [CreateNodesFunction](../../devkit/documents/CreateNodesFunction)
|
A pair of file patterns and [CreateNodesFunction](../../devkit/documents/CreateNodesFunction)
|
||||||
|
|
||||||
|
#### Type parameters
|
||||||
|
|
||||||
|
| Name | Type |
|
||||||
|
| :--- | :---------------------------------------------------------------------- |
|
||||||
|
| `T` | extends `Record`<`string`, `unknown`\> = `Record`<`string`, `unknown`\> |
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
# Type alias: CreateNodesFunction
|
# Type alias: CreateNodesFunction<T\>
|
||||||
|
|
||||||
Ƭ **CreateNodesFunction**: (`projectConfigurationFile`: `string`, `context`: [`CreateNodesContext`](../../devkit/documents/CreateNodesContext)) => { `externalNodes?`: `Record`<`string`, [`ProjectGraphExternalNode`](../../devkit/documents/ProjectGraphExternalNode)\> ; `projects?`: `Record`<`string`, [`ProjectConfiguration`](../../devkit/documents/ProjectConfiguration)\> }
|
Ƭ **CreateNodesFunction**<`T`\>: (`projectConfigurationFile`: `string`, `options`: `T` \| `undefined`, `context`: [`CreateNodesContext`](../../devkit/documents/CreateNodesContext)) => { `externalNodes?`: `Record`<`string`, [`ProjectGraphExternalNode`](../../devkit/documents/ProjectGraphExternalNode)\> ; `projects?`: `Record`<`string`, [`ProjectConfiguration`](../../devkit/documents/ProjectConfiguration)\> }
|
||||||
|
|
||||||
|
#### Type parameters
|
||||||
|
|
||||||
|
| Name | Type |
|
||||||
|
| :--- | :---------------------------------------------------------------------- |
|
||||||
|
| `T` | extends `Record`<`string`, `unknown`\> = `Record`<`string`, `unknown`\> |
|
||||||
|
|
||||||
#### Type declaration
|
#### Type declaration
|
||||||
|
|
||||||
▸ (`projectConfigurationFile`, `context`): `Object`
|
▸ (`projectConfigurationFile`, `options`, `context`): `Object`
|
||||||
|
|
||||||
A function which parses a configuration file into a set of nodes.
|
A function which parses a configuration file into a set of nodes.
|
||||||
Used for creating nodes for the [ProjectGraph](../../devkit/documents/ProjectGraph)
|
Used for creating nodes for the [ProjectGraph](../../devkit/documents/ProjectGraph)
|
||||||
@ -14,6 +20,7 @@ Used for creating nodes for the [ProjectGraph](../../devkit/documents/ProjectGra
|
|||||||
| Name | Type |
|
| Name | Type |
|
||||||
| :------------------------- | :---------------------------------------------------------------- |
|
| :------------------------- | :---------------------------------------------------------------- |
|
||||||
| `projectConfigurationFile` | `string` |
|
| `projectConfigurationFile` | `string` |
|
||||||
|
| `options` | `T` \| `undefined` |
|
||||||
| `context` | [`CreateNodesContext`](../../devkit/documents/CreateNodesContext) |
|
| `context` | [`CreateNodesContext`](../../devkit/documents/CreateNodesContext) |
|
||||||
|
|
||||||
##### Returns
|
##### Returns
|
||||||
|
|||||||
@ -32,8 +32,8 @@ Nx.json configuration
|
|||||||
- [nxCloudEncryptionKey](../../devkit/documents/NxJsonConfiguration#nxcloudencryptionkey): string
|
- [nxCloudEncryptionKey](../../devkit/documents/NxJsonConfiguration#nxcloudencryptionkey): string
|
||||||
- [nxCloudUrl](../../devkit/documents/NxJsonConfiguration#nxcloudurl): string
|
- [nxCloudUrl](../../devkit/documents/NxJsonConfiguration#nxcloudurl): string
|
||||||
- [parallel](../../devkit/documents/NxJsonConfiguration#parallel): number
|
- [parallel](../../devkit/documents/NxJsonConfiguration#parallel): number
|
||||||
- [plugins](../../devkit/documents/NxJsonConfiguration#plugins): string[]
|
- [plugins](../../devkit/documents/NxJsonConfiguration#plugins): PluginDefinition[]
|
||||||
- [pluginsConfig](../../devkit/documents/NxJsonConfiguration#pluginsconfig): Record<string, unknown>
|
- [pluginsConfig](../../devkit/documents/NxJsonConfiguration#pluginsconfig): Record<string, Record<string, unknown>>
|
||||||
- [release](../../devkit/documents/NxJsonConfiguration#release): NxReleaseConfiguration
|
- [release](../../devkit/documents/NxJsonConfiguration#release): NxReleaseConfiguration
|
||||||
- [targetDefaults](../../devkit/documents/NxJsonConfiguration#targetdefaults): TargetDefaults
|
- [targetDefaults](../../devkit/documents/NxJsonConfiguration#targetdefaults): TargetDefaults
|
||||||
- [tasksRunnerOptions](../../devkit/documents/NxJsonConfiguration#tasksrunneroptions): Object
|
- [tasksRunnerOptions](../../devkit/documents/NxJsonConfiguration#tasksrunneroptions): Object
|
||||||
@ -198,7 +198,7 @@ Specifies how many tasks can be run in parallel.
|
|||||||
|
|
||||||
### plugins
|
### plugins
|
||||||
|
|
||||||
• `Optional` **plugins**: `string`[]
|
• `Optional` **plugins**: `PluginDefinition`[]
|
||||||
|
|
||||||
Plugins for extending the project graph
|
Plugins for extending the project graph
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ Plugins for extending the project graph
|
|||||||
|
|
||||||
### pluginsConfig
|
### pluginsConfig
|
||||||
|
|
||||||
• `Optional` **pluginsConfig**: `Record`<`string`, `unknown`\>
|
• `Optional` **pluginsConfig**: `Record`<`string`, `Record`<`string`, `unknown`\>\>
|
||||||
|
|
||||||
Configuration for Nx Plugins
|
Configuration for Nx Plugins
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,19 @@
|
|||||||
# Type alias: NxPluginV2
|
# Type alias: NxPluginV2<T\>
|
||||||
|
|
||||||
Ƭ **NxPluginV2**: `Object`
|
Ƭ **NxPluginV2**<`T`\>: `Object`
|
||||||
|
|
||||||
A plugin for Nx which creates nodes and dependencies for the [ProjectGraph](../../devkit/documents/ProjectGraph)
|
A plugin for Nx which creates nodes and dependencies for the [ProjectGraph](../../devkit/documents/ProjectGraph)
|
||||||
|
|
||||||
|
#### Type parameters
|
||||||
|
|
||||||
|
| Name | Type |
|
||||||
|
| :--- | :---------------------------------------------------------------------- |
|
||||||
|
| `T` | extends `Record`<`string`, `unknown`\> = `Record`<`string`, `unknown`\> |
|
||||||
|
|
||||||
#### Type declaration
|
#### Type declaration
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| :-------------------- | :---------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- |
|
| :-------------------- | :---------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `createDependencies?` | [`CreateDependencies`](../../devkit/documents/CreateDependencies) | Provides a function to analyze files to create dependencies for the [ProjectGraph](../../devkit/documents/ProjectGraph) |
|
| `createDependencies?` | [`CreateDependencies`](../../devkit/documents/CreateDependencies)<`T`\> | Provides a function to analyze files to create dependencies for the [ProjectGraph](../../devkit/documents/ProjectGraph) |
|
||||||
| `createNodes?` | [`CreateNodes`](../../devkit/documents/CreateNodes) | Provides a file pattern and function that retrieves configuration info from those files. e.g. { '\*_/_.csproj': buildProjectsFromCsProjFile } |
|
| `createNodes?` | [`CreateNodes`](../../devkit/documents/CreateNodes)<`T`\> | Provides a file pattern and function that retrieves configuration info from those files. e.g. { '\*_/_.csproj': buildProjectsFromCsProjFile } |
|
||||||
| `name` | `string` | - |
|
| `name` | `string` | - |
|
||||||
|
|||||||
@ -30,8 +30,8 @@ use ProjectsConfigurations or NxJsonConfiguration
|
|||||||
- [nxCloudEncryptionKey](../../devkit/documents/Workspace#nxcloudencryptionkey): string
|
- [nxCloudEncryptionKey](../../devkit/documents/Workspace#nxcloudencryptionkey): string
|
||||||
- [nxCloudUrl](../../devkit/documents/Workspace#nxcloudurl): string
|
- [nxCloudUrl](../../devkit/documents/Workspace#nxcloudurl): string
|
||||||
- [parallel](../../devkit/documents/Workspace#parallel): number
|
- [parallel](../../devkit/documents/Workspace#parallel): number
|
||||||
- [plugins](../../devkit/documents/Workspace#plugins): string[]
|
- [plugins](../../devkit/documents/Workspace#plugins): PluginDefinition[]
|
||||||
- [pluginsConfig](../../devkit/documents/Workspace#pluginsconfig): Record<string, unknown>
|
- [pluginsConfig](../../devkit/documents/Workspace#pluginsconfig): Record<string, Record<string, unknown>>
|
||||||
- [projects](../../devkit/documents/Workspace#projects): Record<string, ProjectConfiguration>
|
- [projects](../../devkit/documents/Workspace#projects): Record<string, ProjectConfiguration>
|
||||||
- [release](../../devkit/documents/Workspace#release): NxReleaseConfiguration
|
- [release](../../devkit/documents/Workspace#release): NxReleaseConfiguration
|
||||||
- [targetDefaults](../../devkit/documents/Workspace#targetdefaults): TargetDefaults
|
- [targetDefaults](../../devkit/documents/Workspace#targetdefaults): TargetDefaults
|
||||||
@ -254,7 +254,7 @@ Specifies how many tasks can be run in parallel.
|
|||||||
|
|
||||||
### plugins
|
### plugins
|
||||||
|
|
||||||
• `Optional` **plugins**: `string`[]
|
• `Optional` **plugins**: `PluginDefinition`[]
|
||||||
|
|
||||||
Plugins for extending the project graph
|
Plugins for extending the project graph
|
||||||
|
|
||||||
@ -266,7 +266,7 @@ Plugins for extending the project graph
|
|||||||
|
|
||||||
### pluginsConfig
|
### pluginsConfig
|
||||||
|
|
||||||
• `Optional` **pluginsConfig**: `Record`<`string`, `unknown`\>
|
• `Optional` **pluginsConfig**: `Record`<`string`, `Record`<`string`, `unknown`\>\>
|
||||||
|
|
||||||
Configuration for Nx Plugins
|
Configuration for Nx Plugins
|
||||||
|
|
||||||
|
|||||||
@ -18,3 +18,39 @@ export default async function* execute(
|
|||||||
yield* asyncGenerator();
|
yield* asyncGenerator();
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const NX_PLUGIN_V2_CONTENTS = `import { basename, dirname } from "path";
|
||||||
|
import { CreateNodes } from "@nx/devkit";
|
||||||
|
|
||||||
|
type PluginOptions = {
|
||||||
|
inferredTags: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createNodes: CreateNodes<PluginOptions> = [
|
||||||
|
"**/my-project-file",
|
||||||
|
(f, options, ctx) => {
|
||||||
|
// f = path/to/my/file/my-project-file
|
||||||
|
const root = dirname(f);
|
||||||
|
// root = path/to/my/file
|
||||||
|
const name = basename(root);
|
||||||
|
// name = file
|
||||||
|
|
||||||
|
return {
|
||||||
|
projects: {
|
||||||
|
[name]: {
|
||||||
|
root,
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: "nx:run-commands",
|
||||||
|
options: {
|
||||||
|
command: "echo 'custom registered target'",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tags: options.inferredTags
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
];
|
||||||
|
`;
|
||||||
|
|||||||
@ -16,7 +16,10 @@ import {
|
|||||||
} from '@nx/e2e/utils';
|
} from '@nx/e2e/utils';
|
||||||
import type { PackageJson } from 'nx/src/utils/package-json';
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
import { ASYNC_GENERATOR_EXECUTOR_CONTENTS } from './nx-plugin.fixtures';
|
import {
|
||||||
|
ASYNC_GENERATOR_EXECUTOR_CONTENTS,
|
||||||
|
NX_PLUGIN_V2_CONTENTS,
|
||||||
|
} from './nx-plugin.fixtures';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
describe('Nx Plugin', () => {
|
describe('Nx Plugin', () => {
|
||||||
@ -263,7 +266,7 @@ describe('Nx Plugin', () => {
|
|||||||
runCLI(`generate @nx/plugin:plugin ${plugin} --linter=eslint`);
|
runCLI(`generate @nx/plugin:plugin ${plugin} --linter=eslint`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to infer projects and targets', async () => {
|
it('should be able to infer projects and targets (v1)', async () => {
|
||||||
// Setup project inference + target inference
|
// Setup project inference + target inference
|
||||||
updateFile(
|
updateFile(
|
||||||
`libs/${plugin}/src/index.ts`,
|
`libs/${plugin}/src/index.ts`,
|
||||||
@ -303,6 +306,36 @@ describe('Nx Plugin', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be able to infer projects and targets (v2)', async () => {
|
||||||
|
// Setup project inference + target inference
|
||||||
|
updateFile(`libs/${plugin}/src/index.ts`, NX_PLUGIN_V2_CONTENTS);
|
||||||
|
|
||||||
|
// Register plugin in nx.json (required for inference)
|
||||||
|
updateFile(`nx.json`, (nxJson) => {
|
||||||
|
const nx = JSON.parse(nxJson);
|
||||||
|
nx.plugins = [
|
||||||
|
{
|
||||||
|
plugin: `@${npmScope}/${plugin}`,
|
||||||
|
options: { inferredTags: ['my-tag'] },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return JSON.stringify(nx, null, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create project that should be inferred by Nx
|
||||||
|
const inferredProject = uniq('inferred');
|
||||||
|
createFile(`libs/${inferredProject}/my-project-file`);
|
||||||
|
|
||||||
|
// Attempt to use inferred project w/ Nx
|
||||||
|
expect(runCLI(`build ${inferredProject}`)).toContain(
|
||||||
|
'custom registered target'
|
||||||
|
);
|
||||||
|
const configuration = JSON.parse(
|
||||||
|
runCLI(`show project ${inferredProject} --json`)
|
||||||
|
);
|
||||||
|
expect(configuration.tags).toEqual(['my-tag']);
|
||||||
|
});
|
||||||
|
|
||||||
it('should be able to use local generators and executors', async () => {
|
it('should be able to use local generators and executors', async () => {
|
||||||
const generator = uniq('generator');
|
const generator = uniq('generator');
|
||||||
const executor = uniq('executor');
|
const executor = uniq('executor');
|
||||||
|
|||||||
@ -70,7 +70,7 @@
|
|||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "Plugins for extending the project graph.",
|
"description": "Plugins for extending the project graph.",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string"
|
"$ref": "#/definitions/plugins"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultProject": {
|
"defaultProject": {
|
||||||
@ -377,6 +377,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "A plugin module to load with default options"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"plugin": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The plugin module to load"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "The options passed to the plugin when creating nodes and dependencies"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { existsSync } from 'fs';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { readJsonFile } from '../utils/fileutils';
|
import { readJsonFile } from '../utils/fileutils';
|
||||||
import { ProjectsConfigurations } from '../config/workspace-json-project-json';
|
import { ProjectsConfigurations } from '../config/workspace-json-project-json';
|
||||||
import { NxPluginV2 } from '../devkit-exports';
|
import { NxPluginV2 } from '../utils/nx-plugin';
|
||||||
|
|
||||||
export const NX_ANGULAR_JSON_PLUGIN_NAME = 'nx-angular-json-plugin';
|
export const NX_ANGULAR_JSON_PLUGIN_NAME = 'nx-angular-json-plugin';
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ export const NxAngularJsonPlugin: NxPluginV2 = {
|
|||||||
name: NX_ANGULAR_JSON_PLUGIN_NAME,
|
name: NX_ANGULAR_JSON_PLUGIN_NAME,
|
||||||
createNodes: [
|
createNodes: [
|
||||||
'angular.json',
|
'angular.json',
|
||||||
(f, ctx) => ({
|
(f, _, ctx) => ({
|
||||||
projects: readAngularJson(ctx.workspaceRoot),
|
projects: readAngularJson(ctx.workspaceRoot),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -367,7 +367,7 @@ function addNrwlJsPluginsConfig(repoRoot: string) {
|
|||||||
json.pluginsConfig = {
|
json.pluginsConfig = {
|
||||||
'@nx/js': {
|
'@nx/js': {
|
||||||
analyzeSourceFiles: true,
|
analyzeSourceFiles: true,
|
||||||
} as NrwlJsPluginConfig,
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -176,12 +176,12 @@ export interface NxJsonConfiguration<T = '*' | string[]> {
|
|||||||
/**
|
/**
|
||||||
* Plugins for extending the project graph
|
* Plugins for extending the project graph
|
||||||
*/
|
*/
|
||||||
plugins?: string[];
|
plugins?: PluginDefinition[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration for Nx Plugins
|
* Configuration for Nx Plugins
|
||||||
*/
|
*/
|
||||||
pluginsConfig?: Record<string, unknown>;
|
pluginsConfig?: Record<string, Record<string, unknown>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default project. When project isn't provided, the default project
|
* Default project. When project isn't provided, the default project
|
||||||
@ -234,6 +234,10 @@ export interface NxJsonConfiguration<T = '*' | string[]> {
|
|||||||
useDaemonProcess?: boolean;
|
useDaemonProcess?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type PluginDefinition =
|
||||||
|
| string
|
||||||
|
| { plugin: string; options?: Record<string, unknown> };
|
||||||
|
|
||||||
export function readNxJson(root: string = workspaceRoot): NxJsonConfiguration {
|
export function readNxJson(root: string = workspaceRoot): NxJsonConfiguration {
|
||||||
const nxJson = join(root, 'nx.json');
|
const nxJson = join(root, 'nx.json');
|
||||||
if (existsSync(nxJson)) {
|
if (existsSync(nxJson)) {
|
||||||
|
|||||||
@ -213,7 +213,7 @@ function readAndCombineAllProjectConfigurations(tree: Tree): {
|
|||||||
if (basename(projectFile) === 'project.json') {
|
if (basename(projectFile) === 'project.json') {
|
||||||
const json = readJson(tree, projectFile);
|
const json = readJson(tree, projectFile);
|
||||||
const config = buildProjectFromProjectJson(json, projectFile);
|
const config = buildProjectFromProjectJson(json, projectFile);
|
||||||
mergeProjectConfigurationIntoRootMap(rootMap, config, projectFile);
|
mergeProjectConfigurationIntoRootMap(rootMap, config);
|
||||||
} else {
|
} else {
|
||||||
const packageJson = readJson<PackageJson>(tree, projectFile);
|
const packageJson = readJson<PackageJson>(tree, projectFile);
|
||||||
const config = buildProjectConfigurationFromPackageJson(
|
const config = buildProjectConfigurationFromPackageJson(
|
||||||
@ -228,8 +228,7 @@ function readAndCombineAllProjectConfigurations(tree: Tree): {
|
|||||||
{
|
{
|
||||||
name: config.name,
|
name: config.name,
|
||||||
root: config.root,
|
root: config.root,
|
||||||
},
|
}
|
||||||
projectFile
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ let parsedLockFile: ParsedLockFile = {};
|
|||||||
export const createNodes: CreateNodes = [
|
export const createNodes: CreateNodes = [
|
||||||
// Look for all lockfiles
|
// Look for all lockfiles
|
||||||
combineGlobPatterns(LOCKFILES),
|
combineGlobPatterns(LOCKFILES),
|
||||||
(lockFile, context) => {
|
(lockFile, _, context) => {
|
||||||
const pluginConfig = jsPluginConfig(context.nxJsonConfiguration);
|
const pluginConfig = jsPluginConfig(context.nxJsonConfiguration);
|
||||||
if (!pluginConfig.analyzeLockfile) {
|
if (!pluginConfig.analyzeLockfile) {
|
||||||
return {};
|
return {};
|
||||||
@ -74,6 +74,7 @@ export const createNodes: CreateNodes = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const createDependencies: CreateDependencies = (
|
export const createDependencies: CreateDependencies = (
|
||||||
|
_,
|
||||||
ctx: CreateDependenciesContext
|
ctx: CreateDependenciesContext
|
||||||
) => {
|
) => {
|
||||||
const pluginConfig = jsPluginConfig(ctx.nxJsonConfiguration);
|
const pluginConfig = jsPluginConfig(ctx.nxJsonConfiguration);
|
||||||
|
|||||||
@ -55,7 +55,8 @@ describe('nx project.json plugin', () => {
|
|||||||
'/root'
|
'/root'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(createNodes[1]('project.json', context)).toMatchInlineSnapshot(`
|
expect(createNodes[1]('project.json', undefined, context))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"projects": {
|
"projects": {
|
||||||
"root": {
|
"root": {
|
||||||
@ -68,7 +69,7 @@ describe('nx project.json plugin', () => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
expect(createNodes[1]('packages/lib-a/project.json', context))
|
expect(createNodes[1]('packages/lib-a/project.json', undefined, context))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"projects": {
|
"projects": {
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export const CreateProjectJsonProjectsPlugin: NxPluginV2 = {
|
|||||||
name: 'nx-core-build-project-json-nodes',
|
name: 'nx-core-build-project-json-nodes',
|
||||||
createNodes: [
|
createNodes: [
|
||||||
'{project.json,**/project.json}',
|
'{project.json,**/project.json}',
|
||||||
(file, context) => {
|
(file, _, context) => {
|
||||||
const root = context.workspaceRoot;
|
const root = context.workspaceRoot;
|
||||||
const json = readJsonFile<ProjectConfiguration>(join(root, file));
|
const json = readJsonFile<ProjectConfiguration>(join(root, file));
|
||||||
const project = buildProjectFromProjectJson(json, file);
|
const project = buildProjectFromProjectJson(json, file);
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import { applyImplicitDependencies } from './utils/implicit-project-dependencies
|
|||||||
import { normalizeProjectNodes } from './utils/normalize-project-nodes';
|
import { normalizeProjectNodes } from './utils/normalize-project-nodes';
|
||||||
import {
|
import {
|
||||||
CreateDependenciesContext,
|
CreateDependenciesContext,
|
||||||
CreateNodesContext,
|
|
||||||
isNxPluginV1,
|
isNxPluginV1,
|
||||||
isNxPluginV2,
|
isNxPluginV2,
|
||||||
loadNxPlugins,
|
loadNxPlugins,
|
||||||
@ -234,7 +233,7 @@ async function updateProjectGraphWithPlugins(
|
|||||||
) {
|
) {
|
||||||
const plugins = await loadNxPlugins(context.nxJsonConfiguration?.plugins);
|
const plugins = await loadNxPlugins(context.nxJsonConfiguration?.plugins);
|
||||||
let graph = initProjectGraph;
|
let graph = initProjectGraph;
|
||||||
for (const plugin of plugins) {
|
for (const { plugin } of plugins) {
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
isNxPluginV1(plugin) &&
|
isNxPluginV1(plugin) &&
|
||||||
@ -280,12 +279,12 @@ async function updateProjectGraphWithPlugins(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const createDependencyPlugins = plugins.filter(
|
const createDependencyPlugins = plugins.filter(
|
||||||
(plugin) => isNxPluginV2(plugin) && plugin.createDependencies
|
({ plugin }) => isNxPluginV2(plugin) && plugin.createDependencies
|
||||||
);
|
);
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
createDependencyPlugins.map(async (plugin) => {
|
createDependencyPlugins.map(async ({ plugin, options }) => {
|
||||||
try {
|
try {
|
||||||
const dependencies = await plugin.createDependencies({
|
const dependencies = await plugin.createDependencies(options, {
|
||||||
...context,
|
...context,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -111,7 +111,7 @@ describe('nx deps utils', () => {
|
|||||||
createCache({}),
|
createCache({}),
|
||||||
createPackageJsonDeps({ plugin: '2.0.0' }),
|
createPackageJsonDeps({ plugin: '2.0.0' }),
|
||||||
createProjectsConfiguration({}),
|
createProjectsConfiguration({}),
|
||||||
createNxJson({ pluginsConfig: { one: 1 } }),
|
createNxJson({ pluginsConfig: { somePlugin: { one: 1 } } }),
|
||||||
createTsConfigJson()
|
createTsConfigJson()
|
||||||
)
|
)
|
||||||
).toEqual(true);
|
).toEqual(true);
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { existsSync } from 'fs';
|
|||||||
import { ensureDirSync, renameSync } from 'fs-extra';
|
import { ensureDirSync, renameSync } from 'fs-extra';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
import { NxJsonConfiguration } from '../config/nx-json';
|
import { NxJsonConfiguration, PluginDefinition } from '../config/nx-json';
|
||||||
import {
|
import {
|
||||||
FileData,
|
FileData,
|
||||||
FileMap,
|
FileMap,
|
||||||
@ -17,6 +17,7 @@ import {
|
|||||||
readJsonFile,
|
readJsonFile,
|
||||||
writeJsonFile,
|
writeJsonFile,
|
||||||
} from '../utils/fileutils';
|
} from '../utils/fileutils';
|
||||||
|
import { PackageJson } from '../utils/package-json';
|
||||||
import { nxVersion } from '../utils/versions';
|
import { nxVersion } from '../utils/versions';
|
||||||
|
|
||||||
export interface FileMapCache {
|
export interface FileMapCache {
|
||||||
@ -24,7 +25,7 @@ export interface FileMapCache {
|
|||||||
nxVersion: string;
|
nxVersion: string;
|
||||||
deps: Record<string, string>;
|
deps: Record<string, string>;
|
||||||
pathMappings: Record<string, any>;
|
pathMappings: Record<string, any>;
|
||||||
nxJsonPlugins: { name: string; version: string }[];
|
nxJsonPlugins: PluginData[];
|
||||||
pluginsConfig?: any;
|
pluginsConfig?: any;
|
||||||
fileMap: FileMap;
|
fileMap: FileMap;
|
||||||
}
|
}
|
||||||
@ -111,10 +112,7 @@ export function createProjectFileMapCache(
|
|||||||
fileMap: FileMap,
|
fileMap: FileMap,
|
||||||
tsConfig: { compilerOptions?: { paths?: { [p: string]: any } } }
|
tsConfig: { compilerOptions?: { paths?: { [p: string]: any } } }
|
||||||
) {
|
) {
|
||||||
const nxJsonPlugins = (nxJson?.plugins || []).map((p) => ({
|
const nxJsonPlugins = getNxJsonPluginsData(nxJson, packageJsonDeps);
|
||||||
name: p,
|
|
||||||
version: packageJsonDeps[p],
|
|
||||||
}));
|
|
||||||
const newValue: FileMapCache = {
|
const newValue: FileMapCache = {
|
||||||
version: '6.0',
|
version: '6.0',
|
||||||
nxVersion: nxVersion,
|
nxVersion: nxVersion,
|
||||||
@ -207,16 +205,9 @@ export function shouldRecomputeWholeGraph(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// a new plugin has been added
|
// a new plugin has been added
|
||||||
if ((nxJson?.plugins || []).length !== cache.nxJsonPlugins.length)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// a plugin has changed
|
|
||||||
if (
|
if (
|
||||||
(nxJson?.plugins || []).some((t) => {
|
JSON.stringify(getNxJsonPluginsData(nxJson, packageJsonDeps)) !==
|
||||||
const matchingPlugin = cache.nxJsonPlugins.find((p) => p.name === t);
|
JSON.stringify(cache.nxJsonPlugins)
|
||||||
if (!matchingPlugin) return true;
|
|
||||||
return matchingPlugin.version !== packageJsonDeps[t];
|
|
||||||
})
|
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -333,3 +324,24 @@ function processProjectNode(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PluginData = {
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
options?: Record<string, unknown>;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getNxJsonPluginsData(
|
||||||
|
nxJson: NxJsonConfiguration,
|
||||||
|
packageJsonDeps: Record<string, string>
|
||||||
|
): PluginData[] {
|
||||||
|
return (nxJson?.plugins || []).map((p) => {
|
||||||
|
const [plugin, options] =
|
||||||
|
typeof p === 'string' ? [p] : [p.plugin, p.options];
|
||||||
|
return {
|
||||||
|
name: plugin,
|
||||||
|
version: packageJsonDeps[plugin],
|
||||||
|
options,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -371,19 +371,15 @@ describe('mergeProjectConfigurationIntoRootMap', () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.getRootMap();
|
.getRootMap();
|
||||||
mergeProjectConfigurationIntoRootMap(
|
mergeProjectConfigurationIntoRootMap(rootMap, {
|
||||||
rootMap,
|
root: 'libs/lib-a',
|
||||||
{
|
name: 'lib-a',
|
||||||
root: 'libs/lib-a',
|
targets: {
|
||||||
name: 'lib-a',
|
build: {
|
||||||
targets: {
|
command: 'tsc',
|
||||||
build: {
|
|
||||||
command: 'tsc',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'inferred-project-config-file.ts'
|
});
|
||||||
);
|
|
||||||
expect(rootMap.get('libs/lib-a')).toMatchInlineSnapshot(`
|
expect(rootMap.get('libs/lib-a')).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"name": "lib-a",
|
"name": "lib-a",
|
||||||
@ -399,33 +395,6 @@ describe('mergeProjectConfigurationIntoRootMap', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shouldn't overwrite project name, unless merging project from project.json", () => {
|
|
||||||
const rootMap = new RootMapBuilder()
|
|
||||||
.addProject({
|
|
||||||
name: 'bad-name',
|
|
||||||
root: 'libs/lib-a',
|
|
||||||
})
|
|
||||||
.getRootMap();
|
|
||||||
mergeProjectConfigurationIntoRootMap(
|
|
||||||
rootMap,
|
|
||||||
{
|
|
||||||
name: 'other-bad-name',
|
|
||||||
root: 'libs/lib-a',
|
|
||||||
},
|
|
||||||
'libs/lib-a/package.json'
|
|
||||||
);
|
|
||||||
expect(rootMap.get('libs/lib-a').name).toEqual('bad-name');
|
|
||||||
mergeProjectConfigurationIntoRootMap(
|
|
||||||
rootMap,
|
|
||||||
{
|
|
||||||
name: 'lib-a',
|
|
||||||
root: 'libs/lib-a',
|
|
||||||
},
|
|
||||||
'libs/lib-a/project.json'
|
|
||||||
);
|
|
||||||
expect(rootMap.get('libs/lib-a').name).toEqual('lib-a');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('readProjectsConfigurationsFromRootMap', () => {
|
describe('readProjectsConfigurationsFromRootMap', () => {
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import { basename } from 'node:path';
|
|
||||||
|
|
||||||
import { NxJsonConfiguration, TargetDefaults } from '../../config/nx-json';
|
import { NxJsonConfiguration, TargetDefaults } from '../../config/nx-json';
|
||||||
import { ProjectGraphExternalNode } from '../../config/project-graph';
|
import { ProjectGraphExternalNode } from '../../config/project-graph';
|
||||||
import {
|
import {
|
||||||
@ -7,30 +5,20 @@ import {
|
|||||||
TargetConfiguration,
|
TargetConfiguration,
|
||||||
} from '../../config/workspace-json-project-json';
|
} from '../../config/workspace-json-project-json';
|
||||||
import { NX_PREFIX } from '../../utils/logger';
|
import { NX_PREFIX } from '../../utils/logger';
|
||||||
import { NxPluginV2 } from '../../utils/nx-plugin';
|
import { LoadedNxPlugin } from '../../utils/nx-plugin';
|
||||||
import { workspaceRoot } from '../../utils/workspace-root';
|
import { workspaceRoot } from '../../utils/workspace-root';
|
||||||
|
|
||||||
import minimatch = require('minimatch');
|
import minimatch = require('minimatch');
|
||||||
|
|
||||||
export function mergeProjectConfigurationIntoRootMap(
|
export function mergeProjectConfigurationIntoRootMap(
|
||||||
projectRootMap: Map<string, ProjectConfiguration>,
|
projectRootMap: Map<string, ProjectConfiguration>,
|
||||||
project: ProjectConfiguration,
|
project: ProjectConfiguration
|
||||||
// project.json is a special case, so we need to detect it.
|
|
||||||
file: string
|
|
||||||
): void {
|
): void {
|
||||||
const matchingProject = projectRootMap.get(project.root);
|
const matchingProject = projectRootMap.get(project.root);
|
||||||
|
|
||||||
if (!matchingProject) {
|
if (!matchingProject) {
|
||||||
projectRootMap.set(project.root, project);
|
projectRootMap.set(project.root, project);
|
||||||
return;
|
return;
|
||||||
} else if (
|
|
||||||
project.name &&
|
|
||||||
project.name !== matchingProject.name &&
|
|
||||||
basename(file) === 'project.json'
|
|
||||||
) {
|
|
||||||
// `name` inside project.json overrides any names from
|
|
||||||
// inference plugins
|
|
||||||
matchingProject.name = project.name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This handles top level properties that are overwritten.
|
// This handles top level properties that are overwritten.
|
||||||
@ -41,7 +29,6 @@ export function mergeProjectConfigurationIntoRootMap(
|
|||||||
const updatedProjectConfiguration = {
|
const updatedProjectConfiguration = {
|
||||||
...matchingProject,
|
...matchingProject,
|
||||||
...project,
|
...project,
|
||||||
name: matchingProject.name,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The next blocks handle properties that should be themselves merged (e.g. targets, tags, and implicit dependencies)
|
// The next blocks handle properties that should be themselves merged (e.g. targets, tags, and implicit dependencies)
|
||||||
@ -79,7 +66,7 @@ export function mergeProjectConfigurationIntoRootMap(
|
|||||||
export function buildProjectsConfigurationsFromProjectPathsAndPlugins(
|
export function buildProjectsConfigurationsFromProjectPathsAndPlugins(
|
||||||
nxJson: NxJsonConfiguration,
|
nxJson: NxJsonConfiguration,
|
||||||
projectFiles: string[], // making this parameter allows devkit to pick up newly created projects
|
projectFiles: string[], // making this parameter allows devkit to pick up newly created projects
|
||||||
plugins: NxPluginV2[],
|
plugins: LoadedNxPlugin[],
|
||||||
root: string = workspaceRoot
|
root: string = workspaceRoot
|
||||||
): {
|
): {
|
||||||
projects: Record<string, ProjectConfiguration>;
|
projects: Record<string, ProjectConfiguration>;
|
||||||
@ -89,7 +76,7 @@ export function buildProjectsConfigurationsFromProjectPathsAndPlugins(
|
|||||||
const externalNodes: Record<string, ProjectGraphExternalNode> = {};
|
const externalNodes: Record<string, ProjectGraphExternalNode> = {};
|
||||||
|
|
||||||
// We iterate over plugins first - this ensures that plugins specified first take precedence.
|
// We iterate over plugins first - this ensures that plugins specified first take precedence.
|
||||||
for (const plugin of plugins) {
|
for (const { plugin, options } of plugins) {
|
||||||
const [pattern, createNodes] = plugin.createNodes ?? [];
|
const [pattern, createNodes] = plugin.createNodes ?? [];
|
||||||
if (!pattern) {
|
if (!pattern) {
|
||||||
continue;
|
continue;
|
||||||
@ -97,7 +84,7 @@ export function buildProjectsConfigurationsFromProjectPathsAndPlugins(
|
|||||||
for (const file of projectFiles) {
|
for (const file of projectFiles) {
|
||||||
if (minimatch(file, pattern, { dot: true })) {
|
if (minimatch(file, pattern, { dot: true })) {
|
||||||
const { projects: projectNodes, externalNodes: pluginExternalNodes } =
|
const { projects: projectNodes, externalNodes: pluginExternalNodes } =
|
||||||
createNodes(file, {
|
createNodes(file, options, {
|
||||||
nxJsonConfiguration: nxJson,
|
nxJsonConfiguration: nxJson,
|
||||||
workspaceRoot: root,
|
workspaceRoot: root,
|
||||||
});
|
});
|
||||||
@ -105,8 +92,7 @@ export function buildProjectsConfigurationsFromProjectPathsAndPlugins(
|
|||||||
projectNodes[node].name ??= node;
|
projectNodes[node].name ??= node;
|
||||||
mergeProjectConfigurationIntoRootMap(
|
mergeProjectConfigurationIntoRootMap(
|
||||||
projectRootMap,
|
projectRootMap,
|
||||||
projectNodes[node],
|
projectNodes[node]
|
||||||
file
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Object.assign(externalNodes, pluginExternalNodes);
|
Object.assign(externalNodes, pluginExternalNodes);
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import {
|
|||||||
} from '../../../plugins/package-json-workspaces';
|
} from '../../../plugins/package-json-workspaces';
|
||||||
import { buildProjectsConfigurationsFromProjectPathsAndPlugins } from './project-configuration-utils';
|
import { buildProjectsConfigurationsFromProjectPathsAndPlugins } from './project-configuration-utils';
|
||||||
import {
|
import {
|
||||||
|
LoadedNxPlugin,
|
||||||
loadNxPlugins,
|
loadNxPlugins,
|
||||||
loadNxPluginsSync,
|
loadNxPluginsSync,
|
||||||
NxPluginV2,
|
NxPluginV2,
|
||||||
@ -137,9 +138,9 @@ export async function retrieveProjectConfigurationsWithAngularProjects(
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
shouldMergeAngularProjects(workspaceRoot, true) &&
|
shouldMergeAngularProjects(workspaceRoot, true) &&
|
||||||
!plugins.some((p) => p.name === NX_ANGULAR_JSON_PLUGIN_NAME)
|
!plugins.some((p) => p.plugin.name === NX_ANGULAR_JSON_PLUGIN_NAME)
|
||||||
) {
|
) {
|
||||||
plugins.push(NxAngularJsonPlugin);
|
plugins.push({ plugin: NxAngularJsonPlugin });
|
||||||
}
|
}
|
||||||
|
|
||||||
const globs = configurationGlobs(workspaceRoot, plugins);
|
const globs = configurationGlobs(workspaceRoot, plugins);
|
||||||
@ -169,7 +170,7 @@ export function retrieveProjectConfigurationsSync(
|
|||||||
function _retrieveProjectConfigurations(
|
function _retrieveProjectConfigurations(
|
||||||
workspaceRoot: string,
|
workspaceRoot: string,
|
||||||
nxJson: NxJsonConfiguration,
|
nxJson: NxJsonConfiguration,
|
||||||
plugins: NxPluginV2[],
|
plugins: LoadedNxPlugin[],
|
||||||
globs: string[]
|
globs: string[]
|
||||||
): {
|
): {
|
||||||
externalNodes: Record<string, ProjectGraphExternalNode>;
|
externalNodes: Record<string, ProjectGraphExternalNode>;
|
||||||
@ -236,8 +237,8 @@ export function retrieveProjectConfigurationsWithoutPluginInference(
|
|||||||
projectGlobPatterns,
|
projectGlobPatterns,
|
||||||
(configs: string[]) => {
|
(configs: string[]) => {
|
||||||
const { projects } = createProjectConfigurations(root, nxJson, configs, [
|
const { projects } = createProjectConfigurations(root, nxJson, configs, [
|
||||||
getNxPackageJsonWorkspacesPlugin(root),
|
{ plugin: getNxPackageJsonWorkspacesPlugin(root) },
|
||||||
CreateProjectJsonProjectsPlugin,
|
{ plugin: CreateProjectJsonProjectsPlugin },
|
||||||
]);
|
]);
|
||||||
return {
|
return {
|
||||||
projectNodes: projects,
|
projectNodes: projects,
|
||||||
@ -273,7 +274,7 @@ export function createProjectConfigurations(
|
|||||||
workspaceRoot: string,
|
workspaceRoot: string,
|
||||||
nxJson: NxJsonConfiguration,
|
nxJson: NxJsonConfiguration,
|
||||||
configFiles: string[],
|
configFiles: string[],
|
||||||
plugins: NxPluginV2[]
|
plugins: LoadedNxPlugin[]
|
||||||
): {
|
): {
|
||||||
projects: Record<string, ProjectConfiguration>;
|
projects: Record<string, ProjectConfiguration>;
|
||||||
externalNodes: Record<string, ProjectGraphExternalNode>;
|
externalNodes: Record<string, ProjectGraphExternalNode>;
|
||||||
@ -305,11 +306,11 @@ export function createProjectConfigurations(
|
|||||||
|
|
||||||
export function configurationGlobs(
|
export function configurationGlobs(
|
||||||
workspaceRoot: string,
|
workspaceRoot: string,
|
||||||
plugins: NxPluginV2[]
|
plugins: LoadedNxPlugin[]
|
||||||
): string[] {
|
): string[] {
|
||||||
const globPatterns: string[] =
|
const globPatterns: string[] =
|
||||||
configurationGlobsWithoutPlugins(workspaceRoot);
|
configurationGlobsWithoutPlugins(workspaceRoot);
|
||||||
for (const plugin of plugins) {
|
for (const { plugin } of plugins) {
|
||||||
if (plugin.createNodes) {
|
if (plugin.createNodes) {
|
||||||
globPatterns.push(plugin.createNodes[0]);
|
globPatterns.push(plugin.createNodes[0]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
import { existsSync } from 'fs';
|
import { existsSync } from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import {
|
import {
|
||||||
FileData,
|
|
||||||
FileMap,
|
FileMap,
|
||||||
ProjectFileMap,
|
|
||||||
ProjectGraph,
|
ProjectGraph,
|
||||||
ProjectGraphExternalNode,
|
ProjectGraphExternalNode,
|
||||||
} from '../config/project-graph';
|
} from '../config/project-graph';
|
||||||
@ -19,10 +17,7 @@ import {
|
|||||||
registerTranspiler,
|
registerTranspiler,
|
||||||
registerTsConfigPaths,
|
registerTsConfigPaths,
|
||||||
} from '../plugins/js/utils/register';
|
} from '../plugins/js/utils/register';
|
||||||
import {
|
import { ProjectConfiguration } from '../config/workspace-json-project-json';
|
||||||
ProjectConfiguration,
|
|
||||||
ProjectsConfigurations,
|
|
||||||
} from '../config/workspace-json-project-json';
|
|
||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
import {
|
import {
|
||||||
createProjectRootMappingsFromProjectConfigurations,
|
createProjectRootMappingsFromProjectConfigurations,
|
||||||
@ -32,7 +27,7 @@ import { normalizePath } from './path';
|
|||||||
import { dirname, join } from 'path';
|
import { dirname, join } from 'path';
|
||||||
import { getNxRequirePaths } from './installation-directory';
|
import { getNxRequirePaths } from './installation-directory';
|
||||||
import { readTsConfig } from '../plugins/js/utils/typescript';
|
import { readTsConfig } from '../plugins/js/utils/typescript';
|
||||||
import { NxJsonConfiguration } from '../config/nx-json';
|
import { NxJsonConfiguration, PluginDefinition } from '../config/nx-json';
|
||||||
|
|
||||||
import type * as ts from 'typescript';
|
import type * as ts from 'typescript';
|
||||||
import { retrieveProjectConfigurationsWithoutPluginInference } from '../project-graph/utils/retrieve-workspace-files';
|
import { retrieveProjectConfigurationsWithoutPluginInference } from '../project-graph/utils/retrieve-workspace-files';
|
||||||
@ -45,6 +40,7 @@ import {
|
|||||||
} from '../adapter/angular-json';
|
} from '../adapter/angular-json';
|
||||||
import { getNxPackageJsonWorkspacesPlugin } from '../../plugins/package-json-workspaces';
|
import { getNxPackageJsonWorkspacesPlugin } from '../../plugins/package-json-workspaces';
|
||||||
import { CreateProjectJsonProjectsPlugin } from '../plugins/project-json/build-nodes/project-json';
|
import { CreateProjectJsonProjectsPlugin } from '../plugins/project-json/build-nodes/project-json';
|
||||||
|
import { FileMapCache } from '../project-graph/nx-deps-cache';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context for {@link CreateNodesFunction}
|
* Context for {@link CreateNodesFunction}
|
||||||
@ -58,8 +54,11 @@ export interface CreateNodesContext {
|
|||||||
* A function which parses a configuration file into a set of nodes.
|
* A function which parses a configuration file into a set of nodes.
|
||||||
* Used for creating nodes for the {@link ProjectGraph}
|
* Used for creating nodes for the {@link ProjectGraph}
|
||||||
*/
|
*/
|
||||||
export type CreateNodesFunction = (
|
export type CreateNodesFunction<
|
||||||
|
T extends Record<string, unknown> = Record<string, unknown>
|
||||||
|
> = (
|
||||||
projectConfigurationFile: string,
|
projectConfigurationFile: string,
|
||||||
|
options: T | undefined,
|
||||||
context: CreateNodesContext
|
context: CreateNodesContext
|
||||||
) => {
|
) => {
|
||||||
projects?: Record<string, ProjectConfiguration>;
|
projects?: Record<string, ProjectConfiguration>;
|
||||||
@ -69,9 +68,11 @@ export type CreateNodesFunction = (
|
|||||||
/**
|
/**
|
||||||
* A pair of file patterns and {@link CreateNodesFunction}
|
* A pair of file patterns and {@link CreateNodesFunction}
|
||||||
*/
|
*/
|
||||||
export type CreateNodes = readonly [
|
export type CreateNodes<
|
||||||
|
T extends Record<string, unknown> = Record<string, unknown>
|
||||||
|
> = readonly [
|
||||||
projectFilePattern: string,
|
projectFilePattern: string,
|
||||||
createNodesFunction: CreateNodesFunction
|
createNodesFunction: CreateNodesFunction<T>
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,27 +111,32 @@ export interface CreateDependenciesContext {
|
|||||||
* A function which parses files in the workspace to create dependencies in the {@link ProjectGraph}
|
* A function which parses files in the workspace to create dependencies in the {@link ProjectGraph}
|
||||||
* Use {@link validateDependency} to validate dependencies
|
* Use {@link validateDependency} to validate dependencies
|
||||||
*/
|
*/
|
||||||
export type CreateDependencies = (
|
export type CreateDependencies<
|
||||||
|
T extends Record<string, unknown> = Record<string, unknown>
|
||||||
|
> = (
|
||||||
|
options: T | undefined,
|
||||||
context: CreateDependenciesContext
|
context: CreateDependenciesContext
|
||||||
) => RawProjectGraphDependency[] | Promise<RawProjectGraphDependency[]>;
|
) => RawProjectGraphDependency[] | Promise<RawProjectGraphDependency[]>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A plugin for Nx which creates nodes and dependencies for the {@link ProjectGraph}
|
* A plugin for Nx which creates nodes and dependencies for the {@link ProjectGraph}
|
||||||
*/
|
*/
|
||||||
export type NxPluginV2 = {
|
export type NxPluginV2<
|
||||||
|
T extends Record<string, unknown> = Record<string, unknown>
|
||||||
|
> = {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a file pattern and function that retrieves configuration info from
|
* Provides a file pattern and function that retrieves configuration info from
|
||||||
* those files. e.g. { '**\/*.csproj': buildProjectsFromCsProjFile }
|
* those files. e.g. { '**\/*.csproj': buildProjectsFromCsProjFile }
|
||||||
*/
|
*/
|
||||||
createNodes?: CreateNodes;
|
createNodes?: CreateNodes<T>;
|
||||||
|
|
||||||
// Todo(@AgentEnder): This shouldn't be a full processor, since its only responsible for defining edges between projects. What do we want the API to be?
|
// Todo(@AgentEnder): This shouldn't be a full processor, since its only responsible for defining edges between projects. What do we want the API to be?
|
||||||
/**
|
/**
|
||||||
* Provides a function to analyze files to create dependencies for the {@link ProjectGraph}
|
* Provides a function to analyze files to create dependencies for the {@link ProjectGraph}
|
||||||
*/
|
*/
|
||||||
createDependencies?: CreateDependencies;
|
createDependencies?: CreateDependencies<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export * from './nx-plugin.deprecated';
|
export * from './nx-plugin.deprecated';
|
||||||
@ -140,11 +146,16 @@ export * from './nx-plugin.deprecated';
|
|||||||
*/
|
*/
|
||||||
export type NxPlugin = NxPluginV1 | NxPluginV2;
|
export type NxPlugin = NxPluginV1 | NxPluginV2;
|
||||||
|
|
||||||
|
export type LoadedNxPlugin = {
|
||||||
|
plugin: NxPluginV2 & Pick<NxPluginV1, 'processProjectGraph'>;
|
||||||
|
options?: Record<string, unknown>;
|
||||||
|
};
|
||||||
|
|
||||||
// Short lived cache (cleared between cmd runs)
|
// Short lived cache (cleared between cmd runs)
|
||||||
// holding resolved nx plugin objects.
|
// holding resolved nx plugin objects.
|
||||||
// Allows loadNxPlugins to be called multiple times w/o
|
// Allows loadNxPlugins to be called multiple times w/o
|
||||||
// executing resolution mulitple times.
|
// executing resolution mulitple times.
|
||||||
let nxPluginCache: Map<string, NxPlugin> = new Map();
|
let nxPluginCache: Map<string, LoadedNxPlugin['plugin']> = new Map();
|
||||||
|
|
||||||
function getPluginPathAndName(
|
function getPluginPathAndName(
|
||||||
moduleName: string,
|
moduleName: string,
|
||||||
@ -191,50 +202,66 @@ function getPluginPathAndName(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function loadNxPluginAsync(
|
export async function loadNxPluginAsync(
|
||||||
moduleName: string,
|
pluginDefinition: PluginDefinition,
|
||||||
paths: string[],
|
paths: string[],
|
||||||
root: string
|
root: string
|
||||||
) {
|
): Promise<LoadedNxPlugin> {
|
||||||
|
const { plugin: moduleName, options } =
|
||||||
|
typeof pluginDefinition === 'object'
|
||||||
|
? pluginDefinition
|
||||||
|
: { plugin: pluginDefinition, options: undefined };
|
||||||
let pluginModule = nxPluginCache.get(moduleName);
|
let pluginModule = nxPluginCache.get(moduleName);
|
||||||
if (pluginModule) {
|
if (pluginModule) {
|
||||||
return pluginModule;
|
return { plugin: pluginModule, options };
|
||||||
}
|
}
|
||||||
|
|
||||||
let { pluginPath, name } = getPluginPathAndName(moduleName, paths, root);
|
let { pluginPath, name } = getPluginPathAndName(moduleName, paths, root);
|
||||||
const plugin = (await import(pluginPath)) as NxPlugin;
|
const plugin = ensurePluginIsV2(
|
||||||
|
(await import(pluginPath)) as LoadedNxPlugin['plugin']
|
||||||
|
);
|
||||||
plugin.name ??= name;
|
plugin.name ??= name;
|
||||||
nxPluginCache.set(moduleName, plugin);
|
nxPluginCache.set(moduleName, plugin);
|
||||||
return plugin;
|
return { plugin, options };
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadNxPluginSync(moduleName: string, paths: string[], root: string) {
|
function loadNxPluginSync(
|
||||||
|
pluginDefinition: PluginDefinition,
|
||||||
|
paths: string[],
|
||||||
|
root: string
|
||||||
|
): LoadedNxPlugin {
|
||||||
|
const { plugin: moduleName, options } =
|
||||||
|
typeof pluginDefinition === 'object'
|
||||||
|
? pluginDefinition
|
||||||
|
: { plugin: pluginDefinition, options: undefined };
|
||||||
let pluginModule = nxPluginCache.get(moduleName);
|
let pluginModule = nxPluginCache.get(moduleName);
|
||||||
if (pluginModule) {
|
if (pluginModule) {
|
||||||
return pluginModule;
|
return { plugin: pluginModule, options };
|
||||||
}
|
}
|
||||||
|
|
||||||
let { pluginPath, name } = getPluginPathAndName(moduleName, paths, root);
|
let { pluginPath, name } = getPluginPathAndName(moduleName, paths, root);
|
||||||
const plugin = require(pluginPath) as NxPlugin;
|
const plugin = ensurePluginIsV2(
|
||||||
|
require(pluginPath)
|
||||||
|
) as LoadedNxPlugin['plugin'];
|
||||||
plugin.name ??= name;
|
plugin.name ??= name;
|
||||||
nxPluginCache.set(moduleName, plugin);
|
nxPluginCache.set(moduleName, plugin);
|
||||||
return plugin;
|
return { plugin, options };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use loadNxPlugins instead.
|
* @deprecated Use loadNxPlugins instead.
|
||||||
*/
|
*/
|
||||||
export function loadNxPluginsSync(
|
export function loadNxPluginsSync(
|
||||||
plugins: string[],
|
plugins: NxJsonConfiguration['plugins'],
|
||||||
paths = getNxRequirePaths(),
|
paths = getNxRequirePaths(),
|
||||||
root = workspaceRoot
|
root = workspaceRoot
|
||||||
): (NxPluginV2 & Pick<NxPluginV1, 'processProjectGraph'>)[] {
|
): LoadedNxPlugin[] {
|
||||||
// TODO: This should be specified in nx.json
|
// TODO: This should be specified in nx.json
|
||||||
// Temporarily load js as if it were a plugin which is built into nx
|
// Temporarily load js as if it were a plugin which is built into nx
|
||||||
// In the future, this will be optional and need to be specified in nx.json
|
// In the future, this will be optional and need to be specified in nx.json
|
||||||
const result: NxPlugin[] = [...getDefaultPluginsSync(root)];
|
const result: LoadedNxPlugin[] = [...getDefaultPluginsSync(root)];
|
||||||
|
|
||||||
if (shouldMergeAngularProjects(root, false)) {
|
if (shouldMergeAngularProjects(root, false)) {
|
||||||
result.push(NxAngularJsonPlugin);
|
result.push({ plugin: NxAngularJsonPlugin, options: undefined });
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins ??= [];
|
plugins ??= [];
|
||||||
@ -253,19 +280,19 @@ export function loadNxPluginsSync(
|
|||||||
|
|
||||||
// We push the nx core node plugins onto the end, s.t. it overwrites any other plugins
|
// We push the nx core node plugins onto the end, s.t. it overwrites any other plugins
|
||||||
result.push(
|
result.push(
|
||||||
getNxPackageJsonWorkspacesPlugin(root),
|
{ plugin: getNxPackageJsonWorkspacesPlugin(root) },
|
||||||
CreateProjectJsonProjectsPlugin
|
{ plugin: CreateProjectJsonProjectsPlugin }
|
||||||
);
|
);
|
||||||
|
|
||||||
return result.map(ensurePluginIsV2);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadNxPlugins(
|
export async function loadNxPlugins(
|
||||||
plugins: string[],
|
plugins: PluginDefinition[],
|
||||||
paths = getNxRequirePaths(),
|
paths = getNxRequirePaths(),
|
||||||
root = workspaceRoot
|
root = workspaceRoot
|
||||||
): Promise<(NxPluginV2 & Pick<NxPluginV1, 'processProjectGraph'>)[]> {
|
): Promise<LoadedNxPlugin[]> {
|
||||||
const result: NxPlugin[] = [...(await getDefaultPlugins(root))];
|
const result: LoadedNxPlugin[] = [...(await getDefaultPlugins(root))];
|
||||||
|
|
||||||
// TODO: These should be specified in nx.json
|
// TODO: These should be specified in nx.json
|
||||||
// Temporarily load js as if it were a plugin which is built into nx
|
// Temporarily load js as if it were a plugin which is built into nx
|
||||||
@ -279,11 +306,11 @@ export async function loadNxPlugins(
|
|||||||
|
|
||||||
// We push the nx core node plugins onto the end, s.t. it overwrites any other plugins
|
// We push the nx core node plugins onto the end, s.t. it overwrites any other plugins
|
||||||
result.push(
|
result.push(
|
||||||
getNxPackageJsonWorkspacesPlugin(root),
|
{ plugin: getNxPackageJsonWorkspacesPlugin(root) },
|
||||||
CreateProjectJsonProjectsPlugin
|
{ plugin: CreateProjectJsonProjectsPlugin }
|
||||||
);
|
);
|
||||||
|
|
||||||
return result.map(ensurePluginIsV2);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensurePluginIsV2(plugin: NxPlugin): NxPluginV2 {
|
function ensurePluginIsV2(plugin: NxPlugin): NxPluginV2 {
|
||||||
@ -494,22 +521,26 @@ function readPluginMainFromProjectConfiguration(
|
|||||||
return main;
|
return main;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDefaultPlugins(root: string) {
|
async function getDefaultPlugins(root: string): Promise<LoadedNxPlugin[]> {
|
||||||
const plugins: NxPlugin[] = [await import('../plugins/js')];
|
const plugins: NxPluginV2[] = [await import('../plugins/js')];
|
||||||
|
|
||||||
if (shouldMergeAngularProjects(root, false)) {
|
if (shouldMergeAngularProjects(root, false)) {
|
||||||
plugins.push(
|
plugins.push(
|
||||||
await import('../adapter/angular-json').then((m) => m.NxAngularJsonPlugin)
|
await import('../adapter/angular-json').then((m) => m.NxAngularJsonPlugin)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return plugins;
|
return plugins.map((p) => ({
|
||||||
|
plugin: p,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDefaultPluginsSync(root: string) {
|
function getDefaultPluginsSync(root: string): LoadedNxPlugin[] {
|
||||||
const plugins: NxPlugin[] = [require('../plugins/js')];
|
const plugins: NxPluginV2[] = [require('../plugins/js')];
|
||||||
|
|
||||||
if (shouldMergeAngularProjects(root, false)) {
|
if (shouldMergeAngularProjects(root, false)) {
|
||||||
plugins.push(require('../adapter/angular-json').NxAngularJsonPlugin);
|
plugins.push(require('../adapter/angular-json').NxAngularJsonPlugin);
|
||||||
}
|
}
|
||||||
return plugins;
|
return plugins.map((p) => ({
|
||||||
|
plugin: p,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export async function getLocalWorkspacePlugins(
|
|||||||
if (existsSync(packageJsonPath)) {
|
if (existsSync(packageJsonPath)) {
|
||||||
const packageJson: PackageJson = readJsonFile(packageJsonPath);
|
const packageJson: PackageJson = readJsonFile(packageJsonPath);
|
||||||
const includeRuntimeCapabilities = nxJson?.plugins?.some((p) =>
|
const includeRuntimeCapabilities = nxJson?.plugins?.some((p) =>
|
||||||
p.startsWith(packageJson.name)
|
(typeof p === 'string' ? p : p.plugin).startsWith(packageJson.name)
|
||||||
);
|
);
|
||||||
const capabilities = await getPluginCapabilities(
|
const capabilities = await getPluginCapabilities(
|
||||||
workspaceRoot,
|
workspaceRoot,
|
||||||
|
|||||||
@ -103,11 +103,13 @@ async function tryGetModule(
|
|||||||
packageJson['nx-migrations'] ??
|
packageJson['nx-migrations'] ??
|
||||||
packageJson['schematics'] ??
|
packageJson['schematics'] ??
|
||||||
packageJson['builders']
|
packageJson['builders']
|
||||||
? await loadNxPluginAsync(
|
? (
|
||||||
packageJson.name,
|
await loadNxPluginAsync(
|
||||||
getNxRequirePaths(workspaceRoot),
|
packageJson.name,
|
||||||
workspaceRoot
|
getNxRequirePaths(workspaceRoot),
|
||||||
)
|
workspaceRoot
|
||||||
|
)
|
||||||
|
).plugin
|
||||||
: ({
|
: ({
|
||||||
name: packageJson.name,
|
name: packageJson.name,
|
||||||
} as NxPlugin);
|
} as NxPlugin);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user