61 Commits

Author SHA1 Message Date
eric
81e9b93914 fix: bun install symlinks 4
Some checks failed
CI / test (ubuntu-latest, linux-x64) (push) Failing after 31s
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled
2026-03-07 00:34:14 +01:00
eric
9cbd027e7e fix: bun install symlinks 4 2026-03-07 00:32:40 +01:00
eric
6b5343fdf3 fix: bun install symlinks 4 2026-03-07 00:30:13 +01:00
eric
9487fafe88 fix: bun install symlinks 3 2026-03-07 00:27:51 +01:00
eric
9e64fd1369 fix: bun install symlinks
Some checks failed
Copilot Setup Steps / copilot-setup-steps (push) Failing after 36s
2026-03-07 00:23:39 +01:00
eric
d04f489b0e fix: bun install symlinks
Some checks failed
CI / test (ubuntu-latest, linux-x64) (push) Failing after 39s
Docs Pages / deploy (push) Failing after 33s
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled
2026-03-07 00:00:00 +01:00
eric
40d621d1cf fix: bun install symlinks 2026-03-06 23:52:27 +01:00
eric
e567dad413 chore(release): v0.2.2
Some checks failed
CI / test (ubuntu-latest, linux-x64) (push) Failing after 36s
Copilot Setup Steps / copilot-setup-steps (push) Failing after 37s
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled
2026-03-06 21:44:56 +01:00
eric
7139aa3ba2 fix: bun_install adds node_modules to each directory
Some checks failed
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled
CI / test (ubuntu-latest, linux-x64) (push) Has been cancelled
Docs Pages / deploy (push) Failing after 42s
2026-03-06 21:44:15 +01:00
eric
49a5054b02 chore(release): v0.2.1
Some checks failed
CI / test (ubuntu-latest, linux-x64) (push) Failing after 31s
Copilot Setup Steps / copilot-setup-steps (push) Failing after 38s
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled
2026-03-06 20:55:09 +01:00
eric
10758aa20a docs: Refactor code structure for improved readability
Some checks failed
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled
CI / test (ubuntu-latest, linux-x64) (push) Has been cancelled
Docs Pages / deploy (push) Failing after 33s
2026-03-06 20:54:28 +01:00
eric
fb7afbb138 chore(release): v0.2.0
Some checks failed
CI / test (ubuntu-latest, linux-x64) (push) Failing after 38s
Docs Pages / deploy (push) Failing after 44s
Copilot Setup Steps / copilot-setup-steps (push) Failing after 34s
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled
2026-03-06 20:34:27 +01:00
eric
3a07d02c0d fix: tests pass 2026-03-06 20:34:11 +01:00
Eric
a3591b85a5 chore: update nix lib
Some checks failed
CI / test (ubuntu-latest, linux-x64) (push) Failing after 35s
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled
2026-03-06 20:03:15 +01:00
Eric
dae19ed2dc chore(release): v0.1.0
Some checks failed
Copilot Setup Steps / copilot-setup-steps (push) Failing after 39s
2026-03-06 20:02:35 +01:00
Eric
e84bd920be feat: bun_script 2026-03-06 19:51:52 +01:00
Eric
7569ca914c chore: script 2026-03-04 20:32:02 +01:00
Eric
cac266ee25 chore(release): v0.0.8 2026-03-04 20:32:02 +01:00
Eric
bf87497c27 fix: .env is located next to package.json 2026-03-04 20:32:01 +01:00
Eric
0872bf7b20 chore(release): v0.0.7 2026-03-04 20:32:01 +01:00
Eric
075a1159cf feat: add docs 2026-03-04 20:32:01 +01:00
Eric
d5b3f5c5ac feat: add option for process cwd (.env support) 2026-03-04 20:32:01 +01:00
Eric
63839fce52 chore(release): v0.0.6 2026-03-04 20:32:01 +01:00
Eric
ab6ee39f62 feat: bun dev target support 2026-03-04 20:32:01 +01:00
Eric
22220b6408 chore(release): v0.0.5 2026-03-04 20:32:01 +01:00
Eric
90be857640 docs: update readme on release 2026-03-04 20:32:01 +01:00
Eric
6b1a2ce1c0 chore(release): v0.0.4 2026-03-04 20:32:00 +01:00
Eric
092aa0cc14 docs: readme instructions 2026-03-04 20:32:00 +01:00
Eric
5dda02dba3 chore(release): v0.0.3 2026-03-04 20:32:00 +01:00
Eric
9116913740 feat: release script 2026-03-04 20:32:00 +01:00
Eric
07210d89d2 test: add bun workspace tests 2026-03-04 20:32:00 +01:00
Eric
799fe61c56 test: add workspace monorepo bun install test 2026-03-04 20:32:00 +01:00
Eric
ce9fff76a3 fix: bazel is green 2026-03-04 20:32:00 +01:00
Eric
45e8f75ca5 feat: cache nix packages in ci 2026-03-04 20:31:59 +01:00
Eric
c00d949936 chore(release): v0.0.2 2026-03-04 20:31:59 +01:00
Eric
c25535b59b chore: update flake 2026-03-04 20:31:59 +01:00
Eric
96d0c2e79d fix: all tests 2026-03-04 20:31:59 +01:00
Eric
56fbea32d8 test: refine new shape test assertions 2026-03-04 20:31:59 +01:00
Eric
c823d3ec19 test: add missing implementation-plan test targets 2026-03-04 20:31:59 +01:00
Eric
f5d42b24db docs: define missing tests 2026-03-04 20:31:59 +01:00
Eric
3bf65e9fc6 fix: harden phase 8 CI workflow and checks 2026-03-04 20:31:59 +01:00
Eric
ed3b159dc2 feat: add phase 8 ci matrix workflow 2026-03-04 20:31:59 +01:00
Eric
5302f573fb fix: tests 2026-03-04 20:31:59 +01:00
Eric
db16748cd1 chore: address phase 7 review feedback 2026-03-04 20:31:58 +01:00
Eric
bdc5e6d976 feat: add phase 7 bun_install module extension 2026-03-04 20:31:58 +01:00
Eric
972a7b238d chore: update flake 2026-03-04 20:31:58 +01:00
Eric
d1b209eb0e fix: tests 2026-03-04 20:31:58 +01:00
Eric
604dc41a95 feat: add phase 6 js_library and ts_library bootstrap 2026-03-04 20:31:58 +01:00
Eric
7b549e9b4f feat: update nix flake 2026-03-04 20:31:58 +01:00
Eric
b33a395c44 fix: use correct bazel 9.0.0 imports 2026-03-04 20:31:58 +01:00
Eric
7d4b9abdd9 feat: implement phase 5 bun_bundle bootstrap 2026-03-04 20:31:58 +01:00
Eric
861a677582 fix: harden bun_test launcher args and test metadata 2026-03-04 20:31:57 +01:00
Eric
42469425e1 feat: add phase 4 bun_test bootstrap 2026-03-04 20:31:57 +01:00
Eric
5044478363 test: simplify bun_binary test targets 2026-03-04 20:31:57 +01:00
Eric
324ca9395b feat: add phase 3 bun_binary bootstrap and tests 2026-03-04 20:31:57 +01:00
Eric
bd6bebd562 docs: add bun_install parameter docs 2026-03-04 20:31:57 +01:00
Eric
e69e2754ca feat: add phase 2 bun_install repository rule bootstrap 2026-03-04 20:31:57 +01:00
Eric
fbfdef222d docs: add plan to repo 2026-03-04 20:31:57 +01:00
Eric
5220c76290 chore: centralize bun version and release URL constants 2026-03-04 20:31:57 +01:00
Eric
ebce24804c feat: bootstrap bun toolchain skeleton and smoke test 2026-03-04 20:31:56 +01:00
Eric
b66339a33b Initial plan 2026-03-04 20:31:36 +01:00
82 changed files with 3963 additions and 421 deletions

View File

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

View File

@@ -5,6 +5,10 @@ on:
branches: ["main"] branches: ["main"]
pull_request: pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
test: test:
permissions: permissions:
@@ -25,6 +29,12 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: bazel-contrib/setup-bazel@0.15.0 - uses: bazel-contrib/setup-bazel@0.15.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: Run tests (${{ matrix.phase8_target }}) - name: Run tests (${{ matrix.phase8_target }})
run: | run: |
echo "Phase 8 target: ${{ matrix.phase8_target }}" echo "Phase 8 target: ${{ matrix.phase8_target }}"

61
.github/workflows/pages.yml vendored Normal file
View File

@@ -0,0 +1,61 @@
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.0
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v4
- uses: bazel-contrib/setup-bazel@0.15.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

3
.gitignore vendored
View File

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

View File

