fix(release): validate wildcard export targets

This commit is contained in:
Danila Poyarkov 2026-08-31 14:36:08 +03:00
parent a7e5abd4ab
commit b7136eea15
2 changed files with 23 additions and 4 deletions

View file

@ -12,7 +12,6 @@ type PackageExports = {
type PackageJSON = {
bin?: Record<string, string> | string
exports?: PackageExports
imports?: PackageExports
name: string
}
@ -56,15 +55,29 @@ export async function validateTarballBinTargets(tarballPath: string): Promise<vo
}
}
function exportTargetPattern(target: string): RegExp {
const escaped = target.replace(/[.+?^${}()|[\]\\]/g, '\\$&')
return new RegExp(`^${escaped.replace(/\*/g, '[^/]+')}$`)
}
export async function validateTarballExportTargets(tarballPath: string): Promise<void> {
const entries = await tarballEntries(tarballPath)
const packageJSON = await tarballPackageJSON(tarballPath)
for (const target of packageExportTargetPaths(packageJSON)) {
if (!target.startsWith('./')) continue
const entry = `package/${target.slice(2)}`
if (!entries.has(entry)) {
throw new Error(`${tarballPath}: export target missing from tarball: ${entry}`)
const relativeTarget = target.slice(2)
let matchingEntries: string[]
if (relativeTarget.includes('*')) {
const pattern = exportTargetPattern(relativeTarget)
matchingEntries = [...entries].filter((entry) => pattern.test(entry.slice('package/'.length)))
} else {
const exactEntry = `package/${relativeTarget}`
matchingEntries = entries.has(exactEntry) ? [exactEntry] : []
}
if (matchingEntries.length === 0) {
throw new Error(
`${tarballPath}: export target missing from tarball: package/${relativeTarget}`
)
}
}
}

View file

@ -19,6 +19,12 @@ describe('packageBinTargets', () => {
})
describe('package export targets', () => {
test('collects wildcard targets from conditional exports', () => {
expect(
packageExportTargetPaths({ exports: { './feature/*': { import: './dist/*.js' } } })
).toEqual(['./dist/*.js'])
})
test('collects targets from conditional exports', () => {
expect(
packageExportTargetPaths({