diff --git a/docs/generated/devkit/README.md b/docs/generated/devkit/README.md index c2dc580fd2e2c..65b3ec6554281 100644 --- a/docs/generated/devkit/README.md +++ b/docs/generated/devkit/README.md @@ -123,6 +123,7 @@ It only uses language primitives and immutable objects - [getProjects](../../devkit/documents/getProjects) - [getWorkspaceLayout](../../devkit/documents/getWorkspaceLayout) - [glob](../../devkit/documents/glob) +- [globAsync](../../devkit/documents/globAsync) - [hashArray](../../devkit/documents/hashArray) - [installPackagesTask](../../devkit/documents/installPackagesTask) - [isWorkspacesEnabled](../../devkit/documents/isWorkspacesEnabled) diff --git a/docs/generated/devkit/glob.md b/docs/generated/devkit/glob.md index 08a29fcafbec7..fa9c895a72296 100644 --- a/docs/generated/devkit/glob.md +++ b/docs/generated/devkit/glob.md @@ -18,3 +18,7 @@ Paths should be unix-style with forward slashes. `string`[] Normalized paths in the workspace that match the provided glob patterns. + +**`Deprecated`** + +Use [globAsync](../../devkit/documents/globAsync) instead. diff --git a/docs/generated/devkit/globAsync.md b/docs/generated/devkit/globAsync.md new file mode 100644 index 0000000000000..6f1f766258ab0 --- /dev/null +++ b/docs/generated/devkit/globAsync.md @@ -0,0 +1,20 @@ +# Function: globAsync + +▸ **globAsync**(`tree`, `patterns`): `Promise`\<`string`[]\> + +Performs a tree-aware glob search on the files in a workspace. Able to find newly +created files and hides deleted files before the updates are committed to disk. +Paths should be unix-style with forward slashes. + +#### Parameters + +| Name | Type | Description | +| :--------- | :------------------------------------ | :---------------------- | +| `tree` | [`Tree`](../../devkit/documents/Tree) | The file system tree | +| `patterns` | `string`[] | A list of glob patterns | + +#### Returns + +`Promise`\<`string`[]\> + +Normalized paths in the workspace that match the provided glob patterns. diff --git a/docs/generated/packages/devkit/documents/nx_devkit.md b/docs/generated/packages/devkit/documents/nx_devkit.md index c2dc580fd2e2c..65b3ec6554281 100644 --- a/docs/generated/packages/devkit/documents/nx_devkit.md +++ b/docs/generated/packages/devkit/documents/nx_devkit.md @@ -123,6 +123,7 @@ It only uses language primitives and immutable objects - [getProjects](../../devkit/documents/getProjects) - [getWorkspaceLayout](../../devkit/documents/getWorkspaceLayout) - [glob](../../devkit/documents/glob) +- [globAsync](../../devkit/documents/globAsync) - [hashArray](../../devkit/documents/hashArray) - [installPackagesTask](../../devkit/documents/installPackagesTask) - [isWorkspacesEnabled](../../devkit/documents/isWorkspacesEnabled) diff --git a/packages/cypress/src/plugins/plugin.ts b/packages/cypress/src/plugins/plugin.ts index 1151907965abf..5313637d35abc 100644 --- a/packages/cypress/src/plugins/plugin.ts +++ b/packages/cypress/src/plugins/plugin.ts @@ -17,11 +17,12 @@ import { getLockFileName } from '@nx/js'; import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs'; import { existsSync, readdirSync } from 'fs'; -import { globWithWorkspaceContext } from 'nx/src/utils/workspace-context'; + import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes'; import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory'; import { NX_PLUGIN_OPTIONS } from '../utils/constants'; import { loadConfigFile } from '@nx/devkit/src/utils/config-utils'; +import { globWithWorkspaceContext } from 'nx/src/utils/workspace-context'; export interface CypressPluginOptions { ciTargetName?: string; @@ -65,9 +66,12 @@ export const createNodes: CreateNodes = [ return {}; } - const hash = calculateHashForCreateNodes(projectRoot, options, context, [ - getLockFileName(detectPackageManager(context.workspaceRoot)), - ]); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); targetsCache[hash] ??= await buildCypressTargets( configFilePath, @@ -205,8 +209,7 @@ async function buildCypressTargets( : Array.isArray(cypressConfig.e2e.excludeSpecPattern) ? cypressConfig.e2e.excludeSpecPattern.map((p) => join(projectRoot, p)) : [join(projectRoot, cypressConfig.e2e.excludeSpecPattern)]; - const specFiles = globWithWorkspaceContext( - context.workspaceRoot, + const specFiles = await globWithWorkspaceContext( specPatterns, excludeSpecPatterns ); diff --git a/packages/detox/src/plugins/plugin.ts b/packages/detox/src/plugins/plugin.ts index 3873b3e0b5ca9..cfe03e75a826a 100644 --- a/packages/detox/src/plugins/plugin.ts +++ b/packages/detox/src/plugins/plugin.ts @@ -42,7 +42,7 @@ export const createDependencies: CreateDependencies = () => { export const createNodes: CreateNodes = [ '**/{detox.config,.detoxrc}.{json,js}', - (configFilePath, options, context) => { + async (configFilePath, options, context) => { options = normalizeOptions(options); const projectRoot = dirname(configFilePath); @@ -52,9 +52,12 @@ export const createNodes: CreateNodes = [ return {}; } - const hash = calculateHashForCreateNodes(projectRoot, options, context, [ - getLockFileName(detectPackageManager(context.workspaceRoot)), - ]); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); targetsCache[hash] ??= buildDetoxTargets(projectRoot, options, context); diff --git a/packages/devkit/src/utils/calculate-hash-for-create-nodes.ts b/packages/devkit/src/utils/calculate-hash-for-create-nodes.ts index 641bc52bbd4c2..45b8779f9b286 100644 --- a/packages/devkit/src/utils/calculate-hash-for-create-nodes.ts +++ b/packages/devkit/src/utils/calculate-hash-for-create-nodes.ts @@ -3,14 +3,14 @@ import { CreateNodesContext, hashArray } from 'nx/src/devkit-exports'; import { hashObject, hashWithWorkspaceContext } from 'nx/src/devkit-internals'; -export function calculateHashForCreateNodes( +export async function calculateHashForCreateNodes( projectRoot: string, options: object, context: CreateNodesContext, additionalGlobs: string[] = [] -): string { +): Promise { return hashArray([ - hashWithWorkspaceContext(context.workspaceRoot, [ + await hashWithWorkspaceContext(context.workspaceRoot, [ join(projectRoot, '**/*'), ...additionalGlobs, ]), diff --git a/packages/eslint/src/plugins/plugin.spec.ts b/packages/eslint/src/plugins/plugin.spec.ts index db7a928423dfb..b84470d2610d9 100644 --- a/packages/eslint/src/plugins/plugin.spec.ts +++ b/packages/eslint/src/plugins/plugin.spec.ts @@ -1,3 +1,21 @@ +import 'nx/src/internal-testing-utils/mock-fs'; + +let fsRoot: string = ''; + +jest.mock( + 'nx/src/utils/globs', + (): Partial => { + const glob: typeof import('fast-glob') = require('fast-glob'); + return { + ...jest.requireActual('nx/src/utils/globs'), + globAsync(patterns: string[]) { + // This glob will operate on memfs thanks to 'nx/src/internal-testing-utils/mock-fs' + return glob(patterns, { cwd: fsRoot }); + }, + }; + } +); + import { CreateNodesContext } from '@nx/devkit'; import { minimatch } from 'minimatch'; import { TempFs } from 'nx/src/internal-testing-utils/temp-fs'; diff --git a/packages/eslint/src/plugins/plugin.ts b/packages/eslint/src/plugins/plugin.ts index 9fc77d68214f9..dcd503e9eb8e6 100644 --- a/packages/eslint/src/plugins/plugin.ts +++ b/packages/eslint/src/plugins/plugin.ts @@ -7,7 +7,7 @@ import { import { existsSync } from 'node:fs'; import { dirname, join, normalize, sep } from 'node:path'; import { combineGlobPatterns } from 'nx/src/utils/globs'; -import { globWithWorkspaceContext } from 'nx/src/utils/workspace-context'; +import { globAsync } from 'nx/src/utils/globs'; import { ESLINT_CONFIG_FILENAMES, baseEsLintConfigFile, @@ -51,8 +51,7 @@ export const createNodes: CreateNodes = [ } } - const projectFiles = globWithWorkspaceContext( - context.workspaceRoot, + const projectFiles = await globAsync( [ 'project.json', 'package.json', @@ -77,8 +76,7 @@ export const createNodes: CreateNodes = [ const nestedProjectRootPatterns = excludePatterns.slice(index + 1); // Ignore project roots where the project does not contain any lintable files - const lintableFiles = globWithWorkspaceContext( - context.workspaceRoot, + const lintableFiles = await globAsync( [join(childProjectRoot, `**/*.{${options.extensions.join(',')}}`)], // exclude nested eslint roots and nested project roots [...nestedEslintRootPatterns, ...nestedProjectRootPatterns] diff --git a/packages/expo/plugins/plugin.ts b/packages/expo/plugins/plugin.ts index d9f3b4bd812d2..7f7c7f70c7be3 100644 --- a/packages/expo/plugins/plugin.ts +++ b/packages/expo/plugins/plugin.ts @@ -72,9 +72,12 @@ export const createNodes: CreateNodes = [ return {}; } - const hash = calculateHashForCreateNodes(projectRoot, options, context, [ - getLockFileName(detectPackageManager(context.workspaceRoot)), - ]); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); targetsCache[hash] ??= buildExpoTargets(projectRoot, options, context); diff --git a/packages/gradle/src/plugin/nodes.ts b/packages/gradle/src/plugin/nodes.ts index 7e19b38cf2f49..d7ed78a8144a1 100644 --- a/packages/gradle/src/plugin/nodes.ts +++ b/packages/gradle/src/plugin/nodes.ts @@ -58,14 +58,14 @@ export function writeTargetsToCache() { export const createNodes: CreateNodes = [ '**/build.{gradle.kts,gradle}', - ( + async ( gradleFilePath, options: GradlePluginOptions | undefined, context: CreateNodesContext ) => { const projectRoot = dirname(gradleFilePath); - const hash = calculateHashForCreateNodes( + const hash = await calculateHashForCreateNodes( projectRoot, options ?? {}, context diff --git a/packages/jest/src/plugins/plugin.ts b/packages/jest/src/plugins/plugin.ts index 37ca2b6824b39..9815403ebb7ec 100644 --- a/packages/jest/src/plugins/plugin.ts +++ b/packages/jest/src/plugins/plugin.ts @@ -94,7 +94,11 @@ export const createNodes: CreateNodes = [ options = normalizeOptions(options); - const hash = calculateHashForCreateNodes(projectRoot, options, context); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context + ); targetsCache[hash] ??= await buildJestTargets( configFilePath, projectRoot, diff --git a/packages/js/src/plugins/typescript/plugin.ts b/packages/js/src/plugins/typescript/plugin.ts index 3c16473a0da11..1473c672351eb 100644 --- a/packages/js/src/plugins/typescript/plugin.ts +++ b/packages/js/src/plugins/typescript/plugin.ts @@ -76,7 +76,7 @@ export const PLUGIN_NAME = '@nx/js/typescript'; export const createNodes: CreateNodes = [ '**/tsconfig*.json', - (configFilePath, options, context) => { + async (configFilePath, options, context) => { const pluginOptions = normalizePluginOptions(options); const projectRoot = dirname(configFilePath); const fullConfigPath = joinPathFragments( @@ -101,7 +101,7 @@ export const createNodes: CreateNodes = [ return {}; } - const nodeHash = calculateHashForCreateNodes( + const nodeHash = await calculateHashForCreateNodes( projectRoot, pluginOptions, context, diff --git a/packages/next/src/plugins/plugin.ts b/packages/next/src/plugins/plugin.ts index 3bfa2b07caaf5..87de5aa084783 100644 --- a/packages/next/src/plugins/plugin.ts +++ b/packages/next/src/plugins/plugin.ts @@ -63,9 +63,12 @@ export const createNodes: CreateNodes = [ } options = normalizeOptions(options); - const hash = calculateHashForCreateNodes(projectRoot, options, context, [ - getLockFileName(detectPackageManager(context.workspaceRoot)), - ]); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); targetsCache[hash] ??= await buildNextTargets( configFilePath, diff --git a/packages/nuxt/src/plugins/plugin.ts b/packages/nuxt/src/plugins/plugin.ts index 922f2d81e60bd..c1614e50456d4 100644 --- a/packages/nuxt/src/plugins/plugin.ts +++ b/packages/nuxt/src/plugins/plugin.ts @@ -62,9 +62,12 @@ export const createNodes: CreateNodes = [ options = normalizeOptions(options); - const hash = calculateHashForCreateNodes(projectRoot, options, context, [ - getLockFileName(detectPackageManager(context.workspaceRoot)), - ]); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); targetsCache[hash] ??= await buildNuxtTargets( configFilePath, projectRoot, diff --git a/packages/nx/src/command-line/init/implementation/react/index.ts b/packages/nx/src/command-line/init/implementation/react/index.ts index 73b7c2360747b..a62a3e146528e 100644 --- a/packages/nx/src/command-line/init/implementation/react/index.ts +++ b/packages/nx/src/command-line/init/implementation/react/index.ts @@ -290,7 +290,7 @@ async function addBundler(options: NormalizedOptions) { options.isStandalone, options.appIsJs ); - renameJsToJsx(options.reactAppName, options.isStandalone); + await renameJsToJsx(options.reactAppName, options.isStandalone); } else { output.log({ title: '🧑‍🔧 Setting up craco + Webpack' }); const { addCracoCommandsToPackageScripts } = await import( diff --git a/packages/nx/src/command-line/init/implementation/react/rename-js-to-jsx.ts b/packages/nx/src/command-line/init/implementation/react/rename-js-to-jsx.ts index 7cef84c375ea8..7b86c034481c9 100644 --- a/packages/nx/src/command-line/init/implementation/react/rename-js-to-jsx.ts +++ b/packages/nx/src/command-line/init/implementation/react/rename-js-to-jsx.ts @@ -3,8 +3,8 @@ import { globWithWorkspaceContext } from '../../../../utils/workspace-context'; import { fileExists } from '../../../../utils/fileutils'; // Vite cannot process JSX like
or
unless the file is named .jsx or .tsx -export function renameJsToJsx(appName: string, isStandalone: boolean) { - const files = globWithWorkspaceContext(process.cwd(), [ +export async function renameJsToJsx(appName: string, isStandalone: boolean) { + const files = await globWithWorkspaceContext(process.cwd(), [ isStandalone ? 'src/**/*.js' : `apps/${appName}/src/**/*.js`, ]); diff --git a/packages/nx/src/command-line/init/init-v2.ts b/packages/nx/src/command-line/init/init-v2.ts index f7cf3ec2a36d4..b3834d56489a0 100644 --- a/packages/nx/src/command-line/init/init-v2.ts +++ b/packages/nx/src/command-line/init/init-v2.ts @@ -168,7 +168,7 @@ async function detectPlugins(): Promise<{ updatePackageScripts: boolean; }> { let files = ['package.json'].concat( - globWithWorkspaceContext(process.cwd(), ['**/*/package.json']) + await globWithWorkspaceContext(process.cwd(), ['**/*/package.json']) ); const detectedPlugins = new Set(); diff --git a/packages/nx/src/config/to-project-name.spec.ts b/packages/nx/src/config/to-project-name.spec.ts index bcc2dedffadf5..d8995c22c076f 100644 --- a/packages/nx/src/config/to-project-name.spec.ts +++ b/packages/nx/src/config/to-project-name.spec.ts @@ -42,7 +42,7 @@ describe('Workspaces', () => { readNxJson(fs.tempDir).plugins, fs.tempDir ); - const res = retrieveProjectConfigurations( + const res = await retrieveProjectConfigurations( plugins, fs.tempDir, readNxJson(fs.tempDir) diff --git a/packages/nx/src/daemon/client/client.ts b/packages/nx/src/daemon/client/client.ts index 3bd933e685b0a..0fb3fa08804af 100644 --- a/packages/nx/src/daemon/client/client.ts +++ b/packages/nx/src/daemon/client/client.ts @@ -30,10 +30,28 @@ import { ProjectGraphError, } from '../../project-graph/error-types'; import { loadRootEnvFiles } from '../../utils/dotenv'; +import { HandleGlobMessage } from '../message-types/glob'; +import { + GET_NX_WORKSPACE_FILES, + HandleNxWorkspaceFilesMessage, +} from '../message-types/get-nx-workspace-files'; +import { + GET_CONTEXT_FILE_DATA, + HandleContextFileDataMessage, +} from '../message-types/get-context-file-data'; +import { + GET_FILES_IN_DIRECTORY, + HandleGetFilesInDirectoryMessage, +} from '../message-types/get-files-in-directory'; +import { HASH_GLOB, HandleHashGlobMessage } from '../message-types/hash-glob'; +import { NxWorkspaceFiles } from '../../native'; const DAEMON_ENV_SETTINGS = { NX_PROJECT_GLOB_CACHE: 'false', NX_CACHE_PROJECTS_CONFIG: 'false', + + // Used to identify that the code is running in the daemon process. + NX_ON_DAEMON_PROCESS: 'true', }; export type UnregisterCallback = () => void; @@ -256,6 +274,54 @@ export class DaemonClient { }); } + glob(globs: string[], exclude?: string[]): Promise { + const message: HandleGlobMessage = { + type: 'GLOB', + globs, + exclude, + }; + return this.sendToDaemonViaQueue(message); + } + + getWorkspaceContextFileData( + globs: string[], + exclude?: string[] + ): Promise { + const message: HandleContextFileDataMessage = { + type: GET_CONTEXT_FILE_DATA, + globs, + exclude, + }; + return this.sendToDaemonViaQueue(message); + } + + getWorkspaceFiles( + projectRootMap: Record + ): Promise { + const message: HandleNxWorkspaceFilesMessage = { + type: GET_NX_WORKSPACE_FILES, + projectRootMap, + }; + return this.sendToDaemonViaQueue(message); + } + + getFilesInDirectory(dir: string): Promise { + const message: HandleGetFilesInDirectoryMessage = { + type: GET_FILES_IN_DIRECTORY, + dir, + }; + return this.sendToDaemonViaQueue(message); + } + + hashGlob(globs: string[], exclude?: string[]): Promise { + const message: HandleHashGlobMessage = { + type: HASH_GLOB, + globs, + exclude, + }; + return this.sendToDaemonViaQueue(message); + } + async isServerAvailable(): Promise { return new Promise((resolve) => { try { diff --git a/packages/nx/src/daemon/is-on-daemon.ts b/packages/nx/src/daemon/is-on-daemon.ts new file mode 100644 index 0000000000000..e105d3d292128 --- /dev/null +++ b/packages/nx/src/daemon/is-on-daemon.ts @@ -0,0 +1,3 @@ +export function isOnDaemon() { + return !!global.NX_DAEMON; +} diff --git a/packages/nx/src/daemon/message-types/get-context-file-data.ts b/packages/nx/src/daemon/message-types/get-context-file-data.ts new file mode 100644 index 0000000000000..c804b93eaf340 --- /dev/null +++ b/packages/nx/src/daemon/message-types/get-context-file-data.ts @@ -0,0 +1,18 @@ +export const GET_CONTEXT_FILE_DATA = 'GET_CONTEXT_FILE_DATA' as const; + +export type HandleContextFileDataMessage = { + type: typeof GET_CONTEXT_FILE_DATA; + globs: string[]; + exclude?: string[]; +}; + +export function isHandleContextFileDataMessage( + message: unknown +): message is HandleContextFileDataMessage { + return ( + typeof message === 'object' && + message !== null && + 'type' in message && + message['type'] === GET_CONTEXT_FILE_DATA + ); +} diff --git a/packages/nx/src/daemon/message-types/get-files-in-directory.ts b/packages/nx/src/daemon/message-types/get-files-in-directory.ts new file mode 100644 index 0000000000000..022a2f8756622 --- /dev/null +++ b/packages/nx/src/daemon/message-types/get-files-in-directory.ts @@ -0,0 +1,17 @@ +export const GET_FILES_IN_DIRECTORY = 'GET_FILES_IN_DIRECTORY' as const; + +export type HandleGetFilesInDirectoryMessage = { + type: typeof GET_FILES_IN_DIRECTORY; + dir: string; +}; + +export function isHandleGetFilesInDirectoryMessage( + message: unknown +): message is HandleGetFilesInDirectoryMessage { + return ( + typeof message === 'object' && + message !== null && + 'type' in message && + message['type'] === GET_FILES_IN_DIRECTORY + ); +} diff --git a/packages/nx/src/daemon/message-types/get-nx-workspace-files.ts b/packages/nx/src/daemon/message-types/get-nx-workspace-files.ts new file mode 100644 index 0000000000000..872157b091f9e --- /dev/null +++ b/packages/nx/src/daemon/message-types/get-nx-workspace-files.ts @@ -0,0 +1,17 @@ +export const GET_NX_WORKSPACE_FILES = 'GET_NX_WORKSPACE_FILES' as const; + +export type HandleNxWorkspaceFilesMessage = { + type: typeof GET_NX_WORKSPACE_FILES; + projectRootMap: Record; +}; + +export function isHandleNxWorkspaceFilesMessage( + message: unknown +): message is HandleNxWorkspaceFilesMessage { + return ( + typeof message === 'object' && + message !== null && + 'type' in message && + message['type'] === GET_NX_WORKSPACE_FILES + ); +} diff --git a/packages/nx/src/daemon/message-types/glob.ts b/packages/nx/src/daemon/message-types/glob.ts new file mode 100644 index 0000000000000..50fd3071cdded --- /dev/null +++ b/packages/nx/src/daemon/message-types/glob.ts @@ -0,0 +1,18 @@ +export const GLOB = 'GLOB' as const; + +export type HandleGlobMessage = { + type: typeof GLOB; + globs: string[]; + exclude?: string[]; +}; + +export function isHandleGlobMessage( + message: unknown +): message is HandleGlobMessage { + return ( + typeof message === 'object' && + message !== null && + 'type' in message && + message['type'] === GLOB + ); +} diff --git a/packages/nx/src/daemon/message-types/hash-glob.ts b/packages/nx/src/daemon/message-types/hash-glob.ts new file mode 100644 index 0000000000000..9bec1f566c14c --- /dev/null +++ b/packages/nx/src/daemon/message-types/hash-glob.ts @@ -0,0 +1,18 @@ +export const HASH_GLOB = 'HASH_GLOB' as const; + +export type HandleHashGlobMessage = { + type: typeof HASH_GLOB; + globs: string[]; + exclude?: string[]; +}; + +export function isHandleHashGlobMessage( + message: unknown +): message is HandleHashGlobMessage { + return ( + typeof message === 'object' && + message !== null && + 'type' in message && + message['type'] === HASH_GLOB + ); +} diff --git a/packages/nx/src/daemon/message-types/update-context-files.ts b/packages/nx/src/daemon/message-types/update-context-files.ts new file mode 100644 index 0000000000000..42eecea94040e --- /dev/null +++ b/packages/nx/src/daemon/message-types/update-context-files.ts @@ -0,0 +1,18 @@ +export const GLOB = 'GLOB' as const; + +export type HandleUpdateContextMessage = { + type: typeof GLOB; + updatedFiles: string[]; + deletedFiles: string[]; +}; + +export function isHandleUpdateContextMessage( + message: unknown +): message is HandleUpdateContextMessage { + return ( + typeof message === 'object' && + message !== null && + 'type' in message && + message['type'] === GLOB + ); +} diff --git a/packages/nx/src/daemon/server/handle-context-file-data.ts b/packages/nx/src/daemon/server/handle-context-file-data.ts new file mode 100644 index 0000000000000..24d9243d45c2a --- /dev/null +++ b/packages/nx/src/daemon/server/handle-context-file-data.ts @@ -0,0 +1,11 @@ +import { getAllFileDataInContext } from '../../utils/workspace-context'; +import { workspaceRoot } from '../../utils/workspace-root'; +import { HandlerResult } from './server'; + +export async function handleContextFileData(): Promise { + const files = getAllFileDataInContext(workspaceRoot); + return { + response: JSON.stringify(files), + description: 'handleContextFileData', + }; +} diff --git a/packages/nx/src/daemon/server/handle-get-files-in-directory.ts b/packages/nx/src/daemon/server/handle-get-files-in-directory.ts new file mode 100644 index 0000000000000..aa781ab77980b --- /dev/null +++ b/packages/nx/src/daemon/server/handle-get-files-in-directory.ts @@ -0,0 +1,13 @@ +import { getFilesInDirectoryUsingContext } from '../../utils/workspace-context'; +import { workspaceRoot } from '../../utils/workspace-root'; +import { HandlerResult } from './server'; + +export async function handleGetFilesInDirectory( + dir: string +): Promise { + const files = getFilesInDirectoryUsingContext(workspaceRoot, dir); + return { + response: JSON.stringify(files), + description: 'handleNxWorkspaceFiles', + }; +} diff --git a/packages/nx/src/daemon/server/handle-glob.ts b/packages/nx/src/daemon/server/handle-glob.ts new file mode 100644 index 0000000000000..c163a33194b52 --- /dev/null +++ b/packages/nx/src/daemon/server/handle-glob.ts @@ -0,0 +1,14 @@ +import { workspaceRoot } from '../../utils/workspace-root'; +import { globWithWorkspaceContext } from '../../utils/workspace-context'; +import { HandlerResult } from './server'; + +export async function handleGlob( + globs: string[], + exclude?: string[] +): Promise { + const files = await globWithWorkspaceContext(workspaceRoot, globs, exclude); + return { + response: JSON.stringify(files), + description: 'handleGlob', + }; +} diff --git a/packages/nx/src/daemon/server/handle-hash-glob.ts b/packages/nx/src/daemon/server/handle-hash-glob.ts new file mode 100644 index 0000000000000..1c283005f31ce --- /dev/null +++ b/packages/nx/src/daemon/server/handle-hash-glob.ts @@ -0,0 +1,14 @@ +import { workspaceRoot } from '../../utils/workspace-root'; +import { hashWithWorkspaceContext } from '../../utils/workspace-context'; +import { HandlerResult } from './server'; + +export async function handleHashGlob( + globs: string[], + exclude?: string[] +): Promise { + const files = await hashWithWorkspaceContext(workspaceRoot, globs, exclude); + return { + response: JSON.stringify(files), + description: 'handleHashGlob', + }; +} diff --git a/packages/nx/src/daemon/server/handle-nx-workspace-files.ts b/packages/nx/src/daemon/server/handle-nx-workspace-files.ts new file mode 100644 index 0000000000000..c4a8c03b04025 --- /dev/null +++ b/packages/nx/src/daemon/server/handle-nx-workspace-files.ts @@ -0,0 +1,16 @@ +import { getNxWorkspaceFilesFromContext } from '../../utils/workspace-context'; +import { workspaceRoot } from '../../utils/workspace-root'; +import { HandlerResult } from './server'; + +export async function handleNxWorkspaceFiles( + projectRootMap: Record +): Promise { + const files = await getNxWorkspaceFilesFromContext( + workspaceRoot, + projectRootMap + ); + return { + response: JSON.stringify(files), + description: 'handleNxWorkspaceFiles', + }; +} diff --git a/packages/nx/src/daemon/server/server.ts b/packages/nx/src/daemon/server/server.ts index c648f0d1cf838..6310c497c372d 100644 --- a/packages/nx/src/daemon/server/server.ts +++ b/packages/nx/src/daemon/server/server.ts @@ -52,11 +52,32 @@ import { watchOutputFiles, watchWorkspace, } from './watcher'; +import { handleGlob } from './handle-glob'; +import { GLOB, isHandleGlobMessage } from '../message-types/glob'; +import { + GET_NX_WORKSPACE_FILES, + isHandleNxWorkspaceFilesMessage, +} from '../message-types/get-nx-workspace-files'; +import { handleNxWorkspaceFiles } from './handle-nx-workspace-files'; +import { + GET_CONTEXT_FILE_DATA, + isHandleContextFileDataMessage, +} from '../message-types/get-context-file-data'; +import { handleContextFileData } from './handle-context-file-data'; +import { + GET_FILES_IN_DIRECTORY, + isHandleGetFilesInDirectoryMessage, +} from '../message-types/get-files-in-directory'; +import { handleGetFilesInDirectory } from './handle-get-files-in-directory'; +import { HASH_GLOB, isHandleHashGlobMessage } from '../message-types/hash-glob'; +import { handleHashGlob } from './handle-hash-glob'; let performanceObserver: PerformanceObserver | undefined; let workspaceWatcherError: Error | undefined; let outputsWatcherError: Error | undefined; +global.NX_DAEMON = true; + export type HandlerResult = { description: string; error?: any; @@ -165,6 +186,26 @@ async function handleMessage(socket, data: string) { ); } else if (payload.type === 'REGISTER_FILE_WATCHER') { registeredFileWatcherSockets.push({ socket, config: payload.config }); + } else if (isHandleGlobMessage(payload)) { + await handleResult(socket, GLOB, () => + handleGlob(payload.globs, payload.exclude) + ); + } else if (isHandleNxWorkspaceFilesMessage(payload)) { + await handleResult(socket, GET_NX_WORKSPACE_FILES, () => + handleNxWorkspaceFiles(payload.projectRootMap) + ); + } else if (isHandleGetFilesInDirectoryMessage(payload)) { + await handleResult(socket, GET_FILES_IN_DIRECTORY, () => + handleGetFilesInDirectory(payload.dir) + ); + } else if (isHandleContextFileDataMessage(payload)) { + await handleResult(socket, GET_CONTEXT_FILE_DATA, () => + handleContextFileData() + ); + } else if (isHandleHashGlobMessage(payload)) { + await handleResult(socket, HASH_GLOB, () => + handleHashGlob(payload.globs, payload.exclude) + ); } else { await respondWithErrorAndExit( socket, diff --git a/packages/nx/src/devkit-exports.ts b/packages/nx/src/devkit-exports.ts index 8e5d7dcffe7e0..f8e454543e519 100644 --- a/packages/nx/src/devkit-exports.ts +++ b/packages/nx/src/devkit-exports.ts @@ -124,7 +124,7 @@ export { /** * @category Generators */ -export { glob } from './generators/utils/glob'; +export { glob, globAsync } from './generators/utils/glob'; /** * @category Generators diff --git a/packages/nx/src/generators/utils/glob.ts b/packages/nx/src/generators/utils/glob.ts index a3920fef4bf36..c97daccded69e 100644 --- a/packages/nx/src/generators/utils/glob.ts +++ b/packages/nx/src/generators/utils/glob.ts @@ -1,7 +1,10 @@ import { minimatch } from 'minimatch'; import { Tree } from '../tree'; import { combineGlobPatterns } from '../../utils/globs'; -import { globWithWorkspaceContext } from '../../utils/workspace-context'; +import { + globWithWorkspaceContext, + globWithWorkspaceContextSync, +} from '../../utils/workspace-context'; /** * Performs a tree-aware glob search on the files in a workspace. Able to find newly @@ -11,9 +14,42 @@ import { globWithWorkspaceContext } from '../../utils/workspace-context'; * @param tree The file system tree * @param patterns A list of glob patterns * @returns Normalized paths in the workspace that match the provided glob patterns. + * @deprecated Use {@link globAsync} instead. */ export function glob(tree: Tree, patterns: string[]): string[] { - const matches = new Set(globWithWorkspaceContext(tree.root, patterns)); + return combineGlobResultsWithTree( + tree, + patterns, + globWithWorkspaceContextSync(tree.root, patterns) + ); +} + +/** + * Performs a tree-aware glob search on the files in a workspace. Able to find newly + * created files and hides deleted files before the updates are committed to disk. + * Paths should be unix-style with forward slashes. + * + * @param tree The file system tree + * @param patterns A list of glob patterns + * @returns Normalized paths in the workspace that match the provided glob patterns. + */ +export async function globAsync( + tree: Tree, + patterns: string[] +): Promise { + return combineGlobResultsWithTree( + tree, + patterns, + await globWithWorkspaceContext(tree.root, patterns) + ); +} + +function combineGlobResultsWithTree( + tree: Tree, + patterns: string[], + results: string[] +) { + const matches = new Set(results); const combinedGlob = combineGlobPatterns(patterns); const matcher = minimatch.makeRe(combinedGlob); diff --git a/packages/nx/src/generators/utils/project-configuration.ts b/packages/nx/src/generators/utils/project-configuration.ts index 1992d6d2e886a..52fde37740f54 100644 --- a/packages/nx/src/generators/utils/project-configuration.ts +++ b/packages/nx/src/generators/utils/project-configuration.ts @@ -4,12 +4,8 @@ import { basename, join, relative } from 'path'; import { buildProjectConfigurationFromPackageJson, getGlobPatternsFromPackageManagerWorkspaces, - createNodes as packageJsonWorkspacesCreateNodes, } from '../../plugins/package-json-workspaces'; -import { - buildProjectFromProjectJson, - ProjectJsonProjectsPlugin, -} from '../../plugins/project-json/build-nodes/project-json'; +import { buildProjectFromProjectJson } from '../../plugins/project-json/build-nodes/project-json'; import { renamePropertyWithStableKeys } from '../../adapter/angular-json'; import { ProjectConfiguration, @@ -19,8 +15,7 @@ import { mergeProjectConfigurationIntoRootMap, readProjectConfigurationsFromRootMap, } from '../../project-graph/utils/project-configuration-utils'; -import { configurationGlobs } from '../../project-graph/utils/retrieve-workspace-files'; -import { globWithWorkspaceContext } from '../../utils/workspace-context'; +import { globWithWorkspaceContextSync } from '../../utils/workspace-context'; import { output } from '../../utils/output'; import { PackageJson } from '../../utils/package-json'; import { joinPathFragments, normalizePath } from '../../utils/path'; @@ -28,7 +23,6 @@ import { readJson, writeJson } from './json'; import { readNxJson } from './nx-json'; import type { Tree } from '../tree'; -import { NxPlugin } from '../../project-graph/plugins'; export { readNxJson, updateNxJson } from './nx-json'; @@ -200,7 +194,7 @@ function readAndCombineAllProjectConfigurations(tree: Tree): { readJson(tree, p, { expectComments: true }) ), ]; - const globbedFiles = globWithWorkspaceContext(tree.root, patterns); + const globbedFiles = globWithWorkspaceContextSync(tree.root, patterns); const createdFiles = findCreatedProjectFiles(tree, patterns); const deletedFiles = findDeletedProjectFiles(tree, patterns); const projectFiles = [...globbedFiles, ...createdFiles].filter( diff --git a/packages/nx/src/project-graph/file-map-utils.ts b/packages/nx/src/project-graph/file-map-utils.ts index 8ebed90d7144e..73d6eb9d795da 100644 --- a/packages/nx/src/project-graph/file-map-utils.ts +++ b/packages/nx/src/project-graph/file-map-utils.ts @@ -39,12 +39,7 @@ export async function createFileMapUsingProjectGraph( ): Promise { const configs = readProjectsConfigurationFromProjectGraph(graph); - let files: FileData[]; - if (daemonClient.enabled()) { - files = await daemonClient.getAllFileData(); - } else { - files = getAllFileDataInContext(workspaceRoot); - } + let files: FileData[] = await getAllFileDataInContext(workspaceRoot); return createFileMap(configs, files); } diff --git a/packages/nx/src/project-graph/file-utils.ts b/packages/nx/src/project-graph/file-utils.ts index 7107547ed9b4a..efba33e943feb 100644 --- a/packages/nx/src/project-graph/file-utils.ts +++ b/packages/nx/src/project-graph/file-utils.ts @@ -1,6 +1,6 @@ import { execSync } from 'child_process'; import { existsSync, readFileSync } from 'fs'; -import { extname, join, relative, sep } from 'path'; +import { basename, extname, join, relative, sep } from 'path'; import { readNxJson } from '../config/configuration'; import { FileData } from '../config/project-graph'; import { @@ -17,16 +17,18 @@ import { } from './project-graph'; import { toOldFormat } from '../adapter/angular-json'; import { getIgnoreObject } from '../utils/ignore'; -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 } from 'minimatch'; -import { CreateNodesResult } from '../devkit-exports'; -import { PackageJsonProjectsNextToProjectJsonPlugin } from '../plugins/project-json/build-nodes/package-json-next-to-project-json'; +import { + buildProjectConfigurationFromPackageJson, + getGlobPatternsFromPackageManagerWorkspaces, +} from '../plugins/package-json-workspaces'; +import { globWithWorkspaceContextSync } from '../utils/workspace-context'; +import { buildProjectFromProjectJson } from '../plugins/project-json/build-nodes/project-json'; +import { PackageJson } from '../utils/package-json'; +import { NxJsonConfiguration } from '../devkit-exports'; export interface Change { type: string; @@ -151,7 +153,7 @@ export function readWorkspaceConfig(opts: { } catch { configuration = { version: 2, - projects: getProjectsSyncNoInference(root, nxJson).projects, + projects: getProjectsSync(root, nxJson), }; } if (opts.format === 'angularCli') { @@ -179,50 +181,59 @@ export { FileData }; /** * TODO(v20): Remove this function. */ -function getProjectsSyncNoInference(root: string, nxJson: NxJsonConfiguration) { - const allConfigFiles = retrieveProjectConfigurationPaths( - root, - getDefaultPluginsSync(root) - ); - const plugins = [ - PackageJsonProjectsNextToProjectJsonPlugin, - ...getDefaultPluginsSync(root), +function getProjectsSync( + root: string, + nxJson: NxJsonConfiguration +): { + [name: string]: ProjectConfiguration; +} { + /** + * We can't update projects that come from plugins anyways, so we are going + * to ignore them for now. Plugins should add their own add/create/update methods + * if they would like to use devkit to update inferred projects. + */ + const patterns = [ + '**/project.json', + 'project.json', + ...getGlobPatternsFromPackageManagerWorkspaces(root, readJsonFile), ]; - - const projectRootMap: Record = {}; - - // We iterate over plugins first - this ensures that plugins specified first take precedence. - for (const plugin of plugins) { - const [pattern, createNodes] = plugin.createNodes ?? []; - if (!pattern) { - continue; - } - const matchingConfigFiles = allConfigFiles.filter((file) => - minimatch(file, pattern, { dot: true }) - ); - for (const file of matchingConfigFiles) { - if (minimatch(file, pattern, { dot: true })) { - let r = createNodes( - file, - {}, + const projectFiles = globWithWorkspaceContextSync(root, patterns); + + const rootMap: Record = {}; + for (const projectFile of projectFiles) { + if (basename(projectFile) === 'project.json') { + const json = readJsonFile(projectFile); + const config = buildProjectFromProjectJson(json, projectFile); + mergeProjectConfigurationIntoRootMap( + rootMap, + config, + undefined, + undefined, + true + ); + } else if (basename(projectFile) === 'package.json') { + const packageJson = readJsonFile(projectFile); + const config = buildProjectConfigurationFromPackageJson( + packageJson, + projectFile, + nxJson + ); + if (!rootMap[config.root]) { + mergeProjectConfigurationIntoRootMap( + rootMap, + // Inferred targets, tags, etc don't show up when running generators + // This is to help avoid running into issues when trying to update the workspace { - nxJsonConfiguration: nxJson, - workspaceRoot: root, - configFiles: matchingConfigFiles, - } - ) as CreateNodesResult; - for (const node in r.projects) { - const project = { - root: node, - ...r.projects[node], - }; - mergeProjectConfigurationIntoRootMap(projectRootMap, project); - } + name: config.name, + root: config.root, + }, + undefined, + undefined, + true + ); } } } - return { - projects: readProjectConfigurationsFromRootMap(projectRootMap), - }; + return readProjectConfigurationsFromRootMap(rootMap); } diff --git a/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts b/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts index 221aefd323cfc..64a86e394bbda 100644 --- a/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts +++ b/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts @@ -28,17 +28,22 @@ export function loadRemoteNxPlugin( // but its typescript. const isWorkerTypescript = path.extname(__filename) === '.ts'; const workerPath = path.join(__dirname, 'plugin-worker'); + + const env: Record = { + ...process.env, + ...(isWorkerTypescript + ? { + // Ensures that the worker uses the same tsconfig as the main process + TS_NODE_PROJECT: path.join(__dirname, '../../../tsconfig.lib.json'), + } + : {}), + }; + + delete env.NX_ON_DAEMON_PROCESS; + const worker = fork(workerPath, [], { stdio: ['ignore', 'inherit', 'inherit', 'ipc'], - env: { - ...process.env, - ...(isWorkerTypescript - ? { - // Ensures that the worker uses the same tsconfig as the main process - TS_NODE_PROJECT: path.join(__dirname, '../../../tsconfig.lib.json'), - } - : {}), - }, + env, execArgv: [ ...process.execArgv, // If the worker is typescript, we need to register ts-node diff --git a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts index d61a11cef9a4b..d87792f1093fc 100644 --- a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts +++ b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts @@ -38,7 +38,7 @@ export async function retrieveWorkspaceFiles( performance.mark('get-workspace-files:start'); const { projectFileMap, globalFiles, externalReferences } = - getNxWorkspaceFilesFromContext(workspaceRoot, projectRootMap); + await getNxWorkspaceFilesFromContext(workspaceRoot, projectRootMap); performance.mark('get-workspace-files:end'); performance.measure( 'get-workspace-files', @@ -60,13 +60,16 @@ export async function retrieveWorkspaceFiles( * Walk through the workspace and return `ProjectConfigurations`. Only use this if the projectFileMap is not needed. */ -export function retrieveProjectConfigurations( +export async function retrieveProjectConfigurations( plugins: LoadedNxPlugin[], workspaceRoot: string, nxJson: NxJsonConfiguration ): Promise { const globPatterns = configurationGlobs(plugins); - const workspaceFiles = globWithWorkspaceContext(workspaceRoot, globPatterns); + const workspaceFiles = await globWithWorkspaceContext( + workspaceRoot, + globPatterns + ); return createProjectConfigurations( workspaceRoot, @@ -98,7 +101,11 @@ export async function retrieveProjectConfigurationsWithAngularProjects( workspaceRoot ); - const res = retrieveProjectConfigurations(plugins, workspaceRoot, nxJson); + const res = await retrieveProjectConfigurations( + plugins, + workspaceRoot, + nxJson + ); cleanup(); return res; } @@ -106,7 +113,7 @@ export async function retrieveProjectConfigurationsWithAngularProjects( export function retrieveProjectConfigurationPaths( root: string, plugins: Array<{ createNodes?: readonly [string, ...unknown[]] } & unknown> -): string[] { +): Promise { const projectGlobPatterns = configurationGlobs(plugins); return globWithWorkspaceContext(root, projectGlobPatterns); } @@ -122,7 +129,10 @@ export async function retrieveProjectConfigurationsWithoutPluginInference( ): Promise> { const nxJson = readNxJson(root); const [plugins, cleanup] = await loadNxPlugins([]); // only load default plugins - const projectGlobPatterns = retrieveProjectConfigurationPaths(root, plugins); + const projectGlobPatterns = await retrieveProjectConfigurationPaths( + root, + plugins + ); const cacheKey = root + ',' + projectGlobPatterns.join(','); if (projectsWithoutPluginCache.has(cacheKey)) { @@ -130,7 +140,7 @@ export async function retrieveProjectConfigurationsWithoutPluginInference( } const projectFiles = - globWithWorkspaceContext(root, projectGlobPatterns) ?? []; + (await globWithWorkspaceContext(root, projectGlobPatterns)) ?? []; const { projects } = await createProjectConfigurations( root, nxJson, diff --git a/packages/nx/src/utils/workspace-context.ts b/packages/nx/src/utils/workspace-context.ts index f45b3026234cb..9640965e758f3 100644 --- a/packages/nx/src/utils/workspace-context.ts +++ b/packages/nx/src/utils/workspace-context.ts @@ -1,6 +1,8 @@ import type { NxWorkspaceFilesExternals, WorkspaceContext } from '../native'; import { performance } from 'perf_hooks'; import { cacheDirectoryForWorkspace } from './cache-directory'; +import { isOnDaemon } from '../daemon/is-on-daemon'; +import { daemonClient } from '../daemon/client/client'; let workspaceContext: WorkspaceContext | undefined; @@ -20,15 +22,25 @@ export function setupWorkspaceContext(workspaceRoot: string) { ); } -export function getNxWorkspaceFilesFromContext( +export async function getNxWorkspaceFilesFromContext( workspaceRoot: string, projectRootMap: Record ) { - ensureContextAvailable(workspaceRoot); - return workspaceContext.getWorkspaceFiles(projectRootMap); + if (isOnDaemon() || !daemonClient.enabled()) { + ensureContextAvailable(workspaceRoot); + return workspaceContext.getWorkspaceFiles(projectRootMap); + } + return daemonClient.getWorkspaceFiles(projectRootMap); } -export function globWithWorkspaceContext( +/** + * Sync method to get files matching globs from workspace context. + * NOTE: This method will create the workspace context if it doesn't exist. + * It should only be used within Nx internal in code paths that **must** be sync. + * If used in an isolated plugin thread this will cause the workspace context + * to be recreated which is slow. + */ +export function globWithWorkspaceContextSync( workspaceRoot: string, globs: string[], exclude?: string[] @@ -37,13 +49,29 @@ export function globWithWorkspaceContext( return workspaceContext.glob(globs, exclude); } -export function hashWithWorkspaceContext( +export async function globWithWorkspaceContext( workspaceRoot: string, globs: string[], exclude?: string[] ) { - ensureContextAvailable(workspaceRoot); - return workspaceContext.hashFilesMatchingGlob(globs, exclude); + if (isOnDaemon() || !daemonClient.enabled()) { + ensureContextAvailable(workspaceRoot); + return workspaceContext.glob(globs, exclude); + } else { + return daemonClient.glob(globs, exclude); + } +} + +export async function hashWithWorkspaceContext( + workspaceRoot: string, + globs: string[], + exclude?: string[] +) { + if (isOnDaemon() || !daemonClient.enabled()) { + ensureContextAvailable(workspaceRoot); + return workspaceContext.hashFilesMatchingGlob(globs, exclude); + } + return daemonClient.hashGlob(globs, exclude); } export function updateFilesInContext( @@ -54,16 +82,22 @@ export function updateFilesInContext( } export function getAllFileDataInContext(workspaceRoot: string) { - ensureContextAvailable(workspaceRoot); - return workspaceContext.allFileData(); + if (isOnDaemon() || !daemonClient.enabled()) { + ensureContextAvailable(workspaceRoot); + return workspaceContext.allFileData(); + } + return daemonClient.getAllFileData(); } export function getFilesInDirectoryUsingContext( workspaceRoot: string, dir: string ) { - ensureContextAvailable(workspaceRoot); - return workspaceContext.getFilesInDirectory(dir); + if (isOnDaemon() || !daemonClient.enabled()) { + ensureContextAvailable(workspaceRoot); + return workspaceContext.getFilesInDirectory(dir); + } + return daemonClient.getFilesInDirectory(dir); } export function updateProjectFiles( diff --git a/packages/playwright/src/plugins/plugin.ts b/packages/playwright/src/plugins/plugin.ts index b27a4b4cc475d..69d143a3560e5 100644 --- a/packages/playwright/src/plugins/plugin.ts +++ b/packages/playwright/src/plugins/plugin.ts @@ -72,9 +72,12 @@ export const createNodes: CreateNodes = [ const normalizedOptions = normalizeOptions(options); - const hash = calculateHashForCreateNodes(projectRoot, options, context, [ - getLockFileName(detectPackageManager(context.workspaceRoot)), - ]); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); targetsCache[hash] ??= await buildPlaywrightTargets( configFilePath, diff --git a/packages/react-native/plugins/plugin.ts b/packages/react-native/plugins/plugin.ts index e1685b5345771..8d3b9751c040c 100644 --- a/packages/react-native/plugins/plugin.ts +++ b/packages/react-native/plugins/plugin.ts @@ -70,9 +70,12 @@ export const createNodes: CreateNodes = [ return {}; } - const hash = calculateHashForCreateNodes(projectRoot, options, context, [ - getLockFileName(detectPackageManager(context.workspaceRoot)), - ]); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); targetsCache[hash] ??= buildReactNativeTargets( projectRoot, diff --git a/packages/remix/src/plugins/plugin.ts b/packages/remix/src/plugins/plugin.ts index 1677a37ed0698..f68b11e557079 100644 --- a/packages/remix/src/plugins/plugin.ts +++ b/packages/remix/src/plugins/plugin.ts @@ -66,9 +66,12 @@ export const createNodes: CreateNodes = [ options = normalizeOptions(options); - const hash = calculateHashForCreateNodes(projectRoot, options, context, [ - getLockFileName(detectPackageManager(context.workspaceRoot)), - ]); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); targetsCache[hash] ??= await buildRemixTargets( configFilePath, projectRoot, diff --git a/packages/rollup/src/plugins/plugin.ts b/packages/rollup/src/plugins/plugin.ts index 6c91222caf705..f73e5df93397f 100644 --- a/packages/rollup/src/plugins/plugin.ts +++ b/packages/rollup/src/plugins/plugin.ts @@ -63,9 +63,12 @@ export const createNodes: CreateNodes = [ options = normalizeOptions(options); - const hash = calculateHashForCreateNodes(projectRoot, options, context, [ - getLockFileName(detectPackageManager(context.workspaceRoot)), - ]); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); targetsCache[hash] ??= await buildRollupTarget( configFilePath, diff --git a/packages/storybook/src/plugins/plugin.ts b/packages/storybook/src/plugins/plugin.ts index c93749fa1e8f7..597ac6a00f0eb 100644 --- a/packages/storybook/src/plugins/plugin.ts +++ b/packages/storybook/src/plugins/plugin.ts @@ -72,9 +72,12 @@ export const createNodes: CreateNodes = [ } options = normalizeOptions(options); - const hash = calculateHashForCreateNodes(projectRoot, options, context, [ - getLockFileName(detectPackageManager(context.workspaceRoot)), - ]); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); const projectName = buildProjectName(projectRoot, context.workspaceRoot); diff --git a/packages/webpack/src/plugins/plugin.ts b/packages/webpack/src/plugins/plugin.ts index e60b83310fa8a..e9a2f59ca5ab5 100644 --- a/packages/webpack/src/plugins/plugin.ts +++ b/packages/webpack/src/plugins/plugin.ts @@ -69,9 +69,12 @@ export const createNodes: CreateNodes = [ return {}; } - const hash = calculateHashForCreateNodes(projectRoot, options, context, [ - getLockFileName(detectPackageManager(context.workspaceRoot)), - ]); + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); const targets = targetsCache[hash] ? targetsCache[hash] : await createWebpackTargets(