@@ -1,21 +1,50 @@
module( module(
name = "rules_bun", name = "rules_bun",
version = "0.0.4", version = "0.2.2",
) )
# Core ruleset dependencies.
bazel_dep(name = "platforms", version = "1.0.0") bazel_dep(name = "platforms", version = "1.0.0")
bazel_dep(name = "rules_shell", version = "0.6.1") 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") bun_ext = use_extension("//bun:extensions.bzl", "bun")
use_repo( use_repo(
bun_ext, bun_ext,
"bun_linux_x64",
"bun_linux_aarch64",
"bun_darwin_x64",
"bun_darwin_aarch64", "bun_darwin_aarch64",
"bun_darwin_x64",
"bun_linux_aarch64",
"bun_linux_x64",
"bun_windows_x64", "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 = "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( register_toolchains(
"//bun:darwin_aarch64_toolchain", "//bun:darwin_aarch64_toolchain",
"//bun:darwin_x64_toolchain", "//bun:darwin_x64_toolchain",

45
MODULE.bazel.lock generated
View File

@@ -141,6 +141,8 @@
"https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", "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/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
"https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", "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/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/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
@@ -153,6 +155,7 @@
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", "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.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.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.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.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.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937",
@@ -189,8 +192,8 @@
"moduleExtensions": { "moduleExtensions": {
"//bun:extensions.bzl%bun": { "//bun:extensions.bzl%bun": {
"general": { "general": {
"bzlTransitiveDigest": "Q0uQOwFAgAU+etePCZ4TUDO+adLX7Z0EmRLaEsKgncw=", "bzlTransitiveDigest": "64B4fTkEHdAlieIOkE/Wi2M/R9lMNZhFxeI1eXEFHRs=",
"usagesDigest": "qk1PDh3WICa0VONYKXJLsmWCesNJxz3Jkb/aH/voIeI=", "usagesDigest": "/0BcCMA6AOzLhQaRK6DquxrCfpPHJUjSUaFz4zmQrsM=",
"recordedInputs": [ "recordedInputs": [
"REPO_MAPPING:,bazel_tools bazel_tools" "REPO_MAPPING:,bazel_tools bazel_tools"
], ],
@@ -248,6 +251,44 @@
} }
} }
}, },
"//bun:extensions.bzl%bun_install": {
"general": {
"bzlTransitiveDigest": "64B4fTkEHdAlieIOkE/Wi2M/R9lMNZhFxeI1eXEFHRs=",
"usagesDigest": "d+DGTyl4FpB6Ygb/R/V5knxm9bGYZKO223wMX1Q6R6w=",
"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
}
},
"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
}
},
"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
}
}
}
}
},
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
"general": { "general": {
"bzlTransitiveDigest": "ABI1D/sbS1ovwaW/kHDoj8nnXjQ0oKU9fzmzEG4iT8o=", "bzlTransitiveDigest": "ABI1D/sbS1ovwaW/kHDoj8nnXjQ0oKU9fzmzEG4iT8o=",

238
README.md
View File

@@ -1,103 +1,209 @@
# rules_bun # Bun rules for [Bazel](https://bazel.build)
Bazel rules for bun. `rules_bun` provides Bazel rules for running, testing, bundling, and developing
JavaScript and TypeScript code with Bun.
## Use ## Repository layout
These steps show how to consume a tagged release of `rules_bun` in a separate Bazel workspace. This repository follows the standard Bazel ruleset layout:
### 1) Add the module dependency ```text
/
In your project's `MODULE.bazel`, add: MODULE.bazel
README.md
```starlark bun/
bazel_dep(name = "rules_bun", version = "0.0.3") BUILD.bazel
defs.bzl
archive_override( extensions.bzl
module_name = "rules_bun", repositories.bzl
urls = ["https://github.com/Eriyc/rules_bun/archive/refs/tags/v0.0.3.tar.gz"], toolchain.bzl
strip_prefix = "rules_bun-v0.0.3", docs/
) examples/
tests/
``` ```
For channel/pre-release tags (for example `v0.0.3-rc.1`), use the matching folder prefix: The public entrypoint for rule authors and users is `@rules_bun//bun:defs.bzl`.
```starlark ## Public API
bazel_dep(name = "rules_bun", version = "0.0.3-rc.1")
archive_override( `rules_bun` exports these primary rules:
module_name = "rules_bun",
urls = ["https://github.com/Eriyc/rules_bun/archive/refs/tags/v0.0.3-rc.1.tar.gz"], - `bun_binary`
strip_prefix = "rules_bun-v0.0.3-rc.1", - `bun_bundle`
) - `bun_dev`
- `bun_script`
- `bun_test`
- `js_library`
- `ts_library`
Reference documentation:
- 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)
To refresh generated rule docs:
```bash
bazel build //docs:rules_md && cp bazel-bin/docs/rules.md docs/rules.md
``` ```
Note: keep the `v` prefix in the Git tag URL and `strip_prefix`; for `bazel_dep(..., version = ...)`, use the module version string without the leading `v`. ## Bzlmod usage
### 2) Create Bun repositories with the extension Release announcements should provide a copy-pasteable module snippet in the
standard ruleset form:
Still in `MODULE.bazel`, add: ```starlark
bazel_dep(name = "rules_bun", version = "0.2.2")
```
Then add the Bun repositories and register the toolchains in `MODULE.bazel`:
```starlark ```starlark
bun_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun") bun_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun")
use_repo( use_repo(
bun_ext, bun_ext,
"bun_linux_x64", "bun_linux_x64",
"bun_linux_aarch64", "bun_linux_aarch64",
"bun_darwin_x64", "bun_darwin_x64",
"bun_darwin_aarch64", "bun_darwin_aarch64",
"bun_windows_x64", "bun_windows_x64",
) )
```
### 3) Register toolchains
Also in `MODULE.bazel`, register:
```starlark
register_toolchains( register_toolchains(
"@rules_bun//bun:darwin_aarch64_toolchain", "@rules_bun//bun:darwin_aarch64_toolchain",
"@rules_bun//bun:darwin_x64_toolchain", "@rules_bun//bun:darwin_x64_toolchain",
"@rules_bun//bun:linux_aarch64_toolchain", "@rules_bun//bun:linux_aarch64_toolchain",
"@rules_bun//bun:linux_x64_toolchain", "@rules_bun//bun:linux_x64_toolchain",
"@rules_bun//bun:windows_x64_toolchain", "@rules_bun//bun:windows_x64_toolchain",
) )
``` ```
### 4) Load rules in `BUILD.bazel` If you want Bazel-managed dependency installation, also add the module
extension for `bun_install`:
```starlark `bun_install` runs `bun install`, not `npm install`. In the example below,
load( `bun_deps` is just the Bazel repository name for the generated
"@rules_bun//bun:defs.bzl", `node_modules` tree. See [docs/bun_install.md](docs/bun_install.md) for the
"bun_binary", full extension reference.
"bun_bundle",
"bun_test",
"js_library",
"ts_library",
)
```
### 5) (Optional) Use `bun_install` module extension
If you want Bazel-managed install repositories, add:
```starlark ```starlark
bun_install_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun_install") bun_install_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun_install")
bun_install_ext.install( bun_install_ext.install(
name = "npm", name = "bun_deps",
package_json = "//:package.json", package_json = "//:package.json",
bun_lockfile = "//:bun.lock", bun_lockfile = "//:bun.lock",
# Optional: include extra install-time files or allow Bun to reuse the
# host HOME/cache.
# install_inputs = ["//:.npmrc"],
# isolated_home = False,
) )
use_repo(bun_install_ext, "npm") use_repo(bun_install_ext, "bun_deps")
``` ```
### 6) Verify setup ## Legacy WORKSPACE usage
Run one of your bun-backed targets, for example: 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_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",
]),
)
```
When `node_modules` is provided, executables from `node_modules/.bin` are added
to `PATH`. This label typically comes from `bun_install`, which still produces a
standard `node_modules/` directory.
### `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 ```bash
bazel test //path/to:your_bun_test bazel test //tests/...
``` ```

View File

@@ -1,3 +1,3 @@
0.0.4 0.2.2
stable stable
0 0

View File

@@ -1,5 +1,24 @@
workspace(name = "rules_bun") workspace(name = "rules_bun")
load("//internal:bun_install.bzl", "bun_install")
load("//bun:repositories.bzl", "bun_register_toolchains") load("//bun:repositories.bzl", "bun_register_toolchains")
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,11 +1,49 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load(":toolchain.bzl", "bun_toolchain") load(":toolchain.bzl", "bun_toolchain")
load(":version.bzl", "BUN_VERSION") load(":version.bzl", "BUN_VERSION")
exports_files([ exports_files([
"defs.bzl", "defs.bzl",
"extensions.bzl", "extensions.bzl",
"repositories.bzl",
"toolchain.bzl",
"version.bzl",
]) ])
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_binary_bzl",
"//internal:bun_bundle_bzl",
"//internal:bun_dev_bzl",
"//internal:bun_script_bzl",
"//internal:bun_test_bzl",
"//internal:js_library_bzl",
],
)
toolchain_type(name = "toolchain_type") toolchain_type(name = "toolchain_type")
bun_toolchain( bun_toolchain(

View File

@@ -1,5 +1,8 @@
"""Public API surface for Bun Bazel rules."""
load("//internal:bun_binary.bzl", _bun_binary = "bun_binary") load("//internal:bun_binary.bzl", _bun_binary = "bun_binary")
load("//internal:bun_bundle.bzl", _bun_bundle = "bun_bundle") 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:bun_test.bzl", _bun_test = "bun_test")
load("//internal:js_library.bzl", _js_library = "js_library", _ts_library = "ts_library") load("//internal:js_library.bzl", _js_library = "js_library", _ts_library = "ts_library")
load(":toolchain.bzl", _BunToolchainInfo = "BunToolchainInfo", _bun_toolchain = "bun_toolchain") load(":toolchain.bzl", _BunToolchainInfo = "BunToolchainInfo", _bun_toolchain = "bun_toolchain")
@@ -8,8 +11,11 @@ visibility("public")
bun_binary = _bun_binary bun_binary = _bun_binary
bun_bundle = _bun_bundle bun_bundle = _bun_bundle
bun_dev = _bun_dev
bun_script = _bun_script
bun_test = _bun_test bun_test = _bun_test
js_library = _js_library js_library = _js_library
ts_library = _ts_library ts_library = _ts_library
BunToolchainInfo = _BunToolchainInfo BunToolchainInfo = _BunToolchainInfo
bun_toolchain = _bun_toolchain bun_toolchain = _bun_toolchain

View File

@@ -58,8 +58,10 @@ bun = module_extension(
_install = tag_class( _install = tag_class(
attrs = { attrs = {
"name": attr.string(mandatory = True), "name": attr.string(mandatory = True),
"package_json": attr.string(mandatory = True), "package_json": attr.label(mandatory = True),
"bun_lockfile": attr.string(mandatory = True), "bun_lockfile": attr.label(mandatory = True),
"install_inputs": attr.label_list(allow_files = True),
"isolated_home": attr.bool(default = True),
}, },
) )
@@ -71,6 +73,8 @@ def _bun_install_impl(ctx):
name = install.name, name = install.name,
package_json = install.package_json, package_json = install.package_json,
bun_lockfile = install.bun_lockfile, bun_lockfile = install.bun_lockfile,
install_inputs = install.install_inputs,
isolated_home = install.isolated_home,
) )

20
docs/BUILD.bazel Normal file
View File

@@ -0,0 +1,20 @@
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_bundle",
"bun_dev",
"bun_script",
"bun_test",
"js_library",
"ts_library",
],
deps = ["//bun:defs_bzl"],
target_compatible_with = ["@platforms//os:linux"],
)

124
docs/bun_install.md Normal file
View File

@@ -0,0 +1,124 @@
# `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`
- 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`.
## 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",
)
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
## 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`.

90
docs/index.md Normal file
View File

