From 8793c639c083c33714da0a29429b338776813d0c Mon Sep 17 00:00:00 2001 From: JounQin Date: Wed, 28 Feb 2024 01:11:59 +0800 Subject: [PATCH] fix: drop `resolve-from`, `resolve-global` and `import-fresh`, resolve global packages correctly (#3939) * fix: drop `resolve-from`, `resolve-global` and `import-fresh`, resolve global packages correctly close #3938 * chore: fix Windows compatible issue --- @commitlint/cli/package.json | 2 - @commitlint/cli/src/cli.ts | 8 +-- @commitlint/load/src/load.test.ts | 5 +- @commitlint/load/src/load.ts | 4 ++ @commitlint/resolve-extends/package.json | 5 +- @commitlint/resolve-extends/src/index.ts | 83 +++++++++++++++--------- yarn.lock | 9 +-- 7 files changed, 63 insertions(+), 53 deletions(-) diff --git a/@commitlint/cli/package.json b/@commitlint/cli/package.json index b846aab378..112cac008f 100644 --- a/@commitlint/cli/package.json +++ b/@commitlint/cli/package.json @@ -54,8 +54,6 @@ "@commitlint/read": "^19.0.0", "@commitlint/types": "^19.0.0", "execa": "^8.0.1", - "resolve-from": "^5.0.0", - "resolve-global": "^2.0.0", "yargs": "^17.0.0" }, "gitHead": "70f7f4688b51774e7ac5e40e896cdaa3f132b2bc" diff --git a/@commitlint/cli/src/cli.ts b/@commitlint/cli/src/cli.ts index 367a5186d5..b871d2fa56 100644 --- a/@commitlint/cli/src/cli.ts +++ b/@commitlint/cli/src/cli.ts @@ -4,7 +4,7 @@ import {fileURLToPath, pathToFileURL} from 'url'; import util from 'util'; import lint from '@commitlint/lint'; -import load from '@commitlint/load'; +import load, {resolveFromSilent, resolveGlobalSilent} from '@commitlint/load'; import read from '@commitlint/read'; import type { Formatter, @@ -16,8 +16,6 @@ import type { } from '@commitlint/types'; import type {Options} from 'conventional-commits-parser'; import {execa, type ExecaError} from 'execa'; -import resolveFrom from 'resolve-from'; -import {resolveGlobalSilent} from 'resolve-global'; import yargs, {type Arguments} from 'yargs'; import {CliFlags} from './types.js'; @@ -458,8 +456,8 @@ function loadFormatter( ): Promise { const moduleName = flags.format || config.formatter || '@commitlint/format'; const modulePath = - resolveFrom.silent(__dirname, moduleName) || - resolveFrom.silent(flags.cwd, moduleName) || + resolveFromSilent(moduleName, __dirname) || + resolveFromSilent(moduleName, flags.cwd) || resolveGlobalSilent(moduleName); if (modulePath) { diff --git a/@commitlint/load/src/load.test.ts b/@commitlint/load/src/load.test.ts index b47219b15d..fbf1d84ddd 100644 --- a/@commitlint/load/src/load.test.ts +++ b/@commitlint/load/src/load.test.ts @@ -5,9 +5,8 @@ import {fileURLToPath} from 'url'; import {RuleConfigSeverity} from '@commitlint/types'; import {fix, git, npm} from '@commitlint/test'; -import resolveFrom from 'resolve-from'; -import load from './load.js'; +import load, {resolveFrom} from './load.js'; import {isDynamicAwaitSupported} from './utils/load-config.js'; const __dirname = path.resolve(fileURLToPath(import.meta.url), '..'); @@ -459,7 +458,7 @@ test('resolves formatter relative from config directory', async () => { const actual = await load({}, {cwd}); expect(actual).toMatchObject({ - formatter: resolveFrom(cwd, './formatters/custom.js'), + formatter: resolveFrom('./formatters/custom.js', cwd), extends: [], plugins: {}, rules: {}, diff --git a/@commitlint/load/src/load.ts b/@commitlint/load/src/load.ts index 77c2cb0851..0d63e74f7d 100644 --- a/@commitlint/load/src/load.ts +++ b/@commitlint/load/src/load.ts @@ -4,6 +4,8 @@ import {validateConfig} from '@commitlint/config-validator'; import executeRule from '@commitlint/execute-rule'; import resolveExtends, { resolveFrom, + resolveFromSilent, + resolveGlobalSilent, loadParserPreset, } from '@commitlint/resolve-extends'; import { @@ -135,3 +137,5 @@ export default async function load( prompt, }; } + +export {resolveFrom, resolveFromSilent, resolveGlobalSilent}; diff --git a/@commitlint/resolve-extends/package.json b/@commitlint/resolve-extends/package.json index 8bd53ec2b9..6de0a54afd 100644 --- a/@commitlint/resolve-extends/package.json +++ b/@commitlint/resolve-extends/package.json @@ -42,10 +42,9 @@ "dependencies": { "@commitlint/config-validator": "^19.0.0", "@commitlint/types": "^19.0.0", - "import-fresh": "^3.0.0", + "global-directory": "^4.0.1", "import-meta-resolve": "^4.0.0", - "lodash.mergewith": "^4.6.2", - "resolve-global": "^2.0.0" + "lodash.mergewith": "^4.6.2" }, "gitHead": "d829bf6260304ca8d6811f329fcdd1b6c50e9749" } diff --git a/@commitlint/resolve-extends/src/index.ts b/@commitlint/resolve-extends/src/index.ts index f8b18a08ac..744f357cff 100644 --- a/@commitlint/resolve-extends/src/index.ts +++ b/@commitlint/resolve-extends/src/index.ts @@ -1,13 +1,12 @@ +import fs from 'fs'; import path from 'path'; import {pathToFileURL, fileURLToPath} from 'url'; -import 'resolve-global'; - +import globalDirectory from 'global-directory'; import {moduleResolve} from 'import-meta-resolve'; import mergeWith from 'lodash.mergewith'; import {validateConfig} from '@commitlint/config-validator'; import type {ParserPreset, UserConfig} from '@commitlint/types'; -import importFresh from 'import-fresh'; const dynamicImport = async (id: string): Promise => { const imported = await import( @@ -16,21 +15,42 @@ const dynamicImport = async (id: string): Promise => { return ('default' in imported && imported.default) || imported; }; +const pathSuffixes = [ + '', + '.js', + '.json', + `${path.sep}index.js`, + `${path.sep}index.json`, +]; + +const specifierSuffixes = ['', '.js', '.json', '/index.js', '/index.json']; + /** * @see moduleResolve */ -export const resolveFrom = (specifier: string, parent?: string): string => { - let resolved: URL; +export const resolveFrom = (lookup: string, parent?: string): string => { + if (path.isAbsolute(lookup)) { + for (const suffix of pathSuffixes) { + const filename = lookup + suffix; + if (fs.existsSync(filename)) { + return filename; + } + } + } + let resolveError: Error | undefined; - for (const suffix of ['', '.js', '.json', '/index.js', '/index.json']) { - try { - resolved = moduleResolve( - specifier + suffix, - pathToFileURL(parent ? parent : import.meta.url) - ); + const base = pathToFileURL( + parent + ? fs.statSync(parent).isDirectory() + ? path.join(parent, 'noop.js') + : parent + : import.meta.url + ); - return fileURLToPath(resolved); + for (const suffix of specifierSuffixes) { + try { + return fileURLToPath(moduleResolve(lookup + suffix, base)); } catch (err) { if (!resolveError) { resolveError = err as Error; @@ -90,11 +110,6 @@ export default async function resolveExtends( ); } -/** - * Fake file name to provide {@link moduleResolve} a filename to resolve from the configuration cwd - */ -const FAKE_FILE_NAME_FOR_RESOLVER = '__'; - async function loadExtends( config: UserConfig = {}, context: ResolveExtendsContext = {} @@ -117,10 +132,7 @@ async function loadExtends( typeof c === 'object' && typeof c.parserPreset === 'string' ) { - const resolvedParserPreset = resolveFrom( - c.parserPreset, - path.join(cwd, FAKE_FILE_NAME_FOR_RESOLVER) - ); + const resolvedParserPreset = resolveFrom(c.parserPreset, cwd); const parserPreset: ParserPreset = { name: c.parserPreset, @@ -207,18 +219,25 @@ function resolveId( throw Object.assign(err, {code: 'MODULE_NOT_FOUND'}); } -function resolveFromSilent(specifier: string, parent: string): string | void { +export function resolveFromSilent( + specifier: string, + parent: string +): string | void { try { - return resolveFrom( - specifier, - path.join(parent, FAKE_FILE_NAME_FOR_RESOLVER) - ); - } catch (err) {} + return resolveFrom(specifier, parent); + } catch {} } -function resolveGlobalSilent(specifier: string): string | void { - try { - const resolveGlobal = importFresh<(id: string) => string>('resolve-global'); - return resolveGlobal(specifier); - } catch (err) {} +/** + * @see https://github.com/sindresorhus/resolve-global/blob/682a6bb0bd8192b74a6294219bb4c536b3708b65/index.js#L7 + */ +export function resolveGlobalSilent(specifier: string): string | void { + for (const globalPackages of [ + globalDirectory.npm.packages, + globalDirectory.yarn.packages, + ]) { + try { + return resolveFrom(specifier, globalPackages); + } catch {} + } } diff --git a/yarn.lock b/yarn.lock index 0d8a22f491..0dca252bd3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4773,7 +4773,7 @@ ignore@^5.0.4, ignore@^5.2.0, ignore@^5.2.4: resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz" integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== -import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0: +import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -7085,13 +7085,6 @@ resolve-from@^5.0.0: resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-global@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/resolve-global/-/resolve-global-2.0.0.tgz#2ff55640800bf3692f089b6008357f75e1a27e54" - integrity sha512-gnAQ0Q/KkupGkuiMyX4L0GaBV8iFwlmoXsMtOz+DFTaKmHhOO/dSlP1RMKhpvHv/dh6K/IQkowGJBqUG0NfBUw== - dependencies: - global-directory "^4.0.1" - resolve-pkg@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-2.0.0.tgz#ac06991418a7623edc119084edc98b0e6bf05a41"