26 Commits

Author SHA1 Message Date
Eric
cf18ebeb79 chore(release): v0.0.2
Some checks failed
Copilot Setup Steps / copilot-setup-steps (push) Failing after 33s
2026-03-04 09:37:10 +01:00
Eric
9b2420c9b9 chore: update flake 2026-03-04 09:37:01 +01:00
Eric
55c23fa8b1 fix: all tests 2026-03-04 09:24:37 +01:00
Eric
f59549bebf test: refine new shape test assertions 2026-03-04 08:16:55 +00:00
Eric
4c87b3cb0f test: add missing implementation-plan test targets 2026-03-04 08:15:30 +00:00
Eric
2ac5412fb0 docs: define missing tests 2026-03-04 09:09:18 +01:00
Eric
2e4e211bef fix: harden phase 8 CI workflow and checks 2026-03-04 08:04:30 +00:00
Eric
d62b2e6e0c feat: add phase 8 ci matrix workflow 2026-03-04 08:01:05 +00:00
Eric
59d5a634d3 fix: tests 2026-03-04 08:57:26 +01:00
Eric
8f9f0a3653 chore: address phase 7 review feedback 2026-03-04 07:54:06 +00:00
Eric
dfc61b6cfc feat: add phase 7 bun_install module extension 2026-03-04 07:52:24 +00:00
Eric
a95c09e92c chore: update flake 2026-03-04 08:49:18 +01:00
Eric
ea244a8bb2 fix: tests 2026-03-04 08:44:11 +01:00
Eric
6cc7204cb3 feat: add phase 6 js_library and ts_library bootstrap 2026-03-04 07:31:19 +00:00
Eric
2837127866 feat: update nix flake 2026-03-04 08:26:46 +01:00
Eric
ef14de881b fix: use correct bazel 9.0.0 imports 2026-03-04 04:43:42 +01:00
Eric
dbc2ca0bc9 feat: implement phase 5 bun_bundle bootstrap 2026-03-04 03:30:07 +00:00
Eric
7a77e04039 fix: harden bun_test launcher args and test metadata 2026-03-04 03:22:58 +00:00
Eric
aa7766eff1 feat: add phase 4 bun_test bootstrap 2026-03-04 03:19:28 +00:00
Eric
198d1dcd18 test: simplify bun_binary test targets 2026-03-04 03:12:39 +00:00
Eric
06a8094212 feat: add phase 3 bun_binary bootstrap and tests 2026-03-04 03:10:35 +00:00
Eric
74622aba91 docs: add bun_install parameter docs 2026-03-04 03:05:49 +00:00
Eric
dfe658763b feat: add phase 2 bun_install repository rule bootstrap 2026-03-04 03:05:01 +00:00
Eric
dc0b26c5b5 docs: add plan to repo 2026-03-04 04:00:17 +01:00
Eric
cb5a578600 chore: centralize bun version and release URL constants 2026-03-04 02:56:27 +00:00
Eric
aa6f87bd86 feat: bootstrap bun toolchain skeleton and smoke test 2026-03-04 02:54:12 +00:00
212 changed files with 719 additions and 11363 deletions

View File

@@ -1 +0,0 @@
9.0.1

View File

@@ -1,6 +1,3 @@
package(default_visibility = ["//visibility:public"])
exports_files([
"ci.yml",
"pages.yml",
])
exports_files(["ci.yml"])

View File

@@ -5,10 +5,6 @@ on:
branches: ["main"]
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
permissions:
@@ -25,58 +21,11 @@ jobs:
phase8_target: windows
runs-on: ${{ matrix.os }}
env:
USE_BAZEL_VERSION: 9.0.1
USE_BAZEL_VERSION: 9.0.0
steps:
- uses: actions/checkout@v4
- uses: bazel-contrib/setup-bazel@0.18.0
with:
bazelisk-cache: true
repository-cache: true
external-cache: true
disk-cache: ci-${{ matrix.phase8_target }}
cache-save: ${{ github.event_name != 'pull_request' }}
- name: Install Nix
if: runner.os != 'Windows'
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
experimental-features = nix-command flakes
- name: Restore and save Nix store cache
if: runner.os != 'Windows'
uses: nix-community/cache-nix-action@v7
with:
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }}
restore-prefixes-first-match: nix-${{ runner.os }}-
- name: Install flake dependencies
if: runner.os != 'Windows'
run: nix develop --accept-flake-config -c true
- name: Set up Python
if: runner.os == 'Windows'
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Provide python3 shim
if: runner.os == 'Windows'
shell: bash
run: |
mkdir -p "$RUNNER_TEMP/bin"
cat >"$RUNNER_TEMP/bin/python3" <<'EOF'
#!/usr/bin/env bash
exec python "$@"
EOF
chmod +x "$RUNNER_TEMP/bin/python3"
echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
- uses: bazel-contrib/setup-bazel@0.15.0
- name: Run tests (${{ matrix.phase8_target }})
if: runner.os != 'Windows'
shell: bash
run: |
echo "Phase 8 target: ${{ matrix.phase8_target }}"
mapfile -t targets < <(./tests/ci_test/phase8_ci_targets.sh "${{ matrix.phase8_target }}")
nix develop --accept-flake-config -c bazel test --test_output=errors "${targets[@]}"
- name: Run tests (${{ matrix.phase8_target }})
if: runner.os == 'Windows'
shell: bash
run: |
echo "Phase 8 target: ${{ matrix.phase8_target }}"
mapfile -t targets < <(./tests/ci_test/phase8_ci_targets.sh "${{ matrix.phase8_target }}")
bazel test --test_output=errors "${targets[@]}"
bazel test //tests/...

View File

@@ -35,11 +35,5 @@ jobs:
extra_nix_config: |
experimental-features = nix-command flakes
- name: Restore and save Nix store cache
uses: nix-community/cache-nix-action@v7
with:
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }}
restore-prefixes-first-match: nix-${{ runner.os }}-
- name: Install flake dependencies
run: nix develop --accept-flake-config -c true

View File

@@ -1,61 +0,0 @@
name: Docs Pages
on:
push:
branches: ["main"]
paths:
- "docs/**"
- "bun/**/*.bzl"
- "internal/**/*.bzl"
- ".github/workflows/pages.yml"
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
deploy:
runs-on: ubuntu-latest
env:
USE_BAZEL_VERSION: 9.0.1
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v4
- uses: bazel-contrib/setup-bazel@0.18.0
with:
bazelisk-cache: true
repository-cache: true
external-cache: true
disk-cache: docs-pages
- name: Generate rule docs
run: |
bazel build //docs:rules_md
cp bazel-bin/docs/rules.md docs/rules.md
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Build with Jekyll
uses: actions/jekyll-build-pages@v1
with:
source: docs
destination: _site
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: _site
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

5
.gitignore vendored
View File

@@ -11,7 +11,6 @@
build/
dist/
node_modules/
*/node_modules/
# Directories for the Bazel IntelliJ plugin containing the generated
# IntelliJ project files and plugin configuration. Seperate directories are
@@ -21,7 +20,3 @@ node_modules/
/.clwb/
.env
!tests/.env
!tests/**/.env
!examples/.env
!examples/**/.env

View File

@@ -1,3 +0,0 @@
tests/binary_test/.env:environment-file:1
tests/script_test/.env:environment-file:1
tests/binary_test/env_parent/.env:environment-file:1

View File

@@ -1,9 +1 @@
package(default_visibility = ["//visibility:public"])
filegroup(
name = "repo_runtime_files",
srcs = [
"BUILD.bazel",
"MODULE.bazel",
],
)

View File