@@ -0,0 +1,90 @@
# 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
## 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_darwin_x64",
"bun_darwin_aarch64",
"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",
)
```
## 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`.
## 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
```

88
docs/rules.md Normal file
View File

@@ -0,0 +1,88 @@
# rules_bun rule reference
This file documents the public rules exported from `@rules_bun//bun:defs.bzl`.
## bun_binary
Runs a JS/TS entry point with Bun as an executable target (`bazel run`).
Attributes:
- `entry_point` (label, required): path to the main JS/TS file to execute.
- `node_modules` (label, optional): package files from a `node_modules` tree, typically produced by `bun_install`, made available in runfiles.
- `data` (label_list, optional): additional runtime files.
- `working_dir` (string, default: `"workspace"`, values: `"workspace" | "entry_point"`): runtime working directory.
## bun_dev
Runs a JS/TS entry point in Bun development watch mode (`bazel run`).
Attributes:
- `entry_point` (label, required): path to the main JS/TS file.
- `watch_mode` (string, default: `"watch"`, values: `"watch" | "hot"`): Bun live-reload mode.
- `restart_on` (label_list, optional): files that trigger full process restart when changed.
- `node_modules` (label, optional): package files from a `node_modules` tree, typically produced by `bun_install`, made available in runfiles.
- `data` (label_list, optional): additional runtime files for dev process.
- `working_dir` (string, default: `"workspace"`, values: `"workspace" | "entry_point"`): runtime working directory.
## bun_script
Runs a named `package.json` script with Bun as an executable target (`bazel run`).
Recommended for package-script based tools such as Vite (`dev`, `build`, `preview`).
When `node_modules` is provided, executables from `node_modules/.bin` are added
to `PATH`, so scripts like `vite` work without wrapper scripts.
Attributes:
- `script` (string, required): package script name passed to `bun run <script>`.
- `package_json` (label, required): `package.json` file containing the named script.
- `node_modules` (label, optional): package files from a `node_modules` tree, typically produced by `bun_install`, made available in runfiles.
- `data` (label_list, optional): additional runtime files for the script.
- `working_dir` (string, default: `"package"`, values: `"workspace" | "package"`): runtime working directory. The default is a good fit for Vite and similar package-script based tools.
## bun_bundle
Bundles one or more JS/TS entry points with Bun build.
Attributes:
- `entry_points` (label_list, required): entry files to bundle.
- `node_modules` (label, optional): package files from a `node_modules` tree, typically produced by `bun_install`, used for package resolution.
- `deps` (label_list, optional): source/library dependencies for transitive inputs.
- `data` (label_list, optional): additional non-source files needed during bundling.
- `target` (string, default: `"browser"`, values: `"browser" | "node" | "bun"`): Bun build target.
- `format` (string, default: `"esm"`, values: `"esm" | "cjs" | "iife"`): module format.
- `minify` (bool, default: `False`): minifies bundle output.
- `sourcemap` (bool, default: `False`): emits source maps.
- `external` (string_list, optional): package names treated as external (not bundled).
## bun_test
Runs Bun tests as a Bazel test target (`bazel test`).
Attributes:
- `srcs` (label_list, required): test source files passed to `bun test`.
- `node_modules` (label, optional): package files from a `node_modules` tree, typically produced by `bun_install`, made available in runfiles.
- `deps` (label_list, optional): library dependencies required by tests.
- `data` (label_list, optional): additional runtime files needed by tests.
## js_library
Aggregates JavaScript sources and transitive Bun source dependencies.
Attributes:
- `srcs` (label_list, optional): `.js`, `.jsx`, `.mjs`, `.cjs` files.
- `deps` (label_list, optional): dependent source libraries.
## ts_library
Aggregates TypeScript sources and transitive Bun source dependencies.
Attributes:
- `srcs` (label_list, optional): `.ts`, `.tsx` files.
- `deps` (label_list, optional): dependent source libraries.

View File

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

View File

@@ -1,3 +1,11 @@
# basic example # basic example
Placeholder for end-to-end bun rules example. Minimal `bun_dev` example.
Run:
```bash
bazel run //examples/basic:web_dev
```
This starts Bun in watch mode for `main.ts`.

1
examples/basic/main.ts Normal file
View File

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

1
examples/vite_monorepo/.gitignore vendored Normal file
View File

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

View File

@@ -0,0 +1,61 @@
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

@@ -0,0 +1,39 @@
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")

531
examples/vite_monorepo/MODULE.bazel.lock generated Normal file
View File

@@ -0,0 +1,531 @@
{
"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

@@ -0,0 +1,28 @@
# 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

@@ -0,0 +1,12 @@
<!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

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

View File

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

View File

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

View File

@@ -0,0 +1,12 @@
<!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

@@ -0,0 +1,9 @@
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

@@ -0,0 +1,15 @@
{
"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

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

View File

@@ -0,0 +1,234 @@
{
"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

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

View File

@@ -0,0 +1,90 @@
#!/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"

12
flake.lock generated
View File

@@ -9,16 +9,16 @@
"treefmt-nix": "treefmt-nix" "treefmt-nix": "treefmt-nix"
}, },
"locked": { "locked": {
"lastModified": 1772613315, "lastModified": 1772815059,
"narHash": "sha256-RlPTOsyfVwuwEzvaMpwS+giOqQa6KQXMuSHyh1bctjk=", "narHash": "sha256-9Mn8t/a7b43omtmKRsF0HmFpCkNpTsvYEq0y85KLL5s=",
"ref": "v1.0.5", "ref": "v2.0.1",
"rev": "e445e49baf8b44b385108cd4f26a14d8ccf9fd35", "rev": "80cc529de7060e079d89a69d8daaf0347b53d8f9",
"revCount": 35, "revCount": 43,
"type": "git", "type": "git",
"url": "https://git.dgren.dev/eric/nix-flake-lib" "url": "https://git.dgren.dev/eric/nix-flake-lib"
}, },
"original": { "original": {
"ref": "v1.0.5", "ref": "v2.0.1",
"type": "git", "type": "git",
"url": "https://git.dgren.dev/eric/nix-flake-lib" "url": "https://git.dgren.dev/eric/nix-flake-lib"
} }

View File

@@ -3,7 +3,7 @@
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
devshell-lib.url = "git+https://git.dgren.dev/eric/nix-flake-lib?ref=v1.0.5"; devshell-lib.url = "git+https://git.dgren.dev/eric/nix-flake-lib?ref=v2.0.1";
devshell-lib.inputs.nixpkgs.follows = "nixpkgs"; devshell-lib.inputs.nixpkgs.follows = "nixpkgs";
}; };
@@ -46,7 +46,7 @@
]; ];
features = { features = {
oxfmt = true; oxfmt = false;
}; };
formatters = { formatters = {
@@ -65,7 +65,9 @@
additionalHooks = { additionalHooks = {
tests = { tests = {
enable = true; enable = true;
entry = "echo 'No tests defined yet.'"; entry = ''
bazel test //tests/...
'';
pass_filenames = false; pass_filenames = false;
stages = [ "pre-push" ]; stages = [ "pre-push" ];
}; };
@@ -136,6 +138,36 @@
sed -E -i 's#^([[:space:]]*version[[:space:]]*=[[:space:]]*")[^"]*(",)$#\1'"$FULL_VERSION"'\2#' "$ROOT_DIR/MODULE.bazel" sed -E -i 's#^([[:space:]]*version[[:space:]]*=[[:space:]]*")[^"]*(",)$#\1'"$FULL_VERSION"'\2#' "$ROOT_DIR/MODULE.bazel"
''; '';
} }
{
run = ''
README="$ROOT_DIR/README.md"
TMP="$README.tmp"
awk -v stable="$BASE_VERSION" -v prerelease="$BASE_VERSION-rc.1" '
{
line = $0
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)
}
print line
}
' "$README" > "$TMP" && mv "$TMP" "$README"
'';
}
]; ];
postVersion = '' postVersion = ''

View File

@@ -1,280 +0,0 @@
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,9 +1,50 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
package(default_visibility = ["//visibility:public"]) package(default_visibility = ["//visibility:public"])
exports_files([ exports_files([
"bun_binary.bzl", "bun_binary.bzl",
"bun_bundle.bzl", "bun_bundle.bzl",
"bun_install.bzl", "bun_dev.bzl",
"bun_test.bzl", "bun_install.bzl",
"js_library.bzl", "bun_script.bzl",
"bun_test.bzl",
"js_library.bzl",
]) ])
bzl_library(
name = "bun_binary_bzl",
srcs = ["bun_binary.bzl"],
)
bzl_library(
name = "bun_bundle_bzl",
srcs = ["bun_bundle.bzl"],
deps = [":js_library_bzl"],
)
bzl_library(
name = "bun_dev_bzl",
srcs = ["bun_dev.bzl"],
)
bzl_library(
name = "bun_install_bzl",
srcs = ["bun_install.bzl"],
)
bzl_library(
name = "bun_script_bzl",
srcs = ["bun_script.bzl"],
)
bzl_library(
name = "bun_test_bzl",
srcs = ["bun_test.bzl"],
deps = [":js_library_bzl"],
)
bzl_library(
name = "js_library_bzl",
srcs = ["js_library.bzl"],
)

View File

