deno
0b928302 - feat: add `deno pack` command to create npm tarballs (#32139)

Commit
76 days ago
feat: add `deno pack` command to create npm tarballs (#32139) Add `deno pack` command that creates npm-compatible tarballs from Deno/JSR projects. It transpiles TypeScript to JavaScript, rewrites `jsr:`/`npm:` specifiers to bare npm names, generates `package.json` with conditional exports and `.d.ts` type entries, and bundles everything into a `.tgz` ready for `npm publish`. Types are extracted via fast-check (same as `deno publish`). When Deno API usage is detected, `@deno/shim-deno` is automatically added as a dependency. ## Usage examples ```sh # Basic: pack the current project deno pack # Override version without editing deno.json deno pack --set-version 2.0.0 # Write tarball to a specific path deno pack --output my-package.tgz # Preview contents without creating the tarball deno pack --dry-run # Skip .d.ts generation (allow slow types) deno pack --allow-slow-types # Don't inject @deno/shim-deno polyfill deno pack --no-deno-shim # Pack with uncommitted changes deno pack --allow-dirty # Exclude test files deno pack --ignore=tests/ # Publish the tarball to npm npm publish scope-package-1.0.0.tgz ``` ## What it does Given a `deno.json` like: ```jsonc { "name": "@scope/my-lib", "version": "1.0.0", "exports": "./mod.ts" } ``` Running `deno pack` produces `scope-my-lib-1.0.0.tgz` containing: - `package.json` with `name`, `version`, `type: "module"`, conditional `exports` (types/import/default), and extracted `dependencies` - Transpiled `.js` files (with inline source maps by default) - Generated `.d.ts` declaration files (via fast-check) - README and LICENSE files (auto-included if present) Specifier rewrites: - `jsr:@std/path` -> `@jsr/std__path` - `npm:express@4` -> `express` - `./utils.ts` -> `./utils.js` - `node:fs` -> unchanged ## How `deno pack` differs from `npm pack` `deno pack` is not an `npm pack` equivalent -- it is a build tool that converts a Deno/JSR project into an npm-publishable package, closer to `tsc` + `npm pack` combined. Notable behavioral differences: - **File selection is graph-based**: only files reachable from `exports` end up in the tarball, not a file listing. Non-JS assets (data files, WASM) are not included unless imported. - **No `.npmignore`/`.gitignore` support**: uses `--ignore` flag and hard-coded exclusions (`.git`, `node_modules`, `.env*`). - **No lifecycle scripts**: `prepublishOnly`/`prepare` hooks are not executed. - **No `bundledDependencies`/`optionalDependencies`**: the generated `package.json` only contains `dependencies`. - **JSR deps use `@jsr/` scope**: e.g. `jsr:@std/path` becomes `@jsr/std__path`, which requires consumers to have the JSR npm registry configured or use `npx jsr add`. ## Implementation details - New modules under `cli/tools/pack/`: `mod.rs`, `extensions.rs`, `unfurl.rs`, `package_json.rs`, `npm_tarball.rs` - Shared unfurl utilities extracted to `cli/tools/unfurl_utils.rs` (reused by `deno publish`) - `check_if_git_repo_dirty` moved to `cli/util/git.rs` (shared between pack and publish) - Reproducible tarballs: `BTreeMap` for deterministic key ordering, sorted tar entries, fixed tar headers (mode/mtime/uid/gid) - Security: symlink checks on auto-included files, `.env`/`.git` exclusion, path traversal protection on tarball filenames The changeset is large but most of it is test coverage in `tests/specs/pack/`. --------- Co-authored-by: Bartek IwaƄczuk <biwanczuk@gmail.com> Co-authored-by: Leo Kettmeir <crowlkats@toaxl.com> Co-authored-by: crowlbot <280062030+crowlbot@users.noreply.github.com>
Parents
Loading