Skip to content

v1.38.0: Shared workspace hoisting, embedder storage overrides, and safer store pruning

Choose a tag to compare

@jdx jdx released this 07 Aug 17:42
· 41 commits to main since this release
Immutable release. Only release title and notes can be modified.
3d5fc64

This release lets embedding hosts fully own installed-package storage, adds a --dry-run preview to store prune, and enriches SBOM output with real license metadata — alongside a batch of fixes for hoisted workspaces, global-virtual-store unlinking, deploy patches, and nested shim resolution.

Added

  • Per-install storage overrides for embedders (#1239 by @jdx) — New source-compatible install_with_overrides / add_with_overrides APIs (via EmbedderInstallOverrides) let a host pin cacheDir, storeDir, and enableGlobalVirtualStore for a single invocation without mutating process env or global state. Overrides take command-line precedence and flow through install, add, frozen-lockfile verification, trust-policy metadata, and warm-path GVS detection, so hosts like mise can isolate embedded npm installs and remove their storage cleanly. Host-owned cache indices now round-trip non-UTF-8 store paths.

  • aube store prune --dry-run (#1228 by @jdx) — Preview exactly what a prune would remove before anything is unlinked. The dry run performs the identical walk and skip decisions (index-referenced files, nlink > 1, exec-marker companions) but never deletes:

    $ aube store prune --dry-run
    Would prune 412 files (up to 18.7 MB) from the store
    

    Closes #1218.

  • Package license metadata in SBOM output (#1208 by @jdx) — aube sbom now reuses aube licenses' installed-package discovery to emit root and dependency licenses in CycloneDX 1.5 (as SPDX identifiers, expressions, or named licenses) and to populate SPDX 2.3 licenseDeclared for valid expressions. Works across isolated, hoisted, linked, and custom virtual-store layouts, with a fingerprinted sidecar and live-manifest fallbacks for older installs. Closes #1204.

Fixed

  • Share hoisted deps across workspace importers (#1243 by @jdx) — The hoisted linker now plans all workspace importers as one tree rooted at the workspace node_modules, so with hoistingLimits=none compatible dependencies hoist to a single physical package at the workspace root, while hoistingLimits=workspaces correctly keeps deps within workspace boundaries (previously it behaved like none). Installs record the exact placement map in hoisted-placements.json so rebuild and licenses reflect the real layout. Fixes #1242.
  • Keep GVS-backed deps out of bare aube unlink (#1230 by @jdx) — With the global virtual store on (the default outside CI), bare aube unlink deleted every ordinary dependency symlink from node_modules/ and reported each as "Unlinked". The internal/external classification is now lex-normalized first (mirroring unlink_bins) so .aube/... targets stay internal without following GVS symlinks into the shared store.
  • Unlink global bins under the shared virtual store (#1232 by @jdx) — aube remove -g <pkg> left the package's bin behind as a dangling symlink in the global bin dir when GVS was enabled. Bin ownership is now checked against the lexically normalized target link_bins actually wrote, with canonicalization retained as a fallback. Reported in #1219.
  • Fail closed on incomplete store index scans (#1237 by @jdx) — A malformed or unreadable cached package index could previously make store prune build an incomplete "referenced" hash set and delete live CAS files. Prune, --dry-run, and store status now abort with the new ERR_AUBE_STORE_INDEX_SCAN_FAILED (with path-specific diagnostics) instead of silently skipping. Discussion #1234.
  • Canonicalize isolated dependency build paths on Windows (#1238 by @jdx) — On Windows with GVS + isolated linking, native build tools such as node-gyp could resolve dependency files (e.g. node-addon-api/node_api.gyp) as missing because lifecycle scripts ran in the logical .aube/<dep> cwd while paths pointed at the hashed store. Lifecycle working directories are now canonicalized to the physical package path for install and rebuild. Addresses #1235.
  • Route deprecation warnings through embedder output (#1236 by @jdx) — Install-time deprecation warnings now flow through InstallControl as structured events (WARN_AUBE_DEPRECATED_PACKAGE / WARN_AUBE_DEPRECATED_PACKAGE_SUMMARY) instead of writing directly to stderr, so embedded hosts no longer race their own progress renderer (fixing corrupted terminal rows in mise on Windows). The aube deprecations hint now only shows for standalone aube, not an invalid host-branded command.
  • Preserve workspace dependency patches through deploy (#1213 by @jdx) — aube deploy previously dropped workspace-root patchedDependencies, so dependencies were silently materialized without their patches. Deploy now filters patches to each importer's lockfile closure, stages them into a content-addressed metadata directory, and writes matching manifest entries so the target install applies and retains them. Fixes #1212.
  • Preserve workspace bins through nested shims (#1207 by @jdx) — Recursive aube exec now falls back to the workspace-root node_modules/.bin (matching pnpm's extraBinPaths), and activated pnpm/npm/yarn shims stay reachable after aube node resolves the real Node binary, so Node tools like Rspack can spawn their package manager.

Changed

  • Correct the --global link registry docs (#1205 by @jdalton) — The -g/--global help for aube link / aube unlink now correctly documents the global link registry location as the XDG cache directory ($XDG_CACHE_HOME/aube/global-links, $HOME/.cache/aube/global-links, or %LOCALAPPDATA%\aube\global-links) rather than $AUBE_HOME/global-links.

New Contributors

Full Changelog: v1.37.0...v1.38.0

💚 Sponsor aube

aube is maintained by @jdx, an open source developer for entire.io, the title sponsor of the jdx.dev open source tools including mise. Work on aube is funded by sponsors.

If aube is saving your team install time or CI minutes, please consider sponsoring at jdx.dev. Individual and company sponsorships are what keep the project fast, free, and independent.