@@ -14,13 +14,38 @@ def _bun_binary_impl(ctx):
set -euo pipefail set -euo pipefail
runfiles_dir="${{RUNFILES_DIR:-$0.runfiles}}" runfiles_dir="${{RUNFILES_DIR:-$0.runfiles}}"
workspace_root="${{runfiles_dir}}/_main"
bun_bin="${{runfiles_dir}}/_main/{bun_short_path}" bun_bin="${{runfiles_dir}}/_main/{bun_short_path}"
entry_point="${{runfiles_dir}}/_main/{entry_short_path}" entry_point="${{runfiles_dir}}/_main/{entry_short_path}"
exec "${{bun_bin}}" run "${{entry_point}}" "$@" resolve_entrypoint_workdir() {{
local dir
dir="$(dirname "${{entry_point}}")"
while [[ "${{dir}}" == "${{workspace_root}}"* ]]; do
if [[ -f "${{dir}}/.env" || -f "${{dir}}/package.json" ]]; then
echo "${{dir}}"
return 0
fi
if [[ "${{dir}}" == "${{workspace_root}}" ]]; then
break
fi
dir="$(dirname "${{dir}}")"
done
echo "$(dirname "${{entry_point}}")"
}}
working_dir="{working_dir}"
if [[ "${{working_dir}}" == "entry_point" ]]; then
cd "$(resolve_entrypoint_workdir)"
else
cd "${{workspace_root}}"
fi
exec "${{bun_bin}}" --bun run "${{entry_point}}" "$@"
""".format( """.format(
bun_short_path = bun_bin.short_path, bun_short_path = bun_bin.short_path,
entry_short_path = entry_point.short_path, entry_short_path = entry_point.short_path,
working_dir = ctx.attr.working_dir,
), ),
) )
@@ -43,13 +68,28 @@ exec "${{bun_bin}}" run "${{entry_point}}" "$@"
bun_binary = rule( bun_binary = rule(
implementation = _bun_binary_impl, 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 = { attrs = {
"entry_point": attr.label( "entry_point": attr.label(
mandatory = True, mandatory = True,
allow_single_file = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"], 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.",
),
"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`.",
), ),
"node_modules": attr.label(),
"data": attr.label_list(allow_files = True),
}, },
executable = True, executable = True,
toolchains = ["//bun:toolchain_type"], toolchains = ["//bun:toolchain_type"],

View File

@@ -27,6 +27,7 @@ def _bun_bundle_impl(ctx):
outputs.append(output) outputs.append(output)
args = ctx.actions.args() args = ctx.actions.args()
args.add("--bun")
args.add("build") args.add("build")
args.add(entry.path) args.add(entry.path)
args.add("--outfile") args.add("--outfile")
@@ -60,25 +61,47 @@ def _bun_bundle_impl(ctx):
bun_bundle = rule( bun_bundle = rule(
implementation = _bun_bundle_impl, 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 = { attrs = {
"entry_points": attr.label_list( "entry_points": attr.label_list(
mandatory = True, mandatory = True,
allow_files = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"], 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.",
), ),
"node_modules": attr.label(),
"deps": attr.label_list(),
"data": attr.label_list(allow_files = True),
"target": attr.string( "target": attr.string(
default = "browser", default = "browser",
values = ["browser", "node", "bun"], values = ["browser", "node", "bun"],
doc = "Bun build target environment.",
), ),
"format": attr.string( "format": attr.string(
default = "esm", default = "esm",
values = ["esm", "cjs", "iife"], 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).",
), ),
"minify": attr.bool(default = False),
"sourcemap": attr.bool(default = False),
"external": attr.string_list(),
}, },
toolchains = ["//bun:toolchain_type"], toolchains = ["//bun:toolchain_type"],
) )

186
internal/bun_dev.bzl Normal file
View File

@@ -0,0 +1,186 @@
"""Rule for running JS/TS scripts with Bun in watch mode for development."""
def _bun_dev_impl(ctx):
toolchain = ctx.toolchains["//bun:toolchain_type"]
bun_bin = toolchain.bun.bun_bin
entry_point = ctx.file.entry_point
restart_watch_paths = "\n".join([path.short_path for path in ctx.files.restart_on])
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}}"
workspace_root="${{runfiles_dir}}/_main"
bun_bin="${{runfiles_dir}}/_main/{bun_short_path}"
entry_point="${{runfiles_dir}}/_main/{entry_short_path}"
resolve_entrypoint_workdir() {{
local dir
dir="$(dirname "${{entry_point}}")"
while [[ "${{dir}}" == "${{workspace_root}}"* ]]; do
if [[ -f "${{dir}}/.env" || -f "${{dir}}/package.json" ]]; then
echo "${{dir}}"
return 0
fi
if [[ "${{dir}}" == "${{workspace_root}}" ]]; then
break
fi
dir="$(dirname "${{dir}}")"
done
echo "$(dirname "${{entry_point}}")"
}}
working_dir="{working_dir}"
if [[ "${{working_dir}}" == "entry_point" ]]; then
cd "$(resolve_entrypoint_workdir)"
else
cd "${{workspace_root}}"
fi
watch_mode="{watch_mode}"
if [[ "${{watch_mode}}" == "hot" ]]; then
dev_flag="--hot"
else
dev_flag="--watch"
fi
run_dev() {{
exec "${{bun_bin}}" --bun "${{dev_flag}}" run "${{entry_point}}" "$@"
}}
if [[ {restart_count} -eq 0 ]]; then
run_dev "$@"
fi
readarray -t restart_paths <<'EOF_RESTART_PATHS'
{restart_watch_paths}
EOF_RESTART_PATHS
file_mtime() {{
local p="$1"
if stat -f '%m' "${{p}}" >/dev/null 2>&1; then
stat -f '%m' "${{p}}"
return 0
fi
stat -c '%Y' "${{p}}"
}}
declare -A mtimes
for rel in "${{restart_paths[@]}}"; do
path="${{runfiles_dir}}/_main/${{rel}}"
if [[ -e "${{path}}" ]]; then
mtimes["${{rel}}"]="$(file_mtime "${{path}}")"
else
mtimes["${{rel}}"]="missing"
fi
done
child_pid=""
restart_child() {{
if [[ -n "${{child_pid}}" ]] && kill -0 "${{child_pid}}" 2>/dev/null; then
kill "${{child_pid}}"
wait "${{child_pid}}" || true
fi
"${{bun_bin}}" --bun "${{dev_flag}}" run "${{entry_point}}" "$@" &
child_pid=$!
}}
cleanup() {{
if [[ -n "${{child_pid}}" ]] && kill -0 "${{child_pid}}" 2>/dev/null; then
kill "${{child_pid}}"
wait "${{child_pid}}" || true
fi
}}
trap cleanup EXIT INT TERM
restart_child "$@"
while true; do
sleep 1
changed=0
for rel in "${{restart_paths[@]}}"; do
path="${{runfiles_dir}}/_main/${{rel}}"
if [[ -e "${{path}}" ]]; then
current="$(file_mtime "${{path}}")"
else
current="missing"
fi
if [[ "${{current}}" != "${{mtimes[${{rel}}]}}" ]]; then
mtimes["${{rel}}"]="${{current}}"
changed=1
fi
done
if [[ "${{changed}}" -eq 1 ]]; then
restart_child "$@"
fi
done
""".format(
bun_short_path = bun_bin.short_path,
entry_short_path = entry_point.short_path,
watch_mode = ctx.attr.watch_mode,
working_dir = ctx.attr.working_dir,
restart_count = len(ctx.files.restart_on),
restart_watch_paths = restart_watch_paths,
),
)
transitive_files = []
if ctx.attr.node_modules:
transitive_files.append(ctx.attr.node_modules[DefaultInfo].files)
runfiles = ctx.runfiles(
files = [bun_bin, entry_point] + ctx.files.data + ctx.files.restart_on,
transitive_files = depset(transitive = transitive_files),
)
return [
DefaultInfo(
executable = launcher,
runfiles = runfiles,
),
]
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.
""",
attrs = {
"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.",
),
"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`.",
),
},
executable = True,
toolchains = ["//bun:toolchain_type"],
)

View File

