diff --git a/packages/reverse-exports/package.json b/packages/reverse-exports/package.json index e31c00e06..ec1f9edb2 100644 --- a/packages/reverse-exports/package.json +++ b/packages/reverse-exports/package.json @@ -9,11 +9,7 @@ "keywords": [], "author": "", "license": "ISC", - "devDependencies": { - "@types/minimatch": "^3.0.4" - }, "dependencies": { - "minimatch": "^3.0.4", "resolve.exports": "^2.0.2" } } diff --git a/packages/reverse-exports/src/index.ts b/packages/reverse-exports/src/index.ts index 09ccc3ca6..d4abfe695 100644 --- a/packages/reverse-exports/src/index.ts +++ b/packages/reverse-exports/src/index.ts @@ -1,5 +1,4 @@ import { posix } from 'path'; -import minimatch from 'minimatch'; import { exports as resolveExports } from 'resolve.exports'; type Exports = string | string[] | { [key: string]: Exports }; @@ -82,12 +81,9 @@ export default function reversePackageExports( } const maybeKeyValuePair = _findPathRecursively(exportsObj, candidate => { - // miminatch does not treat directories as full of content without glob - if (candidate.endsWith('/')) { - candidate += '**'; - } + const regex = new RegExp(_prepareStringForRegex(candidate)); - return minimatch(relativePath, candidate); + return regex.test(relativePath); }); if (!maybeKeyValuePair) { @@ -114,3 +110,16 @@ export default function reversePackageExports( return resolvedPath.replace(/^./, name); } + +export function _prepareStringForRegex(input: string): string { + let result = input + .split('*') + .map(substr => substr.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&')) + .join('.*'); + + if (result.endsWith('/')) { + result += '.*'; + } + + return `^${result}$`; +} diff --git a/packages/reverse-exports/tests/reverse-exports.test.ts b/packages/reverse-exports/tests/reverse-exports.test.ts index de0892956..ff94db842 100644 --- a/packages/reverse-exports/tests/reverse-exports.test.ts +++ b/packages/reverse-exports/tests/reverse-exports.test.ts @@ -1,4 +1,4 @@ -import reversePackageExports, { _findPathRecursively } from '../src'; +import reversePackageExports, { _findPathRecursively, _prepareStringForRegex } from '../src'; describe('reverse exports', function () { it('exports is missing', function () { @@ -140,6 +140,24 @@ describe('reverse exports', function () { 'You tried to reverse exports for the file `./foo.bar` in package `my-addon` but it does not match any of the exports rules defined in package.json. This means it should not be possible to access directly.' ); }); + + it('conditional exports: using a single asterisk as glob for nested path', function () { + const packageJson = { + name: 'my-v2-addon', + exports: { + '.': './dist/index.js', + './*': { + types: './dist/*.d.ts', + default: './dist/*.js', + }, + './addon-main.js': './addon-main.js', + }, + }; + + expect(reversePackageExports(packageJson, './dist/_app_/components/welcome-page.js')).toBe( + 'my-v2-addon/_app_/components/welcome-page' + ); + }); }); describe('_findKeyRecursively', function () { @@ -260,3 +278,16 @@ describe('_findKeyRecursively', function () { expect(_findPathRecursively(exports, str => str === './missing-path.js')).toBe(undefined); }); }); + +describe('_prepareStringForRegex', function () { + [ + { input: './foo', expected: '^\\.\\/foo$' }, + { input: './foo.js', expected: '^\\.\\/foo\\.js$' }, + { input: './foo/*.js', expected: '^\\.\\/foo\\/.*\\.js$' }, + { input: './foo/', expected: '^\\.\\/foo\\/.*$' }, + ].forEach(({ input, expected }) => { + it(input, function () { + expect(_prepareStringForRegex(input)).toStrictEqual(expected); + }); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0ed21d239..7ea52a88b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -568,16 +568,9 @@ importers: packages/reverse-exports: dependencies: - minimatch: - specifier: ^3.0.4 - version: 3.1.2 resolve.exports: specifier: ^2.0.2 version: 2.0.2 - devDependencies: - '@types/minimatch': - specifier: ^3.0.4 - version: 3.0.5 packages/router: dependencies: