diff --git a/e2e/js/src/js-ts-solution.test.ts b/e2e/js/src/js-ts-solution.test.ts index b7211a6c9b..ebd1283d53 100644 --- a/e2e/js/src/js-ts-solution.test.ts +++ b/e2e/js/src/js-ts-solution.test.ts @@ -115,36 +115,36 @@ ${content}` // check build expect(runCLI(`build ${esbuildParentLib}`)).toContain( - `Successfully ran target build for project @proj/${esbuildParentLib} and 5 tasks it depends on` + `Successfully ran target build for project @proj/${esbuildParentLib}` ); expect(runCLI(`build ${rollupParentLib}`)).toContain( - `Successfully ran target build for project @proj/${rollupParentLib} and 5 tasks it depends on` + `Successfully ran target build for project @proj/${rollupParentLib}` ); expect(runCLI(`build ${swcParentLib}`)).toContain( - `Successfully ran target build for project @proj/${swcParentLib} and 5 tasks it depends on` + `Successfully ran target build for project @proj/${swcParentLib}` ); expect(runCLI(`build ${tscParentLib}`)).toContain( - `Successfully ran target build for project @proj/${tscParentLib} and 5 tasks it depends on` + `Successfully ran target build for project @proj/${tscParentLib}` ); expect(runCLI(`build ${viteParentLib}`)).toContain( - `Successfully ran target build for project @proj/${viteParentLib} and 5 tasks it depends on` + `Successfully ran target build for project @proj/${viteParentLib}` ); // check typecheck expect(runCLI(`typecheck ${esbuildParentLib}`)).toContain( - `Successfully ran target typecheck for project @proj/${esbuildParentLib} and 5 tasks it depends on` + `Successfully ran target typecheck for project @proj/${esbuildParentLib}` ); expect(runCLI(`typecheck ${rollupParentLib}`)).toContain( - `Successfully ran target typecheck for project @proj/${rollupParentLib} and 5 tasks it depends on` + `Successfully ran target typecheck for project @proj/${rollupParentLib}` ); expect(runCLI(`typecheck ${swcParentLib}`)).toContain( - `Successfully ran target typecheck for project @proj/${swcParentLib} and 5 tasks it depends on` + `Successfully ran target typecheck for project @proj/${swcParentLib}` ); expect(runCLI(`typecheck ${tscParentLib}`)).toContain( - `Successfully ran target typecheck for project @proj/${tscParentLib} and 5 tasks it depends on` + `Successfully ran target typecheck for project @proj/${tscParentLib}` ); expect(runCLI(`typecheck ${viteParentLib}`)).toContain( - `Successfully ran target typecheck for project @proj/${viteParentLib} and 5 tasks it depends on` + `Successfully ran target typecheck for project @proj/${viteParentLib}` ); // check lint diff --git a/e2e/vite/src/vite-ts-solution.test.ts b/e2e/vite/src/vite-ts-solution.test.ts index ae74cbde8d..6db41d52d2 100644 --- a/e2e/vite/src/vite-ts-solution.test.ts +++ b/e2e/vite/src/vite-ts-solution.test.ts @@ -101,12 +101,12 @@ ${content}` // check build expect(runCLI(`build ${reactApp}`)).toContain( - `Successfully ran target build for project @proj/${reactApp} and 5 tasks it depends on` + `Successfully ran target build for project @proj/${reactApp}` ); // check typecheck expect(runCLI(`typecheck ${reactApp}`)).toContain( - `Successfully ran target typecheck for project @proj/${reactApp} and 6 tasks it depends on` + `Successfully ran target typecheck for project @proj/${reactApp}` ); }, 300_000); }); diff --git a/packages/js/src/plugins/typescript/plugin.spec.ts b/packages/js/src/plugins/typescript/plugin.spec.ts index 3a49e7d38d..91b42cb2dc 100644 --- a/packages/js/src/plugins/typescript/plugin.spec.ts +++ b/packages/js/src/plugins/typescript/plugin.spec.ts @@ -782,7 +782,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/dist", + "{projectRoot}/dist/**/*.d.ts", + "{projectRoot}/dist/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -853,7 +854,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/dist", + "{projectRoot}/dist/**/*.d.ts", + "{projectRoot}/dist/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -928,7 +930,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/dist", + "{projectRoot}/dist/**/*.d.ts", + "{projectRoot}/dist/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -1003,7 +1006,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/dist", + "{projectRoot}/dist/**/*.d.ts", + "{projectRoot}/dist/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -1083,7 +1087,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/dist", + "{projectRoot}/dist/**/*.d.ts", + "{projectRoot}/dist/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -1158,7 +1163,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/dist", + "{projectRoot}/dist/**/*.d.ts", + "{projectRoot}/dist/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -1240,7 +1246,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/dist", + "{projectRoot}/dist/**/*.d.ts", + "{projectRoot}/dist/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -1348,8 +1355,10 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/dist", - "{projectRoot}/cypress/dist", + "{projectRoot}/dist/**/*.d.ts", + "{projectRoot}/dist/tsconfig.tsbuildinfo", + "{projectRoot}/cypress/dist/**/*.d.ts", + "{projectRoot}/cypress/dist/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -1395,7 +1404,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib/nested-project", }, "outputs": [ - "{projectRoot}/dist", + "{projectRoot}/dist/**/*.d.ts", + "{projectRoot}/dist/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -1492,7 +1502,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/dist", + "{projectRoot}/dist/**/*.d.ts", + "{projectRoot}/dist/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -1882,7 +1893,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{workspaceRoot}/dist/libs/my-lib", + "{workspaceRoot}/dist/libs/my-lib/**/*.d.ts", + "{workspaceRoot}/dist/libs/my-lib/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -1964,6 +1976,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cache": true, "command": "tsc --build --emitDeclarationOnly", "dependsOn": [ + "build", "^typecheck", ], "inputs": [ @@ -1993,7 +2006,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/out-tsc/my-lib", + "{projectRoot}/out-tsc/my-lib/**/*.d.ts", "{projectRoot}/out-tsc/*.tsbuildinfo", ], "syncGenerators": [ @@ -2171,8 +2184,10 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "{workspaceRoot}/dist/libs/my-lib/lib.d.ts", "{workspaceRoot}/dist/libs/my-lib/lib.d.ts.map", "{workspaceRoot}/dist/libs/my-lib/lib.tsbuildinfo", - "{workspaceRoot}/dist/out-tsc/libs/my-lib/specs", - "{workspaceRoot}/dist/out-tsc/libs/my-lib/cypress", + "{workspaceRoot}/dist/out-tsc/libs/my-lib/specs/**/*.d.ts", + "{workspaceRoot}/dist/out-tsc/libs/my-lib/specs/tsconfig.tsbuildinfo", + "{workspaceRoot}/dist/out-tsc/libs/my-lib/cypress/**/*.d.ts", + "{workspaceRoot}/dist/out-tsc/libs/my-lib/cypress/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -2216,7 +2231,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib/nested-project", }, "outputs": [ - "{workspaceRoot}/dist/out-tsc/libs/my-lib/nested-project", + "{workspaceRoot}/dist/out-tsc/libs/my-lib/nested-project/**/*.d.ts", + "{workspaceRoot}/dist/out-tsc/libs/my-lib/nested-project/tsconfig.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", @@ -2424,7 +2440,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/dist", + "{projectRoot}/dist/**/*.d.ts", "{projectRoot}/my-lib.tsbuildinfo", ], "syncGenerators": [ @@ -2490,7 +2506,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => { "cwd": "libs/my-lib", }, "outputs": [ - "{projectRoot}/dist", + "{projectRoot}/dist/**/*.d.ts", + "{projectRoot}/dist/my-lib.tsbuildinfo", ], "syncGenerators": [ "@nx/js:typescript-sync", diff --git a/packages/js/src/plugins/typescript/plugin.ts b/packages/js/src/plugins/typescript/plugin.ts index c54d921a9f..5e61a7d303 100644 --- a/packages/js/src/plugins/typescript/plugin.ts +++ b/packages/js/src/plugins/typescript/plugin.ts @@ -322,7 +322,7 @@ async function getConfigFileHash( ...(packageJson ? [hashObject(packageJson)] : []), // change this to bust the cache when making changes that would yield // different results for the same hash - hashObject({ bust: 1 }), + hashObject({ bust: 2 }), ]); } @@ -415,8 +415,30 @@ function buildTscTargets( command = `echo "The 'typecheck' target is disabled because one or more project references set 'noEmit: true' in their tsconfig. Remove this property to resolve this issue."`; } + const dependsOn: string[] = [`^${targetName}`]; + if (options.build && targets[options.build.targetName]) { + // we already processed and have a build target + dependsOn.unshift(options.build.targetName); + } else if (options.build) { + // check if the project will have a build target + const buildConfigPath = joinPathFragments( + projectRoot, + options.build.configName + ); + if ( + context.configFiles.some((f) => f === buildConfigPath) && + isValidPackageJsonBuildConfig( + retrieveTsConfigFromCache(buildConfigPath, context.workspaceRoot), + context.workspaceRoot, + projectRoot + ) + ) { + dependsOn.unshift(options.build.targetName); + } + } + targets[targetName] = { - dependsOn: [`^${targetName}`], + dependsOn, command, options: { cwd: projectRoot }, cache: true, @@ -433,7 +455,8 @@ function buildTscTargets( tsConfig, internalProjectReferences, context.workspaceRoot, - projectRoot + projectRoot, + /* emitDeclarationOnly */ true ), syncGenerators: ['@nx/js:typescript-sync'], metadata: { @@ -483,7 +506,9 @@ function buildTscTargets( tsConfig, internalProjectReferences, context.workspaceRoot, - projectRoot + projectRoot, + // should be false for build target, but providing it just in case is set to true + tsConfig.options.emitDeclarationOnly ), syncGenerators: ['@nx/js:typescript-sync'], metadata: { @@ -685,7 +710,8 @@ function getOutputs( tsConfig: ParsedTsconfigData, internalProjectReferences: Record, workspaceRoot: string, - projectRoot: string + projectRoot: string, + emitDeclarationOnly: boolean ): string[] { const outputs = new Set(); @@ -738,12 +764,32 @@ function getOutputs( ) ); } else if (config.options.outDir) { - outputs.add( - pathToInputOrOutput(config.options.outDir, workspaceRoot, projectRoot) - ); + if (emitDeclarationOnly) { + outputs.add( + pathToInputOrOutput( + joinPathFragments(config.options.outDir, '**/*.d.ts'), + workspaceRoot, + projectRoot + ) + ); + if (tsConfig.options.declarationMap) { + outputs.add( + pathToInputOrOutput( + joinPathFragments(config.options.outDir, '**/*.d.ts.map'), + workspaceRoot, + projectRoot + ) + ); + } + } else { + outputs.add( + pathToInputOrOutput(config.options.outDir, workspaceRoot, projectRoot) + ); + } if (config.options.tsBuildInfoFile) { if ( + emitDeclarationOnly || !normalize(config.options.tsBuildInfoFile).startsWith( `${normalize(config.options.outDir)}${sep}` ) @@ -774,6 +820,16 @@ function getOutputs( projectRoot ) ); + } else if (emitDeclarationOnly) { + // https://www.typescriptlang.org/tsconfig#tsBuildInfoFile + const name = basename(configFilePath, '.json'); + outputs.add( + pathToInputOrOutput( + joinPathFragments(config.options.outDir, `${name}.tsbuildinfo`), + workspaceRoot, + projectRoot + ) + ); } } else if ( config.raw?.include?.length ||