@@ -1,5 +1,157 @@
"""Repository-rule based bun_install implementation.""" """Repository-rule based bun_install implementation."""
_DEFAULT_INSTALL_INPUTS = [
".npmrc",
"bunfig.json",
"bunfig.toml",
]
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 _materialize_workspace_packages(repository_ctx, package_json):
package_root = package_json.dirname
package_root_str = str(package_root)
written = {}
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
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): def _select_bun_binary(repository_ctx):
os_name = repository_ctx.os.name.lower() os_name = repository_ctx.os.name.lower()
arch = repository_ctx.os.arch.lower() arch = repository_ctx.os.arch.lower()
@@ -19,7 +171,6 @@ def _select_bun_binary(repository_ctx):
fail("Unsupported host platform: os={}, arch={}".format(repository_ctx.os.name, repository_ctx.os.arch)) fail("Unsupported host platform: os={}, arch={}".format(repository_ctx.os.name, repository_ctx.os.arch))
def _bun_install_repository_impl(repository_ctx): def _bun_install_repository_impl(repository_ctx):
package_json = repository_ctx.path(repository_ctx.attr.package_json) package_json = repository_ctx.path(repository_ctx.attr.package_json)
bun_lockfile = repository_ctx.path(repository_ctx.attr.bun_lockfile) bun_lockfile = repository_ctx.path(repository_ctx.attr.bun_lockfile)
@@ -31,19 +182,33 @@ def _bun_install_repository_impl(repository_ctx):
fail("bun_install: bun_lockfile not found: {}".format(repository_ctx.attr.bun_lockfile)) fail("bun_install: bun_lockfile not found: {}".format(repository_ctx.attr.bun_lockfile))
bun_bin = _select_bun_binary(repository_ctx) bun_bin = _select_bun_binary(repository_ctx)
lockfile_name = bun_lockfile.basename
repository_ctx.symlink(package_json, "package.json") if lockfile_name not in ["bun.lock", "bun.lockb"]:
repository_ctx.symlink(bun_lockfile, "bun.lockb") lockfile_name = "bun.lock"
result = repository_ctx.execute( repository_ctx.file("package.json", repository_ctx.read(package_json))
[str(bun_bin), "install", "--frozen-lockfile", "--no-progress"], repository_ctx.symlink(bun_lockfile, lockfile_name)
timeout = 600, _materialize_install_inputs(repository_ctx, package_json)
quiet = False, _materialize_workspace_packages(repository_ctx, package_json)
environment = {"HOME": str(repository_ctx.path("."))},
) install_args = [str(bun_bin), "--bun", "install", "--frozen-lockfile", "--no-progress"]
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,
)
if result.return_code: if result.return_code:
fail("""bun_install failed running `bun install --frozen-lockfile`. fail("""bun_install failed running `bun --bun install --frozen-lockfile`.
stdout: stdout:
{} {}
stderr: stderr:
@@ -54,36 +219,38 @@ stderr:
"BUILD.bazel", "BUILD.bazel",
"""filegroup( """filegroup(
name = "node_modules", name = "node_modules",
srcs = glob(["node_modules/**"], allow_empty = False), srcs = glob(["**/node_modules/**"], allow_empty = False),
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
""", """,
) )
bun_install_repository = repository_rule( bun_install_repository = repository_rule(
implementation = _bun_install_repository_impl, implementation = _bun_install_repository_impl,
attrs = { attrs = {
"package_json": attr.label(mandatory = True, allow_single_file = True), "package_json": attr.label(mandatory = True, allow_single_file = True),
"bun_lockfile": attr.label(mandatory = True, allow_single_file = True), "bun_lockfile": attr.label(mandatory = True, allow_single_file = True),
"bun_linux_x64": attr.label(default = "@bun_linux_x64//:bun", allow_single_file = True), "install_inputs": attr.label_list(allow_files = True),
"bun_linux_aarch64": attr.label(default = "@bun_linux_aarch64//:bun", allow_single_file = True), "isolated_home": attr.bool(default = True),
"bun_darwin_x64": attr.label(default = "@bun_darwin_x64//:bun", allow_single_file = True), "bun_linux_x64": attr.label(default = "@bun_linux_x64//:bun-linux-x64/bun", allow_single_file = True),
"bun_darwin_aarch64": attr.label(default = "@bun_darwin_aarch64//:bun", allow_single_file = True), "bun_linux_aarch64": attr.label(default = "@bun_linux_aarch64//:bun-linux-aarch64/bun", allow_single_file = True),
"bun_windows_x64": attr.label(default = "@bun_windows_x64//: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_install_repository = bun_install_repository def bun_install(name, package_json, bun_lockfile, install_inputs = [], isolated_home = True):
def bun_install(name, package_json, bun_lockfile):
"""Create an external repository containing installed node_modules. """Create an external repository containing installed node_modules.
Args: Args:
name: Repository name to create. name: Repository name to create.
package_json: Label to a package.json file. package_json: Label to a package.json file.
bun_lockfile: Label to a bun.lockb 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.
Usage (WORKSPACE): Usage (WORKSPACE):
bun_install( bun_install(
@@ -97,4 +264,6 @@ def bun_install(name, package_json, bun_lockfile):
name = name, name = name,
package_json = package_json, package_json = package_json,
bun_lockfile = bun_lockfile, bun_lockfile = bun_lockfile,
install_inputs = install_inputs,
isolated_home = isolated_home,
) )

219
internal/bun_script.bzl Normal file
View File

@@ -0,0 +1,219 @@
"""Rule for running package.json scripts with Bun."""
def _shell_quote(value):
return "'" + value.replace("'", "'\"'\"'") + "'"
def _bun_script_impl(ctx):
toolchain = ctx.toolchains["//bun:toolchain_type"]
bun_bin = toolchain.bun.bun_bin
package_json = ctx.file.package_json
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}}"
workspace_root="${{runfiles_dir}}/_main"
workspace_root="$(cd "${{workspace_root}}" && pwd -P)"
bun_bin="${{runfiles_dir}}/_main/{bun_short_path}"
package_json="${{runfiles_dir}}/_main/{package_json_short_path}"
package_dir="$(cd "$(dirname "${{package_json}}")" && pwd -P)"
package_rel_dir="{package_rel_dir}"
select_primary_node_modules() {{
local selected=""
local fallback=""
while IFS= read -r node_modules_dir; do
if [[ -z "${{fallback}}" ]]; then
fallback="${{node_modules_dir}}"
fi
if [[ ! -d "${{node_modules_dir}}/.bun" ]]; then
continue
fi
if [[ "${{node_modules_dir}}" != *"/runfiles/_main/"* ]]; then
selected="${{node_modules_dir}}"
break
fi
if [[ -z "${{selected}}" ]]; then
selected="${{node_modules_dir}}"
fi
done < <(find -L "${{runfiles_dir}}" -type d -name node_modules 2>/dev/null | sort)
if [[ -n "${{selected}}" ]]; then
echo "${{selected}}"
else
echo "${{fallback}}"
fi
}}
primary_node_modules="$(select_primary_node_modules)"
runtime_workspace="$(mktemp -d)"
cleanup_runtime_workspace() {{
rm -rf "${{runtime_workspace}}"
}}
trap cleanup_runtime_workspace EXIT
runtime_package_dir="${{runtime_workspace}}/${{package_rel_dir}}"
mkdir -p "${{runtime_package_dir}}"
cp -RL "${{package_dir}}/." "${{runtime_package_dir}}/"
install_repo_root=""
if [[ -n "${{primary_node_modules}}" ]]; then
install_repo_root="$(dirname "${{primary_node_modules}}")"
ln -s "${{primary_node_modules}}" "${{runtime_workspace}}/node_modules"
fi
find_node_modules() {{
local dir="$1"
local root="$2"
while [[ "$dir" == "$root"* ]]; do
if [[ -d "$dir/node_modules" ]]; then
echo "$dir/node_modules"
return 0
fi
if [[ "$dir" == "$root" ]]; then
break
fi
dir="$(dirname "$dir")"
done
return 1
}}
find_install_repo_node_modules() {{
local repo_root="$1"
local rel_dir="$2"
local candidate="${{rel_dir}}"
while [[ -n "${{candidate}}" ]]; do
if [[ -d "${{repo_root}}/${{candidate}}/node_modules" ]]; then
echo "${{repo_root}}/${{candidate}}/node_modules"
return 0
fi
if [[ "${{candidate}}" != */* ]]; then
break
fi
candidate="${{candidate#*/}}"
done
if [[ -d "${{repo_root}}/node_modules" ]]; then
echo "${{repo_root}}/node_modules"
return 0
fi
return 1
}}
resolved_install_node_modules=""
if [[ -n "${{install_repo_root}}" ]]; then
resolved_install_node_modules="$(find_install_repo_node_modules "${{install_repo_root}}" "${{package_rel_dir}}" || true)"
fi
if [[ -n "${{resolved_install_node_modules}}" ]]; then
rm -rf "${{runtime_package_dir}}/node_modules"
ln -s "${{resolved_install_node_modules}}" "${{runtime_package_dir}}/node_modules"
else
resolved_node_modules="$(find_node_modules "${{runtime_package_dir}}" "${{runtime_workspace}}" || true)"
if [[ -n "${{resolved_node_modules}}" && "${{resolved_node_modules}}" != "${{runtime_package_dir}}/node_modules" ]]; then
rm -rf "${{runtime_package_dir}}/node_modules"
ln -s "${{resolved_node_modules}}" "${{runtime_package_dir}}/node_modules"
fi
fi
path_entries=()
if [[ -d "${{runtime_package_dir}}/node_modules/.bin" ]]; then
path_entries+=("${{runtime_package_dir}}/node_modules/.bin")
fi
if [[ -d "${{runtime_workspace}}/node_modules/.bin" && "${{runtime_workspace}}/node_modules/.bin" != "${{runtime_package_dir}}/node_modules/.bin" ]]; then
path_entries+=("${{runtime_workspace}}/node_modules/.bin")
fi
if [[ ${{#path_entries[@]}} -gt 0 ]]; then
export PATH="$(IFS=:; echo "${{path_entries[*]}}"):${{PATH}}"
fi
working_dir="{working_dir}"
if [[ "${{working_dir}}" == "package" ]]; then
cd "${{runtime_package_dir}}"
else
cd "${{runtime_workspace}}"
fi
exec "${{bun_bin}}" --bun run {script} "$@"
""".format(
bun_short_path = bun_bin.short_path,
package_json_short_path = package_json.short_path,
package_rel_dir = package_json.dirname,
working_dir = ctx.attr.working_dir,
script = _shell_quote(ctx.attr.script),
),
)
transitive_files = []
if ctx.attr.node_modules:
transitive_files.append(ctx.attr.node_modules[DefaultInfo].files)
runfiles = ctx.runfiles(
files = [bun_bin, package_json] + ctx.files.data,
transitive_files = depset(transitive = transitive_files),
)
return [
DefaultInfo(
executable = launcher,
runfiles = runfiles,
),
]
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
`node_modules/.bin` available on `PATH`.
""",
attrs = {
"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. 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.",
),
"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.",
),
},
executable = True,
toolchains = ["//bun:toolchain_type"],
)

View File

@@ -24,15 +24,15 @@ bun_bin="${{runfiles_dir}}/_main/{bun_short_path}"
cd "${{runfiles_dir}}/_main" cd "${{runfiles_dir}}/_main"
if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" && -n "${{COVERAGE_DIR:-}}" ]]; then if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" && -n "${{COVERAGE_DIR:-}}" ]]; then
exec "${{bun_bin}}" test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" --coverage "$@" exec "${{bun_bin}}" --bun test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" --coverage "$@"
fi fi
if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" ]]; then if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" ]]; then
exec "${{bun_bin}}" test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" "$@" exec "${{bun_bin}}" --bun test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" "$@"
fi fi
if [[ -n "${{COVERAGE_DIR:-}}" ]]; then if [[ -n "${{COVERAGE_DIR:-}}" ]]; then
exec "${{bun_bin}}" test {src_args} --coverage "$@" exec "${{bun_bin}}" --bun test {src_args} --coverage "$@"
fi fi
exec "${{bun_bin}}" test {src_args} "$@" exec "${{bun_bin}}" --bun test {src_args} "$@"
""".format( """.format(
bun_short_path = bun_bin.short_path, bun_short_path = bun_bin.short_path,
src_args = src_args, src_args = src_args,
@@ -63,14 +63,26 @@ exec "${{bun_bin}}" test {src_args} "$@"
bun_test = rule( bun_test = rule(
implementation = _bun_test_impl, implementation = _bun_test_impl,
doc = """Runs Bun tests as a Bazel test target.
Supports Bazel test filtering (`--test_filter`) and coverage integration.
""",
attrs = { attrs = {
"srcs": attr.label_list( "srcs": attr.label_list(
mandatory = True, mandatory = True,
allow_files = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"], 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.",
), ),
"node_modules": attr.label(),
"deps": attr.label_list(),
"data": attr.label_list(allow_files = True),
}, },
test = True, test = True,
toolchains = ["//bun:toolchain_type"], toolchains = ["//bun:toolchain_type"],

View File

@@ -1,7 +1,9 @@
"""Lightweight JS/TS source grouping rules.""" """Lightweight JS/TS source grouping rules."""
BunSourcesInfo = provider(fields = ["transitive_sources"]) BunSourcesInfo = provider(
"Provides transitive sources for Bun libraries.",
fields = ["transitive_sources"],
)
def _bun_library_impl(ctx): def _bun_library_impl(ctx):
transitive_sources = [ transitive_sources = [
@@ -18,23 +20,30 @@ def _bun_library_impl(ctx):
DefaultInfo(files = all_sources), DefaultInfo(files = all_sources),
] ]
js_library = rule( js_library = rule(
implementation = _bun_library_impl, implementation = _bun_library_impl,
doc = "Aggregates JavaScript sources and transitive Bun source dependencies.",
attrs = { attrs = {
"srcs": attr.label_list( "srcs": attr.label_list(
allow_files = [".js", ".jsx", ".mjs", ".cjs"], allow_files = [".js", ".jsx", ".mjs", ".cjs"],
doc = "JavaScript source files in this library.",
),
"deps": attr.label_list(
doc = "Other Bun source libraries to include transitively.",
), ),
"deps": attr.label_list(),
}, },
) )
ts_library = rule( ts_library = rule(
implementation = _bun_library_impl, implementation = _bun_library_impl,
doc = "Aggregates TypeScript sources and transitive Bun source dependencies.",
attrs = { attrs = {
"srcs": attr.label_list( "srcs": attr.label_list(
allow_files = [".ts", ".tsx"], allow_files = [".ts", ".tsx"],
doc = "TypeScript source files in this library.",
),
"deps": attr.label_list(
doc = "Other Bun source libraries to include transitively.",
), ),
"deps": attr.label_list(),
}, },
) )

View File

@@ -43,3 +43,31 @@ sh_test(
"//tests/binary_test:BUILD.bazel", "//tests/binary_test:BUILD.bazel",
], ],
) )
bun_binary(
name = "env_cwd_bin",
entry_point = "env.ts",
data = [".env"],
working_dir = "entry_point",
)
sh_test(
name = "bun_binary_env_cwd_test",
srcs = ["run_env_binary.sh"],
args = ["$(location :env_cwd_bin)"],
data = [":env_cwd_bin"],
)
bun_binary(
name = "env_parent_cwd_bin",
entry_point = "env_parent/src/main.ts",
data = ["env_parent/.env"],
working_dir = "entry_point",
)
sh_test(
name = "bun_binary_env_parent_cwd_test",
srcs = ["run_parent_env_binary.sh"],
args = ["$(location :env_parent_cwd_bin)"],
data = [":env_parent_cwd_bin"],
)

