Jack Hsu 45847a6754
feat(js): remove nx property from generated package.json files (#29705)
This PR updates our generators to no longer generate with `nx` in
`package.json` by default. The only times it is needed is if you pass
add `tags` or `implicitDependencies` to the project config.

This PR replaces our `projectType` checks to use the `getProjectType`
util from `@nx/js` to prefer the project config, but otherwise will
check for our conventions (e.g. using `exports` for libs,
`tsconfig.lib.json` vs `tsconfig.app.json`).

## Impact
- There shouldn't be any behavioral changes to existing projects that
have explicit `projectType`, `name`, etc. in with `project.json` or
`package.json` (via `nx` property).
- For new projects created under the new TS setup, the `nx` property
will no longer be there. Generators with logic that depend on
`projectType` will now check for `tsconfig.lib.json` and
`tsconfig.app.json` (so all of our generators are covered). If none of
those tsconfig files are found, then we check `package.json`, since
libraries are required to have `exports` to be consumed.
2025-01-23 20:03:28 -05:00

87 lines
2.7 KiB
TypeScript

import {
joinPathFragments,
logger,
readProjectConfiguration,
updateJson,
type Tree,
} from '@nx/devkit';
import type { NormalizedJestProjectSchema } from '../schema';
import { getProjectType } from '@nx/js/src/utils/typescript/ts-solution-setup';
export function updateTsConfig(
host: Tree,
options: NormalizedJestProjectSchema
) {
const { root, projectType: _projectType } = readProjectConfiguration(
host,
options.project
);
if (!host.exists(joinPathFragments(root, 'tsconfig.json'))) {
throw new Error(
`Expected ${joinPathFragments(
root,
'tsconfig.json'
)} to exist. Please create one.`
);
}
updateJson(host, joinPathFragments(root, 'tsconfig.json'), (json) => {
if (
json.references &&
!json.references.some((r) => r.path === './tsconfig.spec.json')
) {
json.references.push({
path: './tsconfig.spec.json',
});
}
return json;
});
const projectType = getProjectType(host, root, _projectType);
// fall-back runtime tsconfig file path in case the user didn't provide one
let runtimeTsconfigPath = joinPathFragments(
root,
projectType === 'application' ? 'tsconfig.app.json' : 'tsconfig.lib.json'
);
if (options.runtimeTsconfigFileName) {
runtimeTsconfigPath = joinPathFragments(
root,
options.runtimeTsconfigFileName
);
// If the app is Next.js it will not have a tsconfig.app.json
const extensions = ['js', 'ts', 'mjs', 'cjs'];
const hasNextConfig = extensions.some((ext) =>
host.exists(joinPathFragments(root, `next.config.${ext}`))
);
if (hasNextConfig && projectType === 'application') {
runtimeTsconfigPath = joinPathFragments(root, 'tsconfig.json');
}
if (!host.exists(runtimeTsconfigPath)) {
// the user provided a runtimeTsconfigFileName that doesn't exist, so we throw an error
throw new Error(
`Cannot find the provided runtimeTsConfigFileName ("${options.runtimeTsconfigFileName}") at the project root "${root}".`
);
}
}
if (host.exists(runtimeTsconfigPath)) {
updateJson(host, runtimeTsconfigPath, (json) => {
const uniqueExclude = new Set([
...(json.exclude || []),
options.js ? 'jest.config.js' : 'jest.config.ts',
'src/**/*.spec.ts',
'src/**/*.test.ts',
...(options.js ? ['src/**/*.spec.js', 'src/**/*.test.js'] : []),
]);
json.exclude = [...uniqueExclude];
return json;
});
} else {
logger.warn(
`Couldn't find a runtime tsconfig file at ${runtimeTsconfigPath} to exclude the test files from. ` +
`If you're using a different filename for your runtime tsconfig, please provide it with the '--runtimeTsconfigFileName' flag.`
);
}
}