cleanup(core): remove async flag from signature of buildProjectsConfigurationsFromProjectPathsAndPlugins (#20228)
This commit is contained in:
parent
2a5d541243
commit
30d94f76ee
@ -1,9 +0,0 @@
|
||||
# Type alias: CreateNodesAsync<T\>
|
||||
|
||||
Ƭ **CreateNodesAsync**<`T`\>: readonly [projectFilePattern: string, createNodesFunction: CreateNodesFunctionAsync<T\>]
|
||||
|
||||
#### Type parameters
|
||||
|
||||
| Name | Type |
|
||||
| :--- | :-------- |
|
||||
| `T` | `unknown` |
|
||||
@ -1,6 +1,6 @@
|
||||
# Type alias: CreateNodesFunction<T\>
|
||||
|
||||
Ƭ **CreateNodesFunction**<`T`\>: (`projectConfigurationFile`: `string`, `options`: `T` \| `undefined`, `context`: [`CreateNodesContext`](../../devkit/documents/CreateNodesContext)) => [`CreateNodesResult`](../../devkit/documents/CreateNodesResult)
|
||||
Ƭ **CreateNodesFunction**<`T`\>: (`projectConfigurationFile`: `string`, `options`: `T` \| `undefined`, `context`: [`CreateNodesContext`](../../devkit/documents/CreateNodesContext)) => [`CreateNodesResult`](../../devkit/documents/CreateNodesResult) \| `Promise`<[`CreateNodesResult`](../../devkit/documents/CreateNodesResult)\>
|
||||
|
||||
#### Type parameters
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
#### Type declaration
|
||||
|
||||
▸ (`projectConfigurationFile`, `options`, `context`): [`CreateNodesResult`](../../devkit/documents/CreateNodesResult)
|
||||
▸ (`projectConfigurationFile`, `options`, `context`): [`CreateNodesResult`](../../devkit/documents/CreateNodesResult) \| `Promise`<[`CreateNodesResult`](../../devkit/documents/CreateNodesResult)\>
|
||||
|
||||
A function which parses a configuration file into a set of nodes.
|
||||
Used for creating nodes for the [ProjectGraph](../../devkit/documents/ProjectGraph)
|
||||
@ -25,4 +25,4 @@ Used for creating nodes for the [ProjectGraph](../../devkit/documents/ProjectGra
|
||||
|
||||
##### Returns
|
||||
|
||||
[`CreateNodesResult`](../../devkit/documents/CreateNodesResult)
|
||||
[`CreateNodesResult`](../../devkit/documents/CreateNodesResult) \| `Promise`<[`CreateNodesResult`](../../devkit/documents/CreateNodesResult)\>
|
||||
|
||||
@ -1,20 +1,19 @@
|
||||
# Type alias: NxPluginV2<TOptions, TCreateNodes\>
|
||||
# Type alias: NxPluginV2<TOptions\>
|
||||
|
||||
Ƭ **NxPluginV2**<`TOptions`, `TCreateNodes`\>: `Object`
|
||||
Ƭ **NxPluginV2**<`TOptions`\>: `Object`
|
||||
|
||||
A plugin for Nx which creates nodes and dependencies for the [ProjectGraph](../../devkit/documents/ProjectGraph)
|
||||
|
||||
#### Type parameters
|
||||
|
||||
| Name | Type |
|
||||
| :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `TOptions` | `unknown` |
|
||||
| `TCreateNodes` | extends [`CreateNodes`](../../devkit/documents/CreateNodes)<`TOptions`\> \| [`CreateNodesAsync`](../../devkit/documents/CreateNodesAsync)<`TOptions`\> = [`CreateNodes`](../../devkit/documents/CreateNodes)<`TOptions`\> \| [`CreateNodesAsync`](../../devkit/documents/CreateNodesAsync)<`TOptions`\> |
|
||||
| Name | Type |
|
||||
| :--------- | :-------- |
|
||||
| `TOptions` | `unknown` |
|
||||
|
||||
#### Type declaration
|
||||
|
||||
| Name | Type | Description |
|
||||
| :-------------------- | :----------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `createDependencies?` | [`CreateDependencies`](../../devkit/documents/CreateDependencies)<`TOptions`\> | Provides a function to analyze files to create dependencies for the [ProjectGraph](../../devkit/documents/ProjectGraph) |
|
||||
| `createNodes?` | `TCreateNodes` | Provides a file pattern and function that retrieves configuration info from those files. e.g. { '\*_/_.csproj': buildProjectsFromCsProjFile } |
|
||||
| `createNodes?` | [`CreateNodes`](../../devkit/documents/CreateNodes) | Provides a file pattern and function that retrieves configuration info from those files. e.g. { '\*_/_.csproj': buildProjectsFromCsProjFile } |
|
||||
| `name` | `string` | - |
|
||||
|
||||
@ -65,7 +65,6 @@ It only uses language primitives and immutable objects
|
||||
|
||||
- [CreateDependencies](../../devkit/documents/CreateDependencies)
|
||||
- [CreateNodes](../../devkit/documents/CreateNodes)
|
||||
- [CreateNodesAsync](../../devkit/documents/CreateNodesAsync)
|
||||
- [CreateNodesFunction](../../devkit/documents/CreateNodesFunction)
|
||||
- [CustomHasher](../../devkit/documents/CustomHasher)
|
||||
- [DynamicDependency](../../devkit/documents/DynamicDependency)
|
||||
|
||||
@ -65,7 +65,6 @@ It only uses language primitives and immutable objects
|
||||
|
||||
- [CreateDependencies](../../devkit/documents/CreateDependencies)
|
||||
- [CreateNodes](../../devkit/documents/CreateNodes)
|
||||
- [CreateNodesAsync](../../devkit/documents/CreateNodesAsync)
|
||||
- [CreateNodesFunction](../../devkit/documents/CreateNodesFunction)
|
||||
- [CustomHasher](../../devkit/documents/CustomHasher)
|
||||
- [DynamicDependency](../../devkit/documents/DynamicDependency)
|
||||
|
||||
@ -59,7 +59,7 @@ A simplified version of Nx's built-in `project.json` plugin is shown below, whic
|
||||
export const createNodes: CreateNodes = [
|
||||
'**/project.json',
|
||||
(projectConfigurationFile: string, opts, context: CreateNodesContext) => {
|
||||
const projectConfiguration = readJson(projectConfigurationFile);
|
||||
const projectConfiguration = readJsonFile(projectConfigurationFile);
|
||||
const root = dirname(projectConfigurationFile);
|
||||
|
||||
return {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": ["node"],
|
||||
"lib": ["DOM", "es2019"]
|
||||
"lib": ["DOM", "es2022"]
|
||||
},
|
||||
"files": [
|
||||
"../../node_modules/@nx/react/typings/cssmodule.d.ts",
|
||||
|
||||
@ -13,4 +13,5 @@ module.exports = {
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageReporters: ['html'],
|
||||
maxWorkers: 1,
|
||||
testEnvironment: 'node',
|
||||
};
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
export default {
|
||||
displayName: 'nx-dev-models-document',
|
||||
globals: {},
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
'^.+\\.[tj]sx?$': [
|
||||
'ts-jest',
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
export default {
|
||||
displayName: 'nx-dev-models-menu',
|
||||
globals: {},
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
'^.+\\.[tj]sx?$': [
|
||||
'ts-jest',
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
export default {
|
||||
displayName: 'nx-dev-models-package',
|
||||
globals: {},
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
'^.+\\.[tj]sx?$': [
|
||||
'ts-jest',
|
||||
|
||||
@ -8,4 +8,5 @@ export default {
|
||||
coverageDirectory: '../../coverage/nx-dev/ui-sponsor-card',
|
||||
setupFilesAfterEnv: ['<rootDir>/test-setup.ts'],
|
||||
preset: '../../jest.preset.js',
|
||||
testEnvironment: 'jsdom',
|
||||
};
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
export default {
|
||||
displayName: 'nx-dev-util-ai',
|
||||
preset: '../../jest.preset.js',
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
|
||||
},
|
||||
|
||||
@ -6,7 +6,6 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'angular',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
setupFilesAfterEnv: ['<rootDir>/test-setup.ts'],
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'create-nx-plugin',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'create-nx-workspace',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'cypress',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -58,6 +58,7 @@ describe('add-nx-cypress-plugin migration', () => {
|
||||
})
|
||||
);
|
||||
updateProjectConfiguration(tree, 'e2e', {
|
||||
name: 'e2e',
|
||||
root: 'e2e',
|
||||
targets: {
|
||||
e2e: {
|
||||
|
||||
@ -6,7 +6,6 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html', 'json'],
|
||||
globals: {},
|
||||
displayName: 'react-native',
|
||||
testEnvironment: 'node',
|
||||
verbose: true,
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'cli',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -3,7 +3,7 @@ import type {
|
||||
TargetConfiguration,
|
||||
} from 'nx/src/config/workspace-json-project-json';
|
||||
import type { Tree } from 'nx/src/generators/tree';
|
||||
import type { CreateNodes, CreateNodesAsync } from 'nx/src/utils/nx-plugin';
|
||||
import type { CreateNodes } from 'nx/src/utils/nx-plugin';
|
||||
import { requireNx } from '../../nx';
|
||||
const {
|
||||
readNxJson,
|
||||
@ -19,7 +19,7 @@ export async function replaceProjectConfigurationsWithPlugin<T = unknown>(
|
||||
tree: Tree,
|
||||
rootMappings: Map<string, string>,
|
||||
pluginPath: string,
|
||||
createNodes: CreateNodes<T> | CreateNodesAsync<T>,
|
||||
createNodes: CreateNodes<T>,
|
||||
pluginOptions: T
|
||||
): Promise<void> {
|
||||
const nxJson = readNxJson(tree);
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'esbuild',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'packages-eslint-plugin',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'eslint',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html', 'json'],
|
||||
globals: {},
|
||||
displayName: 'expo',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'express',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'jest',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'js',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'nest',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'next',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'node',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'nx',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { performance } from 'perf_hooks';
|
||||
import { readNxJson } from '../../config/nx-json';
|
||||
import { readNxJson, NxJsonConfiguration } from '../../config/nx-json';
|
||||
import {
|
||||
FileData,
|
||||
FileMap,
|
||||
@ -136,7 +136,10 @@ function computeWorkspaceConfigHash(
|
||||
return hashArray(projectConfigurationStrings);
|
||||
}
|
||||
|
||||
async function processCollectedUpdatedAndDeletedFiles() {
|
||||
async function processCollectedUpdatedAndDeletedFiles(
|
||||
projects: Record<string, ProjectConfiguration>,
|
||||
nxJson: NxJsonConfiguration
|
||||
) {
|
||||
try {
|
||||
performance.mark('hash-watched-changes-start');
|
||||
const updatedFiles = [...collectedUpdatedFiles.values()];
|
||||
@ -149,14 +152,7 @@ async function processCollectedUpdatedAndDeletedFiles() {
|
||||
'hash-watched-changes-end'
|
||||
);
|
||||
|
||||
const nxJson = readNxJson(workspaceRoot);
|
||||
|
||||
const { projectNodes } = await retrieveProjectConfigurations(
|
||||
workspaceRoot,
|
||||
nxJson
|
||||
);
|
||||
|
||||
const workspaceConfigHash = computeWorkspaceConfigHash(projectNodes);
|
||||
const workspaceConfigHash = computeWorkspaceConfigHash(projects);
|
||||
serverLogger.requestLog(
|
||||
`Updated file-hasher based on watched changes, recomputing project graph...`
|
||||
);
|
||||
@ -172,7 +168,7 @@ async function processCollectedUpdatedAndDeletedFiles() {
|
||||
} else {
|
||||
if (fileMapWithFiles) {
|
||||
fileMapWithFiles = updateFileMap(
|
||||
projectNodes,
|
||||
projects,
|
||||
fileMapWithFiles.fileMap,
|
||||
fileMapWithFiles.allWorkspaceFiles,
|
||||
new Map(Object.entries(updatedFileHashes)),
|
||||
@ -197,13 +193,24 @@ async function processCollectedUpdatedAndDeletedFiles() {
|
||||
`Error detected when recomputing project file map: ${e.message}`
|
||||
);
|
||||
resetInternalState();
|
||||
return e;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async function processFilesAndCreateAndSerializeProjectGraph() {
|
||||
const err = await processCollectedUpdatedAndDeletedFiles();
|
||||
if (err) {
|
||||
try {
|
||||
const nxJson = readNxJson(workspaceRoot);
|
||||
const configResult = await retrieveProjectConfigurations(
|
||||
workspaceRoot,
|
||||
nxJson
|
||||
);
|
||||
await processCollectedUpdatedAndDeletedFiles(
|
||||
configResult.projectNodes,
|
||||
nxJson
|
||||
);
|
||||
writeSourceMaps(configResult.sourceMaps);
|
||||
return createAndSerializeProjectGraph(configResult.projectNodes);
|
||||
} catch (err) {
|
||||
return Promise.resolve({
|
||||
error: err,
|
||||
projectGraph: null,
|
||||
@ -211,8 +218,6 @@ async function processFilesAndCreateAndSerializeProjectGraph() {
|
||||
allWorkspaceFiles: null,
|
||||
serializedProjectGraph: null,
|
||||
});
|
||||
} else {
|
||||
return createAndSerializeProjectGraph();
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,7 +236,9 @@ function copyFileMap(m: FileMap) {
|
||||
return c;
|
||||
}
|
||||
|
||||
async function createAndSerializeProjectGraph(): Promise<{
|
||||
async function createAndSerializeProjectGraph(
|
||||
projects: Record<string, ProjectConfiguration>
|
||||
): Promise<{
|
||||
error: string | null;
|
||||
projectGraph: ProjectGraph | null;
|
||||
fileMap: FileMap | null;
|
||||
@ -240,15 +247,11 @@ async function createAndSerializeProjectGraph(): Promise<{
|
||||
}> {
|
||||
try {
|
||||
performance.mark('create-project-graph-start');
|
||||
const projectConfigurations = await retrieveProjectConfigurations(
|
||||
workspaceRoot,
|
||||
readNxJson(workspaceRoot)
|
||||
);
|
||||
const fileMap = copyFileMap(fileMapWithFiles.fileMap);
|
||||
const allWorkspaceFiles = copyFileData(fileMapWithFiles.allWorkspaceFiles);
|
||||
const { projectGraph, projectFileMapCache } =
|
||||
await buildProjectGraphUsingFileMap(
|
||||
projectConfigurations.projectNodes,
|
||||
projects,
|
||||
knownExternalNodes,
|
||||
fileMap,
|
||||
allWorkspaceFiles,
|
||||
@ -274,8 +277,6 @@ async function createAndSerializeProjectGraph(): Promise<{
|
||||
'json-stringify-end'
|
||||
);
|
||||
|
||||
writeSourceMaps(projectConfigurations.sourceMaps);
|
||||
|
||||
return {
|
||||
error: null,
|
||||
projectGraph,
|
||||
|
||||
@ -51,7 +51,6 @@ export type {
|
||||
NxPluginV2,
|
||||
ProjectTargetConfigurator,
|
||||
CreateNodes,
|
||||
CreateNodesAsync,
|
||||
CreateNodesFunction,
|
||||
CreateNodesResult,
|
||||
CreateNodesContext,
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
getGlobPatternsFromPackageManagerWorkspaces,
|
||||
} from '../../../plugins/package-json-workspaces';
|
||||
import { buildProjectFromProjectJson } from '../../plugins/project-json/build-nodes/project-json';
|
||||
import { getDefaultPluginsSync } from '../../utils/nx-plugin.deprecated';
|
||||
import { renamePropertyWithStableKeys } from '../../adapter/angular-json';
|
||||
import {
|
||||
ProjectConfiguration,
|
||||
@ -14,7 +15,7 @@ import {
|
||||
mergeProjectConfigurationIntoRootMap,
|
||||
readProjectConfigurationsFromRootMap,
|
||||
} from '../../project-graph/utils/project-configuration-utils';
|
||||
import { retrieveProjectConfigurationPathsWithoutPluginInference } from '../../project-graph/utils/retrieve-workspace-files';
|
||||
import { retrieveProjectConfigurationPaths } from '../../project-graph/utils/retrieve-workspace-files';
|
||||
import { output } from '../../utils/output';
|
||||
import { PackageJson } from '../../utils/package-json';
|
||||
import { joinPathFragments, normalizePath } from '../../utils/path';
|
||||
@ -191,9 +192,9 @@ function readAndCombineAllProjectConfigurations(tree: Tree): {
|
||||
readJson(tree, p)
|
||||
),
|
||||
];
|
||||
|
||||
const globbedFiles = retrieveProjectConfigurationPathsWithoutPluginInference(
|
||||
tree.root
|
||||
const globbedFiles = retrieveProjectConfigurationPaths(
|
||||
tree.root,
|
||||
getDefaultPluginsSync(tree.root)
|
||||
);
|
||||
const createdFiles = findCreatedProjectFiles(tree, patterns);
|
||||
const deletedFiles = findDeletedProjectFiles(tree, patterns);
|
||||
|
||||
@ -4,12 +4,13 @@ import { dirname } from 'path';
|
||||
import { readJson, writeJson } from '../../generators/utils/json';
|
||||
import { formatChangedFilesWithPrettierIfAvailable } from '../../generators/internal-utils/format-changed-files-with-prettier-if-available';
|
||||
import { retrieveProjectConfigurationPaths } from '../../project-graph/utils/retrieve-workspace-files';
|
||||
import { loadNxPlugins } from '../../utils/nx-plugin';
|
||||
|
||||
export default async function (tree: Tree) {
|
||||
const nxJson = readNxJson(tree);
|
||||
const projectFiles = await retrieveProjectConfigurationPaths(
|
||||
tree.root,
|
||||
nxJson
|
||||
await loadNxPlugins(nxJson?.plugins)
|
||||
);
|
||||
const projectJsons = projectFiles.filter((f) => f.endsWith('project.json'));
|
||||
|
||||
|
||||
@ -3,9 +3,9 @@ import { dirname, join } from 'node:path';
|
||||
import { ProjectConfiguration } from '../../../config/workspace-json-project-json';
|
||||
import { toProjectName } from '../../../config/workspaces';
|
||||
import { readJsonFile } from '../../../utils/fileutils';
|
||||
import { CreateNodes, NxPluginV2 } from '../../../utils/nx-plugin';
|
||||
import { NxPluginV2 } from '../../../utils/nx-plugin';
|
||||
|
||||
export const CreateProjectJsonProjectsPlugin: NxPluginV2<void, CreateNodes> = {
|
||||
export const CreateProjectJsonProjectsPlugin: NxPluginV2 = {
|
||||
name: 'nx-core-build-project-json-nodes',
|
||||
createNodes: [
|
||||
'{project.json,**/project.json}',
|
||||
|
||||
@ -12,7 +12,6 @@ export const getTouchedProjectsFromProjectGlobChanges: TouchedProjectLocator =
|
||||
async (touchedFiles, projectGraphNodes, nxJson): Promise<string[]> => {
|
||||
const globPattern = combineGlobPatterns(
|
||||
configurationGlobs(
|
||||
workspaceRoot,
|
||||
await loadNxPlugins(
|
||||
nxJson?.plugins,
|
||||
getNxRequirePaths(workspaceRoot),
|
||||
|
||||
@ -33,6 +33,7 @@ import { readNxJson } from '../config/configuration';
|
||||
import { existsSync } from 'fs';
|
||||
import { PackageJson } from '../utils/package-json';
|
||||
import { getNxRequirePaths } from '../utils/installation-directory';
|
||||
import { output } from '../utils/output';
|
||||
|
||||
let storedFileMap: FileMap | null = null;
|
||||
let storedAllWorkspaceFiles: FileData[] | null = null;
|
||||
@ -244,13 +245,13 @@ async function updateProjectGraphWithPlugins(
|
||||
plugin.processProjectGraph &&
|
||||
!plugin.createDependencies
|
||||
) {
|
||||
// TODO(@AgentEnder): Enable after rewriting nx-js-graph-plugin to v2
|
||||
// output.warn({
|
||||
// title: `${plugin.name} is a v1 plugin.`,
|
||||
// bodyLines: [
|
||||
// 'Nx has recently released a v2 model for project graph plugins. The `processProjectGraph` method is deprecated. Plugins should use some combination of `createNodes` and `createDependencies` instead.',
|
||||
// ],
|
||||
// });
|
||||
output.warn({
|
||||
title: `${plugin.name} is a v1 plugin.`,
|
||||
bodyLines: [
|
||||
'Nx has recently released a v2 model for project graph plugins. The `processProjectGraph` method is deprecated. Plugins should use some combination of `createNodes` and `createDependencies` instead.',
|
||||
],
|
||||
});
|
||||
performance.mark(`${plugin.name}:processProjectGraph - start`);
|
||||
graph = await plugin.processProjectGraph(graph, {
|
||||
...context,
|
||||
projectsConfigurations: {
|
||||
@ -265,6 +266,12 @@ async function updateProjectGraphWithPlugins(
|
||||
...context.nxJsonConfiguration,
|
||||
},
|
||||
});
|
||||
performance.mark(`${plugin.name}:processProjectGraph - end`);
|
||||
performance.measure(
|
||||
`${plugin.name}:processProjectGraph`,
|
||||
`${plugin.name}:processProjectGraph - start`,
|
||||
`${plugin.name}:processProjectGraph - end`
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
let message = `Failed to process the project graph with "${plugin.name}".`;
|
||||
@ -287,6 +294,7 @@ async function updateProjectGraphWithPlugins(
|
||||
);
|
||||
await Promise.all(
|
||||
createDependencyPlugins.map(async ({ plugin, options }) => {
|
||||
performance.mark(`${plugin.name}:createDependencies - start`);
|
||||
try {
|
||||
const dependencies = await plugin.createDependencies(options, {
|
||||
...context,
|
||||
@ -308,6 +316,12 @@ async function updateProjectGraphWithPlugins(
|
||||
}
|
||||
throw new Error(message);
|
||||
}
|
||||
performance.mark(`${plugin.name}:createDependencies - end`);
|
||||
performance.measure(
|
||||
`${plugin.name}:createDependencies`,
|
||||
`${plugin.name}:createDependencies - start`,
|
||||
`${plugin.name}:createDependencies - end`
|
||||
);
|
||||
})
|
||||
);
|
||||
return builder.getUpdatedProjectGraph();
|
||||
|
||||
@ -3,7 +3,10 @@ import { existsSync, readFileSync } from 'fs';
|
||||
import { extname, join, relative, sep } from 'path';
|
||||
import { readNxJson } from '../config/configuration';
|
||||
import { FileData } from '../config/project-graph';
|
||||
import { ProjectsConfigurations } from '../config/workspace-json-project-json';
|
||||
import {
|
||||
ProjectConfiguration,
|
||||
ProjectsConfigurations,
|
||||
} from '../config/workspace-json-project-json';
|
||||
import type { NxArgs } from '../utils/command-line-utils';
|
||||
import { workspaceRoot } from '../utils/workspace-root';
|
||||
import { readJsonFile } from '../utils/fileutils';
|
||||
@ -14,10 +17,17 @@ import {
|
||||
} from './project-graph';
|
||||
import { toOldFormat } from '../adapter/angular-json';
|
||||
import { getIgnoreObject } from '../utils/ignore';
|
||||
import { retrieveProjectConfigurationPathsWithoutPluginInference } from './utils/retrieve-workspace-files';
|
||||
import { buildProjectsConfigurationsFromProjectPathsAndPlugins } from './utils/project-configuration-utils';
|
||||
import { retrieveProjectConfigurationPaths } from './utils/retrieve-workspace-files';
|
||||
import {
|
||||
mergeProjectConfigurationIntoRootMap,
|
||||
readProjectConfigurationsFromRootMap,
|
||||
} from './utils/project-configuration-utils';
|
||||
import { NxJsonConfiguration } from '../config/nx-json';
|
||||
import { getDefaultPluginsSync } from '../utils/nx-plugin.deprecated';
|
||||
import minimatch = require('minimatch');
|
||||
import { CreateNodesResult } from '../devkit-exports';
|
||||
import { CreatePackageJsonProjectsNextToProjectJson } from '../plugins/project-json/build-nodes/package-json-next-to-project-json';
|
||||
import { LoadedNxPlugin } from '../utils/nx-plugin';
|
||||
|
||||
export interface Change {
|
||||
type: string;
|
||||
@ -168,13 +178,45 @@ export { FileData };
|
||||
// TODO(17): Remove these exports
|
||||
export { readNxJson, workspaceLayout } from '../config/configuration';
|
||||
|
||||
/**
|
||||
* TODO(v18): Remove this function.
|
||||
*/
|
||||
function getProjectsSyncNoInference(root: string, nxJson: NxJsonConfiguration) {
|
||||
const paths = retrieveProjectConfigurationPathsWithoutPluginInference(root);
|
||||
return buildProjectsConfigurationsFromProjectPathsAndPlugins(
|
||||
nxJson,
|
||||
paths,
|
||||
getDefaultPluginsSync(root),
|
||||
const projectFiles = retrieveProjectConfigurationPaths(
|
||||
root,
|
||||
true
|
||||
getDefaultPluginsSync(root)
|
||||
);
|
||||
const plugins: LoadedNxPlugin[] = [
|
||||
{ plugin: CreatePackageJsonProjectsNextToProjectJson },
|
||||
...getDefaultPluginsSync(root),
|
||||
];
|
||||
|
||||
const projectRootMap: Map<string, ProjectConfiguration> = new Map();
|
||||
|
||||
// We iterate over plugins first - this ensures that plugins specified first take precedence.
|
||||
for (const { plugin, options } of plugins) {
|
||||
const [pattern, createNodes] = plugin.createNodes ?? [];
|
||||
if (!pattern) {
|
||||
continue;
|
||||
}
|
||||
for (const file of projectFiles) {
|
||||
if (minimatch(file, pattern, { dot: true })) {
|
||||
let r = createNodes(file, options, {
|
||||
nxJsonConfiguration: nxJson,
|
||||
workspaceRoot: root,
|
||||
}) as CreateNodesResult;
|
||||
for (const node in r.projects) {
|
||||
const project = {
|
||||
root: node,
|
||||
...r.projects[node],
|
||||
};
|
||||
mergeProjectConfigurationIntoRootMap(projectRootMap, project);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
projects: readProjectConfigurationsFromRootMap(projectRootMap),
|
||||
};
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import {
|
||||
} from '../../config/workspace-json-project-json';
|
||||
import {
|
||||
ConfigurationSourceMaps,
|
||||
SourceInformation,
|
||||
isCompatibleTarget,
|
||||
mergeProjectConfigurationIntoRootMap,
|
||||
mergeTargetConfigurations,
|
||||
readProjectConfigurationsFromRootMap,
|
||||
@ -996,6 +996,112 @@ describe('project-configuration-utils', () => {
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isCompatibleTarget', () => {
|
||||
it('should return true if only one target specifies an executor', () => {
|
||||
expect(
|
||||
isCompatibleTarget(
|
||||
{
|
||||
executor: 'nx:run-commands',
|
||||
},
|
||||
{}
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true if both targets specify the same executor', () => {
|
||||
expect(
|
||||
isCompatibleTarget(
|
||||
{
|
||||
executor: 'nx:run-commands',
|
||||
},
|
||||
{
|
||||
executor: 'nx:run-commands',
|
||||
}
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if both targets specify different executors', () => {
|
||||
expect(
|
||||
isCompatibleTarget(
|
||||
{
|
||||
executor: 'nx:run-commands',
|
||||
},
|
||||
{
|
||||
executor: 'other-executor',
|
||||
}
|
||||
)
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if both targets specify the same command', () => {
|
||||
expect(
|
||||
isCompatibleTarget(
|
||||
{
|
||||
command: 'echo',
|
||||
},
|
||||
{
|
||||
command: 'echo',
|
||||
}
|
||||
)
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
isCompatibleTarget(
|
||||
{
|
||||
command: 'echo',
|
||||
},
|
||||
{
|
||||
executor: 'nx:run-commands',
|
||||
options: {
|
||||
command: 'echo',
|
||||
},
|
||||
}
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if both targets specify different commands', () => {
|
||||
expect(
|
||||
isCompatibleTarget(
|
||||
{
|
||||
command: 'echo',
|
||||
},
|
||||
{
|
||||
command: 'echo2',
|
||||
}
|
||||
)
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
isCompatibleTarget(
|
||||
{
|
||||
command: 'echo',
|
||||
},
|
||||
{
|
||||
executor: 'nx:run-commands',
|
||||
options: {
|
||||
command: 'echo2',
|
||||
},
|
||||
}
|
||||
)
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if one target specifies an executor and the other a command', () => {
|
||||
expect(
|
||||
isCompatibleTarget(
|
||||
{
|
||||
executor: 'nx:noop',
|
||||
},
|
||||
{
|
||||
command: 'echo',
|
||||
}
|
||||
)
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
class RootMapBuilder {
|
||||
|
||||
@ -8,7 +8,6 @@ import {
|
||||
import { NX_PREFIX } from '../../utils/logger';
|
||||
import { CreateNodesResult, LoadedNxPlugin } from '../../utils/nx-plugin';
|
||||
import { workspaceRoot } from '../../utils/workspace-root';
|
||||
import { output } from '../../utils/output';
|
||||
|
||||
import minimatch = require('minimatch');
|
||||
|
||||
@ -147,32 +146,13 @@ export function mergeProjectConfigurationIntoRootMap(
|
||||
);
|
||||
}
|
||||
|
||||
type CreateNodesResultWithMetadata = {
|
||||
result: CreateNodesResult | Promise<CreateNodesResult>;
|
||||
pluginName: string;
|
||||
file: string;
|
||||
};
|
||||
|
||||
type ConfigurationResult = {
|
||||
export type ConfigurationResult = {
|
||||
projects: Record<string, ProjectConfiguration>;
|
||||
externalNodes: Record<string, ProjectGraphExternalNode>;
|
||||
rootMap: Record<string, string>;
|
||||
sourceMaps: ConfigurationSourceMaps;
|
||||
};
|
||||
|
||||
/**
|
||||
* ** DO NOT USE ** - Please use without the `skipAsync` parameter.
|
||||
* @deprecated
|
||||
* @todo(@agentender): Remove in Nx 18 alongside the removal of its usage.
|
||||
*/
|
||||
export function buildProjectsConfigurationsFromProjectPathsAndPlugins(
|
||||
nxJson: NxJsonConfiguration,
|
||||
projectFiles: string[], // making this parameter allows devkit to pick up newly created projects
|
||||
plugins: LoadedNxPlugin[],
|
||||
root: string,
|
||||
skipAsync: true
|
||||
): ConfigurationResult;
|
||||
|
||||
/**
|
||||
* Transforms a list of project paths into a map of project configurations.
|
||||
*
|
||||
@ -185,108 +165,144 @@ export function buildProjectsConfigurationsFromProjectPathsAndPlugins(
|
||||
nxJson: NxJsonConfiguration,
|
||||
projectFiles: string[], // making this parameter allows devkit to pick up newly created projects
|
||||
plugins: LoadedNxPlugin[],
|
||||
root: string,
|
||||
skipAsync?: false
|
||||
): Promise<ConfigurationResult>;
|
||||
export function buildProjectsConfigurationsFromProjectPathsAndPlugins(
|
||||
nxJson: NxJsonConfiguration,
|
||||
projectFiles: string[], // making this parameter allows devkit to pick up newly created projects
|
||||
plugins: LoadedNxPlugin[],
|
||||
root: string = workspaceRoot,
|
||||
skipAsync: boolean = false
|
||||
): ConfigurationResult | Promise<ConfigurationResult> {
|
||||
const results: Array<CreateNodesResultWithMetadata> = [];
|
||||
root: string = workspaceRoot
|
||||
): Promise<ConfigurationResult> {
|
||||
type CreateNodesResultWithContext = CreateNodesResult & {
|
||||
file: string;
|
||||
pluginName: string;
|
||||
};
|
||||
|
||||
const results: Array<Promise<Array<CreateNodesResultWithContext>>> = [];
|
||||
|
||||
// We iterate over plugins first - this ensures that plugins specified first take precedence.
|
||||
for (const { plugin, options } of plugins) {
|
||||
const [pattern, createNodes] = plugin.createNodes ?? [];
|
||||
const pluginResults: Array<
|
||||
CreateNodesResultWithContext | Promise<CreateNodesResultWithContext>
|
||||
> = [];
|
||||
|
||||
performance.mark(`${plugin.name}:createNodes - start`);
|
||||
if (!pattern) {
|
||||
continue;
|
||||
}
|
||||
for (const file of projectFiles) {
|
||||
performance.mark(`${plugin.name}:createNodes:${file} - start`);
|
||||
if (minimatch(file, pattern, { dot: true })) {
|
||||
results.push({
|
||||
result: createNodes(file, options, {
|
||||
try {
|
||||
let r = createNodes(file, options, {
|
||||
nxJsonConfiguration: nxJson,
|
||||
workspaceRoot: root,
|
||||
}),
|
||||
pluginName: plugin.name,
|
||||
file,
|
||||
});
|
||||
});
|
||||
|
||||
if (r instanceof Promise) {
|
||||
pluginResults.push(
|
||||
r
|
||||
.catch((e) => {
|
||||
performance.mark(`${plugin.name}:createNodes:${file} - end`);
|
||||
throw new CreateNodesError(
|
||||
`Unable to create nodes for ${file} using plugin ${plugin.name}.`,
|
||||
e
|
||||
);
|
||||
})
|
||||
.then((r) => {
|
||||
performance.mark(`${plugin.name}:createNodes:${file} - end`);
|
||||
performance.measure(
|
||||
`${plugin.name}:createNodes:${file}`,
|
||||
`${plugin.name}:createNodes:${file} - start`,
|
||||
`${plugin.name}:createNodes:${file} - end`
|
||||
);
|
||||
return { ...r, file, pluginName: plugin.name };
|
||||
})
|
||||
);
|
||||
} else {
|
||||
performance.mark(`${plugin.name}:createNodes:${file} - end`);
|
||||
performance.measure(
|
||||
`${plugin.name}:createNodes:${file}`,
|
||||
`${plugin.name}:createNodes:${file} - start`,
|
||||
`${plugin.name}:createNodes:${file} - end`
|
||||
);
|
||||
pluginResults.push({
|
||||
...r,
|
||||
file,
|
||||
pluginName: plugin.name,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
throw new CreateNodesError(
|
||||
`Unable to create nodes for ${file} using plugin ${plugin.name}.`,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If there are no promises (counter undefined) or all promises have resolved (counter === 0)
|
||||
results.push(
|
||||
Promise.all(pluginResults).then((results) => {
|
||||
performance.mark(`${plugin.name}:createNodes - end`);
|
||||
performance.measure(
|
||||
`${plugin.name}:createNodes`,
|
||||
`${plugin.name}:createNodes - start`,
|
||||
`${plugin.name}:createNodes - end`
|
||||
);
|
||||
return results;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return skipAsync
|
||||
? combineSyncConfigurationResults(results)
|
||||
: combineAsyncConfigurationResults(results);
|
||||
}
|
||||
return Promise.all(results).then((results) => {
|
||||
performance.mark('createNodes:merge - start');
|
||||
const projectRootMap: Map<string, ProjectConfiguration> = new Map();
|
||||
const externalNodes: Record<string, ProjectGraphExternalNode> = {};
|
||||
const configurationSourceMaps: Record<
|
||||
string,
|
||||
Record<string, SourceInformation>
|
||||
> = {};
|
||||
|
||||
function combineSyncConfigurationResults(
|
||||
resultsWithMetadata: CreateNodesResultWithMetadata[]
|
||||
): ConfigurationResult {
|
||||
const projectRootMap: Map<string, ProjectConfiguration> = new Map();
|
||||
const externalNodes: Record<string, ProjectGraphExternalNode> = {};
|
||||
const configurationSourceMaps: Record<
|
||||
string,
|
||||
Record<string, SourceInformation>
|
||||
> = {};
|
||||
|
||||
let warned = false;
|
||||
for (const { result, pluginName, file } of resultsWithMetadata) {
|
||||
if (typeof result === 'object' && 'then' in result) {
|
||||
if (!warned) {
|
||||
output.warn({
|
||||
title: 'One or more plugins in this workspace are async.',
|
||||
bodyLines: [
|
||||
'Configuration from these plugins will not be visible to readWorkspaceConfig or readWorkspaceConfiguration. If you are using these methods, consider reading project info from the graph with createProjectGraphAsync instead.',
|
||||
'If you are not using one of these methods, please open an issue at http://github.com/nrwl/nx',
|
||||
],
|
||||
});
|
||||
warned = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const { projects: projectNodes, externalNodes: pluginExternalNodes } =
|
||||
result;
|
||||
for (const node in projectNodes) {
|
||||
mergeProjectConfigurationIntoRootMap(
|
||||
projectRootMap,
|
||||
{
|
||||
for (const result of results.flat()) {
|
||||
const {
|
||||
projects: projectNodes,
|
||||
externalNodes: pluginExternalNodes,
|
||||
file,
|
||||
pluginName,
|
||||
} = result;
|
||||
for (const node in projectNodes) {
|
||||
const project = {
|
||||
root: node,
|
||||
...projectNodes[node],
|
||||
},
|
||||
configurationSourceMaps,
|
||||
[pluginName, file]
|
||||
);
|
||||
};
|
||||
try {
|
||||
mergeProjectConfigurationIntoRootMap(
|
||||
projectRootMap,
|
||||
project,
|
||||
configurationSourceMaps,
|
||||
[file, pluginName]
|
||||
);
|
||||
} catch (e) {
|
||||
throw new CreateNodesError(
|
||||
`Unable to merge project information for "${project.root}" from ${result.file} using plugin ${result.pluginName}.`,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
Object.assign(externalNodes, pluginExternalNodes);
|
||||
}
|
||||
Object.assign(externalNodes, pluginExternalNodes);
|
||||
}
|
||||
|
||||
const rootMap = createRootMap(projectRootMap);
|
||||
const rootMap = createRootMap(projectRootMap);
|
||||
|
||||
return {
|
||||
projects: readProjectConfigurationsFromRootMap(projectRootMap),
|
||||
externalNodes,
|
||||
rootMap,
|
||||
sourceMaps: configurationSourceMaps,
|
||||
};
|
||||
}
|
||||
performance.mark('createNodes:merge - end');
|
||||
performance.measure(
|
||||
'createNodes:merge',
|
||||
'createNodes:merge - start',
|
||||
'createNodes:merge - end'
|
||||
);
|
||||
|
||||
function combineAsyncConfigurationResults(
|
||||
results: Array<CreateNodesResultWithMetadata>
|
||||
): Promise<ConfigurationResult> {
|
||||
return Promise.all(
|
||||
results.map((resultWithMetadata) =>
|
||||
typeof resultWithMetadata.result === 'object' &&
|
||||
'then' in resultWithMetadata.result
|
||||
? resultWithMetadata.result.then((resolvedResult) => ({
|
||||
...resultWithMetadata,
|
||||
result: resolvedResult,
|
||||
}))
|
||||
: resultWithMetadata
|
||||
)
|
||||
).then((r) => combineSyncConfigurationResults(r));
|
||||
return {
|
||||
projects: readProjectConfigurationsFromRootMap(projectRootMap),
|
||||
externalNodes,
|
||||
rootMap,
|
||||
sourceMaps: configurationSourceMaps,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function readProjectConfigurationsFromRootMap(
|
||||
@ -327,6 +343,23 @@ export function readProjectConfigurationsFromRootMap(
|
||||
return projects;
|
||||
}
|
||||
|
||||
class CreateNodesError extends Error {
|
||||
constructor(msg, cause: Error | unknown) {
|
||||
const message = `${msg} ${
|
||||
!cause
|
||||
? ''
|
||||
: cause instanceof Error
|
||||
? `\n\n\t Inner Error: ${cause.stack}`
|
||||
: cause
|
||||
}`;
|
||||
// These errors are thrown during a JS callback which is invoked via rust.
|
||||
// The errors messaging gets lost in the rust -> js -> rust transition, but
|
||||
// logging the error here will ensure that it is visible in the console.
|
||||
console.error(message);
|
||||
super(message, { cause });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two targets.
|
||||
*
|
||||
@ -417,8 +450,29 @@ export function mergeTargetConfigurations(
|
||||
* If the executors are both specified and don't match, the options aren't considered
|
||||
* "compatible" and shouldn't be merged.
|
||||
*/
|
||||
function isCompatibleTarget(a: TargetConfiguration, b: TargetConfiguration) {
|
||||
return !a.executor || !b.executor || a.executor === b.executor;
|
||||
export function isCompatibleTarget(
|
||||
a: TargetConfiguration,
|
||||
b: TargetConfiguration
|
||||
) {
|
||||
if (a.command || b.command) {
|
||||
const aCommand =
|
||||
a.command ??
|
||||
(a.executor === 'nx:run-commands' ? a.options?.command : null);
|
||||
const bCommand =
|
||||
b.command ??
|
||||
(b.executor === 'nx:run-commands' ? b.options?.command : null);
|
||||
|
||||
const sameCommand = aCommand === bCommand;
|
||||
const aHasNoExecutor = !a.command && !a.executor;
|
||||
const bHasNoExecutor = !b.command && !b.executor;
|
||||
|
||||
return sameCommand || aHasNoExecutor || bHasNoExecutor;
|
||||
}
|
||||
|
||||
const oneHasNoExecutor = !a.executor || !b.executor;
|
||||
const bothHaveSameExecutor = a.executor === b.executor;
|
||||
|
||||
return oneHasNoExecutor || bothHaveSameExecutor;
|
||||
}
|
||||
|
||||
function mergeConfigurations<T extends Object>(
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { getDefaultPlugins } from '../../utils/nx-plugin';
|
||||
import { TempFs } from '../../internal-testing-utils/temp-fs';
|
||||
import { retrieveProjectConfigurationPaths } from './retrieve-workspace-files';
|
||||
|
||||
@ -24,11 +25,13 @@ describe('retrieveProjectConfigurationPaths', () => {
|
||||
name: 'project-1',
|
||||
})
|
||||
);
|
||||
expect(
|
||||
await retrieveProjectConfigurationPaths(fs.tempDir, {})
|
||||
).not.toContain('not-projects/project.json');
|
||||
expect(await retrieveProjectConfigurationPaths(fs.tempDir, {})).toContain(
|
||||
'projects/project.json'
|
||||
|
||||
const configPaths = await retrieveProjectConfigurationPaths(
|
||||
fs.tempDir,
|
||||
await getDefaultPlugins(fs.tempDir)
|
||||
);
|
||||
|
||||
expect(configPaths).not.toContain('not-projects/project.json');
|
||||
expect(configPaths).toContain('projects/project.json');
|
||||
});
|
||||
});
|
||||
|
||||
@ -16,16 +16,16 @@ import {
|
||||
ProjectGraphExternalNode,
|
||||
} from '../../config/project-graph';
|
||||
import type { NxWorkspaceFiles } from '../../native';
|
||||
import {
|
||||
getGlobPatternsFromPackageManagerWorkspaces,
|
||||
getNxPackageJsonWorkspacesPlugin,
|
||||
} from '../../../plugins/package-json-workspaces';
|
||||
import { getNxPackageJsonWorkspacesPlugin } from '../../../plugins/package-json-workspaces';
|
||||
import {
|
||||
ConfigurationSourceMaps,
|
||||
SourceInformation,
|
||||
buildProjectsConfigurationsFromProjectPathsAndPlugins,
|
||||
} from './project-configuration-utils';
|
||||
import { LoadedNxPlugin, loadNxPlugins } from '../../utils/nx-plugin';
|
||||
import {
|
||||
getDefaultPlugins,
|
||||
LoadedNxPlugin,
|
||||
loadNxPlugins,
|
||||
} from '../../utils/nx-plugin';
|
||||
import { CreateProjectJsonProjectsPlugin } from '../../plugins/project-json/build-nodes/project-json';
|
||||
import {
|
||||
globWithWorkspaceContext,
|
||||
@ -49,7 +49,7 @@ export async function retrieveWorkspaceFiles(
|
||||
getNxRequirePaths(workspaceRoot),
|
||||
workspaceRoot
|
||||
);
|
||||
let globs = configurationGlobs(workspaceRoot, plugins);
|
||||
let globs = configurationGlobs(plugins);
|
||||
performance.mark('native-file-deps:end');
|
||||
performance.measure(
|
||||
'native-file-deps',
|
||||
@ -122,7 +122,7 @@ export async function retrieveProjectConfigurations(
|
||||
workspaceRoot
|
||||
);
|
||||
|
||||
const globs = configurationGlobs(workspaceRoot, plugins);
|
||||
const globs = configurationGlobs(plugins);
|
||||
return _retrieveProjectConfigurations(workspaceRoot, nxJson, plugins, globs);
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ export async function retrieveProjectConfigurationsWithAngularProjects(
|
||||
plugins.push({ plugin: NxAngularJsonPlugin });
|
||||
}
|
||||
|
||||
const globs = configurationGlobs(workspaceRoot, plugins);
|
||||
const globs = configurationGlobs(plugins);
|
||||
return _retrieveProjectConfigurations(workspaceRoot, nxJson, plugins, globs);
|
||||
}
|
||||
|
||||
@ -189,21 +189,12 @@ function _retrieveProjectConfigurations(
|
||||
).then(() => result);
|
||||
}
|
||||
|
||||
export async function retrieveProjectConfigurationPaths(
|
||||
export function retrieveProjectConfigurationPaths(
|
||||
root: string,
|
||||
nxJson: NxJsonConfiguration
|
||||
): Promise<string[]> {
|
||||
const projectGlobPatterns = configurationGlobs(
|
||||
root,
|
||||
await loadNxPlugins(nxJson?.plugins ?? [], getNxRequirePaths(root), root)
|
||||
);
|
||||
return globWithWorkspaceContext(root, projectGlobPatterns);
|
||||
}
|
||||
|
||||
export function retrieveProjectConfigurationPathsWithoutPluginInference(
|
||||
root: string
|
||||
plugins: LoadedNxPlugin[]
|
||||
): string[] {
|
||||
return globWithWorkspaceContext(root, configurationGlobsWithoutPlugins(root));
|
||||
const projectGlobPatterns = configurationGlobs(plugins);
|
||||
return globWithWorkspaceContext(root, projectGlobPatterns);
|
||||
}
|
||||
|
||||
const projectsWithoutPluginCache = new Map<
|
||||
@ -216,7 +207,8 @@ export async function retrieveProjectConfigurationsWithoutPluginInference(
|
||||
root: string
|
||||
): Promise<Record<string, ProjectConfiguration>> {
|
||||
const nxJson = readNxJson(root);
|
||||
const projectGlobPatterns = configurationGlobsWithoutPlugins(root);
|
||||
const plugins = await getDefaultPlugins(root);
|
||||
const projectGlobPatterns = retrieveProjectConfigurationPaths(root, plugins);
|
||||
const cacheKey = root + ',' + projectGlobPatterns.join(',');
|
||||
|
||||
if (projectsWithoutPluginCache.has(cacheKey)) {
|
||||
@ -302,12 +294,8 @@ export async function createProjectConfigurations(
|
||||
};
|
||||
}
|
||||
|
||||
export function configurationGlobs(
|
||||
workspaceRoot: string,
|
||||
plugins: LoadedNxPlugin[]
|
||||
): string[] {
|
||||
const globPatterns: string[] =
|
||||
configurationGlobsWithoutPlugins(workspaceRoot);
|
||||
export function configurationGlobs(plugins: LoadedNxPlugin[]): string[] {
|
||||
const globPatterns = [];
|
||||
for (const { plugin } of plugins) {
|
||||
if (plugin.createNodes) {
|
||||
globPatterns.push(plugin.createNodes[0]);
|
||||
@ -315,11 +303,3 @@ export function configurationGlobs(
|
||||
}
|
||||
return globPatterns;
|
||||
}
|
||||
|
||||
function configurationGlobsWithoutPlugins(workspaceRoot: string): string[] {
|
||||
return [
|
||||
'project.json',
|
||||
'**/project.json',
|
||||
...getGlobPatternsFromPackageManagerWorkspaces(workspaceRoot),
|
||||
];
|
||||
}
|
||||
|
||||
@ -1,25 +1,10 @@
|
||||
import { getNxPackageJsonWorkspacesPlugin } from '../../plugins/package-json-workspaces';
|
||||
import {
|
||||
NxAngularJsonPlugin,
|
||||
shouldMergeAngularProjects,
|
||||
} from '../adapter/angular-json';
|
||||
import { NxJsonConfiguration, PluginConfiguration } from '../config/nx-json';
|
||||
import { shouldMergeAngularProjects } from '../adapter/angular-json';
|
||||
import { ProjectGraphProcessor } from '../config/project-graph';
|
||||
import {
|
||||
ProjectConfiguration,
|
||||
TargetConfiguration,
|
||||
} from '../config/workspace-json-project-json';
|
||||
import { TargetConfiguration } from '../config/workspace-json-project-json';
|
||||
import { CreatePackageJsonProjectsNextToProjectJson } from '../plugins/project-json/build-nodes/package-json-next-to-project-json';
|
||||
import { CreateProjectJsonProjectsPlugin } from '../plugins/project-json/build-nodes/project-json';
|
||||
import { retrieveProjectConfigurationsWithoutPluginInference } from '../project-graph/utils/retrieve-workspace-files';
|
||||
import { getNxRequirePaths } from './installation-directory';
|
||||
import {
|
||||
ensurePluginIsV2,
|
||||
getPluginPathAndName,
|
||||
LoadedNxPlugin,
|
||||
nxPluginCache,
|
||||
NxPluginV2,
|
||||
} from './nx-plugin';
|
||||
import { workspaceRoot } from './workspace-root';
|
||||
import { LoadedNxPlugin, NxPluginV2 } from './nx-plugin';
|
||||
|
||||
/**
|
||||
* @deprecated Add targets to the projects in a {@link CreateNodes} function instead. This will be removed in Nx 18
|
||||
@ -55,11 +40,15 @@ export type NxPluginV1 = {
|
||||
* @todo(@agentender) v18: Remove this fn when we remove readWorkspaceConfig
|
||||
*/
|
||||
export function getDefaultPluginsSync(root: string): LoadedNxPlugin[] {
|
||||
const plugins: NxPluginV2[] = [require('../plugins/js')];
|
||||
const plugins: NxPluginV2[] = [
|
||||
require('../plugins/js'),
|
||||
...(shouldMergeAngularProjects(root, false)
|
||||
? [require('../adapter/angular-json').NxAngularJsonPlugin]
|
||||
: []),
|
||||
getNxPackageJsonWorkspacesPlugin(root),
|
||||
CreateProjectJsonProjectsPlugin,
|
||||
];
|
||||
|
||||
if (shouldMergeAngularProjects(root, false)) {
|
||||
plugins.push(require('../adapter/angular-json').NxAngularJsonPlugin);
|
||||
}
|
||||
return plugins.map((p) => ({
|
||||
plugin: p,
|
||||
}));
|
||||
|
||||
@ -41,11 +41,6 @@ import { shouldMergeAngularProjects } from '../adapter/angular-json';
|
||||
import { getNxPackageJsonWorkspacesPlugin } from '../../plugins/package-json-workspaces';
|
||||
import { CreateProjectJsonProjectsPlugin } from '../plugins/project-json/build-nodes/project-json';
|
||||
import { CreatePackageJsonProjectsNextToProjectJson } from '../plugins/project-json/build-nodes/package-json-next-to-project-json';
|
||||
import {
|
||||
mergeProjectConfigurationIntoRootMap,
|
||||
readProjectConfigurationsFromRootMap,
|
||||
} from '../project-graph/utils/project-configuration-utils';
|
||||
import { globWithWorkspaceContext } from './workspace-context';
|
||||
import { retrieveProjectConfigurationsWithoutPluginInference } from '../project-graph/utils/retrieve-workspace-files';
|
||||
|
||||
/**
|
||||
@ -64,17 +59,7 @@ export type CreateNodesFunction<T = unknown> = (
|
||||
projectConfigurationFile: string,
|
||||
options: T | undefined,
|
||||
context: CreateNodesContext
|
||||
) => CreateNodesResult;
|
||||
|
||||
/**
|
||||
* A function which parses a configuration file into a set of nodes.
|
||||
* Used for creating nodes for the {@link ProjectGraph}
|
||||
*/
|
||||
export type CreateNodesFunctionAsync<T = unknown> = (
|
||||
projectConfigurationFile: string,
|
||||
options: T | undefined,
|
||||
context: CreateNodesContext
|
||||
) => Promise<CreateNodesResult>;
|
||||
) => CreateNodesResult | Promise<CreateNodesResult>;
|
||||
|
||||
export interface CreateNodesResult {
|
||||
/**
|
||||
@ -96,11 +81,6 @@ export type CreateNodes<T = unknown> = readonly [
|
||||
createNodesFunction: CreateNodesFunction<T>
|
||||
];
|
||||
|
||||
export type CreateNodesAsync<T = unknown> = readonly [
|
||||
projectFilePattern: string,
|
||||
createNodesFunction: CreateNodesFunctionAsync<T>
|
||||
];
|
||||
|
||||
/**
|
||||
* Context for {@link CreateDependencies}
|
||||
*/
|
||||
@ -145,19 +125,14 @@ export type CreateDependencies<T = unknown> = (
|
||||
/**
|
||||
* A plugin for Nx which creates nodes and dependencies for the {@link ProjectGraph}
|
||||
*/
|
||||
export type NxPluginV2<
|
||||
TOptions = unknown,
|
||||
TCreateNodes extends CreateNodes<TOptions> | CreateNodesAsync<TOptions> =
|
||||
| CreateNodes<TOptions>
|
||||
| CreateNodesAsync<TOptions>
|
||||
> = {
|
||||
export type NxPluginV2<TOptions = unknown> = {
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Provides a file pattern and function that retrieves configuration info from
|
||||
* those files. e.g. { '**\/*.csproj': buildProjectsFromCsProjFile }
|
||||
*/
|
||||
createNodes?: TCreateNodes;
|
||||
createNodes?: CreateNodes;
|
||||
|
||||
// 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?
|
||||
/**
|
||||
@ -248,7 +223,7 @@ export async function loadNxPluginAsync(
|
||||
if (pluginModule) {
|
||||
return { plugin: pluginModule, options };
|
||||
}
|
||||
|
||||
performance.mark(`Load Nx Plugin: ${moduleName} - start`);
|
||||
let { pluginPath, name } = await getPluginPathAndName(
|
||||
moduleName,
|
||||
paths,
|
||||
@ -260,6 +235,12 @@ export async function loadNxPluginAsync(
|
||||
);
|
||||
plugin.name ??= name;
|
||||
nxPluginCache.set(moduleName, plugin);
|
||||
performance.mark(`Load Nx Plugin: ${moduleName} - end`);
|
||||
performance.measure(
|
||||
`Load Nx Plugin: ${moduleName}`,
|
||||
`Load Nx Plugin: ${moduleName} - start`,
|
||||
`Load Nx Plugin: ${moduleName} - end`
|
||||
);
|
||||
return { plugin, options };
|
||||
}
|
||||
|
||||
@ -269,7 +250,9 @@ export async function loadNxPlugins(
|
||||
root = workspaceRoot,
|
||||
projects?: Record<string, ProjectConfiguration>
|
||||
): Promise<LoadedNxPlugin[]> {
|
||||
const result: LoadedNxPlugin[] = [...(await getDefaultPlugins(root))];
|
||||
const result: LoadedNxPlugin[] = [
|
||||
{ plugin: CreatePackageJsonProjectsNextToProjectJson },
|
||||
];
|
||||
|
||||
// When loading plugins for `createNodes`, we don't know what projects exist yet.
|
||||
projects ??= await retrieveProjectConfigurationsWithoutPluginInference(root);
|
||||
@ -281,10 +264,7 @@ export async function loadNxPlugins(
|
||||
}
|
||||
|
||||
// We push the nx core node plugins onto the end, s.t. it overwrites any other plugins
|
||||
result.push(
|
||||
{ plugin: getNxPackageJsonWorkspacesPlugin(root) },
|
||||
{ plugin: CreateProjectJsonProjectsPlugin }
|
||||
);
|
||||
result.push(...(await getDefaultPlugins(root)));
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -515,17 +495,22 @@ function readPluginMainFromProjectConfiguration(
|
||||
return main;
|
||||
}
|
||||
|
||||
async function getDefaultPlugins(root: string): Promise<LoadedNxPlugin[]> {
|
||||
export async function getDefaultPlugins(
|
||||
root: string
|
||||
): Promise<LoadedNxPlugin[]> {
|
||||
const plugins: NxPluginV2[] = [
|
||||
CreatePackageJsonProjectsNextToProjectJson,
|
||||
await import('../plugins/js'),
|
||||
...(shouldMergeAngularProjects(root, false)
|
||||
? [
|
||||
await import('../adapter/angular-json').then(
|
||||
(m) => m.NxAngularJsonPlugin
|
||||
),
|
||||
]
|
||||
: []),
|
||||
getNxPackageJsonWorkspacesPlugin(root),
|
||||
CreateProjectJsonProjectsPlugin,
|
||||
];
|
||||
|
||||
if (shouldMergeAngularProjects(root, false)) {
|
||||
plugins.push(
|
||||
await import('../adapter/angular-json').then((m) => m.NxAngularJsonPlugin)
|
||||
);
|
||||
}
|
||||
return plugins.map((p) => ({
|
||||
plugin: p,
|
||||
}));
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'plugin',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html', 'json'],
|
||||
globals: {},
|
||||
displayName: 'react-native',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'react',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'rollup',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html', 'json'],
|
||||
globals: {},
|
||||
displayName: 'storybook',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'tao',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'web',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'webpack',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -6,6 +6,5 @@ export default {
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||
globals: {},
|
||||
displayName: 'workspace',
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
export default {
|
||||
displayName: 'tools-documentation-create-embeddings',
|
||||
preset: './jest.preset.js',
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
'^.+\\.(ts|tsx|js|jsx|mts|mjs)$': [
|
||||
'ts-jest',
|
||||
|
||||
@ -12,6 +12,5 @@ export default {
|
||||
],
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
testEnvironment: 'node',
|
||||
preset: '../../jest.preset.js',
|
||||
};
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
"emitDecoratorMetadata": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["node", "jest"],
|
||||
"lib": ["ES2021"],
|
||||
"lib": ["ES2022"],
|
||||
"declaration": true,
|
||||
"resolveJsonModule": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user