2
tests/binary_test/env.ts Normal file
View File

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

View File

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

View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
binary="$1"
output="$(${binary})"
if [[ ${output} != "from-dotenv" ]]; then
echo "Expected .env value from entry-point directory, got: ${output}" >&2
exit 1
fi

View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
binary="$1"
output="$(${binary})"
if [[ ${output} != "from-parent-dotenv" ]]; then
echo "Expected .env value from parent directory, got: ${output}" >&2
exit 1
fi

View File

@@ -5,4 +5,4 @@ rule_file="$1"
grep -Fq 'set -euo pipefail' "${rule_file}" 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 '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}" grep -Fq 'exec "${{bun_bin}}" --bun test {src_args} "$@"' "${rule_file}"

View File

@@ -3,5 +3,5 @@ set -euo pipefail
rule_file="$1" rule_file="$1"
grep -Fq 'exec "${{bun_bin}}" test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" "$@"' "${rule_file}" grep -Fq 'exec "${{bun_bin}}" --bun test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" "$@"' "${rule_file}"
grep -Fq 'if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" ]]' "${rule_file}" grep -Fq 'if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" ]]' "${rule_file}"

View File

@@ -6,5 +6,7 @@ extension_file="$1"
grep -Eq 'bun_install[[:space:]]*=[[:space:]]*module_extension\(' "${extension_file}" grep -Eq 'bun_install[[:space:]]*=[[:space:]]*module_extension\(' "${extension_file}"
grep -Eq 'tag_classes[[:space:]]*=[[:space:]]*\{"install":[[:space:]]*_install\}' "${extension_file}" grep -Eq 'tag_classes[[:space:]]*=[[:space:]]*\{"install":[[:space:]]*_install\}' "${extension_file}"
grep -Eq '"name":[[:space:]]*attr\.string\(mandatory[[:space:]]*=[[:space:]]*True\)' "${extension_file}" grep -Eq '"name":[[:space:]]*attr\.string\(mandatory[[:space:]]*=[[:space:]]*True\)' "${extension_file}"
grep -Eq '"package_json":[[:space:]]*attr\.string\(mandatory[[:space:]]*=[[:space:]]*True\)' "${extension_file}" grep -Eq '"package_json":[[:space:]]*attr\.label\(mandatory[[:space:]]*=[[:space:]]*True\)' "${extension_file}"
grep -Eq '"bun_lockfile":[[:space:]]*attr\.string\(mandatory[[:space:]]*=[[:space:]]*True\)' "${extension_file}" grep -Eq '"bun_lockfile":[[:space:]]*attr\.label\(mandatory[[:space:]]*=[[:space:]]*True\)' "${extension_file}"
grep -Eq '"install_inputs":[[:space:]]*attr\.label_list\(allow_files[[:space:]]*=[[:space:]]*True\)' "${extension_file}"
grep -Eq '"isolated_home":[[:space:]]*attr\.bool\(default[[:space:]]*=[[:space:]]*True\)' "${extension_file}"

View File

