diff --git a/README.md b/README.md index 59db145..725a3f0 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ npx update-ts-references --help Usage: update-ts-references [options] Options: - --configName The name of the config files which needs to be updated. Default: tsconfig.json + --configName The name of the config files which needs to be updated. Default: tsconfig.json --rootConfigName The name of the root config file which needs to be updated. Default: tsconfig.json --withoutRootConfig If you will not have a tsconfig in the root directory or don't want to update it. Default: false --check Checks if updates would be necessary (without applying them) @@ -70,7 +70,7 @@ The output for the created file looks like the following ``` ## using --createPathMappings -will create path mappings under `compilerOptions` for a better IDE support. It assumes the source files are under `src`. +will create path mappings under `compilerOptions` for a better IDE support. The generated mappings respect the `rootDir` defined in the referenced `tsconfig.json` or `jsconfig.json` and only fall back to `src` when no `rootDir` is provided. ```json { @@ -106,6 +106,14 @@ Example configuration see [here](./test-scenarios/ts-options-yaml/update-ts-refe ### using multiple configurations for different usecases Executing update-ts-references with different configurations via the parameter `--usecase`. +## about jsconfig.json support +When a dependency does not ship a `tsconfig.json` but provides a `jsconfig.json`, the reference automatically targets that file and the path mappings pick up its `rootDir` as well, if `--createPathMappings` is enabled. `jsconfig.json` files participate in package-level `references`, but they stay out of the root `tsconfig.json`. + +### in combination with the --configName argument +Currently the name of the config file derives from the the configName which is `tsconfig.json` and would look for `jsconfig.json`. + +Example: ` --configName tsconfig.test.json` would look for `jsconfig.test.json` + ## FAQ ### Why is my pnpm workspace alias not working? diff --git a/src/update-ts-references.js b/src/update-ts-references.js index 2b28499..02b213f 100644 --- a/src/update-ts-references.js +++ b/src/update-ts-references.js @@ -12,6 +12,7 @@ const assert = require('assert').strict; const PACKAGE_JSON = 'package.json'; const TSCONFIG_JSON = 'tsconfig.json' +const JSCONFIG_JSON = 'jsconfig.json' const defaultOptions = { configName: TSCONFIG_JSON, @@ -72,6 +73,15 @@ const getAllPackageJsons = async (workspaces, cwd) => { ); }; +const detectJSConfig = (directory, configName) => { + const jsConfigName = configName.replace(/^ts/, 'js') + let detectedConfig = fs.existsSync(path.join(directory, jsConfigName)) ? jsConfigName : null + if (jsConfigName !== JSCONFIG_JSON && detectedConfig === null) { + detectedConfig = fs.existsSync(path.join(directory, JSCONFIG_JSON)) ? JSCONFIG_JSON : null + } + return detectedConfig +} + const detectTSConfig = (directory, configName, createConfig, cwd) => { let detectedConfig = fs.existsSync(path.join(directory, configName)) ? configName : null if (configName !== TSCONFIG_JSON && detectedConfig === null) { @@ -154,6 +164,18 @@ const getReferencesFromDependencies = ( folder: relativePath, }, ]; + } else { + const detectedJsConfig = detectJSConfig(dependencyDir, configName) + if (detectedJsConfig !== null) { + return [ + ...referenceArray, + { + name: dependency, + path: path.join(relativePath, detectedJsConfig), + folder: relativePath, + }, + ]; + } } } return referenceArray; @@ -225,11 +247,12 @@ const updateTsConfig = ( } }; -function getPathsFromReferences(references, tsconfigMap, ignorePathMappings +function getPathsFromReferences(references, tsconfigMap, jsconfigMap, ignorePathMappings = []) { return references.reduce((paths, ref) => { if (ignorePathMappings.includes(ref.name)) return paths - const rootFolder = tsconfigMap[ref.name]?.compilerOptions?.rootDir ?? 'src' + const config = tsconfigMap[ref.name] ?? jsconfigMap[ref.name] + const rootFolder = config?.compilerOptions?.rootDir ?? 'src' return { ...paths, [`${ref.name}`]: [`${ref.folder}${rootFolder === '.' ? '' : `/${rootFolder}`}`], @@ -316,6 +339,7 @@ const execute = async ({ let rootReferences = []; let rootPaths = []; let tsconfigMap = {} + let jsconfigMap = {} packagesMap.forEach((packageEntry, packageName) => { const detectedConfig = detectTSConfig(packageEntry.packageDir, configName, packageEntry.hasTsEntry && createTsConfig, cwd) @@ -329,6 +353,25 @@ const execute = async ({ compilerOptions } } + } else { + const detectedJsConfig = detectJSConfig(packageEntry.packageDir, configName) + if (detectedJsConfig) { + + let compilerOptions + try { + compilerOptions = parse(fs.readFileSync(path.join(packageEntry.packageDir, detectedJsConfig)).toString()).compilerOptions + } catch { + //ignore + } + + jsconfigMap = { + ...jsconfigMap, + [packageName]: { + detectedConfig, + compilerOptions + } + } + } } }); @@ -349,7 +392,7 @@ const execute = async ({ verbose ) || []).map(ensurePosixPathStyle); - const paths = getPathsFromReferences(references, tsconfigMap, ignorePathMappings) + const paths = getPathsFromReferences(references, tsconfigMap, jsconfigMap, ignorePathMappings) if (verbose) { console.log(`references of ${packageName}`, references); @@ -366,8 +409,11 @@ const execute = async ({ packageEntry ); } else { - // eslint-disable-next-line no-console - console.log(`NO ${configName === TSCONFIG_JSON ? configName : `${configName} nor ${TSCONFIG_JSON}`} for ${packageName}`); + const detectedJsConfig = jsconfigMap[packageName]?.detectedConfig + if (!detectedJsConfig) { + // eslint-disable-next-line no-console + console.log(`NO ${configName === TSCONFIG_JSON ? configName : `${configName} nor ${TSCONFIG_JSON}`} for ${packageName}`); + } rootPaths.push({ name: packageName, path: path.relative(cwd, packageEntry.packageDir), @@ -377,7 +423,7 @@ const execute = async ({ }); rootReferences = (rootReferences || []).map(ensurePosixPathStyle); - rootPaths = getPathsFromReferences((rootReferences || []).map(ensurePosixPathStyle), tsconfigMap, ignorePathMappings) + rootPaths = getPathsFromReferences((rootReferences || []).map(ensurePosixPathStyle), tsconfigMap, {}, ignorePathMappings) if (verbose) { console.log('rootReferences', rootReferences); diff --git a/test-scenarios/ts-paths/utils/foos/js-only/jsconfig.json b/test-scenarios/ts-paths/utils/foos/js-only/jsconfig.json new file mode 100644 index 0000000..1dd8e13 --- /dev/null +++ b/test-scenarios/ts-paths/utils/foos/js-only/jsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + } +} diff --git a/test-scenarios/ts-paths/utils/foos/js-only/package.json b/test-scenarios/ts-paths/utils/foos/js-only/package.json new file mode 100644 index 0000000..9a90e51 --- /dev/null +++ b/test-scenarios/ts-paths/utils/foos/js-only/package.json @@ -0,0 +1,5 @@ +{ + "name": "js-only", + "version": "1.0.0", + "dependencies": {} +} diff --git a/test-scenarios/ts-paths/workspace-a/package.json b/test-scenarios/ts-paths/workspace-a/package.json index f35aa29..598f821 100644 --- a/test-scenarios/ts-paths/workspace-a/package.json +++ b/test-scenarios/ts-paths/workspace-a/package.json @@ -2,9 +2,11 @@ "name": "workspace-a", "version": "1.0.0", "dependencies": { - "workspace-b": "1.0.0" + "workspace-b": "1.0.0", + "js-only": "1.0.0", + "js-only2": "1.0.0" }, "devDependencies": { - "foo-a": "1.0.0" + "foo-a": "1.0.0" } } diff --git a/test-scenarios/yarn-ws-check-paths/package.json b/test-scenarios/yarn-ws-check-paths/package.json index f5aeb24..3f10340 100644 --- a/test-scenarios/yarn-ws-check-paths/package.json +++ b/test-scenarios/yarn-ws-check-paths/package.json @@ -5,6 +5,7 @@ "workspaces": [ "workspace-a", "workspace-b", + "workspace-c", "shared/*", "utils/**" ], diff --git a/test-scenarios/yarn-ws-check-paths/utils/foos/js-only/jsconfig.json b/test-scenarios/yarn-ws-check-paths/utils/foos/js-only/jsconfig.json new file mode 100644 index 0000000..1dd8e13 --- /dev/null +++ b/test-scenarios/yarn-ws-check-paths/utils/foos/js-only/jsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + } +} diff --git a/test-scenarios/yarn-ws-check-paths/utils/foos/js-only/package.json b/test-scenarios/yarn-ws-check-paths/utils/foos/js-only/package.json new file mode 100644 index 0000000..9a90e51 --- /dev/null +++ b/test-scenarios/yarn-ws-check-paths/utils/foos/js-only/package.json @@ -0,0 +1,5 @@ +{ + "name": "js-only", + "version": "1.0.0", + "dependencies": {} +} diff --git a/test-scenarios/yarn-ws-check-paths/workspace-a/package.json b/test-scenarios/yarn-ws-check-paths/workspace-a/package.json index f35aa29..2672597 100644 --- a/test-scenarios/yarn-ws-check-paths/workspace-a/package.json +++ b/test-scenarios/yarn-ws-check-paths/workspace-a/package.json @@ -5,6 +5,6 @@ "workspace-b": "1.0.0" }, "devDependencies": { - "foo-a": "1.0.0" + "foo-a": "1.0.0" } } diff --git a/test-scenarios/yarn-ws-check-paths/workspace-c/package.json b/test-scenarios/yarn-ws-check-paths/workspace-c/package.json new file mode 100644 index 0000000..92dea2c --- /dev/null +++ b/test-scenarios/yarn-ws-check-paths/workspace-c/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspace-c", + "version": "1.0.0", + "dependencies": { + "js-only": "1.0.0" + } +} diff --git a/test-scenarios/yarn-ws-check-paths/workspace-c/tsconfig.json b/test-scenarios/yarn-ws-check-paths/workspace-c/tsconfig.json new file mode 100644 index 0000000..27958d3 --- /dev/null +++ b/test-scenarios/yarn-ws-check-paths/workspace-c/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "references": [ + { + "path": "../utils/foos/js-only/jsconfig.json" + } + ] +} diff --git a/test-scenarios/yarn-ws-custom-tsconfig-names/shared/workspace-c/package.json b/test-scenarios/yarn-ws-custom-tsconfig-names/shared/workspace-c/package.json index a401b15..b7bc49c 100644 --- a/test-scenarios/yarn-ws-custom-tsconfig-names/shared/workspace-c/package.json +++ b/test-scenarios/yarn-ws-custom-tsconfig-names/shared/workspace-c/package.json @@ -2,7 +2,8 @@ "name": "workspace-c", "version": "1.0.0", "dependencies": { - "cross-env": "5.0.5" + "cross-env": "5.0.5", + "js-only2": "1.0.0" }, "peerDependencies": { "foo-a": "1.0.0" diff --git a/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only/jsconfig.dev.json b/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only/jsconfig.dev.json new file mode 100644 index 0000000..1dd8e13 --- /dev/null +++ b/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only/jsconfig.dev.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + } +} diff --git a/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only/package.json b/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only/package.json new file mode 100644 index 0000000..9a90e51 --- /dev/null +++ b/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only/package.json @@ -0,0 +1,5 @@ +{ + "name": "js-only", + "version": "1.0.0", + "dependencies": {} +} diff --git a/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only2/jsconfig.json b/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only2/jsconfig.json new file mode 100644 index 0000000..1dd8e13 --- /dev/null +++ b/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only2/jsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + } +} diff --git a/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only2/package.json b/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only2/package.json new file mode 100644 index 0000000..47b403b --- /dev/null +++ b/test-scenarios/yarn-ws-custom-tsconfig-names/utils/foos/js-only2/package.json @@ -0,0 +1,5 @@ +{ + "name": "js-only2", + "version": "1.0.0", + "dependencies": {} +} diff --git a/test-scenarios/yarn-ws-custom-tsconfig-names/workspace-a/package.json b/test-scenarios/yarn-ws-custom-tsconfig-names/workspace-a/package.json index f35aa29..75307be 100644 --- a/test-scenarios/yarn-ws-custom-tsconfig-names/workspace-a/package.json +++ b/test-scenarios/yarn-ws-custom-tsconfig-names/workspace-a/package.json @@ -2,9 +2,10 @@ "name": "workspace-a", "version": "1.0.0", "dependencies": { + "js-only": "1.0.0", "workspace-b": "1.0.0" }, "devDependencies": { - "foo-a": "1.0.0" + "foo-a": "1.0.0" } } diff --git a/tests/update-ts-references.check.test.js b/tests/update-ts-references.check.test.js index 7f0dfd8..5007826 100644 --- a/tests/update-ts-references.check.test.js +++ b/tests/update-ts-references.check.test.js @@ -1,7 +1,7 @@ const path = require('path'); const fs = require('fs'); -const {parse} = require("comment-json") -const {promise: execSh} = require("exec-sh"); +const { parse } = require("comment-json") +const { promise: execSh } = require("exec-sh"); const rootFolderYarnCheck = path.join( process.cwd(), @@ -29,7 +29,7 @@ const rootFolderYarnCheckPathsNoChanges = path.join( 'yarn-ws-check-paths-no-changes' ); -const compilerOptions = {outDir: 'dist', rootDir: 'src'}; +const compilerOptions = { outDir: 'dist', rootDir: 'src' }; const rootTsConfig = [ '.', @@ -215,7 +215,7 @@ test('Detect changes in paths with the --check option', async () => { errorCode = e.code; } - expect(errorCode).toBe(3); + expect(errorCode).toBe(4); const root = [ '.', { @@ -259,14 +259,26 @@ test('Detect changes in paths with the --check option', async () => { }, ]; + const c = [ + './workspace-c', + { + compilerOptions, + references: [ + { + "path": "../utils/foos/js-only/jsconfig.json", + } + ], + }, + ]; + const fooA = [ './utils/foos/foo-a', { - compilerOptions: {...compilerOptions, "paths": { "remove-me": ["../utils/remove/src"]}}, + compilerOptions: { ...compilerOptions, "paths": { "remove-me": ["../utils/remove/src"] } }, }, ]; - [root,a,b,fooA].forEach((tsconfig) => { - const [configPath,config] = tsconfig; + [root, a, b, c, fooA].forEach((tsconfig) => { + const [configPath, config] = tsconfig; expect( parse(fs.readFileSync(path.join(rootFolderYarnCheckPaths, configPath, 'tsconfig.json')).toString()) @@ -293,7 +305,7 @@ test('No changes paths detected with the --check option', async () => { { compilerOptions: { composite: true, - paths: { "foo-b": ["utils/foos/foo-b/src"]} + paths: { "foo-b": ["utils/foos/foo-b/src"] } }, files: [], references: [ @@ -315,7 +327,7 @@ test('No changes paths detected with the --check option', async () => { { compilerOptions: { ...compilerOptions, - paths: { "foo-a": ["../utils/foos/foo-a/src"], "workspace-b": ["../workspace-b/src"], } + paths: { "foo-a": ["../utils/foos/foo-a/src"], "workspace-b": ["../workspace-b/src"], } }, references: [ { diff --git a/tests/update-ts-references.test.js b/tests/update-ts-references.test.js index 6c9197c..7c8516b 100644 --- a/tests/update-ts-references.test.js +++ b/tests/update-ts-references.test.js @@ -1,6 +1,6 @@ const path = require('path'); const fs = require('fs'); -const { parse } = require("comment-json") +const { parse, CommentArray } = require("comment-json") const { setup } = require('./setup'); const rootFolderYarn = path.join(process.cwd(), 'test-run', 'yarn-ws'); @@ -301,12 +301,15 @@ test('create paths mappings ', async () => { { compilerOptions: { ...compilerOptions, - paths: { "foo-a": ["../utils/foos/foo-a/src"], "workspace-b": ["../workspace-b"] } + paths: { "foo-a": ["../utils/foos/foo-a/src"], "js-only": ["../utils/foos/js-only/src"], "workspace-b": ["../workspace-b"] } }, references: [ { path: '../utils/foos/foo-a', }, + { + path: '../utils/foos/js-only/jsconfig.json', + }, { path: '../workspace-b', }, @@ -589,6 +592,9 @@ test('Support custom tsconfig names', async () => { path: '../utils/foos/foo-a/tsconfig.dev.json', prepend: false, }, + { + path: '../utils/foos/js-only/jsconfig.dev.json', + }, { path: '../workspace-b/tsconfig.dev.json', }, @@ -605,6 +611,9 @@ test('Support custom tsconfig names', async () => { { path: '../../utils/foos/foo-a/tsconfig.dev.json', }, + { + path: '../../utils/foos/js-only2/jsconfig.json', + }, ], }, ],