diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dde0600..0fde262 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: release: runs-on: ubuntu-latest - needs: ['test'] + needs: [test] if: "!contains(github.event.head_commit.message, 'skip-release') && !contains(github.event.head_commit.message, 'skip-ci') && github.event_name != 'pull_request'" permissions: contents: write diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 41ddf54..146744a 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -3,8 +3,8 @@ name: Fix on: push: branches-ignore: - - 'main' - - 'dev' + - main + - dev jobs: format: diff --git a/.gitignore b/.gitignore index cb3efa4..f16666b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ dist playground .idea .DS_Store +.eslintcache diff --git a/assets/cjs_shims.js b/assets/cjs_shims.js index bcd355e..eb051db 100644 --- a/assets/cjs_shims.js +++ b/assets/cjs_shims.js @@ -5,7 +5,7 @@ const getImportMetaUrl = () => typeof document === 'undefined' - ? new URL('file:' + __filename).href + ? new URL(`file:${__filename}`).href : (document.currentScript && document.currentScript.src) || new URL('main.js', document.baseURI).href diff --git a/docs/README.md b/docs/README.md index f123ed6..8b61ca7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,7 +2,7 @@ import { html } from 'docup' export default () => { - let isPreview = location.hostname !== 'tsup.egoist.dev' + const isPreview = location.hostname !== 'tsup.egoist.dev' if (!isPreview) return null @@ -409,7 +409,7 @@ You can return a cleanup function in `onSuccess`: import { defineConfig } from 'tsup' export default defineConfig({ - async onSuccess() { + onSuccess() { const server = http.createServer((req, res) => { res.end('Hello World!') }) diff --git a/package.json b/package.json index 40484fe..ee3d641 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,25 @@ { "name": "tsup", "version": "0.0.0-semantic-release", + "packageManager": "pnpm@9.5.0", "description": "Bundle your TypeScript library with no config, powered by esbuild", - "main": "dist/index.js", - "bin": { - "tsup": "dist/cli-default.js", - "tsup-node": "dist/cli-node.js" - }, - "types": "dist/index.d.ts", - "files": [ - "/dist", - "/assets", - "/schema.json" - ], - "author": "EGOIST", "license": "MIT", "homepage": "https://tsup.egoist.dev/", "repository": { "url": "https://github.com/egoist/tsup.git" }, + "author": "EGOIST", + "files": [ + "/assets", + "/dist", + "/schema.json" + ], + "main": "dist/index.js", + "types": "dist/index.d.ts", + "bin": { + "tsup": "dist/cli-default.js", + "tsup-node": "dist/cli-node.js" + }, "scripts": { "dev": "npm run build-fast -- --watch", "build": "tsup src/cli-*.ts src/index.ts src/rollup.ts --clean --splitting", @@ -28,6 +29,26 @@ "test-only": "vitest run", "build-fast": "npm run build -- --no-dts" }, + "peerDependencies": { + "@microsoft/api-extractor": "^7.36.0", + "@swc/core": "^1", + "postcss": "^8.4.12", + "typescript": ">=4.5.0" + }, + "peerDependenciesMeta": { + "@microsoft/api-extractor": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "postcss": { + "optional": true + }, + "typescript": { + "optional": true + } + }, "dependencies": { "bundle-require": "^5.0.0", "cac": "^6.7.14", @@ -72,28 +93,7 @@ "vitest": "2.0.3", "wait-for-expect": "3.0.2" }, - "peerDependencies": { - "@microsoft/api-extractor": "^7.36.0", - "@swc/core": "^1", - "postcss": "^8.4.12", - "typescript": ">=4.5.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "postcss": { - "optional": true - }, - "@swc/core": { - "optional": true - }, - "@microsoft/api-extractor": { - "optional": true - } - }, "engines": { "node": ">=18" - }, - "packageManager": "pnpm@9.5.0" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4dd6062..e1b9032 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -37,7 +37,7 @@ importers: version: 3.1.1 postcss-load-config: specifier: ^6.0.1 - version: 6.0.1(postcss@8.4.39)(yaml@2.4.5) + version: 6.0.1(jiti@1.21.6)(postcss@8.4.39)(yaml@2.4.5) resolve-from: specifier: ^5.0.0 version: 5.0.0 @@ -110,7 +110,7 @@ importers: version: 3.49.0 svelte-preprocess: specifier: 5.0.3 - version: 5.0.3(postcss-load-config@6.0.1(postcss@8.4.39)(yaml@2.4.5))(postcss@8.4.39)(sass@1.77.8)(svelte@3.49.0)(typescript@5.5.3) + version: 5.0.3(postcss-load-config@6.0.1(jiti@1.21.6)(postcss@8.4.39)(yaml@2.4.5))(postcss@8.4.39)(sass@1.77.8)(svelte@3.49.0)(typescript@5.5.3) terser: specifier: ^5.31.3 version: 5.31.3 @@ -1088,6 +1088,10 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + jju@1.4.0: resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} @@ -2553,6 +2557,9 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jiti@1.21.6: + optional: true + jju@1.4.0: {} joycon@3.1.1: {} @@ -2703,10 +2710,11 @@ snapshots: optionalDependencies: postcss: 8.4.39 - postcss-load-config@6.0.1(postcss@8.4.39)(yaml@2.4.5): + postcss-load-config@6.0.1(jiti@1.21.6)(postcss@8.4.39)(yaml@2.4.5): dependencies: lilconfig: 3.1.2 optionalDependencies: + jiti: 1.21.6 postcss: 8.4.39 yaml: 2.4.5 @@ -2892,7 +2900,7 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-preprocess@5.0.3(postcss-load-config@6.0.1(postcss@8.4.39)(yaml@2.4.5))(postcss@8.4.39)(sass@1.77.8)(svelte@3.49.0)(typescript@5.5.3): + svelte-preprocess@5.0.3(postcss-load-config@6.0.1(jiti@1.21.6)(postcss@8.4.39)(yaml@2.4.5))(postcss@8.4.39)(sass@1.77.8)(svelte@3.49.0)(typescript@5.5.3): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 @@ -2902,7 +2910,7 @@ snapshots: svelte: 3.49.0 optionalDependencies: postcss: 8.4.39 - postcss-load-config: 6.0.1(postcss@8.4.39)(yaml@2.4.5) + postcss-load-config: 6.0.1(jiti@1.21.6)(postcss@8.4.39)(yaml@2.4.5) sass: 1.77.8 typescript: 5.5.3 diff --git a/src/api-extractor.ts b/src/api-extractor.ts index 2a16de9..5255648 100644 --- a/src/api-extractor.ts +++ b/src/api-extractor.ts @@ -1,18 +1,12 @@ -import type { - ExtractorResult, - IConfigFile, - IExtractorConfigPrepareOptions, -} from '@microsoft/api-extractor' -import path from 'path' +import path from 'node:path' import { handleError } from './errors' import { + type ExportDeclaration, formatAggregationExports, formatDistributionExports, - type ExportDeclaration, } from './exports' import { loadPkg } from './load' import { createLogger } from './log' -import type { Format, NormalizedOptions } from './options' import { defaultOutExtension, ensureTempDeclarationDir, @@ -21,6 +15,12 @@ import { toAbsolutePath, writeFileSync, } from './utils' +import type { Format, NormalizedOptions } from './options' +import type { + ExtractorResult, + IConfigFile, + IExtractorConfigPrepareOptions, +} from '@microsoft/api-extractor' const logger = createLogger() @@ -29,9 +29,9 @@ function rollupDtsFile( outputFilePath: string, tsconfigFilePath: string, ) { - let cwd = process.cwd() - let packageJsonFullPath = path.join(cwd, 'package.json') - let configObject: IConfigFile = { + const cwd = process.cwd() + const packageJsonFullPath = path.join(cwd, 'package.json') + const configObject: IConfigFile = { mainEntryPointFilePath: inputFilePath, apiReport: { enabled: false, @@ -46,7 +46,7 @@ function rollupDtsFile( }, tsdocMetadata: { enabled: false }, compiler: { - tsconfigFilePath: tsconfigFilePath, + tsconfigFilePath, }, projectFolder: cwd, } @@ -87,14 +87,14 @@ async function rollupDtsFiles( exports: ExportDeclaration[], format: Format, ) { - let declarationDir = ensureTempDeclarationDir() - let outDir = options.outDir || 'dist' - let pkg = await loadPkg(process.cwd()) - let dtsExtension = defaultOutExtension({ format, pkgType: pkg.type }).dts + const declarationDir = ensureTempDeclarationDir() + const outDir = options.outDir || 'dist' + const pkg = await loadPkg(process.cwd()) + const dtsExtension = defaultOutExtension({ format, pkgType: pkg.type }).dts let dtsInputFilePath = path.join( declarationDir, - '_tsup-dts-aggregation' + dtsExtension, + `_tsup-dts-aggregation${dtsExtension}`, ) // @microsoft/api-extractor doesn't support `.d.mts` and `.d.cts` file as a // entrypoint yet. So we replace the extension here as a temporary workaround. @@ -105,7 +105,7 @@ async function rollupDtsFiles( .replace(/\.d\.mts$/, '.dmts.d.ts') .replace(/\.d\.cts$/, '.dcts.d.ts') - let dtsOutputFilePath = path.join(outDir, '_tsup-dts-rollup' + dtsExtension) + const dtsOutputFilePath = path.join(outDir, `_tsup-dts-rollup${dtsExtension}`) writeFileSync( dtsInputFilePath, diff --git a/src/cli-main.ts b/src/cli-main.ts index 78c3dfa..070236e 100644 --- a/src/cli-main.ts +++ b/src/cli-main.ts @@ -1,8 +1,8 @@ import { cac } from 'cac' import { flatten } from 'flat' -import type { Format, Options } from '.' import { version } from '../package.json' import { slash } from './utils' +import type { Format, Options } from '.' function ensureArray(input: string): string[] { return Array.isArray(input) ? input : input.split(',') @@ -117,10 +117,9 @@ export async function main(options: Options = {}) { options.external = external } if (flags.target) { - options.target = - flags.target.indexOf(',') >= 0 - ? flags.target.split(',') - : flags.target + options.target = flags.target.includes(',') + ? flags.target.split(',') + : flags.target } if (flags.dts || flags.dtsResolve || flags.dtsOnly) { options.dts = {} diff --git a/src/errors.ts b/src/errors.ts index d58fa36..b0a78c3 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -1,4 +1,4 @@ -import { isMainThread, parentPort } from 'worker_threads' +import { isMainThread, parentPort } from 'node:worker_threads' import * as colors from 'colorette' export class PrettyError extends Error { @@ -26,12 +26,10 @@ export function handleError(error: any) { if (error.frame) { console.error(colors.red(error.message)) console.error(colors.dim(error.frame)) + } else if (error instanceof PrettyError) { + console.error(colors.red(error.message)) } else { - if (error instanceof PrettyError) { - console.error(colors.red(error.message)) - } else { - console.error(colors.red(error.stack)) - } + console.error(colors.red(error.stack)) } process.exitCode = 1 if (!isMainThread && parentPort) { diff --git a/src/esbuild/external.ts b/src/esbuild/external.ts index 1b26b16..c39bf82 100644 --- a/src/esbuild/external.ts +++ b/src/esbuild/external.ts @@ -1,8 +1,8 @@ +import { match, tsconfigPathsToRegExp } from 'bundle-require' import type { Plugin } from 'esbuild' -import { tsconfigPathsToRegExp, match } from 'bundle-require' // Must not start with "/" or "./" or "../" or "C:\" or be the exact strings ".." or "." -const NON_NODE_MODULE_RE = /^[A-Z]:[\\\/]|^\.{0,2}[\/]|^\.{1,2}$/ +const NON_NODE_MODULE_RE = /^[A-Z]:[/\\]|^\.{0,2}\/|^\.{1,2}$/ export const externalPlugin = ({ external, diff --git a/src/esbuild/index.ts b/src/esbuild/index.ts index 28c30a2..84e7f5d 100644 --- a/src/esbuild/index.ts +++ b/src/esbuild/index.ts @@ -1,23 +1,23 @@ -import fs from 'fs' -import path from 'path' +import fs from 'node:fs' +import path from 'node:path' import { - build as esbuild, type BuildResult, - formatMessages, type Plugin as EsbuildPlugin, + build as esbuild, + formatMessages, } from 'esbuild' -import type { NormalizedOptions, Format } from '..' +import consola from 'consola' import { getProductionDeps, loadPkg } from '../load' import { type Logger, getSilent } from '../log' +import { defaultOutExtension, truthy } from '../utils' import { nodeProtocolPlugin } from './node-protocol' import { externalPlugin } from './external' import { postcssPlugin } from './postcss' import { sveltePlugin } from './svelte' -import consola from 'consola' -import { defaultOutExtension, truthy } from '../utils' import { swcPlugin } from './swc' import { nativeNodeModulesPlugin } from './native-node-module' -import { PluginContainer } from '../plugin' +import type { PluginContainer } from '../plugin' +import type { Format, NormalizedOptions } from '..' import type { OutExtensionFactory } from '../options' const getOutputExtensionMap = ( @@ -47,7 +47,7 @@ const generateExternal = async (external: (string | RegExp)[]) => { continue } - let pkgPath: string = path.isAbsolute(item) + const pkgPath: string = path.isAbsolute(item) ? path.dirname(item) : path.dirname(path.resolve(process.cwd(), item)) diff --git a/src/esbuild/native-node-module.ts b/src/esbuild/native-node-module.ts index f77bade..5b653f3 100644 --- a/src/esbuild/native-node-module.ts +++ b/src/esbuild/native-node-module.ts @@ -1,4 +1,4 @@ -import path from 'path' +import path from 'node:path' import type { Plugin } from 'esbuild' // Copied from https://github.com/evanw/esbuild/issues/1051#issuecomment-806325487 diff --git a/src/esbuild/postcss.ts b/src/esbuild/postcss.ts index 70ebdc5..1c75402 100644 --- a/src/esbuild/postcss.ts +++ b/src/esbuild/postcss.ts @@ -1,7 +1,7 @@ +import fs from 'node:fs' import { type Loader, type Plugin, transform } from 'esbuild' -import fs from 'fs' -import type { Result } from 'postcss-load-config' import { getPostcss } from '../utils' +import type { Result } from 'postcss-load-config' export const postcssPlugin = ({ css, diff --git a/src/esbuild/svelte.ts b/src/esbuild/svelte.ts index 8672664..3dd8744 100644 --- a/src/esbuild/svelte.ts +++ b/src/esbuild/svelte.ts @@ -1,5 +1,5 @@ -import fs from 'fs' -import path from 'path' +import fs from 'node:fs' +import path from 'node:path' import { type Plugin, transform } from 'esbuild' import { localRequire } from '../utils' @@ -110,13 +110,13 @@ export const sveltePlugin = ({ css.set(cssPath, result.css.code) // Directly prepend the `import` statement as sourcemap doesn't matter for now // If that's need we should use `magic-string` - contents = - `import '${useSvelteCssExtension(path.basename(args.path))}';` + + contents = `import '${useSvelteCssExtension(path.basename(args.path))}';${ contents + }` } return { contents, warnings: result.warnings.map(convertMessage) } - } catch (e) { - return { errors: [convertMessage(e)] } + } catch (error) { + return { errors: [convertMessage(error)] } } }) }, diff --git a/src/esbuild/swc.ts b/src/esbuild/swc.ts index 2ba0c50..8d9d28e 100644 --- a/src/esbuild/swc.ts +++ b/src/esbuild/swc.ts @@ -1,11 +1,11 @@ /** * Use SWC to emit decorator metadata */ +import path from 'node:path' +import { localRequire } from '../utils' import type { JscConfig } from '@swc/core' import type { Plugin } from 'esbuild' -import path from 'path' import type { Logger } from '../log' -import { localRequire } from '../utils' export const swcPlugin = ({ logger }: { logger: Logger }): Plugin => { return { diff --git a/src/exports.ts b/src/exports.ts index 7b320a7..cb803b4 100644 --- a/src/exports.ts +++ b/src/exports.ts @@ -1,4 +1,4 @@ -import path from 'path' +import path from 'node:path' import { slash, trimDtsExtension, truthy } from './utils' export type ExportDeclaration = ModuleExport | NamedExport @@ -34,18 +34,17 @@ export function formatAggregationExports( lines.push('export {};') } - return lines.join('\n') + '\n' + return `${lines.join('\n')}\n` } function formatAggregationExport( declaration: ExportDeclaration, declarationDirPath: string, ): string { - let dest = trimDtsExtension( - './' + - path.posix.normalize( - slash(path.relative(declarationDirPath, declaration.destFileName)), - ), + const dest = trimDtsExtension( + `./${path.posix.normalize( + slash(path.relative(declarationDirPath, declaration.destFileName)), + )}`, ) if (declaration.kind === 'module') { @@ -79,11 +78,11 @@ export function formatDistributionExports( path.posix.normalize(slash(toFilePath)), ), ) - if (!importPath.match(/^\.+\//)) { - importPath = './' + importPath + if (!/^\.+\//.test(importPath)) { + importPath = `./${importPath}` } - let seen = { + const seen = { named: new Set(), module: new Set(), } @@ -113,7 +112,7 @@ export function formatDistributionExports( lines.push('export {};') } - return lines.join('\n') + '\n' + return `${lines.join('\n')}\n` } function formatDistributionExport( diff --git a/src/fs.ts b/src/fs.ts index 3adb4f1..cdff1dd 100644 --- a/src/fs.ts +++ b/src/fs.ts @@ -1,5 +1,5 @@ -import path from 'path' -import fs from 'fs' +import path from 'node:path' +import fs from 'node:fs' export const outputFile = async ( filepath: string, diff --git a/src/index.ts b/src/index.ts index 7b4ce1f..b4cfe27 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,23 +1,21 @@ -import path from 'path' -import fs from 'fs' -import { Worker } from 'worker_threads' -import { - removeFiles, - debouncePromise, - slash, - type MaybePromise, - toObjectEntry, -} from './utils' -import { getAllDepsHash, loadTsupConfig } from './load' +import path from 'node:path' +import fs from 'node:fs' +import { Worker } from 'node:worker_threads' import glob from 'globby' import { loadTsConfig } from 'bundle-require' -import { handleError, PrettyError } from './errors' -import type { ChildProcess } from 'child_process' import execa from 'execa' import kill from 'tree-kill' import { version } from '../package.json' +import { PrettyError, handleError } from './errors' +import { getAllDepsHash, loadTsupConfig } from './load' +import { + type MaybePromise, + debouncePromise, + removeFiles, + slash, + toObjectEntry, +} from './utils' import { createLogger, setSilent } from './log' -import type { NormalizedOptions, Format, Options, KILL_SIGNAL } from './options' import { runEsbuild } from './esbuild' import { shebang } from './plugins/shebang' import { cjsSplitting } from './plugins/cjs-splitting' @@ -30,6 +28,8 @@ import { terserPlugin } from './plugins/terser' import { runTypeScriptCompiler } from './tsc' import { runDtsRollup } from './api-extractor' import { cjsInterop } from './plugins/cjs-interop' +import type { ChildProcess } from 'node:child_process' +import type { Format, KILL_SIGNAL, NormalizedOptions, Options } from './options' export type { Format, Options, NormalizedOptions } @@ -389,14 +389,14 @@ export async function build(_options: Options) { 'CLI', `Watching for changes in ${ Array.isArray(watchPaths) - ? watchPaths.map((v) => '"' + v + '"').join(' | ') - : '"' + watchPaths + '"' + ? watchPaths.map((v) => `"${v}"`).join(' | ') + : `"${watchPaths}"` }`, ) logger.info( 'CLI', `Ignoring changes in ${ignored - .map((v) => '"' + v + '"') + .map((v) => `"${v}"`) .join(' | ')}`, ) diff --git a/src/lib/public-dir.ts b/src/lib/public-dir.ts index f15459e..39025e4 100644 --- a/src/lib/public-dir.ts +++ b/src/lib/public-dir.ts @@ -1,4 +1,4 @@ -import path from 'path' +import path from 'node:path' import { copyDirSync } from '../fs' import { slash } from '../utils' diff --git a/src/lib/report-size.ts b/src/lib/report-size.ts index 814cd32..863053d 100644 --- a/src/lib/report-size.ts +++ b/src/lib/report-size.ts @@ -5,7 +5,7 @@ const prettyBytes = (bytes: number) => { if (bytes === 0) return '0 B' const unit = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] const exp = Math.floor(Math.log(bytes) / Math.log(1024)) - return `${(bytes / Math.pow(1024, exp)).toFixed(2)} ${unit[exp]}` + return `${(bytes / 1024 ** exp).toFixed(2)} ${unit[exp]}` } const getLengthOfLongestString = (strings: string[]) => { diff --git a/src/load.ts b/src/load.ts index 98d389f..562b99a 100644 --- a/src/load.ts +++ b/src/load.ts @@ -1,9 +1,9 @@ -import fs from 'fs' +import fs from 'node:fs' +import path from 'node:path' import JoyCon from 'joycon' -import path from 'path' import { bundleRequire } from 'bundle-require' -import { defineConfig } from './' import { jsoncParse } from './utils' +import type { defineConfig } from './' const joycon = new JoyCon() diff --git a/src/log.ts b/src/log.ts index bedfc55..fa550f7 100644 --- a/src/log.ts +++ b/src/log.ts @@ -1,5 +1,5 @@ -import util from 'util' -import { parentPort, isMainThread } from 'worker_threads' +import util from 'node:util' +import { isMainThread, parentPort } from 'node:worker_threads' import * as colors from 'colorette' type LOG_TYPE = 'info' | 'success' | 'error' | 'warn' diff --git a/src/plugin.ts b/src/plugin.ts index 39cb46e..e5c4d47 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,16 +1,16 @@ -import path from 'path' -import type { - OutputFile, - BuildOptions as EsbuildOptions, - Metafile, -} from 'esbuild' +import path from 'node:path' import { + type RawSourceMap, SourceMapConsumer, SourceMapGenerator, - type RawSourceMap, } from 'source-map' -import type { Format, NormalizedOptions } from '.' import { outputFile } from './fs' +import type { + BuildOptions as EsbuildOptions, + Metafile, + OutputFile, +} from 'esbuild' +import type { Format, NormalizedOptions } from '.' import type { Logger } from './log' import type { MaybePromise } from './utils' import type { SourceMap } from 'rollup' diff --git a/src/plugins/cjs-interop.ts b/src/plugins/cjs-interop.ts index dea18d3..0691b2e 100644 --- a/src/plugins/cjs-interop.ts +++ b/src/plugins/cjs-interop.ts @@ -4,7 +4,7 @@ export const cjsInterop = (): Plugin => { return { name: 'cjs-interop', - async renderChunk(code, info) { + renderChunk(code, info) { if ( !this.options.cjsInterop || this.format !== 'cjs' || @@ -18,7 +18,7 @@ export const cjsInterop = (): Plugin => { } return { - code: code + '\nmodule.exports = exports.default;\n', + code: `${code}\nmodule.exports = exports.default;\n`, map: info.map, } }, diff --git a/src/plugins/shebang.ts b/src/plugins/shebang.ts index 2b91633..b5768b2 100644 --- a/src/plugins/shebang.ts +++ b/src/plugins/shebang.ts @@ -5,10 +5,12 @@ export const shebang = (): Plugin => { name: 'shebang', renderChunk(_, info) { - if (info.type === 'chunk' && /\.(cjs|js|mjs)$/.test(info.path)) { - if (info.code.startsWith('#!')) { - info.mode = 0o755 - } + if ( + info.type === 'chunk' && + /\.(cjs|js|mjs)$/.test(info.path) && + info.code.startsWith('#!') + ) { + info.mode = 0o755 } }, } diff --git a/src/plugins/size-reporter.ts b/src/plugins/size-reporter.ts index 94c576e..4333b06 100644 --- a/src/plugins/size-reporter.ts +++ b/src/plugins/size-reporter.ts @@ -1,5 +1,5 @@ -import type { Plugin } from '../plugin' import { reportSize } from '../lib/report-size' +import type { Plugin } from '../plugin' export const sizeReporter = (): Plugin => { return { diff --git a/src/plugins/swc-target.ts b/src/plugins/swc-target.ts index 483eda1..7ec4b5c 100644 --- a/src/plugins/swc-target.ts +++ b/src/plugins/swc-target.ts @@ -1,7 +1,7 @@ -import type { ModuleConfig } from '@swc/core' import { PrettyError } from '../errors' -import type { Plugin } from '../plugin' import { localRequire } from '../utils' +import type { ModuleConfig } from '@swc/core' +import type { Plugin } from '../plugin' const TARGETS = ['es5', 'es3'] as const @@ -58,7 +58,7 @@ export const swcTarget = (): Plugin => { }, module: { type: this.format === 'cjs' ? 'commonjs' : 'es6', - } as ModuleConfig, + } satisfies ModuleConfig, }) return { code: result.code, diff --git a/src/plugins/terser.ts b/src/plugins/terser.ts index c9ae773..d2d96b9 100644 --- a/src/plugins/terser.ts +++ b/src/plugins/terser.ts @@ -1,9 +1,9 @@ -import type { MinifyOptions } from 'terser' import { PrettyError } from '../errors' +import { localRequire } from '../utils' +import type { MinifyOptions } from 'terser' import type { Logger } from '../log' import type { Format, Options } from '../options' import type { Plugin } from '../plugin' -import { localRequire } from '../utils' export const terserPlugin = ({ minifyOptions, @@ -58,9 +58,9 @@ export const terserPlugin = ({ logger.success('TERSER', 'Terser Minification success') return { code: minifiedOutput.code!, map: minifiedOutput.map } - } catch (e) { + } catch (error) { logger.error('TERSER', 'Failed to minify with terser') - logger.error('TERSER', e) + logger.error('TERSER', error) } return { code, map: info.map } diff --git a/src/plugins/tree-shaking.ts b/src/plugins/tree-shaking.ts index ad042e9..71e5555 100644 --- a/src/plugins/tree-shaking.ts +++ b/src/plugins/tree-shaking.ts @@ -1,6 +1,6 @@ -import { rollup, type TreeshakingOptions, type TreeshakingPreset } from 'rollup' +import path from 'node:path' +import { type TreeshakingOptions, type TreeshakingPreset, rollup } from 'rollup' import type { Plugin } from '../plugin' -import path from 'path' export type TreeshakingStrategy = | boolean @@ -51,12 +51,13 @@ export const treeShakingPlugin = ({ }) for (const file of result.output) { - if (file.type === 'chunk') { - if (file.fileName === path.basename(info.path)) { - return { - code: file.code, - map: file.map, - } + if ( + file.type === 'chunk' && + file.fileName === path.basename(info.path) + ) { + return { + code: file.code, + map: file.map, } } } diff --git a/src/rollup.ts b/src/rollup.ts index 619ece8..cc8ae95 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -1,16 +1,16 @@ -import { parentPort } from 'worker_threads' -import type { InputOptions, OutputOptions, Plugin } from 'rollup' -import type { NormalizedOptions } from './' +import { parentPort } from 'node:worker_threads' +import path from 'node:path' import ts from 'typescript' import jsonPlugin from '@rollup/plugin-json' +import resolveFrom from 'resolve-from' import { handleError } from './errors' import { defaultOutExtension, removeFiles, toObjectEntry } from './utils' import { type TsResolveOptions, tsResolvePlugin } from './rollup/ts-resolve' import { createLogger, setSilent } from './log' import { getProductionDeps, loadPkg } from './load' -import path from 'path' import { reportSize } from './lib/report-size' -import resolveFrom from 'resolve-from' +import type { NormalizedOptions } from './' +import type { InputOptions, OutputOptions, Plugin } from 'rollup' const logger = createLogger() @@ -237,7 +237,7 @@ const startRollup = async (options: NormalizedOptions) => { try { await runRollup(config) parentPort?.postMessage('success') - } catch (error) { + } catch { parentPort?.postMessage('error') } parentPort?.close() diff --git a/src/rollup/ts-resolve.ts b/src/rollup/ts-resolve.ts index 0874464..792a840 100644 --- a/src/rollup/ts-resolve.ts +++ b/src/rollup/ts-resolve.ts @@ -1,9 +1,9 @@ -import fs from 'fs' -import path from 'path' -import type { PluginImpl } from 'rollup' +import fs from 'node:fs' +import path from 'node:path' +import { builtinModules } from 'node:module' import _resolve from 'resolve' import createDebug from 'debug' -import { builtinModules } from 'module' +import type { PluginImpl } from 'rollup' const debug = createDebug('tsup:ts-resolve') diff --git a/src/run.ts b/src/run.ts index 3930a34..b91079d 100644 --- a/src/run.ts +++ b/src/run.ts @@ -1,4 +1,4 @@ -import { spawn } from 'child_process' +import { spawn } from 'node:child_process' export function runCode(filename: string, { args }: { args: string[] }) { const cmd = spawn('node', [filename, ...args], { diff --git a/src/tsc.ts b/src/tsc.ts index edaae79..ce4d4c9 100644 --- a/src/tsc.ts +++ b/src/tsc.ts @@ -1,11 +1,11 @@ +import { dirname } from 'node:path' import { loadTsConfig } from 'bundle-require' import ts from 'typescript' import { handleError } from './errors' -import type { ExportDeclaration } from './exports' import { createLogger } from './log' -import type { NormalizedOptions } from './options' import { ensureTempDeclarationDir, toAbsolutePath } from './utils' -import { dirname } from 'path' +import type { ExportDeclaration } from './exports' +import type { NormalizedOptions } from './options' const logger = createLogger() @@ -37,9 +37,9 @@ function getExports( program: ts.Program, fileMapping: Map, ): ExportDeclaration[] { - let checker = program.getTypeChecker() - let aliasPool = new AliasPool() - let assignAlias = aliasPool.assign.bind(aliasPool) + const checker = program.getTypeChecker() + const aliasPool = new AliasPool() + const assignAlias = aliasPool.assign.bind(aliasPool) function extractExports(sourceFileName: string): ExportDeclaration[] { const cwd = program.getCurrentDirectory() @@ -87,9 +87,9 @@ function getExports( * @returns The mapping from source TS file paths to output declaration file paths */ function emitDtsFiles(program: ts.Program, host: ts.CompilerHost) { - let fileMapping = new Map() + const fileMapping = new Map() - let writeFile: ts.WriteFileCallback = ( + const writeFile: ts.WriteFileCallback = ( fileName, text, writeByteOrderMark, @@ -98,7 +98,7 @@ function emitDtsFiles(program: ts.Program, host: ts.CompilerHost) { data, ) => { const sourceFile = sourceFiles?.[0] - let sourceFileName = sourceFile?.fileName + const sourceFileName = sourceFile?.fileName if (sourceFileName && !fileName.endsWith('.map')) { const cwd = program.getCurrentDirectory() @@ -118,21 +118,21 @@ function emitDtsFiles(program: ts.Program, host: ts.CompilerHost) { ) } - let emitResult = program.emit(undefined, writeFile, undefined, true) + const emitResult = program.emit(undefined, writeFile, undefined, true) - let diagnostics = ts + const diagnostics = ts .getPreEmitDiagnostics(program) .concat(emitResult.diagnostics) - let diagnosticMessages: string[] = [] + const diagnosticMessages: string[] = [] diagnostics.forEach((diagnostic) => { if (diagnostic.file) { - let { line, character } = ts.getLineAndCharacterOfPosition( + const { line, character } = ts.getLineAndCharacterOfPosition( diagnostic.file, diagnostic.start!, ) - let message = ts.flattenDiagnosticMessageText( + const message = ts.flattenDiagnosticMessageText( diagnostic.messageText, '\n', ) @@ -140,7 +140,7 @@ function emitDtsFiles(program: ts.Program, host: ts.CompilerHost) { `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`, ) } else { - let message = ts.flattenDiagnosticMessageText( + const message = ts.flattenDiagnosticMessageText( diagnostic.messageText, '\n', ) @@ -148,11 +148,11 @@ function emitDtsFiles(program: ts.Program, host: ts.CompilerHost) { } }) - let diagnosticMessage = diagnosticMessages.join('\n') + const diagnosticMessage = diagnosticMessages.join('\n') if (diagnosticMessage) { logger.error( 'TSC', - 'Failed to emit declaration files.\n\n' + diagnosticMessage, + `Failed to emit declaration files.\n\n${diagnosticMessage}`, ) throw new Error('TypeScript compilation failed') } @@ -161,15 +161,15 @@ function emitDtsFiles(program: ts.Program, host: ts.CompilerHost) { } function emit(compilerOptions?: any, tsconfig?: string) { - let cwd = process.cwd() - let rawTsconfig = loadTsConfig(cwd, tsconfig) + const cwd = process.cwd() + const rawTsconfig = loadTsConfig(cwd, tsconfig) if (!rawTsconfig) { throw new Error(`Unable to find ${tsconfig || 'tsconfig.json'} in ${cwd}`) } - let declarationDir = ensureTempDeclarationDir() + const declarationDir = ensureTempDeclarationDir() - let parsedTsconfig = ts.parseJsonConfigFileContent( + const parsedTsconfig = ts.parseJsonConfigFileContent( { ...rawTsconfig.data, compilerOptions: { @@ -179,7 +179,7 @@ function emit(compilerOptions?: any, tsconfig?: string) { noEmit: false, declaration: true, declarationMap: true, - declarationDir: declarationDir, + declarationDir, emitDeclarationOnly: true, }, }, @@ -187,16 +187,16 @@ function emit(compilerOptions?: any, tsconfig?: string) { tsconfig ? dirname(tsconfig) : './', ) - let options: ts.CompilerOptions = parsedTsconfig.options + const options: ts.CompilerOptions = parsedTsconfig.options - let host: ts.CompilerHost = ts.createCompilerHost(options) - let program: ts.Program = ts.createProgram( + const host: ts.CompilerHost = ts.createCompilerHost(options) + const program: ts.Program = ts.createProgram( parsedTsconfig.fileNames, options, host, ) - let fileMapping = emitDtsFiles(program, host) + const fileMapping = emitDtsFiles(program, host) return getExports(program, fileMapping) } diff --git a/src/utils.ts b/src/utils.ts index 457c58f..0831465 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,6 @@ -import fs from 'fs' +import fs from 'node:fs' +import path from 'node:path' import glob from 'globby' -import path from 'path' import resolveFrom from 'resolve-from' import strip from 'strip-json-comments' import type { Entry, Format } from './options' @@ -30,15 +30,11 @@ export function isExternal( ) { return true } - if (external instanceof RegExp) { - if (external.test(id)) { - return true - } + if (external instanceof RegExp && external.test(id)) { + return true } - if (typeof external === 'function') { - if (external(id, parentId)) { - return true - } + if (typeof external === 'function' && external(id, parentId)) { + return true } } @@ -111,10 +107,9 @@ export function debouncePromise( // Taken from https://github.com/sindresorhus/slash/blob/main/index.js (MIT) export function slash(path: string) { - const isExtendedLengthPath = /^\\\\\?\\/.test(path) - const hasNonAscii = /[^\u0000-\u0080]+/.test(path) + const isExtendedLengthPath = path.startsWith('\\\\?\\') - if (isExtendedLengthPath || hasNonAscii) { + if (isExtendedLengthPath) { return path } @@ -129,7 +124,7 @@ export function truthy(value: T): value is Truthy { export function jsoncParse(data: string) { try { - return new Function('return ' + strip(data).trim())() + return new Function(`return ${strip(data).trim()}`)() } catch { // Silently ignore any error // That's what tsc/jsonc-parser did after all @@ -227,7 +222,7 @@ const findLowestCommonAncestor = (filepaths: string[]) => { } return ancestor.length <= 1 && ancestor[0] === '' - ? '/' + ancestor[0] + ? `/${ancestor[0]}` : ancestor.join('/') } diff --git a/test/css.test.ts b/test/css.test.ts index af65f27..69e2f0b 100644 --- a/test/css.test.ts +++ b/test/css.test.ts @@ -1,4 +1,4 @@ -import { test, expect } from 'vitest' +import { expect, test } from 'vitest' import { getTestName, run } from './utils' test('import css', async () => { diff --git a/test/dts.test.ts b/test/dts.test.ts index 5a44878..174a443 100644 --- a/test/dts.test.ts +++ b/test/dts.test.ts @@ -1,5 +1,5 @@ -import { test, expect } from 'vitest' -import path from 'path' +import path from 'node:path' +import { expect, test } from 'vitest' import { slash } from '../src/utils' import { getTestName, run } from './utils' @@ -371,8 +371,8 @@ test('should only include exported declarations with experimentalDts', async () flags: ['--experimental-dts'], }) - let entry1dts = await getFileContent('dist/entry1.d.ts') - let entry2dts = await getFileContent('dist/entry2.d.ts') + const entry1dts = await getFileContent('dist/entry1.d.ts') + const entry2dts = await getFileContent('dist/entry2.d.ts') expect(entry1dts).toContain('declare1') expect(entry1dts).not.toContain('declare2') diff --git a/test/graphql.test.ts b/test/graphql.test.ts index 0a0e5f1..48bbd70 100644 --- a/test/graphql.test.ts +++ b/test/graphql.test.ts @@ -1,4 +1,4 @@ -import { test, expect } from 'vitest' +import { expect, test } from 'vitest' import { getTestName, run } from './utils' test('bundle graphql-tools with --dts flag', async () => { diff --git a/test/index.test.ts b/test/index.test.ts index 4cc39df..0a95026 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,6 +1,6 @@ -import { test, expect } from 'vitest' -import path from 'path' -import fs from 'fs' +import path from 'node:path' +import fs from 'node:fs' +import { expect, test } from 'vitest' import waitForExpect from 'wait-for-expect' import { debouncePromise } from '../src/utils' import { getTestName, run } from './utils' @@ -253,7 +253,7 @@ test('debounce promise', async () => { if (!result) throw new Error(`${a} !== ${b}`) } - const sleep = (n: number = ~~(Math.random() * 50) + 20) => + const sleep = (n: number = Math.trunc(Math.random() * 50) + 20) => new Promise((resolve) => setTimeout(resolve, n)) let n = 0 @@ -288,8 +288,8 @@ test('debounce promise', async () => { await waitForExpect(() => { equal(n, 2) }) - } catch (err: any) { - return expect.fail(err.message) + } catch (error: any) { + return expect.fail(error.message) } }) @@ -349,7 +349,7 @@ test('windows: backslash in entry', async () => { getTestName(), { 'src/input.ts': `export const foo = 1` }, { - entry: ['src\\input.ts'], + entry: [String.raw`src\input.ts`], }, ) expect(outFiles).toEqual(['input.js']) diff --git a/test/svelte.test.ts b/test/svelte.test.ts index d7fa0a6..60629b7 100644 --- a/test/svelte.test.ts +++ b/test/svelte.test.ts @@ -75,7 +75,7 @@ test('svelte: typescript support', async () => { }) test('svelte: sass support', async () => { - const { outFiles, output, getFileContent } = await run(getTestName(), { + const { outFiles, getFileContent } = await run(getTestName(), { 'input.ts': `import App from './App.svelte' export { App } `, diff --git a/test/tsconfig.test.ts b/test/tsconfig.test.ts index 5bbff1a..f637980 100644 --- a/test/tsconfig.test.ts +++ b/test/tsconfig.test.ts @@ -1,4 +1,4 @@ -import { test, expect } from 'vitest' +import { expect, test } from 'vitest' import { getTestName, run } from './utils' test('custom tsconfig', async () => { diff --git a/test/utils.ts b/test/utils.ts index 7129d93..d928d98 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,9 +1,9 @@ +import path from 'node:path' +import { fileURLToPath } from 'node:url' import { expect } from 'vitest' -import path from 'path' import execa from 'execa' import fs from 'fs-extra' import glob from 'globby' -import { fileURLToPath } from 'url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const cacheDir = path.resolve(__dirname, '.cache') diff --git a/tsconfig.json b/tsconfig.json index 6059c7c..48a6196 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,70 +1,16 @@ { "compilerOptions": { - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "esnext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, - "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, - // "lib": [], /* Specify library files to be included in the compilation. */ - // "allowJs": true, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true /* Generates corresponding '.d.ts' file. */, - "declarationDir": "dist", - // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - // "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./dist" /* Redirect output structure to the directory. */, - // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + "target": "esnext", + "module": "esnext", + "moduleResolution": "node", "resolveJsonModule": true, - "skipLibCheck": true, - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, - - "verbatimModuleSyntax": true + "strict": true, + "declaration": true, + "declarationDir": "dist", + "outDir": "./dist", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "verbatimModuleSyntax": true, + "skipLibCheck": true } } diff --git a/vitest-global.ts b/vitest-global.ts index e38b1b7..90f7b3b 100644 --- a/vitest-global.ts +++ b/vitest-global.ts @@ -1,6 +1,6 @@ +import path from 'node:path' +import fs from 'node:fs/promises' import execa from 'execa' -import path from 'path' -import fs from 'fs/promises' export default async function setup() { const testDir = path.resolve(__dirname, 'test')