diff --git a/README.md b/README.md index 2207858..e6b4f7c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,8 @@ npx update-ts-references --help --check Checks if updates would be necessary (without applying them) --help Show help --createTsConfig Create default TS configs for packages where the main entry in the package.json have a ts|tsx extension (Note: respects the --configName parameter) - --cwd Set working directory. Default: /Users/mirko.kruschke/coding/ecg-public/update-ts-references + -createPathMappings Create paths mappings under compilerOptions for a better IDE support. It respects the rootDir if no rootDir available it falls back to "src" + --cwd Set working directory. Default: /Users/john-doe/projects/my-project --verbose Show verbose output. Default: false ``` @@ -46,7 +47,7 @@ npx husky add .husky/pre-push "npx update-ts-references --check" git add .husky/pre-push ``` -## using --creatTsConfig +## using --createTsConfig Creates a basic tsconfig file for each package where the main entry in the package.json have a `.ts` or `.tsx` extension. It will respect the `--configName` parameter. The output for the created file looks like the following @@ -66,10 +67,37 @@ The output for the created file looks like the following } ``` +## using --createPathMappings +will create path mappings under `compilerOptions` for a better IDE support. It respects the `rootDir` if no `rootDir` available it falls back to `src` + +```json +{ + "extends": "../tsconfig.base.json", // add's extends in case you have a base config in the root directory + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "paths": { // will be added after running update-ts-references with --createPathMappings + "@my-project/some-other-package": ["../some-other-package/src"] + } + }, + "references": [ // will be added after running update-ts-references + { + "path": "../some-other-package" + } + ] +} +``` + + ## using update-ts-references.yaml for configurations -You can configure paths via the _update-ts-references.yaml_ file. This is useful if your repo is having **no** _package.json_ or _pnp-workspace.yaml_ in the root folder. Additional to that it can also being used to extend the paths config next to the normal workspace setup via npm, pnpm, yarn and lerna so you can include or exclude some packages. +You can configure workspace paths via the _update-ts-references.yaml_ file. This is useful if your repo is having **no** _package.json_ or _pnp-workspace.yaml_ in the root folder. Additional to that it can also being used to extend the paths config next to the normal workspace setup via npm, pnpm, yarn and lerna so you can include or exclude some packages. + +Additional to that you can configure also the following options: +- configName (default: tsconfig.json) +- rootConfigName (default: tsconfig.json) +- createPathMappings (default: false) -Example configuration see [here](./test-scenarios/ts-ref-yaml/update-ts-references.yaml) +Example configuration see [here](./test-scenarios/ts-options-yaml/update-ts-references.yaml) diff --git a/package.json b/package.json index eb07af9..3b4c78c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "update-ts-references", - "version": "3.0.0", + "version": "3.1.0", "description": "Updates TypeScript references automatically while using workspaces", "bin": "src/index.js", "scripts": { diff --git a/src/index.js b/src/index.js index 0a15a38..5027afa 100755 --- a/src/index.js +++ b/src/index.js @@ -13,8 +13,8 @@ const { help = defaultOptions.help, h = defaultOptions.help, check = defaultOptions.check, + createPathMappings = defaultOptions.createPathMappings, } = minimist(process.argv.slice(2)); -console.log('->',createTsConfig) if (help || h) { console.log(` Usage: update-ts-references [options] @@ -24,6 +24,7 @@ if (help || h) { --check Checks if updates would be necessary (without applying them) --help Show help --createTsConfig Create default TS configs for packages where the main entry in the package.json have a ts|tsx extension (Note: respects the --configName parameter) + --createPathMappings Create paths mappings under compilerOptions for a better IDE support. It respects the rootDir if no rootDir available it falls back to "src" --cwd Set working directory. Default: ${defaultOptions.cwd} --verbose Show verbose output. Default: ${defaultOptions.verbose} `); @@ -38,7 +39,8 @@ const run = async () => { check, configName, rootConfigName, - createTsConfig + createTsConfig, + createPathMappings }); if (check && changesCount > 0) { diff --git a/src/update-ts-references.js b/src/update-ts-references.js index ae6fa4a..da9c0fb 100644 --- a/src/update-ts-references.js +++ b/src/update-ts-references.js @@ -4,9 +4,9 @@ const fs = require('fs'); const yaml = require('js-yaml'); const minimatch = require('minimatch'); const { - parse, - stringify, - assign + parse, + stringify, + assign } = require('comment-json') const assert = require('assert').strict; @@ -14,297 +14,325 @@ const PACKAGE_JSON = 'package.json'; const TSCONFIG_JSON = 'tsconfig.json' const defaultOptions = { - configName: TSCONFIG_JSON, - rootConfigName: TSCONFIG_JSON, - createTsConfig: false, - cwd: process.cwd(), - verbose: false, - help: false, - check: false, + configName: TSCONFIG_JSON, + rootConfigName: TSCONFIG_JSON, + createTsConfig: false, + cwd: process.cwd(), + verbose: false, + help: false, + check: false, + createPathMappings: false }; -const getAllPackageJsons = async (workspaces,cwd) => { - const ignoreGlobs = []; - const workspaceGlobs = []; +const getAllPackageJsons = async (workspaces, cwd) => { + const ignoreGlobs = []; + const workspaceGlobs = []; - workspaces.forEach((workspaceGlob) => { - if (workspaceGlob.startsWith('!')) { - ignoreGlobs.push(!workspaceGlob.includes('/') ? `${workspaceGlob}/${PACKAGE_JSON}`: workspaceGlob); - } else { - workspaceGlobs.push(workspaceGlob); - } - }); - - return Promise.all( - workspaceGlobs.map( - (workspace) => - new Promise((resolve, reject) => { - glob(`${workspace}/${PACKAGE_JSON}`, {cwd},(error, files) => { - if (error) { - reject(error); - } - resolve(files); - }); - }), + workspaces.forEach((workspaceGlob) => { + if (workspaceGlob.startsWith('!')) { + ignoreGlobs.push(!workspaceGlob.includes('/') ? `${workspaceGlob}/${PACKAGE_JSON}` : workspaceGlob); + } else { + workspaceGlobs.push(workspaceGlob); + } + }); - [] + return Promise.all( + workspaceGlobs.map( + (workspace) => + new Promise((resolve, reject) => { + glob(`${workspace}/${PACKAGE_JSON}`, {cwd}, (error, files) => { + if (error) { + reject(error); + } + resolve(files); + }); + }), + + [] + ) ) - ) - .then((allPackages) => - allPackages.reduce( - (flattendArray, files) => [...flattendArray, ...files], - [] - ) - ) - .then((allPackages) => - allPackages.filter( - (packageName) => - ignoreGlobs.reduce((prev, actualPattern) => { - if (!prev) return prev; - - return minimatch(packageName, actualPattern); - }, true) && !packageName.includes('node_modules') - ) - ); + .then((allPackages) => + allPackages.reduce( + (flattendArray, files) => [...flattendArray, ...files], + [] + ) + ) + .then((allPackages) => + allPackages.filter( + (packageName) => + ignoreGlobs.reduce((prev, actualPattern) => { + if (!prev) return prev; + + return minimatch(packageName, actualPattern); + }, true) && !packageName.includes('node_modules') + ) + ); }; -const detectTSConfig = (directory, configName, createConfig,cwd) => { - let detectedConfig = fs.existsSync(path.join(directory, configName)) ? configName : null - if (configName !== TSCONFIG_JSON && detectedConfig === null) { - detectedConfig = fs.existsSync(path.join(directory, TSCONFIG_JSON)) ? TSCONFIG_JSON : null - } - if(detectedConfig === null && createConfig) { - let maybeExtends = {} - if(fs.existsSync(path.join(cwd, 'tsconfig.base.json'))) { - maybeExtends = { - extends: `${path.join(path.relative(directory,cwd),"tsconfig.base.json").split(path.sep).join(path.posix.sep)}`, +const detectTSConfig = (directory, configName, createConfig, cwd) => { + let detectedConfig = fs.existsSync(path.join(directory, configName)) ? configName : null + if (configName !== TSCONFIG_JSON && detectedConfig === null) { + detectedConfig = fs.existsSync(path.join(directory, TSCONFIG_JSON)) ? TSCONFIG_JSON : null + } + if (detectedConfig === null && createConfig) { + let maybeExtends = {} + if (fs.existsSync(path.join(cwd, 'tsconfig.base.json'))) { + maybeExtends = { + extends: `${path.join(path.relative(directory, cwd), "tsconfig.base.json").split(path.sep).join(path.posix.sep)}`, + } } + const tsconfigFilePath = path.join(directory, configName); + fs.writeFileSync(tsconfigFilePath, stringify(Object.assign(maybeExtends, { + compilerOptions: { + outDir: "dist", + rootDir: "src" + }, + references: [], + }), null, 2) + '\n'); + + return configName } - const tsconfigFilePath = path.join(directory, configName); - fs.writeFileSync(tsconfigFilePath, stringify(Object.assign(maybeExtends,{ - compilerOptions: { - outDir: "dist", - rootDir: "src" - }, - references: [], - }), null, 2) + '\n'); - - return configName - } - return detectedConfig + return detectedConfig } const getPackageNamesAndPackageDir = (packageFilePaths, cwd) => - packageFilePaths.reduce((map, packageFilePath) => { - const fullPackageFilePath = path.join(cwd, packageFilePath); - const packageJson = require(fullPackageFilePath); - const { name } = packageJson; - map.set(name, { - packageDir: path.dirname(fullPackageFilePath), - hasTsEntry: /\.(ts|tsx)$/.test((packageJson.main ? packageJson.main :'')) - }); - return map; - }, new Map()); + packageFilePaths.reduce((map, packageFilePath) => { + const fullPackageFilePath = path.join(cwd, packageFilePath); + const packageJson = require(fullPackageFilePath); + const {name} = packageJson; + map.set(name, { + packageDir: path.dirname(fullPackageFilePath), + hasTsEntry: /\.(ts|tsx)$/.test((packageJson.main ? packageJson.main : '')) + }); + return map; + }, new Map()); const getReferencesFromDependencies = ( - configName, - { packageDir }, - packageName, - packagesMap, - verbose + configName, + {packageDir}, + packageName, + packagesMap, + verbose ) => { - const packageJsonFilePath = path.join(packageDir, PACKAGE_JSON); - - const { - dependencies = {}, - peerDependencies = {}, - devDependencies = {}, - } = require(packageJsonFilePath); - - const mergedDependencies = { - ...dependencies, - ...peerDependencies, - ...devDependencies, - }; - if (verbose) console.log(`all deps from ${packageName}`, mergedDependencies); - - if (Object.keys(mergedDependencies).includes(packageName)) { - throw new Error( - `This package ${packageName} references itself, please check dependencies in package.json` - ); - } - - return Object.keys(mergedDependencies) - .reduce((referenceArray, dependency) => { - if (packagesMap.has(dependency)) { - const { packageDir: dependencyDir } = packagesMap.get(dependency); - const relativePath = path.relative(packageDir, dependencyDir); - const detectedConfig = detectTSConfig(dependencyDir, configName) - if (detectedConfig !== null) { - return [ - ...referenceArray, - { - path: detectedConfig !== TSCONFIG_JSON ? path.join(relativePath, detectedConfig) : relativePath, - }, - ]; - } - } - return referenceArray; - }, []) - .sort((refA, refB) => (refA.path > refB.path ? 1 : -1)); + const packageJsonFilePath = path.join(packageDir, PACKAGE_JSON); + + const { + dependencies = {}, + peerDependencies = {}, + devDependencies = {}, + } = require(packageJsonFilePath); + + const mergedDependencies = { + ...dependencies, + ...peerDependencies, + ...devDependencies, + }; + if (verbose) console.log(`all deps from ${packageName}`, mergedDependencies); + + if (Object.keys(mergedDependencies).includes(packageName)) { + throw new Error( + `This package ${packageName} references itself, please check dependencies in package.json` + ); + } + + return Object.keys(mergedDependencies) + .reduce((referenceArray, dependency) => { + if (packagesMap.has(dependency)) { + const {packageDir: dependencyDir} = packagesMap.get(dependency); + const relativePath = path.relative(packageDir, dependencyDir); + const detectedConfig = detectTSConfig(dependencyDir, configName) + if (detectedConfig !== null) { + return [ + ...referenceArray, + { + name: dependency, + path: detectedConfig !== TSCONFIG_JSON ? path.join(relativePath, detectedConfig) : relativePath, + folder: relativePath, + }, + ]; + } + } + return referenceArray; + }, []) + .sort((refA, refB) => (refA.path > refB.path ? 1 : -1)); }; const ensurePosixPathStyle = (reference) => ({ - ...reference, - path: reference.path.split(path.sep).join(path.posix.sep), + ...reference, + path: reference.path.split(path.sep).join(path.posix.sep), + folder: reference.folder.split(path.sep).join(path.posix.sep), }); const updateTsConfig = ( - configName, - win32OrPosixReferences, - check, - { packageDir } = { packageDir: process.cwd() } + configName, + win32OrPosixReferences, + check, + createPathMappings = false, + {packageDir} = {packageDir: process.cwd()}, ) => { - const references = (win32OrPosixReferences || []).map(ensurePosixPathStyle); - const tsconfigFilePath = path.join(packageDir, configName); + const references = (win32OrPosixReferences || []).map(ensurePosixPathStyle); + const tsconfigFilePath = path.join(packageDir, configName); - try { - const config = parse(fs.readFileSync(tsconfigFilePath).toString()); + try { + const config = parse(fs.readFileSync(tsconfigFilePath).toString()); - const currentReferences = config.references || []; + const currentReferences = config.references || []; - const mergedReferences = references.map((ref) => ({ - ...ref, - ...currentReferences.find((currentRef) => currentRef.path === ref.path), - })); + const mergedReferences = references.map(({path}) => ({ + path, + ...currentReferences.find((currentRef) => currentRef.path === path), + })); - let isEqual = false; - try { - assert.deepEqual(JSON.parse(JSON.stringify(currentReferences)), mergedReferences); - isEqual = true; - } catch (e) { - // ignore me - } - if (!isEqual) { - if (check === false) { - const newTsConfig = assign(config, - { - references: mergedReferences.length ? mergedReferences : undefined, - } - ); - fs.writeFileSync(tsconfigFilePath, stringify(newTsConfig, null, 2) + '\n'); - } - return 1; + let isEqual = false; + try { + assert.deepEqual(JSON.parse(JSON.stringify(currentReferences)), mergedReferences); + isEqual = true; + } catch (e) { + // ignore me + } + if (!isEqual) { + if (check === false) { + + const compilerOptions = config?.compilerOptions ?? {}; + if (createPathMappings) + assign(compilerOptions, { + paths: references.reduce((paths, ref) => ({ + ...paths, + [`${ref.name}`]: [`${ref.folder}/${config.compilerOptions?.rootDir ?? 'src'}`] + }), {}) + }) + + const newTsConfig = assign(config, + { + compilerOptions, + references: mergedReferences.length ? mergedReferences : undefined, + } + ); + fs.writeFileSync(tsconfigFilePath, stringify(newTsConfig, null, 2) + '\n'); + } + return 1; + } + return 0; + } catch (error) { + console.error(`could not read ${tsconfigFilePath}`, error); } - return 0; - } catch (error) { - console.error(`could not read ${tsconfigFilePath}`, error); - } }; const execute = async ({ - cwd, createTsConfig, - verbose, - check, - configName, - rootConfigName -}) => { - let changesCount = 0; - // eslint-disable-next-line no-console - console.log('updating tsconfigs'); - const packageJson = require(path.join(cwd, PACKAGE_JSON)); - - let workspaces = packageJson.workspaces; - if(workspaces && !Array.isArray(workspaces)) { - workspaces = workspaces.packages; - } - - if (!workspaces && fs.existsSync(path.join(cwd, 'lerna.json'))) { - const lernaJson = require(path.join(cwd, 'lerna.json')); - workspaces = lernaJson.packages; - } - - if (!workspaces && fs.existsSync(path.join(cwd, 'pnpm-workspace.yaml'))) { - const pnpmConfig = yaml.load( - fs.readFileSync(path.join(cwd, 'pnpm-workspace.yaml')) - ); - workspaces = pnpmConfig.packages; - } + cwd, createTsConfig, + verbose, + check, + ...configurable + }) => { + let changesCount = 0; + // eslint-disable-next-line no-console + console.log('updating tsconfigs'); + const packageJson = require(path.join(cwd, PACKAGE_JSON)); + + let workspaces = packageJson.workspaces; + if (workspaces && !Array.isArray(workspaces)) { + workspaces = workspaces.packages; + } - if (fs.existsSync(path.join(cwd, 'update-ts-references.yaml'))) { - const config = yaml.load( - fs.readFileSync(path.join(cwd, 'update-ts-references.yaml')) - ); + if (!workspaces && fs.existsSync(path.join(cwd, 'lerna.json'))) { + const lernaJson = require(path.join(cwd, 'lerna.json')); + workspaces = lernaJson.packages; + } - workspaces = [...(config.packages ? config.packages : []), ...(workspaces ? workspaces : [])]; + if (!workspaces && fs.existsSync(path.join(cwd, 'pnpm-workspace.yaml'))) { + const pnpmConfig = yaml.load( + fs.readFileSync(path.join(cwd, 'pnpm-workspace.yaml')) + ); + workspaces = pnpmConfig.packages; + } - if (verbose) { - console.log('joined workspaces config', workspaces); + let { + configName, + rootConfigName, + createPathMappings + } = configurable + + if (fs.existsSync(path.join(cwd, 'update-ts-references.yaml'))) { + const yamlConfig = yaml.load( + fs.readFileSync(path.join(cwd, 'update-ts-references.yaml')) + ); + configName = yamlConfig.configName ?? configName + rootConfigName = yamlConfig.rootConfigName ?? rootConfigName + createPathMappings = yamlConfig.createPathMappings ?? createPathMappings + workspaces = [...(yamlConfig.packages ? yamlConfig.packages : []), ...(workspaces ? workspaces : [])]; + + if (verbose) { + console.log(`configName ${configName}`); + console.log(`rootConfigName ${rootConfigName}`); + console.log(`createPathMappings ${createPathMappings}`) + console.log('joined workspaces', workspaces); + } } - } - if (!workspaces) { - throw new Error( - 'could not detect yarn/npm/pnpm workspaces or lerna in this repository' - ); - } + if (!workspaces) { + throw new Error( + 'could not detect yarn/npm/pnpm workspaces or lerna in this repository' + ); + } - const packageFilePaths = await getAllPackageJsons(workspaces, cwd); - if (verbose) { - console.log('packageFilePaths', packageFilePaths); - } - const packagesMap = getPackageNamesAndPackageDir(packageFilePaths, cwd); + const packageFilePaths = await getAllPackageJsons(workspaces, cwd); + if (verbose) { + console.log('packageFilePaths', packageFilePaths); + } + const packagesMap = getPackageNamesAndPackageDir(packageFilePaths, cwd); - if (verbose) { - console.log('packagesMap', packagesMap); - } + if (verbose) { + console.log('packagesMap', packagesMap); + } - const rootReferences = []; + const rootReferences = []; + + packagesMap.forEach((packageEntry, packageName) => { + const detectedConfig = detectTSConfig(packageEntry.packageDir, configName, packageEntry.hasTsEntry && createTsConfig, cwd) + + if (detectedConfig) { + rootReferences.push({ + name: packageName, + path: path.join(path.relative(cwd, packageEntry.packageDir), detectedConfig !== TSCONFIG_JSON ? detectedConfig : ''), + folder: path.relative(cwd, packageEntry.packageDir), + }); + const references = getReferencesFromDependencies( + configName, + packageEntry, + packageName, + packagesMap, + verbose + ); + if (verbose) { + console.log(`references of ${packageName}`, references); + } + changesCount += updateTsConfig( + detectedConfig, + references, + check, + createPathMappings, + packageEntry + ); + } else { + // eslint-disable-next-line no-console + console.log(`NO ${configName === TSCONFIG_JSON ? configName : `${configName} nor ${TSCONFIG_JSON}`} for ${packageName}`); + } + }); - packagesMap.forEach((packageEntry, packageName) => { - const detectedConfig = detectTSConfig(packageEntry.packageDir, configName, packageEntry.hasTsEntry && createTsConfig,cwd) + if (verbose) { + console.log('rootReferences', rootReferences); + } + changesCount += updateTsConfig( + rootConfigName, + rootReferences, + check, false, {packageDir: cwd} + ); - if (detectedConfig) { - rootReferences.push({ - path: path.join(path.relative(cwd, packageEntry.packageDir), detectedConfig !== TSCONFIG_JSON ? detectedConfig : ''), - }); - const references = getReferencesFromDependencies( - configName, - packageEntry, - packageName, - packagesMap, - verbose - ); - if (verbose) { - console.log(`references of ${packageName}`, references); - } - changesCount += updateTsConfig( - detectedConfig, - references, - check, - packageEntry - ); - } else { - // eslint-disable-next-line no-console - console.log(`NO ${configName === TSCONFIG_JSON ? configName : `${configName} nor ${TSCONFIG_JSON}`} for ${packageName}`); + if (verbose) { + console.log(`counted changes ${changesCount}`); } - }); - - if (verbose) { - console.log('rootReferences', rootReferences); - } - changesCount += updateTsConfig( - rootConfigName, - rootReferences, - check, {packageDir:cwd} - - ); - - if (verbose) { - console.log(`counted changes ${changesCount}`); - } - return changesCount; + return changesCount; }; -module.exports = { execute, defaultOptions }; +module.exports = {execute, defaultOptions}; diff --git a/test-scenarios/ts-options-yaml/package.json b/test-scenarios/ts-options-yaml/package.json new file mode 100644 index 0000000..73a13fb --- /dev/null +++ b/test-scenarios/ts-options-yaml/package.json @@ -0,0 +1,13 @@ +{ + "name": "ts-ref-yaml-workspace", + "version": "0.0.1", + "private": true, + "workspaces": [ + "workspace-b", + "shared/*", + "utils/**/" + ], + "devDependencies": { + "typescript": "latest" + } +} diff --git a/test-scenarios/ts-options-yaml/tsconfig.root.json b/test-scenarios/ts-options-yaml/tsconfig.root.json new file mode 100644 index 0000000..23b6225 --- /dev/null +++ b/test-scenarios/ts-options-yaml/tsconfig.root.json @@ -0,0 +1,8 @@ +{ + "files": [], + "compilerOptions": { + /* Basic Options */ + // "allowJs": true, + "composite": true + } +} diff --git a/test-scenarios/ts-options-yaml/update-ts-references.yaml b/test-scenarios/ts-options-yaml/update-ts-references.yaml new file mode 100644 index 0000000..338df0d --- /dev/null +++ b/test-scenarios/ts-options-yaml/update-ts-references.yaml @@ -0,0 +1,9 @@ +configName: 'tsconfig.dev.json' +rootConfigName: 'tsconfig.root.json' +createPathMappings: true +packages: + # all packages in subdirs of packages/ and components/ + - 'workspace-a' + # exclude packages that are inside test directories + - '!**/tests/**' + - '!workspace-ignore' diff --git a/test-scenarios/ts-options-yaml/workspace-a/package.json b/test-scenarios/ts-options-yaml/workspace-a/package.json new file mode 100644 index 0000000..6b40e48 --- /dev/null +++ b/test-scenarios/ts-options-yaml/workspace-a/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspace-a", + "version": "1.0.0", + "dependencies": { + "workspace-b": "1.0.0" + } +} diff --git a/test-scenarios/ts-options-yaml/workspace-a/tsconfig.dev.json b/test-scenarios/ts-options-yaml/workspace-a/tsconfig.dev.json new file mode 100644 index 0000000..1dd8e13 --- /dev/null +++ b/test-scenarios/ts-options-yaml/workspace-a/tsconfig.dev.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + } +} diff --git a/test-scenarios/ts-options-yaml/workspace-b/package.json b/test-scenarios/ts-options-yaml/workspace-b/package.json new file mode 100644 index 0000000..552cf0e --- /dev/null +++ b/test-scenarios/ts-options-yaml/workspace-b/package.json @@ -0,0 +1,10 @@ +{ + "name": "workspace-b", + "version": "1.0.0", + "dependencies": { + "cross-env": "5.0.5" + }, + "devDependencies": { + "foo-b": "1.0.0" + } +} diff --git a/test-scenarios/ts-options-yaml/workspace-b/tsconfig.dev.json b/test-scenarios/ts-options-yaml/workspace-b/tsconfig.dev.json new file mode 100644 index 0000000..1dd8e13 --- /dev/null +++ b/test-scenarios/ts-options-yaml/workspace-b/tsconfig.dev.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + } +} diff --git a/test-scenarios/ts-options-yaml/workspace-ignore/package.json b/test-scenarios/ts-options-yaml/workspace-ignore/package.json new file mode 100644 index 0000000..280f2d0 --- /dev/null +++ b/test-scenarios/ts-options-yaml/workspace-ignore/package.json @@ -0,0 +1,10 @@ +{ + "name": "ignore", + "version": "1.0.0", + "dependencies": { + "cross-env": "5.0.5" + }, + "devDependencies": { + "foo-b": "1.0.0" + } +} diff --git a/test-scenarios/ts-options-yaml/workspace-ignore/tsconfig.json b/test-scenarios/ts-options-yaml/workspace-ignore/tsconfig.json new file mode 100644 index 0000000..1dd8e13 --- /dev/null +++ b/test-scenarios/ts-options-yaml/workspace-ignore/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + } +} diff --git a/test-scenarios/ts-paths/package.json b/test-scenarios/ts-paths/package.json new file mode 100644 index 0000000..e29972f --- /dev/null +++ b/test-scenarios/ts-paths/package.json @@ -0,0 +1,14 @@ +{ + "name": "ts-ref-yaml-workspace", + "version": "0.0.1", + "private": true, + "workspaces": [ + "workspace-a", + "workspace-b", + "shared/*", + "utils/**/" + ], + "devDependencies": { + "typescript": "latest" + } +} diff --git a/test-scenarios/ts-paths/tsconfig.json b/test-scenarios/ts-paths/tsconfig.json new file mode 100644 index 0000000..23b6225 --- /dev/null +++ b/test-scenarios/ts-paths/tsconfig.json @@ -0,0 +1,8 @@ +{ + "files": [], + "compilerOptions": { + /* Basic Options */ + // "allowJs": true, + "composite": true + } +} diff --git a/test-scenarios/ts-paths/utils/foos/foo-a/package.json b/test-scenarios/ts-paths/utils/foos/foo-a/package.json new file mode 100644 index 0000000..699ec9c --- /dev/null +++ b/test-scenarios/ts-paths/utils/foos/foo-a/package.json @@ -0,0 +1,7 @@ +{ + "name": "foo-a", + "version": "1.0.0", + "dependencies": { + "foo-b": "1.0.0" + } +} diff --git a/test-scenarios/ts-paths/utils/foos/foo-a/tsconfig.json b/test-scenarios/ts-paths/utils/foos/foo-a/tsconfig.json new file mode 100644 index 0000000..aa3d6e5 --- /dev/null +++ b/test-scenarios/ts-paths/utils/foos/foo-a/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src2" + } +} diff --git a/test-scenarios/ts-paths/utils/foos/foo-b/package.json b/test-scenarios/ts-paths/utils/foos/foo-b/package.json new file mode 100644 index 0000000..2c997b8 --- /dev/null +++ b/test-scenarios/ts-paths/utils/foos/foo-b/package.json @@ -0,0 +1,4 @@ +{ + "name": "foo-b", + "version": "1.0.0" +} diff --git a/test-scenarios/ts-paths/utils/foos/foo-b/tsconfig.json b/test-scenarios/ts-paths/utils/foos/foo-b/tsconfig.json new file mode 100644 index 0000000..1dd8e13 --- /dev/null +++ b/test-scenarios/ts-paths/utils/foos/foo-b/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + } +} diff --git a/test-scenarios/ts-paths/workspace-a/package.json b/test-scenarios/ts-paths/workspace-a/package.json new file mode 100644 index 0000000..f35aa29 --- /dev/null +++ b/test-scenarios/ts-paths/workspace-a/package.json @@ -0,0 +1,10 @@ +{ + "name": "workspace-a", + "version": "1.0.0", + "dependencies": { + "workspace-b": "1.0.0" + }, + "devDependencies": { + "foo-a": "1.0.0" + } +} diff --git a/test-scenarios/ts-paths/workspace-a/tsconfig.json b/test-scenarios/ts-paths/workspace-a/tsconfig.json new file mode 100644 index 0000000..1dd8e13 --- /dev/null +++ b/test-scenarios/ts-paths/workspace-a/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + } +} diff --git a/test-scenarios/ts-paths/workspace-b/package.json b/test-scenarios/ts-paths/workspace-b/package.json new file mode 100644 index 0000000..552cf0e --- /dev/null +++ b/test-scenarios/ts-paths/workspace-b/package.json @@ -0,0 +1,10 @@ +{ + "name": "workspace-b", + "version": "1.0.0", + "dependencies": { + "cross-env": "5.0.5" + }, + "devDependencies": { + "foo-b": "1.0.0" + } +} diff --git a/test-scenarios/ts-paths/workspace-b/tsconfig.json b/test-scenarios/ts-paths/workspace-b/tsconfig.json new file mode 100644 index 0000000..1dd8e13 --- /dev/null +++ b/test-scenarios/ts-paths/workspace-b/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + } +} diff --git a/tests/setup.js b/tests/setup.js new file mode 100644 index 0000000..96868d1 --- /dev/null +++ b/tests/setup.js @@ -0,0 +1,28 @@ +const execSh = require('exec-sh').promise; +const fs = require('fs'); + +const setup = async (rootFolder, configName, rootConfigName, createTsConfig, createPathMappings) => { + if (!fs.existsSync(rootFolder)) { + throw new Error(`folder is missing -> ${rootFolder}`); + } + + try { + await execSh( + `npx update-ts-references --verbose${ + configName ? ` --configName ${configName}` : '' + }${ + rootConfigName ? ` --rootConfigName ${rootConfigName}` : '' + }${createTsConfig ? ` --createTsConfig` : ''}${createPathMappings ? ` --createPathMappings` : ''}`, + { + cwd: rootFolder, + } + ); + } catch (e) { + console.log('Error: ', e); + console.log('Stderr: ', e.stderr); + console.log('Stdout: ', e.stdout); + throw e; + } +}; + +module.exports = { setup } diff --git a/tests/update-ts-references.test.js b/tests/update-ts-references.test.js index 1507a67..39cfa0b 100644 --- a/tests/update-ts-references.test.js +++ b/tests/update-ts-references.test.js @@ -1,13 +1,14 @@ -const execSh = require('exec-sh').promise; const path = require('path'); +const execSh = require('exec-sh').promise; const fs = require('fs'); -const { parse } = require("comment-json") +const {parse} = require("comment-json") +const {setup} = require('./setup'); const rootFolderYarn = path.join(process.cwd(), 'test-run', 'yarn-ws'); const rootFolderYarnNohoist = path.join( - process.cwd(), - 'test-run', - 'yarn-ws-nohoist' + process.cwd(), + 'test-run', + 'yarn-ws-nohoist' ); const rootFolderYarnCreate = path.join( @@ -16,452 +17,504 @@ const rootFolderYarnCreate = path.join( 'yarn-ws-create' ); const rootFolderPnpm = path.join(process.cwd(), 'test-run', 'pnpm'); -const rootFolderTsRefYaml = path.join(process.cwd(), 'test-run', 'ts-ref-yaml'); +const rootFolderTsPaths = path.join(process.cwd(), 'test-run', 'ts-paths'); const rootFolderYarnCheck = path.join( - process.cwd(), - 'test-run', - 'yarn-ws-check' + process.cwd(), + 'test-run', + 'yarn-ws-check' ); const rootFolderYarnCheckNoChanges = path.join( - process.cwd(), - 'test-run', - 'yarn-ws-check-no-changes' + process.cwd(), + 'test-run', + 'yarn-ws-check-no-changes' ); const rootFolderLerna = path.join(process.cwd(), 'test-run', 'lerna'); const rootFolderConfigName = path.join( - process.cwd(), - 'test-run', - 'yarn-ws-custom-tsconfig-names' + process.cwd(), + 'test-run', + 'yarn-ws-custom-tsconfig-names' ); -const compilerOptions = { outDir: 'dist', rootDir: 'src' }; - -const setup = async (rootFolder, configName, rootConfigName, createTsConfig) => { - if (!fs.existsSync(rootFolder)) { - throw new Error(`folder is missing -> ${rootFolder}`); - } - - try { - await execSh( - `npx update-ts-references --verbose${ - configName ? ` --configName ${configName}` : '' - }${ - rootConfigName ? ` --rootConfigName ${rootConfigName}` : '' - }${createTsConfig ? ` --createTsConfig` : ''}`, - { - cwd: rootFolder, - } - ); - } catch (e) { - console.log('Error: ', e); - console.log('Stderr: ', e.stderr); - console.log('Stdout: ', e.stdout); - throw e; - } -}; +const compilerOptions = {outDir: 'dist', rootDir: 'src'}; + const rootTsConfig = [ - '.', - { - compilerOptions: { - composite: true, + '.', + { + compilerOptions: { + composite: true, + }, + files: [], + references: [ + { + path: 'workspace-a', + }, + { + path: 'workspace-b', + }, + { + path: 'shared/workspace-c', + }, + { + path: 'shared/workspace-d', + }, + { + path: 'utils/foos/foo-a', + }, + { + path: 'utils/foos/foo-b', + }, + ], }, - files: [], - references: [ - { - path: 'workspace-a', - }, - { - path: 'workspace-b', - }, - { - path: 'shared/workspace-c', - }, - { - path: 'shared/workspace-d', - }, - { - path: 'utils/foos/foo-a', - }, - { - path: 'utils/foos/foo-b', - }, - ], - }, ]; const wsATsConfig = [ - './workspace-a', - { - compilerOptions, - references: [ - { - path: '../utils/foos/foo-a', - }, - { - path: '../workspace-b', - }, - ], - }, + './workspace-a', + { + compilerOptions, + references: [ + { + path: '../utils/foos/foo-a', + }, + { + path: '../workspace-b', + }, + ], + }, ]; const wsBTsConfig = [ - './workspace-b', - { - compilerOptions, - - references: [ - { - path: '../utils/foos/foo-b', - }, - ], - }, + './workspace-b', + { + compilerOptions, + + references: [ + { + path: '../utils/foos/foo-b', + }, + ], + }, ]; const wsCTsConfig = [ - './shared/workspace-c', - { - compilerOptions, - - references: [ - { - path: '../../utils/foos/foo-a', - }, - ], - }, + './shared/workspace-c', + { + compilerOptions, + + references: [ + { + path: '../../utils/foos/foo-a', + }, + ], + }, ]; const wsDTsConfig = [ - './shared/workspace-d', - { - compilerOptions, - - references: [ - { - path: '../workspace-c', - }, - ], - }, + './shared/workspace-d', + { + compilerOptions, + + references: [ + { + path: '../workspace-c', + }, + ], + }, ]; const fooATsConfig = [ - './utils/foos/foo-a', - { - compilerOptions, - references: [ - { - path: '../foo-b', - }, - ], - }, + './utils/foos/foo-a', + { + compilerOptions, + references: [ + { + path: '../foo-b', + }, + ], + }, ]; const fooBTsConfig = [ - './utils/foos/foo-b', - { - compilerOptions, - references: undefined, - }, + './utils/foos/foo-b', + { + compilerOptions, + references: undefined, + }, ]; const tsconfigs = [ - rootTsConfig, - wsATsConfig, - wsBTsConfig, - wsCTsConfig, - wsDTsConfig, - fooATsConfig, - fooBTsConfig, + rootTsConfig, + wsATsConfig, + wsBTsConfig, + wsCTsConfig, + wsDTsConfig, + fooATsConfig, + fooBTsConfig, ]; const tsconfigsIncludingPrepend = [ - rootTsConfig, - [ - './workspace-a', - { - compilerOptions, - references: [ - { - path: '../utils/foos/foo-a', - prepend: false, - }, + rootTsConfig, + [ + './workspace-a', { - path: '../workspace-b', + compilerOptions, + references: [ + { + path: '../utils/foos/foo-a', + prepend: false, + }, + { + path: '../workspace-b', + }, + ], }, - ], - }, - ], - wsBTsConfig, - wsCTsConfig, - wsDTsConfig, - fooATsConfig, - fooBTsConfig, + ], + wsBTsConfig, + wsCTsConfig, + wsDTsConfig, + fooATsConfig, + fooBTsConfig, ]; test('Support yarn and npm workspaces', async () => { - await setup(rootFolderYarn); + await setup(rootFolderYarn); - tsconfigsIncludingPrepend.forEach((tsconfig) => { - const [configPath, config] = tsconfig; + tsconfigsIncludingPrepend.forEach((tsconfig) => { + const [configPath, config] = tsconfig; - expect( - parse(fs.readFileSync(path.join(rootFolderYarn, configPath, 'tsconfig.json')).toString()) - ).toEqual(config); + expect( + parse(fs.readFileSync(path.join(rootFolderYarn, configPath, 'tsconfig.json')).toString()) + ).toEqual(config); - }); - // still has the comment - expect(fs.readFileSync(path.join(rootFolderYarn, 'tsconfig.json')).toString()).toMatch(/\/\* Basic Options \*\//) + }); + // still has the comment + expect(fs.readFileSync(path.join(rootFolderYarn, 'tsconfig.json')).toString()).toMatch(/\/\* Basic Options \*\//) }); test('Support lerna', async () => { - await setup(rootFolderLerna); + await setup(rootFolderLerna); - tsconfigs.forEach((tsconfig) => { - const [configPath, config] = tsconfig; + tsconfigs.forEach((tsconfig) => { + const [configPath, config] = tsconfig; - expect( - parse(fs.readFileSync(path.join(rootFolderLerna, configPath, 'tsconfig.json')).toString()) - ).toEqual(config); - }); + expect( + parse(fs.readFileSync(path.join(rootFolderLerna, configPath, 'tsconfig.json')).toString()) + ).toEqual(config); + }); }); test('Support yarn and npm workspaces with noHoist', async () => { - await setup(rootFolderYarnNohoist); + await setup(rootFolderYarnNohoist); - tsconfigs.forEach((tsconfig) => { - const [configPath, config] = tsconfig; + tsconfigs.forEach((tsconfig) => { + const [configPath, config] = tsconfig; - expect( - parse(fs.readFileSync(path.join(rootFolderYarnNohoist, configPath, 'tsconfig.json')).toString()) - ).toEqual(config); - }); + expect( + parse(fs.readFileSync(path.join(rootFolderYarnNohoist, configPath, 'tsconfig.json')).toString()) + ).toEqual(config); + }); }); test('Support pnpm workspaces', async () => { - await setup(rootFolderPnpm); + await setup(rootFolderPnpm); - tsconfigs.forEach((tsconfig) => { - const [configPath, config] = tsconfig; + tsconfigs.forEach((tsconfig) => { + const [configPath, config] = tsconfig; - expect( - parse(fs.readFileSync(path.join(rootFolderPnpm, configPath, 'tsconfig.json')).toString()) - ).toEqual(config); - }); + expect( + parse(fs.readFileSync(path.join(rootFolderPnpm, configPath, 'tsconfig.json')).toString()) + ).toEqual(config); + }); }); -test('Support update-ts-reference.yaml workspaces', async () => { - await setup(rootFolderTsRefYaml); +test('create paths mappings ', async () => { + await setup(rootFolderTsPaths, undefined, undefined, undefined, true); - tsconfigs.forEach((tsconfig) => { - const [configPath, config] = tsconfig; - expect( - parse(fs.readFileSync(path.join(rootFolderTsRefYaml, configPath, 'tsconfig.json')).toString()) - ).toEqual(config); - }); + const rootTsConfig = [ + '.', + { + compilerOptions: { + composite: true, + }, + files: [], + references: [ + { + path: 'workspace-a', + }, + { + path: 'workspace-b', + }, + { + path: 'utils/foos/foo-a', + }, + { + path: 'utils/foos/foo-b', + }, + ], + }, + ]; + + const wsATsConfig = [ + './workspace-a', + { + compilerOptions: { + ...compilerOptions, + paths: {"foo-a": ["../utils/foos/foo-a/src"], "workspace-b": ["../workspace-b/src"]} + }, + references: [ + { + path: '../utils/foos/foo-a', + }, + { + path: '../workspace-b', + }, + ], + }, + ]; + + const wsBTsConfig = [ + './workspace-b', + { + compilerOptions: {...compilerOptions, paths: {"foo-b": ["../utils/foos/foo-b/src"]}}, + references: [ + { + path: '../utils/foos/foo-b', + }, + ], + }, + ]; + + const fooATsConfig = [ + './utils/foos/foo-a', + { + compilerOptions: { + ...compilerOptions, + rootDir: "src2", + paths: { + "foo-b": ["../foo-b/src2"] + }, + }, + references: [ + { + path: '../foo-b', + }, + ], + }, + ]; + + const fooBTsConfig = [ + './utils/foos/foo-b', + { + compilerOptions, + references: undefined, + }, + ]; + [rootTsConfig, wsATsConfig, wsBTsConfig, fooATsConfig, fooBTsConfig].forEach((tsconfig) => { + const [configPath, config] = tsconfig; + + expect( + parse(fs.readFileSync(path.join(rootFolderTsPaths, configPath, 'tsconfig.json')).toString()) + ).toEqual(config); + }); - // should not touch the ignore config - expect( - parse(fs.readFileSync(path.join(rootFolderTsRefYaml,'workspace-ignore', 'tsconfig.json')).toString()) - ).toEqual( {compilerOptions}); }); test('Test create tsconfig', async () => { - await setup(rootFolderYarnCreate, undefined, undefined,true); - const r = [ - '.', - { - extends: [`./tsconfig.base.json`], - compilerOptions: { - composite: true, - }, - files: [], - references: [ + await setup(rootFolderYarnCreate, undefined, undefined, true); + const r = [ + '.', { - path: 'workspace-a', + extends: [`./tsconfig.base.json`], + compilerOptions: { + composite: true, + }, + files: [], + references: [ + { + path: 'workspace-a', + }, + { + path: 'workspace-b', + } + ], }, + ]; + const a = [ + './workspace-a', { - path: 'workspace-b', - } - ], - }, - ]; - const a = [ - './workspace-a', - { - extends: "../tsconfig.base.json", - compilerOptions: { - outDir: "dist", - rootDir: "src" - }, - references: [ + extends: "../tsconfig.base.json", + compilerOptions: { + outDir: "dist", + rootDir: "src" + }, + references: [ + { + path: '../workspace-b', + }, + ], + }, + ]; + const b = [ + './workspace-b', { - path: '../workspace-b', + compilerOptions }, - ], - }, - ]; - const b = [ - './workspace-b', - { - compilerOptions - }, - ]; + ]; - [r,a,b].forEach((tsconfig) => { - const [configPath, config] = tsconfig; + [r, a, b].forEach((tsconfig) => { + const [configPath, config] = tsconfig; - expect( - parse(fs.readFileSync(path.join(rootFolderYarnCreate, configPath, 'tsconfig.json')).toString()) - ).toEqual(config); - }); - expect(fs.existsSync(path.join(rootFolderYarnCreate,'workspace-c', 'tsconfig.json'))).toBeFalsy(); + expect( + parse(fs.readFileSync(path.join(rootFolderYarnCreate, configPath, 'tsconfig.json')).toString()) + ).toEqual(config); + }); + expect(fs.existsSync(path.join(rootFolderYarnCreate, 'workspace-c', 'tsconfig.json'))).toBeFalsy(); }); test('Detect changes with the --check option', async () => { - let errorCode = 0; - try { - await execSh('npx update-ts-references --check', { - stdio: null, - cwd: rootFolderYarnCheck, + let errorCode = 0; + try { + await execSh('npx update-ts-references --check', { + stdio: null, + cwd: rootFolderYarnCheck, + }); + } catch (e) { + errorCode = e.code; + } + + expect(errorCode).toBe(6); + + tsconfigs.forEach((tsconfig) => { + const [configPath] = tsconfig; + + expect( + parse(fs.readFileSync(path.join(rootFolderYarnCheck, configPath, 'tsconfig.json')).toString()).references + ).toBeFalsy(); }); - } catch (e) { - errorCode = e.code; - } - - expect(errorCode).toBe(6); - - tsconfigs.forEach((tsconfig) => { - const [configPath] = tsconfig; - - expect( - parse(fs.readFileSync(path.join(rootFolderYarnCheck, configPath, 'tsconfig.json')).toString()).references - ).toBeFalsy(); - }); }); test('No changes detected with the --check option', async () => { - let errorCode = 0; - try { - await execSh('npx update-ts-references --check', { - stdio: null, - cwd: rootFolderYarnCheckNoChanges, + let errorCode = 0; + try { + await execSh('npx update-ts-references --check', { + stdio: null, + cwd: rootFolderYarnCheckNoChanges, + }); + } catch (e) { + errorCode = e.code; + } + + expect(errorCode).toBe(0); + + tsconfigs.forEach((tsconfig) => { + const [configPath, config] = tsconfig; + + expect( + parse(fs.readFileSync(path.join(rootFolderYarnCheckNoChanges, configPath, 'tsconfig.json')).toString()) + ).toEqual(config); }); - } catch (e) { - errorCode = e.code; - } - - expect(errorCode).toBe(0); - - tsconfigs.forEach((tsconfig) => { - const [configPath, config] = tsconfig; - - expect( - parse(fs.readFileSync(path.join(rootFolderYarnCheckNoChanges, configPath, 'tsconfig.json')).toString()) - ).toEqual(config); - }); }); - test('Support custom tsconfig names', async () => { - const configName = 'tsconfig.dev.json'; - const rootConfigName = 'tsconfig.ref.json'; - const rootFolder = rootFolderConfigName; - await setup(rootFolder, configName, rootConfigName); - - const tsconfigs = [ - [ - '.', - { - compilerOptions: { - composite: true, - }, - files: [], - references: [ - { - path: 'workspace-a/tsconfig.dev.json', - }, - { - path: 'workspace-b/tsconfig.dev.json', - }, - { - path: 'shared/workspace-c/tsconfig.dev.json', - }, - { - path: 'shared/workspace-d/tsconfig.dev.json', - }, - { - path: 'utils/foos/foo-a/tsconfig.dev.json', - }, - { - path: 'utils/foos/foo-b', - }, + const configName = 'tsconfig.dev.json'; + const rootConfigName = 'tsconfig.ref.json'; + const rootFolder = rootFolderConfigName; + await setup(rootFolder, configName, rootConfigName); + + const tsconfigs = [ + [ + '.', + { + compilerOptions: { + composite: true, + }, + files: [], + references: [ + { + path: 'workspace-a/tsconfig.dev.json', + }, + { + path: 'workspace-b/tsconfig.dev.json', + }, + { + path: 'shared/workspace-c/tsconfig.dev.json', + }, + { + path: 'shared/workspace-d/tsconfig.dev.json', + }, + { + path: 'utils/foos/foo-a/tsconfig.dev.json', + }, + { + path: 'utils/foos/foo-b', + }, + ], + }, + rootConfigName ], - }, - rootConfigName - ], - [ - './workspace-a', - { - compilerOptions, - references: [ - { - path: '../utils/foos/foo-a/tsconfig.dev.json', - prepend: false, - }, - { - path: '../workspace-b/tsconfig.dev.json', - }, + [ + './workspace-a', + { + compilerOptions, + references: [ + { + path: '../utils/foos/foo-a/tsconfig.dev.json', + prepend: false, + }, + { + path: '../workspace-b/tsconfig.dev.json', + }, + ], + }, ], - }, - ], - wsBTsConfig, - [ - './shared/workspace-c', - { - compilerOptions, - - references: [ - { - path: '../../utils/foos/foo-a/tsconfig.dev.json', - }, + wsBTsConfig, + [ + './shared/workspace-c', + { + compilerOptions, + + references: [ + { + path: '../../utils/foos/foo-a/tsconfig.dev.json', + }, + ], + }, ], - }, - ], - [ - './shared/workspace-d', - { - compilerOptions, - - references: [ - { - path: '../workspace-c/tsconfig.dev.json', - }, + [ + './shared/workspace-d', + { + compilerOptions, + + references: [ + { + path: '../workspace-c/tsconfig.dev.json', + }, + ], + }, ], - }, - ], - [ - './utils/foos/foo-a', - { - compilerOptions, - references: [ - { - path: '../foo-b', - }, + [ + './utils/foos/foo-a', + { + compilerOptions, + references: [ + { + path: '../foo-b', + }, + ], + }, ], - }, - ], - [...fooBTsConfig, 'tsconfig.json'], - ]; - - tsconfigs.forEach((tsconfig) => { - const [configPath, config, configNameOverride] = tsconfig; - expect( - parse(fs.readFileSync(path.join(rootFolder, configPath, configNameOverride || configName)).toString()) - ).toEqual( - config - ); - }); + [...fooBTsConfig, 'tsconfig.json'], + ]; + + tsconfigs.forEach((tsconfig) => { + const [configPath, config, configNameOverride] = tsconfig; + expect( + parse(fs.readFileSync(path.join(rootFolder, configPath, configNameOverride || configName)).toString()) + ).toEqual( + config + ); + }); }); diff --git a/tests/update-ts-references.yaml.test.js b/tests/update-ts-references.yaml.test.js new file mode 100644 index 0000000..1fd1e5b --- /dev/null +++ b/tests/update-ts-references.yaml.test.js @@ -0,0 +1,197 @@ +const {setup} = require('./setup'); +const path = require('path'); +const fs = require('fs'); +const {parse} = require("comment-json") + +const rootFolderTsRefYaml = path.join(process.cwd(), 'test-run', 'ts-ref-yaml'); +const rootFolderTsOptionsYaml = path.join(process.cwd(), 'test-run', 'ts-options-yaml'); + +const compilerOptions = {outDir: 'dist', rootDir: 'src'}; + +const rootTsConfig = [ + '.', + { + compilerOptions: { + composite: true, + }, + files: [], + references: [ + { + path: 'workspace-a', + }, + { + path: 'workspace-b', + }, + { + path: 'shared/workspace-c', + }, + { + path: 'shared/workspace-d', + }, + { + path: 'utils/foos/foo-a', + }, + { + path: 'utils/foos/foo-b', + }, + ], + }, +]; + +const wsATsConfig = [ + './workspace-a', + { + compilerOptions, + references: [ + { + path: '../utils/foos/foo-a', + }, + { + path: '../workspace-b', + }, + ], + }, +]; + +const wsBTsConfig = [ + './workspace-b', + { + compilerOptions, + + references: [ + { + path: '../utils/foos/foo-b', + }, + ], + }, +]; + +const wsCTsConfig = [ + './shared/workspace-c', + { + compilerOptions, + + references: [ + { + path: '../../utils/foos/foo-a', + }, + ], + }, +]; + +const wsDTsConfig = [ + './shared/workspace-d', + { + compilerOptions, + + references: [ + { + path: '../workspace-c', + }, + ], + }, +]; + +const fooATsConfig = [ + './utils/foos/foo-a', + { + compilerOptions, + references: [ + { + path: '../foo-b', + }, + ], + }, +]; + +const fooBTsConfig = [ + './utils/foos/foo-b', + { + compilerOptions, + references: undefined, + }, +]; + +const tsconfigs = [ + rootTsConfig, + wsATsConfig, + wsBTsConfig, + wsCTsConfig, + wsDTsConfig, + fooATsConfig, + fooBTsConfig, +]; + + +test('Support update-ts-reference.yaml workspaces', async () => { + await setup(rootFolderTsRefYaml); + + tsconfigs.forEach((tsconfig) => { + const [configPath, config] = tsconfig; + + expect( + parse(fs.readFileSync(path.join(rootFolderTsRefYaml, configPath, 'tsconfig.json')).toString()) + ).toEqual(config); + }); + + // should not touch the ignore config + expect( + parse(fs.readFileSync(path.join(rootFolderTsRefYaml, 'workspace-ignore', 'tsconfig.json')).toString()) + ).toEqual({compilerOptions}); +}); + +test('receive options via the config', async () => { + await setup(rootFolderTsOptionsYaml); + const root = [ + '.', + { + compilerOptions: { + composite: true, + }, + files: [], + references: [ + { + path: 'workspace-a/tsconfig.dev.json', + }, + { + path: 'workspace-b/tsconfig.dev.json', + }, + ], + }, + ]; + + const a = [ + './workspace-a', + { + compilerOptions: { + ...compilerOptions, + paths: {"workspace-b": ["../workspace-b/src"]} + }, + references: [ + { + path: '../workspace-b/tsconfig.dev.json', + }, + ], + }, + ]; + + const b = [ + './workspace-b', + { + compilerOptions, + }, + ]; + + [root,a,b].forEach((tsconfig) => { + const [configPath, config] = tsconfig; + + expect( + parse(fs.readFileSync(path.join(rootFolderTsOptionsYaml, configPath, configPath === '.'?'tsconfig.root.json':'tsconfig.dev.json')).toString()) + ).toEqual(config); + }); + + // should not touch the ignore config + expect( + parse(fs.readFileSync(path.join(rootFolderTsOptionsYaml, 'workspace-ignore', 'tsconfig.json')).toString()) + ).toEqual({compilerOptions}); +});