npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jmlweb/tsup-config-base

v1.1.4

Published

Base tsup configuration for jmlweb projects with sensible defaults

Readme

@jmlweb/tsup-config-base

npm version License: MIT Node.js tsup

Base tsup configuration for jmlweb projects. Provides sensible defaults and a clean API for creating consistent build configurations.

✨ Features

  • 🎯 Sensible Defaults: Pre-configured with common settings for TypeScript libraries
  • 📦 Dual Format: Generates both CommonJS and ESM outputs by default
  • 📝 TypeScript Declarations: Automatic .d.ts generation enabled
  • 🔧 Clean API: Simple function to create configurations with external dependencies
  • Zero Config: Works out of the box with minimal setup
  • 🛠️ Fully Typed: Complete TypeScript support with exported types
  • 🖥️ CLI Preset: Specialized configuration for CLI packages with shebang support

📦 Installation

pnpm add -D @jmlweb/tsup-config-base tsup

💡 Upgrading from a previous version? See the Migration Guide for breaking changes and upgrade instructions.

🚀 Quick Start

Create a tsup.config.ts file in your project root:

import { createTsupConfig } from '@jmlweb/tsup-config-base';

export default createTsupConfig();

💡 Examples

Basic Setup (No Externals)

// tsup.config.ts
import { createTsupConfig } from '@jmlweb/tsup-config-base';

export default createTsupConfig();

With External Dependencies

// tsup.config.ts
import { createTsupConfig } from '@jmlweb/tsup-config-base';

export default createTsupConfig({
  external: ['eslint', 'typescript-eslint', '@eslint/js'],
});

With Internal Workspace Dependencies

// tsup.config.ts
import { createTsupConfig } from '@jmlweb/tsup-config-base';

export default createTsupConfig({
  external: [
    // Internal packages
    '@jmlweb/eslint-config-base-js',
    // External peer dependencies
    '@eslint/js',
    'eslint',
    'eslint-config-prettier',
    'typescript-eslint',
  ],
});

Custom Entry Point

// tsup.config.ts
import { createTsupConfig } from '@jmlweb/tsup-config-base';

export default createTsupConfig({
  entry: ['src/main.ts'],
  external: ['some-dependency'],
});

With Additional Options

// tsup.config.ts
import { createTsupConfig } from '@jmlweb/tsup-config-base';

export default createTsupConfig({
  external: ['vitest'],
  options: {
    minify: true,
    sourcemap: true,
    splitting: true,
  },
});

Multiple Entry Points

// tsup.config.ts
import { createTsupConfig } from '@jmlweb/tsup-config-base';

export default createTsupConfig({
  entry: ['src/index.ts', 'src/cli.ts'],
  external: ['commander'],
});

Object-Style Entry Points

// tsup.config.ts
import { createTsupConfig } from '@jmlweb/tsup-config-base';

export default createTsupConfig({
  entry: {
    index: 'src/index.ts',
    utils: 'src/utils/index.ts',
  },
});

CLI Package Configuration

For CLI packages that need shebang injection, use createTsupCliConfig:

// tsup.config.ts
import { createTsupCliConfig } from '@jmlweb/tsup-config-base';

export default createTsupCliConfig();
// Output: dist/cli.js with #!/usr/bin/env node shebang

CLI with Custom Entry

// tsup.config.ts
import { createTsupCliConfig } from '@jmlweb/tsup-config-base';

export default createTsupCliConfig({
  entry: { bin: 'src/bin.ts' },
  external: ['commander'],
});

CLI with Library API

// tsup.config.ts
import { createTsupCliConfig } from '@jmlweb/tsup-config-base';

export default createTsupCliConfig({
  entry: {
    cli: 'src/cli.ts',
    index: 'src/index.ts',
  },
  shebang: 'cli', // Only add shebang to cli entry
  external: ['commander'],
});

🤔 Why Use This?

Philosophy: TypeScript libraries should publish both CommonJS and ESM formats with type declarations for maximum compatibility across all consuming projects.

This package provides a tsup configuration optimized for building TypeScript libraries with dual-format output. It handles the complexity of generating both CommonJS and ESM builds while maintaining proper type definitions and ensuring external dependencies aren't bundled.

Design Decisions

Dual Format Output (format: ['cjs', 'esm']): Support both module systems

  • Why: The JavaScript ecosystem is in transition from CommonJS to ESM. Publishing both formats ensures your library works in all environments - legacy Node.js projects using require(), modern ESM projects using import, and bundlers that optimize based on format. This maximizes compatibility
  • Trade-off: Slightly larger published package size (two builds). But consumers only use one format, and the compatibility benefit is essential
  • When to override: For internal packages consumed only by ESM projects, you can use ['esm'] only. But dual publishing is safer for public libraries

Type Declaration Generation (dts: true): Automatic .d.ts files

  • Why: TypeScript consumers need type definitions for intellisense, type checking, and developer experience. Generating declarations automatically ensures your library provides first-class TypeScript support without manual maintenance
  • Trade-off: Slightly slower builds due to declaration generation. But type safety for consumers is non-negotiable
  • When to override: Never for libraries meant to be consumed - types are essential for modern JavaScript development

External Dependencies (external array): Control bundling

  • Why: Libraries shouldn't bundle their dependencies - this leads to duplicate code, version conflicts, and bloated packages. The external parameter lets you specify which dependencies should remain as imports, letting consumers manage versions
  • Trade-off: Must carefully specify which dependencies are external (typically all dependencies and peerDependencies)
  • When to override: For standalone CLI tools, you might bundle all dependencies. But for libraries, externals are crucial