@@ -77,6 +77,13 @@ sh_test(
data = ["//internal:bun_install.bzl"], data = ["//internal:bun_install.bzl"],
) )
sh_test(
name = "bun_install_environment_shape_test",
srcs = ["environment_shape.sh"],
args = ["$(location //internal:bun_install.bzl)"],
data = ["//internal:bun_install.bzl"],
)
sh_test( sh_test(
name = "bun_install_workspaces_test", name = "bun_install_workspaces_test",
srcs = ["workspaces.sh"], srcs = ["workspaces.sh"],

View File

@@ -4,6 +4,10 @@ set -euo pipefail
rule_file="$1" rule_file="$1"
grep -Eq 'install", "--frozen-lockfile", "--no-progress"' "${rule_file}" grep -Eq 'install", "--frozen-lockfile", "--no-progress"' "${rule_file}"
grep -Eq 'repository_ctx\.symlink\(package_json, "package\.json"\)' "${rule_file}" grep -Eq 'repository_ctx\.file\("package\.json", repository_ctx\.read\(package_json\)\)' "${rule_file}"
grep -Eq 'repository_ctx\.symlink\(bun_lockfile, "bun\.lockb"\)' "${rule_file}" grep -Eq 'lockfile_name = bun_lockfile\.basename' "${rule_file}"
grep -Eq 'glob\(\["node_modules/\*\*"\]' "${rule_file}" grep -Eq 'if lockfile_name not in \["bun\.lock", "bun\.lockb"\]:' "${rule_file}"
grep -Eq 'repository_ctx\.symlink\(bun_lockfile, lockfile_name\)' "${rule_file}"
grep -Eq 'glob\(\["\*\*/node_modules/\*\*"\]' "${rule_file}"
grep -Eq '_DEFAULT_INSTALL_INPUTS = \[' "${rule_file}"
grep -Eq '"install_inputs": attr\.label_list\(allow_files = True\)' "${rule_file}"

View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail
rule_file="$1"
grep -Eq 'install_args = \[str\(bun_bin\), "--bun", "install", "--frozen-lockfile", "--no-progress"\]' "${rule_file}"
grep -Eq 'if repository_ctx\.attr\.isolated_home:' "${rule_file}"
grep -Eq 'environment[[:space:]]*=[[:space:]]*\{"HOME":[[:space:]]*str\(repository_ctx\.path\("\."\)\)\}' "${rule_file}"
grep -Eq '"isolated_home": attr\.bool\(default = True\)' "${rule_file}"

View File

@@ -0,0 +1,505 @@
#!/usr/bin/env bash
set -euo pipefail
bun_path="${1:-bun}"
if ! command -v bazel >/dev/null 2>&1; then
echo "bazel is required on PATH" >&2
exit 1
fi
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
rules_bun_root="$(cd "${script_dir}/../.." && pwd -P)"
workdir="$(mktemp -d)"
trap 'rm -rf "${workdir}"' EXIT
fixture_dir="${workdir}/fixture"
plain_dir="${workdir}/plain"
bazel_dir="${workdir}/bazel"
mkdir -p "${fixture_dir}/packages/pkg-a" "${fixture_dir}/packages/pkg-b" "${fixture_dir}/packages/web"
cat >"${fixture_dir}/package.json" <<'JSON'
{
"name": "workspace-parity-root",
"private": true,
"workspaces": ["packages/*"]
}
JSON
cat >"${fixture_dir}/packages/pkg-a/package.json" <<'JSON'
{
"name": "@workspace/pkg-a",
"version": "1.0.0",
"main": "index.js"
}
JSON
cat >"${fixture_dir}/packages/pkg-a/index.js" <<'JS'
module.exports = { value: 42 };
JS
cat >"${fixture_dir}/packages/pkg-b/package.json" <<'JSON'
{
"name": "@workspace/pkg-b",
"version": "1.0.0",
"dependencies": {
"@workspace/pkg-a": "workspace:*",
"is-number": "7.0.0"
}
}
JSON
cat >"${fixture_dir}/packages/web/package.json" <<'JSON'
{
"name": "@workspace/web",
"private": true,
"type": "module",
"scripts": {
"build": "vite build"
},
"devDependencies": {
"vite": "5.4.14"
}
}
JSON
cat >"${fixture_dir}/packages/web/index.html" <<'HTML'
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Workspace Parity Web</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="./main.js"></script>
</body>
</html>
HTML
cat >"${fixture_dir}/packages/web/main.js" <<'JS'
import { value } from "./value.js";
const app = document.querySelector("#app");
if (app) {
app.textContent = `value=${value}`;
}
JS
cat >"${fixture_dir}/packages/web/value.js" <<'JS'
export const value = 42;
JS
cat >"${fixture_dir}/packages/web/vite.config.js" <<'JS'
export default {
resolve: {
preserveSymlinks: true,
},
optimizeDeps: {
esbuildOptions: {
preserveSymlinks: true,
},
},
};
JS
"${bun_path}" install --cwd "${fixture_dir}" >/dev/null
rm -rf "${fixture_dir}/node_modules" "${fixture_dir}/packages/pkg-b/node_modules"
cp -R "${fixture_dir}" "${plain_dir}"
cp -R "${fixture_dir}" "${bazel_dir}"
"${bun_path}" install --cwd "${plain_dir}" --frozen-lockfile >/dev/null
cat >"${bazel_dir}/MODULE.bazel" <<EOF
module(
name = "workspace_parity_test",
)
bazel_dep(name = "rules_bun", version = "0.2.2")
bazel_dep(name = "rules_shell", version = "0.6.1")
local_path_override(
module_name = "rules_bun",
path = "${rules_bun_root}",
)
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",
)
bun_install_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun_install")
bun_install_ext.install(
name = "node_modules",
package_json = "//:package.json",
bun_lockfile = "//:bun.lock",
)
use_repo(bun_install_ext, "node_modules")
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",
)
EOF
cat >"${bazel_dir}/BUILD.bazel" <<'EOF'
load("@rules_bun//bun:defs.bzl", "bun_script")
load("@rules_shell//shell:sh_test.bzl", "sh_test")
exports_files([
"package.json",
"bun.lock",
"node_modules_smoke_test.sh",
])
bun_script(
name = "web_build",
script = "build",
package_json = "packages/web/package.json",
node_modules = "@node_modules//:node_modules",
data = [
"packages/web/index.html",
"packages/web/main.js",
"packages/web/value.js",
"packages/web/vite.config.js",
],
)
sh_test(
name = "node_modules_smoke_test",
srcs = ["node_modules_smoke_test.sh"],
data = ["@node_modules//:node_modules"],
)
EOF
cat >"${bazel_dir}/node_modules_smoke_test.sh" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
runfiles_dir="${RUNFILES_DIR:-$0.runfiles}"
if ! find "${runfiles_dir}" -path '*/node_modules/.bin/vite' -print -quit | grep -q .; then
echo "vite binary not found in runfiles node_modules/.bin" >&2
exit 1
fi
EOF
chmod +x "${bazel_dir}/node_modules_smoke_test.sh"
(
cd "${bazel_dir}"
bazel build @node_modules//:node_modules >/dev/null
bazel test //:node_modules_smoke_test >/dev/null
bazel run //:web_build -- --emptyOutDir >/dev/null
)
output_base="$(cd "${bazel_dir}" && bazel info output_base)"
bazel_repo_dir="$(find "${output_base}/external" -maxdepth 1 -type d -name '*+node_modules' | head -n 1)"
if [[ -z ${bazel_repo_dir} ]]; then
echo "Could not locate generated Bazel node_modules repository" >&2
exit 1
fi
bazel_node_modules="${bazel_repo_dir}/node_modules"
plain_node_modules="${plain_dir}/node_modules"
if [[ ! -d ${plain_node_modules} ]]; then
echo "Plain Bun install did not produce node_modules" >&2
exit 1
fi
if [[ ! -d ${bazel_node_modules} ]]; then
echo "Bazel bun_install did not produce node_modules" >&2
exit 1
fi
plain_layout_manifest="${workdir}/plain.layout.manifest"
bazel_layout_manifest="${workdir}/bazel.layout.manifest"
python3 - "${plain_dir}" >"${plain_layout_manifest}" <<'PY'
import hashlib
import os
import stat
import sys
root = sys.argv[1]
def include(rel):
if rel == "node_modules" or rel.startswith("node_modules/"):
return True
if rel.startswith("packages/") and "/node_modules" in rel:
return True
return False
for dirpath, dirnames, filenames in os.walk(root, topdown=True, followlinks=False):
dirnames.sort()
filenames.sort()
rel_dir = os.path.relpath(dirpath, root)
if rel_dir == ".":
rel_dir = ""
for name in dirnames + filenames:
full = os.path.join(dirpath, name)
rel = os.path.join(rel_dir, name) if rel_dir else name
if not include(rel):
continue
st = os.lstat(full)
mode = st.st_mode
if stat.S_ISLNK(mode):
print(f"L {rel} -> {os.readlink(full)}")
elif stat.S_ISDIR(mode):
print(f"D {rel}")
elif stat.S_ISREG(mode):
h = hashlib.sha256()
with open(full, "rb") as f:
while True:
chunk = f.read(1024 * 1024)
if not chunk:
break
h.update(chunk)
print(f"F {rel} {h.hexdigest()}")
else:
print(f"O {rel} {mode}")
PY
python3 - "${bazel_repo_dir}" >"${bazel_layout_manifest}" <<'PY'
import hashlib
import os
import stat
import sys
root = sys.argv[1]
def include(rel):
if rel == "node_modules" or rel.startswith("node_modules/"):
return True
if rel.startswith("packages/") and "/node_modules" in rel:
return True
return False
for dirpath, dirnames, filenames in os.walk(root, topdown=True, followlinks=False):
dirnames.sort()
filenames.sort()
rel_dir = os.path.relpath(dirpath, root)
if rel_dir == ".":
rel_dir = ""
for name in dirnames + filenames:
full = os.path.join(dirpath, name)
rel = os.path.join(rel_dir, name) if rel_dir else name
if not include(rel):
continue
st = os.lstat(full)
mode = st.st_mode
if stat.S_ISLNK(mode):
print(f"L {rel} -> {os.readlink(full)}")
elif stat.S_ISDIR(mode):
print(f"D {rel}")
elif stat.S_ISREG(mode):
h = hashlib.sha256()
with open(full, "rb") as f:
while True:
chunk = f.read(1024 * 1024)
if not chunk:
break
h.update(chunk)
print(f"F {rel} {h.hexdigest()}")
else:
print(f"O {rel} {mode}")
PY
if ! diff -u "${plain_layout_manifest}" "${bazel_layout_manifest}"; then
echo "Workspace node_modules layout differs between plain bun install and Bazel bun_install" >&2
exit 1
fi
plain_manifest="${workdir}/plain.manifest"
bazel_manifest="${workdir}/bazel.manifest"
python3 - "${plain_node_modules}" >"${plain_manifest}" <<'PY'
import hashlib
import os
import stat
import sys
root = sys.argv[1]
for dirpath, dirnames, filenames in os.walk(root, topdown=True, followlinks=False):
dirnames.sort()
filenames.sort()
rel_dir = os.path.relpath(dirpath, root)
if rel_dir == ".":
rel_dir = ""
for name in dirnames + filenames:
full = os.path.join(dirpath, name)
rel = os.path.join(rel_dir, name) if rel_dir else name
st = os.lstat(full)
mode = st.st_mode
if stat.S_ISLNK(mode):
print(f"L {rel} -> {os.readlink(full)}")
elif stat.S_ISDIR(mode):
print(f"D {rel}")
elif stat.S_ISREG(mode):
h = hashlib.sha256()
with open(full, "rb") as f:
while True:
chunk = f.read(1024 * 1024)
if not chunk:
break
h.update(chunk)
print(f"F {rel} {h.hexdigest()}")
else:
print(f"O {rel} {mode}")
PY
python3 - "${bazel_node_modules}" >"${bazel_manifest}" <<'PY'
import hashlib
import os
import stat
import sys
root = sys.argv[1]
for dirpath, dirnames, filenames in os.walk(root, topdown=True, followlinks=False):
dirnames.sort()
filenames.sort()
rel_dir = os.path.relpath(dirpath, root)
if rel_dir == ".":
rel_dir = ""
for name in dirnames + filenames:
full = os.path.join(dirpath, name)
rel = os.path.join(rel_dir, name) if rel_dir else name
st = os.lstat(full)
mode = st.st_mode
if stat.S_ISLNK(mode):
print(f"L {rel} -> {os.readlink(full)}")
elif stat.S_ISDIR(mode):
print(f"D {rel}")
elif stat.S_ISREG(mode):
h = hashlib.sha256()
with open(full, "rb") as f:
while True:
chunk = f.read(1024 * 1024)
if not chunk:
break
h.update(chunk)
print(f"F {rel} {h.hexdigest()}")
else:
print(f"O {rel} {mode}")
PY
if ! diff -u "${plain_manifest}" "${bazel_manifest}"; then
echo "node_modules trees differ between plain bun install and Bazel bun_install" >&2
exit 1
fi
plain_dist_dir="${workdir}/plain-dist"
bazel_dist_dir="${workdir}/bazel-dist"
rm -rf "${plain_dist_dir}" "${bazel_dist_dir}"
"${bun_path}" run --cwd "${plain_dir}/packages/web" build -- --emptyOutDir --outDir "${plain_dist_dir}" >/dev/null
(
cd "${bazel_dir}"
bazel run //:web_build -- --emptyOutDir --outDir "${bazel_dist_dir}" >/dev/null
)
if [[ ! -d ${plain_dist_dir} ]]; then
echo "Plain Bun Vite build did not produce output" >&2
exit 1
fi
if [[ ! -d ${bazel_dist_dir} ]]; then
echo "Bazel Vite build did not produce output" >&2
exit 1
fi
plain_build_manifest="${workdir}/plain.build.manifest"
bazel_build_manifest="${workdir}/bazel.build.manifest"
python3 - "${plain_dist_dir}" >"${plain_build_manifest}" <<'PY'
import hashlib
import os
import stat
import sys
root = sys.argv[1]
for dirpath, dirnames, filenames in os.walk(root, topdown=True, followlinks=False):
dirnames.sort()
filenames.sort()
rel_dir = os.path.relpath(dirpath, root)
if rel_dir == ".":
rel_dir = ""
for name in dirnames + filenames:
full = os.path.join(dirpath, name)
rel = os.path.join(rel_dir, name) if rel_dir else name
st = os.lstat(full)
mode = st.st_mode
if stat.S_ISLNK(mode):
print(f"L {rel} -> {os.readlink(full)}")
elif stat.S_ISDIR(mode):
print(f"D {rel}")
elif stat.S_ISREG(mode):
h = hashlib.sha256()
with open(full, "rb") as f:
while True:
chunk = f.read(1024 * 1024)
if not chunk:
break
h.update(chunk)
print(f"F {rel} {h.hexdigest()}")
else:
print(f"O {rel} {mode}")
PY
python3 - "${bazel_dist_dir}" >"${bazel_build_manifest}" <<'PY'
import hashlib
import os
import stat
import sys
root = sys.argv[1]
for dirpath, dirnames, filenames in os.walk(root, topdown=True, followlinks=False):
dirnames.sort()
filenames.sort()
rel_dir = os.path.relpath(dirpath, root)
if rel_dir == ".":
rel_dir = ""
for name in dirnames + filenames:
full = os.path.join(dirpath, name)
rel = os.path.join(rel_dir, name) if rel_dir else name
st = os.lstat(full)
mode = st.st_mode
if stat.S_ISLNK(mode):
print(f"L {rel} -> {os.readlink(full)}")
elif stat.S_ISDIR(mode):
print(f"D {rel}")
elif stat.S_ISREG(mode):
h = hashlib.sha256()
with open(full, "rb") as f:
while True:
chunk = f.read(1024 * 1024)
if not chunk:
break
h.update(chunk)
print(f"F {rel} {h.hexdigest()}")
else:
print(f"O {rel} {mode}")
PY
if ! diff -u "${plain_build_manifest}" "${bazel_build_manifest}"; then
echo "Vite build outputs differ between plain Bun and Bazel bun_script" >&2
exit 1
fi

