fix(js): Update typescript plugin check for buildable projects (#29431)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> Currently, we use `rootDir` to check if the project is buildable. This might not be correct in the case where the transpiled files are inside source. ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> It should work the for projects as long as the main / exports files are not source files. ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
325b9f6471
commit
a77e3ef083
@ -1819,7 +1819,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
// Sibling package.json
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': `{}`,
|
||||
'libs/my-lib/tsconfig.lib.json': `{}`,
|
||||
'libs/my-lib/tsconfig.lib.json': `{"compilerOptions": {"outDir": "dist"}}`,
|
||||
'libs/my-lib/tsconfig.build.json': `{}`,
|
||||
'libs/my-lib/package.json': `{}`,
|
||||
});
|
||||
@ -1867,7 +1867,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
// Sibling package.json
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': `{}`,
|
||||
'libs/my-lib/tsconfig.lib.json': `{}`,
|
||||
'libs/my-lib/tsconfig.lib.json': `{"compilerOptions": {"outDir": "dist"}}`,
|
||||
'libs/my-lib/tsconfig.build.json': `{}`,
|
||||
'libs/my-lib/package.json': `{}`,
|
||||
});
|
||||
@ -1917,7 +1917,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
// Sibling package.json
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': `{}`,
|
||||
'libs/my-lib/tsconfig.lib.json': `{"compilerOptions": {"rootDir": "src"}}`,
|
||||
'libs/my-lib/tsconfig.lib.json': `{"compilerOptions": {"outDir": "dist"}}`,
|
||||
'libs/my-lib/tsconfig.build.json': `{}`,
|
||||
'libs/my-lib/package.json': `{"main": "dist/index.js"}`,
|
||||
});
|
||||
@ -1965,7 +1965,9 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
"options": {
|
||||
"cwd": "libs/my-lib",
|
||||
},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
"{projectRoot}/dist",
|
||||
],
|
||||
"syncGenerators": [
|
||||
"@nx/js:typescript-sync",
|
||||
],
|
||||
@ -1978,8 +1980,8 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
|
||||
// Sibling project.json
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': `{"compilerOptions": {"rootDir": "src"}}`,
|
||||
'libs/my-lib/tsconfig.lib.json': `{"compilerOptions": {"rootDir": "src"}}`,
|
||||
'libs/my-lib/tsconfig.json': `{}`,
|
||||
'libs/my-lib/tsconfig.lib.json': `{"compilerOptions": {"outDir": "dist"}}`,
|
||||
'libs/my-lib/tsconfig.build.json': `{}`,
|
||||
'libs/my-lib/project.json': `{}`,
|
||||
});
|
||||
@ -2027,7 +2029,9 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
"options": {
|
||||
"cwd": "libs/my-lib",
|
||||
},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
"{projectRoot}/dist",
|
||||
],
|
||||
"syncGenerators": [
|
||||
"@nx/js:typescript-sync",
|
||||
],
|
||||
@ -2043,7 +2047,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
// Sibling package.json
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': `{}`,
|
||||
'libs/my-lib/tsconfig.lib.json': `{"compilerOptions": {"rootDir": "src"}}`,
|
||||
'libs/my-lib/tsconfig.lib.json': `{"compilerOptions": {"outDir": "dist"}}`,
|
||||
'libs/my-lib/tsconfig.build.json': `{}`,
|
||||
'libs/my-lib/package.json': `{ "main": "dist/index.js" }`,
|
||||
});
|
||||
@ -2093,7 +2097,9 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
"options": {
|
||||
"cwd": "libs/my-lib",
|
||||
},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
"{projectRoot}/dist",
|
||||
],
|
||||
"syncGenerators": [
|
||||
"@nx/js:typescript-sync",
|
||||
],
|
||||
@ -2110,7 +2116,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': `{}`,
|
||||
'libs/my-lib/tsconfig.lib.json': `{}`,
|
||||
'libs/my-lib/tsconfig.build.json': `{"compilerOptions": {"rootDir": "src"}}`,
|
||||
'libs/my-lib/tsconfig.build.json': `{"compilerOptions": {"outDir": "dist"}}`,
|
||||
'libs/my-lib/project.json': `{}`,
|
||||
});
|
||||
expect(
|
||||
@ -2159,7 +2165,9 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
"options": {
|
||||
"cwd": "libs/my-lib",
|
||||
},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
"{projectRoot}/dist",
|
||||
],
|
||||
"syncGenerators": [
|
||||
"@nx/js:typescript-sync",
|
||||
],
|
||||
@ -2193,7 +2201,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: {
|
||||
rootDir: 'src',
|
||||
outDir: 'dist',
|
||||
},
|
||||
include: ['src/**/*.ts'],
|
||||
exclude: ['src/**/*.spec.ts'],
|
||||
@ -2247,7 +2255,9 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
"options": {
|
||||
"cwd": "libs/my-lib",
|
||||
},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
"{projectRoot}/dist",
|
||||
],
|
||||
"syncGenerators": [
|
||||
"@nx/js:typescript-sync",
|
||||
],
|
||||
@ -2272,7 +2282,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
extends: '../../tsconfig.foo.json',
|
||||
include: ['src/**/*.ts'],
|
||||
compilerOptions: {
|
||||
rootDir: 'src',
|
||||
outDir: 'dist',
|
||||
},
|
||||
}),
|
||||
'libs/my-lib/package.json': `{"main": "dist/index.js"}`,
|
||||
@ -2326,7 +2336,9 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
"options": {
|
||||
"cwd": "libs/my-lib",
|
||||
},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
"{projectRoot}/dist",
|
||||
],
|
||||
"syncGenerators": [
|
||||
"@nx/js:typescript-sync",
|
||||
],
|
||||
@ -2351,7 +2363,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
extends: '../../tsconfig.foo.json',
|
||||
compilerOptions: {
|
||||
rootDir: 'src',
|
||||
outDir: 'dist',
|
||||
},
|
||||
include: ['src/**/*.ts'],
|
||||
}),
|
||||
@ -2412,7 +2424,9 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
"options": {
|
||||
"cwd": "libs/my-lib",
|
||||
},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
"{projectRoot}/dist",
|
||||
],
|
||||
"syncGenerators": [
|
||||
"@nx/js:typescript-sync",
|
||||
],
|
||||
@ -2428,7 +2442,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': '{}',
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: { rootDir: 'src' },
|
||||
compilerOptions: { outDir: 'dist' },
|
||||
include: ['src/**/*.ts'],
|
||||
exclude: ['src/**/foo.ts'], // should be ignored because a referenced internal project includes this same pattern
|
||||
references: [
|
||||
@ -2494,7 +2508,9 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
"options": {
|
||||
"cwd": "libs/my-lib",
|
||||
},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
"{projectRoot}/dist",
|
||||
],
|
||||
"syncGenerators": [
|
||||
"@nx/js:typescript-sync",
|
||||
],
|
||||
@ -2511,7 +2527,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': '{}',
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: { rootDir: 'src' }, // rootDir is required to determine if the project is buildable
|
||||
compilerOptions: { outDir: 'dist' }, // outDir is required to determine if the project is buildable
|
||||
include: ['src/**/*.ts'],
|
||||
exclude: ['src/**/foo.ts'], // should be ignored
|
||||
references: [{ path: './tsconfig.other.json' }],
|
||||
@ -2548,7 +2564,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': '{}',
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: { rootDir: 'src' },
|
||||
compilerOptions: { outDir: 'dist' },
|
||||
include: ['**/*.ts'],
|
||||
exclude: ['**/foo.ts'], // should be ignored
|
||||
references: [{ path: './tsconfig.other.json' }],
|
||||
@ -2584,7 +2600,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': '{}',
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: { rootDir: 'src' }, // rooDir is required to determine if the project is buildable
|
||||
compilerOptions: { outDir: 'dist' }, // outDir is required to determine if the project is buildable
|
||||
include: ['src/**/*.ts'],
|
||||
exclude: ['src/**/foo.ts'], // should be ignored
|
||||
references: [{ path: './tsconfig.other.json' }],
|
||||
@ -2620,7 +2636,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': '{}',
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: { rootDir: 'src' },
|
||||
compilerOptions: { outDir: 'dist' },
|
||||
include: ['src/**/*.ts'],
|
||||
exclude: ['src/**/foo.ts'], // should be ignored
|
||||
references: [{ path: './tsconfig.other.json' }],
|
||||
@ -2656,7 +2672,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.json': '{}',
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: { rootDir: 'src' },
|
||||
compilerOptions: { outDir: 'dist' },
|
||||
include: ['src/**/*.ts'],
|
||||
exclude: [
|
||||
'src/**/foo.ts', // should be ignored
|
||||
@ -2696,7 +2712,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
it('should fall back to named inputs when not using include', async () => {
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: { rootDir: 'src' },
|
||||
compilerOptions: { outDir: 'dist' },
|
||||
files: ['main.ts'],
|
||||
}),
|
||||
'libs/my-lib/tsconfig.json': `{}`,
|
||||
@ -2746,19 +2762,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
"cwd": "libs/my-lib",
|
||||
},
|
||||
"outputs": [
|
||||
"{projectRoot}/**/*.js",
|
||||
"{projectRoot}/**/*.cjs",
|
||||
"{projectRoot}/**/*.mjs",
|
||||
"{projectRoot}/**/*.jsx",
|
||||
"{projectRoot}/**/*.js.map",
|
||||
"{projectRoot}/**/*.jsx.map",
|
||||
"{projectRoot}/**/*.d.ts",
|
||||
"{projectRoot}/**/*.d.cts",
|
||||
"{projectRoot}/**/*.d.mts",
|
||||
"{projectRoot}/**/*.d.ts.map",
|
||||
"{projectRoot}/**/*.d.cts.map",
|
||||
"{projectRoot}/**/*.d.mts.map",
|
||||
"{projectRoot}/tsconfig.lib.tsbuildinfo",
|
||||
"{projectRoot}/dist",
|
||||
],
|
||||
"syncGenerators": [
|
||||
"@nx/js:typescript-sync",
|
||||
@ -2778,12 +2782,11 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: {
|
||||
outFile: '../../dist/libs/my-lib/index.js',
|
||||
rootDir: 'src',
|
||||
},
|
||||
files: ['main.ts'],
|
||||
}),
|
||||
'libs/my-lib/tsconfig.json': `{}`,
|
||||
'libs/my-lib/package.json': `{"main": "dist/libs/my-lib/index.js"}`,
|
||||
'libs/my-lib/package.json': `{}`,
|
||||
});
|
||||
expect(
|
||||
await invokeCreateNodesOnMatchingFiles(context, {
|
||||
@ -2851,12 +2854,11 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: {
|
||||
outDir: '../../dist/libs/my-lib',
|
||||
rootDir: 'src',
|
||||
},
|
||||
files: ['main.ts'],
|
||||
}),
|
||||
'libs/my-lib/tsconfig.json': `{}`,
|
||||
'libs/my-lib/package.json': `{"main": "dist/libs/my-lib/index.js"}`,
|
||||
'libs/my-lib/package.json': `{"main": "../../dist/libs/my-lib/index.js"}`,
|
||||
});
|
||||
expect(
|
||||
await invokeCreateNodesOnMatchingFiles(context, {
|
||||
@ -2919,7 +2921,6 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
it('should add the inline output files when `outDir` is not defined', async () => {
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: { rootDir: 'src' },
|
||||
files: ['main.ts'],
|
||||
}),
|
||||
'libs/my-lib/tsconfig.json': `{}`,
|
||||
@ -3000,7 +3001,6 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: {
|
||||
outFile: '../../dist/libs/my-lib/lib.js',
|
||||
rootDir: 'src',
|
||||
},
|
||||
files: ['main.ts'],
|
||||
references: [{ path: './tsconfig.other.json' }],
|
||||
@ -3008,11 +3008,10 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
'libs/my-lib/tsconfig.other.json': JSON.stringify({
|
||||
compilerOptions: {
|
||||
outDir: '../../dist/libs/my-lib/other',
|
||||
rootDir: 'src',
|
||||
},
|
||||
include: ['other/**/*.ts'],
|
||||
}),
|
||||
'libs/my-lib/package.json': `{"main": "dist/libs/my-lib/lib.js"}`,
|
||||
'libs/my-lib/package.json': `{"main": "../../dist/libs/my-lib/lib.js"}`,
|
||||
});
|
||||
expect(
|
||||
await invokeCreateNodesOnMatchingFiles(context, {
|
||||
@ -3087,12 +3086,11 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: {
|
||||
outFile: '../../dist/libs/my-lib/index.js',
|
||||
rootDir: 'src',
|
||||
tsBuildInfoFile: '../../dist/libs/my-lib/my-lib.tsbuildinfo',
|
||||
},
|
||||
files: ['main.ts'],
|
||||
}),
|
||||
'libs/my-lib/package.json': `{"main": "dist/libs/my-lib/index.js"}`,
|
||||
'libs/my-lib/package.json': `{"main": "../../dist/libs/my-lib/index.js"}`,
|
||||
});
|
||||
expect(
|
||||
await invokeCreateNodesOnMatchingFiles(context, {
|
||||
@ -3159,7 +3157,6 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
'libs/my-lib/tsconfig.json': '{}',
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: {
|
||||
rootDir: 'src',
|
||||
tsBuildInfoFile: '../../dist/libs/my-lib/my-lib.tsbuildinfo',
|
||||
},
|
||||
files: ['main.ts'],
|
||||
@ -3239,7 +3236,6 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: {
|
||||
rootDir: 'src',
|
||||
outDir: 'dist',
|
||||
tsBuildInfoFile: 'my-lib.tsbuildinfo',
|
||||
},
|
||||
@ -3312,7 +3308,6 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||
compilerOptions: {
|
||||
outDir: 'dist',
|
||||
rootDir: 'src',
|
||||
tsBuildInfoFile: 'dist/my-lib.tsbuildinfo',
|
||||
},
|
||||
files: ['main.ts'],
|
||||
|
||||
@ -22,6 +22,7 @@ import { existsSync, readdirSync, statSync } from 'node:fs';
|
||||
import {
|
||||
basename,
|
||||
dirname,
|
||||
extname,
|
||||
join,
|
||||
normalize,
|
||||
relative,
|
||||
@ -210,6 +211,11 @@ async function createNodesInternal(
|
||||
projectRoot
|
||||
);
|
||||
|
||||
const packageJsonPath = joinPathFragments(projectRoot, 'package.json');
|
||||
const packageJson = existsSync(packageJsonPath)
|
||||
? readJsonFile(packageJsonPath)
|
||||
: null;
|
||||
|
||||
const nodeHash = hashArray([
|
||||
...[
|
||||
fullConfigPath,
|
||||
@ -219,6 +225,7 @@ async function createNodesInternal(
|
||||
join(context.workspaceRoot, lockFileName),
|
||||
].map(hashFile),
|
||||
hashObject(options),
|
||||
...(packageJson ? [hashObject(packageJson)] : []),
|
||||
]);
|
||||
const cacheKey = `${nodeHash}_${configFilePath}`;
|
||||
|
||||
@ -325,12 +332,7 @@ function buildTscTargets(
|
||||
if (
|
||||
options.build &&
|
||||
basename(configFilePath) === options.build.configName &&
|
||||
isValidPackageJsonBuildConfig(
|
||||
tsConfig,
|
||||
context.workspaceRoot,
|
||||
projectRoot,
|
||||
configFilePath
|
||||
)
|
||||
isValidPackageJsonBuildConfig(tsConfig, context.workspaceRoot, projectRoot)
|
||||
) {
|
||||
internalProjectReferences ??= resolveInternalProjectReferences(
|
||||
tsConfig,
|
||||
@ -618,21 +620,22 @@ function getOutputs(
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a `package.json` file has a valid build configuration by ensuring
|
||||
* that the `main`, `module`, or `exports` do not include paths from the `rootDir`.
|
||||
* Or if `outFile` is defined, it should not be within the `rootDir`.
|
||||
* Validates the build configuration of a `package.json` file by ensuring that paths in the `exports`, `module`,
|
||||
* and `main` fields reference valid output paths within the `outDir` defined in the TypeScript configuration.
|
||||
* Priority is given to the `exports` field, specifically the `.` export if defined. If `exports` is not defined,
|
||||
* the function falls back to validating `main` and `module` fields. If `outFile` is specified, it validates that the file
|
||||
* is located within the output directory.
|
||||
* If no `package.json` file exists, it assumes the configuration is valid.
|
||||
*
|
||||
* @param tsConfig The TypeScript configuration object.
|
||||
* @param workspaceRoot The workspace root path.
|
||||
* @param projectRoot The project root path.
|
||||
* @param tsConfigPath The path to the TypeScript configuration file.
|
||||
* @returns `true` if the package has a valid build configuration; otherwise, `false`.
|
||||
*/
|
||||
function isValidPackageJsonBuildConfig(
|
||||
tsConfig,
|
||||
workspaceRoot: string,
|
||||
projectRoot: string,
|
||||
tsConfigPath: string
|
||||
projectRoot: string
|
||||
): boolean {
|
||||
if (!existsSync(joinPathFragments(projectRoot, 'package.json'))) {
|
||||
// If the package.json file does not exist.
|
||||
@ -643,42 +646,30 @@ function isValidPackageJsonBuildConfig(
|
||||
joinPathFragments(projectRoot, 'package.json')
|
||||
);
|
||||
|
||||
const rootDir = tsConfig.options.rootDir ?? 'src/';
|
||||
if (!tsConfig.options.rootDir) {
|
||||
console.warn(
|
||||
`The 'rootDir' option is not set in the tsconfig file at ${tsConfigPath}. Assuming 'src/' as the root directory.`
|
||||
);
|
||||
}
|
||||
const outDir = tsConfig.options.outFile
|
||||
? dirname(tsConfig.options.outFile)
|
||||
: tsConfig.options.outDir;
|
||||
const resolvedOutDir = outDir
|
||||
? resolve(workspaceRoot, projectRoot, outDir)
|
||||
: undefined;
|
||||
|
||||
const isPathWithinSrc = (path: string): boolean => {
|
||||
const resolvedRootDir = resolve(workspaceRoot, projectRoot, rootDir);
|
||||
const pathToCheck = resolve(workspaceRoot, projectRoot, path);
|
||||
const isPathSourceFile = (path: string): boolean => {
|
||||
if (resolvedOutDir) {
|
||||
const pathToCheck = resolve(workspaceRoot, projectRoot, path);
|
||||
return !pathToCheck.startsWith(resolvedOutDir);
|
||||
}
|
||||
|
||||
return pathToCheck.startsWith(resolvedRootDir);
|
||||
const ext = extname(path);
|
||||
// Check that the file extension is a TS file extension. As the source files are in the same directory as the output files.
|
||||
return ['.ts', '.tsx', '.cts', '.mts'].includes(ext);
|
||||
};
|
||||
|
||||
// If `outFile` is defined, check the validity of the path.
|
||||
if (tsConfig.options.outFile) {
|
||||
if (isPathWithinSrc(tsConfig.options.outFile)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const buildPaths = ['main', 'module'];
|
||||
for (const field of buildPaths) {
|
||||
if (packageJson[field] && isPathWithinSrc(packageJson[field])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const exports = packageJson?.exports;
|
||||
|
||||
// Checks if the value is a path within the `src` directory.
|
||||
const containsInvalidPath = (
|
||||
value: string | Record<string, string>
|
||||
): boolean => {
|
||||
if (typeof value === 'string') {
|
||||
return isPathWithinSrc(value);
|
||||
return isPathSourceFile(value);
|
||||
} else if (typeof value === 'object') {
|
||||
return Object.entries(value).some(([currentKey, subValue]) => {
|
||||
// Skip types field
|
||||
@ -686,7 +677,7 @@ function isValidPackageJsonBuildConfig(
|
||||
return false;
|
||||
}
|
||||
if (typeof subValue === 'string') {
|
||||
return isPathWithinSrc(subValue);
|
||||
return isPathSourceFile(subValue);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@ -694,17 +685,34 @@ function isValidPackageJsonBuildConfig(
|
||||
return false;
|
||||
};
|
||||
|
||||
if (typeof exports === 'string' && isPathWithinSrc(exports)) {
|
||||
return false;
|
||||
}
|
||||
const exports = packageJson?.exports;
|
||||
|
||||
// Check nested exports if `exports` is an object.
|
||||
if (typeof exports === 'object') {
|
||||
for (const key in exports) {
|
||||
if (containsInvalidPath(exports[key])) {
|
||||
// Check the `.` export if `exports` is defined.
|
||||
if (exports) {
|
||||
if (typeof exports === 'string') {
|
||||
return !isPathSourceFile(exports);
|
||||
} else if (typeof exports === 'object' && '.' in exports) {
|
||||
if (containsInvalidPath(exports['.'])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check other exports if `.` is not defined or valid.
|
||||
for (const key in exports) {
|
||||
if (key !== '.' && containsInvalidPath(exports[key])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// If `exports` is not defined, fallback to `main` and `module` fields.
|
||||
const buildPaths = ['main', 'module'];
|
||||
for (const field of buildPaths) {
|
||||
if (packageJson[field] && isPathSourceFile(packageJson[field])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user