@@ -1,57 +1,21 @@
module(
name = "rules_bun",
version = "1.0.3",
version = "0.1.0",
)
# Core ruleset dependencies.
bazel_dep(name = "platforms", version = "1.0.0")
bazel_dep(name = "rules_shell", version = "0.6.1")
bazel_dep(name = "bazel_skylib", version = "1.8.2")
bazel_dep(name = "stardoc", version = "0.7.2")
bazel_dep(name = "rules_multirun", version = "0.9.0", dev_dependency = True)
# Repository-local setup for this ruleset's own tests and examples.
bun_ext = use_extension("//bun:extensions.bzl", "bun")
use_repo(
bun_ext,
"bun_darwin_aarch64",
"bun_darwin_x64",
"bun_linux_aarch64",
"bun_linux_x64",
"bun_linux_aarch64",
"bun_darwin_x64",
"bun_darwin_aarch64",
"bun_windows_x64",
)
# Test fixture dependency installation used by //tests/script_test.
bun_install_ext = use_extension("//bun:extensions.bzl", "bun_install", dev_dependency = True)
bun_install_ext.install(
name = "script_test_vite_node_modules",
bun_lockfile = "//tests/script_test:vite_app/bun.lock",
package_json = "//tests/script_test:vite_app/package.json",
)
use_repo(bun_install_ext, "script_test_vite_node_modules")
bun_install_ext.install(
name = "script_test_vite_monorepo_node_modules",
bun_lockfile = "//tests/script_test:vite_monorepo/bun.lock",
package_json = "//tests/script_test:vite_monorepo/package.json",
)
use_repo(bun_install_ext, "script_test_vite_monorepo_node_modules")
bun_install_ext.install(
name = "script_test_paraglide_monorepo_node_modules",
bun_lockfile = "//tests/script_test:paraglide_monorepo/bun.lock",
package_json = "//tests/script_test:paraglide_monorepo/package.json",
)
use_repo(bun_install_ext, "script_test_paraglide_monorepo_node_modules")
bun_install_ext.install(
name = "examples_vite_monorepo_node_modules",
bun_lockfile = "//examples/vite_monorepo:bun.lock",
package_json = "//examples/vite_monorepo:package.json",
)
use_repo(bun_install_ext, node_modules = "examples_vite_monorepo_node_modules")
# Register the published Bun toolchains for this repository.
register_toolchains(
"//bun:darwin_aarch64_toolchain",
"//bun:darwin_x64_toolchain",

123
MODULE.bazel.lock generated
View File

@@ -34,9 +34,8 @@
"https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9",
"https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
"https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6",
"https://bcr.bazel.build/modules/bazel_features/1.33.0/source.json": "13617db3930328c2cd2807a0f13d52ca870ac05f96db9668655113265147b2a6",
"https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
"https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080",
"https://bcr.bazel.build/modules/bazel_features/1.42.1/source.json": "fcd4396b2df85f64f2b3bb436ad870793ecf39180f1d796f913cc9276d355309",
"https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
"https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
@@ -52,8 +51,8 @@
"https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6",
"https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67",
"https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb",
"https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f",
"https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd",
"https://bcr.bazel.build/modules/buildozer/8.2.1/MODULE.bazel": "61e9433c574c2bd9519cad7fa66b9c1d2b8e8d5f3ae5d6528a2c2d26e68d874d",
"https://bcr.bazel.build/modules/buildozer/8.2.1/source.json": "7c33f6a26ee0216f85544b4bca5e9044579e0219b6898dd653f5fb449cf2e484",
"https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
@@ -113,8 +112,8 @@
"https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8",
"https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c",
"https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37",
"https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84",
"https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07",
"https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8",
"https://bcr.bazel.build/modules/rules_cc/0.2.14/source.json": "55d0a4587c5592fad350f6e698530f4faf0e7dd15e69d43f8d87e220c78bea54",
"https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642",
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
@@ -142,8 +141,6 @@
"https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
"https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
"https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
"https://bcr.bazel.build/modules/rules_multirun/0.9.0/MODULE.bazel": "32d628ef586b5b23f67e55886b7bc38913ea4160420d66ae90521dda2ff37df0",
"https://bcr.bazel.build/modules/rules_multirun/0.9.0/source.json": "e882ba77962fa6c5fe68619e5c7d0374ec9a219fb8d03c42eadaf6d0243771bd",
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
@@ -156,7 +153,6 @@
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
"https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
"https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
"https://bcr.bazel.build/modules/rules_python/0.27.1/MODULE.bazel": "65dc875cc1a06c30d5bbdba7ab021fd9e551a6579e408a3943a61303e2228a53",
"https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
"https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
"https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937",
@@ -193,8 +189,8 @@
"moduleExtensions": {
"//bun:extensions.bzl%bun": {
"general": {
"bzlTransitiveDigest": "314UOH4dQIGBHGpxCwA7yzI++E2J3bjIc20m5MZhM7U=",
"usagesDigest": "prFfUGEBfgU9euYPzwB9Wux0cLYR+2MKCz+nUIyHYkI=",
"bzlTransitiveDigest": "Q0uQOwFAgAU+etePCZ4TUDO+adLX7Z0EmRLaEsKgncw=",
"usagesDigest": "qk1PDh3WICa0VONYKXJLsmWCesNJxz3Jkb/aH/voIeI=",
"recordedInputs": [
"REPO_MAPPING:,bazel_tools bazel_tools"
],
@@ -219,26 +215,6 @@
"build_file_content": "\nexports_files([\"bun-linux-aarch64/bun\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-linux-aarch64/bun\"],\n visibility = [\"//visibility:public\"],\n)\n"
}
},
"bun_linux_x64_musl": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-linux-x64-musl.zip"
],
"sha256": "48a6c32277d343db0148ce066336472ffd380358a4d26bb1329714742492d824",
"build_file_content": "\nexports_files([\"bun-linux-x64-musl/bun\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-linux-x64-musl/bun\"],\n visibility = [\"//visibility:public\"],\n)\n"
}
},
"bun_linux_aarch64_musl": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-linux-aarch64-musl.zip"
],
"sha256": "d2c81365a2e529b78a42330d3a0056e8dbd7896b4a6782c8e392b6532141e34d",
"build_file_content": "\nexports_files([\"bun-linux-aarch64-musl/bun\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-linux-aarch64-musl/bun\"],\n visibility = [\"//visibility:public\"],\n)\n"
}
},
"bun_darwin_x64": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
@@ -268,91 +244,6 @@
"sha256": "7a77b3e245e2e26965c93089a4a1332e8a326d3364c89fae1d1fd99cdd3cd73d",
"build_file_content": "\nexports_files([\"bun-windows-x64/bun.exe\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-windows-x64/bun.exe\"],\n visibility = [\"//visibility:public\"],\n)\n"
}
},
"bun_windows_aarch64": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-windows-aarch64.zip"
],
"sha256": "6822f3aa7bd2be40fb94c194a1185aae1c6fade54ca4fc2efdc722e37f3257d2",
"build_file_content": "\nexports_files([\"bun-windows-aarch64/bun.exe\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-windows-aarch64/bun.exe\"],\n visibility = [\"//visibility:public\"],\n)\n"
}
}
}
}
},
"//bun:extensions.bzl%bun_install": {
"general": {
"bzlTransitiveDigest": "314UOH4dQIGBHGpxCwA7yzI++E2J3bjIc20m5MZhM7U=",
"usagesDigest": "rhYKu+vVZOHFMZV+ai/X42v6prfhsLITQYyLZaCnX+g=",
"recordedInputs": [
"REPO_MAPPING:,bazel_tools bazel_tools"
],
"generatedRepoSpecs": {
"script_test_vite_node_modules": {
"repoRuleId": "@@//internal:bun_install.bzl%bun_install_repository",
"attributes": {
"package_json": "@@//tests/script_test:vite_app/package.json",
"bun_lockfile": "@@//tests/script_test:vite_app/bun.lock",
"install_inputs": [],
"isolated_home": true,
"production": false,
"omit": [],
"linker": "",
"backend": "",
"ignore_scripts": true,
"install_flags": [],
"visible_repo_name": "script_test_vite_node_modules"
}
},
"script_test_vite_monorepo_node_modules": {
"repoRuleId": "@@//internal:bun_install.bzl%bun_install_repository",
"attributes": {
"package_json": "@@//tests/script_test:vite_monorepo/package.json",
"bun_lockfile": "@@//tests/script_test:vite_monorepo/bun.lock",
"install_inputs": [],
"isolated_home": true,
"production": false,
"omit": [],
"linker": "",
"backend": "",
"ignore_scripts": true,
"install_flags": [],
"visible_repo_name": "script_test_vite_monorepo_node_modules"
}
},
"script_test_paraglide_monorepo_node_modules": {
"repoRuleId": "@@//internal:bun_install.bzl%bun_install_repository",
"attributes": {
"package_json": "@@//tests/script_test:paraglide_monorepo/package.json",
"bun_lockfile": "@@//tests/script_test:paraglide_monorepo/bun.lock",
"install_inputs": [],
"isolated_home": true,
"production": false,
"omit": [],
"linker": "",
"backend": "",
"ignore_scripts": true,
"install_flags": [],
"visible_repo_name": "script_test_paraglide_monorepo_node_modules"
}
},
"examples_vite_monorepo_node_modules": {
"repoRuleId": "@@//internal:bun_install.bzl%bun_install_repository",
"attributes": {
"package_json": "@@//examples/vite_monorepo:package.json",
"bun_lockfile": "@@//examples/vite_monorepo:bun.lock",
"install_inputs": [],
"isolated_home": true,
"production": false,
"omit": [],
"linker": "",
"backend": "",
"ignore_scripts": true,
"install_flags": [],
"visible_repo_name": "examples_vite_monorepo_node_modules"
}
}
}
}

317
README.md
View File

@@ -1,300 +1,53 @@
# Bun rules for [Bazel](https://bazel.build)
# rules_bun
`rules_bun` provides Bazel rules for running, testing, building, compiling,
bundling, and developing JavaScript and TypeScript code with Bun.
Bazel rules for bun.
## Repository layout
## Current status
This repository follows the standard Bazel ruleset layout:
Phase 1 bootstrap is in place:
```text
/
MODULE.bazel
README.md
bun/
BUILD.bazel
defs.bzl
extensions.bzl
repositories.bzl
toolchain.bzl
docs/
examples/
tests/
```
- Bun toolchain rule and provider (`/bun/toolchain.bzl`)
- Platform-specific Bun repository downloads (`/bun/repositories.bzl`)
- Toolchain declarations and registration targets (`/bun/BUILD.bazel`)
- Smoke test for `bun --version` (`//tests/toolchain_test:bun_version_test`)
The public entrypoint for rule authors and users is `@rules_bun//bun:defs.bzl`.
Phase 2 bootstrap is in place:
Runtime launcher targets from `bun_binary`, `bun_script`, `bun_test`,
`bun_dev`, and `js_run_devserver` use native platform wrappers. Windows runtime
support is native and does not require Git Bash or MSYS.
- Repository-rule based `bun_install` (`/internal/bun_install.bzl`)
- Public export via `bun/defs.bzl`
- Focused install behavior tests (`//tests/install_test:all`)
## Public API
Phase 3 bootstrap is in place:
`rules_bun` exports these primary rules:
- Executable `bun_binary` rule (`/internal/bun_binary.bzl`)
- Public export via `bun/defs.bzl`
- Focused JS/TS runnable tests (`//tests/binary_test:all`)
- `bun_binary`
- `bun_build`
- `bun_compile`
- `bun_bundle`
- `bun_dev`
- `bun_script`
- `bun_test`
- `js_binary`
- `js_test`
- `js_run_devserver`
- `js_library`
- `ts_library`
Phase 4 bootstrap is in place:
Reference documentation:
- Test rule `bun_test` (`/internal/bun_test.bzl`)
- Public export via `bun/defs.bzl`
- Focused passing/failing test targets (`//tests/bun_test_test:all`)
- Published docs site: https://eriyc.github.io/rules_bun/
- Generated build rule reference: [docs/rules.md](docs/rules.md)
- `bun_install` extension docs: [docs/bun_install.md](docs/bun_install.md)
- Docs index: [docs/index.md](docs/index.md)
Phase 5 bootstrap is in place:
## Hermeticity
- Bundle rule `bun_bundle` (`/internal/bun_bundle.bzl`)
- Public export via `bun/defs.bzl`
- Focused output/minify tests (`//tests/bundle_test:all`)
`rules_bun` now draws a sharp line between hermetic rule surfaces and local
workflow helpers.
Phase 6 bootstrap is in place:
- Hermetic build/test surfaces: `bun_build`, `bun_bundle`, `bun_compile`, `bun_test`
- Runfiles-only executable surface: `bun_binary`
- Reproducible but non-hermetic repository fetch surface: `bun_install`
- Local workflow helpers: `bun_script`, `bun_dev`, `js_run_devserver`
- Source grouping rules `js_library` / `ts_library` (`/internal/js_library.bzl`)
- Transitive `deps` propagation wired into `bun_bundle` and `bun_test`
- Focused dependency-propagation tests (`//tests/library_test:all`)
Strict defaults are enabled by default:
Phase 7 bootstrap is in place:
- `bun_install` skips lifecycle scripts unless `ignore_scripts = False`
- `bun_build`, `bun_bundle`, `bun_compile`, and `bun_test` require `install_mode = "disable"`
- Runtime launchers stage hermetic `bun`, `bunx`, and `node` commands on `PATH` and do not inherit the host `PATH` unless `inherit_host_path = True`
- Bzlmod `bun_install` module extension (`/bun/extensions.bzl`) using Bazel 9-compatible extension/tag syntax
- Focused module-extension shape test (`//tests/install_extension_test:all`)
To refresh generated rule docs:
Phase 8 bootstrap is in place:
```bash
bazel build //docs:rules_md && cp bazel-bin/docs/rules.md docs/rules.md
```
## Bzlmod usage
Release announcements should provide a copy-pasteable module snippet in the
standard ruleset form:
```starlark
bazel_dep(name = "rules_bun", version = "1.0.3")
```
Then add the Bun repositories and register the toolchains in `MODULE.bazel`:
```starlark
bun_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun")
use_repo(
bun_ext,
"bun_linux_x64",
"bun_linux_aarch64",
"bun_linux_x64_musl",
"bun_linux_aarch64_musl",
"bun_darwin_x64",
"bun_darwin_aarch64",
"bun_windows_x64",
"bun_windows_aarch64",
)
register_toolchains(
"@rules_bun//bun:darwin_aarch64_toolchain",
"@rules_bun//bun:darwin_x64_toolchain",
"@rules_bun//bun:linux_aarch64_toolchain",
"@rules_bun//bun:linux_x64_toolchain",
"@rules_bun//bun:windows_x64_toolchain",
)
```
If you want Bazel-managed dependency installation, also add the module
extension for `bun_install`:
`bun_install` runs `bun install`, not `npm install`. In the example below,
`bun_deps` is just the Bazel repository name for the generated
`node_modules` tree. See [docs/bun_install.md](docs/bun_install.md) for the
full extension reference.
```starlark
bun_install_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun_install")
bun_install_ext.install(
name = "bun_deps",
package_json = "//:package.json",
bun_lockfile = "//:bun.lock",
# Optional: include extra install-time files.
# install_inputs = ["//:.npmrc"],
# Optional non-hermetic opt-in:
# ignore_scripts = False,
# isolated_home = False,
)
use_repo(bun_install_ext, "bun_deps")
```
## `rules_js` compatibility layer
`rules_bun` now exposes a Bun-backed compatibility layer for the most common
`rules_js` entrypoints:
- `@rules_bun//js:defs.bzl` exports `js_binary`, `js_test`, `js_run_devserver`,
`js_library`, `ts_library`, and `JsInfo`.
- `@rules_bun//npm:extensions.bzl` exports `npm_translate_lock`, which creates a
Bun-installed external repo and generates `@<repo>//:defs.bzl` with
`npm_link_all_packages()`.
Example:
```starlark
load("@rules_bun//js:defs.bzl", "js_binary")
load("@npm//:defs.bzl", "npm_link_all_packages")
npm_link_all_packages()
js_binary(
name = "app",
entry_point = "src/main.ts",
node_modules = ":node_modules",
)
```
This is a compatibility subset, not a full reimplementation of `rules_js`.
Package aliases created by `npm_link_all_packages()` use sanitized target names
such as `npm__vite` or `npm__at_types_node`.
## Legacy WORKSPACE usage
For non-Bzlmod consumers, the repository exposes a legacy setup macro in
`@rules_bun//bun:repositories.bzl`:
```starlark
load("@rules_bun//bun:repositories.bzl", "bun_register_toolchains")
bun_register_toolchains()
```
## Loading rules in BUILD files
```starlark
load(
"@rules_bun//bun:defs.bzl",
"bun_binary",
"bun_build",
"bun_compile",
"bun_bundle",
"bun_dev",
"bun_script",
"bun_test",
"js_library",
"ts_library",
)
```
## Common workflows
### `bun_script` for package scripts
Use `bun_script` to expose a `package.json` script as a Bazel executable.
This is the recommended way to run Vite-style `dev`, `build`, and `preview`
scripts.
```starlark
load("@rules_bun//bun:defs.bzl", "bun_script")
bun_script(
name = "web_dev",
script = "dev",
package_json = "package.json",
node_modules = "@bun_deps//:node_modules",
data = glob([
"src/**",
"static/**",
"vite.config.*",
"svelte.config.*",
"tsconfig*.json",
]),
)
```
Launcher-based runtime rules stage hermetic `bun`, `bunx`, and `node`
commands on `PATH`. When `node_modules` is provided, executables from
`node_modules/.bin` are also added to the runtime `PATH`. The host `PATH` is
not inherited unless `inherit_host_path = True`. This label typically comes
from `bun_install`, which still produces a standard `node_modules/` directory.
### `bun_build` and `bun_compile`
Use `bun_build` for general-purpose `bun build` output directories and
`bun_compile` for standalone executables built with `bun build --compile`.
```starlark
load("@rules_bun//bun:defs.bzl", "bun_build", "bun_compile")
bun_build(
name = "site",
entry_points = ["src/index.html"],
data = glob(["src/**"]),
splitting = True,
metafile = True,
)
bun_compile(
name = "cli",
entry_point = "src/cli.ts",
)
```
`bun_build` exposes a directory output so Bun can emit HTML, CSS, assets, and
split chunks. `bun_compile` produces a single executable artifact and supports
explicit cross-compilation via `compile_executable`. When `root` is omitted,
`bun_build` derives a stable default from the entry point parent directory so
HTML and asset output stays inside Bazel's declared output tree.
### `bun_dev` for local development
Use `bun_dev` for long-running watch or hot-reload development targets.
```starlark
load("@rules_bun//bun:defs.bzl", "bun_dev")
bun_dev(
name = "web_dev",
entry_point = "src/main.ts",
# Optional: run from the entry point directory so Bun auto-loads colocated .env files.
# working_dir = "entry_point",
)
```
Supported development options include:
- `watch_mode = "watch"`
- `watch_mode = "hot"`
- `restart_on = [...]`
- `working_dir = "workspace" | "entry_point"`
### Working directory behavior
`bun_binary` and `bun_dev` support `working_dir`:
- `"workspace"`: run from the Bazel runfiles workspace root.
- `"entry_point"`: run from the nearest ancestor of the entry point that
contains `.env` or `package.json`.
## Tests and examples
The repository keeps conformance and integration coverage in [tests/](tests/) and
usage samples in [examples/](examples/).
Representative example docs:
- [examples/basic/README.md](examples/basic/README.md)
- [examples/workspace/README.md](examples/workspace/README.md)
- [examples/vite_monorepo/README.md](examples/vite_monorepo/README.md)
To validate the ruleset locally:
```bash
bazel test //tests/...
```
- CI matrix workflow for linux-x64, darwin-arm64, and windows (`/.github/workflows/ci.yml`)
- Bazel 9 pin in CI via `USE_BAZEL_VERSION=9.0.0`
- Focused CI matrix shape test (`//tests/ci_test:all`)

View File

@@ -1,3 +1,3 @@
1.0.3
0.0.2
stable
0

View File

@@ -1,24 +1,5 @@
workspace(name = "rules_bun")
load("//internal:bun_install.bzl", "bun_install")
load("//bun:repositories.bzl", "bun_register_toolchains")
bun_register_toolchains()
bun_install(
name = "script_test_vite_node_modules",
package_json = "//tests/script_test:vite_app/package.json",
bun_lockfile = "//tests/script_test:vite_app/bun.lock",
)
bun_install(
name = "script_test_vite_monorepo_node_modules",
package_json = "//tests/script_test:vite_monorepo/package.json",
bun_lockfile = "//tests/script_test:vite_monorepo/bun.lock",
)
bun_install(
name = "examples_vite_monorepo_node_modules",
package_json = "//examples/vite_monorepo:package.json",
bun_lockfile = "//examples/vite_monorepo:bun.lock",
)

View File

@@ -1,65 +1,11 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load(":toolchain.bzl", "bun_toolchain")
load(":version.bzl", "BUN_VERSION")
exports_files([
"defs.bzl",
"extensions.bzl",
"repositories.bzl",
"toolchain.bzl",
"version.bzl",
])
filegroup(
name = "repo_runtime_files",
srcs = [
"BUILD.bazel",
"defs.bzl",
"extensions.bzl",
"repositories.bzl",
"toolchain.bzl",
"version.bzl",
],
visibility = ["//visibility:public"],
)
bzl_library(
name = "toolchain_bzl",
srcs = ["toolchain.bzl"],
visibility = ["//visibility:public"],
)
bzl_library(
name = "extensions_bzl",
srcs = ["extensions.bzl"],
visibility = ["//visibility:public"],
deps = ["//internal:bun_install_bzl"],
)
bzl_library(
name = "repositories_bzl",
srcs = ["repositories.bzl"],
visibility = ["//visibility:public"],
)
bzl_library(
name = "defs_bzl",
srcs = ["defs.bzl"],
visibility = ["//visibility:public"],
deps = [
":toolchain_bzl",
"//internal:bun_build_support_bzl",
"//internal:bun_binary_bzl",
"//internal:bun_compile_bzl",
"//internal:bun_bundle_bzl",
"//internal:bun_dev_bzl",
"//internal:bun_script_bzl",
"//internal:bun_test_bzl",
"//internal:js_compat_bzl",
"//internal:js_library_bzl",
],
)
toolchain_type(name = "toolchain_type")
bun_toolchain(

View File

@@ -1,29 +1,15 @@
"""Public API surface for Bun Bazel rules."""
load("//internal:bun_compile.bzl", _bun_build = "bun_build", _bun_compile = "bun_compile")
load("//internal:bun_binary.bzl", _bun_binary = "bun_binary")
load("//internal:bun_bundle.bzl", _bun_bundle = "bun_bundle")
load("//internal:bun_dev.bzl", _bun_dev = "bun_dev")
load("//internal:bun_script.bzl", _bun_script = "bun_script")
load("//internal:bun_test.bzl", _bun_test = "bun_test")
load("//internal:js_compat.bzl", _JsInfo = "JsInfo", _js_binary = "js_binary", _js_run_devserver = "js_run_devserver", _js_test = "js_test")
load("//internal:js_library.bzl", _js_library = "js_library", _ts_library = "ts_library")
load(":toolchain.bzl", _BunToolchainInfo = "BunToolchainInfo", _bun_toolchain = "bun_toolchain")
visibility("public")
bun_binary = _bun_binary
bun_build = _bun_build
bun_compile = _bun_compile
bun_bundle = _bun_bundle
bun_dev = _bun_dev
bun_script = _bun_script
bun_test = _bun_test
js_binary = _js_binary
js_test = _js_test
js_run_devserver = _js_run_devserver
js_library = _js_library
ts_library = _ts_library
JsInfo = _JsInfo
BunToolchainInfo = _BunToolchainInfo
bun_toolchain = _bun_toolchain

View File

@@ -13,16 +13,6 @@ _BUN_ARCHIVES = {
"asset": "bun-linux-aarch64.zip",
"binary": "bun-linux-aarch64/bun",
},
"bun_linux_x64_musl": {
"sha256": "48a6c32277d343db0148ce066336472ffd380358a4d26bb1329714742492d824",
"asset": "bun-linux-x64-musl.zip",
"binary": "bun-linux-x64-musl/bun",
},
"bun_linux_aarch64_musl": {
"sha256": "d2c81365a2e529b78a42330d3a0056e8dbd7896b4a6782c8e392b6532141e34d",
"asset": "bun-linux-aarch64-musl.zip",
"binary": "bun-linux-aarch64-musl/bun",
},
"bun_darwin_x64": {
"sha256": "c1d90bf6140f20e572c473065dc6b37a4b036349b5e9e4133779cc642ad94323",
"asset": "bun-darwin-x64.zip",
@@ -38,11 +28,6 @@ _BUN_ARCHIVES = {
"asset": "bun-windows-x64.zip",
"binary": "bun-windows-x64/bun.exe",
},
"bun_windows_aarch64": {
"sha256": "6822f3aa7bd2be40fb94c194a1185aae1c6fade54ca4fc2efdc722e37f3257d2",
"asset": "bun-windows-aarch64.zip",
"binary": "bun-windows-aarch64/bun.exe",
},
}
_BUN_GITHUB_RELEASE_URL_TEMPLATE = "https://github.com/oven-sh/bun/releases/download/bun-v{}/{}"
@@ -73,16 +58,8 @@ bun = module_extension(
_install = tag_class(
attrs = {
"name": attr.string(mandatory = True),
"package_json": attr.label(mandatory = True),
"bun_lockfile": attr.label(mandatory = True),
"install_inputs": attr.label_list(allow_files = True),
"isolated_home": attr.bool(default = True),
"production": attr.bool(default = False),
"omit": attr.string_list(),
"linker": attr.string(),
"backend": attr.string(),
"ignore_scripts": attr.bool(default = True),
"install_flags": attr.string_list(),
"package_json": attr.string(mandatory = True),
"bun_lockfile": attr.string(mandatory = True),
},
)
@@ -94,15 +71,6 @@ def _bun_install_impl(ctx):
name = install.name,
package_json = install.package_json,
bun_lockfile = install.bun_lockfile,
install_inputs = install.install_inputs,
isolated_home = install.isolated_home,
production = install.production,
omit = install.omit,
linker = install.linker,
backend = install.backend,
ignore_scripts = install.ignore_scripts,
install_flags = install.install_flags,
visible_repo_name = install.name,
)

View File

@@ -12,16 +12,6 @@ _BUN_ARCHIVES = {
"asset": "bun-linux-aarch64.zip",
"binary": "bun-linux-aarch64/bun",
},
"bun_linux_x64_musl": {
"sha256": "48a6c32277d343db0148ce066336472ffd380358a4d26bb1329714742492d824",
"asset": "bun-linux-x64-musl.zip",
"binary": "bun-linux-x64-musl/bun",
},
"bun_linux_aarch64_musl": {
"sha256": "d2c81365a2e529b78a42330d3a0056e8dbd7896b4a6782c8e392b6532141e34d",
"asset": "bun-linux-aarch64-musl.zip",
"binary": "bun-linux-aarch64-musl/bun",
},
"bun_darwin_x64": {
"sha256": "c1d90bf6140f20e572c473065dc6b37a4b036349b5e9e4133779cc642ad94323",
"asset": "bun-darwin-x64.zip",
@@ -37,11 +27,6 @@ _BUN_ARCHIVES = {
"asset": "bun-windows-x64.zip",
"binary": "bun-windows-x64/bun.exe",
},
"bun_windows_aarch64": {
"sha256": "6822f3aa7bd2be40fb94c194a1185aae1c6fade54ca4fc2efdc722e37f3257d2",
"asset": "bun-windows-aarch64.zip",
"binary": "bun-windows-aarch64/bun.exe",
},
}
_BUN_GITHUB_RELEASE_URL_TEMPLATE = "https://github.com/oven-sh/bun/releases/download/bun-v{}/{}"

View File

@@ -1,24 +0,0 @@
load("@stardoc//stardoc:stardoc.bzl", "stardoc")
package(default_visibility = ["//visibility:public"])
stardoc(
name = "rules_md",
out = "rules.md",
input = "//bun:defs.bzl",
symbol_names = [
"bun_binary",
"bun_build",
"bun_compile",
"bun_bundle",
"bun_dev",
"bun_script",
"bun_test",
"js_binary",
"js_run_devserver",
"js_test",
"js_library",
"ts_library",
],
deps = ["//bun:defs_bzl"],
)

View File

@@ -1,186 +0,0 @@
# `bun_install`
`bun_install` is a Bzlmod module extension for creating an external repository
that contains a Bun-generated `node_modules/` tree.
Unlike the build rules in [rules.md](rules.md), `bun_install` is not loaded from
`@rules_bun//bun:defs.bzl`. It is loaded from
`@rules_bun//bun:extensions.bzl`, so it is documented separately.
## What it does
`bun_install`:
- runs `bun install --frozen-lockfile`
- uses your checked-in `package.json` and `bun.lock` or `bun.lockb`
- creates an external Bazel repository exposing `:node_modules`
- generates `:defs.bzl` with `npm_link_all_packages()` and `package_target_name()`
- keeps dependency installation under Bun rather than npm
The generated repository can then be passed to rules such as `bun_script`,
`bun_binary`, `bun_bundle`, and `bun_test`.
## Hermeticity
`bun_install` is a repository convenience rule, not a hermetic build action.
It is intended to be reproducible from a checked-in lockfile and pinned Bun
toolchain, but it still performs dependency fetching as part of repository
materialization.
Strict defaults now favor reproducibility:
- `isolated_home = True`
- `ignore_scripts = True`
Set `ignore_scripts = False` only when you explicitly want lifecycle scripts to
run during repository creation.
## Usage
```starlark
bun_install_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun_install")
bun_install_ext.install(
name = "bun_deps",
package_json = "//:package.json",
bun_lockfile = "//:bun.lock",
production = True,
omit = ["peer"],
)
use_repo(bun_install_ext, "bun_deps")
```
Then reference the installed dependencies from build targets:
```starlark
load("@rules_bun//bun:defs.bzl", "bun_script")
bun_script(
name = "web_dev",
script = "dev",
package_json = "package.json",
node_modules = "@bun_deps//:node_modules",
)
```
## `install(...)` attributes
### `name`
Repository name to create.
This becomes the external repository you reference later, for example
`@bun_deps//:node_modules`.
### `package_json`
Label string pointing to the source `package.json` file.
Example:
```starlark
package_json = "//:package.json"
```
### `bun_lockfile`
Label string pointing to the Bun lockfile.
Supported lockfile names are:
- `bun.lock`
- `bun.lockb`
Example:
```starlark
bun_lockfile = "//:bun.lock"
```
### `install_inputs`
Optional list of additional files under the same package root to copy into the
install repository before Bun runs.
Use this for install-time config or patch files that Bun needs to see, for
example `.npmrc`, `bunfig.toml`, or patch files referenced by your manifest.
Example:
```starlark
install_inputs = [
"//:.npmrc",
"//:patches/react.patch",
]
```
`bun_install` also copies these root-level files automatically when present:
- `.npmrc`
- `bunfig.json`
- `bunfig.toml`
### `isolated_home`
Optional boolean controlling whether Bun runs with `HOME` set to the generated
repository root.
- `True` (default): more isolated install environment
- `False`: lets Bun use the host `HOME`, which can improve repeated-install
performance when Bun's cache is home-scoped
### `production`
Optional boolean controlling whether Bun installs only production dependencies.
Example:
```starlark
production = True
```
### `omit`
Optional list of dependency groups to omit, forwarded as repeated
`--omit` flags. Common values are `dev`, `optional`, and `peer`.
### `linker`
Optional Bun linker strategy, forwarded as `--linker`.
Common values:
- `isolated`
- `hoisted`
### `backend`
Optional Bun install backend, forwarded as `--backend`.
Examples include `hardlink`, `symlink`, and `copyfile`.
### `ignore_scripts`
Optional boolean controlling whether Bun skips lifecycle scripts in the project
manifest.
- `True` (default): skips lifecycle scripts for stricter, more reproducible installs
- `False`: allows lifecycle scripts to run during repository creation
### `install_flags`
Optional list of additional raw flags forwarded to `bun install`.
## Notes
- `bun_install` runs Bun, not npm.
- The repository name is arbitrary. `bun_deps` is only an example.
- The generated repository exposes a standard `node_modules/` tree because that
is the dependency layout Bun installs.
- `--frozen-lockfile` is used, so the lockfile must already be in sync with
`package.json`.
- Additional `install_inputs` must be files under the same package root as the
selected `package_json`.
- `bun_install` does not make the install step remotely hermetic; it makes the
generated repository stricter and more reproducible by default.

View File

@@ -1,106 +0,0 @@
# rules_bun docs
Documentation for `rules_bun`, a Bazel ruleset for Bun.
## Ruleset layout
The repository exposes its public Bazel API from the [bun/](../bun/) package:
- `@rules_bun//bun:defs.bzl` for build rules
- `@rules_bun//bun:extensions.bzl` for Bzlmod extensions
- `@rules_bun//bun:repositories.bzl` for legacy WORKSPACE setup
Supporting material lives in:
- [examples/](../examples/) for usage samples
- [tests/](../tests/) for repository conformance and integration tests
- [docs/rules.md](rules.md) for generated build rule reference
- [docs/bun_install.md](bun_install.md) for `bun_install` extension docs
## Hermeticity
- Hermetic rule surfaces: `bun_build`, `bun_bundle`, `bun_compile`, `bun_test`
- Runfiles-only executable surface: `bun_binary`
- Reproducible but non-hermetic repository surface: `bun_install`
- Local workflow helpers: `bun_script`, `bun_dev`, `js_run_devserver`
## Rule reference
- [rules.md](rules.md)
## Bzlmod extensions
- [bun_install.md](bun_install.md)
## Typical Bzlmod setup
```starlark
bazel_dep(name = "rules_bun", version = "0.2.1")
bun_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun")
use_repo(
bun_ext,
"bun_linux_x64",
"bun_linux_aarch64",
"bun_linux_x64_musl",
"bun_linux_aarch64_musl",
"bun_darwin_x64",
"bun_darwin_aarch64",
"bun_windows_x64",
"bun_windows_aarch64",
)
register_toolchains(
"@rules_bun//bun:darwin_aarch64_toolchain",
"@rules_bun//bun:darwin_x64_toolchain",
"@rules_bun//bun:linux_aarch64_toolchain",
"@rules_bun//bun:linux_x64_toolchain",
"@rules_bun//bun:windows_x64_toolchain",
)
```
## Vite package scripts
Use `bun_script` for package-script driven workflows such as `dev`, `build`,
and `preview`.
The `node_modules` label below refers to dependencies installed by
`bun_install`.
```starlark
load("@rules_bun//bun:defs.bzl", "bun_script")
bun_script(
name = "web_dev",
script = "dev",
package_json = "package.json",
node_modules = "@my_workspace//:node_modules",
data = glob([
"src/**",
"public/**",
"index.html",
"vite.config.*",
"tsconfig*.json",
]),
)
```
`bun_script` runs from the package directory by default and adds
`node_modules/.bin` to `PATH`.
## Build and compile
Use `bun_build` when Bun may emit a directory of outputs such as HTML, CSS,
chunks, and static assets. Use `bun_compile` for standalone executables created
with `bun build --compile`.
## Regeneration
The rule reference is generated from the public Starlark symbols in
`@rules_bun//bun:defs.bzl`:
```bash
bazel build //docs:rules_md
cp bazel-bin/docs/rules.md docs/rules.md
```

View File

@@ -1,499 +0,0 @@
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
Public API surface for Bun Bazel rules.
## Hermeticity And Determinism
- Hermetic rule surfaces: `bun_build`, `bun_bundle`, `bun_compile`, `bun_test`
- Runfiles-only executable surface: `bun_binary`
- Reproducible but non-hermetic repository surface: `bun_install`
- Local workflow helpers: `bun_script`, `bun_dev`, `js_run_devserver`
Strict defaults:
- `bun_build`, `bun_bundle`, `bun_compile`, and `bun_test` require `install_mode = "disable"`
- Runtime launchers stage hermetic `bun`, `bunx`, and `node` commands on `PATH` and do not inherit the host `PATH` unless `inherit_host_path = True`
<a id="bun_binary"></a>
## bun_binary
<pre>
load("@rules_bun//bun:defs.bzl", "bun_binary")
bun_binary(<a href="#bun_binary-name">name</a>, <a href="#bun_binary-deps">deps</a>, <a href="#bun_binary-data">data</a>, <a href="#bun_binary-conditions">conditions</a>, <a href="#bun_binary-entry_point">entry_point</a>, <a href="#bun_binary-env_files">env_files</a>, <a href="#bun_binary-install_mode">install_mode</a>, <a href="#bun_binary-no_env_file">no_env_file</a>,
<a href="#bun_binary-node_modules">node_modules</a>, <a href="#bun_binary-preload">preload</a>, <a href="#bun_binary-run_flags">run_flags</a>, <a href="#bun_binary-smol">smol</a>, <a href="#bun_binary-working_dir">working_dir</a>)
</pre>
Runs a JS/TS entry point with Bun as an executable target.
Use this rule for non-test scripts and CLIs that should run via `bazel run`.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="bun_binary-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="bun_binary-deps"></a>deps | Library dependencies required by the program. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_binary-data"></a>data | Additional runtime files required by the program. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_binary-conditions"></a>conditions | Custom package resolve conditions passed to Bun. | List of strings | optional | `[]` |
| <a id="bun_binary-entry_point"></a>entry_point | Path to the main JS/TS file to execute. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="bun_binary-env_files"></a>env_files | Additional environment files loaded with `--env-file`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_binary-install_mode"></a>install_mode | Whether Bun may auto-install missing packages at runtime. Non-`disable` values are runtime opt-ins and are not hermetic. | String | optional | `"disable"` |
| <a id="bun_binary-inherit_host_path"></a>inherit_host_path | If true, appends the host PATH after the staged Bun runtime tool bin and `node_modules/.bin` entries at runtime. | Boolean | optional | `False` |
| <a id="bun_binary-no_env_file"></a>no_env_file | If true, disables Bun's automatic `.env` loading. | Boolean | optional | `False` |
| <a id="bun_binary-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="bun_binary-preload"></a>preload | Modules to preload with `--preload` before running the entry point. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_binary-run_flags"></a>run_flags | Additional raw flags forwarded to `bun run` before the entry point. | List of strings | optional | `[]` |
| <a id="bun_binary-smol"></a>smol | If true, enables Bun's lower-memory runtime mode. | Boolean | optional | `False` |
| <a id="bun_binary-working_dir"></a>working_dir | Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`. | String | optional | `"workspace"` |
<a id="bun_build"></a>
## bun_build
<pre>
load("@rules_bun//bun:defs.bzl", "bun_build")
bun_build(<a href="#bun_build-name">name</a>, <a href="#bun_build-deps">deps</a>, <a href="#bun_build-data">data</a>, <a href="#bun_build-asset_naming">asset_naming</a>, <a href="#bun_build-banner">banner</a>, <a href="#bun_build-build_flags">build_flags</a>, <a href="#bun_build-chunk_naming">chunk_naming</a>, <a href="#bun_build-conditions">conditions</a>,
<a href="#bun_build-css_chunking">css_chunking</a>, <a href="#bun_build-define">define</a>, <a href="#bun_build-drop">drop</a>, <a href="#bun_build-emit_dce_annotations">emit_dce_annotations</a>, <a href="#bun_build-entry_naming">entry_naming</a>, <a href="#bun_build-entry_points">entry_points</a>, <a href="#bun_build-env">env</a>, <a href="#bun_build-external">external</a>,
<a href="#bun_build-feature">feature</a>, <a href="#bun_build-footer">footer</a>, <a href="#bun_build-format">format</a>, <a href="#bun_build-install_mode">install_mode</a>, <a href="#bun_build-jsx_factory">jsx_factory</a>, <a href="#bun_build-jsx_fragment">jsx_fragment</a>, <a href="#bun_build-jsx_import_source">jsx_import_source</a>,
<a href="#bun_build-jsx_runtime">jsx_runtime</a>, <a href="#bun_build-jsx_side_effects">jsx_side_effects</a>, <a href="#bun_build-keep_names">keep_names</a>, <a href="#bun_build-loader">loader</a>, <a href="#bun_build-metafile">metafile</a>, <a href="#bun_build-metafile_md">metafile_md</a>, <a href="#bun_build-minify">minify</a>,
<a href="#bun_build-minify_identifiers">minify_identifiers</a>, <a href="#bun_build-minify_syntax">minify_syntax</a>, <a href="#bun_build-minify_whitespace">minify_whitespace</a>, <a href="#bun_build-no_bundle">no_bundle</a>, <a href="#bun_build-node_modules">node_modules</a>, <a href="#bun_build-packages">packages</a>,
<a href="#bun_build-production">production</a>, <a href="#bun_build-public_path">public_path</a>, <a href="#bun_build-react_fast_refresh">react_fast_refresh</a>, <a href="#bun_build-root">root</a>, <a href="#bun_build-sourcemap">sourcemap</a>, <a href="#bun_build-splitting">splitting</a>, <a href="#bun_build-target">target</a>)
</pre>
Builds one or more entry points with `bun build`.
The rule emits a directory artifact so Bun can materialize multi-file output
graphs such as HTML, CSS, assets, and split chunks. Optional metafile outputs
may be requested with `metafile` and `metafile_md`.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="bun_build-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="bun_build-deps"></a>deps | Source/library dependencies that provide transitive inputs. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_build-data"></a>data | Additional non-source files needed during building. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_build-asset_naming"></a>asset_naming | Optional asset naming template. | String | optional | `""` |
| <a id="bun_build-banner"></a>banner | Optional bundle banner text. | String | optional | `""` |
| <a id="bun_build-build_flags"></a>build_flags | Additional raw flags forwarded to `bun build`. | List of strings | optional | `[]` |
| <a id="bun_build-chunk_naming"></a>chunk_naming | Optional chunk naming template. | String | optional | `""` |
| <a id="bun_build-conditions"></a>conditions | Custom resolve conditions passed to Bun. | List of strings | optional | `[]` |
| <a id="bun_build-css_chunking"></a>css_chunking | If true, Bun chunks CSS across multiple entry points. | Boolean | optional | `False` |
| <a id="bun_build-define"></a>define | Repeated `--define` values such as `process.env.NODE_ENV:"production"`. | List of strings | optional | `[]` |
| <a id="bun_build-drop"></a>drop | Repeated `--drop` values, for example `console`. | List of strings | optional | `[]` |
| <a id="bun_build-emit_dce_annotations"></a>emit_dce_annotations | If true, re-emits DCE annotations in the bundle. | Boolean | optional | `False` |
| <a id="bun_build-entry_naming"></a>entry_naming | Optional entry naming template. | String | optional | `""` |
| <a id="bun_build-entry_points"></a>entry_points | Entry files to build, including JS/TS or HTML entry points. | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
| <a id="bun_build-env"></a>env | Inline environment variable behavior passed to `--env`. | String | optional | `""` |
| <a id="bun_build-external"></a>external | Modules treated as externals (not bundled). | List of strings | optional | `[]` |
| <a id="bun_build-feature"></a>feature | Repeated `--feature` values for dead-code elimination. | List of strings | optional | `[]` |
| <a id="bun_build-footer"></a>footer | Optional bundle footer text. | String | optional | `""` |
| <a id="bun_build-format"></a>format | Output module format. | String | optional | `"esm"` |
| <a id="bun_build-install_mode"></a>install_mode | Whether Bun may auto-install missing packages while executing the build. Hermetic builds require `\"disable\"`, and other values are rejected. | String | optional | `"disable"` |
| <a id="bun_build-jsx_factory"></a>jsx_factory | Optional JSX factory override. | String | optional | `""` |
| <a id="bun_build-jsx_fragment"></a>jsx_fragment | Optional JSX fragment override. | String | optional | `""` |
| <a id="bun_build-jsx_import_source"></a>jsx_import_source | Optional JSX import source override. | String | optional | `""` |
| <a id="bun_build-jsx_runtime"></a>jsx_runtime | Optional JSX runtime override. | String | optional | `""` |
| <a id="bun_build-jsx_side_effects"></a>jsx_side_effects | If true, treats JSX as having side effects. | Boolean | optional | `False` |
| <a id="bun_build-keep_names"></a>keep_names | If true, preserves function and class names when minifying. | Boolean | optional | `False` |
| <a id="bun_build-loader"></a>loader | Repeated `--loader` values such as `.svg:file`. | List of strings | optional | `[]` |
| <a id="bun_build-metafile"></a>metafile | If true, emits Bun's JSON metafile alongside the output directory. | Boolean | optional | `False` |
| <a id="bun_build-metafile_md"></a>metafile_md | If true, emits Bun's markdown metafile alongside the output directory. | Boolean | optional | `False` |
| <a id="bun_build-minify"></a>minify | If true, enables all Bun minification passes. | Boolean | optional | `False` |
| <a id="bun_build-minify_identifiers"></a>minify_identifiers | If true, minifies identifiers only. | Boolean | optional | `False` |
| <a id="bun_build-minify_syntax"></a>minify_syntax | If true, minifies syntax only. | Boolean | optional | `False` |
| <a id="bun_build-minify_whitespace"></a>minify_whitespace | If true, minifies whitespace only. | Boolean | optional | `False` |
| <a id="bun_build-no_bundle"></a>no_bundle | If true, transpiles without bundling. | Boolean | optional | `False` |
| <a id="bun_build-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, for package resolution. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="bun_build-packages"></a>packages | Whether packages stay bundled or are treated as external. | String | optional | `"bundle"` |
| <a id="bun_build-production"></a>production | If true, sets `NODE_ENV=production` and enables Bun production mode. | Boolean | optional | `False` |
| <a id="bun_build-public_path"></a>public_path | Optional public path prefix for emitted imports. | String | optional | `""` |
| <a id="bun_build-react_fast_refresh"></a>react_fast_refresh | If true, enables Bun's React fast refresh transform. | Boolean | optional | `False` |
| <a id="bun_build-root"></a>root | Optional root directory for multiple entry points. When omitted, `bun_build` derives one from the entry point parent directories to keep emitted files inside the declared output tree. | String | optional | `""` |
| <a id="bun_build-sourcemap"></a>sourcemap | Sourcemap emission mode. | String | optional | `"none"` |
| <a id="bun_build-splitting"></a>splitting | If true, enables code splitting. | Boolean | optional | `False` |
| <a id="bun_build-target"></a>target | Bun build target environment. | String | optional | `"browser"` |
<a id="bun_bundle"></a>
## bun_bundle
<pre>
load("@rules_bun//bun:defs.bzl", "bun_bundle")
bun_bundle(<a href="#bun_bundle-name">name</a>, <a href="#bun_bundle-deps">deps</a>, <a href="#bun_bundle-data">data</a>, <a href="#bun_bundle-build_flags">build_flags</a>, <a href="#bun_bundle-entry_points">entry_points</a>, <a href="#bun_bundle-external">external</a>, <a href="#bun_bundle-format">format</a>, <a href="#bun_bundle-install_mode">install_mode</a>, <a href="#bun_bundle-minify">minify</a>,
<a href="#bun_bundle-node_modules">node_modules</a>, <a href="#bun_bundle-sourcemap">sourcemap</a>, <a href="#bun_bundle-target">target</a>)
</pre>
Bundles one or more JS/TS entry points using Bun build.
Each entry point produces one output JavaScript artifact.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="bun_bundle-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="bun_bundle-deps"></a>deps | Source/library dependencies that provide transitive inputs. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_bundle-data"></a>data | Additional non-source files needed during bundling. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_bundle-build_flags"></a>build_flags | Additional raw flags forwarded to `bun build`. | List of strings | optional | `[]` |
| <a id="bun_bundle-entry_points"></a>entry_points | Entry files to bundle. | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
| <a id="bun_bundle-external"></a>external | Package names to treat as externals (not bundled). | List of strings | optional | `[]` |
| <a id="bun_bundle-format"></a>format | Output module format. | String | optional | `"esm"` |
| <a id="bun_bundle-install_mode"></a>install_mode | Whether Bun may auto-install missing packages during bundling. Hermetic bundles require `\"disable\"`, and other values are rejected. | String | optional | `"disable"` |
| <a id="bun_bundle-minify"></a>minify | If true, minifies bundle output. | Boolean | optional | `False` |
| <a id="bun_bundle-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, for package resolution. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="bun_bundle-sourcemap"></a>sourcemap | If true, emits source maps. | Boolean | optional | `False` |
| <a id="bun_bundle-target"></a>target | Bun build target environment. | String | optional | `"browser"` |
<a id="bun_compile"></a>
## bun_compile
<pre>
load("@rules_bun//bun:defs.bzl", "bun_compile")
bun_compile(<a href="#bun_compile-name">name</a>, <a href="#bun_compile-deps">deps</a>, <a href="#bun_compile-data">data</a>, <a href="#bun_compile-asset_naming">asset_naming</a>, <a href="#bun_compile-banner">banner</a>, <a href="#bun_compile-build_flags">build_flags</a>, <a href="#bun_compile-bytecode">bytecode</a>, <a href="#bun_compile-chunk_naming">chunk_naming</a>,
<a href="#bun_compile-compile_autoload_bunfig">compile_autoload_bunfig</a>, <a href="#bun_compile-compile_autoload_dotenv">compile_autoload_dotenv</a>, <a href="#bun_compile-compile_autoload_package_json">compile_autoload_package_json</a>,
<a href="#bun_compile-compile_autoload_tsconfig">compile_autoload_tsconfig</a>, <a href="#bun_compile-compile_exec_argv">compile_exec_argv</a>, <a href="#bun_compile-compile_executable">compile_executable</a>, <a href="#bun_compile-conditions">conditions</a>,
<a href="#bun_compile-css_chunking">css_chunking</a>, <a href="#bun_compile-define">define</a>, <a href="#bun_compile-drop">drop</a>, <a href="#bun_compile-emit_dce_annotations">emit_dce_annotations</a>, <a href="#bun_compile-entry_naming">entry_naming</a>, <a href="#bun_compile-entry_point">entry_point</a>, <a href="#bun_compile-env">env</a>,
<a href="#bun_compile-external">external</a>, <a href="#bun_compile-feature">feature</a>, <a href="#bun_compile-footer">footer</a>, <a href="#bun_compile-format">format</a>, <a href="#bun_compile-install_mode">install_mode</a>, <a href="#bun_compile-jsx_factory">jsx_factory</a>, <a href="#bun_compile-jsx_fragment">jsx_fragment</a>,
<a href="#bun_compile-jsx_import_source">jsx_import_source</a>, <a href="#bun_compile-jsx_runtime">jsx_runtime</a>, <a href="#bun_compile-jsx_side_effects">jsx_side_effects</a>, <a href="#bun_compile-keep_names">keep_names</a>, <a href="#bun_compile-loader">loader</a>, <a href="#bun_compile-minify">minify</a>,
<a href="#bun_compile-minify_identifiers">minify_identifiers</a>, <a href="#bun_compile-minify_syntax">minify_syntax</a>, <a href="#bun_compile-minify_whitespace">minify_whitespace</a>, <a href="#bun_compile-no_bundle">no_bundle</a>, <a href="#bun_compile-node_modules">node_modules</a>, <a href="#bun_compile-packages">packages</a>,
<a href="#bun_compile-production">production</a>, <a href="#bun_compile-public_path">public_path</a>, <a href="#bun_compile-react_fast_refresh">react_fast_refresh</a>, <a href="#bun_compile-root">root</a>, <a href="#bun_compile-sourcemap">sourcemap</a>, <a href="#bun_compile-splitting">splitting</a>, <a href="#bun_compile-target">target</a>,
<a href="#bun_compile-windows_copyright">windows_copyright</a>, <a href="#bun_compile-windows_description">windows_description</a>, <a href="#bun_compile-windows_hide_console">windows_hide_console</a>, <a href="#bun_compile-windows_icon">windows_icon</a>,
<a href="#bun_compile-windows_publisher">windows_publisher</a>, <a href="#bun_compile-windows_title">windows_title</a>, <a href="#bun_compile-windows_version">windows_version</a>)
</pre>
Compiles a Bun program into a standalone executable with `bun build --compile`.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="bun_compile-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="bun_compile-deps"></a>deps | Source/library dependencies that provide transitive inputs. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_compile-data"></a>data | Additional non-source files needed during building. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_compile-asset_naming"></a>asset_naming | Optional asset naming template. | String | optional | `""` |
| <a id="bun_compile-banner"></a>banner | Optional bundle banner text. | String | optional | `""` |
| <a id="bun_compile-build_flags"></a>build_flags | Additional raw flags forwarded to `bun build`. | List of strings | optional | `[]` |
| <a id="bun_compile-bytecode"></a>bytecode | If true, enables Bun bytecode caching in the compiled executable. | Boolean | optional | `False` |
| <a id="bun_compile-chunk_naming"></a>chunk_naming | Optional chunk naming template. | String | optional | `""` |
| <a id="bun_compile-compile_autoload_bunfig"></a>compile_autoload_bunfig | Whether the compiled executable auto-loads `bunfig.toml` at runtime. | Boolean | optional | `True` |
| <a id="bun_compile-compile_autoload_dotenv"></a>compile_autoload_dotenv | Whether the compiled executable auto-loads `.env` files at runtime. | Boolean | optional | `True` |
| <a id="bun_compile-compile_autoload_package_json"></a>compile_autoload_package_json | Whether the compiled executable auto-loads `package.json` at runtime. | Boolean | optional | `False` |
| <a id="bun_compile-compile_autoload_tsconfig"></a>compile_autoload_tsconfig | Whether the compiled executable auto-loads `tsconfig.json` at runtime. | Boolean | optional | `False` |
| <a id="bun_compile-compile_exec_argv"></a>compile_exec_argv | Repeated `--compile-exec-argv` values prepended to the executable's `execArgv`. | List of strings | optional | `[]` |
| <a id="bun_compile-compile_executable"></a>compile_executable | Optional Bun executable used for cross-compilation via `--compile-executable-path`. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="bun_compile-conditions"></a>conditions | Custom resolve conditions passed to Bun. | List of strings | optional | `[]` |
| <a id="bun_compile-css_chunking"></a>css_chunking | If true, Bun chunks CSS across multiple entry points. | Boolean | optional | `False` |
| <a id="bun_compile-define"></a>define | Repeated `--define` values such as `process.env.NODE_ENV:"production"`. | List of strings | optional | `[]` |
| <a id="bun_compile-drop"></a>drop | Repeated `--drop` values, for example `console`. | List of strings | optional | `[]` |
| <a id="bun_compile-emit_dce_annotations"></a>emit_dce_annotations | If true, re-emits DCE annotations in the bundle. | Boolean | optional | `False` |
| <a id="bun_compile-entry_naming"></a>entry_naming | Optional entry naming template. | String | optional | `""` |
| <a id="bun_compile-entry_point"></a>entry_point | Entry file to compile into an executable. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="bun_compile-env"></a>env | Inline environment variable behavior passed to `--env`. | String | optional | `""` |
| <a id="bun_compile-external"></a>external | Modules treated as externals (not bundled). | List of strings | optional | `[]` |
| <a id="bun_compile-feature"></a>feature | Repeated `--feature` values for dead-code elimination. | List of strings | optional | `[]` |
| <a id="bun_compile-footer"></a>footer | Optional bundle footer text. | String | optional | `""` |
| <a id="bun_compile-format"></a>format | Output module format. | String | optional | `"esm"` |
| <a id="bun_compile-install_mode"></a>install_mode | Whether Bun may auto-install missing packages while executing the build. Hermetic compile actions require `\"disable\"`, and other values are rejected. | String | optional | `"disable"` |
| <a id="bun_compile-jsx_factory"></a>jsx_factory | Optional JSX factory override. | String | optional | `""` |
| <a id="bun_compile-jsx_fragment"></a>jsx_fragment | Optional JSX fragment override. | String | optional | `""` |
| <a id="bun_compile-jsx_import_source"></a>jsx_import_source | Optional JSX import source override. | String | optional | `""` |
| <a id="bun_compile-jsx_runtime"></a>jsx_runtime | Optional JSX runtime override. | String | optional | `""` |
| <a id="bun_compile-jsx_side_effects"></a>jsx_side_effects | If true, treats JSX as having side effects. | Boolean | optional | `False` |
| <a id="bun_compile-keep_names"></a>keep_names | If true, preserves function and class names when minifying. | Boolean | optional | `False` |
| <a id="bun_compile-loader"></a>loader | Repeated `--loader` values such as `.svg:file`. | List of strings | optional | `[]` |
| <a id="bun_compile-minify"></a>minify | If true, enables all Bun minification passes. | Boolean | optional | `False` |
| <a id="bun_compile-minify_identifiers"></a>minify_identifiers | If true, minifies identifiers only. | Boolean | optional | `False` |
| <a id="bun_compile-minify_syntax"></a>minify_syntax | If true, minifies syntax only. | Boolean | optional | `False` |
| <a id="bun_compile-minify_whitespace"></a>minify_whitespace | If true, minifies whitespace only. | Boolean | optional | `False` |
| <a id="bun_compile-no_bundle"></a>no_bundle | If true, transpiles without bundling. | Boolean | optional | `False` |
| <a id="bun_compile-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, for package resolution. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="bun_compile-packages"></a>packages | Whether packages stay bundled or are treated as external. | String | optional | `"bundle"` |
| <a id="bun_compile-production"></a>production | If true, sets `NODE_ENV=production` and enables Bun production mode. | Boolean | optional | `False` |
| <a id="bun_compile-public_path"></a>public_path | Optional public path prefix for emitted imports. | String | optional | `""` |
| <a id="bun_compile-react_fast_refresh"></a>react_fast_refresh | If true, enables Bun's React fast refresh transform. | Boolean | optional | `False` |
| <a id="bun_compile-root"></a>root | Optional root directory for multiple entry points. | String | optional | `""` |
| <a id="bun_compile-sourcemap"></a>sourcemap | Sourcemap emission mode. | String | optional | `"none"` |
| <a id="bun_compile-splitting"></a>splitting | If true, enables code splitting. | Boolean | optional | `False` |
| <a id="bun_compile-target"></a>target | Bun build target environment for the compiled executable. | String | optional | `"bun"` |
| <a id="bun_compile-windows_copyright"></a>windows_copyright | Optional Windows copyright metadata. | String | optional | `""` |
| <a id="bun_compile-windows_description"></a>windows_description | Optional Windows description metadata. | String | optional | `""` |
| <a id="bun_compile-windows_hide_console"></a>windows_hide_console | When targeting Windows, hides the console window for GUI-style executables. | Boolean | optional | `False` |
| <a id="bun_compile-windows_icon"></a>windows_icon | Optional Windows icon path passed directly to Bun. | String | optional | `""` |
| <a id="bun_compile-windows_publisher"></a>windows_publisher | Optional Windows publisher metadata. | String | optional | `""` |
| <a id="bun_compile-windows_title"></a>windows_title | Optional Windows executable title. | String | optional | `""` |
| <a id="bun_compile-windows_version"></a>windows_version | Optional Windows version metadata. | String | optional | `""` |
<a id="bun_dev"></a>
## bun_dev
<pre>
load("@rules_bun//bun:defs.bzl", "bun_dev")
bun_dev(<a href="#bun_dev-name">name</a>, <a href="#bun_dev-data">data</a>, <a href="#bun_dev-conditions">conditions</a>, <a href="#bun_dev-entry_point">entry_point</a>, <a href="#bun_dev-env_files">env_files</a>, <a href="#bun_dev-install_mode">install_mode</a>, <a href="#bun_dev-no_clear_screen">no_clear_screen</a>, <a href="#bun_dev-no_env_file">no_env_file</a>,
<a href="#bun_dev-node_modules">node_modules</a>, <a href="#bun_dev-preload">preload</a>, <a href="#bun_dev-restart_on">restart_on</a>, <a href="#bun_dev-run_flags">run_flags</a>, <a href="#bun_dev-smol">smol</a>, <a href="#bun_dev-watch_mode">watch_mode</a>, <a href="#bun_dev-working_dir">working_dir</a>)
</pre>
Runs a JS/TS entry point in Bun development watch mode.
This rule is intended for local dev loops (`bazel run`) and supports Bun
watch/HMR plus optional full restarts on selected file changes.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="bun_dev-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="bun_dev-data"></a>data | Additional runtime files required by the dev process. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_dev-conditions"></a>conditions | Custom package resolve conditions passed to Bun. | List of strings | optional | `[]` |
| <a id="bun_dev-entry_point"></a>entry_point | Path to the main JS/TS file to execute in dev mode. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="bun_dev-env_files"></a>env_files | Additional environment files loaded with `--env-file`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_dev-install_mode"></a>install_mode | Whether Bun may auto-install missing packages in dev mode. This is a local workflow helper, not a hermetic execution surface. | String | optional | `"disable"` |
| <a id="bun_dev-inherit_host_path"></a>inherit_host_path | If true, appends the host PATH after the staged Bun runtime tool bin and `node_modules/.bin` entries at runtime. | Boolean | optional | `False` |
| <a id="bun_dev-no_clear_screen"></a>no_clear_screen | If true, disables terminal clearing on Bun reloads. | Boolean | optional | `False` |
| <a id="bun_dev-no_env_file"></a>no_env_file | If true, disables Bun's automatic `.env` loading. | Boolean | optional | `False` |
| <a id="bun_dev-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="bun_dev-preload"></a>preload | Modules to preload with `--preload` before running the entry point. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_dev-restart_on"></a>restart_on | Files that trigger a full Bun process restart when they change. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_dev-run_flags"></a>run_flags | Additional raw flags forwarded to `bun run` before the entry point. | List of strings | optional | `[]` |
| <a id="bun_dev-smol"></a>smol | If true, enables Bun's lower-memory runtime mode. | Boolean | optional | `False` |
| <a id="bun_dev-watch_mode"></a>watch_mode | Bun live-reload mode: `watch` (default) or `hot`. | String | optional | `"watch"` |
| <a id="bun_dev-working_dir"></a>working_dir | Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`. | String | optional | `"workspace"` |
<a id="bun_script"></a>
## bun_script
<pre>
load("@rules_bun//bun:defs.bzl", "bun_script")
bun_script(<a href="#bun_script-name">name</a>, <a href="#bun_script-data">data</a>, <a href="#bun_script-conditions">conditions</a>, <a href="#bun_script-env_files">env_files</a>, <a href="#bun_script-execution_mode">execution_mode</a>, <a href="#bun_script-filters">filters</a>, <a href="#bun_script-install_mode">install_mode</a>, <a href="#bun_script-no_env_file">no_env_file</a>,
<a href="#bun_script-no_exit_on_error">no_exit_on_error</a>, <a href="#bun_script-node_modules">node_modules</a>, <a href="#bun_script-package_json">package_json</a>, <a href="#bun_script-preload">preload</a>, <a href="#bun_script-run_flags">run_flags</a>, <a href="#bun_script-script">script</a>, <a href="#bun_script-shell">shell</a>, <a href="#bun_script-silent">silent</a>,
<a href="#bun_script-smol">smol</a>, <a href="#bun_script-working_dir">working_dir</a>, <a href="#bun_script-workspaces">workspaces</a>)
</pre>
Runs a named `package.json` script with Bun as an executable target.
Use this rule to expose existing package scripts such as `dev`, `build`, or
`check` via `bazel run` without adding wrapper shell scripts. This is a good fit
for Vite-style workflows, where scripts like `vite dev` or `vite build` are
declared in `package.json` and expect to run from the package directory with
the staged Bun runtime tool bin and `node_modules/.bin` available on `PATH`.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="bun_script-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="bun_script-data"></a>data | Additional runtime files required by the script. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_script-conditions"></a>conditions | Custom package resolve conditions passed to Bun. | List of strings | optional | `[]` |
| <a id="bun_script-env_files"></a>env_files | Additional environment files loaded with `--env-file`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_script-execution_mode"></a>execution_mode | How Bun should execute matching workspace scripts. | String | optional | `"single"` |
| <a id="bun_script-filters"></a>filters | Workspace package filters passed via repeated `--filter` flags. | List of strings | optional | `[]` |
| <a id="bun_script-install_mode"></a>install_mode | Whether Bun may auto-install missing packages while running the script. This is a local workflow helper, not a hermetic execution surface. | String | optional | `"disable"` |
| <a id="bun_script-inherit_host_path"></a>inherit_host_path | If true, appends the host PATH after the staged Bun runtime tool bin and `node_modules/.bin` entries at runtime. | Boolean | optional | `False` |
| <a id="bun_script-no_env_file"></a>no_env_file | If true, disables Bun's automatic `.env` loading. | Boolean | optional | `False` |
| <a id="bun_script-no_exit_on_error"></a>no_exit_on_error | If true, Bun keeps running other workspace scripts when one fails. | Boolean | optional | `False` |
| <a id="bun_script-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles. The staged Bun runtime tool bin and executables from `node_modules/.bin` are added to `PATH`, which is useful for scripts such as `vite`. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="bun_script-package_json"></a>package_json | Label of the `package.json` file containing the named script. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="bun_script-preload"></a>preload | Modules to preload with `--preload` before running the script. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_script-run_flags"></a>run_flags | Additional raw flags forwarded to `bun run` before the script name. | List of strings | optional | `[]` |
| <a id="bun_script-script"></a>script | Name of the `package.json` script to execute via `bun run <script>`. | String | required | |
| <a id="bun_script-shell"></a>shell | Optional shell implementation for package scripts. | String | optional | `""` |
| <a id="bun_script-silent"></a>silent | If true, suppresses Bun's command echo for package scripts. | Boolean | optional | `False` |
| <a id="bun_script-smol"></a>smol | If true, enables Bun's lower-memory runtime mode. | Boolean | optional | `False` |
| <a id="bun_script-working_dir"></a>working_dir | Working directory at runtime: Bazel runfiles `workspace` root or the directory containing `package.json`. The default `package` mode matches tools such as Vite that resolve config and assets relative to the package directory. | String | optional | `"package"` |
| <a id="bun_script-workspaces"></a>workspaces | If true, runs the script in all workspace packages. | Boolean | optional | `False` |
<a id="bun_test"></a>
## bun_test
<pre>
load("@rules_bun//bun:defs.bzl", "bun_test")
bun_test(<a href="#bun_test-name">name</a>, <a href="#bun_test-deps">deps</a>, <a href="#bun_test-srcs">srcs</a>, <a href="#bun_test-data">data</a>, <a href="#bun_test-bail">bail</a>, <a href="#bun_test-concurrent">concurrent</a>, <a href="#bun_test-coverage">coverage</a>, <a href="#bun_test-coverage_reporters">coverage_reporters</a>, <a href="#bun_test-env_files">env_files</a>,
<a href="#bun_test-install_mode">install_mode</a>, <a href="#bun_test-max_concurrency">max_concurrency</a>, <a href="#bun_test-no_env_file">no_env_file</a>, <a href="#bun_test-node_modules">node_modules</a>, <a href="#bun_test-only">only</a>, <a href="#bun_test-pass_with_no_tests">pass_with_no_tests</a>, <a href="#bun_test-preload">preload</a>,
<a href="#bun_test-randomize">randomize</a>, <a href="#bun_test-reporter">reporter</a>, <a href="#bun_test-rerun_each">rerun_each</a>, <a href="#bun_test-retry">retry</a>, <a href="#bun_test-seed">seed</a>, <a href="#bun_test-smol">smol</a>, <a href="#bun_test-test_flags">test_flags</a>, <a href="#bun_test-timeout_ms">timeout_ms</a>, <a href="#bun_test-todo">todo</a>,
<a href="#bun_test-update_snapshots">update_snapshots</a>)
</pre>
Runs Bun tests as a Bazel test target.
Supports Bazel test filtering (`--test_filter`) and coverage integration.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="bun_test-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="bun_test-deps"></a>deps | Library dependencies required by test sources. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_test-srcs"></a>srcs | Test source files passed to `bun test`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
| <a id="bun_test-data"></a>data | Additional runtime files needed by tests. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_test-bail"></a>bail | Optional failure count after which Bun exits the test run. | Integer | optional | `0` |
| <a id="bun_test-concurrent"></a>concurrent | If true, treats all tests as concurrent tests. | Boolean | optional | `False` |
| <a id="bun_test-coverage"></a>coverage | If true, always enables Bun coverage output. | Boolean | optional | `False` |
| <a id="bun_test-coverage_reporters"></a>coverage_reporters | Repeated Bun coverage reporters such as `text` or `lcov`. | List of strings | optional | `[]` |
| <a id="bun_test-env_files"></a>env_files | Additional environment files loaded with `--env-file`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_test-install_mode"></a>install_mode | Whether Bun may auto-install missing packages while testing. Hermetic tests require `\"disable\"`, and other values are rejected. | String | optional | `"disable"` |
| <a id="bun_test-inherit_host_path"></a>inherit_host_path | If true, appends the host PATH after the staged Bun runtime tool bin and `node_modules/.bin` entries at runtime. | Boolean | optional | `False` |
| <a id="bun_test-max_concurrency"></a>max_concurrency | Optional maximum number of concurrent tests. | Integer | optional | `0` |
| <a id="bun_test-no_env_file"></a>no_env_file | If true, disables Bun's automatic `.env` loading. | Boolean | optional | `False` |
| <a id="bun_test-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="bun_test-only"></a>only | If true, runs only tests marked with `test.only()` or `describe.only()`. | Boolean | optional | `False` |
| <a id="bun_test-pass_with_no_tests"></a>pass_with_no_tests | If true, exits successfully when no tests are found. | Boolean | optional | `False` |
| <a id="bun_test-preload"></a>preload | Modules to preload with `--preload` before running tests. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="bun_test-randomize"></a>randomize | If true, runs tests in random order. | Boolean | optional | `False` |
| <a id="bun_test-reporter"></a>reporter | Test reporter format. | String | optional | `"console"` |
| <a id="bun_test-rerun_each"></a>rerun_each | Optional number of times to rerun each test file. | Integer | optional | `0` |
| <a id="bun_test-retry"></a>retry | Optional default retry count for all tests. | Integer | optional | `0` |
| <a id="bun_test-seed"></a>seed | Optional randomization seed. | Integer | optional | `0` |
| <a id="bun_test-smol"></a>smol | If true, enables Bun's lower-memory runtime mode. | Boolean | optional | `False` |
| <a id="bun_test-test_flags"></a>test_flags | Additional raw flags forwarded to `bun test` before the test source list. | List of strings | optional | `[]` |
| <a id="bun_test-timeout_ms"></a>timeout_ms | Optional per-test timeout in milliseconds. | Integer | optional | `0` |
| <a id="bun_test-todo"></a>todo | If true, includes tests marked with `test.todo()`. | Boolean | optional | `False` |
| <a id="bun_test-update_snapshots"></a>update_snapshots | If true, updates Bun snapshot files. | Boolean | optional | `False` |
<a id="js_library"></a>
## js_library
<pre>
load("@rules_bun//bun:defs.bzl", "js_library")
js_library(<a href="#js_library-name">name</a>, <a href="#js_library-deps">deps</a>, <a href="#js_library-srcs">srcs</a>, <a href="#js_library-data">data</a>, <a href="#js_library-types">types</a>)
</pre>
Aggregates JavaScript sources and transitive Bun source dependencies.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="js_library-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="js_library-deps"></a>deps | Other Bun source libraries to include transitively. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="js_library-srcs"></a>srcs | JavaScript source files in this library. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="js_library-data"></a>data | Optional runtime files propagated to dependents. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="js_library-types"></a>types | Optional declaration files associated with this library. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
<a id="js_run_devserver"></a>
## js_run_devserver
<pre>
load("@rules_bun//bun:defs.bzl", "js_run_devserver")
js_run_devserver(<a href="#js_run_devserver-name">name</a>, <a href="#js_run_devserver-deps">deps</a>, <a href="#js_run_devserver-data">data</a>, <a href="#js_run_devserver-node_modules">node_modules</a>, <a href="#js_run_devserver-package_dir_hint">package_dir_hint</a>, <a href="#js_run_devserver-package_json">package_json</a>, <a href="#js_run_devserver-tool">tool</a>, <a href="#js_run_devserver-working_dir">working_dir</a>)
</pre>
Runs an executable target from a staged JS workspace.
This is a Bun-backed compatibility adapter for `rules_js`-style devserver
targets. It stages the same runtime workspace as the Bun rules, then executes
the provided tool with any default arguments.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="js_run_devserver-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="js_run_devserver-deps"></a>deps | Library dependencies required by the dev server. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="js_run_devserver-data"></a>data | Additional runtime files required by the dev server. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="js_run_devserver-node_modules"></a>node_modules | Optional label providing package files from a node_modules tree, typically produced by bun_install or npm_translate_lock, in runfiles. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="js_run_devserver-package_dir_hint"></a>package_dir_hint | Optional package-relative directory hint when package_json is not supplied. | String | optional | `"."` |
| <a id="js_run_devserver-package_json"></a>package_json | Optional package.json used to resolve the package working directory. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="js_run_devserver-tool"></a>tool | Executable target to launch as the dev server. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="js_run_devserver-inherit_host_path"></a>inherit_host_path | If true, appends the host PATH after the staged Bun runtime tool bin and `node_modules/.bin` entries at runtime. | Boolean | optional | `False` |
| <a id="js_run_devserver-working_dir"></a>working_dir | Working directory at runtime: Bazel runfiles workspace root or the resolved package directory. | String | optional | `"workspace"` |
<a id="ts_library"></a>
## ts_library
<pre>
load("@rules_bun//bun:defs.bzl", "ts_library")
ts_library(<a href="#ts_library-name">name</a>, <a href="#ts_library-deps">deps</a>, <a href="#ts_library-srcs">srcs</a>, <a href="#ts_library-data">data</a>, <a href="#ts_library-types">types</a>)
</pre>
Aggregates TypeScript sources and transitive Bun source dependencies.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="ts_library-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="ts_library-deps"></a>deps | Other Bun source libraries to include transitively. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="ts_library-srcs"></a>srcs | TypeScript source files in this library. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="ts_library-data"></a>data | Optional runtime files propagated to dependents. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="ts_library-types"></a>types | Optional declaration files associated with this library. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
<a id="js_binary"></a>
## js_binary
<pre>
load("@rules_bun//bun:defs.bzl", "js_binary")
js_binary(<a href="#js_binary-name">name</a>, <a href="#js_binary-kwargs">**kwargs</a>)
</pre>
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="js_binary-name"></a>name | <p align="center"> - </p> | none |
| <a id="js_binary-kwargs"></a>kwargs | <p align="center"> - </p> | none |
<a id="js_test"></a>
## js_test
<pre>
load("@rules_bun//bun:defs.bzl", "js_test")
js_test(<a href="#js_test-name">name</a>, <a href="#js_test-entry_point">entry_point</a>, <a href="#js_test-srcs">srcs</a>, <a href="#js_test-kwargs">**kwargs</a>)
</pre>
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="js_test-name"></a>name | <p align="center"> - </p> | none |
| <a id="js_test-entry_point"></a>entry_point | <p align="center"> - </p> | `None` |
| <a id="js_test-srcs"></a>srcs | <p align="center"> - </p> | `None` |
| <a id="js_test-kwargs"></a>kwargs | <p align="center"> - </p> | none |

View File

@@ -1,21 +1,5 @@
load("//bun:defs.bzl", "bun_dev")
package(default_visibility = ["//visibility:public"])
exports_files([
"README.md",
"main.ts",
])
bun_dev(
name = "web_dev",
entry_point = "main.ts",
)
bun_dev(
name = "web_dev_hot_restart",
entry_point = "main.ts",
no_clear_screen = True,
restart_on = ["README.md"],
watch_mode = "hot",
)

View File

@@ -1,20 +1,3 @@
# basic example
Minimal `bun_dev` example.
Run:
```bash
bazel run //examples/basic:web_dev
```
This starts Bun in watch mode for `main.ts`.
For the hot-reload launcher variant:
```bash
bazel run //examples/basic:web_dev_hot_restart
```
This starts Bun with `watch_mode = "hot"`, disables screen clearing, and wires
`README.md` through `restart_on` to exercise the custom restart launcher path.
Placeholder for end-to-end bun rules example.

View File

@@ -1 +0,0 @@
console.log("rules_bun bun_dev example");

View File

@@ -1 +0,0 @@
bazel-*

View File

@@ -1,61 +0,0 @@
load("@rules_bun//bun:defs.bzl", "bun_script")
# //:BUILD.bazel
load("@rules_multirun//:defs.bzl", "multirun")
load("@rules_shell//shell:sh_test.bzl", "sh_test")
package(default_visibility = ["//visibility:public"])
exports_files([
"README.md",
"package.json",
"bun.lock",
"apps/app-a/package.json",
"apps/app-b/package.json",
])
multirun(
name = "dev",
commands = [
":app_a_dev",
":app_b_dev",
],
jobs = 0,
)
bun_script(
name = "app_a_dev",
data = [
"apps/app-a/index.html",
"apps/app-a/main.js",
"apps/app-a/vite.config.js",
],
node_modules = "@node_modules//:node_modules",
package_json = "apps/app-a/package.json",
script = "dev",
)
bun_script(
name = "app_b_dev",
data = [
"apps/app-b/index.html",
"apps/app-b/main.js",
"apps/app-b/vite.config.js",
],
node_modules = "@node_modules//:node_modules",
package_json = "apps/app-b/package.json",
script = "dev",
)
sh_test(
name = "vite_monorepo_workspace_resolution_test",
srcs = ["run_vite_monorepo_apps.sh"],
args = [
"$(location :app_a_dev)",
"$(location :app_b_dev)",
],
data = [
":app_a_dev",
":app_b_dev",
],
)

View File

@@ -1,39 +0,0 @@
module(
name = "rules_bun_example_vite_monorepo",
version = "0.1.0",
)
bazel_dep(name = "rules_bun", version = "0.2.2")
bazel_dep(name = "rules_multirun", version = "0.9.0")
bazel_dep(name = "rules_shell", version = "0.6.1")
local_path_override(
module_name = "rules_bun",
path = "../..",
)
bun_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun")
use_repo(
bun_ext,
"bun_darwin_aarch64",
"bun_darwin_x64",
"bun_linux_aarch64",
"bun_linux_x64",
"bun_windows_x64",
)
register_toolchains(
"@rules_bun//bun:darwin_aarch64_toolchain",
"@rules_bun//bun:darwin_x64_toolchain",
"@rules_bun//bun:linux_aarch64_toolchain",
"@rules_bun//bun:linux_x64_toolchain",
"@rules_bun//bun:windows_x64_toolchain",
)
bun_install_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun_install")
bun_install_ext.install(
name = "npm",
bun_lockfile = "//:bun.lock",
package_json = "//:package.json",
)
use_repo(bun_install_ext, node_modules = "npm")

View File

@@ -1,531 +0,0 @@
{
"lockFileVersion": 26,
"registryFileHashes": {
"https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
"https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
"https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16",
"https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1",
"https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215",
"https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2",
"https://bcr.bazel.build/modules/abseil-cpp/20250814.1/source.json": "cea3901d7e299da7320700abbaafe57a65d039f10d0d7ea601c4a66938ea4b0c",
"https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896",
"https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85",
"https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e",
"https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1",
"https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4",
"https://bcr.bazel.build/modules/apple_support/1.24.2/source.json": "2c22c9827093250406c5568da6c54e6fdf0ef06238def3d99c71b12feb057a8d",
"https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
"https://bcr.bazel.build/modules/bazel_features/1.10.0/MODULE.bazel": "f75e8807570484a99be90abcd52b5e1f390362c258bcb73106f4544957a48101",
"https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
"https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
"https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
"https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
"https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
"https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
"https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a",
"https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65",
"https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d",
"https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9",
"https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
"https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6",
"https://bcr.bazel.build/modules/bazel_features/1.33.0/source.json": "13617db3930328c2cd2807a0f13d52ca870ac05f96db9668655113265147b2a6",
"https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
"https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
"https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
"https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
"https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
"https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6",
"https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67",
"https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb",
"https://bcr.bazel.build/modules/buildozer/8.2.1/MODULE.bazel": "61e9433c574c2bd9519cad7fa66b9c1d2b8e8d5f3ae5d6528a2c2d26e68d874d",
"https://bcr.bazel.build/modules/buildozer/8.2.1/source.json": "7c33f6a26ee0216f85544b4bca5e9044579e0219b6898dd653f5fb449cf2e484",
"https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
"https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
"https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108",
"https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46",
"https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
"https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0",
"https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000",
"https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
"https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74",
"https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9",
"https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
"https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
"https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
"https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
"https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
"https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580",
"https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96",
"https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
"https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
"https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
"https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
"https://bcr.bazel.build/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95",
"https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
"https://bcr.bazel.build/modules/protobuf/32.1/MODULE.bazel": "89cd2866a9cb07fee9ff74c41ceace11554f32e0d849de4e23ac55515cfada4d",
"https://bcr.bazel.build/modules/protobuf/33.4/MODULE.bazel": "114775b816b38b6d0ca620450d6b02550c60ceedfdc8d9a229833b34a223dc42",
"https://bcr.bazel.build/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79",
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
"https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34",
"https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680",
"https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
"https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a",
"https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4",
"https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa",
"https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
"https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
"https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a",
"https://bcr.bazel.build/modules/rules_apple/4.1.0/MODULE.bazel": "76e10fd4a48038d3fc7c5dc6e63b7063bbf5304a2e3bd42edda6ec660eebea68",
"https://bcr.bazel.build/modules/rules_apple/4.1.0/source.json": "8ee81e1708756f81b343a5eb2b2f0b953f1d25c4ab3d4a68dc02754872e80715",
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
"https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
"https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
"https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
"https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
"https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
"https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
"https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0",
"https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8",
"https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c",
"https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37",
"https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8",
"https://bcr.bazel.build/modules/rules_cc/0.2.14/source.json": "55d0a4587c5592fad350f6e698530f4faf0e7dd15e69d43f8d87e220c78bea54",
"https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642",
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
"https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
"https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
"https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
"https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
"https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
"https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
"https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
"https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
"https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
"https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2",
"https://bcr.bazel.build/modules/rules_java/9.0.3/MODULE.bazel": "1f98ed015f7e744a745e0df6e898a7c5e83562d6b759dfd475c76456dda5ccea",
"https://bcr.bazel.build/modules/rules_java/9.0.3/source.json": "b038c0c07e12e658135bbc32cc1a2ded6e33785105c9d41958014c592de4593e",
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
"https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
"https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
"https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
"https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd",
"https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
"https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
"https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
"https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
"https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
"https://bcr.bazel.build/modules/rules_multirun/0.9.0/MODULE.bazel": "32d628ef586b5b23f67e55886b7bc38913ea4160420d66ae90521dda2ff37df0",
"https://bcr.bazel.build/modules/rules_multirun/0.9.0/source.json": "e882ba77962fa6c5fe68619e5c7d0374ec9a219fb8d03c42eadaf6d0243771bd",
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
"https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
"https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483",
"https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
"https://bcr.bazel.build/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96",
"https://bcr.bazel.build/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e",
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
"https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
"https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
"https://bcr.bazel.build/modules/rules_python/0.27.1/MODULE.bazel": "65dc875cc1a06c30d5bbdba7ab021fd9e551a6579e408a3943a61303e2228a53",
"https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
"https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
"https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937",
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
"https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13",
"https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6",
"https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8",
"https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8",
"https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32",
"https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
"https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b",
"https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b",
"https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c",
"https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca",
"https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046",
"https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd",
"https://bcr.bazel.build/modules/rules_swift/3.1.2/MODULE.bazel": "72c8f5cf9d26427cee6c76c8e3853eb46ce6b0412a081b2b6db6e8ad56267400",
"https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66",
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
"https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
"https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
"https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
"https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b",
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806",
"https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
},
"selectedYankedVersions": {},
"moduleExtensions": {
"@@rules_bun+//bun:extensions.bzl%bun": {
"general": {
"bzlTransitiveDigest": "64B4fTkEHdAlieIOkE/Wi2M/R9lMNZhFxeI1eXEFHRs=",
"usagesDigest": "NKGlTDuQz8QyvtynGiqPQZ47pqfh7gwmp164c1kruoc=",
"recordedInputs": [
"REPO_MAPPING:rules_bun+,bazel_tools bazel_tools"
],
"generatedRepoSpecs": {
"bun_linux_x64": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-linux-x64.zip"
],
"sha256": "f57bc0187e39623de716ba3a389fda5486b2d7be7131a980ba54dc7b733d2e08",
"build_file_content": "\nexports_files([\"bun-linux-x64/bun\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-linux-x64/bun\"],\n visibility = [\"//visibility:public\"],\n)\n"
}
},
"bun_linux_aarch64": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-linux-aarch64.zip"
],
"sha256": "fa5ecb25cafa8e8f5c87a0f833719d46dd0af0a86c7837d806531212d55636d3",
"build_file_content": "\nexports_files([\"bun-linux-aarch64/bun\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-linux-aarch64/bun\"],\n visibility = [\"//visibility:public\"],\n)\n"
}
},
"bun_darwin_x64": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-darwin-x64.zip"
],
"sha256": "c1d90bf6140f20e572c473065dc6b37a4b036349b5e9e4133779cc642ad94323",
"build_file_content": "\nexports_files([\"bun-darwin-x64/bun\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-darwin-x64/bun\"],\n visibility = [\"//visibility:public\"],\n)\n"
}
},
"bun_darwin_aarch64": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-darwin-aarch64.zip"
],
"sha256": "82034e87c9d9b4398ea619aee2eed5d2a68c8157e9a6ae2d1052d84d533ccd8d",
"build_file_content": "\nexports_files([\"bun-darwin-aarch64/bun\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-darwin-aarch64/bun\"],\n visibility = [\"//visibility:public\"],\n)\n"
}
},
"bun_windows_x64": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-windows-x64.zip"
],
"sha256": "7a77b3e245e2e26965c93089a4a1332e8a326d3364c89fae1d1fd99cdd3cd73d",
"build_file_content": "\nexports_files([\"bun-windows-x64/bun.exe\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-windows-x64/bun.exe\"],\n visibility = [\"//visibility:public\"],\n)\n"
}
}
}
}
},
"@@rules_bun+//bun:extensions.bzl%bun_install": {
"general": {
"bzlTransitiveDigest": "64B4fTkEHdAlieIOkE/Wi2M/R9lMNZhFxeI1eXEFHRs=",
"usagesDigest": "7SehYeU297FzlGHTRg/G5aakC/abC14POtOr8Qy38vA=",
"recordedInputs": [
"REPO_MAPPING:rules_bun+,bazel_tools bazel_tools"
],
"generatedRepoSpecs": {
"npm": {
"repoRuleId": "@@rules_bun+//internal:bun_install.bzl%bun_install_repository",
"attributes": {
"package_json": "@@//:package.json",
"bun_lockfile": "@@//:bun.lock",
"install_inputs": [],
"isolated_home": true
}
}
}
}
},
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
"general": {
"bzlTransitiveDigest": "ABI1D/sbS1ovwaW/kHDoj8nnXjQ0oKU9fzmzEG4iT8o=",
"usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
"recordedInputs": [
"REPO_MAPPING:rules_kotlin+,bazel_tools bazel_tools"
],
"generatedRepoSpecs": {
"com_github_jetbrains_kotlin_git": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository",
"attributes": {
"urls": [
"https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
],
"sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
}
},
"com_github_jetbrains_kotlin": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository",
"attributes": {
"git_repository_name": "com_github_jetbrains_kotlin_git",
"compiler_version": "1.9.23"
}
},
"com_github_google_ksp": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository",
"attributes": {
"urls": [
"https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
],
"sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
"strip_version": "1.9.23-1.0.20"
}
},
"com_github_pinterest_ktlint": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
"attributes": {
"sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
"urls": [
"https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
],
"executable": true
}
},
"rules_android": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
"strip_prefix": "rules_android-0.1.1",
"urls": [
"https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
]
}
}
}
}
},
"@@rules_python+//python/extensions:config.bzl%config": {
"general": {
"bzlTransitiveDigest": "2hLgIvNVTLgxus0ZuXtleBe70intCfo0cHs8qvt6cdM=",
"usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=",
"recordedInputs": [
"REPO_MAPPING:rules_python+,bazel_tools bazel_tools",
"REPO_MAPPING:rules_python+,pypi__build rules_python++config+pypi__build",
"REPO_MAPPING:rules_python+,pypi__click rules_python++config+pypi__click",
"REPO_MAPPING:rules_python+,pypi__colorama rules_python++config+pypi__colorama",
"REPO_MAPPING:rules_python+,pypi__importlib_metadata rules_python++config+pypi__importlib_metadata",
"REPO_MAPPING:rules_python+,pypi__installer rules_python++config+pypi__installer",
"REPO_MAPPING:rules_python+,pypi__more_itertools rules_python++config+pypi__more_itertools",
"REPO_MAPPING:rules_python+,pypi__packaging rules_python++config+pypi__packaging",
"REPO_MAPPING:rules_python+,pypi__pep517 rules_python++config+pypi__pep517",
"REPO_MAPPING:rules_python+,pypi__pip rules_python++config+pypi__pip",
"REPO_MAPPING:rules_python+,pypi__pip_tools rules_python++config+pypi__pip_tools",
"REPO_MAPPING:rules_python+,pypi__pyproject_hooks rules_python++config+pypi__pyproject_hooks",
"REPO_MAPPING:rules_python+,pypi__setuptools rules_python++config+pypi__setuptools",
"REPO_MAPPING:rules_python+,pypi__tomli rules_python++config+pypi__tomli",
"REPO_MAPPING:rules_python+,pypi__wheel rules_python++config+pypi__wheel",
"REPO_MAPPING:rules_python+,pypi__zipp rules_python++config+pypi__zipp"
],
"generatedRepoSpecs": {
"rules_python_internal": {
"repoRuleId": "@@rules_python+//python/private:internal_config_repo.bzl%internal_config_repo",
"attributes": {
"transition_setting_generators": {},
"transition_settings": []
}
},
"pypi__build": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/e2/03/f3c8ba0a6b6e30d7d18c40faab90807c9bb5e9a1e3b2fe2008af624a9c97/build-1.2.1-py3-none-any.whl",
"sha256": "75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__click": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl",
"sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__colorama": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl",
"sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__importlib_metadata": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl",
"sha256": "30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__installer": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl",
"sha256": "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__more_itertools": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/50/e2/8e10e465ee3987bb7c9ab69efb91d867d93959095f4807db102d07995d94/more_itertools-10.2.0-py3-none-any.whl",
"sha256": "686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__packaging": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl",
"sha256": "2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__pep517": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/25/6e/ca4a5434eb0e502210f591b97537d322546e4833dcb4d470a48c375c5540/pep517-0.13.1-py3-none-any.whl",
"sha256": "31b206f67165b3536dd577c5c3f1518e8fbaf38cbc57efff8369a392feff1721",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__pip": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl",
"sha256": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__pip_tools": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/0d/dc/38f4ce065e92c66f058ea7a368a9c5de4e702272b479c0992059f7693941/pip_tools-7.4.1-py3-none-any.whl",
"sha256": "4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__pyproject_hooks": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/ae/f3/431b9d5fe7d14af7a32340792ef43b8a714e7726f1d7b69cc4e8e7a3f1d7/pyproject_hooks-1.1.0-py3-none-any.whl",
"sha256": "7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__setuptools": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/90/99/158ad0609729111163fc1f674a5a42f2605371a4cf036d0441070e2f7455/setuptools-78.1.1-py3-none-any.whl",
"sha256": "c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__tomli": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl",
"sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__wheel": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl",
"sha256": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__zipp": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/da/55/a03fd7240714916507e1fcf7ae355bd9d9ed2e6db492595f1a67f61681be/zipp-3.18.2-py3-none-any.whl",
"sha256": "dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
}
}
}
},
"@@rules_python+//python/uv:uv.bzl%uv": {
"general": {
"bzlTransitiveDigest": "ijW9KS7qsIY+yBVvJ+Nr1mzwQox09j13DnE3iIwaeTM=",
"usagesDigest": "H8dQoNZcoqP+Mu0tHZTi4KHATzvNkM5ePuEqoQdklIU=",
"recordedInputs": [
"REPO_MAPPING:rules_python+,bazel_tools bazel_tools",
"REPO_MAPPING:rules_python+,platforms platforms"
],
"generatedRepoSpecs": {
"uv": {
"repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo",
"attributes": {
"toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'",
"toolchain_names": [
"none"
],
"toolchain_implementations": {
"none": "'@@rules_python+//python:none'"
},
"toolchain_compatible_with": {
"none": [
"@platforms//:incompatible"
]
},
"toolchain_target_settings": {}
}
}
}
}
}
},
"facts": {}
}

