diff --git a/packages/cypress/src/plugins/plugin.spec.ts b/packages/cypress/src/plugins/plugin.spec.ts index 7754a4ffdd6d34..fbb4bd3254822d 100644 --- a/packages/cypress/src/plugins/plugin.spec.ts +++ b/packages/cypress/src/plugins/plugin.spec.ts @@ -348,6 +348,10 @@ describe('@nx/cypress/plugin', () => { }); function mockCypressConfig(cypressConfig: Cypress.ConfigOptions) { + // This isn't JS, but all that really matters here + // is that the hash is different after updating the + // config file. The actual config read is mocked below. + tempFs.createFileSync('cypress.config.js', JSON.stringify(cypressConfig)); jest.mock( join(tempFs.tempDir, 'cypress.config.js'), () => ({ diff --git a/packages/cypress/src/plugins/plugin.ts b/packages/cypress/src/plugins/plugin.ts index dba51d94a2574e..1151907965abff 100644 --- a/packages/cypress/src/plugins/plugin.ts +++ b/packages/cypress/src/plugins/plugin.ts @@ -31,20 +31,22 @@ export interface CypressPluginOptions { } const cachePath = join(projectGraphCacheDirectory, 'cypress.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; - -const calculatedTargets: Record = {}; +const targetsCache = readTargetsCache(); function readTargetsCache(): Record { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache(targets: Record) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -67,16 +69,13 @@ export const createNodes: CreateNodes = [ getLockFileName(detectPackageManager(context.workspaceRoot)), ]); - const { targets, metadata } = targetsCache[hash] - ? targetsCache[hash] - : await buildCypressTargets( - configFilePath, - projectRoot, - options, - context - ); - - calculatedTargets[hash] = { targets, metadata }; + targetsCache[hash] ??= await buildCypressTargets( + configFilePath, + projectRoot, + options, + context + ); + const { targets, metadata } = targetsCache[hash]; const project: Omit = { projectType: 'application', diff --git a/packages/detox/src/plugins/plugin.ts b/packages/detox/src/plugins/plugin.ts index 7fb2ec7f33a3ea..3873b3e0b5ca99 100644 --- a/packages/detox/src/plugins/plugin.ts +++ b/packages/detox/src/plugins/plugin.ts @@ -22,31 +22,21 @@ export interface DetoxPluginOptions { } const cachePath = join(projectGraphCacheDirectory, 'detox.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; - -const calculatedTargets: Record< - string, - Record -> = {}; +const targetsCache = readTargetsCache(); function readTargetsCache(): Record< string, Record> > { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache( - targets: Record< - string, - Record> - > -) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + writeJsonFile(cachePath, targetsCache); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -66,16 +56,12 @@ export const createNodes: CreateNodes = [ getLockFileName(detectPackageManager(context.workspaceRoot)), ]); - const targets = targetsCache[hash] - ? targetsCache[hash] - : buildDetoxTargets(projectRoot, options, context); - - calculatedTargets[hash] = targets; + targetsCache[hash] ??= buildDetoxTargets(projectRoot, options, context); return { projects: { [projectRoot]: { - targets, + targets: targetsCache[hash], }, }, }; diff --git a/packages/expo/plugins/plugin.ts b/packages/expo/plugins/plugin.ts index 62ffcc692a3f30..d9f3b4bd812d25 100644 --- a/packages/expo/plugins/plugin.ts +++ b/packages/expo/plugins/plugin.ts @@ -30,31 +30,25 @@ export interface ExpoPluginOptions { } const cachePath = join(projectGraphCacheDirectory, 'expo.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; - -const calculatedTargets: Record< - string, - Record -> = {}; +const targetsCache = readTargetsCache(); function readTargetsCache(): Record< string, Record> > { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache( - targets: Record< - string, - Record> - > -) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -82,16 +76,12 @@ export const createNodes: CreateNodes = [ getLockFileName(detectPackageManager(context.workspaceRoot)), ]); - const targets = targetsCache[hash] - ? targetsCache[hash] - : buildExpoTargets(projectRoot, options, context); - - calculatedTargets[hash] = targets; + targetsCache[hash] ??= buildExpoTargets(projectRoot, options, context); return { projects: { [projectRoot]: { - targets, + targets: targetsCache[hash], }, }, }; diff --git a/packages/gradle/src/plugin/dependencies.ts b/packages/gradle/src/plugin/dependencies.ts index 764bfc61dc2707..a09a3dafa503da 100644 --- a/packages/gradle/src/plugin/dependencies.ts +++ b/packages/gradle/src/plugin/dependencies.ts @@ -13,7 +13,7 @@ import { getGradleReport, invalidateGradleReportCache, } from '../utils/get-gradle-report'; -import { calculatedTargets, writeTargetsToCache } from './nodes'; +import { writeTargetsToCache } from './nodes'; export const createDependencies: CreateDependencies = async ( _, @@ -58,7 +58,7 @@ export const createDependencies: CreateDependencies = async ( gradleDependenciesEnd.name ); - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); if (dependencies.length) { invalidateGradleReportCache(); } diff --git a/packages/gradle/src/plugin/nodes.ts b/packages/gradle/src/plugin/nodes.ts index 1e330022e5ff9e..7e19b38cf2f494 100644 --- a/packages/gradle/src/plugin/nodes.ts +++ b/packages/gradle/src/plugin/nodes.ts @@ -34,39 +34,26 @@ export interface GradlePluginOptions { } const cachePath = join(projectGraphCacheDirectory, 'gradle.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; - -export const calculatedTargets: Record< +const targetsCache = readTargetsCache(); +type GradleTargets = Record< string, { name: string; targets: Record; metadata: ProjectConfiguration['metadata']; } -> = {}; +>; -function readTargetsCache(): Record< - string, - { - name: string; - targets: Record; - metadata: ProjectConfiguration['metadata']; - } -> { - return readJsonFile(cachePath); +function readTargetsCache(): GradleTargets { + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -export function writeTargetsToCache( - targets: Record< - string, - { - name: string; - targets: Record; - metadata: ProjectConfiguration['metadata']; - } - > -) { - writeJsonFile(cachePath, targets); +export function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + ...targetsCache, + }); } export const createNodes: CreateNodes = [ @@ -83,76 +70,84 @@ export const createNodes: CreateNodes = [ options ?? {}, context ); - if (targetsCache[hash]) { - calculatedTargets[hash] = targetsCache[hash]; - return { - projects: { - [projectRoot]: targetsCache[hash], - }, - }; - } - - try { - const { - gradleProjectToTasksTypeMap, - gradleFileToOutputDirsMap, - gradleFileToGradleProjectMap, - gradleProjectToProjectName, - } = getGradleReport(); - - const gradleProject = gradleFileToGradleProjectMap.get( - gradleFilePath - ) as string; - const projectName = gradleProjectToProjectName.get(gradleProject); - if (!projectName) { - return; - } - - const tasksTypeMap = gradleProjectToTasksTypeMap.get( - gradleProject - ) as Map; - let tasks: GradleTask[] = []; - for (let [taskName, taskType] of tasksTypeMap.entries()) { - tasks.push({ - type: taskType, - name: taskName, - }); - } - - const outputDirs = gradleFileToOutputDirsMap.get(gradleFilePath) as Map< - string, - string - >; - - const { targets, targetGroups } = createGradleTargets( - tasks, - options, - context, - outputDirs, - gradleProject - ); - const project = { - name: projectName, - targets, - metadata: { - targetGroups, - technologies: ['gradle'], - }, - }; - calculatedTargets[hash] = project; - - return { - projects: { - [projectRoot]: project, - }, - }; - } catch (e) { - console.error(e); + targetsCache[hash] ??= createGradleProject( + gradleFilePath, + options, + context + ); + const project = targetsCache[hash]; + if (!project) { return {}; } + return { + projects: { + [projectRoot]: project, + }, + }; }, ]; +function createGradleProject( + gradleFilePath: string, + options: GradlePluginOptions | undefined, + context: CreateNodesContext +) { + try { + const { + gradleProjectToTasksTypeMap, + gradleFileToOutputDirsMap, + gradleFileToGradleProjectMap, + gradleProjectToProjectName, + } = getGradleReport(); + + const gradleProject = gradleFileToGradleProjectMap.get( + gradleFilePath + ) as string; + const projectName = gradleProjectToProjectName.get(gradleProject); + if (!projectName) { + return; + } + + const tasksTypeMap = gradleProjectToTasksTypeMap.get(gradleProject) as Map< + string, + string + >; + let tasks: GradleTask[] = []; + for (let [taskName, taskType] of tasksTypeMap.entries()) { + tasks.push({ + type: taskType, + name: taskName, + }); + } + + const outputDirs = gradleFileToOutputDirsMap.get(gradleFilePath) as Map< + string, + string + >; + + const { targets, targetGroups } = createGradleTargets( + tasks, + options, + context, + outputDirs, + gradleProject + ); + const project = { + name: projectName, + targets, + metadata: { + targetGroups, + technologies: ['gradle'], + }, + }; + + return project; + } catch (e) { + console.error(e); + return undefined; + } +} + function createGradleTargets( tasks: GradleTask[], options: GradlePluginOptions | undefined, diff --git a/packages/jest/src/plugins/plugin.spec.ts b/packages/jest/src/plugins/plugin.spec.ts index cfc0d5ce758ca9..f2e4a177a1cc3a 100644 --- a/packages/jest/src/plugins/plugin.spec.ts +++ b/packages/jest/src/plugins/plugin.spec.ts @@ -33,8 +33,6 @@ describe('@nx/jest/plugin', () => { }); }); - test('foo', () => {}); - afterEach(() => { jest.resetModules(); process.chdir(cwd); diff --git a/packages/jest/src/plugins/plugin.ts b/packages/jest/src/plugins/plugin.ts index 5487852c681195..37ca2b6824b391 100644 --- a/packages/jest/src/plugins/plugin.ts +++ b/packages/jest/src/plugins/plugin.ts @@ -28,22 +28,24 @@ export interface JestPluginOptions { } const cachePath = join(projectGraphCacheDirectory, 'jest.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; +const targetsCache = readTargetsCache(); type JestTargets = Awaited>; -const calculatedTargets: JestTargets = {}; - function readTargetsCache(): Record { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache(targets: JestTargets) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const cache = readTargetsCache(); + writeJsonFile(cachePath, { + ...cache, + ...targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -93,11 +95,14 @@ export const createNodes: CreateNodes = [ options = normalizeOptions(options); const hash = calculateHashForCreateNodes(projectRoot, options, context); - const { targets, metadata } = - targetsCache[hash] ?? - (await buildJestTargets(configFilePath, projectRoot, options, context)); + targetsCache[hash] ??= await buildJestTargets( + configFilePath, + projectRoot, + options, + context + ); - calculatedTargets[hash] = { targets, metadata }; + const { targets, metadata } = targetsCache[hash]; return { projects: { diff --git a/packages/js/src/plugins/typescript/plugin.spec.ts b/packages/js/src/plugins/typescript/plugin.spec.ts index 7389c5dd69222b..a2a05d9c68a031 100644 --- a/packages/js/src/plugins/typescript/plugin.spec.ts +++ b/packages/js/src/plugins/typescript/plugin.spec.ts @@ -2,6 +2,7 @@ import { type CreateNodesContext } from '@nx/devkit'; import { minimatch } from 'minimatch'; import { TempFs } from 'nx/src/internal-testing-utils/temp-fs'; import { PLUGIN_NAME, TscPluginOptions, createNodes } from './plugin'; +import { setupWorkspaceContext } from 'nx/src/utils/workspace-context'; describe(`Plugin: ${PLUGIN_NAME}`, () => { let context: CreateNodesContext; @@ -30,7 +31,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should create nodes for root tsconfig.json files', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'package.json': `{}`, 'project.json': `{}`, 'tsconfig.json': `{}`, @@ -85,7 +86,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should not create nodes when it is not a tsconfig.json file and there is no sibling tsconfig.json file', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'package.json': `{}`, 'project.json': `{}`, 'tsconfig.base.json': `{}`, @@ -102,7 +103,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { describe('typecheck target', () => { it('should create a node with a typecheck target for a project level tsconfig.json file by default (when there is a sibling package.json or project.json)', async () => { // Sibling package.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/package.json': `{}`, }); @@ -140,7 +141,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // Sibling project.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/project.json': `{}`, }); @@ -178,7 +179,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // Other tsconfigs present - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/tsconfig.lib.json': `{}`, 'libs/my-lib/tsconfig.build.json': `{}`, @@ -221,7 +222,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { it('should not create typecheck target for a project level tsconfig.json file if set to false in plugin options', async () => { // Sibling package.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/package.json': `{}`, }); @@ -241,7 +242,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // Sibling project.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/project.json': `{}`, }); @@ -263,7 +264,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { it('should not invoke tsc with `--emitDeclarationOnly` when `noEmit` is set in the tsconfig.json file', async () => { // set directly in tsconfig.json file - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ compilerOptions: { noEmit: true }, }), @@ -303,7 +304,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // set in extended tsconfig file - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'tsconfig.base.json': JSON.stringify({ compilerOptions: { noEmit: true }, }), @@ -347,7 +348,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should not invoke tsc with `--emitDeclarationOnly` when `noEmit` is set in any of the referenced tsconfig.json files', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ files: [], references: [{ path: './tsconfig.lib.json' }], @@ -393,7 +394,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { describe('inputs', () => { it('should add the config file and the `include` and `exclude` patterns', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ include: ['src/**/*.ts'], exclude: ['src/**/foo.ts'], @@ -437,7 +438,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should add extended config files', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ extends: '../../tsconfig.foo.json', include: ['src/**/*.ts'], @@ -486,7 +487,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should add files from internal project references', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ include: ['src/**/*.ts'], exclude: ['src/**/*.spec.ts'], // should be ignored because a referenced internal project includes this same pattern @@ -551,7 +552,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { it('should only add exclude paths that are not part of other tsconfig files include paths', async () => { // exact match - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ references: [ { path: './tsconfig.lib.json' }, @@ -588,7 +589,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // other file include pattern is a subset of exclude pattern - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ references: [ { path: './tsconfig.lib.json' }, @@ -624,7 +625,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // exclude pattern is a subset of other file include pattern - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ references: [ { path: './tsconfig.lib.json' }, @@ -660,7 +661,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // handles mismatches with leading `./` - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ references: [ { path: './tsconfig.lib.json' }, @@ -696,7 +697,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // no matching pattern in the exclude list - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ references: [ { path: './tsconfig.lib.json' }, @@ -737,7 +738,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should fall back to named inputs when not using include', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ files: ['main.ts'] }), 'libs/my-lib/package.json': `{}`, }); @@ -792,7 +793,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { describe('outputs', () => { it('should add the `outFile`', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ compilerOptions: { outFile: '../../dist/libs/my-lib/index.js' }, files: ['main.ts'], @@ -840,7 +841,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should add the `outDir`', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ compilerOptions: { outDir: '../../dist/libs/my-lib' }, files: ['main.ts'], @@ -884,7 +885,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should add the inline output files when `outDir` is not defined', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ files: ['main.ts'], }), @@ -939,7 +940,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should collect outputs from all internal project references', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ files: [], references: [ @@ -1004,7 +1005,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { it('should respect the "tsBuildInfoFile" option', async () => { // outFile - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ compilerOptions: { outFile: '../../dist/libs/my-lib/index.js', @@ -1054,7 +1055,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // no outFile & no outDir - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': JSON.stringify({ compilerOptions: { tsBuildInfoFile: '../../dist/libs/my-lib/my-lib.tsbuildinfo', @@ -1116,7 +1117,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { describe('build target', () => { it('should not create a node with a build target for a project level tsconfig files by default', async () => { // Sibling package.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/tsconfig.lib.json': `{}`, 'libs/my-lib/tsconfig.build.json': `{}`, @@ -1139,7 +1140,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // Sibling project.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/tsconfig.lib.json': `{}`, 'libs/my-lib/tsconfig.build.json': `{}`, @@ -1164,7 +1165,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { it('should not create build target for a project level tsconfig.json file if set to false in plugin options', async () => { // Sibling package.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/tsconfig.lib.json': `{}`, 'libs/my-lib/tsconfig.build.json': `{}`, @@ -1188,7 +1189,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // Sibling project.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/tsconfig.lib.json': `{}`, 'libs/my-lib/tsconfig.build.json': `{}`, @@ -1214,7 +1215,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { it('should create a node with a build target when enabled, for a project level tsconfig.lib.json build file by default', async () => { // Sibling package.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/tsconfig.lib.json': `{}`, 'libs/my-lib/tsconfig.build.json': `{}`, @@ -1259,7 +1260,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // Sibling project.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/tsconfig.lib.json': `{}`, 'libs/my-lib/tsconfig.build.json': `{}`, @@ -1306,7 +1307,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { it('should create a node with a build target when enabled, using a custom configured target name', async () => { // Sibling package.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/tsconfig.lib.json': `{}`, 'libs/my-lib/tsconfig.build.json': `{}`, @@ -1355,7 +1356,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { it('should create a node with a build target when enabled, using a custom configured tsconfig file', async () => { // Sibling project.json - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': `{}`, 'libs/my-lib/tsconfig.lib.json': `{}`, 'libs/my-lib/tsconfig.build.json': `{}`, @@ -1404,7 +1405,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { describe('inputs', () => { it('should add the config file and the `include` and `exclude` patterns', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ include: ['src/**/*.ts'], exclude: ['src/**/*.spec.ts'], @@ -1453,7 +1454,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should add extended config files', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': '{}', 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ extends: '../../tsconfig.foo.json', @@ -1507,7 +1508,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should add files from internal project references', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': '{}', 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ include: ['src/**/*.ts'], @@ -1571,7 +1572,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { it('should only add exclude paths that are not part of other tsconfig files include paths', async () => { // exact match - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': '{}', 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ include: ['src/**/*.ts'], @@ -1606,7 +1607,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // other file include pattern is a subset of exclude pattern - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': '{}', 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ include: ['**/*.ts'], @@ -1640,7 +1641,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // exclude pattern is a subset of other file include pattern - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': '{}', 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ include: ['src/**/*.ts'], @@ -1674,7 +1675,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // handles mismatches with leading `./` - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': '{}', 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ include: ['src/**/*.ts'], @@ -1708,7 +1709,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // no matching pattern in the exclude list - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': '{}', 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ include: ['src/**/*.ts'], @@ -1747,7 +1748,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should fall back to named inputs when not using include', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ files: ['main.ts'], }), @@ -1809,7 +1810,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { describe('outputs', () => { it('should add the `outFile`', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ compilerOptions: { outFile: '../../dist/libs/my-lib/index.js' }, files: ['main.ts'], @@ -1862,7 +1863,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should add the `outDir`', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ compilerOptions: { outDir: '../../dist/libs/my-lib' }, files: ['main.ts'], @@ -1911,7 +1912,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should add the inline output files when `outDir` is not defined', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ files: ['main.ts'], }), @@ -1971,7 +1972,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); it('should collect outputs from all internal project references', async () => { - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': '{}', 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ compilerOptions: { outFile: '../../dist/libs/my-lib/lib.js' }, @@ -2033,7 +2034,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { it('should respect the "tsBuildInfoFile" option', async () => { // outFile - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': '{}', 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ compilerOptions: { @@ -2088,7 +2089,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { `); // no outFile & no outDir - applyFilesToTempFsAndContext(tempFs, context, { + await applyFilesToTempFsAndContext(tempFs, context, { 'libs/my-lib/tsconfig.json': '{}', 'libs/my-lib/tsconfig.lib.json': JSON.stringify({ compilerOptions: { @@ -2153,16 +2154,17 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { }); }); -function applyFilesToTempFsAndContext( +async function applyFilesToTempFsAndContext( tempFs: TempFs, context: CreateNodesContext, fileSys: Record ) { - tempFs.createFilesSync(fileSys); + await tempFs.createFiles(fileSys); // @ts-expect-error update otherwise readonly property for testing context.configFiles = Object.keys(fileSys).filter((file) => minimatch(file, createNodes[0], { dot: true }) ); + setupWorkspaceContext(tempFs.tempDir); } async function invokeCreateNodesOnMatchingFiles( diff --git a/packages/js/src/plugins/typescript/plugin.ts b/packages/js/src/plugins/typescript/plugin.ts index f7914af6d62251..3c16473a0da11d 100644 --- a/packages/js/src/plugins/typescript/plugin.ts +++ b/packages/js/src/plugins/typescript/plugin.ts @@ -50,28 +50,25 @@ interface NormalizedPluginOptions { } const cachePath = join(projectGraphCacheDirectory, 'tsc.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; - -const calculatedTargets: Record< - string, - Record -> = {}; +const targetsCache = readTargetsCache(); function readTargetsCache(): Record< string, Record> > { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache( - targets: Record>> -) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + ...targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -113,17 +110,18 @@ export const createNodes: CreateNodes = [ // The hash is calculated at the node/project level, so we add the config file path to avoid conflicts when caching const cacheKey = `${nodeHash}_${configFilePath}`; - const targets = targetsCache[cacheKey] - ? targetsCache[cacheKey] - : buildTscTargets(fullConfigPath, projectRoot, pluginOptions, context); - - calculatedTargets[cacheKey] = targets; + targetsCache[cacheKey] ??= buildTscTargets( + fullConfigPath, + projectRoot, + pluginOptions, + context + ); return { projects: { [projectRoot]: { projectType: 'library', - targets, + targets: targetsCache[cacheKey], }, }, }; diff --git a/packages/next/src/plugins/plugin.ts b/packages/next/src/plugins/plugin.ts index 033fd47721c5e6..3bfa2b07caaf52 100644 --- a/packages/next/src/plugins/plugin.ts +++ b/packages/next/src/plugins/plugin.ts @@ -26,28 +26,25 @@ export interface NextPluginOptions { } const cachePath = join(projectGraphCacheDirectory, 'next.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; - -const calculatedTargets: Record< - string, - Record -> = {}; +const targetsCache = readTargetsCache(); function readTargetsCache(): Record< string, Record > { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache( - targets: Record> -) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + ...targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -70,17 +67,18 @@ export const createNodes: CreateNodes = [ getLockFileName(detectPackageManager(context.workspaceRoot)), ]); - const targets = - targetsCache[hash] ?? - (await buildNextTargets(configFilePath, projectRoot, options, context)); - - calculatedTargets[hash] = targets; + targetsCache[hash] ??= await buildNextTargets( + configFilePath, + projectRoot, + options, + context + ); return { projects: { [projectRoot]: { root: projectRoot, - targets, + targets: targetsCache[hash], }, }, }; diff --git a/packages/nuxt/src/plugins/plugin.ts b/packages/nuxt/src/plugins/plugin.ts index 02b5761c9328dd..922f2d81e60bdb 100644 --- a/packages/nuxt/src/plugins/plugin.ts +++ b/packages/nuxt/src/plugins/plugin.ts @@ -18,28 +18,25 @@ import { getLockFileName } from '@nx/js'; import { loadConfigFile } from '@nx/devkit/src/utils/config-utils'; const cachePath = join(projectGraphCacheDirectory, 'nuxt.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; - -const calculatedTargets: Record< - string, - Record -> = {}; +const targetsCache = readTargetsCache(); function readTargetsCache(): Record< string, Record > { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache( - targets: Record> -) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + ...targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -68,17 +65,18 @@ export const createNodes: CreateNodes = [ const hash = calculateHashForCreateNodes(projectRoot, options, context, [ getLockFileName(detectPackageManager(context.workspaceRoot)), ]); - const targets = targetsCache[hash] - ? targetsCache[hash] - : await buildNuxtTargets(configFilePath, projectRoot, options, context); - - calculatedTargets[hash] = targets; + targetsCache[hash] ??= await buildNuxtTargets( + configFilePath, + projectRoot, + options, + context + ); return { projects: { [projectRoot]: { root: projectRoot, - targets, + targets: targetsCache[hash], }, }, }; diff --git a/packages/nx/src/project-graph/utils/project-configuration-utils.ts b/packages/nx/src/project-graph/utils/project-configuration-utils.ts index 011536724d38cb..8ff6752c7d6331 100644 --- a/packages/nx/src/project-graph/utils/project-configuration-utils.ts +++ b/packages/nx/src/project-graph/utils/project-configuration-utils.ts @@ -433,6 +433,10 @@ export async function createProjectConfigurations( } for (const node in projectNodes) { + // Handles `{projects: {'libs/foo': undefined}}`. + if (!projectNodes[node]) { + continue; + } const project = { root: node, ...projectNodes[node], diff --git a/packages/playwright/src/plugins/plugin.ts b/packages/playwright/src/plugins/plugin.ts index 861be3897a4a0f..b27a4b4cc475dc 100644 --- a/packages/playwright/src/plugins/plugin.ts +++ b/packages/playwright/src/plugins/plugin.ts @@ -35,22 +35,24 @@ interface NormalizedOptions { const cachePath = join(projectGraphCacheDirectory, 'playwright.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; +const targetsCache = readTargetsCache(); type PlaywrightTargets = Pick; -const calculatedTargets: Record = {}; - function readTargetsCache(): Record { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache(targets: Record) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...readTargetsCache, + targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -74,16 +76,13 @@ export const createNodes: CreateNodes = [ getLockFileName(detectPackageManager(context.workspaceRoot)), ]); - const { targets, metadata } = - targetsCache[hash] ?? - (await buildPlaywrightTargets( - configFilePath, - projectRoot, - normalizedOptions, - context - )); - - calculatedTargets[hash] = { targets, metadata }; + targetsCache[hash] ??= await buildPlaywrightTargets( + configFilePath, + projectRoot, + normalizedOptions, + context + ); + const { targets, metadata } = targetsCache[hash]; return { projects: { diff --git a/packages/react-native/plugins/plugin.ts b/packages/react-native/plugins/plugin.ts index 6cdc96d7649592..e1685b5345771b 100644 --- a/packages/react-native/plugins/plugin.ts +++ b/packages/react-native/plugins/plugin.ts @@ -30,31 +30,24 @@ export interface ReactNativePluginOptions { } const cachePath = join(projectGraphCacheDirectory, 'react-native.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; - -const calculatedTargets: Record< - string, - Record -> = {}; - +const targetsCache = readTargetsCache(); function readTargetsCache(): Record< string, Record> > { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache( - targets: Record< - string, - Record> - > -) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + ...targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -81,16 +74,16 @@ export const createNodes: CreateNodes = [ getLockFileName(detectPackageManager(context.workspaceRoot)), ]); - const targets = targetsCache[hash] - ? targetsCache[hash] - : buildReactNativeTargets(projectRoot, options, context); - - calculatedTargets[hash] = targets; + targetsCache[hash] ??= buildReactNativeTargets( + projectRoot, + options, + context + ); return { projects: { [projectRoot]: { - targets, + targets: targetsCache[hash], }, }, }; diff --git a/packages/remix/src/plugins/plugin.ts b/packages/remix/src/plugins/plugin.ts index 9515693f450f1d..1677a37ed06984 100644 --- a/packages/remix/src/plugins/plugin.ts +++ b/packages/remix/src/plugins/plugin.ts @@ -18,27 +18,25 @@ import { existsSync, readdirSync } from 'fs'; import { loadConfigFile } from '@nx/devkit/src/utils/config-utils'; const cachePath = join(projectGraphCacheDirectory, 'remix.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; -const calculatedTargets: Record< - string, - Record -> = {}; +const targetsCache = readTargetsCache(); function readTargetsCache(): Record< string, Record > { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache( - targets: Record> -) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + ...targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -71,23 +69,19 @@ export const createNodes: CreateNodes = [ const hash = calculateHashForCreateNodes(projectRoot, options, context, [ getLockFileName(detectPackageManager(context.workspaceRoot)), ]); - const targets = targetsCache[hash] - ? targetsCache[hash] - : await buildRemixTargets( - configFilePath, - projectRoot, - options, - context, - siblingFiles - ); - - calculatedTargets[hash] = targets; + targetsCache[hash] ??= await buildRemixTargets( + configFilePath, + projectRoot, + options, + context, + siblingFiles + ); return { projects: { [projectRoot]: { root: projectRoot, - targets, + targets: targetsCache[hash], }, }, }; diff --git a/packages/rollup/src/plugins/plugin.spec.ts b/packages/rollup/src/plugins/plugin.spec.ts index 2ff90dd42f7eca..c8fcf7ec48638a 100644 --- a/packages/rollup/src/plugins/plugin.spec.ts +++ b/packages/rollup/src/plugins/plugin.spec.ts @@ -38,16 +38,7 @@ describe('@nx/rollup/plugin', () => { workspaceRoot: tempFs.tempDir, configFiles: [], }; - - tempFs.createFileSync('package.json', JSON.stringify({ name: 'mylib' })); - tempFs.createFileSync( - 'src/index.js', - `export function main() { - console.log("hello world"); - }` - ); - - loadConfigFile.mockReturnValue({ + const rollupConfigOptions = { options: [ { output: { @@ -57,7 +48,24 @@ describe('@nx/rollup/plugin', () => { }, }, ], - }); + }; + + // This isn't JS, but all that really matters here + // is that the hash is different after updating the + // config file. The actual config read is mocked below. + tempFs.createFileSync( + 'rollup.config.js', + JSON.stringify(rollupConfigOptions) + ); + tempFs.createFileSync('package.json', JSON.stringify({ name: 'mylib' })); + tempFs.createFileSync( + 'src/index.js', + `export function main() { + console.log("hello world"); + }` + ); + + loadConfigFile.mockReturnValue(rollupConfigOptions); process.chdir(tempFs.tempDir); }); @@ -97,18 +105,7 @@ describe('@nx/rollup/plugin', () => { workspaceRoot: tempFs.tempDir, configFiles: [], }; - - tempFs.createFileSync( - 'mylib/package.json', - JSON.stringify({ name: 'mylib' }) - ); - tempFs.createFileSync( - 'mylib/src/index.js', - `export function main() { - console.log("hello world"); - }` - ); - loadConfigFile.mockReturnValue({ + const rollupConfigOptions = { options: [ { output: { @@ -125,7 +122,25 @@ describe('@nx/rollup/plugin', () => { }, }, ], - }); + }; + // This isn't JS, but all that really matters here + // is that the hash is different after updating the + // config file. The actual config read is mocked below. + tempFs.createFileSync( + 'mylib/rollup.config.js', + JSON.stringify(rollupConfigOptions) + ); + tempFs.createFileSync( + 'mylib/package.json', + JSON.stringify({ name: 'mylib' }) + ); + tempFs.createFileSync( + 'mylib/src/index.js', + `export function main() { + console.log("hello world"); + }` + ); + loadConfigFile.mockReturnValue(rollupConfigOptions); process.chdir(tempFs.tempDir); }); diff --git a/packages/rollup/src/plugins/plugin.ts b/packages/rollup/src/plugins/plugin.ts index a78d85df8c5bff..b4f7e1bc97d431 100644 --- a/packages/rollup/src/plugins/plugin.ts +++ b/packages/rollup/src/plugins/plugin.ts @@ -21,27 +21,25 @@ import { type RollupOptions } from 'rollup'; import { loadConfigFile } from 'rollup/loadConfigFile'; const cachePath = join(projectGraphCacheDirectory, 'rollup.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; -const calculatedTargets: Record< - string, - Record -> = {}; +const targetsCache = readTargetsCache(); function readTargetsCache(): Record< string, Record > { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache( - targets: Record> -) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + ...targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -69,16 +67,18 @@ export const createNodes: CreateNodes = [ getLockFileName(detectPackageManager(context.workspaceRoot)), ]); - const targets = targetsCache[hash] - ? targetsCache[hash] - : await buildRollupTarget(configFilePath, projectRoot, options, context); + targetsCache[hash] ??= await buildRollupTarget( + configFilePath, + projectRoot, + options, + context + ); - calculatedTargets[hash] = targets; return { projects: { [projectRoot]: { root: projectRoot, - targets, + targets: targetsCache[hash], }, }, }; diff --git a/packages/storybook/src/plugins/plugin.ts b/packages/storybook/src/plugins/plugin.ts index ff908f64c4bd10..c93749fa1e8f7a 100644 --- a/packages/storybook/src/plugins/plugin.ts +++ b/packages/storybook/src/plugins/plugin.ts @@ -26,28 +26,25 @@ export interface StorybookPluginOptions { } const cachePath = join(projectGraphCacheDirectory, 'storybook.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; - -const calculatedTargets: Record< - string, - Record -> = {}; +const targetsCache = readTargetsCache(); function readTargetsCache(): Record< string, Record > { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache( - targets: Record> -) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + ...targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -81,23 +78,19 @@ export const createNodes: CreateNodes = [ const projectName = buildProjectName(projectRoot, context.workspaceRoot); - const targets = targetsCache[hash] - ? targetsCache[hash] - : await buildStorybookTargets( - configFilePath, - projectRoot, - options, - context, - projectName - ); - - calculatedTargets[hash] = targets; + targetsCache[hash] ??= await buildStorybookTargets( + configFilePath, + projectRoot, + options, + context, + projectName + ); const result = { projects: { [projectRoot]: { root: projectRoot, - targets, + targets: targetsCache[hash], }, }, }; diff --git a/packages/vite/src/plugins/plugin.ts b/packages/vite/src/plugins/plugin.ts index f28d1b6faadbf5..b823ce405fd131 100644 --- a/packages/vite/src/plugins/plugin.ts +++ b/packages/vite/src/plugins/plugin.ts @@ -26,28 +26,25 @@ export interface VitePluginOptions { } const cachePath = join(projectGraphCacheDirectory, 'vite.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; - -const calculatedTargets: Record< - string, - Record -> = {}; +const targetsCache = readTargetsCache(); function readTargetsCache(): Record< string, Record > { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache( - targets: Record> -) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + ...targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; }; @@ -72,17 +69,19 @@ export const createNodes: CreateNodes = [ calculateHashForCreateNodes(projectRoot, options, context, [ getLockFileName(detectPackageManager(context.workspaceRoot)), ]) + configFilePath; - const targets = targetsCache[hash] - ? targetsCache[hash] - : await buildViteTargets(configFilePath, projectRoot, options, context); - calculatedTargets[hash] = targets; + targetsCache[hash] ??= await buildViteTargets( + configFilePath, + projectRoot, + options, + context + ); return { projects: { [projectRoot]: { root: projectRoot, - targets, + targets: targetsCache[hash], }, }, }; diff --git a/packages/webpack/src/plugins/plugin.ts b/packages/webpack/src/plugins/plugin.ts index c733b193ae58fc..e60b83310fa8a3 100644 --- a/packages/webpack/src/plugins/plugin.ts +++ b/packages/webpack/src/plugins/plugin.ts @@ -27,28 +27,25 @@ export interface WebpackPluginOptions { } const cachePath = join(projectGraphCacheDirectory, 'webpack.hash'); -const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; - -const calculatedTargets: Record< - string, - Record -> = {}; +const targetsCache = readTargetsCache(); function readTargetsCache(): Record< string, Record > { - return readJsonFile(cachePath); + return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache( - targets: Record> -) { - writeJsonFile(cachePath, targets); +function writeTargetsToCache() { + const oldCache = readTargetsCache(); + writeJsonFile(cachePath, { + ...oldCache, + ...targetsCache, + }); } export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(calculatedTargets); + writeTargetsToCache(); return []; };