View File

@@ -1,5 +1,16 @@
load("@rules_shell//shell:sh_test.bzl", "sh_test") load("@rules_shell//shell:sh_test.bzl", "sh_test")
test_suite(
name = "examples_test",
tests = [
":examples_basic_run_e2e_test",
":examples_workspace_bundle_e2e_test",
":examples_workspace_catalog_shape_test",
":examples_vite_monorepo_catalog_shape_test",
":examples_vite_monorepo_e2e_test",
],
)
sh_test( sh_test(
name = "examples_basic_e2e_build_test", name = "examples_basic_e2e_build_test",
srcs = ["examples_basic_e2e_build_test.sh"], srcs = ["examples_basic_e2e_build_test.sh"],
@@ -13,6 +24,13 @@ sh_test(
], ],
) )
sh_test(
name = "examples_basic_run_e2e_test",
srcs = ["examples_basic_run_e2e_test.sh"],
args = ["$(location //examples/basic:web_dev)"],
data = ["//examples/basic:web_dev"],
)
sh_test( sh_test(
name = "examples_workspace_bundle_e2e_test", name = "examples_workspace_bundle_e2e_test",
srcs = ["examples_workspace_bundle_e2e_test.sh"], srcs = ["examples_workspace_bundle_e2e_test.sh"],
@@ -35,6 +53,34 @@ sh_test(
], ],
) )
sh_test(
name = "examples_vite_monorepo_catalog_shape_test",
srcs = ["examples_vite_monorepo_catalog_shape_test.sh"],
args = [
"$(location //examples/vite_monorepo:package.json)",
"$(location //examples/vite_monorepo:apps/app-a/package.json)",
"$(location //examples/vite_monorepo:apps/app-b/package.json)",
],
data = [
"//examples/vite_monorepo:package.json",
"//examples/vite_monorepo:apps/app-a/package.json",
"//examples/vite_monorepo:apps/app-b/package.json",
],
)
sh_test(
name = "examples_vite_monorepo_e2e_test",
srcs = ["examples_vite_monorepo_e2e_test.sh"],
args = [
"$(location //examples/vite_monorepo:app_a_dev)",
"$(location //examples/vite_monorepo:app_b_dev)",
],
data = [
"//examples/vite_monorepo:app_a_dev",
"//examples/vite_monorepo:app_b_dev",
],
)
sh_test( sh_test(
name = "repo_all_targets_test", name = "repo_all_targets_test",
srcs = ["repo_all_targets_test.sh"], srcs = ["repo_all_targets_test.sh"],

View File

@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -euo pipefail
binary="$1"
workdir="$(mktemp -d)"
log_file="${workdir}/basic.log"
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
"${binary}" >"${log_file}" 2>&1 &
server_pid=$!
for _ in {1..20}; do
if grep -Fq "rules_bun bun_dev example" "${log_file}"; then
exit 0
fi
if ! kill -0 "${server_pid}" 2>/dev/null; then
cat "${log_file}" >&2
echo "basic example process exited unexpectedly" >&2
exit 1
fi
sleep 0.5
done
cat "${log_file}" >&2
echo "Timed out waiting for bun_dev example output" >&2
exit 1

View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
root_package_json="$1"
app_a_package_json="$2"
app_b_package_json="$3"
grep -Eq '"workspaces"[[:space:]]*:[[:space:]]*\{' "${root_package_json}"
grep -Eq '"packages"[[:space:]]*:[[:space:]]*\[' "${root_package_json}"
grep -Eq '"apps/\*"' "${root_package_json}"
grep -Eq '"catalog"[[:space:]]*:[[:space:]]*\{' "${root_package_json}"
grep -Eq '"vite"[[:space:]]*:[[:space:]]*"5\.4\.14"' "${root_package_json}"
grep -Eq '"catalogs"[[:space:]]*:[[:space:]]*\{' "${root_package_json}"
grep -Eq '"testing"[[:space:]]*:[[:space:]]*\{' "${root_package_json}"
grep -Eq '"vitest"[[:space:]]*:[[:space:]]*"3\.2\.4"' "${root_package_json}"
grep -Eq '"vite"[[:space:]]*:[[:space:]]*"catalog:"' "${app_a_package_json}"
grep -Eq '"vite"[[:space:]]*:[[:space:]]*"catalog:"' "${app_b_package_json}"
grep -Eq '"vitest"[[:space:]]*:[[:space:]]*"catalog:testing"' "${app_b_package_json}"

View File

@@ -0,0 +1,75 @@
#!/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
}
verify_vite_app() {
local binary="$1"
local expected_title="$2"
local expected_js="$3"
local log_name="$4"
local port
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
if ! curl --fail --silent "http://127.0.0.1:${port}/main.js" | grep -Fq "${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

@@ -0,0 +1,86 @@
load("//bun:defs.bzl", "bun_script")
load("@rules_shell//shell:sh_test.bzl", "sh_test")
bun_script(
name = "hello_script",
script = "hello",
package_json = "package.json",
data = ["hello.ts"],
)
sh_test(
name = "bun_script_ts_test",
srcs = ["run_script.sh"],
args = ["$(location :hello_script)", "hello-script"],
data = [":hello_script"],
)
bun_script(
name = "env_script",
script = "print-env",
package_json = "package.json",
data = [
".env",
"env.ts",
],
)
sh_test(
name = "bun_script_package_cwd_test",
srcs = ["run_env_script.sh"],
args = ["$(location :env_script)"],
data = [":env_script"],
)
bun_script(
name = "vite_dev_server",
script = "dev",
package_json = "vite_app/package.json",
node_modules = "@script_test_vite_node_modules//:node_modules",
data = [
"vite_app/index.html",
"vite_app/main.js",
],
)
sh_test(
name = "bun_script_vite_app_test",
srcs = ["run_vite_app.sh"],
args = ["$(location :vite_dev_server)"],
data = [":vite_dev_server"],
)
bun_script(
name = "vite_monorepo_app_a_dev_server",
script = "dev",
package_json = "vite_monorepo/apps/app-a/package.json",
node_modules = "@script_test_vite_monorepo_node_modules//:node_modules",
data = [
"vite_monorepo/apps/app-a/index.html",
"vite_monorepo/apps/app-a/main.js",
],
)
bun_script(
name = "vite_monorepo_app_b_dev_server",
script = "dev",
package_json = "vite_monorepo/apps/app-b/package.json",
node_modules = "@script_test_vite_monorepo_node_modules//:node_modules",
data = [
"vite_monorepo/apps/app-b/index.html",
"vite_monorepo/apps/app-b/main.js",
],
)
sh_test(
name = "bun_script_vite_monorepo_apps_test",
srcs = ["run_vite_monorepo_apps.sh"],
args = [
"$(location :vite_monorepo_app_a_dev_server)",
"$(location :vite_monorepo_app_b_dev_server)",
],
data = [
":vite_monorepo_app_a_dev_server",
":vite_monorepo_app_b_dev_server",
],
)

2
tests/script_test/env.ts Normal file
View File

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

View File

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

View File

@@ -0,0 +1,12 @@
{
"name": "script-test",
"private": true,
"type": "module",
"scripts": {
"hello": "bun ./hello.ts",
"print-env": "bun ./env.ts"
},
"devDependencies": {
"@types/bun": "^1.3.10"
}
}

View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
binary="$1"
output="$(${binary})"
if [[ ${output} != "from-dotenv" ]]; then
echo "Expected .env value from package directory, got: ${output}" >&2
exit 1
fi

11
tests/script_test/run_script.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail
binary="$1"
expected="$2"
output="$(${binary})"
if [[ ${output} != "${expected}" ]]; then
echo "Unexpected output from ${binary}: ${output}" >&2
exit 1
fi

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env bash
set -euo pipefail
binary="$1"
workdir="$(mktemp -d)"
log_file="${workdir}/vite.log"
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
port="$(
python3 - <<'PY'
import socket
sock = socket.socket()
sock.bind(("127.0.0.1", 0))
print(sock.getsockname()[1])
sock.close()
PY
)"
"${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" >&2
exit 1
fi
if curl --fail --silent "http://127.0.0.1:${port}/" | grep -Fq "Vite via bun_script"; then
break
fi
sleep 0.5
done
if ! curl --fail --silent "http://127.0.0.1:${port}/" | grep -Fq "Vite via bun_script"; then
cat "${log_file}" >&2
echo "Timed out waiting for Vite index page" >&2
exit 1
fi
if ! curl --fail --silent "http://127.0.0.1:${port}/main.js" | grep -Fq "Hello from Vite"; then
cat "${log_file}" >&2
echo "Expected Vite module output was not served" >&2
exit 1
fi

View File

@@ -0,0 +1,75 @@
#!/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
}
verify_vite_app() {
local binary="$1"
local expected_title="$2"
local expected_js="$3"
local log_name="$4"
local port
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
if ! curl --fail --silent "http://127.0.0.1:${port}/main.js" | grep -Fq "${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

@@ -0,0 +1,127 @@
{
"lockfileVersion": 1,
"configVersion": 1,
"workspaces": {
"": {
"name": "vite-app-test",
"devDependencies": {
"vite": "5.4.14",
},
},
},
"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=="],
"@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/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
"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=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"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=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"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=="],
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,12 @@
<!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

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

View File

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

View File

@@ -0,0 +1,12 @@
<!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

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

View File

@@ -0,0 +1,8 @@
{
"name": "vite-monorepo-app-b",
"private": true,
"type": "module",
"scripts": {
"dev": "vite"
}
}

View File

@@ -0,0 +1,137 @@
{
"lockfileVersion": 1,
"configVersion": 1,
"workspaces": {
"": {
"name": "vite-monorepo-test",
"devDependencies": {
"vite": "5.4.14",
},
},
"apps/app-a": {
"name": "vite-monorepo-app-a",
},
"apps/app-b": {
"name": "vite-monorepo-app-b",
},
},
"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=="],
"@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/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
"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=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"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=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"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"],
}
}

View File

@@ -0,0 +1,10 @@
{
"name": "vite-monorepo-test",
"private": true,
"workspaces": [
"apps/*"
],
"devDependencies": {
"vite": "5.4.14"
}
}