View File

@@ -1,28 +0,0 @@
# Vite monorepo example
Bun workspace-style example with two Vite applications sharing one root
`bun_install` dependency installation.
Apps:
- `apps/app-a`
- `apps/app-b`
This example also exercises Bun's workspace catalog syntax:
- `workspaces.catalog` provides the default `vite` version referenced as `catalog:`
- `workspaces.catalogs.testing` provides a named catalog referenced as `catalog:testing`
Both apps run `vite` via their own `package.json` scripts while sharing the same
generated `node_modules/` tree.
Run either app with Bazel:
```bash
bazel run //examples/vite_monorepo:app_a_dev -- --host 127.0.0.1 --port 5173 --strictPort
bazel run //examples/vite_monorepo:app_b_dev -- --host 127.0.0.1 --port 5174 --strictPort
```
This example maps its `bun_install` output to the canonical `@node_modules`
repository name in `MODULE.bazel`, so `bun_script` targets don't need to hard-
code a generated repository name.

View File

@@ -1,12 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite monorepo app A</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/main.js"></script>
</body>
</html>

View File

@@ -1,7 +0,0 @@
const app = document.querySelector("#app");
if (app) {
app.textContent = "Hello from monorepo app A";
}
console.log("Hello from monorepo app A");

View File

@@ -1,11 +0,0 @@
{
"name": "vite-monorepo-app-a",
"private": true,
"type": "module",
"scripts": {
"dev": "vite"
},
"devDependencies": {
"vite": "catalog:"
}
}

