mirror of
https://github.com/egoist/tsup.git
synced 2026-01-25 16:08:11 +00:00
159 lines
3.5 KiB
TypeScript
159 lines
3.5 KiB
TypeScript
import fs from 'fs'
|
|
import path from 'path'
|
|
import JoyCon from 'joycon'
|
|
import stripJsonComments from 'strip-json-comments'
|
|
import resovleFrom from 'resolve-from'
|
|
import { parse as parseJson } from 'jju/lib/parse'
|
|
import { transform } from 'sucrase'
|
|
import glob from 'globby'
|
|
import { requireFromString } from './require-from-string'
|
|
|
|
const joycon = new JoyCon()
|
|
|
|
joycon.addLoader({
|
|
test: /\.json$/,
|
|
async load(filepath) {
|
|
try {
|
|
const content = stripJsonComments(
|
|
await fs.promises.readFile(filepath, 'utf8')
|
|
)
|
|
return parseJson(content)
|
|
} catch (error) {
|
|
throw new Error(
|
|
`Failed to parse ${path.relative(process.cwd(), filepath)}: ${
|
|
error.message
|
|
}`
|
|
)
|
|
}
|
|
},
|
|
})
|
|
|
|
joycon.addLoader({
|
|
test: /\.ts$/,
|
|
async load(filepath) {
|
|
const content = await fs.promises.readFile(filepath, 'utf8')
|
|
const { code } = transform(content, {
|
|
filePath: filepath,
|
|
transforms: ['imports', 'typescript'],
|
|
})
|
|
const mod = requireFromString(code, filepath)
|
|
return mod.default || mod
|
|
},
|
|
})
|
|
|
|
joycon.addLoader({
|
|
test: /\.cjs$/,
|
|
load(filepath) {
|
|
delete require.cache[filepath]
|
|
return require(filepath)
|
|
},
|
|
})
|
|
|
|
// No backslash in path
|
|
function slash(input: string) {
|
|
return input.replace(/\\/g, '/')
|
|
}
|
|
|
|
export type External =
|
|
| string
|
|
| RegExp
|
|
| ((id: string, parentId?: string) => boolean)
|
|
|
|
export function isExternal(
|
|
externals: External | External[],
|
|
id: string,
|
|
parentId?: string
|
|
) {
|
|
id = slash(id)
|
|
|
|
if (!Array.isArray(externals)) {
|
|
externals = [externals]
|
|
}
|
|
|
|
for (const external of externals) {
|
|
if (
|
|
typeof external === 'string' &&
|
|
(id === external || id.includes(`/node_modules/${external}/`))
|
|
) {
|
|
return true
|
|
}
|
|
if (external instanceof RegExp) {
|
|
if (external.test(id)) {
|
|
return true
|
|
}
|
|
}
|
|
if (typeof external === 'function') {
|
|
if (external(id, parentId)) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
export function loadTsConfig(cwd: string) {
|
|
return joycon.load(
|
|
['tsconfig.build.json', 'tsconfig.json'],
|
|
cwd,
|
|
path.dirname(cwd)
|
|
)
|
|
}
|
|
|
|
export async function getDeps(cwd: string) {
|
|
const data = await loadPkg(cwd)
|
|
|
|
const deps = Array.from(
|
|
new Set([
|
|
...Object.keys(data.dependencies || {}),
|
|
...Object.keys(data.peerDependencies || {}),
|
|
])
|
|
)
|
|
|
|
return deps
|
|
}
|
|
|
|
export async function loadPkg(cwd: string) {
|
|
const { data } = await joycon.load(['package.json'], cwd, path.dirname(cwd))
|
|
return data || {}
|
|
}
|
|
|
|
export function getBabel(): null | typeof import('@babel/core') {
|
|
const p = resovleFrom.silent(process.cwd(), '@babel/core')
|
|
return p && require(p)
|
|
}
|
|
|
|
export function getPostcss(): null | typeof import('postcss') {
|
|
const p = resovleFrom.silent(process.cwd(), 'postcss')
|
|
return p && require(p)
|
|
}
|
|
|
|
export function localRequire(moduleName: string) {
|
|
const p = resovleFrom.silent(process.cwd(), moduleName)
|
|
return p && require(p)
|
|
}
|
|
|
|
export function pathExists(p: string) {
|
|
return new Promise((resolve) => {
|
|
fs.access(p, (err) => {
|
|
resolve(!err)
|
|
})
|
|
})
|
|
}
|
|
|
|
export function loadTsupConfig(cwd: string) {
|
|
return joycon.load(
|
|
['tsup.config.ts', 'tsup.config.js', 'tsup.config.cjs', 'tsup.config.json'],
|
|
cwd,
|
|
path.dirname(cwd)
|
|
)
|
|
}
|
|
|
|
export async function removeFiles(patterns: string[], dir: string) {
|
|
const files = await glob(patterns, {
|
|
cwd: dir,
|
|
absolute: true,
|
|
})
|
|
await Promise.all(files.map((file) => fs.promises.unlink(file)))
|
|
}
|