Skip to content

Releases: saintparish4/opal

v0.3.1

Choose a tag to compare

@github-actions github-actions released this 27 Sep 02:10

Full Changelog: v0.3.0...v0.3.1

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 19 Sep 16:21

Full Changelog: v0.2.1...v0.3.0

v0.2.1

Choose a tag to compare

@github-actions github-actions released this 29 Aug 20:23

A performance fix for one finding: a 367-package Next.js install spent most of its time parsing package metadata it never used, and almost none of it on the network.

Every package on the registry publishes a record of every version it has ever released. Opal was building the full dependency detail for all of them before selecting one. On that project it parsed 130,246 published versions to choose 367, then held the rest in memory and freed it again.

Version bodies are now kept as raw slices and parsed on demand.

Measured

On a 367-package Next.js tree with a warm store and warm metadata:

before after
whole install, offline 128.6s 37.7s
the resolve phase alone 74.3s 8.4s
whole install, with network 188.9s 60.0s
--prefer-offline — 26.0s
lockfile and tree already present — 5.9s

Also in this release

  • Per-phase timings. 365 packages resolved in 587.1s described the whole install, not resolution. It now reads (resolve 43.2s, fetch 0.5s, link 13.5s), because those three phases are slow for unrelated reasons and one total hides which to fix.
  • Fewer syscalls when linking. A 21,000 file tree made 21,000 create_dir_all calls where a few hundred would do. Invisible on ext4, and not on a DrvFS mount under WSL2.
  • The hardlink warning now names the remedy. If your project and cache sit on different filesystems, every file is copied instead of linked, which can be most of an install's time. Set OPAL_CACHE_DIR to the same filesystem, or move the project off /mnt/c if you are on WSL2.

Note

A version a registry lists but cannot be installed from — no tarball, or no usable integrity — is now skipped in favour of the next best match, rather than being filtered out when the packument was first read.

No lockfile format change. v0.2.0 lockfiles are read as-is.

Full Changelog: v0.2.0...v0.2.1

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 29 Aug 18:28

Correctness, speed, and visibility across the package manager. Four bugs in this release produced a wrong node_modules without ever failing an install.

Breaking

opal.lock is now v3. A v0.1.0 binary refuses a v3 lockfile rather than misreading it, so upgrade before sharing a lockfile with one. Going the other way, v0.2.0 replaces a v1 or v2 lockfile by re-resolving — except under --frozen-lockfile, where it is an error, because a build that promised not to rewrite the lockfile must not rewrite it to upgrade it either.

A required dependency this platform cannot run is now EBADPLATFORM, matching npm. Previously it installed and produced a tree that could not run. A package declared in optionalDependencies is still skipped, which is how jest, vite and anything else depending on fsevents keeps working.

The graph cache misses once after upgrading: the resolver learned to walk files it used to skip, so records written by v0.1.0 no longer describe what it would produce.

Fixed — installs that were silently wrong

  • A root dependency could be linked at the wrong version. With shared@^1 declared alongside a dependency on shared@^2, the tree got 2.x at the top level and the version you asked for was downloaded and never placed.
  • --production overwrote opal.lock, and --production --frozen-lockfile — the ordinary CI invocation — failed against a perfectly valid lockfile every time.
  • Platform variants of native optionals all installed. esbuild declares 25, totalling 256 MB; one 9.8 MB binary is what belongs on a host. They stay recorded in opal.lock, so one committed file still installs the right binary on every platform.
  • A dependency could write lines into your lockfile. Range::parse(">=1\npkg …") kept the newline and the lockfile is one fact per line, so a dependency's own package.json could append entries — including package entries with attacker-controlled tarball URLs — to the lockfile of every project installing it. Found by fuzzing.

Faster

  • Registry metadata is cached across runs. Re-resolving a 74-package tree against a warm store went from 7.6s to 0.36s, making no round trips at all. --offline and --prefer-offline are new.
  • Packuments are fetched in npm's abbreviated form, roughly half the bytes.
  • The CAS hashes before writing, so content it already holds costs a hash and a stat instead of a write, an fsync, a read-back and a rename.

New

  • npm: alias specifiers. "string-width-cjs": "npm:string-width@^4.2.0" installs one package under another's name — how a package depends on two majors of one dependency at once. Unblocks glob@10, rimraf@5, node-gyp@10 and sucrase, which could not be installed at all.
  • Progress output. A spinner while resolving and linking, a bar advancing per package while fetching, and one warning per deprecated package. Plain lines when stderr is not a terminal, so CI logs stay readable.
  • opal cache gc prunes what it can no longer use — graph records for deleted projects, and registry metadata past 30 days.
  • Bounded retries and explicit timeouts on registry requests; ceilings on what a tarball may unpack to.

Install

curl -fsSL https://raw.githubusercontent.com/saintparish4/opal/master/install.sh | bash

macOS and Linux, x64 and arm64. WSL2 is covered by the Linux builds. Native Windows remains a v2 target.

Full Changelog: v0.1.0...v0.2.0

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 18:24