Clean Builds (clean: true): Fresh output on every build

  • Why: Cleaning the output directory prevents stale files from previous builds causing issues. Ensures deterministic builds and prevents shipping renamed or deleted files
  • Trade-off: Very slightly slower builds (must delete files first). But the reliability is worth it
  • When to override: Rarely - clean builds prevent an entire class of mysterious bugs

📋 Configuration Details

Default Settings

| Setting | Default Value | Description | | ---------- | ------------------ | ----------------------------------- | | entry | ['src/index.ts'] | Entry point(s) for the build | | format | ['cjs', 'esm'] | Output formats (dual publishing) | | dts | true | Generate TypeScript declarations | | clean | true | Clean output directory before build | | outDir | 'dist' | Output directory | | external | [] | External packages to exclude |

API Reference

createTsupConfig(options?: TsupConfigOptions): Options

Creates a tsup configuration with sensible defaults for library packages.

Parameters:

| Option | Type | Default | Description | | ---------- | ------------------------------------ | ------------------ | -------------------------------- | | entry | string[] \| Record<string, string> | ['src/index.ts'] | Entry point files | | format | ('cjs' \| 'esm' \| 'iife')[] | ['cjs', 'esm'] | Output formats | | dts | boolean | true | Generate declaration files | | clean | boolean | true | Clean output before build | | outDir | string | 'dist' | Output directory | | external | (string \| RegExp)[] | [] | Packages to exclude from bundle | | options | Partial<Options> | {} | Additional tsup options to merge |

Returns: A complete tsup Options object.

createTsupCliConfig(options?: TsupCliConfigOptions): Options | Options[]

Creates a CLI-specific tsup configuration with shebang support.

Parameters:

| Option | Type | Default | Description | | ---------- | ------------------------------------ | ----------------------- | ------------------------------------------- | | entry | string[] \| Record<string, string> | { cli: 'src/cli.ts' } | Entry point files | | format | ('cjs' \| 'esm' \| 'iife')[] | ['esm'] | Output formats (ESM only by default) | | dts | boolean | true | Generate declaration files | | clean | boolean | true | Clean output before build | | outDir | string | 'dist' | Output directory | | external | (string \| RegExp)[] | [] | Packages to exclude from bundle | | target | NodeTarget | 'node18' | Node.js target version | | shebang | boolean \| string \| string[] | true | Add shebang to entries (true = all entries) | | options | Partial<Options> | {} | Additional tsup options to merge |

Returns: A tsup Options object, or an array of Options when selective shebang is used.

Exported Constants

  • BASE_DEFAULTS - Default library configuration values
  • CLI_DEFAULTS - Default CLI configuration values
  • Options - Re-exported from tsup

Type Exports

  • EntryConfig - Entry point configuration type (string[] | Record<string, string>)
  • NodeTarget - Node.js target version type ('node16' | 'node18' | 'node20' | 'node22' | ...)
  • TsupConfigOptions - Options for createTsupConfig
  • TsupCliConfigOptions - Options for createTsupCliConfig

🎯 When to Use

Use this configuration when you want:

  • ✅ Consistent build configuration across multiple packages
  • ✅ Dual-format output (CommonJS + ESM) for maximum compatibility
  • ✅ Automatic TypeScript declaration generation
  • ✅ A clean, simple API for specifying externals
  • ✅ Easy customization without repeating boilerplate
  • ✅ CLI packages with proper shebang injection

🔧 Extending the Configuration

You can extend the configuration for your specific needs:

Adding Custom Options

// tsup.config.ts
import { createTsupConfig } from '@jmlweb/tsup-config-base';

export default createTsupConfig({
  external: ['vitest'],
  options: {
    minify: true,
    sourcemap: true,
    splitting: true,
    target: 'es2022',
  },
});

Overriding Defaults

// tsup.config.ts
import { createTsupConfig } from '@jmlweb/tsup-config-base';

export default createTsupConfig({
  format: ['esm'], // ESM only
  dts: false, // Disable type declarations
  outDir: 'build', // Custom output directory
});

Externals Strategy

When configuring external, include:

  1. Peer dependencies: Packages that consumers should install themselves
  2. Workspace dependencies: Internal @jmlweb/* packages used via workspace:*
  3. Optional dependencies: Packages that may or may not be present
// Example: ESLint config package
export default createTsupConfig({
  external: [
    // Internal workspace dependency
    '@jmlweb/eslint-config-base-js',
    // Peer dependencies
    '@eslint/js',
    'eslint',
    'eslint-config-prettier',
    'eslint-plugin-simple-import-sort',
    'typescript-eslint',
  ],
});

📝 Usage with Scripts

Add build scripts to your package.json:

{
  "scripts": {
    "build": "tsup",
    "clean": "rm -rf dist",
    "prepublishOnly": "pnpm build"
  }
}

Then run:

pnpm build    # Build the package
pnpm clean    # Clean build output

📋 Requirements

  • Node.js >= 18.0.0
  • tsup >= 8.0.0

📦 Peer Dependencies

This package requires the following peer dependency:

  • tsup (>=8.0.0)

🔗 Related Packages

Internal Packages

External Tools

  • tsup - Bundle TypeScript libraries with zero config
  • esbuild - Extremely fast JavaScript bundler (used by tsup)
  • TypeScript - JavaScript with syntax for types
  • Rollup - Alternative bundler for complex configurations

🔄 Migration Guide

Upgrading to a New Version

Note: If no breaking changes were introduced in a version, it's safe to upgrade without additional steps.

No breaking changes have been introduced yet. This package follows semantic versioning. When breaking changes are introduced, detailed migration instructions will be provided here.

For version history, see the Changelog.

Need Help? If you encounter issues during migration, please open an issue.

📜 Changelog

See CHANGELOG.md for version history and release notes.

📄 License

MIT