View File

@@ -1 +0,0 @@
export default {};

View File

@@ -1,12 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite monorepo app B</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/main.js"></script>
</body>
</html>

View File

@@ -1,9 +0,0 @@
import { nanoid } from "nanoid";
const app = document.querySelector("#app");
if (app) {
const id = nanoid();
app.textContent = "Hello from monorepo app B " + id;
}
console.log("Hello from monorepo app B");

View File

@@ -1,15 +0,0 @@
{
"name": "vite-monorepo-app-b",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --port 5174"
},
"dependencies": {
"nanoid": "5.1.6"
},
"devDependencies": {
"vite": "catalog:",
"vitest": "catalog:testing"
}
}

View File

@@ -1 +0,0 @@
export default {};

View File

@@ -1,234 +0,0 @@
{
"lockfileVersion": 1,
"configVersion": 1,
"workspaces": {
"": {
"name": "vite-monorepo-test",
},
"apps/app-a": {
"name": "vite-monorepo-app-a",
"devDependencies": {
"vite": "catalog:",
},
},
"apps/app-b": {
"name": "vite-monorepo-app-b",
"dependencies": {
"nanoid": "5.1.6",
},
"devDependencies": {
"vite": "catalog:",
"vitest": "catalog:testing",
},
},
},
"catalog": {
"vite": "5.4.14",
},
"catalogs": {
"testing": {
"vitest": "3.2.4",
},
},
"packages": {
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
"@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="],
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q=="],
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg=="],
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w=="],
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.59.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA=="],
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.59.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg=="],
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw=="],
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA=="],
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA=="],
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA=="],
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg=="],
"@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q=="],
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA=="],
"@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA=="],
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg=="],
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg=="],
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.59.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w=="],
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg=="],
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg=="],
"@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.59.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ=="],
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.59.0", "", { "os": "none", "cpu": "arm64" }, "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA=="],
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A=="],
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.59.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA=="],
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA=="],
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA=="],
"@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
"@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
"@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
"@vitest/mocker": ["@vitest/mocker@3.2.4", "", { "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ=="],
"@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="],
"@vitest/runner": ["@vitest/runner@3.2.4", "", { "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" } }, "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ=="],
"@vitest/snapshot": ["@vitest/snapshot@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ=="],
"@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="],
"@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="],
"assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
"cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
"chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="],
"check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="],
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
"deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],
"es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="],
"esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
"estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
"expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
"loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="],
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
"pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
"postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="],
"rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="],
"siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
"std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
"strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="],
"tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
"tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
"tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="],
"tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="],
"tinyspy": ["tinyspy@4.0.4", "", {}, "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q=="],
"vite": ["vite@5.4.14", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA=="],
"vite-monorepo-app-a": ["vite-monorepo-app-a@workspace:apps/app-a"],
"vite-monorepo-app-b": ["vite-monorepo-app-b@workspace:apps/app-b"],
"vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="],
"vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="],
"why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
"postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
}
}

View File

@@ -1,17 +0,0 @@
{
"name": "vite-monorepo-test",
"private": true,
"workspaces": {
"packages": [
"apps/*"
],
"catalog": {
"vite": "5.4.14"
},
"catalogs": {
"testing": {
"vitest": "3.2.4"
}
}
}
}

View File

@@ -1,90 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
app_a_binary="$1"
app_b_binary="$2"
workdir="$(mktemp -d)"
server_pid=""
log_file=""
cleanup() {
if [[ -n ${server_pid} ]] && kill -0 "${server_pid}" 2>/dev/null; then
kill "${server_pid}" 2>/dev/null || true
wait "${server_pid}" 2>/dev/null || true
fi
rm -rf "${workdir}"
}
trap cleanup EXIT
pick_port() {
python3 - <<'PY'
import socket
sock = socket.socket()
sock.bind(("127.0.0.1", 0))
print(sock.getsockname()[1])
sock.close()
PY
}
matches_expected_js() {
local content="$1"
local expected="$2"
if [[ ${expected} == *"*"* ]]; then
local regex
regex="$(printf '%s' "${expected}" | sed -e 's/[][(){}.+?^$|\\]/\\&/g' -e 's/\*/.*/g')"
printf '%s' "${content}" | grep -Eq "${regex}"
else
printf '%s' "${content}" | grep -Fq "${expected}"
fi
}
verify_vite_app() {
local binary="$1"
local expected_title="$2"
local expected_js="$3"
local log_name="$4"
local port
local main_js
port="$(pick_port)"
log_file="${workdir}/${log_name}.log"
"${binary}" --host 127.0.0.1 --port "${port}" --strictPort >"${log_file}" 2>&1 &
server_pid=$!
for _ in {1..60}; do
if ! kill -0 "${server_pid}" 2>/dev/null; then
cat "${log_file}" >&2
echo "Vite server exited unexpectedly for ${log_name}" >&2
exit 1
fi
if curl --fail --silent "http://127.0.0.1:${port}/" | grep -Fq "${expected_title}"; then
break
fi
sleep 0.5
done
if ! curl --fail --silent "http://127.0.0.1:${port}/" | grep -Fq "${expected_title}"; then
cat "${log_file}" >&2
echo "Timed out waiting for Vite index page for ${log_name}" >&2
exit 1
fi
main_js="$(curl --fail --silent "http://127.0.0.1:${port}/main.js")"
if ! matches_expected_js "${main_js}" "${expected_js}"; then
cat "${log_file}" >&2
echo "Expected Vite module output was not served for ${log_name}" >&2
exit 1
fi
kill "${server_pid}" 2>/dev/null || true
wait "${server_pid}" 2>/dev/null || true
server_pid=""
}
verify_vite_app "${app_a_binary}" "Vite monorepo app A" "Hello from monorepo app A" "app-a"
verify_vite_app "${app_b_binary}" "Vite monorepo app B" "Hello from monorepo app B *" "app-b"

View File

@@ -1,22 +0,0 @@
load("//bun:defs.bzl", "bun_bundle", "ts_library")
package(default_visibility = ["//visibility:public"])
exports_files([
"README.md",
"package.json",
"packages/pkg-a/package.json",
"packages/pkg-b/package.json",
])
ts_library(
name = "pkg_a_lib",
srcs = ["packages/pkg-a/index.ts"],
)
bun_bundle(
name = "pkg_b_bundle",
entry_points = ["packages/pkg-b/main.ts"],
deps = [":pkg_a_lib"],
target = "bun",
)

View File

@@ -1,14 +0,0 @@
# workspace example
Minimal Bun workspace-style layout with two packages:
- `@workspace/pkg-a`: exports a string helper
- `@workspace/pkg-b`: imports from `pkg-a` and prints the message
The workspace root also defines a Bun `catalog` pin for `lodash`, and both packages consume it via `"lodash": "catalog:"` to keep versions consistent across packages.
This example demonstrates building a target from a workspace-shaped directory tree with Bazel:
```bash
bazel build //examples/workspace:pkg_b_bundle
```

View File

@@ -1,10 +0,0 @@
{
"name": "workspace-root",
"private": true,
"workspaces": [
"packages/*"
],
"catalog": {
"lodash": "^4.17.21"
}
}

View File

@@ -1,3 +0,0 @@
export function workspaceMessage(): string {
return "workspace-pkg-a";
}

View File

@@ -1,8 +0,0 @@
{
"name": "@workspace/pkg-a",
"version": "1.0.0",
"main": "index.ts",
"dependencies": {
"lodash": "catalog:"
}
}

View File

@@ -1,3 +0,0 @@
import { workspaceMessage } from "../pkg-a/index";
console.log(`hello-${workspaceMessage()}`);

View File

@@ -1,8 +0,0 @@
{
"name": "@workspace/pkg-b",
"version": "1.0.0",
"dependencies": {
"@workspace/pkg-a": "workspace:*",
"lodash": "catalog:"
}
}

80
flake.lock generated
View File

