diff --git a/src/experimental/wildcard.ts b/src/experimental/wildcard.ts index 7f4d8048..c95817c2 100644 --- a/src/experimental/wildcard.ts +++ b/src/experimental/wildcard.ts @@ -1,4 +1,5 @@ import fs from 'fs/promises' +import type { Dirent } from 'fs' import path from 'path' import { SRC } from '../constants' import { ExportCondition } from '../types' @@ -10,63 +11,55 @@ import { const getWildcardEntry = ( key: string, - exports: string | Record, -): string | Record | undefined => { - if (typeof exports === 'string') return exports + exports: Record, +): Record | undefined => { if (!key.includes('./*') || !exports[key]) return undefined return { [key]: exports[key] } } -export async function getExportables(cwd: string): Promise { - const dirents = await fs.readdir(path.resolve(cwd, SRC), { - withFileTypes: true, - }) +const isExportable = async ( + dirent: Dirent, + pathname: string, +): Promise => { + if (dirent.isDirectory()) { + const innerDirents = await fs.readdir(path.join(pathname, dirent.name), { + withFileTypes: true, + }) + return innerDirents.some( + ({ name }) => name.startsWith('index') && hasAvailableExtension(name), + ) + } + return ( + dirent.isFile() && + !dirent.name.startsWith('index') && + hasAvailableExtension(dirent.name) + ) +} +async function getExportables(cwd: string): Promise { + const pathname = path.resolve(cwd, SRC) + const dirents = await fs.readdir(pathname, { withFileTypes: true }) const exportables: (string | undefined)[] = await Promise.all( - dirents.map(async (dirent) => { - if (dirent.isDirectory()) { - // Read inside directory and check if it has an index file - const innerDirents = await fs.readdir( - path.join(cwd, SRC, dirent.name), - { - withFileTypes: true, - }, - ) - const hasExportableFile = innerDirents.some( - ({ name }) => name.startsWith('index') && hasAvailableExtension(name), - ) - return hasExportableFile ? dirent.name : undefined - } - - if ( - dirent.isFile() && - !dirent.name.startsWith('index') && - hasAvailableExtension(dirent.name) - ) { - return dirent.name - } - return undefined - }), + dirents.map(async (dirent) => + (await isExportable(dirent, pathname)) ? dirent.name : undefined, + ), ) return exportables.filter(nonNullable) } -export async function validateExports( - exports: ExportCondition, - cwd: string, -): Promise { - const wildcardEntry = getWildcardEntry('./*', exports) - - if (!wildcardEntry) return exports - if (typeof wildcardEntry === 'string') return exports - - const exportables = await getExportables(cwd) - const wildcardExports = exportables.map((exportable) => { +function mapWildcard( + wildcardEntry: string | Record, + exportables: string[], +): (string | ExportCondition)[] { + return exportables.map((exportable) => { const filename = exportable.includes('.') ? filenameWithoutExtension(exportable) : undefined if (!filename) { + if (typeof wildcardEntry === 'string') { + return wildcardEntry.replace(/\*/g, exportable) + } return { [`./${exportable}`]: JSON.parse( JSON.stringify(wildcardEntry['./*']).replace( @@ -78,11 +71,23 @@ export async function validateExports( } return JSON.parse(JSON.stringify(wildcardEntry).replace(/\*/g, filename)) }) +} + +export async function validateExports( + exports: ExportCondition | Record, + cwd: string, +): Promise { + if (typeof exports === 'string') return exports + const wildcardEntry = getWildcardEntry('./*', exports) + if (!wildcardEntry) return exports + + const exportables = await getExportables(cwd) + const resolvedWildcardExports = mapWildcard(wildcardEntry, exportables) const resolvedExports = Object.assign( {}, exports, - ...wildcardExports, + ...resolvedWildcardExports, exports, ) delete resolvedExports['./*']