Write package.json in bun's layout
Type of change
- Bug fix (non-breaking change which fixes an issue)
Description
Found in the reflex 0.11.0a1 pre-release testing (FINDING-029).
Reflex wrote .web/package.json as compact one-line JSON, and reflex.lock/package.json is a byte copy of that file. Whenever bun add changes the file, bun rewrites it 2-space indented. The persisted file therefore flipped between the two layouts and produced VCS diffs with no content change.
Every package.json writer now produces bun's layout:
reflex_base.compiler.templates.package_json_template, whichinitialize_package_jsonandsync_root_package_json_to_webusefrontend_skeleton.update_package_json_overrides
The layout is json.dumps(..., indent=2, ensure_ascii=False) + "\n", written as UTF-8 with newline="\n", so Windows writes LF like bun does. bun writes non-ASCII characters as raw UTF-8 rather than \uXXXX escapes. For that reason every package.json reader now uses encoding="utf-8": _read_package_json_object, js_runtimes._existing_web_package_sections and exec.get_package_json_and_hash. A file that is not valid UTF-8 is treated as unusable, the same as invalid JSON. The persisted copy is made with path_ops.cp, so it gets the same layout.
Checked against bun 1.4.4, the version reflex pins:
bun addon a reflex-rendered file changes only the entries it adds. Its output equalsjson.dumps(json.loads(out), indent=2, ensure_ascii=False) + "\n".- bun keeps whatever trailing newline the file already has. An indented file goes through
bun addandbun removebyte-identical. - bun keeps arrays expanded when they start expanded, which is how reflex writes them.
Changes To Core Features:
- Have you added an explanation of what your changes do and why you'd like us to include them?
- Have you written new tests for your core changes, as applicable?
- Have you successfully ran tests with your changes locally?
Every test below fails on main and passes with this change. Most of them run under a new windows_text_io fixture in tests/units/conftest.py. When no encoding or newline is given, the fixture makes text-mode file access decode as ASCII and translate LF to CRLF on writes.
tests/units/utils/test_frontend_skeleton.py:test_rendered_package_json_matches_bun_formatandtest_update_package_json_overrides_matches_bun_format: layout, UTF-8, and no\rin the file.test_sync_root_package_json_repairs_unusable_file[\xff{}]: a non-UTF-8 file is repaired instead of raising.
tests/units/utils/test_exec.py::test_get_package_json_and_hash_reads_utf8tests/units/utils/test_js_runtimes.py::test_existing_web_package_sections_reads_utf8
test_frontend_skeleton.py, test_exec.py, test_js_runtimes.py, test_prerequisites.py and tests/units/compiler pass, and ruff, ruff format, pyright and pre-commit are clean on the changed files.
š¤ Generated with Claude Code