@@ -1,5 +1,28 @@
{
"nodes": {
"devshell-lib": {
"inputs": {
"git-hooks": "git-hooks",
"nixpkgs": [
"nixpkgs"
],
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1772613315,
"narHash": "sha256-RlPTOsyfVwuwEzvaMpwS+giOqQa6KQXMuSHyh1bctjk=",
"ref": "v1.0.5",
"rev": "e445e49baf8b44b385108cd4f26a14d8ccf9fd35",
"revCount": 35,
"type": "git",
"url": "https://git.dgren.dev/eric/nix-flake-lib"
},
"original": {
"ref": "v1.0.5",
"type": "git",
"url": "https://git.dgren.dev/eric/nix-flake-lib"
}
},
"flake-compat": {
"flake": false,
"locked": {
@@ -20,7 +43,7 @@
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": "nixpkgs_2"
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1772024342,
@@ -39,7 +62,7 @@
"gitignore": {
"inputs": {
"nixpkgs": [
"repo-lib",
"devshell-lib",
"git-hooks",
"nixpkgs"
]
@@ -59,22 +82,6 @@
}
},
"nixpkgs": {
"locked": {
"lastModified": 1772542754,
"narHash": "sha256-WGV2hy+VIeQsYXpsLjdr4GvHv5eECMISX1zKLTedhdg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "8c809a146a140c5c8806f13399592dbcb1bb5dc4",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1770073757,
"narHash": "sha256-Vy+G+F+3E/Tl+GMNgiHl9Pah2DgShmIUBJXmbiQPHbI=",
@@ -90,7 +97,7 @@
"type": "github"
}
},
"nixpkgs_3": {
"nixpkgs_2": {
"locked": {
"lastModified": 1770107345,
"narHash": "sha256-tbS0Ebx2PiA1FRW8mt8oejR0qMXmziJmPaU1d4kYY9g=",
@@ -106,38 +113,31 @@
"type": "github"
}
},
"repo-lib": {
"inputs": {
"git-hooks": "git-hooks",
"nixpkgs": [
"nixpkgs"
],
"treefmt-nix": "treefmt-nix"
},
"nixpkgs_3": {
"locked": {
"lastModified": 1772866275,
"narHash": "sha256-lsJrFIbq6OO5wUC648VnvOmJm3qgJrlEugbdjeZsP34=",
"ref": "refs/tags/v3.0.0",
"rev": "96d2d190466dddcb9e652c38b70152f09b9fcb05",
"revCount": 50,
"type": "git",
"url": "https://git.dgren.dev/eric/nix-flake-lib"
"lastModified": 1772542754,
"narHash": "sha256-WGV2hy+VIeQsYXpsLjdr4GvHv5eECMISX1zKLTedhdg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "8c809a146a140c5c8806f13399592dbcb1bb5dc4",
"type": "github"
},
"original": {
"ref": "refs/tags/v3.0.0",
"type": "git",
"url": "https://git.dgren.dev/eric/nix-flake-lib"
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"repo-lib": "repo-lib"
"devshell-lib": "devshell-lib",
"nixpkgs": "nixpkgs_3"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": "nixpkgs_3"
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1770228511,

224
flake.nix
View File

@@ -3,137 +3,141 @@
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
repo-lib.url = "git+https://git.dgren.dev/eric/nix-flake-lib?ref=refs/tags/v3.0.0";
repo-lib.inputs.nixpkgs.follows = "nixpkgs";
devshell-lib.url = "git+https://git.dgren.dev/eric/nix-flake-lib?ref=v1.0.5";
devshell-lib.inputs.nixpkgs.follows = "nixpkgs";
};
outputs =
{
self,
nixpkgs,
repo-lib,
devshell-lib,
...
}:
let
bazelVersion = "9.0.1";
supportedSystems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
in
repo-lib.lib.mkRepo {
inherit self nixpkgs;
src = ./.;
{
devShells = forAllSystems (
system:
let
pkgs = import nixpkgs { inherit system; };
bazel9 = pkgs.writeShellScriptBin "bazel" ''
export USE_BAZEL_VERSION="''${USE_BAZEL_VERSION:-9.0.0}"
exec ${pkgs.bazelisk}/bin/bazelisk "$@"
'';
env = devshell-lib.lib.mkDevShell {
inherit system;
config = {
shell.extraShellText = ''
export USE_BAZEL_VERSION="''${USE_BAZEL_VERSION:-${bazelVersion}}"
export BUN_INSTALL="''${BUN_INSTALL:-$HOME/.bun}"
export PATH="$BUN_INSTALL/bin:$PATH"
'';
extraPackages = with pkgs; [
go
gopls
gotools
bun
bazel9
bazel-buildtools
self.packages.${system}.release
];
formatting = {
programs.shfmt.enable = true;
settings.shfmt.options = [
"-i"
"2"
"-s"
"-w"
];
};
features = {
oxfmt = true;
};
release = {
steps = [
{
run.script = ''
sed -E -i 's#^([[:space:]]*version[[:space:]]*=[[:space:]]*")[^"]*(",)$#\1'"$FULL_VERSION"'\2#' "$ROOT_DIR/MODULE.bazel"
'';
}
{
run.script = ''
README="$ROOT_DIR/README.md"
TMP="$README.tmp"
formatters = {
shfmt.enable = true;
};
awk -v stable="$BASE_VERSION" -v prerelease="$BASE_VERSION-rc.1" '
{
line = $0
formatterSettings = {
shfmt.options = [
"-i"
"2"
"-s"
"-w"
];
};
if (line ~ /bazel_dep\(name = "rules_bun", version = "/ && line !~ /-rc\.1/) {
sub(/version = "[^"]+"/, "version = \"" stable "\"", line)
} else if (line ~ /bazel_dep\(name = "rules_bun", version = "/ && line ~ /-rc\.1/) {
sub(/version = "[^"]+"/, "version = \"" prerelease "\"", line)
} else if (line ~ /archive\/refs\/tags\/v/ && line !~ /-rc\.1/) {
sub(/v[^"]+\.tar\.gz/, "v" stable ".tar.gz", line)
} else if (line ~ /archive\/refs\/tags\/v/ && line ~ /-rc\.1/) {
sub(/v[^"]+\.tar\.gz/, "v" prerelease ".tar.gz", line)
} else if (line ~ /strip_prefix = "rules_bun-v/ && line !~ /-rc\.1/) {
sub(/rules_bun-v[^"]+/, "rules_bun-v" stable, line)
} else if (line ~ /strip_prefix = "rules_bun-v/ && line ~ /-rc\.1/) {
sub(/rules_bun-v[^"]+/, "rules_bun-v" prerelease, line)
} else if (line ~ /For channel\/pre-release tags \(for example `v.*-rc\.1`\), use the matching folder prefix:/) {
sub(/`v[^`]+`/, "`v" prerelease "`", line)
}
additionalHooks = {
tests = {
enable = true;
entry = "echo 'No tests defined yet.'";
pass_filenames = false;
stages = [ "pre-push" ];
};
};
print line
}
' "$README" > "$TMP" && mv "$TMP" "$README"
'';
}
{
run.script = ''
bazel cquery //tests/... >/dev/null
'';
}
];
tools = [
{
name = "Bun";
bin = "${pkgs.bun}/bin/bun";
versionCmd = "--version";
color = "YELLOW";
}
{
name = "Go";
bin = "${pkgs.go}/bin/go";
versionCmd = "version";
color = "CYAN";
}
{
name = "Bazel";
bin = "${bazel9}/bin/bazel";
versionCmd = "--version";
color = "BLUE";
}
];
extraShellHook = ''
export USE_BAZEL_VERSION="''${USE_BAZEL_VERSION:-9.0.0}"
export BUN_INSTALL="''${BUN_INSTALL:-$HOME/.bun}"
export PATH="$BUN_INSTALL/bin:$PATH"
'';
};
in
{
default = env.shell;
}
);
checks = forAllSystems (
system:
let
env = devshell-lib.lib.mkDevShell { inherit system; };
in
{
inherit (env) pre-commit-check;
}
);
formatter = forAllSystems (system: (devshell-lib.lib.mkDevShell { inherit system; }).formatter);
# Optional: release command (`release`)
#
# The release script always updates VERSION first, then:
# 1) runs release steps in order (file writes and scripts)
# 2) runs postVersion hook
# 3) formats, stages, commits, tags, and pushes
#
# Runtime env vars available in release.run/postVersion:
# BASE_VERSION, CHANNEL, PRERELEASE_NUM, FULL_VERSION, FULL_TAG
#
packages = forAllSystems (system: {
release = devshell-lib.lib.mkRelease {
inherit system;
release = [ ];
postVersion = ''
echo "Released $FULL_TAG"
'';
};
};
});
perSystem =
{
pkgs,
system,
...
}:
let
bazel9 = pkgs.writeShellScriptBin "bazel" ''
export USE_BAZEL_VERSION="''${USE_BAZEL_VERSION:-${bazelVersion}}"
exec ${pkgs.bazelisk}/bin/bazelisk "$@"
'';
in
{
tools = [
(repo-lib.lib.tools.fromPackage {
name = "Bun";
package = pkgs.bun;
version.args = [ "--version" ];
banner.color = "YELLOW";
})
(repo-lib.lib.tools.fromPackage {
name = "Bazel";
package = bazel9;
version.args = [ "--version" ];
banner.color = "GREEN";
})
];
shell.packages = [
pkgs.bazel-buildtools
pkgs.curl
pkgs.python3
self.packages.${system}.release
];
checks.tests = {
command = "bazelisk test //tests/...";
stage = "pre-push";
passFilenames = false;
runtimeInputs = [
bazel9
pkgs.bun
pkgs.curl
pkgs.python3
];
};
};
};
}

280
implementation_plan.md Normal file
View File

@@ -0,0 +1,280 @@
Here's a comprehensive plan for implementing a Bazel-native `bun_rules` package:
---
## `bun_rules`: Bazel-Native Bun Implementation Plan
### What Is This?
A Bazel ruleset that integrates the [Bun](https://bun.sh) JavaScript runtime natively — similar to `rules_nodejs` but leveraging Bun's bundler, test runner, package manager, and runtime. The goal is hermetic, reproducible builds using Bun as the toolchain.
---
## Phase 1: Repository Skeleton & Toolchain
**Where to start.** Every Bazel ruleset begins with the toolchain — nothing else works without it.
### 1.1 Repo Structure
```
bun_rules/
├── MODULE.bazel # Bzlmod module definition
├── WORKSPACE # Legacy workspace support
├── BUILD.bazel
├── bun/
│ ├── repositories.bzl # Download bun binaries per platform
│ ├── toolchain.bzl # bun_toolchain rule
│ └── defs.bzl # Public API re-exports
├── internal/
│ ├── bun_binary.bzl
│ ├── bun_test.bzl
│ ├── bun_install.bzl
│ └── bun_bundle.bzl
├── examples/
│ └── basic/
└── tests/
├── toolchain_test/
├── install_test/
├── binary_test/
└── bundle_test/
```
### 1.2 Toolchain Rule (`toolchain.bzl`)
```python
BunToolchainInfo = provider(fields = ["bun_bin", "version"])
bun_toolchain = rule(
implementation = _bun_toolchain_impl,
attrs = {
"bun": attr.label(allow_single_file = True, executable = True, cfg = "exec"),
"version": attr.string(),
},
)
```
### 1.3 Binary Downloads (`repositories.bzl`)
Use `http_file` to fetch platform-specific Bun binaries:
- `bun-linux-x64`, `bun-linux-aarch64`
- `bun-darwin-x64`, `bun-darwin-aarch64`
- `bun-windows-x64.exe`
Use SHA256 checksums pinned per Bun release. Register via `register_toolchains()`.
**Tests needed:**
- `toolchain_resolution_test` — assert the correct binary is selected per `--platforms`
- `bun --version` smoke test via a `sh_test`
---
## Phase 2: `bun_install` (Package Manager)
Replaces `npm install` / `yarn`. This is the highest-leverage rule because every downstream rule depends on it.
### Rule Design
```python
bun_install(
name = "node_modules",
package_json = "//:package.json",
bun_lockfile = "//:bun.lockb",
)
```
- Runs `bun install --frozen-lockfile` in a sandboxed action
- Outputs a `node_modules/` directory as a `TreeArtifact`
- Must be hermetic: no network in actions (vendor or use a repository rule to pre-fetch)
### Key Challenges
- `bun.lockb` is binary — you need to commit it and treat it as a source file
- Network access during `bun install` breaks Bazel's sandbox; solve with either:
- A **repository rule** that runs install at analysis time (like `npm_install` in rules_nodejs)
- Or a **module extension** in Bzlmod
**Tests needed:**
- Install succeeds with a valid `package.json` + `bun.lockb`
- Build fails (with a clear error) when `bun.lockb` is out of date
- Determinism test: run install twice, assert identical output digest
- Test that `node_modules` is correctly provided to downstream rules
---
## Phase 3: `bun_binary` (Run JS/TS scripts)
```python
bun_binary(
name = "my_script",
entry_point = "src/main.ts",
node_modules = "//:node_modules",
data = glob(["src/**"]),
)
```
- Wraps `bun run <entry>` as a Bazel executable
- Provides `DefaultInfo` with a launcher script
- Handles both `.js` and `.ts` natively (no transpile step needed)
**Tests needed:**
- `bun_binary` produces a runnable target (`bazel run`)
- TypeScript entry points work without separate compilation
- `data` deps are available at runtime
- Environment variables pass through correctly
---
## Phase 4: `bun_test` (Test Runner)
```python
bun_test(
name = "my_test",
srcs = ["src/foo.test.ts"],
node_modules = "//:node_modules",
)
```
- Wraps `bun test` with Bazel's test runner protocol
- Must exit with code 0/non-0 correctly
- Outputs JUnit XML for `--test_output` compatibility (use `bun test --reporter junit`)
**Tests needed:**
- Passing test suite returns exit 0
- Failing test suite returns exit non-0 (Bazel marks as FAILED)
- Test filtering via `--test_filter` works
- Coverage via `bun test --coverage` integrates with `bazel coverage`
- Tests are re-run when source files change (input tracking)
- Tests are **not** re-run when unrelated files change (cache correctness)
---
## Phase 5: `bun_bundle` (Bundler)
```python
bun_bundle(
name = "app_bundle",
entry_points = ["src/index.ts"],
node_modules = "//:node_modules",
target = "browser", # or "node", "bun"
format = "esm", # or "cjs", "iife"
minify = True,
)
```
- Runs `bun build` as a Bazel action
- Outputs are declared files (JS, sourcemaps, assets)
- Supports splitting, external packages, define/env vars
**Tests needed:**
- Output file exists and has non-zero size
- `minify = True` produces smaller output than `minify = False`
- `external` packages are not bundled
- Sourcemaps are generated when requested
- Build is hermetic: same inputs → identical output digest (content hash)
- Invalid entry point produces a clear build error (not a cryptic Bazel failure)
---
## Phase 6: `js_library` / `ts_library` (Source Grouping)
Lightweight rules for grouping sources and propagating them through the dep graph:
```python
ts_library(
name = "utils",
srcs = glob(["src/**/*.ts"]),
deps = [":node_modules"],
)
```
**Tests needed:**
- `deps` correctly propagate transitive sources to `bun_bundle` and `bun_test`
- Circular dep detection (or at least graceful failure)
---
## Required Tests Summary
| Category | Test |
| ------------- | ----------------------------------------------------------- |
| Toolchain | Correct binary resolves per platform |
| Toolchain | `bun --version` executes successfully |
| `bun_install` | Clean install works |
| `bun_install` | Stale lockfile fails with clear error |
| `bun_install` | Output is deterministic |
| `bun_binary` | JS entry point runs |
| `bun_binary` | TS entry point runs without compile step |
| `bun_binary` | Data files available at runtime |
| `bun_test` | Passing tests → exit 0 |
| `bun_test` | Failing tests → exit non-0 |
| `bun_test` | Cache hit: unchanged test not re-run |
| `bun_test` | Cache miss: changed source triggers re-run |
| `bun_test` | JUnit XML output parseable |
| `bun_bundle` | Output file produced |
| `bun_bundle` | Minification reduces output size |
| `bun_bundle` | Hermetic: identical inputs → identical digest |
| `bun_bundle` | External packages excluded correctly |
| Integration | `examples/basic` builds end-to-end with `bazel build //...` |
| Integration | `bazel test //...` passes all tests |
### Gap-Closing Checklist (Concrete Targets)
Use this checklist to close the current coverage gaps with explicit test targets.
| Status | Gap | Proposed target | Location |
| ------- | ---------------------------------------------------------- | ---------------------------------- | ------------------------------------ |
| Partial | Toolchain resolves per platform is only host-select tested | `toolchain_resolution_matrix_test` | `tests/toolchain_test/BUILD.bazel` |
| Missing | `bun_install` deterministic output digest | `bun_install_determinism_test` | `tests/install_test/BUILD.bazel` |
| Missing | `bun_binary` runtime data files availability | `bun_binary_data_test` | `tests/binary_test/BUILD.bazel` |
| Partial | `bun_test` failing suite exists but is manual-only | `bun_test_failing_suite_test` | `tests/bun_test_test/BUILD.bazel` |
| Missing | `bun_test` cache hit (unchanged inputs) | `bun_test_cache_hit_test` | `tests/bun_test_test/BUILD.bazel` |
| Missing | `bun_test` cache miss (changed source) | `bun_test_cache_miss_test` | `tests/bun_test_test/BUILD.bazel` |
| Missing | `bun_test` JUnit XML parseability | `bun_test_junit_output_test` | `tests/bun_test_test/BUILD.bazel` |
| Missing | `bun_bundle` hermetic digest stability | `bundle_hermetic_digest_test` | `tests/bundle_test/BUILD.bazel` |
| Missing | `bun_bundle` external package exclusion | `bundle_external_exclusion_test` | `tests/bundle_test/BUILD.bazel` |
| Missing | `examples/basic` end-to-end build via Bazel | `examples_basic_e2e_build_test` | `tests/integration_test/BUILD.bazel` |
| Partial | CI currently runs `bazel test //tests/...` only | `repo_all_targets_test` | `tests/integration_test/BUILD.bazel` |
Recommended implementation order:
1. `bun_test_failing_suite_test` (remove/manual split) and `bun_binary_data_test`
2. `bun_install_determinism_test`, `bundle_hermetic_digest_test`
3. `bun_test_cache_hit_test`, `bun_test_cache_miss_test`, `bun_test_junit_output_test`
4. `bundle_external_exclusion_test`, `examples_basic_e2e_build_test`, `repo_all_targets_test`
---
## Development Sequence
```
1. Toolchain downloads + resolution ← start here
2. bun_install (repository rule approach)
3. bun_binary (simplest runtime rule)
4. bun_test
5. bun_bundle
6. js_library / ts_library
7. Bzlmod module extension for installs
8. CI matrix (linux-x64, darwin-arm64, windows)
9. Docs + examples
```
---
## Where to Start Right Now
**Day 1:** Copy the pattern from [`rules_go`](https://github.com/bazelbuild/rules_go) or [`aspect-build/rules_js`](https://github.com/aspect-build/rules_js) for toolchain registration. Write `repositories.bzl` that fetches the Bun binary for your current platform only. Write a `sh_test` that calls `bun --version` and asserts it exits 0. Get that green.
**Reference implementations to study:**
- `aspect-build/rules_js` — best modern reference for JS in Bazel
- `bazelbuild/rules_nodejs` — older but battle-tested patterns
- `bazelbuild/rules_python` — excellent toolchain download pattern to copy
The toolchain is the entire foundation. Nothing else is possible without it being solid.

View File

@@ -1,157 +1,9 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
package(default_visibility = ["//visibility:public"])
exports_files([
"bun_build_support.bzl",
"bun_binary.bzl",
"bun_command.bzl",
"bun_compile.bzl",
"bun_bundle.bzl",
"bun_dev.bzl",
"bun_install.bzl",
"bun_script.bzl",
"bun_test.bzl",
"js_compat.bzl",
"js_library.bzl",
"js_run_devserver.bzl",
"runtime_launcher.bzl",
"runtime_launcher.js",
"workspace.bzl",
"bun_binary.bzl",
"bun_bundle.bzl",
"bun_install.bzl",
"bun_test.bzl",
"js_library.bzl",
])
filegroup(
name = "repo_runtime_files",
srcs = [
"BUILD.bazel",
"bun_binary.bzl",
"bun_build_support.bzl",
"bun_bundle.bzl",
"bun_command.bzl",
"bun_compile.bzl",
"bun_dev.bzl",
"bun_install.bzl",
"bun_script.bzl",
"bun_test.bzl",
"js_compat.bzl",
"js_library.bzl",
"js_run_devserver.bzl",
"runtime_launcher.bzl",
"runtime_launcher.js",
"workspace.bzl",
],
visibility = ["//visibility:public"],
)
bzl_library(
name = "bun_command_bzl",
srcs = ["bun_command.bzl"],
)
bzl_library(
name = "bun_build_support_bzl",
srcs = ["bun_build_support.bzl"],
deps = [
":bun_command_bzl",
":js_library_bzl",
],
)
bzl_library(
name = "bun_binary_bzl",
srcs = ["bun_binary.bzl"],
deps = [
":bun_command_bzl",
":js_library_bzl",
":runtime_launcher_bzl",
":workspace_bzl",
],
)
bzl_library(
name = "bun_compile_bzl",
srcs = ["bun_compile.bzl"],
deps = [
":bun_build_support_bzl",
],
)
bzl_library(
name = "bun_bundle_bzl",
srcs = ["bun_bundle.bzl"],
deps = [
":bun_build_support_bzl",
],
)
bzl_library(
name = "bun_dev_bzl",
srcs = ["bun_dev.bzl"],
deps = [
":bun_command_bzl",
":runtime_launcher_bzl",
":workspace_bzl",
],
)
bzl_library(
name = "bun_install_bzl",
srcs = ["bun_install.bzl"],
)
bzl_library(
name = "bun_script_bzl",
srcs = ["bun_script.bzl"],
deps = [
":bun_command_bzl",
":runtime_launcher_bzl",
":workspace_bzl",
],
)
bzl_library(
name = "bun_test_bzl",
srcs = ["bun_test.bzl"],
deps = [
":bun_command_bzl",
":js_library_bzl",
":runtime_launcher_bzl",
":workspace_bzl",
],
)
bzl_library(
name = "js_compat_bzl",
srcs = ["js_compat.bzl"],
deps = [
":bun_binary_bzl",
":bun_test_bzl",
":js_library_bzl",
":js_run_devserver_bzl",
],
)
bzl_library(
name = "js_library_bzl",
srcs = ["js_library.bzl"],
)
bzl_library(
name = "js_run_devserver_bzl",
srcs = ["js_run_devserver.bzl"],
deps = [
":js_library_bzl",
":runtime_launcher_bzl",
":workspace_bzl",
],
)
bzl_library(
name = "runtime_launcher_bzl",
srcs = ["runtime_launcher.bzl"],
)
bzl_library(
name = "workspace_bzl",
srcs = ["workspace.bzl"],
)

View File

@@ -1,130 +1,56 @@
"""Rule for running JS/TS scripts with Bun."""
load("//internal:bun_command.bzl", "append_flag", "append_flag_values", "append_install_mode", "append_raw_flags")
load("//internal:js_library.bzl", "collect_js_runfiles")
load("//internal:runtime_launcher.bzl", "declare_runtime_wrapper", "runfiles_path", "runtime_launcher_attrs", "write_launcher_spec")
load("//internal:workspace.bzl", "create_bun_workspace_info", "workspace_runfiles")
def _bun_binary_impl(ctx):
toolchain = ctx.toolchains["//bun:toolchain_type"]
bun_bin = toolchain.bun.bun_bin
entry_point = ctx.file.entry_point
dep_runfiles = [collect_js_runfiles(dep) for dep in ctx.attr.deps]
workspace_info = create_bun_workspace_info(
ctx,
extra_files = ctx.files.data + ctx.files.preload + ctx.files.env_files + [bun_bin],
primary_file = entry_point,
launcher = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(
output = launcher,
is_executable = True,
content = """#!/usr/bin/env bash
set -euo pipefail
runfiles_dir="${{RUNFILES_DIR:-$0.runfiles}}"
bun_bin="${{runfiles_dir}}/_main/{bun_short_path}"
entry_point="${{runfiles_dir}}/_main/{entry_short_path}"
exec "${{bun_bin}}" run "${{entry_point}}" "$@"
""".format(
bun_short_path = bun_bin.short_path,
entry_short_path = entry_point.short_path,
),
)
argv = ["--bun", "run"]
append_install_mode(argv, ctx.attr.install_mode)
append_flag(argv, "--no-env-file", ctx.attr.no_env_file)
append_flag(argv, "--smol", ctx.attr.smol)
append_flag_values(argv, "--conditions", ctx.attr.conditions)
append_raw_flags(argv, ctx.attr.run_flags)
transitive_files = []
if ctx.attr.node_modules:
transitive_files.append(ctx.attr.node_modules[DefaultInfo].files)
spec_file = write_launcher_spec(ctx, {
"version": 1,
"kind": "bun_run",
"bun_short_path": runfiles_path(bun_bin),
"primary_source_short_path": runfiles_path(entry_point),
"package_json_short_path": "",
"install_metadata_short_path": runfiles_path(workspace_info.install_metadata_file) if workspace_info.install_metadata_file else "",
"install_repo_runfiles_path": workspace_info.install_repo_runfiles_path,
"node_modules_roots": workspace_info.node_modules_roots,
"package_dir_hint": workspace_info.package_dir_hint,
"working_dir_mode": ctx.attr.working_dir,
"inherit_host_path": ctx.attr.inherit_host_path,
"argv": argv,
"args": ctx.attr.args,
"passthrough_args": True,
"tool_short_path": "",
"restart_on": [],
"watch_mode": "",
"reporter": "",
"coverage": False,
"coverage_reporters": [],
"preload_short_paths": [runfiles_path(file) for file in ctx.files.preload],
"env_file_short_paths": [runfiles_path(file) for file in ctx.files.env_files],
"test_short_paths": [],
})
launcher = declare_runtime_wrapper(ctx, bun_bin, spec_file)
runfiles = ctx.runfiles(
files = [bun_bin, entry_point] + ctx.files.data,
transitive_files = depset(transitive = transitive_files),
)
return [
workspace_info,
DefaultInfo(
executable = launcher.executable,
runfiles = workspace_runfiles(
ctx,
workspace_info,
direct_files = [launcher.executable, launcher.runner, spec_file],
transitive_files = dep_runfiles,
),
executable = launcher,
runfiles = runfiles,
),
]
_BUN_BINARY_ATTRS = runtime_launcher_attrs()
_BUN_BINARY_ATTRS.update({
"entry_point": attr.label(
mandatory = True,
allow_single_file = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
doc = "Path to the main JS/TS file to execute.",
),
"node_modules": attr.label(
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles.",
),
"data": attr.label_list(
allow_files = True,
doc = "Additional runtime files required by the program.",
),
"deps": attr.label_list(
doc = "Library dependencies required by the program.",
),
"preload": attr.label_list(
allow_files = True,
doc = "Modules to preload with `--preload` before running the entry point.",
),
"env_files": attr.label_list(
allow_files = True,
doc = "Additional environment files loaded with `--env-file`.",
),
"no_env_file": attr.bool(
default = False,
doc = "If true, disables Bun's automatic `.env` loading.",
),
"smol": attr.bool(
default = False,
doc = "If true, enables Bun's lower-memory runtime mode.",
),
"conditions": attr.string_list(
doc = "Custom package resolve conditions passed to Bun.",
),
"install_mode": attr.string(
default = "disable",
values = ["disable", "auto", "fallback", "force"],
doc = "Whether Bun may auto-install missing packages at runtime.",
),
"run_flags": attr.string_list(
doc = "Additional raw flags forwarded to `bun run` before the entry point.",
),
"working_dir": attr.string(
default = "workspace",
values = ["workspace", "entry_point"],
doc = "Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`.",
),
"inherit_host_path": attr.bool(
default = False,
doc = "If true, appends the host PATH after the staged Bun runtime tool bin and node_modules/.bin entries at runtime.",
),
})
bun_binary = rule(
implementation = _bun_binary_impl,
doc = """Runs a JS/TS entry point with Bun as an executable target.
Use this rule for non-test scripts and CLIs that should run via `bazel run`.
""",
attrs = _BUN_BINARY_ATTRS,
attrs = {
"entry_point": attr.label(
mandatory = True,
allow_single_file = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
),
"node_modules": attr.label(),
"data": attr.label_list(allow_files = True),
},
executable = True,
toolchains = ["//bun:toolchain_type"],
)

View File

@@ -1,208 +0,0 @@
"""Shared helpers for Bun build- and compile-style rules."""
load("//internal:bun_command.bzl", "add_flag", "add_flag_value", "add_flag_values", "add_install_mode", "add_raw_flags")
load("//internal:js_library.bzl", "collect_js_sources")
_STAGED_BUILD_RUNNER = """import { spawnSync } from "node:child_process";
import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { dirname, resolve } from "node:path";
const [, , manifestPath, ...buildArgs] = process.argv;
const execroot = process.cwd();
const stageDir = mkdtempSync(resolve(tmpdir(), "rules_bun_build-"));
function rewriteArgPath(flag, value) {
return `${flag}=${resolve(execroot, value)}`;
}
try {
for (const relpath of readFileSync(manifestPath, "utf8").split(/\\r?\\n/)) {
if (!relpath) {
continue;
}
const src = resolve(execroot, relpath);
const dest = resolve(stageDir, relpath);
mkdirSync(dirname(dest), { recursive: true });
cpSync(src, dest, { dereference: true, force: true, recursive: true });
}
const forwardedArgs = [];
for (let index = 0; index < buildArgs.length; index += 1) {
const arg = buildArgs[index];
if ((arg === "--outdir" || arg === "--outfile") && index + 1 < buildArgs.length) {
forwardedArgs.push(arg, resolve(execroot, buildArgs[index + 1]));
index += 1;
continue;
}
if (arg.startsWith("--metafile=")) {
forwardedArgs.push(rewriteArgPath("--metafile", arg.slice("--metafile=".length)));
continue;
}
if (arg.startsWith("--metafile-md=")) {
forwardedArgs.push(rewriteArgPath("--metafile-md", arg.slice("--metafile-md=".length)));
continue;
}
forwardedArgs.push(arg);
}
const result = spawnSync(process.execPath, forwardedArgs, {
cwd: stageDir,
stdio: "inherit",
});
if (result.error) {
throw result.error;
}
process.exit(typeof result.status === "number" ? result.status : 1);
} finally {
rmSync(stageDir, { recursive: true, force: true });
}
"""
def sort_files_by_short_path(files):
files_by_path = {}
short_paths = []
for file in files:
files_by_path[file.short_path] = file
short_paths.append(file.short_path)
return [files_by_path[short_path] for short_path in sorted(short_paths)]
def validate_hermetic_install_mode(attr, rule_name):
if getattr(attr, "install_mode", "disable") != "disable":
fail("{} requires install_mode = \"disable\" for hermetic execution".format(rule_name))
def infer_entry_point_root(entries):
if not entries:
return None
common_segments = entries[0].path.split("/")[:-1]
for entry in entries[1:]:
entry_segments = entry.path.split("/")[:-1]
common_length = min(len(common_segments), len(entry_segments))
idx = common_length
for segment_idx in range(common_length):
if common_segments[segment_idx] != entry_segments[segment_idx]:
idx = segment_idx
break
common_segments = common_segments[:idx]
if not common_segments:
return "."
return "/".join(common_segments)
def bun_build_transitive_inputs(ctx):
transitive_inputs = []
if getattr(ctx.attr, "node_modules", None):
transitive_inputs.append(ctx.attr.node_modules[DefaultInfo].files)
for dep in getattr(ctx.attr, "deps", []):
transitive_inputs.append(collect_js_sources(dep))
return transitive_inputs
def add_bun_build_common_flags(args, attr, metafile = None, metafile_md = None, root = None):
build_root = root
if build_root == None:
build_root = getattr(attr, "root", None)
add_install_mode(args, getattr(attr, "install_mode", "disable"))
add_flag_value(args, "--target", getattr(attr, "target", None))
add_flag_value(args, "--format", getattr(attr, "format", None))
add_flag(args, "--production", getattr(attr, "production", False))
add_flag(args, "--splitting", getattr(attr, "splitting", False))
add_flag_value(args, "--root", build_root)
sourcemap = getattr(attr, "sourcemap", None)
if sourcemap == True:
args.add("--sourcemap")
elif sourcemap and sourcemap != "none":
add_flag_value(args, "--sourcemap", sourcemap)
add_flag_value(args, "--banner", getattr(attr, "banner", None))
add_flag_value(args, "--footer", getattr(attr, "footer", None))
add_flag_value(args, "--public-path", getattr(attr, "public_path", None))
add_flag_value(args, "--packages", getattr(attr, "packages", None))
add_flag_values(args, "--external", getattr(attr, "external", []))
add_flag_value(args, "--entry-naming", getattr(attr, "entry_naming", None))
add_flag_value(args, "--chunk-naming", getattr(attr, "chunk_naming", None))
add_flag_value(args, "--asset-naming", getattr(attr, "asset_naming", None))
add_flag(args, "--minify", getattr(attr, "minify", False))
add_flag(args, "--minify-syntax", getattr(attr, "minify_syntax", False))
add_flag(args, "--minify-whitespace", getattr(attr, "minify_whitespace", False))
add_flag(args, "--minify-identifiers", getattr(attr, "minify_identifiers", False))
add_flag(args, "--keep-names", getattr(attr, "keep_names", False))
add_flag(args, "--css-chunking", getattr(attr, "css_chunking", False))
add_flag_values(args, "--conditions", getattr(attr, "conditions", []))
add_flag_value(args, "--env", getattr(attr, "env", None))
add_flag_values(args, "--define", getattr(attr, "define", []))
add_flag_values(args, "--drop", getattr(attr, "drop", []))
add_flag_values(args, "--feature", getattr(attr, "feature", []))
add_flag_values(args, "--loader", getattr(attr, "loader", []))
add_flag_value(args, "--jsx-factory", getattr(attr, "jsx_factory", None))
add_flag_value(args, "--jsx-fragment", getattr(attr, "jsx_fragment", None))
add_flag_value(args, "--jsx-import-source", getattr(attr, "jsx_import_source", None))
add_flag_value(args, "--jsx-runtime", getattr(attr, "jsx_runtime", None))
add_flag(args, "--jsx-side-effects", getattr(attr, "jsx_side_effects", False))
add_flag(args, "--react-fast-refresh", getattr(attr, "react_fast_refresh", False))
add_flag(args, "--emit-dce-annotations", getattr(attr, "emit_dce_annotations", False))
add_flag(args, "--no-bundle", getattr(attr, "no_bundle", False))
if metafile:
args.add("--metafile=%s" % metafile.path)
if metafile_md:
args.add("--metafile-md=%s" % metafile_md.path)
add_raw_flags(args, getattr(attr, "build_flags", []))
def add_bun_compile_flags(args, attr, compile_executable = None):
add_flag(args, "--compile", True)
add_flag(args, "--bytecode", getattr(attr, "bytecode", False))
add_flag_values(args, "--compile-exec-argv", getattr(attr, "compile_exec_argv", []))
if getattr(attr, "compile_autoload_dotenv", True):
args.add("--compile-autoload-dotenv")
else:
args.add("--no-compile-autoload-dotenv")
if getattr(attr, "compile_autoload_bunfig", True):
args.add("--compile-autoload-bunfig")
else:
args.add("--no-compile-autoload-bunfig")
if getattr(attr, "compile_autoload_tsconfig", False):
args.add("--compile-autoload-tsconfig")
else:
args.add("--no-compile-autoload-tsconfig")
if getattr(attr, "compile_autoload_package_json", False):
args.add("--compile-autoload-package-json")
else:
args.add("--no-compile-autoload-package-json")
if compile_executable:
add_flag_value(args, "--compile-executable-path", compile_executable.path)
add_flag(args, "--windows-hide-console", getattr(attr, "windows_hide_console", False))
add_flag_value(args, "--windows-icon", getattr(attr, "windows_icon", None))
add_flag_value(args, "--windows-title", getattr(attr, "windows_title", None))
add_flag_value(args, "--windows-publisher", getattr(attr, "windows_publisher", None))
add_flag_value(args, "--windows-version", getattr(attr, "windows_version", None))
add_flag_value(args, "--windows-description", getattr(attr, "windows_description", None))
add_flag_value(args, "--windows-copyright", getattr(attr, "windows_copyright", None))
def declare_staged_bun_build_action(ctx, bun_bin, build_args, build_inputs, outputs, mnemonic, progress_message, name_suffix):
sorted_inputs = sort_files_by_short_path(build_inputs.to_list())
input_manifest = ctx.actions.declare_file(ctx.label.name + name_suffix + ".inputs")
runner = ctx.actions.declare_file(ctx.label.name + name_suffix + "_runner.js")
ctx.actions.write(
output = input_manifest,
content = "".join([file.path + "\n" for file in sorted_inputs]),
)
ctx.actions.write(
output = runner,
content = _STAGED_BUILD_RUNNER,
)
ctx.actions.run(
executable = bun_bin,
arguments = ["--bun", runner.path, input_manifest.path, build_args],
inputs = depset(
direct = [input_manifest, runner],
transitive = [build_inputs],
),
outputs = outputs,
mnemonic = mnemonic,
progress_message = progress_message,
)

View File

@@ -1,53 +1,58 @@
"""Rule for bundling JS/TS sources with Bun."""
load("//internal:bun_build_support.bzl", "add_bun_build_common_flags", "bun_build_transitive_inputs", "declare_staged_bun_build_action", "sort_files_by_short_path", "validate_hermetic_install_mode")
load("//internal:js_library.bzl", "BunSourcesInfo")
def _output_name(target_name, entry):
stem = entry.short_path.rsplit(".", 1)[0]
sanitized = stem.replace("\\", "_").replace("/", "_").replace("-", "_").replace(".", "_").replace("@", "at_")
sanitized = sanitized.replace("__", "_").replace("__", "_").replace("__", "_")
sanitized = sanitized.strip("_")
if not sanitized:
sanitized = entry.basename.rsplit(".", 1)[0]
return "{}__{}.js".format(target_name, sanitized)
stem = entry.basename.rsplit(".", 1)[0]
return "{}__{}.js".format(target_name, stem)
def _bun_bundle_impl(ctx):
validate_hermetic_install_mode(ctx.attr, "bun_bundle")
toolchain = ctx.toolchains["//bun:toolchain_type"]
bun_bin = toolchain.bun.bun_bin
entry_points = sort_files_by_short_path(ctx.files.entry_points)
data_files = sort_files_by_short_path(ctx.files.data)
transitive_inputs = bun_build_transitive_inputs(ctx)
transitive_inputs = []
if ctx.attr.node_modules:
transitive_inputs.append(ctx.attr.node_modules[DefaultInfo].files)
for dep in ctx.attr.deps:
if BunSourcesInfo in dep:
transitive_inputs.append(dep[BunSourcesInfo].transitive_sources)
else:
transitive_inputs.append(dep[DefaultInfo].files)
outputs = []
for entry in entry_points:
for entry in ctx.files.entry_points:
output = ctx.actions.declare_file(_output_name(ctx.label.name, entry))
outputs.append(output)
args = ctx.actions.args()
args.add("--bun")
args.add("build")
add_bun_build_common_flags(args, ctx.attr)
args.add(entry.path)
args.add("--outfile")
args.add(output.path)
args.add(entry.path)
args.add("--target")
args.add(ctx.attr.target)
args.add("--format")
args.add(ctx.attr.format)
if ctx.attr.minify:
args.add("--minify")
if ctx.attr.sourcemap:
args.add("--sourcemap")
for package in ctx.attr.external:
args.add("--external")
args.add(package)
declare_staged_bun_build_action(
ctx,
bun_bin,
args,
depset(
direct = [entry] + data_files,
ctx.actions.run(
executable = bun_bin,
arguments = [args],
inputs = depset(
direct = [entry] + ctx.files.data,
transitive = transitive_inputs,
),
outputs = [output],
mnemonic = "BunBundle",
progress_message = "Bundling {} with Bun".format(entry.short_path),
name_suffix = "_bundle_{}".format(output.basename.rsplit(".", 1)[0]),
)
return [DefaultInfo(files = depset(outputs))]
@@ -55,55 +60,25 @@ def _bun_bundle_impl(ctx):
bun_bundle = rule(
implementation = _bun_bundle_impl,
doc = """Bundles one or more JS/TS entry points using Bun build.
Each entry point produces one output JavaScript artifact.
""",
attrs = {
"entry_points": attr.label_list(
mandatory = True,
allow_files = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
doc = "Entry files to bundle.",
),
"node_modules": attr.label(
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, for package resolution.",
),
"deps": attr.label_list(
doc = "Source/library dependencies that provide transitive inputs.",
),
"data": attr.label_list(
allow_files = True,
doc = "Additional non-source files needed during bundling.",
),
"install_mode": attr.string(
default = "disable",
values = ["disable", "auto", "fallback", "force"],
doc = "Whether Bun may auto-install missing packages during bundling. Hermetic bundle actions require `disable`; other values are rejected.",
),
"node_modules": attr.label(),
"deps": attr.label_list(),
"data": attr.label_list(allow_files = True),
"target": attr.string(
default = "browser",
values = ["browser", "node", "bun"],
doc = "Bun build target environment.",
),
"format": attr.string(
default = "esm",
values = ["esm", "cjs", "iife"],
doc = "Output module format.",
),
"minify": attr.bool(
default = False,
doc = "If true, minifies bundle output.",
),
"sourcemap": attr.bool(
default = False,
doc = "If true, emits source maps.",
),
"external": attr.string_list(
doc = "Package names to treat as externals (not bundled).",
),
"build_flags": attr.string_list(
doc = "Additional raw flags forwarded to `bun build`.",
),
"minify": attr.bool(default = False),
"sourcemap": attr.bool(default = False),
"external": attr.string_list(),
},
toolchains = ["//bun:toolchain_type"],
)

View File

@@ -1,113 +0,0 @@
"""Shared Bun CLI flag builders for rules and launchers."""
def shell_quote(value):
return "'" + str(value).replace("'", "'\"'\"'") + "'"
def _runfiles_workspace(file):
workspace_name = file.owner.workspace_name
if workspace_name:
return workspace_name
return "_main"
def runfiles_path_expr(file):
return '"${runfiles_dir}/%s/%s"' % (_runfiles_workspace(file), file.short_path)
def render_shell_array(name, values):
rendered = [shell_quote(value) for value in values]
return "%s=(%s)" % (name, " ".join(rendered))
def append_shell_arg(lines, name, value):
lines.append("%s+=(%s)" % (name, shell_quote(value)))
def append_shell_expr(lines, name, expr):
lines.append("%s+=(%s)" % (name, expr))
def append_shell_flag(lines, name, flag, enabled):
if enabled:
append_shell_arg(lines, name, flag)
def append_shell_flag_value(lines, name, flag, value):
if value == None:
return
if type(value) == type("") and not value:
return
append_shell_arg(lines, name, flag)
append_shell_arg(lines, name, value)
def append_shell_flag_values(lines, name, flag, values):
for value in values:
append_shell_flag_value(lines, name, flag, value)
def append_shell_flag_files(lines, name, flag, files):
for file in files:
append_shell_arg(lines, name, flag)
append_shell_expr(lines, name, runfiles_path_expr(file))
def append_shell_raw_flags(lines, name, values):
for value in values:
append_shell_arg(lines, name, value)
def append_shell_install_mode(lines, name, install_mode):
if install_mode == "disable":
append_shell_arg(lines, name, "--no-install")
elif install_mode in ["fallback", "force"]:
append_shell_flag_value(lines, name, "--install", install_mode)
def add_flag(args, flag, enabled):
if enabled:
args.add(flag)
def add_flag_value(args, flag, value):
if value == None:
return
if type(value) == type("") and not value:
return
args.add(flag)
args.add(value)
def add_flag_values(args, flag, values):
for value in values:
add_flag_value(args, flag, value)
def add_flag_files(args, flag, files):
for file in files:
args.add(flag)
args.add(file.path)
def add_raw_flags(args, values):
args.add_all(values)
def add_install_mode(args, install_mode):
if install_mode == "disable":
args.add("--no-install")
elif install_mode in ["fallback", "force"]:
add_flag_value(args, "--install", install_mode)
def append_arg(values, value):
values.append(str(value))
def append_flag(values, flag, enabled):
if enabled:
append_arg(values, flag)
def append_flag_value(values, flag, value):
if value == None:
return
if type(value) == type("") and not value:
return
append_arg(values, flag)
append_arg(values, value)
def append_flag_values(values, flag, items):
for item in items:
append_flag_value(values, flag, item)
def append_raw_flags(values, items):
for item in items:
append_arg(values, item)
def append_install_mode(values, install_mode):
if install_mode == "disable":
append_arg(values, "--no-install")
elif install_mode in ["fallback", "force"]:
append_flag_value(values, "--install", install_mode)

View File

@@ -1,335 +0,0 @@
"""Rules for Bun build outputs and standalone executables."""
load("//internal:bun_build_support.bzl", "add_bun_build_common_flags", "add_bun_compile_flags", "bun_build_transitive_inputs", "declare_staged_bun_build_action", "infer_entry_point_root", "sort_files_by_short_path", "validate_hermetic_install_mode")
def _bun_build_impl(ctx):
validate_hermetic_install_mode(ctx.attr, "bun_build")
toolchain = ctx.toolchains["//bun:toolchain_type"]
bun_bin = toolchain.bun.bun_bin
entry_points = sort_files_by_short_path(ctx.files.entry_points)
data_files = sort_files_by_short_path(ctx.files.data)
output_dir = ctx.actions.declare_directory(ctx.label.name)
metafile = None
if ctx.attr.metafile:
metafile = ctx.actions.declare_file(ctx.label.name + ".meta.json")
metafile_md = None
if ctx.attr.metafile_md:
metafile_md = ctx.actions.declare_file(ctx.label.name + ".meta.md")
build_root = ctx.attr.root
if not build_root:
build_root = infer_entry_point_root(entry_points)
transitive_inputs = bun_build_transitive_inputs(ctx)
build_inputs = depset(
direct = entry_points + data_files,
transitive = transitive_inputs,
)
build_args = ctx.actions.args()
build_args.add("--bun")
build_args.add("build")
add_bun_build_common_flags(build_args, ctx.attr, metafile = metafile, metafile_md = metafile_md, root = build_root)
build_args.add("--outdir")
build_args.add(output_dir.path)
build_args.add_all(entry_points)
outputs = [output_dir]
if metafile:
outputs.append(metafile)
if metafile_md:
outputs.append(metafile_md)
declare_staged_bun_build_action(
ctx,
bun_bin,
build_args,
build_inputs,
outputs = outputs,
mnemonic = "BunBuild",
progress_message = "Building {} with Bun".format(ctx.label.name),
name_suffix = "_build",
)
return [DefaultInfo(files = depset(outputs))]
def _bun_compile_impl(ctx):
validate_hermetic_install_mode(ctx.attr, "bun_compile")
toolchain = ctx.toolchains["//bun:toolchain_type"]
bun_bin = toolchain.bun.bun_bin
output = ctx.actions.declare_file(ctx.label.name)
compile_executable = ctx.file.compile_executable
data_files = sort_files_by_short_path(ctx.files.data)
args = ctx.actions.args()
args.add("--bun")
args.add("build")
add_bun_build_common_flags(args, ctx.attr)
add_bun_compile_flags(args, ctx.attr, compile_executable = compile_executable)
args.add("--outfile")
args.add(output.path)
args.add(ctx.file.entry_point.path)
direct_inputs = [ctx.file.entry_point] + data_files
if compile_executable:
direct_inputs.append(compile_executable)
declare_staged_bun_build_action(
ctx,
bun_bin,
args,
depset(
direct = direct_inputs,
transitive = bun_build_transitive_inputs(ctx),
),
outputs = [output],
mnemonic = "BunCompile",
progress_message = "Compiling {} with Bun".format(ctx.file.entry_point.short_path),
name_suffix = "_compile",
)
return [
DefaultInfo(
executable = output,
files = depset([output]),
),
]
_COMMON_BUILD_ATTRS = {
"node_modules": attr.label(
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, for package resolution.",
),
"deps": attr.label_list(
doc = "Source/library dependencies that provide transitive inputs.",
),
"data": attr.label_list(
allow_files = True,
doc = "Additional non-source files needed during building.",
),
"install_mode": attr.string(
default = "disable",
values = ["disable", "auto", "fallback", "force"],
doc = "Whether Bun may auto-install missing packages while executing the build. Hermetic build actions require `disable`; other values are rejected.",
),
"target": attr.string(
default = "browser",
values = ["browser", "node", "bun"],
doc = "Bun build target environment.",
),
"format": attr.string(
default = "esm",
values = ["esm", "cjs", "iife"],
doc = "Output module format.",
),
"production": attr.bool(
default = False,
doc = "If true, sets `NODE_ENV=production` and enables Bun production mode.",
),
"splitting": attr.bool(
default = False,
doc = "If true, enables code splitting.",
),
"root": attr.string(
doc = "Optional root directory for multiple entry points.",
),
"sourcemap": attr.string(
default = "none",
values = ["none", "linked", "inline", "external"],
doc = "Sourcemap emission mode.",
),
"banner": attr.string(
doc = "Optional bundle banner text.",
),
"footer": attr.string(
doc = "Optional bundle footer text.",
),
"public_path": attr.string(
doc = "Optional public path prefix for emitted imports.",
),
"packages": attr.string(
default = "bundle",
values = ["bundle", "external"],
doc = "Whether packages stay bundled or are treated as external.",
),
"external": attr.string_list(
doc = "Modules treated as externals (not bundled).",
),
"entry_naming": attr.string(
doc = "Optional entry naming template.",
),
"chunk_naming": attr.string(
doc = "Optional chunk naming template.",
),
"asset_naming": attr.string(
doc = "Optional asset naming template.",
),
"minify": attr.bool(
default = False,
doc = "If true, enables all Bun minification passes.",
),
"minify_syntax": attr.bool(
default = False,
doc = "If true, minifies syntax only.",
),
"minify_whitespace": attr.bool(
default = False,
doc = "If true, minifies whitespace only.",
),
"minify_identifiers": attr.bool(
default = False,
doc = "If true, minifies identifiers only.",
),
"keep_names": attr.bool(
default = False,
doc = "If true, preserves function and class names when minifying.",
),
"css_chunking": attr.bool(
default = False,
doc = "If true, Bun chunks CSS across multiple entry points.",
),
"conditions": attr.string_list(
doc = "Custom resolve conditions passed to Bun.",
),
"env": attr.string(
doc = "Inline environment variable behavior passed to `--env`.",
),
"define": attr.string_list(
doc = "Repeated `--define` values such as `process.env.NODE_ENV:\"production\"`.",
),
"drop": attr.string_list(
doc = "Repeated `--drop` values, for example `console`.",
),
"feature": attr.string_list(
doc = "Repeated `--feature` values for dead-code elimination.",
),
"loader": attr.string_list(
doc = "Repeated `--loader` values such as `.svg:file`.",
),
"jsx_factory": attr.string(
doc = "Optional JSX factory override.",
),
"jsx_fragment": attr.string(
doc = "Optional JSX fragment override.",
),
"jsx_import_source": attr.string(
doc = "Optional JSX import source override.",
),
"jsx_runtime": attr.string(
values = ["", "automatic", "classic"],
default = "",
doc = "Optional JSX runtime override.",
),
"jsx_side_effects": attr.bool(
default = False,
doc = "If true, treats JSX as having side effects.",
),
"react_fast_refresh": attr.bool(
default = False,
doc = "If true, enables Bun's React fast refresh transform.",
),
"emit_dce_annotations": attr.bool(
default = False,
doc = "If true, re-emits DCE annotations in the bundle.",
),
"no_bundle": attr.bool(
default = False,
doc = "If true, transpiles without bundling.",
),
"build_flags": attr.string_list(
doc = "Additional raw flags forwarded to `bun build`.",
),
}
bun_build = rule(
implementation = _bun_build_impl,
doc = """Builds one or more entry points with `bun build`.
The rule emits a directory artifact so Bun can materialize multi-file output
graphs such as HTML, CSS, assets, and split chunks. Optional metafile outputs
may be requested with `metafile` and `metafile_md`.
""",
attrs = dict(_COMMON_BUILD_ATTRS, **{
"entry_points": attr.label_list(
mandatory = True,
allow_files = True,
doc = "Entry files to build, including JS/TS or HTML entry points.",
),
"metafile": attr.bool(
default = False,
doc = "If true, emits Bun's JSON metafile alongside the output directory.",
),
"metafile_md": attr.bool(
default = False,
doc = "If true, emits Bun's markdown metafile alongside the output directory.",
),
}),
toolchains = ["//bun:toolchain_type"],
)
bun_compile = rule(
implementation = _bun_compile_impl,
doc = """Compiles a Bun program into a standalone executable with `bun build --compile`.""",
attrs = dict(_COMMON_BUILD_ATTRS, **{
"target": attr.string(
default = "bun",
values = ["browser", "node", "bun"],
doc = "Bun build target environment for the compiled executable.",
),
"entry_point": attr.label(
mandatory = True,
allow_single_file = True,
doc = "Entry file to compile into an executable.",
),
"bytecode": attr.bool(
default = False,
doc = "If true, enables Bun bytecode caching in the compiled executable.",
),
"compile_exec_argv": attr.string_list(
doc = "Repeated `--compile-exec-argv` values prepended to the executable's `execArgv`.",
),
"compile_executable": attr.label(
allow_single_file = True,
doc = "Optional Bun executable used for cross-compilation via `--compile-executable-path`.",
),
"compile_autoload_dotenv": attr.bool(
default = True,
doc = "Whether the compiled executable auto-loads `.env` files at runtime.",
),
"compile_autoload_bunfig": attr.bool(
default = True,
doc = "Whether the compiled executable auto-loads `bunfig.toml` at runtime.",
),
"compile_autoload_tsconfig": attr.bool(
default = False,
doc = "Whether the compiled executable auto-loads `tsconfig.json` at runtime.",
),
"compile_autoload_package_json": attr.bool(
default = False,
doc = "Whether the compiled executable auto-loads `package.json` at runtime.",
),
"windows_hide_console": attr.bool(
default = False,
doc = "When targeting Windows, hides the console window for GUI-style executables.",
),
"windows_icon": attr.string(
doc = "Optional Windows icon path passed directly to Bun.",
),
"windows_title": attr.string(
doc = "Optional Windows executable title.",
),
"windows_publisher": attr.string(
doc = "Optional Windows publisher metadata.",
),
"windows_version": attr.string(
doc = "Optional Windows version metadata.",
),
"windows_description": attr.string(
doc = "Optional Windows description metadata.",
),
"windows_copyright": attr.string(
doc = "Optional Windows copyright metadata.",
),
}),
executable = True,
toolchains = ["//bun:toolchain_type"],
)

View File

@@ -1,140 +0,0 @@
"""Rule for running JS/TS scripts with Bun in watch mode for development."""
load("//internal:bun_command.bzl", "append_flag", "append_flag_values", "append_install_mode", "append_raw_flags")
load("//internal:runtime_launcher.bzl", "declare_runtime_wrapper", "runfiles_path", "runtime_launcher_attrs", "write_launcher_spec")
load("//internal:workspace.bzl", "create_bun_workspace_info", "workspace_runfiles")
def _bun_dev_impl(ctx):
toolchain = ctx.toolchains["//bun:toolchain_type"]
bun_bin = toolchain.bun.bun_bin
entry_point = ctx.file.entry_point
workspace_info = create_bun_workspace_info(
ctx,
extra_files = ctx.files.data + ctx.files.restart_on + ctx.files.preload + ctx.files.env_files + [bun_bin],
primary_file = entry_point,
)
argv = ["--bun", "run"]
append_install_mode(argv, ctx.attr.install_mode)
append_flag(argv, "--no-env-file", ctx.attr.no_env_file)
append_flag(argv, "--smol", ctx.attr.smol)
append_flag_values(argv, "--conditions", ctx.attr.conditions)
append_flag(argv, "--no-clear-screen", ctx.attr.no_clear_screen)
append_raw_flags(argv, ctx.attr.run_flags)
spec_file = write_launcher_spec(ctx, {
"version": 1,
"kind": "bun_run",
"bun_short_path": runfiles_path(bun_bin),
"primary_source_short_path": runfiles_path(entry_point),
"package_json_short_path": "",
"install_metadata_short_path": runfiles_path(workspace_info.install_metadata_file) if workspace_info.install_metadata_file else "",
"install_repo_runfiles_path": workspace_info.install_repo_runfiles_path,
"node_modules_roots": workspace_info.node_modules_roots,
"package_dir_hint": workspace_info.package_dir_hint,
"working_dir_mode": ctx.attr.working_dir,
"inherit_host_path": ctx.attr.inherit_host_path,
"argv": argv,
"args": ctx.attr.args,
"passthrough_args": True,
"tool_short_path": "",
"restart_on": [runfiles_path(file) for file in ctx.files.restart_on],
"watch_mode": ctx.attr.watch_mode,
"reporter": "",
"coverage": False,
"coverage_reporters": [],
"preload_short_paths": [runfiles_path(file) for file in ctx.files.preload],
"env_file_short_paths": [runfiles_path(file) for file in ctx.files.env_files],
"test_short_paths": [],
})
launcher = declare_runtime_wrapper(ctx, bun_bin, spec_file)
return [
workspace_info,
DefaultInfo(
executable = launcher.executable,
runfiles = workspace_runfiles(
ctx,
workspace_info,
direct_files = [launcher.executable, launcher.runner, spec_file],
),
),
]
_BUN_DEV_ATTRS = runtime_launcher_attrs()
_BUN_DEV_ATTRS.update({
"entry_point": attr.label(
mandatory = True,
allow_single_file = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
doc = "Path to the main JS/TS file to execute in dev mode.",
),
"watch_mode": attr.string(
default = "watch",
values = ["watch", "hot"],
doc = "Bun live-reload mode: `watch` (default) or `hot`.",
),
"restart_on": attr.label_list(
allow_files = True,
doc = "Files that trigger a full Bun process restart when they change.",
),
"node_modules": attr.label(
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles.",
),
"data": attr.label_list(
allow_files = True,
doc = "Additional runtime files required by the dev process.",
),
"preload": attr.label_list(
allow_files = True,
doc = "Modules to preload with `--preload` before running the entry point.",
),
"env_files": attr.label_list(
allow_files = True,
doc = "Additional environment files loaded with `--env-file`.",
),
"no_env_file": attr.bool(
default = False,
doc = "If true, disables Bun's automatic `.env` loading.",
),
"smol": attr.bool(
default = False,
doc = "If true, enables Bun's lower-memory runtime mode.",
),
"conditions": attr.string_list(
doc = "Custom package resolve conditions passed to Bun.",
),
"install_mode": attr.string(
default = "disable",
values = ["disable", "auto", "fallback", "force"],
doc = "Whether Bun may auto-install missing packages in dev mode.",
),
"no_clear_screen": attr.bool(
default = False,
doc = "If true, disables terminal clearing on Bun reloads.",
),
"run_flags": attr.string_list(
doc = "Additional raw flags forwarded to `bun run` before the entry point.",
),
"working_dir": attr.string(
default = "workspace",
values = ["workspace", "entry_point"],
doc = "Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`.",
),
"inherit_host_path": attr.bool(
default = False,
doc = "If true, appends the host PATH after the staged Bun runtime tool bin and node_modules/.bin entries at runtime.",
),
})
bun_dev = rule(
implementation = _bun_dev_impl,
doc = """Runs a JS/TS entry point in Bun development watch mode.
This rule is intended for local dev loops (`bazel run`) and supports Bun
watch/HMR plus optional full restarts on selected file changes. It is a local
workflow helper rather than a hermetic build rule.
""",
attrs = _BUN_DEV_ATTRS,
executable = True,
toolchains = ["//bun:toolchain_type"],
)

View File

@@ -1,251 +1,5 @@
"""Repository-rule based bun_install implementation."""
_DEFAULT_INSTALL_INPUTS = [
".npmrc",
"bunfig.json",
"bunfig.toml",
]
_MANIFEST_DEP_FIELDS = [
"dependencies",
"devDependencies",
"optionalDependencies",
"peerDependencies",
]
def _normalize_path(path):
normalized = path.replace("\\", "/")
if normalized.endswith("/") and normalized != "/":
normalized = normalized[:-1]
return normalized
def _relative_to_root(root, child):
normalized_root = _normalize_path(root)
normalized_child = _normalize_path(child)
if normalized_child == normalized_root:
return ""
prefix = normalized_root + "/"
if not normalized_child.startswith(prefix):
fail("bun_install: expected install input {} to be under {}".format(child, root))
return normalized_child[len(prefix):]
def _segment_matches(name, pattern):
if pattern == "*":
return True
if "*" not in pattern:
return name == pattern
parts = pattern.split("*")
if len(parts) == 1:
return name == pattern
pos = 0
anchored_start = not pattern.startswith("*")
anchored_end = not pattern.endswith("*")
for i, part in enumerate(parts):
if not part:
continue
match_index = name.find(part, pos)
if match_index < 0:
return False
if i == 0 and anchored_start and match_index != 0:
return False
pos = match_index + len(part)
if anchored_end and parts[-1] and not name.endswith(parts[-1]):
return False
return True
def _walk_workspace_dirs(root, segments):
matches = [root]
for segment in segments:
if segment == "**":
fail("bun_install: `**` is not supported in workspace patterns; use explicit segments or `*`")
next_matches = []
for parent in matches:
for child in parent.readdir():
if child.is_dir and _segment_matches(child.basename, segment):
next_matches.append(child)
matches = next_matches
return matches
def _workspace_patterns(repository_ctx, package_json):
manifest = json.decode(repository_ctx.read(package_json))
workspaces = manifest.get("workspaces", [])
if type(workspaces) == type({}):
workspaces = workspaces.get("packages", [])
if type(workspaces) != type([]):
fail("bun_install: `workspaces` must be a list or an object with a `packages` list")
patterns = []
for pattern in workspaces:
if type(pattern) != type(""):
fail("bun_install: workspace pattern must be a string, got {}".format(type(pattern)))
normalized = "/".join([segment for segment in pattern.split("/") if segment and segment != "."])
if normalized:
patterns.append(normalized)
return patterns
def _validate_catalog_shape(field, value):
if value == None:
return
if type(value) != type({}):
fail("bun_install: `{}` must be an object".format(field))
if field not in ["catalogs", "workspaces.catalogs"]:
return
for name, catalog in value.items():
if type(name) != type(""):
fail("bun_install: `catalogs` keys must be strings, got {}".format(type(name)))
if type(catalog) != type({}):
fail("bun_install: `catalogs.{}` must be an object".format(name))
def _copy_json_value(value):
return json.decode(json.encode(value))
def _package_target_name(package_name):
sanitized = package_name
sanitized = sanitized.replace("@", "at_")
sanitized = sanitized.replace("/", "_")
sanitized = sanitized.replace("-", "_")
sanitized = sanitized.replace(".", "_")
sanitized = sanitized.replace("__", "_").replace("__", "_").replace("__", "_")
sanitized = sanitized.strip("_")
if not sanitized:
sanitized = "package"
return "npm__" + sanitized
def _manifest_dependency_names(manifest):
names = {}
for field in _MANIFEST_DEP_FIELDS:
dependencies = manifest.get(field)
if dependencies == None:
continue
if type(dependencies) != type({}):
fail("bun_install: `{}` must be an object when present".format(field))
for name in dependencies.keys():
names[name] = True
return names
def _normalized_root_manifest(repository_ctx, package_json):
manifest = json.decode(repository_ctx.read(package_json))
workspaces = manifest.get("workspaces")
for field in ["catalog", "catalogs"]:
manifest_value = manifest.get(field)
_validate_catalog_shape(field, manifest_value)
if type(workspaces) != type({}):
continue
workspace_value = workspaces.get(field)
_validate_catalog_shape("workspaces.{}".format(field), workspace_value)
if workspace_value == None:
continue
if manifest_value == None:
manifest[field] = _copy_json_value(workspace_value)
continue
if manifest_value != workspace_value:
fail(
"bun_install: `{}` conflicts with `workspaces.{}`; use one source of truth or keep both values identical".format(field, field),
)
return json.encode(manifest)
def _materialize_workspace_packages(repository_ctx, package_json):
package_root = package_json.dirname
package_root_str = str(package_root)
written = {}
workspace_packages = {}
for pattern in _workspace_patterns(repository_ctx, package_json):
segments = pattern.split("/")
for workspace_dir in _walk_workspace_dirs(package_root, segments):
workspace_package_json = repository_ctx.path(str(workspace_dir) + "/package.json")
if not workspace_package_json.exists:
continue
workspace_dir_str = str(workspace_dir)
if workspace_dir_str == package_root_str:
continue
relative_dir = _relative_to_root(package_root_str, workspace_dir_str)
if relative_dir in written:
continue
repository_ctx.file(
relative_dir + "/package.json",
repository_ctx.read(workspace_package_json),
)
written[relative_dir] = True
manifest = json.decode(repository_ctx.read(workspace_package_json))
package_name = manifest.get("name")
workspace_packages[relative_dir] = package_name if type(package_name) == type("") else ""
package_dirs = sorted(workspace_packages.keys())
package_names_by_dir = {}
for package_dir in package_dirs:
package_name = workspace_packages[package_dir]
if package_name:
package_names_by_dir[package_dir] = package_name
return struct(
package_dirs = package_dirs,
package_names_by_dir = package_names_by_dir,
package_names = [workspace_packages[package_dir] for package_dir in package_dirs if workspace_packages[package_dir]],
)
def _materialize_install_inputs(repository_ctx, package_json):
package_root = package_json.dirname
package_root_str = str(package_root)
written = {}
for relative_path in _DEFAULT_INSTALL_INPUTS:
source_path = repository_ctx.path(str(package_root) + "/" + relative_path)
if source_path.exists and not source_path.is_dir:
repository_ctx.file(relative_path, repository_ctx.read(source_path))
written[relative_path] = True
for install_input in repository_ctx.attr.install_inputs:
source_path = repository_ctx.path(install_input)
if not source_path.exists:
fail("bun_install: install input not found: {}".format(install_input))
if source_path.is_dir:
fail("bun_install: install_inputs must be files under the package root: {}".format(install_input))
relative_path = _relative_to_root(package_root_str, str(source_path))
if not relative_path:
fail("bun_install: install input must be a file under the package root: {}".format(install_input))
if relative_path in written:
continue
repository_ctx.file(relative_path, repository_ctx.read(source_path))
written[relative_path] = True
def _select_bun_binary(repository_ctx):
os_name = repository_ctx.os.name.lower()
arch = repository_ctx.os.arch.lower()
@@ -265,67 +19,6 @@ def _select_bun_binary(repository_ctx):
fail("Unsupported host platform: os={}, arch={}".format(repository_ctx.os.name, repository_ctx.os.arch))
def _render_package_targets_file(package_names):
lines = ["NPM_PACKAGE_TARGETS = {"]
for package_name in package_names:
lines.append(' "{}": "{}",'.format(package_name, _package_target_name(package_name)))
lines.extend([
"}",
"",
])
return "\n".join(lines)
def _render_repo_defs_bzl(repo_name):
return """load(":packages.bzl", "NPM_PACKAGE_TARGETS")
def package_target_name(package_name):
return NPM_PACKAGE_TARGETS.get(package_name)
def npm_link_all_packages(name = "node_modules", imported_links = []):
if not native.existing_rule(name):
native.alias(
name = name,
actual = "@{repo_name}//:node_modules",
)
requested = {{}}
for package_name in imported_links:
requested[package_name] = True
for package_name, target_name in NPM_PACKAGE_TARGETS.items():
if imported_links and package_name not in requested:
continue
if native.existing_rule(target_name):
continue
native.alias(
name = target_name,
actual = "@{repo_name}//:%s" % target_name,
)
""".format(repo_name = repo_name)
def _render_repo_build(package_names):
lines = [
'exports_files(["defs.bzl", "packages.bzl"])',
"",
"filegroup(",
' name = "node_modules",',
' srcs = glob(["**/node_modules/**"], allow_empty = False),',
' visibility = ["//visibility:public"],',
")",
"",
]
for package_name in package_names:
lines.extend([
"filegroup(",
' name = "{}",'.format(_package_target_name(package_name)),
' srcs = glob(["node_modules/{}/**"], allow_empty = True),'.format(package_name),
' visibility = ["//visibility:public"],',
")",
"",
])
return "\n".join(lines)
def _bun_install_repository_impl(repository_ctx):
package_json = repository_ctx.path(repository_ctx.attr.package_json)
@@ -338,45 +31,19 @@ def _bun_install_repository_impl(repository_ctx):
fail("bun_install: bun_lockfile not found: {}".format(repository_ctx.attr.bun_lockfile))
bun_bin = _select_bun_binary(repository_ctx)
lockfile_name = bun_lockfile.basename
root_manifest = json.decode(repository_ctx.read(package_json))
if lockfile_name not in ["bun.lock", "bun.lockb"]:
lockfile_name = "bun.lock"
repository_ctx.symlink(package_json, "package.json")
repository_ctx.symlink(bun_lockfile, "bun.lockb")
repository_ctx.file("package.json", _normalized_root_manifest(repository_ctx, package_json))
repository_ctx.symlink(bun_lockfile, lockfile_name)
_materialize_install_inputs(repository_ctx, package_json)
workspace_packages = _materialize_workspace_packages(repository_ctx, package_json)
install_args = [str(bun_bin), "--bun", "install", "--frozen-lockfile", "--no-progress"]
if repository_ctx.attr.production:
install_args.append("--production")
for omit in repository_ctx.attr.omit:
install_args.extend(["--omit", omit])
if repository_ctx.attr.linker:
install_args.extend(["--linker", repository_ctx.attr.linker])
if repository_ctx.attr.backend:
install_args.extend(["--backend", repository_ctx.attr.backend])
if repository_ctx.attr.ignore_scripts:
install_args.append("--ignore-scripts")
install_args.extend(repository_ctx.attr.install_flags)
if repository_ctx.attr.isolated_home:
result = repository_ctx.execute(
install_args,
timeout = 600,
quiet = False,
environment = {"HOME": str(repository_ctx.path("."))},
)
else:
result = repository_ctx.execute(
install_args,
timeout = 600,
quiet = False,
)
result = repository_ctx.execute(
[str(bun_bin), "install", "--frozen-lockfile", "--no-progress"],
timeout = 600,
quiet = False,
environment = {"HOME": str(repository_ctx.path("."))},
)
if result.return_code:
fail("""bun_install failed running `bun --bun install --frozen-lockfile`.
fail("""bun_install failed running `bun install --frozen-lockfile`.
stdout:
{}
stderr:
@@ -384,78 +51,39 @@ stderr:
""".format(result.stdout, result.stderr))
repository_ctx.file(
"node_modules/.rules_bun/install.json",
json.encode({
"bun_lockfile": lockfile_name,
"install_root_rel_dir": ".",
"package_json": "package.json",
"workspace_package_dirs": workspace_packages.package_dirs,
"workspace_package_names_by_dir": workspace_packages.package_names_by_dir,
}) + "\n",
"BUILD.bazel",
"""filegroup(
name = "node_modules",
srcs = glob(["node_modules/**"], allow_empty = False),
visibility = ["//visibility:public"],
)
""",
)
package_names = {}
for package_name in _manifest_dependency_names(root_manifest).keys():
package_names[package_name] = True
for package_name in workspace_packages.package_names:
package_names[package_name] = True
sorted_package_names = sorted(package_names.keys())
visible_repo_name = repository_ctx.attr.visible_repo_name or repository_ctx.name
repository_ctx.file("packages.bzl", _render_package_targets_file(sorted_package_names))
repository_ctx.file("defs.bzl", _render_repo_defs_bzl(visible_repo_name))
repository_ctx.file("BUILD.bazel", _render_repo_build(sorted_package_names))
bun_install_repository = repository_rule(
implementation = _bun_install_repository_impl,
attrs = {
"package_json": attr.label(mandatory = True, allow_single_file = True),
"bun_lockfile": attr.label(mandatory = True, allow_single_file = True),
"install_inputs": attr.label_list(allow_files = True),
"isolated_home": attr.bool(default = True),
"production": attr.bool(default = False),
"omit": attr.string_list(),
"linker": attr.string(),
"backend": attr.string(),
"ignore_scripts": attr.bool(default = True),
"install_flags": attr.string_list(),
"visible_repo_name": attr.string(),
"bun_linux_x64": attr.label(default = "@bun_linux_x64//:bun-linux-x64/bun", allow_single_file = True),
"bun_linux_aarch64": attr.label(default = "@bun_linux_aarch64//:bun-linux-aarch64/bun", allow_single_file = True),
"bun_darwin_x64": attr.label(default = "@bun_darwin_x64//:bun-darwin-x64/bun", allow_single_file = True),
"bun_darwin_aarch64": attr.label(default = "@bun_darwin_aarch64//:bun-darwin-aarch64/bun", allow_single_file = True),
"bun_windows_x64": attr.label(default = "@bun_windows_x64//:bun-windows-x64/bun.exe", allow_single_file = True),
"bun_linux_x64": attr.label(default = "@bun_linux_x64//:bun", allow_single_file = True),
"bun_linux_aarch64": attr.label(default = "@bun_linux_aarch64//:bun", allow_single_file = True),
"bun_darwin_x64": attr.label(default = "@bun_darwin_x64//:bun", allow_single_file = True),
"bun_darwin_aarch64": attr.label(default = "@bun_darwin_aarch64//:bun", allow_single_file = True),
"bun_windows_x64": attr.label(default = "@bun_windows_x64//:bun", allow_single_file = True),
},
)
def bun_install(
name,
package_json,
bun_lockfile,
install_inputs = [],
isolated_home = True,
production = False,
omit = [],
linker = "",
backend = "",
ignore_scripts = True,
install_flags = []):
_bun_install_repository = bun_install_repository
def bun_install(name, package_json, bun_lockfile):
"""Create an external repository containing installed node_modules.
Args:
name: Repository name to create.
package_json: Label to a package.json file.
bun_lockfile: Label to a bun.lockb file.
install_inputs: Optional additional files under the package root to copy
into the install context, such as patch files or auth/config files.
isolated_home: Whether to run Bun with HOME set to the generated
repository root for a more isolated install context.
production: Whether to omit devDependencies during install.
omit: Optional Bun dependency groups to omit, such as `dev` or `peer`.
linker: Optional Bun linker strategy, such as `isolated` or `hoisted`.
backend: Optional Bun install backend, such as `hardlink` or `copyfile`.
ignore_scripts: Whether to skip lifecycle scripts in the project manifest.
install_flags: Additional raw flags forwarded to `bun install`.
Usage (WORKSPACE):
bun_install(
@@ -469,13 +97,4 @@ def bun_install(
name = name,
package_json = package_json,
bun_lockfile = bun_lockfile,
install_inputs = install_inputs,
isolated_home = isolated_home,
production = production,
omit = omit,
linker = linker,
backend = backend,
ignore_scripts = ignore_scripts,
install_flags = install_flags,
visible_repo_name = name,
)

View File

@@ -1,169 +0,0 @@
"""Rule for running package.json scripts with Bun."""
load("//internal:bun_command.bzl", "append_flag", "append_flag_value", "append_flag_values", "append_install_mode", "append_raw_flags")
load("//internal:runtime_launcher.bzl", "declare_runtime_wrapper", "runfiles_path", "runtime_launcher_attrs", "write_launcher_spec")
load("//internal:workspace.bzl", "create_bun_workspace_info", "workspace_runfiles")
def _bun_script_impl(ctx):
toolchain = ctx.toolchains["//bun:toolchain_type"]
bun_bin = toolchain.bun.bun_bin
package_json = ctx.file.package_json
workspace_info = create_bun_workspace_info(
ctx,
extra_files = ctx.files.data + ctx.files.preload + ctx.files.env_files + [bun_bin],
package_dir_hint = package_json.dirname or ".",
package_json = package_json,
primary_file = package_json,
)
argv = ["--bun", "run"]
append_install_mode(argv, ctx.attr.install_mode)
append_flag(argv, "--no-env-file", ctx.attr.no_env_file)
append_flag(argv, "--smol", ctx.attr.smol)
append_flag_values(argv, "--conditions", ctx.attr.conditions)
append_flag(argv, "--workspaces", ctx.attr.workspaces)
append_flag_values(argv, "--filter", ctx.attr.filters)
if ctx.attr.execution_mode == "parallel":
append_flag(argv, "--parallel", True)
elif ctx.attr.execution_mode == "sequential":
append_flag(argv, "--sequential", True)
append_flag(argv, "--no-exit-on-error", ctx.attr.no_exit_on_error)
append_flag_value(argv, "--shell", ctx.attr.shell)
append_flag(argv, "--silent", ctx.attr.silent)
append_raw_flags(argv, ctx.attr.run_flags)
spec_file = write_launcher_spec(ctx, {
"version": 1,
"kind": "bun_run",
"bun_short_path": runfiles_path(bun_bin),
"primary_source_short_path": "",
"package_json_short_path": runfiles_path(package_json),
"install_metadata_short_path": runfiles_path(workspace_info.install_metadata_file) if workspace_info.install_metadata_file else "",
"install_repo_runfiles_path": workspace_info.install_repo_runfiles_path,
"node_modules_roots": workspace_info.node_modules_roots,
"package_dir_hint": package_json.dirname or ".",
"working_dir_mode": ctx.attr.working_dir,
"inherit_host_path": ctx.attr.inherit_host_path,
"argv": argv,
"args": [ctx.attr.script] + ctx.attr.args,
"passthrough_args": True,
"tool_short_path": "",
"restart_on": [],
"watch_mode": "",
"reporter": "",
"coverage": False,
"coverage_reporters": [],
"preload_short_paths": [runfiles_path(file) for file in ctx.files.preload],
"env_file_short_paths": [runfiles_path(file) for file in ctx.files.env_files],
"test_short_paths": [],
})
launcher = declare_runtime_wrapper(ctx, bun_bin, spec_file)
return [
workspace_info,
DefaultInfo(
executable = launcher.executable,
runfiles = workspace_runfiles(
ctx,
workspace_info,
direct_files = [launcher.executable, launcher.runner, spec_file],
),
),
]
_BUN_SCRIPT_ATTRS = runtime_launcher_attrs()
_BUN_SCRIPT_ATTRS.update({
"script": attr.string(
mandatory = True,
doc = "Name of the `package.json` script to execute via `bun run <script>`.",
),
"package_json": attr.label(
mandatory = True,
allow_single_file = True,
doc = "Label of the `package.json` file containing the named script.",
),
"node_modules": attr.label(
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles. The staged Bun runtime tool bin and executables from `node_modules/.bin` are added to `PATH`, which is useful for scripts such as `vite`.",
),
"data": attr.label_list(
allow_files = True,
doc = "Additional runtime files required by the script.",
),
"preload": attr.label_list(
allow_files = True,
doc = "Modules to preload with `--preload` before running the script.",
),
"env_files": attr.label_list(
allow_files = True,
doc = "Additional environment files loaded with `--env-file`.",
),
"no_env_file": attr.bool(
default = False,
doc = "If true, disables Bun's automatic `.env` loading.",
),
"smol": attr.bool(
default = False,
doc = "If true, enables Bun's lower-memory runtime mode.",
),
"conditions": attr.string_list(
doc = "Custom package resolve conditions passed to Bun.",
),
"install_mode": attr.string(
default = "disable",
values = ["disable", "auto", "fallback", "force"],
doc = "Whether Bun may auto-install missing packages while running the script.",
),
"filters": attr.string_list(
doc = "Workspace package filters passed via repeated `--filter` flags.",
),
"workspaces": attr.bool(
default = False,
doc = "If true, runs the script in all workspace packages.",
),
"execution_mode": attr.string(
default = "single",
values = ["single", "parallel", "sequential"],
doc = "How Bun should execute matching workspace scripts.",
),
"no_exit_on_error": attr.bool(
default = False,
doc = "If true, Bun keeps running other workspace scripts when one fails.",
),
"shell": attr.string(
default = "",
values = ["", "bun", "system"],
doc = "Optional shell implementation for package scripts.",
),
"silent": attr.bool(
default = False,
doc = "If true, suppresses Bun's command echo for package scripts.",
),
"run_flags": attr.string_list(
doc = "Additional raw flags forwarded to `bun run` before the script name.",
),
"working_dir": attr.string(
default = "package",
values = ["workspace", "package"],
doc = "Working directory at runtime: Bazel runfiles `workspace` root or the directory containing `package.json`. The default `package` mode matches tools such as Vite that resolve config and assets relative to the package directory.",
),
"inherit_host_path": attr.bool(
default = False,
doc = "If true, appends the host PATH after the staged Bun runtime tool bin and node_modules/.bin entries at runtime.",
),
})
bun_script = rule(
implementation = _bun_script_impl,
doc = """Runs a named `package.json` script with Bun as an executable target.
Use this rule to expose existing package scripts such as `dev`, `build`, or
`check` via `bazel run` without adding wrapper shell scripts. This is a good fit
for Vite-style workflows, where scripts like `vite dev` or `vite build` are
declared in `package.json` and expect to run from the package directory with
the staged Bun runtime tool bin and `node_modules/.bin` on `PATH`. This is a
local workflow helper rather than a hermetic build rule.
""",
attrs = _BUN_SCRIPT_ATTRS,
executable = True,
toolchains = ["//bun:toolchain_type"],
)

View File

@@ -1,198 +1,77 @@
"""Rule for running test suites with Bun."""
load("//internal:bun_command.bzl", "append_flag", "append_flag_value", "append_install_mode", "append_raw_flags")
load("//internal:js_library.bzl", "collect_js_runfiles")
load("//internal:runtime_launcher.bzl", "declare_runtime_wrapper", "runfiles_path", "runtime_launcher_attrs", "write_launcher_spec")
load("//internal:workspace.bzl", "create_bun_workspace_info", "workspace_runfiles")
load("//internal:js_library.bzl", "BunSourcesInfo")
def _shell_quote(value):
return "'" + value.replace("'", "'\"'\"'") + "'"
def _bun_test_impl(ctx):
if ctx.attr.install_mode != "disable":
fail("bun_test requires install_mode = \"disable\" for hermetic test execution")
toolchain = ctx.toolchains["//bun:toolchain_type"]
bun_bin = toolchain.bun.bun_bin
primary_file = ctx.files.srcs[0]
dep_runfiles = [collect_js_runfiles(dep) for dep in ctx.attr.deps]
workspace_info = create_bun_workspace_info(
ctx,
extra_files = ctx.files.srcs + ctx.files.data + ctx.files.preload + ctx.files.env_files + [bun_bin],
primary_file = primary_file,
src_args = " ".join([_shell_quote(src.short_path) for src in ctx.files.srcs])
launcher = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(
output = launcher,
is_executable = True,
content = """#!/usr/bin/env bash
set -euo pipefail
runfiles_dir="${{RUNFILES_DIR:-$0.runfiles}}"
bun_bin="${{runfiles_dir}}/_main/{bun_short_path}"
cd "${{runfiles_dir}}/_main"
if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" && -n "${{COVERAGE_DIR:-}}" ]]; then
exec "${{bun_bin}}" test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" --coverage "$@"
fi
if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" ]]; then
exec "${{bun_bin}}" test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" "$@"
fi
if [[ -n "${{COVERAGE_DIR:-}}" ]]; then
exec "${{bun_bin}}" test {src_args} --coverage "$@"
fi
exec "${{bun_bin}}" test {src_args} "$@"
""".format(
bun_short_path = bun_bin.short_path,
src_args = src_args,
),
)
argv = ["--bun", "test"]
append_install_mode(argv, ctx.attr.install_mode)
append_flag(argv, "--no-env-file", ctx.attr.no_env_file)
append_flag(argv, "--smol", ctx.attr.smol)
append_flag_value(argv, "--timeout", str(ctx.attr.timeout_ms) if ctx.attr.timeout_ms > 0 else None)
append_flag(argv, "--update-snapshots", ctx.attr.update_snapshots)
append_flag_value(argv, "--rerun-each", str(ctx.attr.rerun_each) if ctx.attr.rerun_each > 0 else None)
append_flag_value(argv, "--retry", str(ctx.attr.retry) if ctx.attr.retry > 0 else None)
append_flag(argv, "--todo", ctx.attr.todo)
append_flag(argv, "--only", ctx.attr.only)
append_flag(argv, "--pass-with-no-tests", ctx.attr.pass_with_no_tests)
append_flag(argv, "--concurrent", ctx.attr.concurrent)
append_flag(argv, "--randomize", ctx.attr.randomize)
append_flag_value(argv, "--seed", str(ctx.attr.seed) if ctx.attr.seed > 0 else None)
append_flag_value(argv, "--bail", str(ctx.attr.bail) if ctx.attr.bail > 0 else None)
append_flag_value(argv, "--max-concurrency", str(ctx.attr.max_concurrency) if ctx.attr.max_concurrency > 0 else None)
append_raw_flags(argv, ctx.attr.test_flags)
transitive_files = []
if ctx.attr.node_modules:
transitive_files.append(ctx.attr.node_modules[DefaultInfo].files)
for dep in ctx.attr.deps:
if BunSourcesInfo in dep:
transitive_files.append(dep[BunSourcesInfo].transitive_sources)
else:
transitive_files.append(dep[DefaultInfo].files)
spec_file = write_launcher_spec(ctx, {
"version": 1,
"kind": "bun_test",
"bun_short_path": runfiles_path(bun_bin),
"primary_source_short_path": runfiles_path(primary_file),
"package_json_short_path": "",
"install_metadata_short_path": runfiles_path(workspace_info.install_metadata_file) if workspace_info.install_metadata_file else "",
"install_repo_runfiles_path": workspace_info.install_repo_runfiles_path,
"node_modules_roots": workspace_info.node_modules_roots,
"package_dir_hint": workspace_info.package_dir_hint,
"working_dir_mode": "workspace",
"inherit_host_path": ctx.attr.inherit_host_path,
"argv": argv,
"args": ctx.attr.args,
"passthrough_args": True,
"tool_short_path": "",
"restart_on": [],
"watch_mode": "",
"reporter": ctx.attr.reporter,
"coverage": ctx.attr.coverage,
"coverage_reporters": ctx.attr.coverage_reporters,
"preload_short_paths": [runfiles_path(file) for file in ctx.files.preload],
"env_file_short_paths": [runfiles_path(file) for file in ctx.files.env_files],
"test_short_paths": [runfiles_path(file) for file in ctx.files.srcs],
})
launcher = declare_runtime_wrapper(ctx, bun_bin, spec_file)
runfiles = ctx.runfiles(
files = [bun_bin] + ctx.files.srcs + ctx.files.data,
transitive_files = depset(transitive = transitive_files),
)
return [
workspace_info,
DefaultInfo(
executable = launcher.executable,
runfiles = workspace_runfiles(
ctx,
workspace_info,
direct_files = [launcher.executable, launcher.runner, spec_file],
transitive_files = dep_runfiles,
),
executable = launcher,
runfiles = runfiles,
),
]
_BUN_TEST_ATTRS = runtime_launcher_attrs()
_BUN_TEST_ATTRS.update({
"srcs": attr.label_list(
mandatory = True,
allow_files = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
doc = "Test source files passed to `bun test`.",
),
"node_modules": attr.label(
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles.",
),
"deps": attr.label_list(
doc = "Library dependencies required by test sources.",
),
"data": attr.label_list(
allow_files = True,
doc = "Additional runtime files needed by tests.",
),
"preload": attr.label_list(
allow_files = True,
doc = "Modules to preload with `--preload` before running tests.",
),
"env_files": attr.label_list(
allow_files = True,
doc = "Additional environment files loaded with `--env-file`.",
),
"no_env_file": attr.bool(
default = False,
doc = "If true, disables Bun's automatic `.env` loading.",
),
"smol": attr.bool(
default = False,
doc = "If true, enables Bun's lower-memory runtime mode.",
),
"install_mode": attr.string(
default = "disable",
values = ["disable", "auto", "fallback", "force"],
doc = "Whether Bun may auto-install missing packages while testing.",
),
"timeout_ms": attr.int(
default = 0,
doc = "Optional per-test timeout in milliseconds.",
),
"update_snapshots": attr.bool(
default = False,
doc = "If true, updates Bun snapshot files.",
),
"rerun_each": attr.int(
default = 0,
doc = "Optional number of times to rerun each test file.",
),
"retry": attr.int(
default = 0,
doc = "Optional default retry count for all tests.",
),
"todo": attr.bool(
default = False,
doc = "If true, includes tests marked with `test.todo()`.",
),
"only": attr.bool(
default = False,
doc = "If true, runs only tests marked with `test.only()` or `describe.only()`.",
),
"pass_with_no_tests": attr.bool(
default = False,
doc = "If true, exits successfully when no tests are found.",
),
"concurrent": attr.bool(
default = False,
doc = "If true, treats all tests as concurrent tests.",
),
"randomize": attr.bool(
default = False,
doc = "If true, runs tests in random order.",
),
"seed": attr.int(
default = 0,
doc = "Optional randomization seed.",
),
"bail": attr.int(
default = 0,
doc = "Optional failure count after which Bun exits the test run.",
),
"reporter": attr.string(
default = "console",
values = ["console", "dots", "junit"],
doc = "Test reporter format.",
),
"max_concurrency": attr.int(
default = 0,
doc = "Optional maximum number of concurrent tests.",
),
"coverage": attr.bool(
default = False,
doc = "If true, always enables Bun coverage output.",
),
"coverage_reporters": attr.string_list(
doc = "Repeated Bun coverage reporters such as `text` or `lcov`.",
),
"test_flags": attr.string_list(
doc = "Additional raw flags forwarded to `bun test` before the test source list.",
),
"inherit_host_path": attr.bool(
default = False,
doc = "If true, appends the host PATH after the staged Bun runtime tool bin and node_modules/.bin entries at runtime.",
),
})
bun_test = rule(
implementation = _bun_test_impl,
doc = """Runs Bun tests as a Bazel test target.
Supports Bazel test filtering (`--test_filter`) and coverage integration. Tests
run with strict install-mode semantics and do not inherit the host PATH unless
explicitly requested.
""",
attrs = _BUN_TEST_ATTRS,
attrs = {
"srcs": attr.label_list(
mandatory = True,
allow_files = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
),
"node_modules": attr.label(),
"deps": attr.label_list(),
"data": attr.label_list(allow_files = True),
},
test = True,
toolchains = ["//bun:toolchain_type"],
)

View File

@@ -1,29 +0,0 @@
"""rules_js-style compatibility exports backed by Bun."""
load("//internal:bun_binary.bzl", _bun_binary = "bun_binary")
load("//internal:bun_test.bzl", _bun_test = "bun_test")
load("//internal:js_library.bzl", _JsInfo = "JsInfo", _js_library = "js_library", _ts_library = "ts_library")
load("//internal:js_run_devserver.bzl", _js_run_devserver = "js_run_devserver")
JsInfo = _JsInfo
js_library = _js_library
ts_library = _ts_library
js_run_devserver = _js_run_devserver
def js_binary(name, **kwargs):
_bun_binary(name = name, **kwargs)
def js_test(name, entry_point = None, srcs = None, **kwargs):
if entry_point != None:
if srcs != None:
fail("js_test accepts either `entry_point` or `srcs`, but not both")
srcs = [entry_point]
if srcs == None:
fail("js_test requires `entry_point` or `srcs`")
_bun_test(
name = name,
srcs = srcs,
**kwargs
)

View File

@@ -1,116 +1,40 @@
"""Lightweight JS/TS source grouping rules."""
JsInfo = provider(
doc = "Provides transitive JavaScript/TypeScript metadata for Bun and JS compatibility rules.",
fields = {
"sources": "Direct source files owned by this target.",
"transitive_sources": "Transitive source files from this target and its deps.",
"types": "Direct type files owned by this target.",
"transitive_types": "Transitive type files from this target and its deps.",
"data_files": "Direct runtime data files owned by this target.",
"transitive_runfiles": "Transitive runtime files from this target and its deps.",
},
)
BunSourcesInfo = provider(fields = ["transitive_sources"])
BunSourcesInfo = provider(
"Provides transitive sources for Bun libraries.",
fields = ["transitive_sources"],
)
def collect_js_sources(dep):
if JsInfo in dep:
return dep[JsInfo].transitive_sources
if BunSourcesInfo in dep:
return dep[BunSourcesInfo].transitive_sources
return dep[DefaultInfo].files
def collect_js_runfiles(dep):
if JsInfo in dep:
return dep[JsInfo].transitive_runfiles
if BunSourcesInfo in dep:
return dep[BunSourcesInfo].transitive_sources
return dep[DefaultInfo].files
def _bun_library_impl(ctx):
transitive_sources = [collect_js_sources(dep) for dep in ctx.attr.deps]
transitive_types = [
dep[JsInfo].transitive_types
transitive_sources = [
dep[BunSourcesInfo].transitive_sources
for dep in ctx.attr.deps
if JsInfo in dep
if BunSourcesInfo in dep
]
transitive_runfiles = [collect_js_runfiles(dep) for dep in ctx.attr.deps]
all_sources = depset(
direct = ctx.files.srcs,
transitive = transitive_sources,
)
all_types = depset(
direct = ctx.files.types,
transitive = transitive_types,
)
all_runfiles = depset(
direct = ctx.files.srcs + ctx.files.types + ctx.files.data,
transitive = transitive_runfiles,
)
default_files = depset(
direct = ctx.files.srcs + ctx.files.types + ctx.files.data,
transitive = transitive_sources + transitive_types + transitive_runfiles,
)
js_info = JsInfo(
sources = depset(ctx.files.srcs),
transitive_sources = all_sources,
types = depset(ctx.files.types),
transitive_types = all_types,
data_files = depset(ctx.files.data),
transitive_runfiles = all_runfiles,
)
return [
js_info,
BunSourcesInfo(transitive_sources = all_sources),
DefaultInfo(files = default_files),
DefaultInfo(files = all_sources),
]
js_library = rule(
implementation = _bun_library_impl,
doc = "Aggregates JavaScript sources and transitive Bun source dependencies.",
attrs = {
"srcs": attr.label_list(
allow_files = [".js", ".jsx", ".mjs", ".cjs"],
doc = "JavaScript source files in this library.",
),
"types": attr.label_list(
allow_files = [".d.ts"],
doc = "Optional declaration files associated with this library.",
),
"data": attr.label_list(
allow_files = True,
doc = "Optional runtime files propagated to dependents.",
),
"deps": attr.label_list(
doc = "Other Bun source libraries to include transitively.",
),
"deps": attr.label_list(),
},
)
ts_library = rule(
implementation = _bun_library_impl,
doc = "Aggregates TypeScript sources and transitive Bun source dependencies.",
attrs = {
"srcs": attr.label_list(
allow_files = [".ts", ".tsx"],
doc = "TypeScript source files in this library.",
),
"types": attr.label_list(
allow_files = [".d.ts"],
doc = "Optional declaration files associated with this library.",
),
"data": attr.label_list(
allow_files = True,
doc = "Optional runtime files propagated to dependents.",
),
"deps": attr.label_list(
doc = "Other Bun source libraries to include transitively.",
),
"deps": attr.label_list(),
},
)

View File

@@ -1,111 +0,0 @@
"""Compatibility rule for running an executable target as a dev server."""
load("//internal:js_library.bzl", "collect_js_runfiles")
load("//internal:runtime_launcher.bzl", "declare_runtime_wrapper", "runfiles_path", "runtime_launcher_attrs", "write_launcher_spec")
load("//internal:workspace.bzl", "create_bun_workspace_info", "workspace_runfiles")
def _js_run_devserver_impl(ctx):
toolchain = ctx.toolchains["//bun:toolchain_type"]
bun_bin = toolchain.bun.bun_bin
package_json = ctx.file.package_json
dep_runfiles = [collect_js_runfiles(dep) for dep in ctx.attr.deps]
tool_default_info = ctx.attr.tool[DefaultInfo]
workspace_info = create_bun_workspace_info(
ctx,
primary_file = package_json or tool_default_info.files_to_run.executable,
package_json = package_json,
package_dir_hint = ctx.attr.package_dir_hint,
extra_files = ctx.files.data + [bun_bin, tool_default_info.files_to_run.executable],
)
spec_file = write_launcher_spec(ctx, {
"version": 1,
"kind": "tool_exec",
"bun_short_path": runfiles_path(bun_bin),
"primary_source_short_path": runfiles_path(package_json) if package_json else runfiles_path(tool_default_info.files_to_run.executable),
"package_json_short_path": runfiles_path(package_json) if package_json else "",
"install_metadata_short_path": runfiles_path(workspace_info.install_metadata_file) if workspace_info.install_metadata_file else "",
"install_repo_runfiles_path": workspace_info.install_repo_runfiles_path,
"node_modules_roots": workspace_info.node_modules_roots,
"package_dir_hint": ctx.attr.package_dir_hint,
"working_dir_mode": ctx.attr.working_dir,
"inherit_host_path": ctx.attr.inherit_host_path,
"argv": [],
"args": ctx.attr.args,
"passthrough_args": True,
"tool_short_path": runfiles_path(tool_default_info.files_to_run.executable),
"restart_on": [],
"watch_mode": "",
"reporter": "",
"coverage": False,
"coverage_reporters": [],
"preload_short_paths": [],
"env_file_short_paths": [],
"test_short_paths": [],
})
launcher = declare_runtime_wrapper(ctx, bun_bin, spec_file)
return [
workspace_info,
DefaultInfo(
executable = launcher.executable,
runfiles = workspace_runfiles(
ctx,
workspace_info,
direct_files = [launcher.executable, launcher.runner, spec_file, tool_default_info.files_to_run.executable],
transitive_files = dep_runfiles,
).merge(tool_default_info.default_runfiles),
),
]
_JS_RUN_DEVSERVER_ATTRS = runtime_launcher_attrs()
_JS_RUN_DEVSERVER_ATTRS.update({
"tool": attr.label(
mandatory = True,
executable = True,
cfg = "target",
doc = "Executable target to launch as the dev server.",
),
"package_json": attr.label(
allow_single_file = True,
doc = "Optional package.json used to resolve the package working directory.",
),
"package_dir_hint": attr.string(
default = ".",
doc = "Optional package-relative directory hint when package_json is not supplied.",
),
"node_modules": attr.label(
doc = "Optional label providing package files from a node_modules tree, typically produced by bun_install or npm_translate_lock, in runfiles.",
),
"deps": attr.label_list(
doc = "Library dependencies required by the dev server.",
),
"data": attr.label_list(
allow_files = True,
doc = "Additional runtime files required by the dev server.",
),
"working_dir": attr.string(
default = "workspace",
values = ["workspace", "package"],
doc = "Working directory at runtime: Bazel runfiles workspace root or the resolved package directory.",
),
"inherit_host_path": attr.bool(
default = False,
doc = "If true, appends the host PATH after the staged Bun runtime tool bin and node_modules/.bin entries at runtime.",
),
})
js_run_devserver = rule(
implementation = _js_run_devserver_impl,
doc = """Runs an executable target from a staged JS workspace.
This is a Bun-backed compatibility adapter for `rules_js`-style devserver
targets. It stages the same runtime workspace as the Bun rules, then executes
the provided tool with any default arguments. It is intended for local
development workflows rather than hermetic build execution.
""",
attrs = _JS_RUN_DEVSERVER_ATTRS,
executable = True,
toolchains = ["//bun:toolchain_type"],
)

View File

@@ -1,173 +0,0 @@
"""Shared launcher spec and OS-native wrapper helpers for runtime rules."""
_RUNTIME_LAUNCHER = Label("//internal:runtime_launcher.js")
_WINDOWS_CONSTRAINT = Label("@platforms//os:windows")
_POSIX_WRAPPER_TEMPLATE = """#!/bin/sh
set -eu
self="$0"
runfiles_dir="${RUNFILES_DIR:-}"
manifest="${RUNFILES_MANIFEST_FILE:-}"
if [ -n "${runfiles_dir}" ] && [ -d "${runfiles_dir}" ]; then
:
elif [ -n "${manifest}" ] && [ -f "${manifest}" ]; then
:
elif [ -d "${self}.runfiles" ]; then
runfiles_dir="${self}.runfiles"
elif [ -f "${self}.runfiles_manifest" ]; then
manifest="${self}.runfiles_manifest"
elif [ -f "${self}.exe.runfiles_manifest" ]; then
manifest="${self}.exe.runfiles_manifest"
else
echo "rules_bun: unable to locate runfiles for ${self}" >&2
exit 1
fi
rlocation() {
path="$1"
if [ -n "${runfiles_dir}" ]; then
printf '%s\\n' "${runfiles_dir}/${path}"
return 0
fi
result=""
while IFS= read -r line; do
case "${line}" in
"${path} "*)
result="${line#${path} }"
break
;;
esac
done < "${manifest}"
if [ -z "${result}" ]; then
echo "rules_bun: missing runfile ${path}" >&2
exit 1
fi
printf '%s\\n' "${result}"
}
bun_bin="$(rlocation "__BUN_RUNFILES_PATH__")"
runner="$(rlocation "__RUNNER_RUNFILES_PATH__")"
spec="$(rlocation "__SPEC_RUNFILES_PATH__")"
export RULES_BUN_LAUNCHER_PATH="${self}"
if [ -n "${runfiles_dir}" ]; then
export RULES_BUN_RUNFILES_DIR="${runfiles_dir}"
fi
if [ -n "${manifest}" ]; then
export RULES_BUN_RUNFILES_MANIFEST="${manifest}"
fi
exec "${bun_bin}" --bun "${runner}" "${spec}" "$@"
"""
_CMD_WRAPPER_TEMPLATE = """@echo off
setlocal
set "SELF=%~f0"
set "RUNFILES_DIR_VALUE=%RUNFILES_DIR%"
set "RUNFILES_MANIFEST_VALUE=%RUNFILES_MANIFEST_FILE%"
if defined RUNFILES_DIR_VALUE if exist "%RUNFILES_DIR_VALUE%" goto have_runfiles
if defined RUNFILES_MANIFEST_VALUE if exist "%RUNFILES_MANIFEST_VALUE%" goto have_runfiles
if exist "%SELF%.runfiles" (
set "RUNFILES_DIR_VALUE=%SELF%.runfiles"
goto have_runfiles
)
if exist "%SELF%.runfiles_manifest" (
set "RUNFILES_MANIFEST_VALUE=%SELF%.runfiles_manifest"
goto have_runfiles
)
if exist "%~dpn0.runfiles_manifest" (
set "RUNFILES_MANIFEST_VALUE=%~dpn0.runfiles_manifest"
goto have_runfiles
)
echo rules_bun: unable to locate runfiles for "%SELF%" 1>&2
exit /b 1
:have_runfiles
call :rlocation "__BUN_RUNFILES_PATH__" BUN_BIN || exit /b 1
call :rlocation "__RUNNER_RUNFILES_PATH__" RUNNER || exit /b 1
call :rlocation "__SPEC_RUNFILES_PATH__" SPEC || exit /b 1
set "RULES_BUN_LAUNCHER_PATH=%SELF%"
if defined RUNFILES_DIR_VALUE (
set "RULES_BUN_RUNFILES_DIR=%RUNFILES_DIR_VALUE%"
) else (
set "RULES_BUN_RUNFILES_DIR="
)
if defined RUNFILES_MANIFEST_VALUE (
set "RULES_BUN_RUNFILES_MANIFEST=%RUNFILES_MANIFEST_VALUE%"
) else (
set "RULES_BUN_RUNFILES_MANIFEST="
)
"%BUN_BIN%" --bun "%RUNNER%" "%SPEC%" %*
exit /b %ERRORLEVEL%
:rlocation
set "LOOKUP=%~1"
set "OUTPUT_VAR=%~2"
if defined RUNFILES_DIR_VALUE (
set "%OUTPUT_VAR%=%RUNFILES_DIR_VALUE%\\%LOOKUP:/=\\%"
exit /b 0
)
for /f "tokens=1,* delims= " %%A in ('findstr /b /c:"%LOOKUP% " "%RUNFILES_MANIFEST_VALUE%"') do (
set "%OUTPUT_VAR%=%%B"
exit /b 0
)
echo rules_bun: missing runfile %LOOKUP% 1>&2
exit /b 1
"""
def runfiles_path(file):
workspace_name = file.owner.workspace_name
if workspace_name:
return "{}/{}".format(workspace_name, file.short_path)
return "_main/{}".format(file.short_path)
def runtime_launcher_attrs():
return {
"_runtime_launcher": attr.label(
default = _RUNTIME_LAUNCHER,
allow_single_file = True,
),
"_windows_constraint": attr.label(
default = _WINDOWS_CONSTRAINT,
),
}
def is_windows_target(ctx):
return ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
def write_launcher_spec(ctx, spec):
spec_file = ctx.actions.declare_file(ctx.label.name + ".launcher.json")
ctx.actions.write(
output = spec_file,
content = json.encode(spec) + "\n",
)
return spec_file
def declare_runtime_wrapper(ctx, bun_bin, spec_file):
runner = ctx.file._runtime_launcher
wrapper = ctx.actions.declare_file(ctx.label.name + (".cmd" if is_windows_target(ctx) else ""))
content = _CMD_WRAPPER_TEMPLATE if is_windows_target(ctx) else _POSIX_WRAPPER_TEMPLATE
content = content.replace("__BUN_RUNFILES_PATH__", runfiles_path(bun_bin)).replace(
"__RUNNER_RUNFILES_PATH__",
runfiles_path(runner),
).replace(
"__SPEC_RUNFILES_PATH__",
runfiles_path(spec_file),
)
ctx.actions.write(
output = wrapper,
content = content,
is_executable = True,
)
return struct(
executable = wrapper,
runner = runner,
)

File diff suppressed because it is too large Load Diff

View File

@@ -1,113 +0,0 @@
"""Shared Bun workspace metadata helpers."""
BunWorkspaceInfo = provider(
doc = "Workspace/runtime metadata shared by Bun rules and adapters.",
fields = {
"install_metadata_file": "Optional install metadata file from bun_install.",
"install_repo_runfiles_path": "Runfiles root for the node_modules repository when present.",
"metadata_file": "Rule-local metadata file describing the staged workspace inputs.",
"node_modules_files": "Depset of node_modules files from bun_install.",
"node_modules_roots": "Sorted repo-relative node_modules roots available in runfiles.",
"package_dir_hint": "Package-relative directory when known at analysis time.",
"package_json": "Package manifest file when explicitly provided.",
"primary_file": "Primary source file used to resolve the runtime package context.",
"runtime_files": "Depset of runtime files required to stage the workspace.",
},
)
def find_install_metadata_file(files):
for file in files:
if file.short_path.endswith("node_modules/.rules_bun/install.json"):
return file
return None
def _runfiles_workspace(file):
workspace_name = file.owner.workspace_name
if workspace_name:
return workspace_name
return "_main"
def _repo_relative_short_path(file):
short_path = file.short_path.replace("\\", "/")
workspace_name = _runfiles_workspace(file)
external_prefix = "../{}/".format(workspace_name)
if short_path.startswith(external_prefix):
return short_path[len(external_prefix):]
if short_path == "../{}".format(workspace_name):
return "."
return short_path
def resolve_node_modules_roots(files):
roots = {}
marker = "/node_modules/"
for file in files:
short_path = _repo_relative_short_path(file)
if short_path == "node_modules" or short_path.startswith("node_modules/"):
roots["node_modules"] = True
marker_index = short_path.find(marker)
if marker_index >= 0:
roots[short_path[:marker_index + len("/node_modules")]] = True
return sorted(roots.keys())
def create_bun_workspace_info(ctx, primary_file = None, package_json = None, package_dir_hint = ".", extra_files = None):
direct_runtime_files = []
if primary_file:
direct_runtime_files.append(primary_file)
if package_json and package_json != primary_file:
direct_runtime_files.append(package_json)
direct_runtime_files.extend(extra_files or [])
node_modules_files = depset()
install_metadata_file = None
install_repo_runfiles_path = ""
node_modules_roots = []
if getattr(ctx.attr, "node_modules", None):
node_modules_files = ctx.attr.node_modules[DefaultInfo].files
node_modules_file_list = node_modules_files.to_list()
install_metadata_file = find_install_metadata_file(node_modules_file_list)
node_modules_roots = resolve_node_modules_roots(node_modules_file_list)
if install_metadata_file:
install_repo_runfiles_path = _runfiles_workspace(install_metadata_file)
elif node_modules_file_list:
install_repo_runfiles_path = _runfiles_workspace(node_modules_file_list[0])
metadata_file = ctx.actions.declare_file(ctx.label.name + ".bun_workspace.json")
ctx.actions.write(
output = metadata_file,
content = json.encode({
"install_metadata": install_metadata_file.short_path if install_metadata_file else "",
"install_repo_runfiles_path": install_repo_runfiles_path,
"node_modules_roots": node_modules_roots,
"package_dir_hint": package_dir_hint or ".",
"package_json": package_json.short_path if package_json else "",
"primary_file": primary_file.short_path if primary_file else "",
}) + "\n",
)
direct_runtime_files.append(metadata_file)
runtime_files = depset(
direct = direct_runtime_files,
transitive = [node_modules_files],
)
return BunWorkspaceInfo(
install_metadata_file = install_metadata_file,
install_repo_runfiles_path = install_repo_runfiles_path,
metadata_file = metadata_file,
node_modules_files = node_modules_files,
node_modules_roots = node_modules_roots,
package_dir_hint = package_dir_hint or ".",
package_json = package_json,
primary_file = primary_file,
runtime_files = runtime_files,
)
def workspace_runfiles(ctx, workspace_info, direct_files = None, transitive_files = None):
return ctx.runfiles(
files = direct_files or [],
transitive_files = depset(
transitive = [workspace_info.runtime_files] + (transitive_files or []),
),
)

View File

@@ -1,21 +0,0 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
package(default_visibility = ["//visibility:public"])
exports_files(["defs.bzl"])
filegroup(
name = "repo_runtime_files",
srcs = [
"BUILD.bazel",
"defs.bzl",
],
visibility = ["//visibility:public"],
)
bzl_library(
name = "defs_bzl",
srcs = ["defs.bzl"],
visibility = ["//visibility:public"],
deps = ["//internal:js_compat_bzl"],
)

View File

@@ -1,12 +0,0 @@
"""rules_js-style public API backed by Bun."""
load("//internal:js_compat.bzl", _JsInfo = "JsInfo", _js_binary = "js_binary", _js_library = "js_library", _js_run_devserver = "js_run_devserver", _js_test = "js_test", _ts_library = "ts_library")
visibility("public")
JsInfo = _JsInfo
js_binary = _js_binary
js_test = _js_test
js_run_devserver = _js_run_devserver
js_library = _js_library
ts_library = _ts_library

View File

@@ -1,32 +0,0 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
package(default_visibility = ["//visibility:public"])
exports_files([
"extensions.bzl",
"repositories.bzl",
])
filegroup(
name = "repo_runtime_files",
srcs = [
"BUILD.bazel",
"extensions.bzl",
"repositories.bzl",
],
visibility = ["//visibility:public"],
)
bzl_library(
name = "extensions_bzl",
srcs = ["extensions.bzl"],
visibility = ["//visibility:public"],
deps = ["//internal:bun_install_bzl"],
)
bzl_library(
name = "repositories_bzl",
srcs = ["repositories.bzl"],
visibility = ["//visibility:public"],
deps = ["//internal:bun_install_bzl"],
)

View File

@@ -1,28 +0,0 @@
load("//internal:bun_install.bzl", "bun_install_repository")
_translate = tag_class(
attrs = {
"name": attr.string(mandatory = True),
"package_json": attr.label(mandatory = True),
"lockfile": attr.label(mandatory = True),
"install_inputs": attr.label_list(allow_files = True),
"isolated_home": attr.bool(default = True),
},
)
def _npm_translate_lock_impl(ctx):
for mod in ctx.modules:
for install in mod.tags.translate:
bun_install_repository(
name = install.name,
package_json = install.package_json,
bun_lockfile = install.lockfile,
install_inputs = install.install_inputs,
isolated_home = install.isolated_home,
visible_repo_name = install.name,
)
npm_translate_lock = module_extension(
implementation = _npm_translate_lock_impl,
tag_classes = {"translate": _translate},
)

View File

@@ -1,11 +0,0 @@
load("//internal:bun_install.bzl", "bun_install_repository")
def npm_translate_lock(name, package_json, lockfile, install_inputs = [], isolated_home = True):
bun_install_repository(
name = name,
package_json = package_json,
bun_lockfile = lockfile,
install_inputs = install_inputs,
isolated_home = isolated_home,
visible_repo_name = name,
)

View File

@@ -1,3 +1 @@
package(default_visibility = ["//visibility:public"])
exports_files(["nested_bazel_test.sh"])

View File

@@ -1 +0,0 @@
BUN_ENV_CWD_TEST=from-dotenv

View File

@@ -1,5 +1,5 @@
load("@rules_shell//shell:sh_test.bzl", "sh_test")
load("//bun:defs.bzl", "bun_binary")
load("@rules_shell//shell:sh_test.bzl", "sh_test")
bun_binary(
name = "hello_js_bin",
@@ -8,12 +8,8 @@ bun_binary(
sh_test(
name = "bun_binary_js_test",
size = "small",
srcs = ["run_binary.sh"],
args = [
"$(location :hello_js_bin)",
"hello-js",
],
args = ["$(location :hello_js_bin)", "hello-js"],
data = [":hello_js_bin"],
)
@@ -24,140 +20,26 @@ bun_binary(
sh_test(
name = "bun_binary_ts_test",
size = "small",
srcs = ["run_binary.sh"],
args = [
"$(location :hello_ts_bin)",
"hello-ts",
],
args = ["$(location :hello_ts_bin)", "hello-ts"],
data = [":hello_ts_bin"],
)
bun_binary(
name = "hello_js_with_data_bin",
data = ["payload.txt"],
entry_point = "hello.js",
data = ["payload.txt"],
)
sh_test(
name = "bun_binary_data_test",
size = "small",
srcs = ["verify_data_shape.sh"],
args = [
"$(rlocationpath //internal:bun_binary.bzl)",
"$(rlocationpath //tests/binary_test:BUILD.bazel)",
"$(location //internal:bun_binary.bzl)",
"$(location //tests/binary_test:BUILD.bazel)",
],
data = [
"//internal:bun_binary.bzl",
"//tests/binary_test:BUILD.bazel",
],
)
bun_binary(
name = "env_cwd_bin",
data = [".env"],
entry_point = "env.ts",
working_dir = "entry_point",
)
sh_test(
name = "bun_binary_env_cwd_test",
size = "small",
srcs = ["run_env_binary.sh"],
args = ["$(location :env_cwd_bin)"],
data = [":env_cwd_bin"],
)
bun_binary(
name = "env_parent_cwd_bin",
data = ["env_parent/.env"],
entry_point = "env_parent/src/main.ts",
working_dir = "entry_point",
)
sh_test(
name = "bun_binary_env_parent_cwd_test",
size = "small",
srcs = ["run_parent_env_binary.sh"],
args = ["$(location :env_parent_cwd_bin)"],
data = [":env_parent_cwd_bin"],
)
bun_binary(
name = "runtime_flag_bin",
args = [
"one",
"two",
],
entry_point = "flag_probe.ts",
env_files = ["runtime.env"],
preload = ["preload.ts"],
)
sh_test(
name = "bun_binary_runtime_flags_test",
size = "small",
srcs = ["run_flag_binary.sh"],
args = ["$(location :runtime_flag_bin)"],
data = [":runtime_flag_bin"],
)
sh_test(
name = "bun_binary_runtime_flags_shape_test",
size = "small",
srcs = ["verify_runtime_flags_shape.sh"],
args = ["$(location :runtime_flag_bin)"],
data = [":runtime_flag_bin"],
)
bun_binary(
name = "configured_launcher_bin",
conditions = [
"browser",
"development",
],
entry_point = "hello.ts",
inherit_host_path = True,
install_mode = "force",
node_modules = "@script_test_vite_node_modules//:node_modules",
run_flags = [
"--hot",
"--console-depth",
"4",
],
smol = True,
visibility = ["//tests/ci_test:__pkg__"],
)
sh_test(
name = "bun_binary_configured_launcher_shape_test",
size = "small",
srcs = ["verify_configured_launcher_shape.sh"],
args = ["$(location :configured_launcher_bin)"],
data = [":configured_launcher_bin"],
)
bun_binary(
name = "path_default_bin",
entry_point = "path_probe.ts",
)
bun_binary(
name = "path_inherit_bin",
entry_point = "path_probe.ts",
inherit_host_path = True,
)
sh_test(
name = "bun_binary_host_path_test",
size = "small",
srcs = ["run_path_binary.sh"],
args = [
"$(location :path_default_bin)",
"$(location :path_inherit_bin)",
],
data = [
":path_default_bin",
":path_inherit_bin",
],
)

View File

@@ -1,2 +0,0 @@
const value = process.env.BUN_ENV_CWD_TEST ?? "missing";
console.log(value);

View File

@@ -1 +0,0 @@
BUN_ENV_PARENT_TEST=from-parent-dotenv

View File

@@ -1,2 +0,0 @@
const value = process.env.BUN_ENV_PARENT_TEST ?? "missing";
console.log(value);

View File

@@ -1,7 +0,0 @@
const state = globalThis as typeof globalThis & { __rules_bun_preloaded?: string };
console.log(JSON.stringify({
preloaded: state.__rules_bun_preloaded ?? null,
env: process.env.RUNTIME_FLAG_TEST ?? null,
argv: process.argv.slice(2),
}));

View File

@@ -1,18 +0,0 @@
import { spawnSync } from "node:child_process";
const pathValue = process.env.PATH ?? "";
function commandSucceeds(command: string, args: string[]): boolean {
const result = spawnSync(command, args, {
encoding: "utf8",
env: process.env,
});
return result.status === 0;
}
console.log(JSON.stringify({
hasHostSentinel: pathValue.includes("rules_bun_host_path_sentinel"),
canRunBun: commandSucceeds("bun", ["-e", "process.exit(0)"]),
canRunBunx: commandSucceeds("bunx", ["--version"]),
canRunNode: commandSucceeds("node", ["-e", "process.exit(0)"]),
}));

View File

@@ -1 +0,0 @@
(globalThis as typeof globalThis & { __rules_bun_preloaded?: string }).__rules_bun_preloaded = "yes";

View File

@@ -3,20 +3,9 @@ set -euo pipefail
binary="$1"
expected="$2"
output="$(${binary})"
run_launcher() {
local launcher="$1"
shift
if [[ ${launcher} == *.cmd ]]; then
cmd.exe /c call "${launcher}" "$@" | tr -d '\r'
return 0
fi
"${launcher}" "$@"
}
output="$(run_launcher "${binary}")"
if [[ ${output} != "${expected}" ]]; then
if [[ "${output}" != "${expected}" ]]; then
echo "Unexpected output from ${binary}: ${output}" >&2
exit 1
fi

View File

@@ -1,21 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
binary="$1"
run_launcher() {
local launcher="$1"
shift
if [[ ${launcher} == *.cmd ]]; then
cmd.exe /c call "${launcher}" "$@" | tr -d '\r'
return 0
fi
"${launcher}" "$@"
}
output="$(run_launcher "${binary}")"
if [[ ${output} != "from-dotenv" ]]; then
echo "Expected .env value from entry-point directory, got: ${output}" >&2
exit 1
fi

View File

@@ -1,23 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
binary="$1"
run_launcher() {
local launcher="$1"
shift
if [[ ${launcher} == *.cmd ]]; then
cmd.exe /c call "${launcher}" "$@" | tr -d '\r'
return 0
fi
"${launcher}" "$@"
}
output="$(run_launcher "${binary}")"
expected='{"preloaded":"yes","env":"from-env-file","argv":["one","two"]}'
if [[ ${output} != "${expected}" ]]; then
echo "Unexpected output from ${binary}: ${output}" >&2
exit 1
fi

View File

@@ -1,21 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
binary="$1"
run_launcher() {
local launcher="$1"
shift
if [[ ${launcher} == *.cmd ]]; then
cmd.exe /c call "${launcher}" "$@" | tr -d '\r'
return 0
fi
"${launcher}" "$@"
}
output="$(run_launcher "${binary}")"
if [[ ${output} != "from-parent-dotenv" ]]; then
echo "Expected .env value from parent directory, got: ${output}" >&2
exit 1
fi

View File

@@ -1,28 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
default_binary="$1"
inherit_binary="$2"
run_launcher() {
local launcher="$1"
shift
if [[ ${launcher} == *.cmd ]]; then
env PATH="rules_bun_host_path_sentinel:${PATH:-}" cmd.exe /c call "${launcher}" "$@" | tr -d '\r'
return 0
fi
env PATH="rules_bun_host_path_sentinel:${PATH:-}" "${launcher}" "$@"
}
default_output="$(run_launcher "${default_binary}")"
inherit_output="$(run_launcher "${inherit_binary}")"
if [[ ${default_output} != '{"hasHostSentinel":false,"canRunBun":true,"canRunBunx":true,"canRunNode":true}' ]]; then
echo "Expected default launcher to hide host PATH, got: ${default_output}" >&2
exit 1
fi
if [[ ${inherit_output} != '{"hasHostSentinel":true,"canRunBun":true,"canRunBunx":true,"canRunNode":true}' ]]; then
echo "Expected inherit_host_path launcher to preserve host PATH, got: ${inherit_output}" >&2
exit 1
fi

View File

@@ -1 +0,0 @@
RUNTIME_FLAG_TEST=from-env-file

View File

@@ -1,23 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
launcher="$1"
python3 - "${launcher}" <<'PY'
import json
import pathlib
import sys
path = pathlib.Path(sys.argv[1])
if path.suffix.lower() == ".cmd":
path = pathlib.Path(str(path)[:-4])
spec = json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
argv = spec["argv"]
assert spec["install_metadata_short_path"].endswith("node_modules/.rules_bun/install.json"), spec
assert spec["inherit_host_path"] is True, spec
assert spec["node_modules_roots"], spec
assert all(not root.startswith("../") for root in spec["node_modules_roots"]), spec
for value in ["--smol", "--conditions", "browser", "development", "--install", "force", "--hot", "--console-depth", "4"]:
assert value in argv, (value, spec)
PY

View File

@@ -1,65 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ -z ${RUNFILES_DIR:-} && -n ${TEST_SRCDIR:-} && -d ${TEST_SRCDIR} ]]; then
RUNFILES_DIR="${TEST_SRCDIR}"
fi
if [[ -z ${RUNFILES_DIR:-} && -z ${RUNFILES_MANIFEST_FILE:-} ]]; then
if [[ -d "$0.runfiles" ]]; then
RUNFILES_DIR="$0.runfiles"
elif [[ -f "$0.runfiles_manifest" ]]; then
RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.exe.runfiles_manifest" ]]; then
RUNFILES_MANIFEST_FILE="$0.exe.runfiles_manifest"
fi
fi
rule_file="$1"
build_file="$2"
resolve_runfile() {
local path="${1:-}"
local candidate
local resolved
if [[ -z ${path} ]]; then
echo "Error: missing runfile path" >&2
exit 1
fi
if [[ ${path} == /* || ${path} =~ ^[A-Za-z]:[\\/] ]]; then
printf '%s\n' "${path}"
return 0
fi
if [[ -e ${path} ]]; then
printf '%s\n' "${path}"
return 0
fi
for candidate in \
"${path}" \
"${TEST_WORKSPACE:-}/${path}" \
"_main/${path}"; do
[[ -z ${candidate} ]] && continue
if [[ -n ${RUNFILES_DIR:-} && -e "${RUNFILES_DIR}/${candidate}" ]]; then
printf '%s\n' "${RUNFILES_DIR}/${candidate}"
return 0
fi
if [[ -n ${RUNFILES_MANIFEST_FILE:-} ]]; then
resolved="$(
awk -v key="${candidate}" 'index($0, key " ") == 1 { print substr($0, length(key) + 2); exit }' \
"${RUNFILES_MANIFEST_FILE}"
)"
if [[ -n ${resolved} ]]; then
printf '%s\n' "${resolved}"
return 0
fi
fi
done
echo "Error: unable to resolve runfile: ${path}" >&2
exit 1
}
rule_file="$(resolve_runfile "${1:-}")"
build_file="$(resolve_runfile "${2:-}")"
grep -Eq 'extra_files = ctx\.files\.data \+ ctx\.files\.preload \+ ctx\.files\.env_files \+ \[bun_bin\]' "${rule_file}"
grep -Eq 'files = \[bun_bin, entry_point\] \+ ctx\.files\.data' "${rule_file}"
grep -Eq 'name = "hello_js_with_data_bin"' "${build_file}"
grep -Eq 'data = \["payload\.txt"\]' "${build_file}"

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
launcher="$1"
python3 - "${launcher}" <<'PY'
import json
import pathlib
import sys
path = pathlib.Path(sys.argv[1])
if path.suffix.lower() == ".cmd":
path = pathlib.Path(str(path)[:-4])
spec = json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
assert "--no-install" in spec["argv"], spec
assert spec["inherit_host_path"] is False, spec
assert spec["preload_short_paths"] and spec["preload_short_paths"][0].endswith("tests/binary_test/preload.ts"), spec
assert spec["env_file_short_paths"] and spec["env_file_short_paths"][0].endswith("tests/binary_test/runtime.env"), spec
PY

View File

@@ -3,87 +3,38 @@ load("//bun:defs.bzl", "bun_test")
bun_test(
name = "passing_suite",
size = "small",
srcs = ["passing.test.ts"],
)
bun_test(
name = "failing_suite",
size = "small",
srcs = ["failing.test.ts"],
)
bun_test(
name = "configured_suite",
size = "small",
srcs = ["passing.test.ts"],
bail = 1,
concurrent = True,
coverage = True,
coverage_reporters = ["lcov"],
env_files = ["test.env"],
max_concurrency = 4,
no_env_file = True,
preload = ["preload.ts"],
randomize = True,
reporter = "junit",
rerun_each = 2,
seed = 7,
test_flags = ["--only-failures"],
timeout_ms = 250,
update_snapshots = True,
visibility = ["//tests/ci_test:__pkg__"],
)
bun_test(
name = "configured_retry_suite",
size = "small",
srcs = ["passing.test.ts"],
retry = 3,
)
sh_test(
name = "bun_test_configured_suite_shape_test",
size = "small",
srcs = ["configured_suite_shape.sh"],
args = [
"$(location :configured_suite)",
"$(location :configured_retry_suite)",
],
data = [
":configured_retry_suite",
":configured_suite",
],
)
sh_test(
name = "bun_test_failing_suite_test",
size = "small",
srcs = ["failing_suite_shape.sh"],
args = ["$(rlocationpath //tests/bun_test_test:BUILD.bazel)"],
args = ["$(location //tests/bun_test_test:BUILD.bazel)"],
data = ["//tests/bun_test_test:BUILD.bazel"],
)
sh_test(
name = "bun_test_cache_hit_test",
size = "small",
srcs = ["cache_hit_shape.sh"],
args = ["$(location :passing_suite)"],
data = [":passing_suite"],
args = ["$(location //internal:bun_test.bzl)"],
data = ["//internal:bun_test.bzl"],
)
sh_test(
name = "bun_test_cache_miss_test",
size = "small",
srcs = ["cache_miss_shape.sh"],
args = ["$(location :configured_suite)"],
data = [":configured_suite"],
args = ["$(location //internal:bun_test.bzl)"],
data = ["//internal:bun_test.bzl"],
)
sh_test(
name = "bun_test_junit_output_test",
size = "small",
srcs = ["junit_shape.sh"],
args = ["$(location :configured_suite)"],
data = [":configured_suite"],
args = ["$(location //internal:bun_test.bzl)"],
data = ["//internal:bun_test.bzl"],
)

View File

@@ -1,19 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
launcher="$1"
rule_file="$1"
python3 - "${launcher}" <<'PY'
import json
import pathlib
import sys
path = pathlib.Path(sys.argv[1])
if path.suffix.lower() == ".cmd":
path = pathlib.Path(str(path)[:-4])
spec = json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
assert spec["kind"] == "bun_test", spec
assert spec["argv"][:2] == ["--bun", "test"], spec
assert spec["test_short_paths"], spec
PY
grep -Fq 'set -euo pipefail' "${rule_file}"
grep -Fq 'src_args = " ".join([_shell_quote(src.short_path) for src in ctx.files.srcs])' "${rule_file}"
grep -Fq 'exec "${{bun_bin}}" test {src_args} "$@"' "${rule_file}"

View File

@@ -1,20 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
launcher="$1"
rule_file="$1"
python3 - "${launcher}" <<'PY'
import json
import pathlib
import sys
path = pathlib.Path(sys.argv[1])
if path.suffix.lower() == ".cmd":
path = pathlib.Path(str(path)[:-4])
spec = json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
assert spec["coverage"] is True, spec
assert spec["preload_short_paths"], spec
assert spec["env_file_short_paths"], spec
assert spec["test_short_paths"], spec
PY
grep -Eq 'files = \[bun_bin\] \+ ctx\.files\.srcs \+ ctx\.files\.data' "${rule_file}"
grep -Eq '"srcs": attr\.label_list\(' "${rule_file}"

View File

@@ -1,42 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
launcher="$1"
retry_launcher="$2"
python3 - "${launcher}" "${retry_launcher}" <<'PY'
import json
import pathlib
import sys
def read_spec(launcher: str):
path = pathlib.Path(launcher)
if path.suffix.lower() == ".cmd":
path = pathlib.Path(str(path)[:-4])
return json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
launcher_spec = read_spec(sys.argv[1])
retry_spec = read_spec(sys.argv[2])
for value in [
"--no-install",
"--no-env-file",
"--timeout",
"--update-snapshots",
"--rerun-each",
"--concurrent",
"--randomize",
"--seed",
"--bail",
"--max-concurrency",
]:
assert value in launcher_spec["argv"], (value, launcher_spec)
assert launcher_spec["preload_short_paths"], launcher_spec
assert launcher_spec["env_file_short_paths"], launcher_spec
assert launcher_spec["reporter"] == "junit", launcher_spec
assert launcher_spec["coverage"] is True, launcher_spec
assert launcher_spec["coverage_reporters"] == ["lcov"], launcher_spec
assert "--retry" in retry_spec["argv"], retry_spec
assert "3" in retry_spec["argv"], retry_spec
PY

View File

@@ -1,63 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ -z ${RUNFILES_DIR:-} && -n ${TEST_SRCDIR:-} && -d ${TEST_SRCDIR} ]]; then
RUNFILES_DIR="${TEST_SRCDIR}"
fi
if [[ -z ${RUNFILES_DIR:-} && -z ${RUNFILES_MANIFEST_FILE:-} ]]; then
if [[ -d "$0.runfiles" ]]; then
RUNFILES_DIR="$0.runfiles"
elif [[ -f "$0.runfiles_manifest" ]]; then
RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.exe.runfiles_manifest" ]]; then
RUNFILES_MANIFEST_FILE="$0.exe.runfiles_manifest"
fi
fi
resolve_runfile() {
local path="${1:-}"
local candidate
local resolved
if [[ -z ${path} ]]; then
echo "Error: missing runfile path" >&2
exit 1
fi
if [[ ${path} == /* || ${path} =~ ^[A-Za-z]:[\\/] ]]; then
printf '%s\n' "${path}"
return 0
fi
if [[ -e ${path} ]]; then
printf '%s\n' "${path}"
return 0
fi
for candidate in \
"${path}" \
"${TEST_WORKSPACE:-}/${path}" \
"_main/${path}"; do
[[ -z ${candidate} ]] && continue
if [[ -n ${RUNFILES_DIR:-} && -e "${RUNFILES_DIR}/${candidate}" ]]; then
printf '%s\n' "${RUNFILES_DIR}/${candidate}"
return 0
fi
if [[ -n ${RUNFILES_MANIFEST_FILE:-} ]]; then
resolved="$(
awk -v key="${candidate}" 'index($0, key " ") == 1 { print substr($0, length(key) + 2); exit }' \
"${RUNFILES_MANIFEST_FILE}"
)"
if [[ -n ${resolved} ]]; then
printf '%s\n' "${resolved}"
return 0
fi
fi
done
echo "Error: unable to resolve runfile: ${path}" >&2
exit 1
}
build_file="$(resolve_runfile "${1:-}")"
build_file="$1"
grep -Eq 'name = "failing_suite"' "${build_file}"
if grep -Eq 'tags = \["manual"\]' "${build_file}"; then

View File

@@ -1,17 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
launcher="$1"
rule_file="$1"
python3 - "${launcher}" <<'PY'
import json
import pathlib
import sys
path = pathlib.Path(sys.argv[1])
if path.suffix.lower() == ".cmd":
path = pathlib.Path(str(path)[:-4])
spec = json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
assert spec["reporter"] == "junit", spec
PY
grep -Fq 'exec "${{bun_bin}}" test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" "$@"' "${rule_file}"
grep -Fq 'if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" ]]' "${rule_file}"

View File

@@ -1 +0,0 @@
(globalThis as typeof globalThis & { __rules_bun_test_preloaded?: boolean }).__rules_bun_test_preloaded = true;

View File

@@ -1 +0,0 @@
TEST_FROM_ENV=1

View File

@@ -1,5 +1,5 @@
load("//bun:defs.bzl", "bun_bundle")
load("@rules_shell//shell:sh_test.bzl", "sh_test")
load("//bun:defs.bzl", "bun_build", "bun_bundle", "bun_compile")
bun_bundle(
name = "simple_bundle",
@@ -18,132 +18,8 @@ bun_bundle(
external = ["left-pad"],
)
bun_bundle(
name = "collision_bundle",
entry_points = [
"collision_case/a/main.ts",
"collision_case/b/main.ts",
],
)
bun_build(
name = "site_build",
data = [
"site/main.ts",
"site/styles.css",
],
entry_points = ["site/index.html"],
splitting = True,
)
bun_build(
name = "site_build_with_meta",
data = [
"site/main.ts",
"site/styles.css",
],
entry_points = ["site/index.html"],
metafile = True,
metafile_md = True,
)
bun_build(
name = "advanced_site_build",
asset_naming = "assets/[name]-[hash].[ext]",
banner = "/* bundle banner */",
build_flags = [
"--app",
"--server-components",
],
chunk_naming = "chunks/[name]-[hash].[ext]",
conditions = [
"browser",
"custom",
],
css_chunking = True,
data = [
"site/main.ts",
"site/styles.css",
],
define = [
"process.env.NODE_ENV:\"production\"",
"__DEV__:false",
],
drop = [
"console",
"debugger",
],
emit_dce_annotations = True,
entry_naming = "entries/[name]-[hash].[ext]",
entry_points = ["site/index.html"],
env = "PUBLIC_*",
external = [
"left-pad",
"react",
],
feature = [
"react_fast_refresh",
"server_components",
],
footer = "// bundle footer",
format = "cjs",
jsx_factory = "h",
jsx_fragment = "Fragment",
jsx_import_source = "preact",
jsx_runtime = "automatic",
jsx_side_effects = True,
keep_names = True,
loader = [
".svg:file",
".txt:text",
],
minify = True,
minify_identifiers = True,
minify_syntax = True,
minify_whitespace = True,
no_bundle = True,
packages = "external",
production = True,
public_path = "/static/",
react_fast_refresh = True,
root = "tests/bundle_test/site",
sourcemap = "linked",
splitting = True,
tags = ["manual"],
target = "node",
)
bun_compile(
name = "compiled_cli",
entry_point = "cli.ts",
)
bun_compile(
name = "compiled_cli_with_flags",
bytecode = True,
compile_autoload_bunfig = False,
compile_autoload_dotenv = False,
compile_autoload_package_json = True,
compile_autoload_tsconfig = True,
compile_exec_argv = [
"--smol",
"--inspect-wait",
],
compile_executable = "fake_cross_bun.bin",
entry_point = "cli.ts",
tags = ["manual"],
windows_copyright = "(c) rules_bun",
windows_description = "compile flag coverage",
windows_hide_console = True,
windows_icon = "branding/icon.ico",
windows_publisher = "rules_bun",
windows_title = "Rules Bun Test App",
windows_version = "1.2.3.4",
)
sh_test(
name = "bundle_output_test",
size = "small",
srcs = ["verify_bundle.sh"],
args = ["$(location :simple_bundle)"],
data = [":simple_bundle"],
@@ -151,21 +27,19 @@ sh_test(
sh_test(
name = "bundle_minify_test",
size = "small",
srcs = ["verify_minify.sh"],
args = [
"$(location :simple_bundle)",
"$(location :minified_bundle)",
],
data = [
":minified_bundle",
":simple_bundle",
":minified_bundle",
],
)
sh_test(
name = "bundle_hermetic_digest_test",
size = "small",
srcs = ["verify_hermetic_shape.sh"],
args = ["$(location //internal:bun_bundle.bzl)"],
data = ["//internal:bun_bundle.bzl"],
@@ -173,7 +47,6 @@ sh_test(
sh_test(
name = "bundle_external_exclusion_test",
size = "small",
srcs = ["verify_external_shape.sh"],
args = [
"$(location //internal:bun_bundle.bzl)",
@@ -184,78 +57,3 @@ sh_test(
"//tests/bundle_test:BUILD.bazel",
],
)
sh_test(
name = "bundle_collision_output_test",
size = "small",
srcs = ["verify_collision_outputs.sh"],
args = ["$(locations :collision_bundle)"],
data = [":collision_bundle"],
)
sh_test(
name = "bundle_sourcemap_shape_test",
size = "small",
srcs = ["verify_sourcemap_shape.sh"],
tags = [
"exclusive",
"no-sandbox",
],
data = [
"BUILD.bazel",
"//:repo_runtime_files",
"//bun:repo_runtime_files",
"//internal:repo_runtime_files",
"//tests:nested_bazel_test.sh",
"//tests/bundle_test/sourcemap_case:BUILD.bazel",
"//tests/bundle_test/sourcemap_case:entry.ts",
],
env_inherit = ["PATH"],
)
sh_test(
name = "bun_build_site_output_test",
size = "small",
srcs = ["verify_site_build.sh"],
args = ["$(location :site_build)"],
data = [":site_build"],
)
sh_test(
name = "bun_build_site_meta_test",
size = "small",
srcs = ["verify_site_build_meta.sh"],
args = ["$(locations :site_build_with_meta)"],
data = [":site_build_with_meta"],
)
sh_test(
name = "bun_compile_output_test",
size = "small",
srcs = ["run_compiled_binary.sh"],
args = ["$(location :compiled_cli)"],
data = [":compiled_cli"],
)
sh_test(
name = "bun_build_compile_flag_shape_test",
size = "small",
srcs = ["verify_flag_aquery.sh"],
tags = [
"exclusive",
"no-sandbox",
],
data = [
"BUILD.bazel",
"cli.ts",
"fake_cross_bun.bin",
"site/index.html",
"site/main.ts",
"site/styles.css",
"//:repo_runtime_files",
"//bun:repo_runtime_files",
"//internal:repo_runtime_files",
"//tests:nested_bazel_test.sh",
],
env_inherit = ["PATH"],
)

View File

@@ -1 +0,0 @@
console.log("compiled-cli");

View File

@@ -1 +0,0 @@
console.log("a");

Some files were not shown because too many files have changed in this diff Show More