---
title: Advanced
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

## Creating binary files

A binary is an executable file distributed in an npm package via the
[bin](https://docs.npmjs.com/files/package.json#bin) field. Packemon offers first class support for
binary files by:

- Prepending a `#!/usr/bin/env node` shebang to the output file. Do not include this in the source
  file!
- Updating the `bin` field in `package.json` to the output file (if not already defined).

To make use of this functionality, you must define an [input](./config.md#inputs) with the name
`bin`, or store your bins in a `bin` directory.

```json title="package.json"
{
  "name": "package",
  "packemon": {
    "inputs": {
      "bin": "src/bin.ts"
    },
    "platform": "node"
  }
}
```

The contents of the binary source file can be whatever you want, but do be aware that code in the
module scope will be executed immediately when the file is executed by Node.js.

## Customizing Babel, swc, and Rollup

> This is an advanced escape hatch and should be avoided unless absolutely necessary, for example,
> processing CSS files in a way that Packemon does not support.

Customizing the Babel, swc, and Rollup configs are an _opt-in feature_, and require the following
conditions to be met:

- A `--loadConfigs` option is passed on the command line. This enables searching and loading of
  config files, otherwise, we want to avoid the filesystem lookups.
- A `packemon.config.{ts,js}` file at the monorepo/polyrepo root, which applies customizations to
  all packages. Or _optional_ `.packemon.{ts,js}` files within each package, which applies
  customizations to that package individually. An example of this is found below, or view the
  [@boost/config](https://boostlib.dev/docs/config) docs.

<Tabs
  groupId="package-structure"
  defaultValue="poly"
  values={[
    { label: 'Polyrepo', value: 'poly' },
    { label: 'Monorepo', value: 'mono' },
  ]}
>
  <TabItem value="poly">

```
/
├── src/
├── package.json
├── packemon.config.js
├── LICENSE
└── README.md
```

  </TabItem>
  <TabItem value="mono">

```
/
├── packages/
│   ├── foo/
│   |   ├── src/
│   |   ├── .packemon.js
│   |   ├── package.json
│   |   ├── LICENSE
│   |   └── README.md
│   ├── bar/
│   |   ├── src/
│   |   ├── .packemon.js
│   |   ├── package.json
│   |   ├── LICENSE
│   |   └── README.md
│   └── baz/
│       ├── src/
│       ├── .packemon.js
│       ├── package.json
│       ├── LICENSE
│       └── README.md
├── lerna.json
├── package.json
├── packemon.config.js
├── LICENSE
└── README.md
```

  </TabItem>
</Tabs>

Both of these config files have the same structure, and may define the fields below. All of these
fields require a function (except `swc`), which is passed the finalized config as an argument (with
output fields also accepting the current build as the 2nd argument). This config can then be mutated
in place.

- `babelInput` - For parsing syntax into an AST (TypeScript, JSX, etc).
- `babelOutput` - For applying transformations.
- `rollupInput` - For defining inputs, outputs, and more.
- `rollupOutput` - For customizing each output.
- `swc` - Enables swc instead of Babel.
- `swcInput` - For parsing syntax into an AST (TypeScript, JSX, etc).
- `swcOutput` - For applying transformations.

<Tabs
  groupId="configs"
  defaultValue="ts"
  values={[
    { label: 'TypeScript', value: 'ts' },
    { label: 'JavaScript', value: 'js' },
  ]}
>
  <TabItem value="ts">

```ts
import type { ConfigFile } from 'packemon';
import linaria from '@linaria/rollup';

const config: ConfigFile = {
  babelOutput(config, build) {
    config.presets.push('@linaria/babel-preset');
  },
  rollupInput(config) {
    config.plugins.unshift(linaria());
  },
};

export default config;
```

  </TabItem>
  <TabItem value="js">

```js
const linaria = require('@linaria/rollup');

module.exports = {
  babelOutput(config) {
    config.presets.push('@linaria/babel-preset');
  },
  rollupInput(config) {
    config.plugins.unshift(linaria());
  },
};
```

  </TabItem>
</Tabs>

> We suggest _not mutating_ the config that Packemon generates, as it may break our assumptions.
> Instead, prefer to only apply additions that add new functionality.

## Stamping releases

For situations where you update Packemon and want to release _every_ package, even those that have
not been modified since the last release, you can use stamping. Stamping is a very simple concept
where we modify the `package.json` of each package with a `release` timestamp, and can be achieved
by passing `--stamp` to the `build` or `pack` commands.
