Skip to content

Move bun.lock under reflex.lock/bun.lock#6475

Open
masenf wants to merge 12 commits intomainfrom
masenf/reflex-lock
Open

Move bun.lock under reflex.lock/bun.lock#6475
masenf wants to merge 12 commits intomainfrom
masenf/reflex-lock

Conversation

@masenf
Copy link
Copy Markdown
Collaborator

@masenf masenf commented May 8, 2026

This will avoid conflicts with reflex apps that also host some javascript app in the same directory.

Followup for #6289

This will avoid conflicts with reflex apps that also host some javascript app
in the same directory.
@masenf masenf requested review from a team and Alek99 as code owners May 8, 2026 14:04
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Greptile Summary

This PR moves the canonical bun.lock from the project root to reflex.lock/bun.lock to avoid conflicts with user-managed JS projects co-located in the same directory. It also generalises the mechanism to cover npm's package-lock.json and persists package.json under reflex.lock/ so resolved dependency pins survive a fresh reflex init.

  • New reflex.lock/ directory: Bun.ROOT_LOCKFILE_DIR = \"reflex.lock\" constant introduced; all lockfile sync helpers updated to read/write from this directory instead of the project root.
  • Pinned vs unpinned install split: _install_frontend_packages partitions packages into pinned and unpinned sets, running them through separate bun add calls, and removes stale deps before the frozen-lockfile initial install.
  • Implicit npm detection: prefer_npm_over_bun gains a third precedence level based on which lockfile is present in reflex.lock/.

Confidence Score: 4/5

Safe to merge for bun users; npm users who specify unpinned frontend_packages will hit a broken install.

The --only-missing flag is bun-specific and is passed unconditionally to whichever package manager is active. Any user running under npm (Windows+OneDrive, REFLEX_USE_NPM=1, or the new implicit npm detection) who has unversioned entries in frontend_packages or plugin dev-deps will see npm add --only-missing fail with an unknown-option error, blocking the entire frontend install. The rest of the refactoring is well-structured.

reflex/utils/js_runtimes.py — the unpinned package install paths pass --only-missing without checking whether the active package manager is bun.

Important Files Changed

Filename Overview
reflex/utils/js_runtimes.py Major refactor of frontend install logic: adds pinned/unpinned package splitting, frozen-lockfile initial install, and stale-dep removal. Introduces --only-missing flag that is bun-specific but passed unconditionally, breaking npm users with unpinned packages.
reflex/utils/frontend_skeleton.py Moves bun.lock canonical path from project root to reflex.lock/bun.lock, generalises to cover npm lockfiles and package.json, and adds _copy_if_exists helper. No migration path for the old root bun.lock (flagged in previous review).
packages/reflex-base/src/reflex_base/constants/installer.py Adds ROOT_LOCKFILE_DIR = "reflex.lock" constant to Bun and LOCKFILE_PATH = "package-lock.json" to Node. Clean, no issues.
reflex/utils/exec.py Adds reflex.lock directory to the reload-path exclusion list, preventing file-watcher churn when lockfiles are updated.
tests/units/test_prerequisites.py Extensive new tests for the revised install flow, package pinning, stale-dep removal, npm-lock persistence, and prefer_npm_over_bun implicit detection. Good coverage.
docs/getting_started/project-structure.md Documentation updated to reflect the new reflex.lock/ directory for bun.lock. Accurate and clear.

Reviews (2): Last reviewed commit: "remove bad test assertion" | Re-trigger Greptile

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 8, 2026

Merging this PR will not alter performance

✅ 24 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing masenf/reflex-lock (891630f) with main (941f9bb)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

adhami3310
adhami3310 previously approved these changes May 8, 2026
@masenf
Copy link
Copy Markdown
Collaborator Author

masenf commented May 8, 2026

LOL hot reload is broken now, because reflex.lock is not excluded from the reload path 🤦

masenf added 9 commits May 8, 2026 11:37
Avoid reload loop when a code change results in a lock file change.
This allows restoration of the previous package.json for the app.

Explicitly pinned packages will be updated with `bun add` so they will
overwrite what might have been in the lock file / package.json previously. This
is important for updating framework dependencies across reflex versions which
are strictly pinned.

Unpinned packages are added with `bun add --only-missing` so they will NOT
override previously saved version pins.
now that packages.json isn't being rewritten on each init, it is important to
explicitly look for referenced top-level packages that are no longer used in
the current app and remove them.
Avoid extra invocations of the package manager.
Also sync package-lock.json to reflex.lock directory.
The first `install` command only does something if there is an existing
package.json / lockfile; in the absense of the lock file, there is nothing to
install, so skip it.
To better respect checked-in lock files, do not automatically try using a
different package manager which may NOT have a lock file, resulting in
unexpected packages being downloaded.
@masenf
Copy link
Copy Markdown
Collaborator Author

masenf commented May 8, 2026

@greptile-apps re-review

Comment thread reflex/utils/js_runtimes.py Outdated
Comment on lines +683 to +715
if unpinned_packages:
run_package_manager(
[
primary_package_manager,
"add",
"--legacy-peer-deps",
"--only-missing",
*unpinned_packages,
],
show_status_message="Installing frontend packages",
)
if all_pinned_dev:
run_package_manager(
[
primary_package_manager,
"add",
"--legacy-peer-deps",
"-d",
*development_deps,
*all_pinned_dev,
],
show_status_message="Installing frontend development dependencies",
show_status_message="Pinning frontend development dependencies",
)

# Install custom packages defined in frontend_packages
if packages:
if unpinned_dev_deps:
run_package_manager(
[primary_package_manager, "add", "--legacy-peer-deps", *packages],
show_status_message="Installing frontend packages from config and components",
[
primary_package_manager,
"add",
"--legacy-peer-deps",
"--only-missing",
"-d",
*unpinned_dev_deps,
],
show_status_message="Installing frontend development dependencies",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 --only-missing is bun-specific but used unconditionally

--only-missing is a bun flag; npm does not recognize it. When primary_package_manager is npm (Windows+OneDrive path, REFLEX_USE_NPM=1, or the new implicit npm detection when only package-lock.json is present) and any unpinned packages or dev-deps are requested, both npm add --legacy-peer-deps --only-missing <pkgs> and the dev-deps variant will fail with an "unknown option" error, breaking the entire install. This is a regression relative to the old code which never passed --only-missing. The fix is to check the package manager before adding this flag.

Avoid adding unpinned packages that are already accounted for, to avoid
resetting the version specified in the lock file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants