You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Terminology correction (2026-06-24): this issue says "--no-install" in places, but that is the WRONG term. webjs's zero-install is default bun run dev with auto-install ON (no flag). The --no-install FLAG is the opposite (it DISABLES auto-install, for CI/prod strictness) and webjs does not use it. Read every "--no-install" below as "default auto-install / bun run dev zero-install". The research question is whether DEFAULT auto-install honors package.json ranges + the lockfile on a current (1.3.14) Bun.
Question
Make Bun zero-install (default bun run dev auto-install, no node_modules) resolve dependencies EXACTLY as npm install / bun install + node_modules would, for the FULL package.json: caret/tilde/x ranges, dist-tags, prerelease, peer + optional deps, npm: aliases, and the whole transitive tree, not just exact direct pins.
A zero-install Bun app (no node_modules) runs the SAME version set that npm install / bun install + node_modules would, across the whole tree, verified differentially.
Avenues to investigate
bun install --lockfile-only (most promising): can Bun produce/refresh a bun.lock by RESOLUTION ONLY, with no node_modules? If yes, run it at scaffold/first-run (cheap), then feat: pin Bun zero-install deps via an onLoad specifier-rewrite from package.json #685's exact-pin reads the lock and pins every declared dep. The lock IS npm-equivalent resolution output, so this closes the range gap with zero node_modules.
Transitive correctness: when auto-install fetches an exact dep (zod@3.22.4), does it resolve zod's OWN deps deterministically (per the lock / zod's manifest) or fetch them at latest? feat: pin Bun zero-install deps via an onLoad specifier-rewrite from package.json #685 only pins the app's DIRECT imports (the onLoad skips node_modules/cache dep files). Verify whether a bun.lock under zero-install pins the FULL tree.
Boot-time resolve-once-and-cache: on first run with no lock, do a one-time resolution (lockfile-only or a registry query) writing a bun.lock / internal manifest, then pin from it. Trigger in the webjs-bun.mjs bootstrap or a webjs CLI step.
Custom resolver (heavy fallback): re-implement semver max-satisfying + registry version queries to resolve ranges ourselves. Re-implements a package-manager solver; last resort.
Edge cases the solution must cover
caret/tilde/x/*/||/hyphen ranges, dist-tags (latest/next), prerelease versions, peer + optional deps, dedup, npm: aliases, git/file/workspace specifiers (bare today), and the full transitive tree.
Acceptance
A no-node_modules Bun app resolves to the identical version tree a node_modules install would (differential test). Then --no-install-by-default (scaffold + #682) becomes safe.
Cross-references
#684 (prior research, concluded exact-only via the onLoad rewrite), #685 (shipped exact-only pin), #682 (closed; the --no-install default this unblocks), #675 (zero-install bootstrap), #687.
Forward-looking research task; the first investigation pass (the bun install --lockfile-only avenue) is being recorded as comments below.
Question
Make Bun zero-install (default
bun run devauto-install, nonode_modules) resolve dependencies EXACTLY asnpm install/bun install+node_moduleswould, for the FULLpackage.json: caret/tilde/x ranges, dist-tags, prerelease, peer + optional deps,npm:aliases, and the whole transitive tree, not just exact direct pins.Background (verified in #684 + shipped in #685)
import 'zod@3.22.4') but ENOENTs on a RANGE or dist-tag (import 'zod@^3'/'zod@latest').onResolveplugins are bypassed for auto-install;onLoadspecifier-rewriting works (that is feat: pin Bun zero-install deps via an onLoad specifier-rewrite from package.json #685).bun.lockexact, else an exactpackage.jsonpin). A caret/tilde RANGE WITHOUT abun.lockis left BARE and resolves to LATEST. That is the gap.--no-install: a range-based app with nobun.lockruns unpinned-latest.Goal
A zero-install Bun app (no
node_modules) runs the SAME version set thatnpm install/bun install+node_moduleswould, across the whole tree, verified differentially.Avenues to investigate
bun install --lockfile-only(most promising): can Bun produce/refresh abun.lockby RESOLUTION ONLY, with nonode_modules? If yes, run it at scaffold/first-run (cheap), then feat: pin Bun zero-install deps via an onLoad specifier-rewrite from package.json #685's exact-pin reads the lock and pins every declared dep. The lock IS npm-equivalent resolution output, so this closes the range gap with zeronode_modules.zod@3.22.4), does it resolve zod's OWN deps deterministically (per the lock / zod's manifest) or fetch them at latest? feat: pin Bun zero-install deps via an onLoad specifier-rewrite from package.json #685 only pins the app's DIRECT imports (the onLoad skipsnode_modules/cache dep files). Verify whether abun.lockunder zero-install pins the FULL tree.bun.lock+ the feat: pin Bun zero-install deps via an onLoad specifier-rewrite from package.json #685 rewrite end-to-end: does a presentbun.lock+ the exact-pin rewrite ALREADY achieve full npm-equivalence today? Test differentially against anode_modulesinstall of the samepackage.json.bun.lock/ internal manifest, then pin from it. Trigger in thewebjs-bun.mjsbootstrap or awebjsCLI step.Edge cases the solution must cover
caret/tilde/x/
*/||/hyphen ranges, dist-tags (latest/next), prerelease versions, peer + optional deps, dedup,npm:aliases, git/file/workspace specifiers (bare today), and the full transitive tree.Acceptance
A no-
node_modulesBun app resolves to the identical version tree anode_modulesinstall would (differential test). Then--no-install-by-default (scaffold + #682) becomes safe.Cross-references
#684 (prior research, concluded exact-only via the onLoad rewrite), #685 (shipped exact-only pin), #682 (closed; the
--no-installdefault this unblocks), #675 (zero-install bootstrap), #687.Forward-looking research task; the first investigation pass (the
bun install --lockfile-onlyavenue) is being recorded as comments below.