---
url: /docs/guide/workspaces.md
---
# Bunup Workspaces
Effortlessly manage **multiple packages in a monorepo** with Bunupβs built-in workspace support.
This eliminates the need for separate build configurations and multiple commands for each package. With a single configuration file and a single command, you can build all your packages at once.
## Creating a Workspace Configuration
Define your workspace using the `defineWorkspace` function:
```ts [bunup.config.ts]
import { defineWorkspace } from "bunup";
export default defineWorkspace([
// Package configurations go here
]);
```
## Package Configuration
Each package requires three properties:
| Property | Type | Description |
| -------- | ------------------------------ | ------------------------------------------------------------ |
| `name` | `string` | Unique identifier for the package |
| `root` | `string` | Path to the package directory, relative to the monorepo root |
| `config` | `BunupConfig \| BunupConfig[]` | Optional build configuration(s) for this package |
π If you omit `config`, Bunup will use **defaults**:
* Build as ESM-only
* Use [default entry points](/#default-entry-points) (e.g. `src/index.ts`)
* Generate TypeScript declaration files (`.d.ts`) for entry points that need them
## Basic Usage
A minimal workspace with two packages:
```ts [bunup.config.ts]
import { defineWorkspace } from "bunup";
export default defineWorkspace([
{
name: "core",
root: "packages/core",
config: {
// Bunup finds 'src/index.ts' by default
// Or specify exactly which files to build
// entry: ["src/index.ts", "src/plugins.ts"],
format: ["esm", "cjs"],
},
},
{
name: "utils",
root: "packages/utils",
// Uses default entry points
// Uses default format: esm
// Generates .d.ts declaration files
},
]);
```
Here, **`core`** has custom formats, while **`utils`** works out of the box with defaults.
## Shared Options
You can define **shared options** for all packages, reducing repetition:
```ts [bunup.config.ts]
export default defineWorkspace(
[
{
name: "core",
root: "packages/core",
config: {
format: ["esm"], // overrides shared format
},
},
{
name: "utils",
root: "packages/utils",
// config is optional, shared options apply
},
],
{
// Shared options
format: ["esm", "cjs"],
exports: true,
}
);
```
## Multiple Build Configurations
Each package can have multiple builds by passing an array.
::: info Named Configurations
When using an array of build configurations, the `name` property is **required** for each configuration to identify the builds in logs and reports.
:::
```ts [bunup.config.ts]
export default defineWorkspace([
{
name: "web",
root: "packages/web",
config: [
{
entry: "src/index.ts",
name: "node",
format: "esm",
target: "node",
},
{
entry: "src/browser.ts",
name: "browser",
format: ["esm", "iife"],
target: "browser",
outDir: "dist/browser",
},
],
},
]);
```
**Another example:** if you have different entry points that need different build configurations, you can specify them separately. For instance, your main module might need both ESM and CJS formats, while a CLI entry point might only need ESM:
```ts [bunup.config.ts]
export default defineWorkspace([
{
name: "main",
root: "packages/main",
config: [
{
entry: "src/index.ts",
name: "main",
format: ["esm", "cjs"],
},
{
entry: "src/cli.ts",
name: "cli",
format: ["esm"],
},
],
},
]);
```
## Path Resolution
All paths in package configs are **relative to the package root**:
```
myproject/
βββ packages/
β βββ core/ <- package root
β β βββ src/ <- entries resolved here
β β βββ dist/ <- outputs here
β βββ utils/
βββ bunup.config.ts
βββ package.json
```
Example:
```ts
{
name: "core",
root: "packages/core",
config: {
entry: "src/index.ts", // resolves to packages/core/src/index.ts
outDir: "dist", // outputs to packages/core/dist/
},
}
```
::: tip Plugin Paths
When using plugins (like [`copy`](/docs/builtin-plugins/copy)), paths are also resolved relative to the **package root**.
For example, `copy("assets/**/*.svg")` in the `core` package will copy from `packages/core/assets`.
:::
## Building Packages
### Build all packages
```sh
bunx bunup
```
### Watch mode
```sh
bunx bunup --watch
```
Bunup will watch **all packages** and rebuild only those that change.
### Build specific packages
Use the `--filter` option with package names:
```sh
bunx bunup --filter core,utils
# or in watch mode
bunx bunup --filter core,utils --watch
```
::: info Incremental Builds
Workspaces are **incremental**: only changed packages are rebuilt.
:::
---
---
url: /docs/guide/cli-options.md
---
# CLI Options
---
---
url: /docs/advanced/compile.md
---
# Compile to Executable
Bunup supports creating standalone executables using the `compile` option. This allows you to bundle your code and the Bun runtime into a single executable file that can be distributed and run without requiring Bun to be installed.
## Use Case
The `compile` option is useful when you want to:
* Distribute CLI tools that users can run without installing Bun
* Create standalone executables for scripts and utilities
* Package your code with all dependencies included
## Output Directory
Compiled executables output to `bin/` by default, unlike normal builds which output to `dist/` by default. If you want to change the output location, you can use the `outDir` option to specify a different directory like `dist/` or any other location.
## Basic Usage
```typescript [bunup.config.ts]
export default defineConfig({
entry: 'src/cli.ts',
compile: true, // Create executable for current platform
});
```
This will output the executable to the `bin/` directory.
## Customizing Output Directory
You can change the output directory using the `outDir` option:
```typescript [bunup.config.ts]
export default defineConfig({
entry: 'src/cli.ts',
compile: true,
outDir: 'dist', // Output to dist/ instead of bin/
});
```
## Cross-Compilation
Target specific platforms:
```typescript [bunup.config.ts]
export default defineConfig({
entry: 'src/cli.ts',
compile: 'bun-linux-x64', // Cross-compile for Linux
});
```
## Advanced Configuration
```typescript [bunup.config.ts]
export default defineConfig({
entry: 'src/cli.ts',
compile: {
target: 'bun-linux-x64',
outfile: './bin/my-app',
windows: {
hideConsole: true,
icon: './icon.ico',
},
},
});
```
## Multiple Entrypoints
Only one entrypoint can be compiled at a time. If you want to compile multiple entrypoints, you need to use a build config array with separate configurations:
```typescript [bunup.config.ts]
export default defineConfig([
{
name: 'main',
entry: 'src/main.ts',
compile: true,
},
{
name: 'cli',
entry: 'src/cli.ts',
compile: {
outfile: 'my-cli',
},
},
]);
```
This will create separate executables for each entrypoint.
## Cross-Compiling for Multiple Targets
If you want to cross-compile the same entrypoint for multiple targets, or use different configurations for different targets, you can create separate objects in the config array:
```typescript [bunup.config.ts]
export default defineConfig([
{
name: 'cli-linux',
entry: 'src/cli.ts',
compile: 'bun-linux-x64',
},
{
name: 'cli-windows',
entry: 'src/cli.ts',
compile: {
target: 'bun-windows-x64',
outfile: './bin/my-app-windows.exe',
windows: {
hideConsole: true,
icon: './icon.ico',
},
},
},
{
name: 'cli-macos',
entry: 'src/cli.ts',
compile: {
target: 'bun-darwin-arm64',
outfile: './bin/my-app-macos',
},
},
]);
```
This approach allows you to:
* Build executables for multiple platforms in a single build command
* Apply platform-specific configurations (like Windows console hiding or custom icons)
* Customize the output filename for each target platform
## Mixing Executables and Library Builds
You can also mix executable compilation with normal library builds in the same config array. This is useful when you want to build both a library and CLI tools:
```typescript [bunup.config.ts]
export default defineConfig([
{
name: 'library',
entry: 'src/index.ts',
format: ['esm', 'cjs'],
dts: true,
// Normal library build
},
{
name: 'cli',
entry: 'src/cli.ts',
compile: true,
// Compile to executable
},
]);
```
This allows you to build your library and create executables in a single build process.
## Learn More
For detailed information about available targets and configuration options, see the [Bun documentation on executables](https://bun.com/docs/bundler/executables).
---
---
url: /docs/guide/config-file.md
---
# Config File
Centralize your build settings with a configuration file when CLI options aren't enough.
## Getting Started
Create a `bunup.config.ts` file in your project root:
```ts [bunup.config.ts]
import { defineConfig } from 'bunup';
export default defineConfig({
// ...your configuration options go here
});
```
This is the simplest way to centralize and reuse your build configuration. See [Options](/docs/guide/options) for all the available options.
## Multiple Configurations
Bunup supports exporting an **array of configurations**, useful when you want to build for multiple environments or formats in a single run.
::: info Named Configurations
When using an array of configurations, the `name` property is **required** for each configuration to identify the builds in logs and reports.
:::
```ts [bunup.config.ts]
export default defineConfig([
{
entry: "src/index.ts",
name: 'node',
format: 'esm',
target: 'node',
},
{
entry: "src/browser.ts",
name: 'browser',
format: ['esm', 'iife'],
target: 'browser',
outDir: 'dist/browser',
},
]);
```
With this setup, Bunup will build both Node.js and browser bundles.
**Another example:** if you have different entry points that need different build configurations, you can specify them separately. For instance, your main module might need both ESM and CJS formats, while a CLI entry point might only need ESM:
```ts [bunup.config.ts]
export default defineConfig([
{
entry: "src/index.ts",
name: 'main',
format: ['esm', 'cjs'],
},
{
entry: "src/cli.ts",
name: 'cli',
format: ['esm'],
},
{
entry: "src/browser.ts",
name: 'browser',
format: ['esm', 'iife'],
outDir: 'dist/browser'
},
]);
```
## Filtering Configurations
When you have multiple configurations in an array, you can use the `--filter` option to build only specific configurations by name:
```sh [CLI]
# Single
bunup --filter main
# Multiple
bunup --filter main,browser
```
Only the configurations matching these names will be built - perfect for testing specific builds without running the entire suite.
## Custom Configuration Path
If you need to use a configuration file with a non-standard name or location, you can specify its path using the `--config` CLI option:
::: code-group
```sh [CLI]
bunup --config ./configs/custom.bunup.config.ts
# or using alias
bunup -c ./configs/custom.bunup.config.ts
```
:::
This allows you to keep your configuration files organized in custom locations or use different configuration files for different environments.
## Disabling Configuration Files
To explicitly disable config file usage and rely only on CLI options:
```sh [CLI]
bunup --no-config
```
---
---
url: /docs/builtin-plugins/copy.md
---
# Copy
The copy plugin copies files and directories to your build output. It supports glob patterns, direct folder copying, file transformation with filename changes, and can copy to specific destinations or rename files and folders.
## Basic Usage
```ts [bunup.config.ts]
import { defineConfig } from 'bunup';
import { copy } from 'bunup/plugins';
export default defineConfig({
plugins: [copy(['README.md', 'assets/**/*'])],
});
```
This will copy the `README.md` file and all files in the `assets` directory to your build output directory.
Use `copy(pattern)` to copy files or folders. Optionally, add `.to(destination)` to set the output name or location, `.with(options)` for extra settings, and `.transform(fn)` to modify files during copy. By default, everything is copied to your build output directory.
## Examples
Below are some examples of how to use the copy plugin.
### Basic File Operations
```ts
// Copy single file
copy('README.md')
// Copy multiple specific files
copy(['README.md', 'LICENSE', 'CHANGELOG.md'])
// Copy and rename a file
copy('README.md').to('documentation.md')
```
### Directory Operations
```ts
// Copy entire directory as is (preserves structure)
copy('assets') // β dist/assets/
// Copy and rename directory
copy('assets').to('static') // β dist/static/
// Copy multiple directories
copy(['assets', 'public', 'docs'])
```
### Glob Patterns
```ts
// Copy all markdown files recursively
copy('**/*.md')
// Copy all files in assets directory
copy('assets/**/*')
// Copy with multiple patterns
copy([
'assets/**/*', // All files in assets
'docs/**/*.md', // Markdown files in docs
'src/**/*.css', // CSS files in src
])
```
### Pattern Exclusions
```ts
// Exclude specific files and patterns
copy([
'assets/**/*', // Include all assets
'!**/*.tmp', // Exclude temporary files
'!**/*.log', // Exclude log files
'!**/node_modules', // Exclude node_modules
'!**/.DS_Store' // Exclude system files
])
```
### Flattening Structure
```ts
// Flatten all files from subdirectories
copy('assets/**/*').to('static') // All files β dist/static/
// Flatten specific file types
copy('src/**/*.css').to('styles') // All CSS β dist/styles/
copy('images/**/*.{png,jpg,svg}').to('assets') // All images β dist/assets/
```
### Multiple Copy Operations
You can add multiple copy plugins for different copy operations:
```ts
export default defineConfig({
plugins: [
copy('README.md'),
copy('assets/**/*').to('static'),
copy('docs/**/*.md').to('documentation'),
],
});
```
## Transform Files
Transform files on the fly during the copy operation using the `transform()` method. The transform function receives a context object with file content, paths, and build options.
```ts
// Simple transformation - minify JSON files
copy('data/**/*.json')
.transform(({ content }) => {
// Return content only - keeps original filename
return JSON.stringify(JSON.parse(content.toString()))
})
// Transform with filename change - TypeScript to JavaScript
copy('scripts/**/*.ts')
.transform(async ({ content, path }) => {
const transpiler = new Bun.Transpiler({ loader: 'ts' })
// Return object to change both content and filename
return {
content: transpiler.transformSync(content.toString()),
filename: basename(path).replace('.ts', '.js')
}
})
// Access full context including build options
copy('config/**/*')
.transform(({ content, path, destination, options }) => {
// options contains build configuration (outDir, minify, etc.)
// destination is where the file will be written
const processed = content.toString()
.replace('__BUILD_MODE__', options.watch ? 'development' : 'production')
.replace('__OUT_DIR__', options.outDir)
return processed
})
```
## Options
The copy plugin supports additional options via the `with()` method to customize copy behavior.
### `followSymlinks`
Whether to follow symbolic links when copying files. By default, symbolic links are not followed.
```ts [bunup.config.ts]
copy('assets/**/*').with({
followSymlinks: true
})
```
### `excludeDotfiles`
Whether to exclude dotfiles (files starting with a dot) from being copied. By default, dotfiles are included in the copy operation.
```ts [bunup.config.ts]
copy('assets/**/*').with({
excludeDotfiles: true
})
```
### `override`
Whether to override existing files in the destination. By default, existing files are overwritten.
```ts [bunup.config.ts]
// Skip files that already exist in the destination
copy('assets/**/*').with({
override: false
})
```
### `watchMode`
Controls the behavior of the copy plugin in watch mode. Available options:
* `'changed'` (default): Only copy files that have been modified since the last build
* `'always'`: Copy all files on every build, regardless of changes
* `'skip'`: Skip copying entirely in watch mode
```ts [bunup.config.ts]
// Only copy changed files in watch mode (default)
copy('assets/**/*').with({
watchMode: 'changed'
})
// Always copy all files, even in watch mode
copy('config/**/*').with({
watchMode: 'always'
})
// Skip copying in watch mode (useful for large static assets)
copy('videos/**/*').with({
watchMode: 'skip'
})
```
---
---
url: /docs/guide/css.md
---
# CSS
Bunup handles CSS automatically. Just import it and it works.
## Quick Start
Import CSS in your TypeScript files:
```typescript [src/index.ts]
import './styles.css';
import { Button } from './components/button';
export { Button };
```
```css [src/styles.css]
.button {
background-color: #007bff;
color: white;
padding: 8px 16px;
border: none;
border-radius: 4px;
}
```
Bunup automatically bundles your CSS into `dist/index.css` with cross-browser compatibility.
Any CSS imports encountered in your files will be bundled together into `dist/index.css`.
To generate separate CSS files instead of a single `index.css` output, add them as entry points rather than importing them in your files:
```typescript [bunup.config.ts]
import { defineConfig } from 'bunup';
export default defineConfig({
entry: [
'src/index.ts',
'src/components/button.css'
'src/components/alert.css'
],
});
```
This creates individual CSS files in your build output:
```plaintext
dist/
βββ index.js
βββ components/
βββ button.css
βββ alert.css
```
## CSS Modules
CSS modules prevent style conflicts by automatically scoping class names. Just add `.module.css` to your filename:
::: tip
New to CSS modules? Check out [this guide](https://css-tricks.com/css-modules-part-1-need/) to learn what they are and why they're useful.
:::
```css [src/components/button.module.css]
.primary {
background-color: #007bff;
color: white;
padding: 8px 16px;
border: none;
border-radius: 4px;
}
```
```tsx [src/components/button.tsx]
import styles from "./button.module.css";
export function Button({ children }) {
return (
);
}
```
That's it! Bunup handles the rest automatically.
### Sharing Styles
Reuse styles with the `composes` property:
```css [src/components/button.module.css] {9,15}
.base {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.primary {
composes: base;
background-color: #007bff;
color: white;
}
.secondary {
composes: base;
background-color: transparent;
color: #007bff;
border: 1px solid #007bff;
}
```
**Rules:**
* `composes` must come first in the class
* Works only with single class selectors (not `#id` or `.class1, .class2`)
**From other files:**
```css [src/components/button.module.css] {2}
.primary {
composes: base from "../shared.module.css";
background-color: #007bff;
color: white;
}
```
::: warning
Avoid conflicting properties when composing from separate files.
:::
## Distributing CSS
Export CSS files for package consumers:
```json [package.json]
{
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./styles.css": "./dist/index.css" // [!code ++]
}
}
```
Users can then import your styles:
```javascript
import 'your-package/styles.css';
import { Button } from 'your-package';
```
::: tip
Use the [inject styles option](/docs/extra-options/inject-styles) to bundle CSS directly into JavaScript so users do not need a separate CSS import.
:::
## Browser Compatibility
Bunup automatically ensures cross-browser compatibility:
* Converts modern CSS syntax to work in older browsers
* Adds vendor prefixes (`-webkit-`, `-moz-`, etc.) where needed
* Targets: Chrome 87+, Firefox 78+, Safari 14+, Edge 88+
## TypeScript Support
Bunup automatically creates TypeScript definitions for CSS modules. Get autocomplete and type safety for free.
```css [src/components/button.module.css]
.primary {
background-color: #007bff;
color: white;
}
.secondary {
background-color: transparent;
color: #007bff;
}
```
Bunup generates this TypeScript file:
```ts [src/components/button.module.css.d.ts]
declare const classes: {
readonly primary: string;
readonly secondary: string;
};
export default classes;
```
**You get:**
* Autocomplete when typing `styles.`
* Errors for typos like `styles.primry`
* Safe refactoring when renaming CSS classes
### Development
Type definitions generate automatically when you build. For the best experience with CSS modules, use watch mode:
```sh
bunup --watch
```
Watch mode instantly regenerates type definitions when CSS module files change. Change a class name and save, you'll immediately see TypeScript errors wherever the old class name is used.
### Configuration
#### Exclude from Git
Since type definitions are auto-generated, exclude them from version control:
```plaintext [.gitignore]
**/*.module.*.d.ts
```
#### Disable type generation
Turn off automatic type generation if you prefer to handle it manually:
::: code-group
```sh [CLI]
bunup --no-css.typed-modules
```
```ts [bunup.config.ts]
import { defineConfig } from 'bunup';
export default defineConfig({
css: {
typedModules: false
}
});
```
:::
---
---
url: /docs/extra-options/exports.md
---
# Exports
Bunup automatically generates and updates the `exports` field in your package.json file after each build.
Bunup handles mapping all entry points to their corresponding output files, including ESM/CJS formats and type declarations. The exports field stays perfectly in sync with your build configuration always - no manual updates needed when you make any change to config.
## Usage
Enable exports generation in your Bunup configuration:
::: code-group
```sh [CLI]
bunup --exports
```
```ts [bunup.config.ts]
import { defineConfig } from 'bunup';
export default defineConfig({
exports: true,
});
```
:::
This will automatically update your package.json with the correct exports field each time you build. For example:
```json [package.json]
{
"name": "my-package",
"version": "1.0.0",
"type": "module",
"files": [ // [!code ++]
"dist" // [!code ++]
], // [!code ++]
"module": "./dist/index.js", // [!code ++]
"main": "./dist/index.cjs", // [!code ++]
"types": "./dist/index.d.ts", // [!code ++]
"exports": { // [!code ++]
".": { // [!code ++]
"import": { // [!code ++]
"types": "./dist/index.d.ts", // [!code ++]
"default": "./dist/index.js" // [!code ++]
}, // [!code ++]
"require": { // [!code ++]
"types": "./dist/index.d.cts", // [!code ++]
"default": "./dist/index.cjs" // [!code ++]
} // [!code ++]
} // [!code ++]
} // [!code ++]
}
```
## Custom Exports
The `customExports` option allows you to specify additional export fields that will be preserved alongside the automatically generated exports. This is useful when you need custom export conditions or paths that aren't automatically generated by the build process.
```ts [bunup.config.ts]
import { defineConfig } from 'bunup';
export default defineConfig({
exports: {
customExports: (ctx) => ({
'./package.json': './package.json',
})
},
});
```
## Exclude
The `exclude` option allows you to filter out specific export keys from the generated exports field in your package.json. This operates on the final export keys (like `"."`, `"./utils"`, `"./components"`) that appear in the exports object.
You can provide an array of strings (using exact export keys, wildcards, or a mix of both), or a function that returns such an array.
::: code-group
```sh [CLI]
# Single exclusion - exclude the "./internal" export key
bunup --exports.exclude=./internal
# Multiple exclusions
bunup --exports.exclude=./utils,./internal
# Using wildcards - exclude all exports under "./private"
bunup --exports.exclude="./private/*"
# Mix both - exact keys and wildcards
bunup --exports.exclude="./internal,./private/*"
```
```ts [bunup.config.ts]
import { defineConfig } from 'bunup';
export default defineConfig({
entry: ['src/index.ts', 'src/utils.ts', 'src/internal.ts'],
exports: {
// Exclude the "./internal" export key from package.json exports
exclude: ['./internal']
},
});
```
:::
This will generate exports for `"."` and `"./utils"` but exclude `"./internal"` from the final package.json:
```json [package.json]
{
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./utils": {
"import": "./dist/utils.js",
"types": "./dist/utils.d.ts"
}
// "./internal" is excluded
}
}
```
For more dynamic control, you can use a function:
```ts [bunup.config.ts]
import { defineConfig } from 'bunup';
export default defineConfig({
entry: ['src/index.ts', 'src/utils.ts', 'src/internal.ts'],
exports: {
exclude: (ctx) => {
// Access build context information
const { options, meta } = ctx;
// Dynamically exclude export keys based on your logic
return ['./internal', './debug'];
}
},
});
```
## Exclude CLI
By default, CLI-related entry points are automatically excluded from the package exports field. This prevents binary/command-line tools from being exposed as importable package exports, which is the correct behavior in most cases since CLI entries are typically used via the `bin` field in package.json.
The plugin uses glob patterns to automatically detect and exclude common CLI entry point patterns:
* Files or directories named `cli` (e.g., `cli.ts`, `cli/index.ts`)
* Files or directories named `bin` (e.g., `bin.ts`, `bin/index.ts`)
* CLI-related paths in any directory (e.g., `src/cli.ts`, `tools/bin/index.ts`)
If you want to include CLI entries in your exports (which is rarely needed), you can disable this behavior:
::: code-group
```sh [CLI]
bunup --no-exports.exclude-cli
```
```ts [bunup.config.ts]
import { defineConfig } from 'bunup';
export default defineConfig({
exports: {
excludeCli: false // Include CLI entries in exports
},
});
```
:::
When disabled, CLI entries will be treated like any other entry point and included in the exports field.
## Exclude CSS
When you use CSS files and import them in your JavaScript files, Bun will bundle the CSS and include it in the build output. As a result, these CSS files will be automatically added to the exports field with appropriate export keys.
The `excludeCss` option allows you to prevent CSS files from being included in the exports field if you prefer to handle CSS distribution manually or don't want to expose CSS files as part of your package's public API.
::: code-group
```sh [CLI]
bunup --exports.exclude-css
```
```ts [bunup.config.ts]
import { defineConfig } from 'bunup';
export default defineConfig({
exports: {
excludeCss: true
},
});
```
:::
## Include Package JSON
By default, exports generation automatically adds `"./package.json": "./package.json"` to your package's exports field. This export is useful for:
* **Package introspection**: Allowing consumers to access your package's metadata programmatically
* **Tooling compatibility**: Many development tools and package managers expect to be able to import package.json
* **Runtime information**: Enabling your package to access its own version and metadata at runtime
The `includePackageJson` option allows you to control this behavior:
::: code-group
```sh [CLI]
bunup --no-exports.include-package-json
```
```ts [bunup.config.ts]
import { defineConfig } from 'bunup';
export default defineConfig({
exports: {
includePackageJson: false // Disable package.json export
},
});
```
:::
When enabled (default), your exports field will include:
```json [package.json]
{
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./package.json": "./package.json" // [!code ++]
}
}
```
## All
The `all` option controls how open your package exports are. This affects what files consumers can import from your package.
When `all: true`, a wildcard subpath export is added that allows importing any file from your package:
::: code-group
```sh [CLI]
bunup --exports.all
```
```ts [bunup.config.ts]
import { defineConfig } from 'bunup';
export default defineConfig({
exports: {
all: true
},
});
```
:::
This generates:
```json [package.json]
{
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./*": "./*" // [!code ++]
}
}
```
With `all: true`, consumers can import any file that ends up in your published package.
::: warning
When using `all: true`, any file that ends up in your published tarball becomes importable. Control what you publish using the `files` field in package.json or `.npmignore` to avoid exposing internal files.
:::
## Export Keys and Output Structure
Bunup generates export keys based on the output file paths. In some cases, such as when using glob patterns like `src/**/*.ts`, the output structure may include the `src/` directory, which affects the generated export keys.
In certain configurations, your output files may be nested under a `src/` directory:
::: code-group
```sh [CLI]
bunup 'src/**/*.ts'
```
```ts [bunup.config.ts]
export default defineConfig({
entry: ['src/**/*.ts'],
});
```
:::
Output structure:
```
dist/
βββ src/
βββ components/
β βββ Button.js
βββ utils/
βββ format.js
```
When this happens, the generated export keys will include the `./src/` prefix:
```json
{
"exports": {
"./src/components/Button": "./dist/src/components/Button.js",
"./src/utils/format": "./dist/src/utils/format.js"
}
}
```
If you don't want `./src/` in your export keys, you can set `sourceBase` to `'./src'`. This tells Bunup to use `src/` as the base directory, which removes `src/` from the output structure:
::: code-group
```sh [CLI]
bunup 'src/**/*.ts' --source-base ./src
```
```ts [bunup.config.ts]
export default defineConfig({
entry: ['src/**/*.ts'],
sourceBase: './src',
});
```
:::
Output structure:
```
dist/
βββ components/
β βββ Button.js
βββ utils/
βββ format.js
```
As a result, the generated export keys no longer include the `./src/` prefix:
```json
{
"exports": {
"./components/Button": "./dist/components/Button.js",
"./utils/format": "./dist/utils/format.js"
}
}
```
### Key Takeaway
Bunup generates export keys based on the output file paths relative to your output directory. The `sourceBase` option controls the output structure, which directly affects the generated export keys. This is not specific to `./src`, you can use `sourceBase` with any directory structure to control how paths appear in your export keys.
For more details on how `sourceBase` works, see the [Source Base Directory](/docs/guide/options#source-base-directory) option.
---
---
url: /docs/extra-options/inject-styles.md
---
# Inject Styles
Inject styles automatically includes your CSS styles in your JavaScript bundle, so users don't need to manually import CSS files. Instead of creating separate `.css` files, your styles become part of your JavaScript code.
## How it works
Instead of outputting CSS files in the build output, inject styles converts your CSS into JavaScript that creates `