Skip to content

Commit

Permalink
chore: wildcard to experimental
Browse files Browse the repository at this point in the history
  • Loading branch information
devjiwonchoi committed Aug 17, 2023
1 parent 4148d68 commit 72efa89
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 100 deletions.
2 changes: 1 addition & 1 deletion src/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
fileExists,
getSourcePathFromExportPath,
getExportPath,
validateExports,
} from './utils'
import {
constructDefaultExportCondition,
Expand All @@ -28,6 +27,7 @@ import {
import type { BuildMetadata } from './types'
import { TypescriptOptions, resolveTsConfig } from './typescript'
import { logSizeStats } from './logging'
import { validateExports } from './experimental/wildcard'

function assignDefault(
options: BundleConfig,
Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ export const availableExportConventions = [
]
export const availableESExtensionsRegex = /\.(m|c)?[jt]sx?$/
export const dtsExtensionRegex = /\.d\.(m|c)?ts$/

export const SRC = 'src'
90 changes: 90 additions & 0 deletions src/experimental/wildcard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import fs from 'fs/promises'
import path from 'path'
import { SRC } from '../constants'
import { ExportCondition } from '../types'
import {
filenameWithoutExtension,
hasAvailableExtension,
nonNullable,
} from '../utils'

const getWildcardEntry = (
key: string,
exports: string | Record<string, ExportCondition>,
): string | Record<string, ExportCondition> | undefined => {
if (typeof exports === 'string') return exports
if (!key.includes('./*') || !exports[key]) return undefined
return { [key]: exports[key] }
}

export async function getExportables(cwd: string): Promise<string[]> {
const dirents = await fs.readdir(path.resolve(cwd, SRC), {
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
}),
)
return exportables.filter(nonNullable)
}

export async function validateExports(
exports: ExportCondition,
cwd: string,
): Promise<ExportCondition> {
const wildcardEntry = getWildcardEntry('./*', exports)

if (!wildcardEntry) return exports
if (typeof wildcardEntry === 'string') return exports

const exportables = await getExportables(cwd)
const wildcardExports = exportables.map((exportable) => {
const filename = exportable.includes('.')
? filenameWithoutExtension(exportable)
: undefined

if (!filename) {
return {
[`./${exportable}`]: JSON.parse(
JSON.stringify(wildcardEntry['./*']).replace(
/\*/g,
`${exportable}/index`,
),
),
}
}
return JSON.parse(JSON.stringify(wildcardEntry).replace(/\*/g, filename))
})

const resolvedExports = Object.assign(
{},
exports,
...wildcardExports,
exports,
)
delete resolvedExports['./*']
return resolvedExports
}
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type PackageMetadata = {
dependencies?: Record<string, string>
peerDependencies?: Record<string, string>
peerDependenciesMeta?: Record<string, Record<string, string>>
exports?: ExportCondition
exports?: string | Record<string, ExportCondition>
types?: string
typings?: string
}
Expand Down
108 changes: 10 additions & 98 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import fs from 'fs/promises'
import type { Dirent } from 'fs'
import path from 'path'
import type { ExportCondition, PackageMetadata } from './types'
import { availableExportConventions, availableExtensions } from './constants'
import { PackageMetadata } from './types'
import {
availableExportConventions,
availableExtensions,
SRC,
} from './constants'

export function exit(err: string | Error) {
logger.error(err)
Expand Down Expand Up @@ -73,7 +76,6 @@ export function getExportPath(

export const isNotNull = <T>(n: T | false): n is T => Boolean(n)

const SRC = 'src' // resolve from src/ directory
export function resolveSourceFile(cwd: string, filename: string) {
return path.resolve(cwd, SRC, filename)
}
Expand Down Expand Up @@ -145,98 +147,8 @@ export function filenameWithoutExtension(file: string | undefined) {

export const nonNullable = <T>(n?: T): n is T => Boolean(n)

const isExportableExtension = (filename: string): boolean => {
const ext = path.extname(filename).slice(1)
return [...availableExtensions, ...availableExportConventions].includes(ext)
}

const hasSrc = (dirents: Dirent[]) => {
return dirents.some((dirent) => dirent.name === SRC && dirent.isDirectory())
}

export async function getExportables(cwd: string): Promise<string[]> {
let currentDirPath = cwd
let dirents = await fs.readdir(cwd, { withFileTypes: true })
if (hasSrc(dirents)) {
currentDirPath = path.join(cwd, SRC)
dirents = await fs.readdir(path.join(cwd, SRC), { withFileTypes: true })
}

const exportables: (string | undefined)[] = await Promise.all(
dirents.map(async (dirent) => {
if (dirent.isDirectory()) {
let innerDirents = await fs.readdir(
path.join(currentDirPath, dirent.name),
{
withFileTypes: true,
},
)
if (hasSrc(innerDirents)) {
currentDirPath = path.join(currentDirPath, dirent.name, SRC)
innerDirents = await fs.readdir(currentDirPath, {
withFileTypes: true,
})
}
const hasExportableFile = innerDirents.some(
({ name }) => name.startsWith('index') && isExportableExtension(name),
)
return hasExportableFile ? dirent.name : undefined
}

if (
dirent.isFile() &&
!dirent.name.startsWith('index') &&
isExportableExtension(dirent.name)
) {
return dirent.name
}
return undefined
}),
)
return exportables.filter(nonNullable)
}

export function getExportConditionByKey(
key: string,
exports: any,
): { [key: string]: ExportCondition } | undefined {
if (!key.includes('./*') || !exports[key]) return undefined
return { [key]: exports[key] }
}
export const fileExtension = (file: string | undefined) =>
file ? path.extname(file).slice(1) : undefined

export async function validateExports(
exports: ExportCondition,
cwd: string,
): Promise<ExportCondition> {
const wildcardEntry = getExportConditionByKey('./*', exports)
console.log(!!wildcardEntry, wildcardEntry, exports, 'eejjeejj2')
if (!wildcardEntry) return exports

const exportables = await getExportables(cwd)
const wildcardExports = exportables.map((exportable) => {
const filename = exportable.includes('.')
? filenameWithoutExtension(exportable)
: undefined

if (!filename) {
return {
[`./${exportable}`]: JSON.parse(
JSON.stringify(wildcardEntry['./*']).replace(
/\*/g,
`${exportable}/index`,
),
),
}
}
return JSON.parse(JSON.stringify(wildcardEntry).replace(/\*/g, filename))
})

const resolvedExports = Object.assign(
{},
exports,
...wildcardExports,
exports,
)
delete resolvedExports['./*']
return resolvedExports
}
export const hasAvailableExtension = (filename: string): boolean =>
availableExtensions.includes(path.extname(filename).slice(1))

0 comments on commit 72efa89

Please sign in to comment.