diff --git a/scripts/updateProjectReferences.ts b/scripts/updateProjectReferences.ts index 4c437083eb9c..c6769ca24e24 100644 --- a/scripts/updateProjectReferences.ts +++ b/scripts/updateProjectReferences.ts @@ -35,6 +35,20 @@ import { getWorkspacesList } from './utils/getWorkspacesList'; } }; + const parseTSConfigFile = (configPath: string) => { + try { + return fs.existsSync(configPath) + ? JSON.parse(fs.readFileSync(configPath).toString()) + : null; + } catch { + console.error(chalk.bold.red('Error while parsing file: '), configPath); + process.exit(1); + } + }; + + const isDiffInConfig = async (actualConfig: any[] = [], expectedConfig: any[] = []) => + (await serializeConfig(actualConfig)) !== (await serializeConfig(expectedConfig)); + const workspaces = getWorkspacesList(); // NOTE: Workspace keys must be sorted due to file systems being a part of the equation... @@ -54,6 +68,12 @@ import { getWorkspacesList } from './utils/getWorkspacesList'; const workspacePath = path.resolve(process.cwd(), workspace.location); const workspaceConfigPath = path.resolve(workspacePath, 'tsconfig.json'); + const workspaceLibConfigPath = path.resolve(workspacePath, 'tsconfig.lib.json'); + + // actual references of the workspace = typings from argv + parsed package.json (assigned later) + const nextWorkspaceReferences = typingPaths.map((typingPath: string) => ({ + path: path.relative(workspacePath, path.resolve(process.cwd(), typingPath)), + })); const defaultWorkspaceConfig = { extends: path.relative(workspacePath, path.resolve(process.cwd(), 'tsconfig.json')), @@ -61,19 +81,12 @@ import { getWorkspacesList } from './utils/getWorkspacesList'; include: ['.'], }; - let workspaceConfig; - try { - workspaceConfig = fs.existsSync(workspaceConfigPath) - ? JSON.parse(fs.readFileSync(workspaceConfigPath).toString()) - : defaultWorkspaceConfig; - } catch { - console.error(chalk.bold.red('Error while parsing file: '), workspaceConfigPath); - process.exit(1); - } + // parse tsconfig.json, which should exist, so if it doesn't, assign default config to have it created + const workspaceConfig = + parseTSConfigFile(workspaceConfigPath) ?? defaultWorkspaceConfig; - const nextWorkspaceReferences = typingPaths.map((typingPath: string) => ({ - path: path.relative(workspacePath, path.resolve(process.cwd(), typingPath)), - })); + // parse tsconfig.lib.json, which may not exist, and shall not be created + const workspaceLibConfig = parseTSConfigFile(workspaceLibConfigPath); Object.values(workspace.workspaceDependencies).forEach(dependencyLocation => { const dependencyPath = path.resolve(process.cwd(), dependencyLocation); @@ -90,59 +103,43 @@ import { getWorkspacesList } from './utils/getWorkspacesList'; } }); + const expectedReferences = nextWorkspaceReferences; + const expectedLibReferences = nextWorkspaceReferences.filter( + // Don't include reference to schema-utils due to issues with the @sinclair/typebox library + // When using a reference it results in incorrect imports + ({ path }) => path !== '../schema-utils', + ); + if (isTesting) { - if ( - (await serializeConfig(workspaceConfig.references ?? [])) !== - (await serializeConfig(nextWorkspaceReferences)) - ) { + const isConfigDiff = await isDiffInConfig( + workspaceConfig.references, + expectedReferences, + ); + + const isConfigLibDiff = + workspaceLibConfig !== null && + (await isDiffInConfig(workspaceLibConfig.references, expectedLibReferences)); + + if (isConfigDiff || isConfigLibDiff) { console.error( chalk.red( `TypeScript project references in ${workspace.location} are inconsistent with package.json#dependencies.`, ), chalk.red.bold(`Run "yarn update-project-references" to fix them.`), ); - process.exit(1); } return; } - workspaceConfig.references = nextWorkspaceReferences; + if (readOnlyGlobs.some((path: string) => minimatch(workspace.location, path))) return; - if (!readOnlyGlobs.some((path: string) => minimatch(workspace.location, path))) { - fs.writeFileSync(workspaceConfigPath, await serializeConfig(workspaceConfig)); - } - - // Copy references also to tsconfig.lib.json if exists - const workspaceLibConfigPath = path.resolve(workspacePath, 'tsconfig.lib.json'); - if (fs.existsSync(workspaceLibConfigPath)) { - try { - const workspaceLibConfig = JSON.parse( - fs.readFileSync(workspaceLibConfigPath).toString(), - ); + workspaceConfig.references = expectedReferences; + fs.writeFileSync(workspaceConfigPath, await serializeConfig(workspaceConfig)); - workspaceLibConfig.references = nextWorkspaceReferences.filter( - // Don't include reference to schema-utils due to issues with the @sinclair/typebox library - // When using a reference it results in incorrect imports - ({ path }) => path !== '../schema-utils', - ); - - if ( - !readOnlyGlobs.some((path: string) => minimatch(workspace.location, path)) - ) { - fs.writeFileSync( - workspaceLibConfigPath, - await serializeConfig(workspaceLibConfig, 2), - ); - } - } catch { - console.error( - chalk.bold.red('Error while parsing file: '), - workspaceLibConfigPath, - ); - process.exit(1); - } - } + if (workspaceLibConfig === null) return; + workspaceLibConfig.references = expectedLibReferences; + fs.writeFileSync(workspaceLibConfigPath, await serializeConfig(workspaceLibConfig, 2)); }); })();