Today’s scrap has a very long title and is about pnpm workspaces that contain a compiled executable in a TypeScript monorepo.
pnpm install in a monorepo, the local
bin file of a workspace
may not exist yet. This happens when that file needs to be generated first (e.g.
when using TypeScript). Then
pnpm is unable to link the missing file. This
also results in errors when trying to execute the
bin from another workspace.
tl/dr; Make sure the referenced file in the
bin field of
exists, and import the generated file from there.
So how to safely use a compiled bin? Let’s assume this situation:
- The entry script for the CLI tool is at
- This source file is compiled to
- Compiled by the
buildscript that runs
Here are some relevant bits in the
package.json file of the workspace that
wants to expose the
"type": "module" to publish as ESM in
package.json. Import the generated
Publishing as CommonJS? Then use
Make sure to include the shebang (that first line starting with
consumers of your package will see errors like this:
bin/my-command: line 1: syntax error near unexpected token `'../lib/index.js''
In case the package is supposed to be published, use the
and make sure to include both the
lib folders in the
(like in the example above).
A note about
postinstall script to create the file works since pnpm v8.6.6,
postinstall scripts should be avoided when possible:
- Can perform malicious acts (security scanners don’t like them)
- Can be disabled by the consumer using
- Can be disabled if the consumer uses
Bun does not execute arbitrary lifecycle scripts for installed dependencies.
That’s why this little guide doesn’t promote it, and this scrap got longer than I wanted!
- This scrap is based on this GitHub comment in the pnpm repository.
- I’ve seen and tried workarounds to (
touchthe file from
postinstallscripts, but that’s flaky at best and not portable.
- The same issue might occur when using npm, Bun and/or Yarn. True or not, it’s better to be safe than sorry.
you can target the
src/cli.jsfile directly from the