mirror of
https://github.com/oven-sh/bun
synced 2026-02-03 23:48:52 +00:00
Compare commits
2 Commits
ciro/fix-p
...
jarred/pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7aabaafbb4 | ||
|
|
b6bd724bc4 |
@@ -462,7 +462,6 @@ function getBuildZigStep(platform, options) {
|
||||
cancel_on_build_failing: isMergeQueue(),
|
||||
env: getBuildEnv(platform, options),
|
||||
command: `bun run build:ci --target bun-zig --toolchain ${toolchain}`,
|
||||
timeout_in_minutes: 25,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -544,8 +543,9 @@ function getTestBunStep(platform, options, testOptions = {}) {
|
||||
label: `${getPlatformLabel(platform)} - test-bun`,
|
||||
depends_on: depends,
|
||||
agents: getTestAgent(platform, options),
|
||||
retry: getRetry(),
|
||||
cancel_on_build_failing: isMergeQueue(),
|
||||
retry: getRetry(),
|
||||
soft_fail: isMainBranch() ? true : [{ exit_status: 2 }],
|
||||
parallelism: unifiedTests ? undefined : os === "darwin" ? 2 : 10,
|
||||
command:
|
||||
os === "windows"
|
||||
@@ -590,7 +590,6 @@ function getBuildImageStep(platform, options) {
|
||||
DEBUG: "1",
|
||||
},
|
||||
retry: getRetry(),
|
||||
cancel_on_build_failing: isMergeQueue(),
|
||||
command: command.filter(Boolean).join(" "),
|
||||
timeout_in_minutes: 3 * 60,
|
||||
};
|
||||
|
||||
3
.clangd
3
.clangd
@@ -6,6 +6,3 @@ CompileFlags:
|
||||
|
||||
Diagnostics:
|
||||
UnusedIncludes: None
|
||||
|
||||
HeaderInsertion:
|
||||
IncludeBlocks: Preserve # Do not auto-include headers.
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
|
||||
bench
|
||||
vendor
|
||||
*-fixture.{js,ts}
|
||||
zig-cache
|
||||
packages/bun-uws/fuzzing
|
||||
build
|
||||
2
.github/workflows/clang-format.yml
vendored
2
.github/workflows/clang-format.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
merge_group:
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
BUN_VERSION: "1.1.27"
|
||||
LLVM_VERSION: "18.1.8"
|
||||
LLVM_VERSION_MAJOR: "18"
|
||||
|
||||
|
||||
2
.github/workflows/clang-tidy.yml
vendored
2
.github/workflows/clang-tidy.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
merge_group:
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
BUN_VERSION: "1.1.27"
|
||||
LLVM_VERSION: "18.1.8"
|
||||
LLVM_VERSION_MAJOR: "18"
|
||||
|
||||
|
||||
10
.github/workflows/labeled.yml
vendored
10
.github/workflows/labeled.yml
vendored
@@ -1,6 +1,6 @@
|
||||
name: Issue Labeled
|
||||
env:
|
||||
BUN_VERSION: 1.1.44
|
||||
BUN_VERSION: 1.1.13
|
||||
|
||||
on:
|
||||
issues:
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
# - name: Setup Bun
|
||||
# uses: ./.github/actions/setup-bun
|
||||
# with:
|
||||
# bun-version: ${{ env.BUN_VERSION }}
|
||||
# bun-version: "1.1.24"
|
||||
# - name: "categorize bug"
|
||||
# id: add-labels
|
||||
# env:
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: ${{ env.BUN_VERSION }}
|
||||
bun-version: "1.1.13"
|
||||
- name: "add platform and command label"
|
||||
id: add-labels
|
||||
if: github.event.label.name == 'crash'
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
echo "labels=$LABELS" >> $GITHUB_OUTPUT
|
||||
bun scripts/is-outdated.ts
|
||||
|
||||
if [[ -f "is-outdated.txt" ]]; then
|
||||
if [[ -f "is-outdated.txt" ]]; then
|
||||
echo "is-outdated=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
@@ -154,7 +154,7 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Thank you for reporting this crash.
|
||||
Thank you for reporting this crash.
|
||||
|
||||
For Bun's internal tracking, this issue is [${{ steps.generate-comment-text.outputs.sentry-id }}](${{ steps.generate-comment-text.outputs.sentry-link }}).
|
||||
|
||||
|
||||
22
.github/workflows/lint.yml
vendored
22
.github/workflows/lint.yml
vendored
@@ -1,22 +0,0 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
OXLINT_VERSION: "0.15.0"
|
||||
|
||||
jobs:
|
||||
lint-js:
|
||||
name: "Lint JavaScript"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: ${{ env.BUN_VERSION }}
|
||||
- name: Lint
|
||||
run: bunx oxlint --config oxlint.json --quiet --format github
|
||||
2
.github/workflows/prettier-format.yml
vendored
2
.github/workflows/prettier-format.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
merge_group:
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
BUN_VERSION: "1.1.27"
|
||||
|
||||
jobs:
|
||||
prettier-format:
|
||||
|
||||
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@@ -66,7 +66,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.44"
|
||||
bun-version: "1.1.20"
|
||||
- name: Install Dependencies
|
||||
run: bun install
|
||||
- name: Sign Release
|
||||
@@ -94,7 +94,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.44"
|
||||
bun-version: "1.1.20"
|
||||
- name: Install Dependencies
|
||||
run: bun install
|
||||
- name: Release
|
||||
@@ -123,7 +123,7 @@ jobs:
|
||||
if: ${{ env.BUN_VERSION != 'canary' }}
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.44"
|
||||
bun-version: "1.1.20"
|
||||
- name: Setup Bun
|
||||
if: ${{ env.BUN_VERSION == 'canary' }}
|
||||
uses: ./.github/actions/setup-bun
|
||||
@@ -265,7 +265,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: "1.1.44"
|
||||
bun-version: "1.1.20"
|
||||
- name: Install Dependencies
|
||||
run: bun install
|
||||
- name: Release
|
||||
@@ -309,7 +309,7 @@ jobs:
|
||||
uses: ./.github/actions/setup-bun
|
||||
if: ${{ env.BUN_LATEST == 'true' }}
|
||||
with:
|
||||
bun-version: "1.1.44"
|
||||
bun-version: "1.1.12"
|
||||
- name: Bump version
|
||||
uses: ./.github/actions/bump
|
||||
if: ${{ env.BUN_LATEST == 'true' }}
|
||||
|
||||
3
.github/workflows/run-lint.yml
vendored
3
.github/workflows/run-lint.yml
vendored
@@ -4,7 +4,6 @@ permissions:
|
||||
contents: read
|
||||
env:
|
||||
LLVM_VERSION: 16
|
||||
BUN_VERSION: "1.1.44"
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
@@ -23,7 +22,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: ${{ env.BUN_VERSION }}
|
||||
bun-version: "1.1.3"
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
bun --cwd=packages/bun-internal-test install
|
||||
|
||||
5
.github/workflows/test-bump.yml
vendored
5
.github/workflows/test-bump.yml
vendored
@@ -8,9 +8,6 @@ on:
|
||||
description: What is the release tag? (e.g. "1.0.2", "canary")
|
||||
required: true
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
|
||||
jobs:
|
||||
bump:
|
||||
name: "Bump version"
|
||||
@@ -24,7 +21,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup-bun
|
||||
with:
|
||||
bun-version: ${{ env.BUN_VERSION }}
|
||||
bun-version: "1.1.12"
|
||||
- name: Bump version
|
||||
uses: ./.github/actions/bump
|
||||
with:
|
||||
|
||||
19
.github/workflows/typos.yml
vendored
19
.github/workflows/typos.yml
vendored
@@ -1,19 +0,0 @@
|
||||
name: Typos
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Spellcheck
|
||||
uses: crate-ci/typos@v1.29.4
|
||||
with:
|
||||
files: docs/**/*
|
||||
2
.github/workflows/zig-format.yml
vendored
2
.github/workflows/zig-format.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
merge_group:
|
||||
|
||||
env:
|
||||
BUN_VERSION: "1.1.44"
|
||||
BUN_VERSION: "1.1.27"
|
||||
|
||||
jobs:
|
||||
zig-format:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# command script import vendor/zig/tools/lldb_pretty_printers.py
|
||||
command script import vendor/zig/tools/lldb_pretty_printers.py
|
||||
command script import vendor/WebKit/Tools/lldb/lldb_webkit.py
|
||||
|
||||
# type summary add --summary-string "${var} | inner=${var[0-30]}, source=${var[33-64]}, tag=${var[31-32]}" "unsigned long"
|
||||
|
||||
2
.mailmap
2
.mailmap
@@ -1,2 +0,0 @@
|
||||
# To learn more about git's mailmap: https://ntietz.com/blog/git-mailmap-for-name-changes
|
||||
chloe caruso <git@paperclover.net> <me@paperdave.net>
|
||||
@@ -1,2 +0,0 @@
|
||||
[type.md]
|
||||
extend-ignore-words-re = ["^ba"]
|
||||
18
.vscode/launch.json
generated
vendored
18
.vscode/launch.json
generated
vendored
@@ -160,7 +160,7 @@
|
||||
"request": "launch",
|
||||
"name": "bun run [file]",
|
||||
"program": "${workspaceFolder}/build/debug/bun-debug",
|
||||
"args": ["${file}"],
|
||||
"args": ["run", "${fileBasename}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"FORCE_COLOR": "0",
|
||||
@@ -176,7 +176,7 @@
|
||||
"request": "launch",
|
||||
"name": "bun run [file] (fast)",
|
||||
"program": "${workspaceFolder}/build/debug/bun-debug",
|
||||
"args": ["run", "${file}"],
|
||||
"args": ["run", "${fileBasename}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"BUN_DEBUG_QUIET_LOGS": "1",
|
||||
@@ -195,7 +195,7 @@
|
||||
"request": "launch",
|
||||
"name": "bun run [file] (verbose)",
|
||||
"program": "${workspaceFolder}/build/debug/bun-debug",
|
||||
"args": ["run", "${file}"],
|
||||
"args": ["run", "${fileBasename}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"BUN_DEBUG_QUIET_LOGS": "0",
|
||||
@@ -210,7 +210,7 @@
|
||||
"request": "launch",
|
||||
"name": "bun run [file] --watch",
|
||||
"program": "${workspaceFolder}/build/debug/bun-debug",
|
||||
"args": ["run", "--watch", "${file}"],
|
||||
"args": ["run", "--watch", "${fileBasename}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
// "BUN_DEBUG_DEBUGGER": "1",
|
||||
@@ -228,7 +228,7 @@
|
||||
"request": "launch",
|
||||
"name": "bun run [file] --hot",
|
||||
"program": "${workspaceFolder}/build/debug/bun-debug",
|
||||
"args": ["run", "--hot", "${file}"],
|
||||
"args": ["run", "--hot", "${fileBasename}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"BUN_DEBUG_QUIET_LOGS": "1",
|
||||
@@ -243,7 +243,7 @@
|
||||
"request": "launch",
|
||||
"name": "bun run [file] --inspect",
|
||||
"program": "${workspaceFolder}/build/debug/bun-debug",
|
||||
"args": ["run", "${file}"],
|
||||
"args": ["run", "${fileBasename}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"FORCE_COLOR": "0",
|
||||
@@ -265,7 +265,7 @@
|
||||
"request": "launch",
|
||||
"name": "bun run [file] --inspect-brk",
|
||||
"program": "${workspaceFolder}/build/debug/bun-debug",
|
||||
"args": ["run", "${file}"],
|
||||
"args": ["run", "${fileBasename}"],
|
||||
"cwd": "${fileDirname}",
|
||||
"env": {
|
||||
"FORCE_COLOR": "0",
|
||||
@@ -736,10 +736,6 @@
|
||||
"name": "BUN_DEBUG_QUIET_LOGS",
|
||||
"value": "1",
|
||||
},
|
||||
{
|
||||
"name": "BUN_DEBUG_SYS",
|
||||
"value": "1",
|
||||
},
|
||||
{
|
||||
"name": "BUN_GARBAGE_COLLECTOR_LEVEL",
|
||||
"value": "2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Configuring a development environment for Bun can take 10-30 minutes depending on your internet connection and computer speed. You will need ~10GB of free disk space for the repository and build artifacts.
|
||||
|
||||
If you are using Windows, please refer to [this guide](https://bun.sh/docs/project/building-windows)
|
||||
If you are using Windows, please refer to [this guide](/docs/project/building-windows.md)
|
||||
|
||||
## Install Dependencies
|
||||
|
||||
@@ -63,7 +63,7 @@ $ brew install llvm@18
|
||||
|
||||
```bash#Ubuntu/Debian
|
||||
$ # LLVM has an automatic installation script that is compatible with all versions of Ubuntu
|
||||
$ wget https://apt.llvm.org/llvm.sh -O - | sudo bash -s -- 18 all
|
||||
$ wget https://apt.llvm.org/llvm.sh -O - | sudo bash -s -- 16 all
|
||||
```
|
||||
|
||||
```bash#Arch
|
||||
@@ -71,21 +71,23 @@ $ sudo pacman -S llvm clang lld
|
||||
```
|
||||
|
||||
```bash#Fedora
|
||||
$ sudo dnf install llvm18 clang18 lld18-devel
|
||||
$ sudo dnf install 'dnf-command(copr)'
|
||||
$ sudo dnf copr enable -y @fedora-llvm-team/llvm17
|
||||
$ sudo dnf install llvm16 clang16 lld16-devel
|
||||
```
|
||||
|
||||
```bash#openSUSE Tumbleweed
|
||||
$ sudo zypper install clang18 lld18 llvm18
|
||||
$ sudo zypper install clang16 lld16 llvm16
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
If none of the above solutions apply, you will have to install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-18.1.8).
|
||||
If none of the above solutions apply, you will have to install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-16.0.6).
|
||||
|
||||
Make sure Clang/LLVM 18 is in your path:
|
||||
|
||||
```bash
|
||||
$ which clang-18
|
||||
$ which clang-16
|
||||
```
|
||||
|
||||
If not, run this to manually add it:
|
||||
@@ -94,13 +96,13 @@ If not, run this to manually add it:
|
||||
|
||||
```bash#macOS (Homebrew)
|
||||
# use fish_add_path if you're using fish
|
||||
# use path+="$(brew --prefix llvm@18)/bin" if you are using zsh
|
||||
$ export PATH="$(brew --prefix llvm@18)/bin:$PATH"
|
||||
# use path+="$(brew --prefix llvm@16)/bin" if you are using zsh
|
||||
$ export PATH="$(brew --prefix llvm@16)/bin:$PATH"
|
||||
```
|
||||
|
||||
```bash#Arch
|
||||
# use fish_add_path if you're using fish
|
||||
$ export PATH="$PATH:/usr/lib/llvm18/bin"
|
||||
$ export PATH="$PATH:/usr/lib/llvm16/bin"
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
@@ -161,7 +163,7 @@ The binary will be located at `./build/release/bun` and `./build/release/bun-pro
|
||||
|
||||
### Download release build from pull requests
|
||||
|
||||
To save you time spent building a release build locally, we provide a way to run release builds from pull requests. This is useful for manually testing changes in a release build before they are merged.
|
||||
To save you time spent building a release build locally, we provide a way to run release builds from pull requests. This is useful for manully testing changes in a release build before they are merged.
|
||||
|
||||
To run a release build from a pull request, you can use the `bun-pr` npm package:
|
||||
|
||||
@@ -238,7 +240,7 @@ The issue may manifest when initially running `bun setup` as Clang being unable
|
||||
```
|
||||
The C++ compiler
|
||||
|
||||
"/usr/bin/clang++-18"
|
||||
"/usr/bin/clang++-16"
|
||||
|
||||
is not able to compile a simple test program.
|
||||
```
|
||||
|
||||
27
Makefile
27
Makefile
@@ -91,9 +91,9 @@ ZIG ?= $(shell which zig 2>/dev/null || echo -e "error: Missing zig. Please make
|
||||
# This is easier to happen than you'd expect.
|
||||
# Using realpath here causes issues because clang uses clang++ as a symlink
|
||||
# so if that's resolved, it won't build for C++
|
||||
REAL_CC = $(shell which clang-18 2>/dev/null || which clang 2>/dev/null)
|
||||
REAL_CXX = $(shell which clang++-18 2>/dev/null || which clang++ 2>/dev/null)
|
||||
CLANG_FORMAT = $(shell which clang-format-18 2>/dev/null || which clang-format 2>/dev/null)
|
||||
REAL_CC = $(shell which clang-16 2>/dev/null || which clang 2>/dev/null)
|
||||
REAL_CXX = $(shell which clang++-16 2>/dev/null || which clang++ 2>/dev/null)
|
||||
CLANG_FORMAT = $(shell which clang-format-16 2>/dev/null || which clang-format 2>/dev/null)
|
||||
|
||||
CC = $(REAL_CC)
|
||||
CXX = $(REAL_CXX)
|
||||
@@ -117,14 +117,14 @@ CC_WITH_CCACHE = $(CCACHE_PATH) $(CC)
|
||||
ifeq ($(OS_NAME),darwin)
|
||||
# Find LLVM
|
||||
ifeq ($(wildcard $(LLVM_PREFIX)),)
|
||||
LLVM_PREFIX = $(shell brew --prefix llvm@18)
|
||||
LLVM_PREFIX = $(shell brew --prefix llvm@16)
|
||||
endif
|
||||
ifeq ($(wildcard $(LLVM_PREFIX)),)
|
||||
LLVM_PREFIX = $(shell brew --prefix llvm)
|
||||
endif
|
||||
ifeq ($(wildcard $(LLVM_PREFIX)),)
|
||||
# This is kinda ugly, but I can't find a better way to error :(
|
||||
LLVM_PREFIX = $(shell echo -e "error: Unable to find llvm. Please run 'brew install llvm@18' or set LLVM_PREFIX=/path/to/llvm")
|
||||
LLVM_PREFIX = $(shell echo -e "error: Unable to find llvm. Please run 'brew install llvm@16' or set LLVM_PREFIX=/path/to/llvm")
|
||||
endif
|
||||
|
||||
LDFLAGS += -L$(LLVM_PREFIX)/lib
|
||||
@@ -164,7 +164,7 @@ CMAKE_FLAGS_WITHOUT_RELEASE = -DCMAKE_C_COMPILER=$(CC) \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=$(MIN_MACOS_VERSION) \
|
||||
$(CMAKE_CXX_COMPILER_LAUNCHER_FLAG) \
|
||||
-DCMAKE_AR=$(AR) \
|
||||
-DCMAKE_RANLIB=$(which llvm-18-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) \
|
||||
-DCMAKE_RANLIB=$(which llvm-16-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) \
|
||||
-DCMAKE_CXX_STANDARD=20 \
|
||||
-DCMAKE_C_STANDARD=17 \
|
||||
-DCMAKE_CXX_STANDARD_REQUIRED=ON \
|
||||
@@ -191,7 +191,7 @@ endif
|
||||
|
||||
ifeq ($(OS_NAME),linux)
|
||||
LIBICONV_PATH =
|
||||
AR = $(shell which llvm-ar-18 2>/dev/null || which llvm-ar 2>/dev/null || which ar 2>/dev/null)
|
||||
AR = $(shell which llvm-ar-16 2>/dev/null || which llvm-ar 2>/dev/null || which ar 2>/dev/null)
|
||||
endif
|
||||
|
||||
OPTIMIZATION_LEVEL=-O3 $(MARCH_NATIVE)
|
||||
@@ -286,7 +286,7 @@ STRIP=/usr/bin/strip
|
||||
endif
|
||||
|
||||
ifeq ($(OS_NAME),linux)
|
||||
STRIP=$(shell which llvm-strip 2>/dev/null || which llvm-strip-18 2>/dev/null || which strip 2>/dev/null || echo "Missing strip")
|
||||
STRIP=$(shell which llvm-strip 2>/dev/null || which llvm-strip-16 2>/dev/null || which strip 2>/dev/null || echo "Missing strip")
|
||||
endif
|
||||
|
||||
|
||||
@@ -674,7 +674,7 @@ endif
|
||||
.PHONY: assert-deps
|
||||
assert-deps:
|
||||
@echo "Checking if the required utilities are available..."
|
||||
@if [ $(CLANG_VERSION) -lt "18" ]; then echo -e "ERROR: clang version >=18 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@18"; exit 1; fi
|
||||
@if [ $(CLANG_VERSION) -lt "15" ]; then echo -e "ERROR: clang version >=15 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@16"; exit 1; fi
|
||||
@cmake --version >/dev/null 2>&1 || (echo -e "ERROR: cmake is required."; exit 1)
|
||||
@$(PYTHON) --version >/dev/null 2>&1 || (echo -e "ERROR: python is required."; exit 1)
|
||||
@$(ESBUILD) --version >/dev/null 2>&1 || (echo -e "ERROR: esbuild is required."; exit 1)
|
||||
@@ -1261,7 +1261,6 @@ jsc-build-mac-compile:
|
||||
-DBUN_FAST_TLS=ON \
|
||||
-DENABLE_FTL_JIT=ON \
|
||||
-DUSE_BUN_JSC_ADDITIONS=ON \
|
||||
-DUSE_BUN_EVENT_LOOP=ON \
|
||||
-G Ninja \
|
||||
$(CMAKE_FLAGS_WITHOUT_RELEASE) \
|
||||
-DPTHREAD_JIT_PERMISSIONS_API=1 \
|
||||
@@ -1285,7 +1284,6 @@ jsc-build-mac-compile-lto:
|
||||
-DUSE_THIN_ARCHIVES=OFF \
|
||||
-DBUN_FAST_TLS=ON \
|
||||
-DUSE_BUN_JSC_ADDITIONS=ON \
|
||||
-DUSE_BUN_EVENT_LOOP=ON \
|
||||
-DCMAKE_C_FLAGS="-flto=full" \
|
||||
-DCMAKE_CXX_FLAGS="-flto=full" \
|
||||
-DENABLE_FTL_JIT=ON \
|
||||
@@ -1312,7 +1310,6 @@ jsc-build-mac-compile-debug:
|
||||
-DENABLE_MALLOC_HEAP_BREAKDOWN=ON \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-DUSE_BUN_JSC_ADDITIONS=ON \
|
||||
-DUSE_BUN_EVENT_LOOP=ON \
|
||||
-DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \
|
||||
-DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \
|
||||
-G Ninja \
|
||||
@@ -1337,7 +1334,6 @@ jsc-build-linux-compile-config:
|
||||
-DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \
|
||||
-DUSE_THIN_ARCHIVES=OFF \
|
||||
-DUSE_BUN_JSC_ADDITIONS=ON \
|
||||
-DUSE_BUN_EVENT_LOOP=ON \
|
||||
-DENABLE_FTL_JIT=ON \
|
||||
-DENABLE_REMOTE_INSPECTOR=ON \
|
||||
-DJSEXPORT_PRIVATE=WTF_EXPORT_DECLARATION \
|
||||
@@ -1361,7 +1357,6 @@ jsc-build-linux-compile-config-debug:
|
||||
-DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \
|
||||
-DUSE_THIN_ARCHIVES=OFF \
|
||||
-DUSE_BUN_JSC_ADDITIONS=ON \
|
||||
-DUSE_BUN_EVENT_LOOP=ON \
|
||||
-DENABLE_FTL_JIT=ON \
|
||||
-DENABLE_REMOTE_INSPECTOR=ON \
|
||||
-DJSEXPORT_PRIVATE=WTF_EXPORT_DECLARATION \
|
||||
@@ -1380,14 +1375,14 @@ jsc-build-linux-compile-config-debug:
|
||||
jsc-build-linux-compile-build:
|
||||
mkdir -p $(WEBKIT_RELEASE_DIR) && \
|
||||
cd $(WEBKIT_RELEASE_DIR) && \
|
||||
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON -DUSE_BUN_EVENT_LOOP=ON" \
|
||||
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON" \
|
||||
cmake --build $(WEBKIT_RELEASE_DIR) --config relwithdebuginfo --target jsc
|
||||
|
||||
.PHONY: jsc-build-linux-compile-build-debug
|
||||
jsc-build-linux-compile-build-debug:
|
||||
mkdir -p $(WEBKIT_DEBUG_DIR) && \
|
||||
cd $(WEBKIT_DEBUG_DIR) && \
|
||||
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON -DUSE_BUN_EVENT_LOOP=ON" \
|
||||
CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON" \
|
||||
cmake --build $(WEBKIT_DEBUG_DIR) --config Debug --target jsc
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
Bun is an all-in-one toolkit for JavaScript and TypeScript apps. It ships as a single executable called `bun`.
|
||||
|
||||
At its core is the _Bun runtime_, a fast JavaScript runtime designed as **a drop-in replacement for Node.js**. It's written in Zig and powered by JavaScriptCore under the hood, dramatically reducing startup times and memory usage.
|
||||
At its core is the _Bun runtime_, a fast JavaScript runtime designed as a drop-in replacement for Node.js. It's written in Zig and powered by JavaScriptCore under the hood, dramatically reducing startup times and memory usage.
|
||||
|
||||
```bash
|
||||
bun run index.tsx # TS and JSX supported out-of-the-box
|
||||
|
||||
416
bench/bun.lock
416
bench/bun.lock
@@ -1,416 +0,0 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bench",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.16.10",
|
||||
"@babel/preset-react": "^7.16.7",
|
||||
"@babel/standalone": "^7.24.7",
|
||||
"@swc/core": "^1.2.133",
|
||||
"benchmark": "^2.1.4",
|
||||
"braces": "^3.0.2",
|
||||
"color": "^4.2.3",
|
||||
"esbuild": "^0.14.12",
|
||||
"eventemitter3": "^5.0.0",
|
||||
"execa": "^8.0.1",
|
||||
"fast-glob": "3.3.1",
|
||||
"fdir": "^6.1.0",
|
||||
"mitata": "^1.0.25",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"string-width": "7.1.0",
|
||||
"tinycolor2": "^1.6.0",
|
||||
"zx": "^7.2.3",
|
||||
},
|
||||
"devDependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@ampproject/remapping": ["@ampproject/remapping@2.2.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" } }, "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w=="],
|
||||
|
||||
"@babel/code-frame": ["@babel/code-frame@7.18.6", "", { "dependencies": { "@babel/highlight": "^7.18.6" } }, "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q=="],
|
||||
|
||||
"@babel/compat-data": ["@babel/compat-data@7.20.14", "", {}, "sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw=="],
|
||||
|
||||
"@babel/core": ["@babel/core@7.20.12", "", { "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.20.7", "@babel/helper-compilation-targets": "^7.20.7", "@babel/helper-module-transforms": "^7.20.11", "@babel/helpers": "^7.20.7", "@babel/parser": "^7.20.7", "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.12", "@babel/types": "^7.20.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.2", "semver": "^6.3.0" } }, "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg=="],
|
||||
|
||||
"@babel/generator": ["@babel/generator@7.20.14", "", { "dependencies": { "@babel/types": "^7.20.7", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" } }, "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg=="],
|
||||
|
||||
"@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA=="],
|
||||
|
||||
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.20.7", "", { "dependencies": { "@babel/compat-data": "^7.20.5", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ=="],
|
||||
|
||||
"@babel/helper-environment-visitor": ["@babel/helper-environment-visitor@7.18.9", "", {}, "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg=="],
|
||||
|
||||
"@babel/helper-function-name": ["@babel/helper-function-name@7.19.0", "", { "dependencies": { "@babel/template": "^7.18.10", "@babel/types": "^7.19.0" } }, "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w=="],
|
||||
|
||||
"@babel/helper-hoist-variables": ["@babel/helper-hoist-variables@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q=="],
|
||||
|
||||
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="],
|
||||
|
||||
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.20.11", "", { "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.10", "@babel/types": "^7.20.7" } }, "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg=="],
|
||||
|
||||
"@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.20.2", "", {}, "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ=="],
|
||||
|
||||
"@babel/helper-simple-access": ["@babel/helper-simple-access@7.20.2", "", { "dependencies": { "@babel/types": "^7.20.2" } }, "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA=="],
|
||||
|
||||
"@babel/helper-split-export-declaration": ["@babel/helper-split-export-declaration@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA=="],
|
||||
|
||||
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.19.4", "", {}, "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw=="],
|
||||
|
||||
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.19.1", "", {}, "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w=="],
|
||||
|
||||
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.18.6", "", {}, "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw=="],
|
||||
|
||||
"@babel/helpers": ["@babel/helpers@7.20.13", "", { "dependencies": { "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.13", "@babel/types": "^7.20.7" } }, "sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg=="],
|
||||
|
||||
"@babel/highlight": ["@babel/highlight@7.18.6", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g=="],
|
||||
|
||||
"@babel/parser": ["@babel/parser@7.20.15", "", { "bin": "./bin/babel-parser.js" }, "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg=="],
|
||||
|
||||
"@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.18.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q=="],
|
||||
|
||||
"@babel/plugin-transform-react-display-name": ["@babel/plugin-transform-react-display-name@7.18.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA=="],
|
||||
|
||||
"@babel/plugin-transform-react-jsx": ["@babel/plugin-transform-react-jsx@7.20.13", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-MmTZx/bkUrfJhhYAYt3Urjm+h8DQGrPrnKQ94jLo7NLuOU+T89a7IByhKmrb8SKhrIYIQ0FN0CHMbnFRen4qNw=="],
|
||||
|
||||
"@babel/plugin-transform-react-jsx-development": ["@babel/plugin-transform-react-jsx-development@7.18.6", "", { "dependencies": { "@babel/plugin-transform-react-jsx": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA=="],
|
||||
|
||||
"@babel/plugin-transform-react-pure-annotations": ["@babel/plugin-transform-react-pure-annotations@7.18.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ=="],
|
||||
|
||||
"@babel/preset-react": ["@babel/preset-react@7.18.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/helper-validator-option": "^7.18.6", "@babel/plugin-transform-react-display-name": "^7.18.6", "@babel/plugin-transform-react-jsx": "^7.18.6", "@babel/plugin-transform-react-jsx-development": "^7.18.6", "@babel/plugin-transform-react-pure-annotations": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg=="],
|
||||
|
||||
"@babel/standalone": ["@babel/standalone@7.24.7", "", {}, "sha512-QRIRMJ2KTeN+vt4l9OjYlxDVXEpcor1Z6V7OeYzeBOw6Q8ew9oMTHjzTx8s6ClsZO7wVf6JgTRutihatN6K0yA=="],
|
||||
|
||||
"@babel/template": ["@babel/template@7.20.7", "", { "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7" } }, "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw=="],
|
||||
|
||||
"@babel/traverse": ["@babel/traverse@7.20.13", "", { "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/parser": "^7.20.13", "@babel/types": "^7.20.7", "debug": "^4.1.0", "globals": "^11.1.0" } }, "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ=="],
|
||||
|
||||
"@babel/types": ["@babel/types@7.20.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" } }, "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.14.54", "", { "os": "linux", "cpu": "none" }, "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.1.1", "", { "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w=="],
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.0", "", {}, "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="],
|
||||
|
||||
"@jridgewell/set-array": ["@jridgewell/set-array@1.1.2", "", {}, "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.4.14", "", {}, "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="],
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.17", "", { "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" } }, "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g=="],
|
||||
|
||||
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||
|
||||
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
|
||||
|
||||
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
||||
|
||||
"@swc/core": ["@swc/core@1.3.35", "", { "dependencies": { "@swc/core-darwin-arm64": "1.3.35", "@swc/core-darwin-x64": "1.3.35", "@swc/core-linux-arm-gnueabihf": "1.3.35", "@swc/core-linux-arm64-gnu": "1.3.35", "@swc/core-linux-arm64-musl": "1.3.35", "@swc/core-linux-x64-gnu": "1.3.35", "@swc/core-linux-x64-musl": "1.3.35", "@swc/core-win32-arm64-msvc": "1.3.35", "@swc/core-win32-ia32-msvc": "1.3.35", "@swc/core-win32-x64-msvc": "1.3.35" } }, "sha512-KmiBin0XSVzJhzX19zTiCqmLslZ40Cl7zqskJcTDeIrRhfgKdiAsxzYUanJgMJIRjYtl9Kcg1V/Ip2o2wL8v3w=="],
|
||||
|
||||
"@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.3.35", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zQUFkHx4gZpu0uo2IspvPnKsz8bsdXd5bC33xwjtoAI1cpLerDyqo4v2zIahEp+FdKZjyVsLHtfJiQiA1Qka3A=="],
|
||||
|
||||
"@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.3.35", "", { "os": "darwin", "cpu": "x64" }, "sha512-oOSkSGWtALovaw22lNevKD434OQTPf8X+dVPvPMrJXJpJ34dWDlFWpLntoc+arvKLNZ7LQmTuk8rR1hkrAY7cw=="],
|
||||
|
||||
"@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.3.35", "", { "os": "linux", "cpu": "arm" }, "sha512-Yie8k00O6O8BCATS/xeKStquV4OYSskUGRDXBQVDw1FrE23PHaSeHCgg4q6iNZjJzXCOJbaTCKnYoIDn9DMf7A=="],
|
||||
|
||||
"@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.3.35", "", { "os": "linux", "cpu": "arm64" }, "sha512-Zlv3WHa/4x2p51HSvjUWXHfSe1Gl2prqImUZJc8NZOlj75BFzVuR0auhQ+LbwvIQ3gaA1LODX9lyS9wXL3yjxA=="],
|
||||
|
||||
"@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.3.35", "", { "os": "linux", "cpu": "arm64" }, "sha512-u6tCYsrSyZ8U+4jLMA/O82veBfLy2aUpn51WxQaeH7wqZGy9TGSJXoO8vWxARQ6b72vjsnKDJHP4MD8hFwcctg=="],
|
||||
|
||||
"@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.3.35", "", { "os": "linux", "cpu": "x64" }, "sha512-Dtxf2IbeH7XlNhP1Qt2/MvUPkpEbn7hhGfpSRs4ot8D3Vf5QEX4S/QtC1OsFWuciiYgHAT1Ybjt4xZic9DSkmA=="],
|
||||
|
||||
"@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.3.35", "", { "os": "linux", "cpu": "x64" }, "sha512-4XavNJ60GprjpTiESCu5daJUnmErixPAqDitJSMu4TV32LNIE8G00S9pDLXinDTW1rgcGtQdq1NLkNRmwwovtg=="],
|
||||
|
||||
"@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.3.35", "", { "os": "win32", "cpu": "arm64" }, "sha512-dNGfKCUSX2M4qVyaS80Lyos0FkXyHRCvrdQ2Y4Hrg3FVokiuw3yY6fLohpUfQ5ws3n2A39dh7jGDeh34+l0sGA=="],
|
||||
|
||||
"@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.3.35", "", { "os": "win32", "cpu": "ia32" }, "sha512-ChuPSrDR+JBf7S7dEKPicnG8A3bM0uWPsW2vG+V2wH4iNfNxKVemESHosmYVeEZXqMpomNMvLyeHep1rjRsc0Q=="],
|
||||
|
||||
"@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.3.35", "", { "os": "win32", "cpu": "x64" }, "sha512-/RvphT4WfuGfIK84Ha0dovdPrKB1bW/mc+dtdmhv2E3EGkNc5FoueNwYmXWRimxnU7X0X7IkcRhyKB4G5DeAmg=="],
|
||||
|
||||
"@types/fs-extra": ["@types/fs-extra@11.0.4", "", { "dependencies": { "@types/jsonfile": "*", "@types/node": "*" } }, "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ=="],
|
||||
|
||||
"@types/jsonfile": ["@types/jsonfile@6.1.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ=="],
|
||||
|
||||
"@types/minimist": ["@types/minimist@1.2.5", "", {}, "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag=="],
|
||||
|
||||
"@types/node": ["@types/node@18.19.8", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-g1pZtPhsvGVTwmeVoexWZLTQaOvXwoSq//pTL0DHeNzUDrFnir4fgETdhjhIxjVnN+hKOuh98+E1eMLnUXstFg=="],
|
||||
|
||||
"@types/ps-tree": ["@types/ps-tree@1.1.6", "", {}, "sha512-PtrlVaOaI44/3pl3cvnlK+GxOM3re2526TJvPvh7W+keHIXdV4TE0ylpPBAcvFQCbGitaTXwL9u+RF7qtVeazQ=="],
|
||||
|
||||
"@types/which": ["@types/which@3.0.3", "", {}, "sha512-2C1+XoY0huExTbs8MQv1DuS5FS86+SEjdM9F/+GS61gg5Hqbtj8ZiDSx8MfWcyei907fIPbfPGCOrNUTnVHY1g=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@6.0.1", "", {}, "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
||||
|
||||
"benchmark": ["benchmark@2.1.4", "", { "dependencies": { "lodash": "^4.17.4", "platform": "^1.3.3" } }, "sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ=="],
|
||||
|
||||
"braces": ["braces@3.0.2", "", { "dependencies": { "fill-range": "^7.0.1" } }, "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A=="],
|
||||
|
||||
"browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001456", "", {}, "sha512-XFHJY5dUgmpMV25UqaD4kVq2LsiaU5rS8fb0f17pCoXQiQslzmFgnfOxfvo1bTpTqf7dwG/N/05CnLCnOEKmzA=="],
|
||||
|
||||
"chalk": ["chalk@5.3.0", "", {}, "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w=="],
|
||||
|
||||
"color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
|
||||
|
||||
"convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.3", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w=="],
|
||||
|
||||
"data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="],
|
||||
|
||||
"debug": ["debug@4.3.4", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ=="],
|
||||
|
||||
"dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="],
|
||||
|
||||
"duplexer": ["duplexer@0.1.2", "", {}, "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.4.302", "", {}, "sha512-Uk7C+7aPBryUR1Fwvk9VmipBcN9fVsqBO57jV2ZjTm+IZ6BMNqu7EDVEg2HxCNufk6QcWlFsBkhQyQroB2VWKw=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@10.3.0", "", {}, "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw=="],
|
||||
|
||||
"esbuild": ["esbuild@0.14.54", "", { "dependencies": { "@esbuild/linux-loong64": "0.14.54", "esbuild-android-64": "0.14.54", "esbuild-android-arm64": "0.14.54", "esbuild-darwin-64": "0.14.54", "esbuild-darwin-arm64": "0.14.54", "esbuild-freebsd-64": "0.14.54", "esbuild-freebsd-arm64": "0.14.54", "esbuild-linux-32": "0.14.54", "esbuild-linux-64": "0.14.54", "esbuild-linux-arm": "0.14.54", "esbuild-linux-arm64": "0.14.54", "esbuild-linux-mips64le": "0.14.54", "esbuild-linux-ppc64le": "0.14.54", "esbuild-linux-riscv64": "0.14.54", "esbuild-linux-s390x": "0.14.54", "esbuild-netbsd-64": "0.14.54", "esbuild-openbsd-64": "0.14.54", "esbuild-sunos-64": "0.14.54", "esbuild-windows-32": "0.14.54", "esbuild-windows-64": "0.14.54", "esbuild-windows-arm64": "0.14.54" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA=="],
|
||||
|
||||
"esbuild-android-64": ["esbuild-android-64@0.14.54", "", { "os": "android", "cpu": "x64" }, "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ=="],
|
||||
|
||||
"esbuild-android-arm64": ["esbuild-android-arm64@0.14.54", "", { "os": "android", "cpu": "arm64" }, "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg=="],
|
||||
|
||||
"esbuild-darwin-64": ["esbuild-darwin-64@0.14.54", "", { "os": "darwin", "cpu": "x64" }, "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug=="],
|
||||
|
||||
"esbuild-darwin-arm64": ["esbuild-darwin-arm64@0.14.54", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw=="],
|
||||
|
||||
"esbuild-freebsd-64": ["esbuild-freebsd-64@0.14.54", "", { "os": "freebsd", "cpu": "x64" }, "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg=="],
|
||||
|
||||
"esbuild-freebsd-arm64": ["esbuild-freebsd-arm64@0.14.54", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q=="],
|
||||
|
||||
"esbuild-linux-32": ["esbuild-linux-32@0.14.54", "", { "os": "linux", "cpu": "ia32" }, "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw=="],
|
||||
|
||||
"esbuild-linux-64": ["esbuild-linux-64@0.14.54", "", { "os": "linux", "cpu": "x64" }, "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg=="],
|
||||
|
||||
"esbuild-linux-arm": ["esbuild-linux-arm@0.14.54", "", { "os": "linux", "cpu": "arm" }, "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw=="],
|
||||
|
||||
"esbuild-linux-arm64": ["esbuild-linux-arm64@0.14.54", "", { "os": "linux", "cpu": "arm64" }, "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig=="],
|
||||
|
||||
"esbuild-linux-mips64le": ["esbuild-linux-mips64le@0.14.54", "", { "os": "linux", "cpu": "none" }, "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw=="],
|
||||
|
||||
"esbuild-linux-ppc64le": ["esbuild-linux-ppc64le@0.14.54", "", { "os": "linux", "cpu": "ppc64" }, "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ=="],
|
||||
|
||||
"esbuild-linux-riscv64": ["esbuild-linux-riscv64@0.14.54", "", { "os": "linux", "cpu": "none" }, "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg=="],
|
||||
|
||||
"esbuild-linux-s390x": ["esbuild-linux-s390x@0.14.54", "", { "os": "linux", "cpu": "s390x" }, "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA=="],
|
||||
|
||||
"esbuild-netbsd-64": ["esbuild-netbsd-64@0.14.54", "", { "os": "none", "cpu": "x64" }, "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w=="],
|
||||
|
||||
"esbuild-openbsd-64": ["esbuild-openbsd-64@0.14.54", "", { "os": "openbsd", "cpu": "x64" }, "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw=="],
|
||||
|
||||
"esbuild-sunos-64": ["esbuild-sunos-64@0.14.54", "", { "os": "sunos", "cpu": "x64" }, "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw=="],
|
||||
|
||||
"esbuild-windows-32": ["esbuild-windows-32@0.14.54", "", { "os": "win32", "cpu": "ia32" }, "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w=="],
|
||||
|
||||
"esbuild-windows-64": ["esbuild-windows-64@0.14.54", "", { "os": "win32", "cpu": "x64" }, "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ=="],
|
||||
|
||||
"esbuild-windows-arm64": ["esbuild-windows-arm64@0.14.54", "", { "os": "win32", "cpu": "arm64" }, "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg=="],
|
||||
|
||||
"escalade": ["escalade@3.1.1", "", {}, "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="],
|
||||
|
||||
"escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
||||
|
||||
"event-stream": ["event-stream@3.3.4", "", { "dependencies": { "duplexer": "~0.1.1", "from": "~0", "map-stream": "~0.1.0", "pause-stream": "0.0.11", "split": "0.3", "stream-combiner": "~0.0.4", "through": "~2.3.1" } }, "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g=="],
|
||||
|
||||
"eventemitter3": ["eventemitter3@5.0.0", "", {}, "sha512-riuVbElZZNXLeLEoprfNYoDSwTBRR44X3mnhdI1YcnENpWTCsTTVZ2zFuqQcpoyqPQIUXdiPEU0ECAq0KQRaHg=="],
|
||||
|
||||
"execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
||||
|
||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||
|
||||
"fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="],
|
||||
|
||||
"fastq": ["fastq@1.15.0", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw=="],
|
||||
|
||||
"fdir": ["fdir@6.1.0", "", { "peerDependencies": { "picomatch": "2.x" } }, "sha512-274qhz5PxNnA/fybOu6apTCUnM0GnO3QazB6VH+oag/7DQskdYq8lm07ZSm90kEQuWYH5GvjAxGruuHrEr0bcg=="],
|
||||
|
||||
"fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
|
||||
|
||||
"fill-range": ["fill-range@7.0.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ=="],
|
||||
|
||||
"formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],
|
||||
|
||||
"from": ["from@0.1.7", "", {}, "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g=="],
|
||||
|
||||
"fs-extra": ["fs-extra@11.2.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw=="],
|
||||
|
||||
"fx": ["fx@31.0.0", "", { "bin": { "fx": "index.js" } }, "sha512-OoeYSPKqNKmfnH4s+rGYI0c8OZmqqOOXsUtqy0YyHqQQoQSDiDs3m3M9uXKx5OQR+jDx7/FhYqpO3kl/As/xgg=="],
|
||||
|
||||
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
|
||||
|
||||
"get-east-asian-width": ["get-east-asian-width@1.2.0", "", {}, "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA=="],
|
||||
|
||||
"get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="],
|
||||
|
||||
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
|
||||
|
||||
"globby": ["globby@13.2.2", "", { "dependencies": { "dir-glob": "^3.0.1", "fast-glob": "^3.3.0", "ignore": "^5.2.4", "merge2": "^1.4.1", "slash": "^4.0.0" } }, "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
||||
"has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||
|
||||
"human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
|
||||
|
||||
"ignore": ["ignore@5.3.0", "", {}, "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg=="],
|
||||
|
||||
"is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
|
||||
|
||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||
|
||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"jsesc": ["jsesc@2.5.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="],
|
||||
|
||||
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
||||
|
||||
"jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="],
|
||||
|
||||
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||
|
||||
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
|
||||
|
||||
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
||||
|
||||
"map-stream": ["map-stream@0.1.0", "", {}, "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g=="],
|
||||
|
||||
"merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
|
||||
|
||||
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
||||
|
||||
"micromatch": ["micromatch@4.0.5", "", { "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" } }, "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA=="],
|
||||
|
||||
"mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
|
||||
|
||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
|
||||
"mitata": ["mitata@1.0.25", "", {}, "sha512-0v5qZtVW5vwj9FDvYfraR31BMDcRLkhSFWPTLaxx/Z3/EvScfVtAAWtMI2ArIbBcwh7P86dXh0lQWKiXQPlwYA=="],
|
||||
|
||||
"ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="],
|
||||
|
||||
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
|
||||
|
||||
"node-fetch": ["node-fetch@3.3.1", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow=="],
|
||||
|
||||
"node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="],
|
||||
|
||||
"npm-run-path": ["npm-run-path@5.2.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg=="],
|
||||
|
||||
"onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="],
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
|
||||
|
||||
"pause-stream": ["pause-stream@0.0.11", "", { "dependencies": { "through": "~2.3" } }, "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A=="],
|
||||
|
||||
"picocolors": ["picocolors@1.0.0", "", {}, "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="],
|
||||
|
||||
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"platform": ["platform@1.3.6", "", {}, "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg=="],
|
||||
|
||||
"ps-tree": ["ps-tree@1.2.0", "", { "dependencies": { "event-stream": "=3.3.4" }, "bin": { "ps-tree": "./bin/ps-tree.js" } }, "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA=="],
|
||||
|
||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||
|
||||
"react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="],
|
||||
|
||||
"react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="],
|
||||
|
||||
"reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="],
|
||||
|
||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||
|
||||
"scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="],
|
||||
|
||||
"semver": ["semver@6.3.0", "", { "bin": { "semver": "./bin/semver.js" } }, "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||
|
||||
"simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="],
|
||||
|
||||
"slash": ["slash@4.0.0", "", {}, "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew=="],
|
||||
|
||||
"split": ["split@0.3.3", "", { "dependencies": { "through": "2" } }, "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA=="],
|
||||
|
||||
"stream-combiner": ["stream-combiner@0.0.4", "", { "dependencies": { "duplexer": "~0.1.1" } }, "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw=="],
|
||||
|
||||
"string-width": ["string-width@7.1.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
|
||||
|
||||
"strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
||||
|
||||
"supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
||||
|
||||
"through": ["through@2.3.8", "", {}, "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="],
|
||||
|
||||
"tinycolor2": ["tinycolor2@1.6.0", "", {}, "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="],
|
||||
|
||||
"to-fast-properties": ["to-fast-properties@2.0.0", "", {}, "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="],
|
||||
|
||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||
|
||||
"undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
|
||||
|
||||
"universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
|
||||
|
||||
"update-browserslist-db": ["update-browserslist-db@1.0.10", "", { "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "browserslist-lint": "cli.js" } }, "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ=="],
|
||||
|
||||
"web-streams-polyfill": ["web-streams-polyfill@3.3.2", "", {}, "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ=="],
|
||||
|
||||
"webpod": ["webpod@0.0.2", "", { "bin": { "webpod": "dist/index.js" } }, "sha512-cSwwQIeg8v4i3p4ajHhwgR7N6VyxAf+KYSSsY6Pd3aETE+xEU4vbitz7qQkB0I321xnhDdgtxuiSfk5r/FVtjg=="],
|
||||
|
||||
"which": ["which@3.0.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg=="],
|
||||
|
||||
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
||||
|
||||
"yaml": ["yaml@2.3.4", "", {}, "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA=="],
|
||||
|
||||
"zx": ["zx@7.2.3", "", { "dependencies": { "@types/fs-extra": "^11.0.1", "@types/minimist": "^1.2.2", "@types/node": "^18.16.3", "@types/ps-tree": "^1.1.2", "@types/which": "^3.0.0", "chalk": "^5.2.0", "fs-extra": "^11.1.1", "fx": "*", "globby": "^13.1.4", "minimist": "^1.2.8", "node-fetch": "3.3.1", "ps-tree": "^1.2.0", "webpod": "^0", "which": "^3.0.0", "yaml": "^2.2.2" }, "bin": { "zx": "build/cli.js" } }, "sha512-QODu38nLlYXg/B/Gw7ZKiZrvPkEsjPN3LQ5JFXM7h0JvwhEdPNNl+4Ao1y4+o3CLNiDUNcwzQYZ4/Ko7kKzCMA=="],
|
||||
|
||||
"@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.2", "", { "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.9" } }, "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A=="],
|
||||
|
||||
"@babel/highlight/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
||||
|
||||
"ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
||||
|
||||
"ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
}
|
||||
}
|
||||
BIN
bench/bun.lockb
Executable file
BIN
bench/bun.lockb
Executable file
Binary file not shown.
@@ -1,669 +0,0 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "expect-to-equal",
|
||||
"devDependencies": {
|
||||
"jest": "^29.3.1",
|
||||
"vitest": "^0.25.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@ampproject/remapping": ["@ampproject/remapping@2.2.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" } }, "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w=="],
|
||||
|
||||
"@babel/code-frame": ["@babel/code-frame@7.18.6", "", { "dependencies": { "@babel/highlight": "^7.18.6" } }, "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q=="],
|
||||
|
||||
"@babel/compat-data": ["@babel/compat-data@7.20.14", "", {}, "sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw=="],
|
||||
|
||||
"@babel/core": ["@babel/core@7.20.12", "", { "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.20.7", "@babel/helper-compilation-targets": "^7.20.7", "@babel/helper-module-transforms": "^7.20.11", "@babel/helpers": "^7.20.7", "@babel/parser": "^7.20.7", "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.12", "@babel/types": "^7.20.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.2", "semver": "^6.3.0" } }, "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg=="],
|
||||
|
||||
"@babel/generator": ["@babel/generator@7.20.14", "", { "dependencies": { "@babel/types": "^7.20.7", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" } }, "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg=="],
|
||||
|
||||
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.20.7", "", { "dependencies": { "@babel/compat-data": "^7.20.5", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ=="],
|
||||
|
||||
"@babel/helper-environment-visitor": ["@babel/helper-environment-visitor@7.18.9", "", {}, "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg=="],
|
||||
|
||||
"@babel/helper-function-name": ["@babel/helper-function-name@7.19.0", "", { "dependencies": { "@babel/template": "^7.18.10", "@babel/types": "^7.19.0" } }, "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w=="],
|
||||
|
||||
"@babel/helper-hoist-variables": ["@babel/helper-hoist-variables@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q=="],
|
||||
|
||||
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="],
|
||||
|
||||
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.20.11", "", { "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.10", "@babel/types": "^7.20.7" } }, "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg=="],
|
||||
|
||||
"@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.20.2", "", {}, "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ=="],
|
||||
|
||||
"@babel/helper-simple-access": ["@babel/helper-simple-access@7.20.2", "", { "dependencies": { "@babel/types": "^7.20.2" } }, "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA=="],
|
||||
|
||||
"@babel/helper-split-export-declaration": ["@babel/helper-split-export-declaration@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA=="],
|
||||
|
||||
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.19.4", "", {}, "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw=="],
|
||||
|
||||
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.19.1", "", {}, "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w=="],
|
||||
|
||||
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.18.6", "", {}, "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw=="],
|
||||
|
||||
"@babel/helpers": ["@babel/helpers@7.20.13", "", { "dependencies": { "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.13", "@babel/types": "^7.20.7" } }, "sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg=="],
|
||||
|
||||
"@babel/highlight": ["@babel/highlight@7.18.6", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g=="],
|
||||
|
||||
"@babel/parser": ["@babel/parser@7.20.15", "", { "bin": "./bin/babel-parser.js" }, "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg=="],
|
||||
|
||||
"@babel/plugin-syntax-async-generators": ["@babel/plugin-syntax-async-generators@7.8.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw=="],
|
||||
|
||||
"@babel/plugin-syntax-bigint": ["@babel/plugin-syntax-bigint@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg=="],
|
||||
|
||||
"@babel/plugin-syntax-class-properties": ["@babel/plugin-syntax-class-properties@7.12.13", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA=="],
|
||||
|
||||
"@babel/plugin-syntax-import-meta": ["@babel/plugin-syntax-import-meta@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g=="],
|
||||
|
||||
"@babel/plugin-syntax-json-strings": ["@babel/plugin-syntax-json-strings@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA=="],
|
||||
|
||||
"@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.18.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q=="],
|
||||
|
||||
"@babel/plugin-syntax-logical-assignment-operators": ["@babel/plugin-syntax-logical-assignment-operators@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig=="],
|
||||
|
||||
"@babel/plugin-syntax-nullish-coalescing-operator": ["@babel/plugin-syntax-nullish-coalescing-operator@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ=="],
|
||||
|
||||
"@babel/plugin-syntax-numeric-separator": ["@babel/plugin-syntax-numeric-separator@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug=="],
|
||||
|
||||
"@babel/plugin-syntax-object-rest-spread": ["@babel/plugin-syntax-object-rest-spread@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA=="],
|
||||
|
||||
"@babel/plugin-syntax-optional-catch-binding": ["@babel/plugin-syntax-optional-catch-binding@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q=="],
|
||||
|
||||
"@babel/plugin-syntax-optional-chaining": ["@babel/plugin-syntax-optional-chaining@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg=="],
|
||||
|
||||
"@babel/plugin-syntax-top-level-await": ["@babel/plugin-syntax-top-level-await@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw=="],
|
||||
|
||||
"@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.20.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.19.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ=="],
|
||||
|
||||
"@babel/template": ["@babel/template@7.20.7", "", { "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7" } }, "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw=="],
|
||||
|
||||
"@babel/traverse": ["@babel/traverse@7.20.13", "", { "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/parser": "^7.20.13", "@babel/types": "^7.20.7", "debug": "^4.1.0", "globals": "^11.1.0" } }, "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ=="],
|
||||
|
||||
"@babel/types": ["@babel/types@7.20.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" } }, "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg=="],
|
||||
|
||||
"@bcoe/v8-coverage": ["@bcoe/v8-coverage@0.2.3", "", {}, "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.16.17", "", { "os": "android", "cpu": "arm" }, "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.16.17", "", { "os": "android", "cpu": "arm64" }, "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.16.17", "", { "os": "android", "cpu": "x64" }, "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.16.17", "", { "os": "darwin", "cpu": "arm64" }, "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.16.17", "", { "os": "darwin", "cpu": "x64" }, "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.16.17", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.16.17", "", { "os": "freebsd", "cpu": "x64" }, "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.16.17", "", { "os": "linux", "cpu": "arm" }, "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.16.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.16.17", "", { "os": "linux", "cpu": "ia32" }, "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.16.17", "", { "os": "linux", "cpu": "none" }, "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.16.17", "", { "os": "linux", "cpu": "none" }, "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.16.17", "", { "os": "linux", "cpu": "ppc64" }, "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.16.17", "", { "os": "linux", "cpu": "none" }, "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.16.17", "", { "os": "linux", "cpu": "s390x" }, "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.16.17", "", { "os": "linux", "cpu": "x64" }, "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.16.17", "", { "os": "none", "cpu": "x64" }, "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.16.17", "", { "os": "openbsd", "cpu": "x64" }, "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.16.17", "", { "os": "sunos", "cpu": "x64" }, "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.16.17", "", { "os": "win32", "cpu": "arm64" }, "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.16.17", "", { "os": "win32", "cpu": "ia32" }, "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.16.17", "", { "os": "win32", "cpu": "x64" }, "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q=="],
|
||||
|
||||
"@istanbuljs/load-nyc-config": ["@istanbuljs/load-nyc-config@1.1.0", "", { "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" } }, "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ=="],
|
||||
|
||||
"@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="],
|
||||
|
||||
"@jest/console": ["@jest/console@29.4.3", "", { "dependencies": { "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "jest-message-util": "^29.4.3", "jest-util": "^29.4.3", "slash": "^3.0.0" } }, "sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A=="],
|
||||
|
||||
"@jest/core": ["@jest/core@29.4.3", "", { "dependencies": { "@jest/console": "^29.4.3", "@jest/reporters": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.4.3", "jest-config": "^29.4.3", "jest-haste-map": "^29.4.3", "jest-message-util": "^29.4.3", "jest-regex-util": "^29.4.3", "jest-resolve": "^29.4.3", "jest-resolve-dependencies": "^29.4.3", "jest-runner": "^29.4.3", "jest-runtime": "^29.4.3", "jest-snapshot": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "jest-watcher": "^29.4.3", "micromatch": "^4.0.4", "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"] }, "sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ=="],
|
||||
|
||||
"@jest/environment": ["@jest/environment@29.4.3", "", { "dependencies": { "@jest/fake-timers": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "jest-mock": "^29.4.3" } }, "sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA=="],
|
||||
|
||||
"@jest/expect": ["@jest/expect@29.4.3", "", { "dependencies": { "expect": "^29.4.3", "jest-snapshot": "^29.4.3" } }, "sha512-iktRU/YsxEtumI9zsPctYUk7ptpC+AVLLk1Ax3AsA4g1C+8OOnKDkIQBDHtD5hA/+VtgMd5AWI5gNlcAlt2vxQ=="],
|
||||
|
||||
"@jest/expect-utils": ["@jest/expect-utils@29.4.3", "", { "dependencies": { "jest-get-type": "^29.4.3" } }, "sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ=="],
|
||||
|
||||
"@jest/fake-timers": ["@jest/fake-timers@29.4.3", "", { "dependencies": { "@jest/types": "^29.4.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", "jest-message-util": "^29.4.3", "jest-mock": "^29.4.3", "jest-util": "^29.4.3" } }, "sha512-4Hote2MGcCTWSD2gwl0dwbCpBRHhE6olYEuTj8FMowdg3oQWNKr2YuxenPQYZ7+PfqPY1k98wKDU4Z+Hvd4Tiw=="],
|
||||
|
||||
"@jest/globals": ["@jest/globals@29.4.3", "", { "dependencies": { "@jest/environment": "^29.4.3", "@jest/expect": "^29.4.3", "@jest/types": "^29.4.3", "jest-mock": "^29.4.3" } }, "sha512-8BQ/5EzfOLG7AaMcDh7yFCbfRLtsc+09E1RQmRBI4D6QQk4m6NSK/MXo+3bJrBN0yU8A2/VIcqhvsOLFmziioA=="],
|
||||
|
||||
"@jest/reporters": ["@jest/reporters@29.4.3", "", { "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", "jest-message-util": "^29.4.3", "jest-util": "^29.4.3", "jest-worker": "^29.4.3", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "v8-to-istanbul": "^9.0.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"] }, "sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg=="],
|
||||
|
||||
"@jest/schemas": ["@jest/schemas@29.4.3", "", { "dependencies": { "@sinclair/typebox": "^0.25.16" } }, "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg=="],
|
||||
|
||||
"@jest/source-map": ["@jest/source-map@29.4.3", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.15", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" } }, "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w=="],
|
||||
|
||||
"@jest/test-result": ["@jest/test-result@29.4.3", "", { "dependencies": { "@jest/console": "^29.4.3", "@jest/types": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "sha512-Oi4u9NfBolMq9MASPwuWTlC5WvmNRwI4S8YrQg5R5Gi47DYlBe3sh7ILTqi/LGrK1XUE4XY9KZcQJTH1WJCLLA=="],
|
||||
|
||||
"@jest/test-sequencer": ["@jest/test-sequencer@29.4.3", "", { "dependencies": { "@jest/test-result": "^29.4.3", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.4.3", "slash": "^3.0.0" } }, "sha512-yi/t2nES4GB4G0mjLc0RInCq/cNr9dNwJxcGg8sslajua5Kb4kmozAc+qPLzplhBgfw1vLItbjyHzUN92UXicw=="],
|
||||
|
||||
"@jest/transform": ["@jest/transform@29.4.3", "", { "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.4.3", "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.4.3", "jest-regex-util": "^29.4.3", "jest-util": "^29.4.3", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", "write-file-atomic": "^4.0.2" } }, "sha512-8u0+fBGWolDshsFgPQJESkDa72da/EVwvL+II0trN2DR66wMwiQ9/CihaGfHdlLGFzbBZwMykFtxuwFdZqlKwg=="],
|
||||
|
||||
"@jest/types": ["@jest/types@29.4.3", "", { "dependencies": { "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", "chalk": "^4.0.0" } }, "sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.2", "", { "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.9" } }, "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A=="],
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.0", "", {}, "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="],
|
||||
|
||||
"@jridgewell/set-array": ["@jridgewell/set-array@1.1.2", "", {}, "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.4.14", "", {}, "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="],
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.17", "", { "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" } }, "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g=="],
|
||||
|
||||
"@sinclair/typebox": ["@sinclair/typebox@0.25.23", "", {}, "sha512-VEB8ygeP42CFLWyAJhN5OklpxUliqdNEUcXb4xZ/CINqtYGTjL5ukluKdKzQ0iWdUxyQ7B0539PAUhHKrCNWSQ=="],
|
||||
|
||||
"@sinonjs/commons": ["@sinonjs/commons@2.0.0", "", { "dependencies": { "type-detect": "4.0.8" } }, "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg=="],
|
||||
|
||||
"@sinonjs/fake-timers": ["@sinonjs/fake-timers@10.0.2", "", { "dependencies": { "@sinonjs/commons": "^2.0.0" } }, "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw=="],
|
||||
|
||||
"@types/babel__core": ["@types/babel__core@7.20.0", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ=="],
|
||||
|
||||
"@types/babel__generator": ["@types/babel__generator@7.6.4", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg=="],
|
||||
|
||||
"@types/babel__template": ["@types/babel__template@7.4.1", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g=="],
|
||||
|
||||
"@types/babel__traverse": ["@types/babel__traverse@7.18.3", "", { "dependencies": { "@babel/types": "^7.3.0" } }, "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w=="],
|
||||
|
||||
"@types/chai": ["@types/chai@4.3.4", "", {}, "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw=="],
|
||||
|
||||
"@types/chai-subset": ["@types/chai-subset@1.3.3", "", { "dependencies": { "@types/chai": "*" } }, "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw=="],
|
||||
|
||||
"@types/graceful-fs": ["@types/graceful-fs@4.1.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw=="],
|
||||
|
||||
"@types/istanbul-lib-coverage": ["@types/istanbul-lib-coverage@2.0.4", "", {}, "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g=="],
|
||||
|
||||
"@types/istanbul-lib-report": ["@types/istanbul-lib-report@3.0.0", "", { "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg=="],
|
||||
|
||||
"@types/istanbul-reports": ["@types/istanbul-reports@3.0.1", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw=="],
|
||||
|
||||
"@types/node": ["@types/node@18.14.0", "", {}, "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A=="],
|
||||
|
||||
"@types/prettier": ["@types/prettier@2.7.2", "", {}, "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg=="],
|
||||
|
||||
"@types/stack-utils": ["@types/stack-utils@2.0.1", "", {}, "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw=="],
|
||||
|
||||
"@types/yargs": ["@types/yargs@17.0.22", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g=="],
|
||||
|
||||
"@types/yargs-parser": ["@types/yargs-parser@20.2.2", "", {}, "sha512-sUWMriymrSqTvxCmCkf+7k392TNDcMJBHI1/rysWJxKnWAan/Zk4gZ/GEieSRo4EqIEPpbGU3Sd/0KTRoIA3pA=="],
|
||||
|
||||
"acorn": ["acorn@8.8.2", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw=="],
|
||||
|
||||
"acorn-walk": ["acorn-walk@8.2.0", "", {}, "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA=="],
|
||||
|
||||
"ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
|
||||
|
||||
"argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
||||
|
||||
"assertion-error": ["assertion-error@1.1.0", "", {}, "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="],
|
||||
|
||||
"babel-jest": ["babel-jest@29.4.3", "", { "dependencies": { "@jest/transform": "^29.4.3", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.4.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, "peerDependencies": { "@babel/core": "^7.8.0" } }, "sha512-o45Wyn32svZE+LnMVWv/Z4x0SwtLbh4FyGcYtR20kIWd+rdrDZ9Fzq8Ml3MYLD+mZvEdzCjZsCnYZ2jpJyQ+Nw=="],
|
||||
|
||||
"babel-plugin-istanbul": ["babel-plugin-istanbul@6.1.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" } }, "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA=="],
|
||||
|
||||
"babel-plugin-jest-hoist": ["babel-plugin-jest-hoist@29.4.3", "", { "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", "@types/babel__core": "^7.1.14", "@types/babel__traverse": "^7.0.6" } }, "sha512-mB6q2q3oahKphy5V7CpnNqZOCkxxZ9aokf1eh82Dy3jQmg4xvM1tGrh5y6BQUJh4a3Pj9+eLfwvAZ7VNKg7H8Q=="],
|
||||
|
||||
"babel-preset-current-node-syntax": ["babel-preset-current-node-syntax@1.0.1", "", { "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.8.3", "@babel/plugin-syntax-import-meta": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.8.3", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-top-level-await": "^7.8.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ=="],
|
||||
|
||||
"babel-preset-jest": ["babel-preset-jest@29.4.3", "", { "dependencies": { "babel-plugin-jest-hoist": "^29.4.3", "babel-preset-current-node-syntax": "^1.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gWx6COtSuma6n9bw+8/F+2PCXrIgxV/D1TJFnp6OyBK2cxPWg0K9p/sriNYeifKjpUkMViWQ09DSWtzJQRETsw=="],
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
||||
|
||||
"braces": ["braces@3.0.2", "", { "dependencies": { "fill-range": "^7.0.1" } }, "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A=="],
|
||||
|
||||
"browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="],
|
||||
|
||||
"bser": ["bser@2.1.1", "", { "dependencies": { "node-int64": "^0.4.0" } }, "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ=="],
|
||||
|
||||
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
||||
|
||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||
|
||||
"camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001456", "", {}, "sha512-XFHJY5dUgmpMV25UqaD4kVq2LsiaU5rS8fb0f17pCoXQiQslzmFgnfOxfvo1bTpTqf7dwG/N/05CnLCnOEKmzA=="],
|
||||
|
||||
"chai": ["chai@4.3.7", "", { "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^4.1.2", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" } }, "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A=="],
|
||||
|
||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||
|
||||
"char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="],
|
||||
|
||||
"check-error": ["check-error@1.0.2", "", {}, "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA=="],
|
||||
|
||||
"ci-info": ["ci-info@3.8.0", "", {}, "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw=="],
|
||||
|
||||
"cjs-module-lexer": ["cjs-module-lexer@1.2.2", "", {}, "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="],
|
||||
|
||||
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
|
||||
|
||||
"co": ["co@4.6.0", "", {}, "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ=="],
|
||||
|
||||
"collect-v8-coverage": ["collect-v8-coverage@1.0.1", "", {}, "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||
|
||||
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.3", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w=="],
|
||||
|
||||
"debug": ["debug@4.3.4", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ=="],
|
||||
|
||||
"dedent": ["dedent@0.7.0", "", {}, "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA=="],
|
||||
|
||||
"deep-eql": ["deep-eql@4.1.3", "", { "dependencies": { "type-detect": "^4.0.0" } }, "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw=="],
|
||||
|
||||
"deepmerge": ["deepmerge@4.3.0", "", {}, "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og=="],
|
||||
|
||||
"detect-newline": ["detect-newline@3.1.0", "", {}, "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA=="],
|
||||
|
||||
"diff-sequences": ["diff-sequences@29.4.3", "", {}, "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.4.302", "", {}, "sha512-Uk7C+7aPBryUR1Fwvk9VmipBcN9fVsqBO57jV2ZjTm+IZ6BMNqu7EDVEg2HxCNufk6QcWlFsBkhQyQroB2VWKw=="],
|
||||
|
||||
"emittery": ["emittery@0.13.1", "", {}, "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="],
|
||||
|
||||
"esbuild": ["esbuild@0.16.17", "", { "dependencies": { "@esbuild/android-arm": "0.16.17", "@esbuild/android-arm64": "0.16.17", "@esbuild/android-x64": "0.16.17", "@esbuild/darwin-arm64": "0.16.17", "@esbuild/darwin-x64": "0.16.17", "@esbuild/freebsd-arm64": "0.16.17", "@esbuild/freebsd-x64": "0.16.17", "@esbuild/linux-arm": "0.16.17", "@esbuild/linux-arm64": "0.16.17", "@esbuild/linux-ia32": "0.16.17", "@esbuild/linux-loong64": "0.16.17", "@esbuild/linux-mips64el": "0.16.17", "@esbuild/linux-ppc64": "0.16.17", "@esbuild/linux-riscv64": "0.16.17", "@esbuild/linux-s390x": "0.16.17", "@esbuild/linux-x64": "0.16.17", "@esbuild/netbsd-x64": "0.16.17", "@esbuild/openbsd-x64": "0.16.17", "@esbuild/sunos-x64": "0.16.17", "@esbuild/win32-arm64": "0.16.17", "@esbuild/win32-ia32": "0.16.17", "@esbuild/win32-x64": "0.16.17" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg=="],
|
||||
|
||||
"escalade": ["escalade@3.1.1", "", {}, "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="],
|
||||
|
||||
"escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="],
|
||||
|
||||
"esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],
|
||||
|
||||
"execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="],
|
||||
|
||||
"exit": ["exit@0.1.2", "", {}, "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ=="],
|
||||
|
||||
"expect": ["expect@29.4.3", "", { "dependencies": { "@jest/expect-utils": "^29.4.3", "jest-get-type": "^29.4.3", "jest-matcher-utils": "^29.4.3", "jest-message-util": "^29.4.3", "jest-util": "^29.4.3" } }, "sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg=="],
|
||||
|
||||
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
|
||||
|
||||
"fb-watchman": ["fb-watchman@2.0.2", "", { "dependencies": { "bser": "2.1.1" } }, "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA=="],
|
||||
|
||||
"fill-range": ["fill-range@7.0.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ=="],
|
||||
|
||||
"find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
|
||||
|
||||
"fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.1", "", {}, "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="],
|
||||
|
||||
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
|
||||
|
||||
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
|
||||
|
||||
"get-func-name": ["get-func-name@2.0.0", "", {}, "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig=="],
|
||||
|
||||
"get-package-type": ["get-package-type@0.1.0", "", {}, "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q=="],
|
||||
|
||||
"get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
|
||||
|
||||
"glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
|
||||
"globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.10", "", {}, "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="],
|
||||
|
||||
"has": ["has@1.0.3", "", { "dependencies": { "function-bind": "^1.1.1" } }, "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw=="],
|
||||
|
||||
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||
|
||||
"html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="],
|
||||
|
||||
"human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
|
||||
|
||||
"import-local": ["import-local@3.1.0", "", { "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" }, "bin": { "import-local-fixture": "fixtures/cli.js" } }, "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg=="],
|
||||
|
||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||
|
||||
"inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="],
|
||||
|
||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
|
||||
"is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
|
||||
|
||||
"is-core-module": ["is-core-module@2.11.0", "", { "dependencies": { "has": "^1.0.3" } }, "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw=="],
|
||||
|
||||
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||
|
||||
"is-generator-fn": ["is-generator-fn@2.1.0", "", {}, "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ=="],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.0", "", {}, "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw=="],
|
||||
|
||||
"istanbul-lib-instrument": ["istanbul-lib-instrument@5.2.1", "", { "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" } }, "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg=="],
|
||||
|
||||
"istanbul-lib-report": ["istanbul-lib-report@3.0.0", "", { "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" } }, "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw=="],
|
||||
|
||||
"istanbul-lib-source-maps": ["istanbul-lib-source-maps@4.0.1", "", { "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" } }, "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw=="],
|
||||
|
||||
"istanbul-reports": ["istanbul-reports@3.1.5", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w=="],
|
||||
|
||||
"jest": ["jest@29.4.3", "", { "dependencies": { "@jest/core": "^29.4.3", "@jest/types": "^29.4.3", "import-local": "^3.0.2", "jest-cli": "^29.4.3" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"], "bin": { "jest": "bin/jest.js" } }, "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA=="],
|
||||
|
||||
"jest-changed-files": ["jest-changed-files@29.4.3", "", { "dependencies": { "execa": "^5.0.0", "p-limit": "^3.1.0" } }, "sha512-Vn5cLuWuwmi2GNNbokPOEcvrXGSGrqVnPEZV7rC6P7ck07Dyw9RFnvWglnupSh+hGys0ajGtw/bc2ZgweljQoQ=="],
|
||||
|
||||
"jest-circus": ["jest-circus@29.4.3", "", { "dependencies": { "@jest/environment": "^29.4.3", "@jest/expect": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", "jest-each": "^29.4.3", "jest-matcher-utils": "^29.4.3", "jest-message-util": "^29.4.3", "jest-runtime": "^29.4.3", "jest-snapshot": "^29.4.3", "jest-util": "^29.4.3", "p-limit": "^3.1.0", "pretty-format": "^29.4.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "sha512-Vw/bVvcexmdJ7MLmgdT3ZjkJ3LKu8IlpefYokxiqoZy6OCQ2VAm6Vk3t/qHiAGUXbdbJKJWnc8gH3ypTbB/OBw=="],
|
||||
|
||||
"jest-cli": ["jest-cli@29.4.3", "", { "dependencies": { "@jest/core": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/types": "^29.4.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", "jest-config": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "prompts": "^2.0.1", "yargs": "^17.3.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"], "bin": { "jest": "bin/jest.js" } }, "sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg=="],
|
||||
|
||||
"jest-config": ["jest-config@29.4.3", "", { "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.4.3", "@jest/types": "^29.4.3", "babel-jest": "^29.4.3", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "jest-circus": "^29.4.3", "jest-environment-node": "^29.4.3", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", "jest-resolve": "^29.4.3", "jest-runner": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "micromatch": "^4.0.4", "parse-json": "^5.2.0", "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "peerDependencies": { "@types/node": "*", "ts-node": ">=9.0.0" }, "optionalPeers": ["ts-node"] }, "sha512-eCIpqhGnIjdUCXGtLhz4gdDoxKSWXKjzNcc5r+0S1GKOp2fwOipx5mRcwa9GB/ArsxJ1jlj2lmlD9bZAsBxaWQ=="],
|
||||
|
||||
"jest-diff": ["jest-diff@29.4.3", "", { "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", "pretty-format": "^29.4.3" } }, "sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA=="],
|
||||
|
||||
"jest-docblock": ["jest-docblock@29.4.3", "", { "dependencies": { "detect-newline": "^3.0.0" } }, "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg=="],
|
||||
|
||||
"jest-each": ["jest-each@29.4.3", "", { "dependencies": { "@jest/types": "^29.4.3", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "jest-util": "^29.4.3", "pretty-format": "^29.4.3" } }, "sha512-1ElHNAnKcbJb/b+L+7j0/w7bDvljw4gTv1wL9fYOczeJrbTbkMGQ5iQPFJ3eFQH19VPTx1IyfePdqSpePKss7Q=="],
|
||||
|
||||
"jest-environment-node": ["jest-environment-node@29.4.3", "", { "dependencies": { "@jest/environment": "^29.4.3", "@jest/fake-timers": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "jest-mock": "^29.4.3", "jest-util": "^29.4.3" } }, "sha512-gAiEnSKF104fsGDXNkwk49jD/0N0Bqu2K9+aMQXA6avzsA9H3Fiv1PW2D+gzbOSR705bWd2wJZRFEFpV0tXISg=="],
|
||||
|
||||
"jest-get-type": ["jest-get-type@29.4.3", "", {}, "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg=="],
|
||||
|
||||
"jest-haste-map": ["jest-haste-map@29.4.3", "", { "dependencies": { "@jest/types": "^29.4.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", "jest-util": "^29.4.3", "jest-worker": "^29.4.3", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "sha512-eZIgAS8tvm5IZMtKlR8Y+feEOMfo2pSQkmNbufdbMzMSn9nitgGxF1waM/+LbryO3OkMcKS98SUb+j/cQxp/vQ=="],
|
||||
|
||||
"jest-leak-detector": ["jest-leak-detector@29.4.3", "", { "dependencies": { "jest-get-type": "^29.4.3", "pretty-format": "^29.4.3" } }, "sha512-9yw4VC1v2NspMMeV3daQ1yXPNxMgCzwq9BocCwYrRgXe4uaEJPAN0ZK37nFBhcy3cUwEVstFecFLaTHpF7NiGA=="],
|
||||
|
||||
"jest-matcher-utils": ["jest-matcher-utils@29.4.3", "", { "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.4.3", "jest-get-type": "^29.4.3", "pretty-format": "^29.4.3" } }, "sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg=="],
|
||||
|
||||
"jest-message-util": ["jest-message-util@29.4.3", "", { "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.4.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", "pretty-format": "^29.4.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw=="],
|
||||
|
||||
"jest-mock": ["jest-mock@29.4.3", "", { "dependencies": { "@jest/types": "^29.4.3", "@types/node": "*", "jest-util": "^29.4.3" } }, "sha512-LjFgMg+xed9BdkPMyIJh+r3KeHt1klXPJYBULXVVAkbTaaKjPX1o1uVCAZADMEp/kOxGTwy/Ot8XbvgItOrHEg=="],
|
||||
|
||||
"jest-pnp-resolver": ["jest-pnp-resolver@1.2.3", "", { "peerDependencies": { "jest-resolve": "*" } }, "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w=="],
|
||||
|
||||
"jest-regex-util": ["jest-regex-util@29.4.3", "", {}, "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg=="],
|
||||
|
||||
"jest-resolve": ["jest-resolve@29.4.3", "", { "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.4.3", "jest-pnp-resolver": "^1.2.2", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "sha512-GPokE1tzguRyT7dkxBim4wSx6E45S3bOQ7ZdKEG+Qj0Oac9+6AwJPCk0TZh5Vu0xzeX4afpb+eDmgbmZFFwpOw=="],
|
||||
|
||||
"jest-resolve-dependencies": ["jest-resolve-dependencies@29.4.3", "", { "dependencies": { "jest-regex-util": "^29.4.3", "jest-snapshot": "^29.4.3" } }, "sha512-uvKMZAQ3nmXLH7O8WAOhS5l0iWyT3WmnJBdmIHiV5tBbdaDZ1wqtNX04FONGoaFvSOSHBJxnwAVnSn1WHdGVaw=="],
|
||||
|
||||
"jest-runner": ["jest-runner@29.4.3", "", { "dependencies": { "@jest/console": "^29.4.3", "@jest/environment": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", "jest-environment-node": "^29.4.3", "jest-haste-map": "^29.4.3", "jest-leak-detector": "^29.4.3", "jest-message-util": "^29.4.3", "jest-resolve": "^29.4.3", "jest-runtime": "^29.4.3", "jest-util": "^29.4.3", "jest-watcher": "^29.4.3", "jest-worker": "^29.4.3", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "sha512-GWPTEiGmtHZv1KKeWlTX9SIFuK19uLXlRQU43ceOQ2hIfA5yPEJC7AMkvFKpdCHx6pNEdOD+2+8zbniEi3v3gA=="],
|
||||
|
||||
"jest-runtime": ["jest-runtime@29.4.3", "", { "dependencies": { "@jest/environment": "^29.4.3", "@jest/fake-timers": "^29.4.3", "@jest/globals": "^29.4.3", "@jest/source-map": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.4.3", "jest-message-util": "^29.4.3", "jest-mock": "^29.4.3", "jest-regex-util": "^29.4.3", "jest-resolve": "^29.4.3", "jest-snapshot": "^29.4.3", "jest-util": "^29.4.3", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "sha512-F5bHvxSH+LvLV24vVB3L8K467dt3y3dio6V3W89dUz9nzvTpqd/HcT9zfYKL2aZPvD63vQFgLvaUX/UpUhrP6Q=="],
|
||||
|
||||
"jest-snapshot": ["jest-snapshot@29.4.3", "", { "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", "@jest/expect-utils": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", "expect": "^29.4.3", "graceful-fs": "^4.2.9", "jest-diff": "^29.4.3", "jest-get-type": "^29.4.3", "jest-haste-map": "^29.4.3", "jest-matcher-utils": "^29.4.3", "jest-message-util": "^29.4.3", "jest-util": "^29.4.3", "natural-compare": "^1.4.0", "pretty-format": "^29.4.3", "semver": "^7.3.5" } }, "sha512-NGlsqL0jLPDW91dz304QTM/SNO99lpcSYYAjNiX0Ou+sSGgkanKBcSjCfp/pqmiiO1nQaOyLp6XQddAzRcx3Xw=="],
|
||||
|
||||
"jest-util": ["jest-util@29.4.3", "", { "dependencies": { "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" } }, "sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q=="],
|
||||
|
||||
"jest-validate": ["jest-validate@29.4.3", "", { "dependencies": { "@jest/types": "^29.4.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", "pretty-format": "^29.4.3" } }, "sha512-J3u5v7aPQoXPzaar6GndAVhdQcZr/3osWSgTeKg5v574I9ybX/dTyH0AJFb5XgXIB7faVhf+rS7t4p3lL9qFaw=="],
|
||||
|
||||
"jest-watcher": ["jest-watcher@29.4.3", "", { "dependencies": { "@jest/test-result": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", "jest-util": "^29.4.3", "string-length": "^4.0.1" } }, "sha512-zwlXH3DN3iksoIZNk73etl1HzKyi5FuQdYLnkQKm5BW4n8HpoG59xSwpVdFrnh60iRRaRBGw0gcymIxjJENPcA=="],
|
||||
|
||||
"jest-worker": ["jest-worker@29.4.3", "", { "dependencies": { "@types/node": "*", "jest-util": "^29.4.3", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-GLHN/GTAAMEy5BFdvpUfzr9Dr80zQqBrh0fz1mtRMe05hqP45+HfQltu7oTBfduD0UeZs09d+maFtFYAXFWvAA=="],
|
||||
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
||||
|
||||
"jsesc": ["jsesc@2.5.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="],
|
||||
|
||||
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
|
||||
|
||||
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
||||
|
||||
"kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
|
||||
|
||||
"leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
|
||||
|
||||
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
||||
|
||||
"local-pkg": ["local-pkg@0.4.3", "", {}, "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g=="],
|
||||
|
||||
"locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
|
||||
|
||||
"loupe": ["loupe@2.3.6", "", { "dependencies": { "get-func-name": "^2.0.0" } }, "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA=="],
|
||||
|
||||
"lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
|
||||
|
||||
"make-dir": ["make-dir@3.1.0", "", { "dependencies": { "semver": "^6.0.0" } }, "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="],
|
||||
|
||||
"makeerror": ["makeerror@1.0.12", "", { "dependencies": { "tmpl": "1.0.5" } }, "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg=="],
|
||||
|
||||
"merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
|
||||
|
||||
"micromatch": ["micromatch@4.0.5", "", { "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" } }, "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA=="],
|
||||
|
||||
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
||||
|
||||
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="],
|
||||
|
||||
"nanoid": ["nanoid@3.3.4", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw=="],
|
||||
|
||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||
|
||||
"node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
|
||||
|
||||
"node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="],
|
||||
|
||||
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
|
||||
|
||||
"npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
|
||||
|
||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
||||
|
||||
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
||||
|
||||
"p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
||||
|
||||
"p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="],
|
||||
|
||||
"parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],
|
||||
|
||||
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
||||
|
||||
"path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="],
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
|
||||
|
||||
"pathval": ["pathval@1.1.1", "", {}, "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ=="],
|
||||
|
||||
"picocolors": ["picocolors@1.0.0", "", {}, "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="],
|
||||
|
||||
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"pirates": ["pirates@4.0.5", "", {}, "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ=="],
|
||||
|
||||
"pkg-dir": ["pkg-dir@4.2.0", "", { "dependencies": { "find-up": "^4.0.0" } }, "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ=="],
|
||||
|
||||
"postcss": ["postcss@8.4.21", "", { "dependencies": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg=="],
|
||||
|
||||
"pretty-format": ["pretty-format@29.4.3", "", { "dependencies": { "@jest/schemas": "^29.4.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA=="],
|
||||
|
||||
"prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="],
|
||||
|
||||
"react-is": ["react-is@18.2.0", "", {}, "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="],
|
||||
|
||||
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
|
||||
|
||||
"resolve": ["resolve@1.22.1", "", { "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw=="],
|
||||
|
||||
"resolve-cwd": ["resolve-cwd@3.0.0", "", { "dependencies": { "resolve-from": "^5.0.0" } }, "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg=="],
|
||||
|
||||
"resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
|
||||
|
||||
"resolve.exports": ["resolve.exports@2.0.0", "", {}, "sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg=="],
|
||||
|
||||
"rollup": ["rollup@3.17.0", "", { "dependencies": { "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-0zZQ0J4p0ZtTla6l8sheDTUyNfGZQDpU5h0nPHf6xtUXIzKK70LmB2IRR0wLnzaL8a02fjmsJy+XCncbSwOpjg=="],
|
||||
|
||||
"semver": ["semver@7.3.8", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
||||
|
||||
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
||||
|
||||
"slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||
|
||||
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"source-map-js": ["source-map-js@1.0.2", "", {}, "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="],
|
||||
|
||||
"source-map-support": ["source-map-support@0.5.13", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w=="],
|
||||
|
||||
"sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
|
||||
|
||||
"stack-utils": ["stack-utils@2.0.6", "", { "dependencies": { "escape-string-regexp": "^2.0.0" } }, "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ=="],
|
||||
|
||||
"string-length": ["string-length@4.0.2", "", { "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" } }, "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ=="],
|
||||
|
||||
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"strip-bom": ["strip-bom@4.0.0", "", {}, "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w=="],
|
||||
|
||||
"strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
|
||||
|
||||
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
||||
|
||||
"strip-literal": ["strip-literal@1.0.1", "", { "dependencies": { "acorn": "^8.8.2" } }, "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q=="],
|
||||
|
||||
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||
|
||||
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||
|
||||
"test-exclude": ["test-exclude@6.0.0", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" } }, "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w=="],
|
||||
|
||||
"tinybench": ["tinybench@2.3.1", "", {}, "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA=="],
|
||||
|
||||
"tinypool": ["tinypool@0.3.1", "", {}, "sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ=="],
|
||||
|
||||
"tinyspy": ["tinyspy@1.1.1", "", {}, "sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g=="],
|
||||
|
||||
"tmpl": ["tmpl@1.0.5", "", {}, "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw=="],
|
||||
|
||||
"to-fast-properties": ["to-fast-properties@2.0.0", "", {}, "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="],
|
||||
|
||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||
|
||||
"type-detect": ["type-detect@4.0.8", "", {}, "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="],
|
||||
|
||||
"type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
|
||||
|
||||
"update-browserslist-db": ["update-browserslist-db@1.0.10", "", { "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "browserslist-lint": "cli.js" } }, "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ=="],
|
||||
|
||||
"v8-to-istanbul": ["v8-to-istanbul@9.1.0", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0" } }, "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA=="],
|
||||
|
||||
"vite": ["vite@4.1.2", "", { "dependencies": { "esbuild": "^0.16.14", "fsevents": "~2.3.2", "postcss": "^8.4.21", "resolve": "^1.22.1", "rollup": "^3.10.0" }, "peerDependencies": { "@types/node": ">= 14", "less": "*", "sass": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["less", "sass", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-MWDb9Rfy3DI8omDQySbMK93nQqStwbsQWejXRY2EBzEWKmLAXWb1mkI9Yw2IJrc+oCvPCI1Os5xSSIBYY6DEAw=="],
|
||||
|
||||
"vitest": ["vitest@0.25.8", "", { "dependencies": { "@types/chai": "^4.3.4", "@types/chai-subset": "^1.3.3", "@types/node": "*", "acorn": "^8.8.1", "acorn-walk": "^8.2.0", "chai": "^4.3.7", "debug": "^4.3.4", "local-pkg": "^0.4.2", "source-map": "^0.6.1", "strip-literal": "^1.0.0", "tinybench": "^2.3.1", "tinypool": "^0.3.0", "tinyspy": "^1.0.2", "vite": "^3.0.0 || ^4.0.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@vitest/browser": "*", "@vitest/ui": "*", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-X75TApG2wZTJn299E/TIYevr4E9/nBo1sUtZzn0Ci5oK8qnpZAZyhwg0qCeMSakGIWtc6oRwcQFyFfW14aOFWg=="],
|
||||
|
||||
"walker": ["walker@1.0.8", "", { "dependencies": { "makeerror": "1.0.12" } }, "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"write-file-atomic": ["write-file-atomic@4.0.2", "", { "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" } }, "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg=="],
|
||||
|
||||
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
|
||||
|
||||
"yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"yargs": ["yargs@17.7.0", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-dwqOPg5trmrre9+v8SUo2q/hAwyKoVfu8OC1xPHKJGNdxAvPl4sKxL4vBnh3bQz/ZvvGAFeA5H3ou2kcOY8sQQ=="],
|
||||
|
||||
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
|
||||
|
||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||
|
||||
"@ampproject/remapping/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.1.1", "", { "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w=="],
|
||||
|
||||
"@babel/core/convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="],
|
||||
|
||||
"@babel/core/semver": ["semver@6.3.0", "", { "bin": { "semver": "./bin/semver.js" } }, "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="],
|
||||
|
||||
"@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
||||
|
||||
"@babel/helper-compilation-targets/semver": ["semver@6.3.0", "", { "bin": { "semver": "./bin/semver.js" } }, "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="],
|
||||
|
||||
"@babel/highlight/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
||||
|
||||
"@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="],
|
||||
|
||||
"@types/chai-subset/@types/chai": ["@types/chai@2.0.4", "", {}, "sha512-DNUVOufLw3znPcZaEvjAER3F1KScpGSrp3n8eIE5R7rdjTJE2w4orUiVY3KHBzvGCx0++ZlymkAzjroa76NPRA=="],
|
||||
|
||||
"istanbul-lib-instrument/semver": ["semver@6.3.0", "", { "bin": { "semver": "./bin/semver.js" } }, "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="],
|
||||
|
||||
"jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||
|
||||
"make-dir/semver": ["semver@6.3.0", "", { "bin": { "semver": "./bin/semver.js" } }, "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="],
|
||||
|
||||
"p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
||||
|
||||
"pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
||||
|
||||
"test-exclude/minimatch": ["minimatch@3.0.8", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q=="],
|
||||
|
||||
"v8-to-istanbul/convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="],
|
||||
|
||||
"@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
||||
|
||||
"@babel/highlight/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
||||
|
||||
"@babel/highlight/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
||||
|
||||
"@babel/highlight/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
||||
|
||||
"@babel/highlight/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||
|
||||
"@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
}
|
||||
}
|
||||
BIN
bench/expect-to-equal/bun.lockb
Executable file
BIN
bench/expect-to-equal/bun.lockb
Executable file
Binary file not shown.
@@ -1,37 +0,0 @@
|
||||
# express benchmark
|
||||
|
||||
This benchmarks a hello world express server.
|
||||
|
||||
To install dependencies:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
To run in Bun:
|
||||
|
||||
```sh
|
||||
bun ./express.mjs
|
||||
```
|
||||
|
||||
To run in Node:
|
||||
|
||||
```sh
|
||||
node ./express.mjs
|
||||
```
|
||||
|
||||
To run in Deno:
|
||||
|
||||
```sh
|
||||
deno run -A ./express.mjs
|
||||
```
|
||||
|
||||
To benchmark each runtime:
|
||||
|
||||
```bash
|
||||
oha http://localhost:3000 -n 500000 -H "Accept-Encoding: identity"
|
||||
```
|
||||
|
||||
We recommend using `oha` or `bombardier` for benchmarking. We do not recommend using `ab`, as it uses HTTP/1.0 which stopped being used by web browsers in the early 2000s. We also do not recommend using autocannon, as the node:http client is not performant enough to measure the throughput of Bun's HTTP server.
|
||||
|
||||
Note the `Accept-Encoding: identity` header exists to prevent Deno's HTTP server from compressing the response.
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
// See the README.md for more information
|
||||
import express from "express";
|
||||
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3000;
|
||||
let i = 0;
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.send("Hello World! (request number: " + i++ + ")");
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Express server listening on port ${port}`);
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "express",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "5"
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bench",
|
||||
"dependencies": {
|
||||
"@napi-rs/cli": "^2.10.1",
|
||||
"@node-rs/helper": "^1.3.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@napi-rs/cli": ["@napi-rs/cli@2.14.8", "", { "bin": { "napi": "scripts/index.js" } }, "sha512-IvA3s8BqohMdUbOkFn7+23u1dhIJZCkA8Xps7DD4SLdCMbcbUF6MUuKiqxuqmVHBFTaxU25sU56WdX3efqGgPw=="],
|
||||
|
||||
"@napi-rs/triples": ["@napi-rs/triples@1.1.0", "", {}, "sha512-XQr74QaLeMiqhStEhLn1im9EOMnkypp7MZOwQhGzqp2Weu5eQJbpPxWxixxlYRKWPOmJjsk6qYfYH9kq43yc2w=="],
|
||||
|
||||
"@node-rs/helper": ["@node-rs/helper@1.3.3", "", { "dependencies": { "@napi-rs/triples": "^1.1.0" } }, "sha512-p4OdfQObGN9YFy5WZaGwlPYICQSe7xZYyXB0sxREmvj1HzGKp5bPg2PlfgfMZEfnjIA882B9ZrnagYzZihIwjA=="],
|
||||
}
|
||||
}
|
||||
BIN
bench/ffi/src/bun.lockb
Executable file
BIN
bench/ffi/src/bun.lockb
Executable file
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bench",
|
||||
"dependencies": {
|
||||
"@babel/standalone": "7.24.10",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@babel/standalone": ["@babel/standalone@7.24.10", "", {}, "sha512-nGC37EKfmelpyCXto1pw6SBkD5ZQRdMbL6WISi28xWit9dtiy9dChU1WgEfzturUTxrmOGkMDRrCydFMA7uOaQ=="],
|
||||
}
|
||||
}
|
||||
BIN
bench/gzip/bun.lockb
Executable file
BIN
bench/gzip/bun.lockb
Executable file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
bench/hot-module-reloading/css-stress-test/bun.lockb
Executable file
BIN
bench/hot-module-reloading/css-stress-test/bun.lockb
Executable file
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
import ReactDOM from "react-dom";
|
||||
import { Main } from "./main";
|
||||
|
||||
const Base = () => {
|
||||
const Base = ({}) => {
|
||||
const name = typeof location !== "undefined" ? decodeURIComponent(location.search.substring(1)) : null;
|
||||
return <Main productName={name} />;
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ $ hyperfine --prepare 'rm -rf node_modules' --runs 1 'bun install' 'pnpm install
|
||||
To run the benchmark with offline mode but without lockfiles:
|
||||
|
||||
```sh
|
||||
$ hyperfine --prepare 'rm -rf node_modules' --warmup 1 'rm bun.lock && bun install' 'rm pnpm-lock.yaml && pnpm install --prefer-offline' 'rm yarn.lock && yarn --offline' 'rm package-lock.json && npm install --prefer-offline'
|
||||
$ hyperfine --prepare 'rm -rf node_modules' --warmup 1 'rm bun.lockb && bun install' 'rm pnpm-lock.yaml && pnpm install --prefer-offline' 'rm yarn.lock && yarn --offline' 'rm package-lock.json && npm install --prefer-offline'
|
||||
```
|
||||
|
||||
##
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"execa": "^8.0.1",
|
||||
"fast-glob": "3.3.1",
|
||||
"fdir": "^6.1.0",
|
||||
"mitata": "^1.0.25",
|
||||
"mitata": "^1.0.10",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"string-width": "7.1.0",
|
||||
|
||||
175
bench/postgres/.gitignore
vendored
175
bench/postgres/.gitignore
vendored
@@ -1,175 +0,0 @@
|
||||
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||
|
||||
# Logs
|
||||
|
||||
logs
|
||||
_.log
|
||||
npm-debug.log_
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Caches
|
||||
|
||||
.cache
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
|
||||
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
# Runtime data
|
||||
|
||||
pids
|
||||
_.pid
|
||||
_.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
|
||||
.temp
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# IntelliJ based IDEs
|
||||
.idea
|
||||
|
||||
# Finder (MacOS) folder config
|
||||
.DS_Store
|
||||
@@ -1,27 +0,0 @@
|
||||
# Postgres table load benchmark
|
||||
|
||||
To install dependencies:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
To run in Bun:
|
||||
|
||||
```bash
|
||||
bun ./index.mjs
|
||||
```
|
||||
|
||||
To run in Node.js:
|
||||
|
||||
```bash
|
||||
node index.mjs
|
||||
```
|
||||
|
||||
To run in Deno:
|
||||
|
||||
```bash
|
||||
deno run -A index.mjs
|
||||
```
|
||||
|
||||
You will need a localhost Postgres server running.
|
||||
Binary file not shown.
@@ -1,47 +0,0 @@
|
||||
const isBun = typeof globalThis?.Bun?.sql !== "undefined";
|
||||
import postgres from "postgres";
|
||||
const sql = isBun ? Bun.sql : postgres;
|
||||
|
||||
// Create the table if it doesn't exist
|
||||
await sql`
|
||||
CREATE TABLE IF NOT EXISTS "users_bun_bench" (
|
||||
id SERIAL PRIMARY KEY,
|
||||
first_name TEXT NOT NULL,
|
||||
last_name TEXT NOT NULL,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
dob TEXT NOT NULL
|
||||
)
|
||||
`;
|
||||
|
||||
// Check if users already exist
|
||||
const existingUsers = await sql`SELECT COUNT(*) as count FROM "users_bun_bench"`;
|
||||
|
||||
if (+(existingUsers?.[0]?.count ?? existingUsers?.count) < 100) {
|
||||
// Generate 100 users if none exist
|
||||
const users = Array.from({ length: 100 }, (_, i) => ({
|
||||
first_name: `FirstName${i}`,
|
||||
last_name: `LastName${i}`,
|
||||
email: `user${i}@example.com`,
|
||||
dob: new Date(1970 + Math.floor(Math.random() * 30), Math.floor(Math.random() * 12), Math.floor(Math.random() * 28))
|
||||
.toISOString()
|
||||
.split("T")[0],
|
||||
}));
|
||||
|
||||
// Insert all users
|
||||
await sql`
|
||||
INSERT INTO users_bun_bench (first_name, last_name, email, dob) ${sql(users)}
|
||||
`;
|
||||
}
|
||||
|
||||
const type = isBun ? "Bun.sql" : "postgres";
|
||||
console.time(type);
|
||||
let promises = [];
|
||||
for (let i = 0; i < 100_000; i++) {
|
||||
promises.push(sql`SELECT * FROM "users_bun_bench" LIMIT 100`);
|
||||
if (i % 100 === 0 && promises.length > 1) {
|
||||
await Promise.all(promises);
|
||||
promises.length = 0;
|
||||
}
|
||||
}
|
||||
await Promise.all(promises);
|
||||
console.timeEnd(type);
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "postgres",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"postgres": "^3.4.5"
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
// Enable latest features
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleDetection": "force",
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "react-hello-world",
|
||||
"dependencies": {
|
||||
"react": "next",
|
||||
"react-dom": "next",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
|
||||
|
||||
"react": ["react@18.3.0-next-b72ed698f-20230303", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-l6RbwXa9Peerh9pQEq62DDypxSQfavbybY0wV1vwZ63X0P5VaaEesZAz1KPpnVvXjTtQaOMQsIPvnQwmaVqzTQ=="],
|
||||
|
||||
"react-dom": ["react-dom@18.3.0-next-b72ed698f-20230303", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "0.24.0-next-b72ed698f-20230303" }, "peerDependencies": { "react": "18.3.0-next-b72ed698f-20230303" } }, "sha512-0Gh/gmTT6H8KxswIQB/8shdTTfs6QIu86nNqZf3Y0RBqIwgTVxRaQVz14/Fw4/Nt81nK/Jt6KT4bx3yvOxZDGQ=="],
|
||||
|
||||
"scheduler": ["scheduler@0.24.0-next-b72ed698f-20230303", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-ct4DMMFbc2kFxCdvbG+i/Jn1S1oqrIFSn2VX/mam+Ya0iuNy+lb8rgT7A+YBUqrQNDaNEqABYI2sOQgqoRxp7w=="],
|
||||
}
|
||||
}
|
||||
BIN
bench/react-hello-world/bun.lockb
Executable file
BIN
bench/react-hello-world/bun.lockb
Executable file
Binary file not shown.
@@ -1,56 +0,0 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "scan",
|
||||
"dependencies": {
|
||||
"esbuild": "^0.14.11",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.14.54", "", { "os": "linux", "cpu": "none" }, "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw=="],
|
||||
|
||||
"esbuild": ["esbuild@0.14.54", "", { "dependencies": { "@esbuild/linux-loong64": "0.14.54", "esbuild-android-64": "0.14.54", "esbuild-android-arm64": "0.14.54", "esbuild-darwin-64": "0.14.54", "esbuild-darwin-arm64": "0.14.54", "esbuild-freebsd-64": "0.14.54", "esbuild-freebsd-arm64": "0.14.54", "esbuild-linux-32": "0.14.54", "esbuild-linux-64": "0.14.54", "esbuild-linux-arm": "0.14.54", "esbuild-linux-arm64": "0.14.54", "esbuild-linux-mips64le": "0.14.54", "esbuild-linux-ppc64le": "0.14.54", "esbuild-linux-riscv64": "0.14.54", "esbuild-linux-s390x": "0.14.54", "esbuild-netbsd-64": "0.14.54", "esbuild-openbsd-64": "0.14.54", "esbuild-sunos-64": "0.14.54", "esbuild-windows-32": "0.14.54", "esbuild-windows-64": "0.14.54", "esbuild-windows-arm64": "0.14.54" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA=="],
|
||||
|
||||
"esbuild-android-64": ["esbuild-android-64@0.14.54", "", { "os": "android", "cpu": "x64" }, "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ=="],
|
||||
|
||||
"esbuild-android-arm64": ["esbuild-android-arm64@0.14.54", "", { "os": "android", "cpu": "arm64" }, "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg=="],
|
||||
|
||||
"esbuild-darwin-64": ["esbuild-darwin-64@0.14.54", "", { "os": "darwin", "cpu": "x64" }, "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug=="],
|
||||
|
||||
"esbuild-darwin-arm64": ["esbuild-darwin-arm64@0.14.54", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw=="],
|
||||
|
||||
"esbuild-freebsd-64": ["esbuild-freebsd-64@0.14.54", "", { "os": "freebsd", "cpu": "x64" }, "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg=="],
|
||||
|
||||
"esbuild-freebsd-arm64": ["esbuild-freebsd-arm64@0.14.54", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q=="],
|
||||
|
||||
"esbuild-linux-32": ["esbuild-linux-32@0.14.54", "", { "os": "linux", "cpu": "ia32" }, "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw=="],
|
||||
|
||||
"esbuild-linux-64": ["esbuild-linux-64@0.14.54", "", { "os": "linux", "cpu": "x64" }, "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg=="],
|
||||
|
||||
"esbuild-linux-arm": ["esbuild-linux-arm@0.14.54", "", { "os": "linux", "cpu": "arm" }, "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw=="],
|
||||
|
||||
"esbuild-linux-arm64": ["esbuild-linux-arm64@0.14.54", "", { "os": "linux", "cpu": "arm64" }, "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig=="],
|
||||
|
||||
"esbuild-linux-mips64le": ["esbuild-linux-mips64le@0.14.54", "", { "os": "linux", "cpu": "none" }, "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw=="],
|
||||
|
||||
"esbuild-linux-ppc64le": ["esbuild-linux-ppc64le@0.14.54", "", { "os": "linux", "cpu": "ppc64" }, "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ=="],
|
||||
|
||||
"esbuild-linux-riscv64": ["esbuild-linux-riscv64@0.14.54", "", { "os": "linux", "cpu": "none" }, "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg=="],
|
||||
|
||||
"esbuild-linux-s390x": ["esbuild-linux-s390x@0.14.54", "", { "os": "linux", "cpu": "s390x" }, "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA=="],
|
||||
|
||||
"esbuild-netbsd-64": ["esbuild-netbsd-64@0.14.54", "", { "os": "none", "cpu": "x64" }, "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w=="],
|
||||
|
||||
"esbuild-openbsd-64": ["esbuild-openbsd-64@0.14.54", "", { "os": "openbsd", "cpu": "x64" }, "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw=="],
|
||||
|
||||
"esbuild-sunos-64": ["esbuild-sunos-64@0.14.54", "", { "os": "sunos", "cpu": "x64" }, "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw=="],
|
||||
|
||||
"esbuild-windows-32": ["esbuild-windows-32@0.14.54", "", { "os": "win32", "cpu": "ia32" }, "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w=="],
|
||||
|
||||
"esbuild-windows-64": ["esbuild-windows-64@0.14.54", "", { "os": "win32", "cpu": "x64" }, "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ=="],
|
||||
|
||||
"esbuild-windows-arm64": ["esbuild-windows-arm64@0.14.54", "", { "os": "win32", "cpu": "arm64" }, "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg=="],
|
||||
}
|
||||
}
|
||||
BIN
bench/scanner/bun.lockb
Executable file
BIN
bench/scanner/bun.lockb
Executable file
Binary file not shown.
@@ -25,10 +25,6 @@ bench("Buffer.from('short string')", () => {
|
||||
return Buffer.from("short string");
|
||||
});
|
||||
|
||||
bench("new Buffer('short string')", () => {
|
||||
return new Buffer("short string");
|
||||
});
|
||||
|
||||
const loooong = "long string".repeat(9999).split("").join(" ");
|
||||
bench("Buffer.byteLength('long string'.repeat(9999))", () => {
|
||||
return Buffer.byteLength(loooong);
|
||||
@@ -39,19 +35,11 @@ bench("Buffer.from(ArrayBuffer(100))", () => {
|
||||
return Buffer.from(hundred);
|
||||
});
|
||||
|
||||
bench("new Buffer(ArrayBuffer(100))", () => {
|
||||
return new Buffer(hundred);
|
||||
});
|
||||
|
||||
var hundredArray = new Uint8Array(100);
|
||||
bench("Buffer.from(Uint8Array(100))", () => {
|
||||
return Buffer.from(hundredArray);
|
||||
});
|
||||
|
||||
bench("new Buffer(Uint8Array(100))", () => {
|
||||
return new Buffer(hundredArray);
|
||||
});
|
||||
|
||||
var empty = new Uint8Array(0);
|
||||
bench("Buffer.from(Uint8Array(0))", () => {
|
||||
return Buffer.from(empty);
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import { Buffer } from "node:buffer";
|
||||
import { bench, run } from "../runner.mjs";
|
||||
|
||||
const variations = [
|
||||
["latin1", "hello world"],
|
||||
["utf16", "hello emoji 🤔"],
|
||||
];
|
||||
|
||||
for (const [label, string] of variations) {
|
||||
const big = Buffer.alloc(1000000, string).toString();
|
||||
const small = Buffer.from(string).toString();
|
||||
const substring = big.slice(0, big.length - 2);
|
||||
|
||||
bench(`${substring.length}`, () => {
|
||||
return Buffer.byteLength(substring, "utf8");
|
||||
});
|
||||
|
||||
bench(`${small.length}`, () => {
|
||||
return Buffer.byteLength(small);
|
||||
});
|
||||
|
||||
bench(`${big.length}`, () => {
|
||||
return Buffer.byteLength(big);
|
||||
});
|
||||
}
|
||||
|
||||
await run();
|
||||
@@ -1,97 +0,0 @@
|
||||
import { bench, run } from "../runner.mjs";
|
||||
|
||||
// Can be strings or buffers.
|
||||
const shortStr = Buffer.from("abcd1234"); // 8 chars
|
||||
const longStr = Buffer.alloc(128 * 1024, "xABcDpQrStUvWxYz=-1]23]12312312][3123][123][");
|
||||
|
||||
// Short string benchmarks
|
||||
|
||||
bench("wyhash (short)", () => {
|
||||
Bun.hash.wyhash(shortStr);
|
||||
});
|
||||
|
||||
bench("adler32 (short)", () => {
|
||||
Bun.hash.adler32(shortStr);
|
||||
});
|
||||
|
||||
bench("crc32 (short)", () => {
|
||||
Bun.hash.crc32(shortStr);
|
||||
});
|
||||
|
||||
bench("cityHash32 (short)", () => {
|
||||
Bun.hash.cityHash32(shortStr);
|
||||
});
|
||||
|
||||
bench("cityHash64 (short)", () => {
|
||||
Bun.hash.cityHash64(shortStr);
|
||||
});
|
||||
|
||||
bench("xxHash32 (short)", () => {
|
||||
Bun.hash.xxHash32(shortStr);
|
||||
});
|
||||
|
||||
bench("xxHash64 (short)", () => {
|
||||
Bun.hash.xxHash64(shortStr);
|
||||
});
|
||||
|
||||
bench("xxHash3 (short)", () => {
|
||||
Bun.hash.xxHash3(shortStr);
|
||||
});
|
||||
|
||||
bench("murmur32v3 (short)", () => {
|
||||
Bun.hash.murmur32v3(shortStr);
|
||||
});
|
||||
|
||||
bench("murmur32v2 (short)", () => {
|
||||
Bun.hash.murmur32v2(shortStr);
|
||||
});
|
||||
|
||||
bench("murmur64v2 (short)", () => {
|
||||
Bun.hash.murmur64v2(shortStr);
|
||||
});
|
||||
|
||||
bench("wyhash (128 KB)", () => {
|
||||
Bun.hash.wyhash(longStr);
|
||||
});
|
||||
|
||||
bench("adler32 (128 KB)", () => {
|
||||
Bun.hash.adler32(longStr);
|
||||
});
|
||||
|
||||
bench("crc32 (128 KB)", () => {
|
||||
Bun.hash.crc32(longStr);
|
||||
});
|
||||
|
||||
bench("cityHash32 (128 KB)", () => {
|
||||
Bun.hash.cityHash32(longStr);
|
||||
});
|
||||
|
||||
bench("cityHash64 (128 KB)", () => {
|
||||
Bun.hash.cityHash64(longStr);
|
||||
});
|
||||
|
||||
bench("xxHash32 (128 KB)", () => {
|
||||
Bun.hash.xxHash32(longStr);
|
||||
});
|
||||
|
||||
bench("xxHash64 (128 KB)", () => {
|
||||
Bun.hash.xxHash64(longStr);
|
||||
});
|
||||
|
||||
bench("xxHash3 (128 KB)", () => {
|
||||
Bun.hash.xxHash3(longStr);
|
||||
});
|
||||
|
||||
bench("murmur32v3 (128 KB)", () => {
|
||||
Bun.hash.murmur32v3(longStr);
|
||||
});
|
||||
|
||||
bench("murmur32v2 (128 KB)", () => {
|
||||
Bun.hash.murmur32v2(longStr);
|
||||
});
|
||||
|
||||
bench("murmur64v2 (128 KB)", () => {
|
||||
Bun.hash.murmur64v2(longStr);
|
||||
});
|
||||
|
||||
run();
|
||||
@@ -1,14 +1,20 @@
|
||||
import { noOpForTesting as noop } from "bun:internal-for-testing";
|
||||
import { bench, run } from "../runner.mjs";
|
||||
|
||||
// These are no-op C++ functions that are exported to JS.
|
||||
const lazy = globalThis[Symbol.for("Bun.lazy")];
|
||||
const noop = lazy("noop");
|
||||
const fn = noop.function;
|
||||
const regular = noop.functionRegular;
|
||||
const callback = noop.callback;
|
||||
|
||||
bench("C++ callback into JS", () => {
|
||||
callback(() => {});
|
||||
});
|
||||
|
||||
bench("C++ fn regular", () => {
|
||||
regular();
|
||||
});
|
||||
|
||||
bench("C++ fn", () => {
|
||||
fn();
|
||||
});
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import { bench, run } from "../runner.mjs";
|
||||
import { brotliCompress, brotliDecompress, createBrotliCompress, createBrotliDecompress } from "node:zlib";
|
||||
import { promisify } from "node:util";
|
||||
import { pipeline } from "node:stream/promises";
|
||||
import { Readable } from "node:stream";
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
const brotliCompressAsync = promisify(brotliCompress);
|
||||
const brotliDecompressAsync = promisify(brotliDecompress);
|
||||
|
||||
const testData =
|
||||
process.argv.length > 2
|
||||
? readFileSync(process.argv[2])
|
||||
: Buffer.alloc(1024 * 1024 * 16, "abcdefghijklmnopqrstuvwxyz");
|
||||
let compressed;
|
||||
|
||||
bench("brotli compress", async () => {
|
||||
compressed = await brotliCompressAsync(testData);
|
||||
});
|
||||
|
||||
bench("brotli decompress", async () => {
|
||||
await brotliDecompressAsync(compressed);
|
||||
});
|
||||
|
||||
bench("brotli compress stream", async () => {
|
||||
const source = Readable.from([testData]);
|
||||
const compress = createBrotliCompress();
|
||||
await pipeline(source, compress);
|
||||
});
|
||||
|
||||
bench("brotli decompress stream", async () => {
|
||||
const source = Readable.from([compressed]);
|
||||
const decompress = createBrotliDecompress();
|
||||
await pipeline(source, decompress);
|
||||
});
|
||||
|
||||
await run();
|
||||
@@ -10,6 +10,7 @@ bench("new URLSearchParams(obj)", () => {
|
||||
"Content-Length": "123",
|
||||
"User-Agent": "node-fetch/1.0",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Content-Length": "0",
|
||||
"Content-Range": "bytes 0-9/10",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
import { bench, run } from "../runner.mjs";
|
||||
import zlib from "node:zlib";
|
||||
import { promisify } from "node:util";
|
||||
|
||||
const deflate = promisify(zlib.deflate);
|
||||
const inflate = promisify(zlib.inflate);
|
||||
|
||||
const short = "Hello World!";
|
||||
const long = "Hello World!".repeat(1024);
|
||||
const veryLong = "Hello World!".repeat(10240);
|
||||
|
||||
// Pre-compress some data for decompression tests
|
||||
const shortBuf = Buffer.from(short);
|
||||
const longBuf = Buffer.from(long);
|
||||
const veryLongBuf = Buffer.from(veryLong);
|
||||
|
||||
let [shortCompressed, longCompressed, veryLongCompressed] = await Promise.all([
|
||||
deflate(shortBuf, { level: 6 }),
|
||||
deflate(longBuf, { level: 6 }),
|
||||
deflate(veryLongBuf, { level: 6 }),
|
||||
]);
|
||||
|
||||
const format = new Intl.NumberFormat("en-US", { notation: "compact", unit: "byte" });
|
||||
// Compression tests at different levels
|
||||
bench(`deflate ${format.format(short.length)}B (level 1)`, async () => {
|
||||
await deflate(shortBuf, { level: 1 });
|
||||
});
|
||||
|
||||
bench(`deflate ${format.format(short.length)} (level 6)`, async () => {
|
||||
await deflate(shortBuf, { level: 6 });
|
||||
});
|
||||
|
||||
bench(`deflate ${format.format(long.length)} (level 1)`, async () => {
|
||||
await deflate(longBuf, { level: 1 });
|
||||
});
|
||||
|
||||
bench(`deflate ${format.format(long.length)} (level 6)`, async () => {
|
||||
await deflate(longBuf, { level: 6 });
|
||||
});
|
||||
|
||||
bench(`deflate ${format.format(veryLong.length)} (level 1)`, async () => {
|
||||
await deflate(veryLongBuf, { level: 1 });
|
||||
});
|
||||
|
||||
bench(`deflate ${format.format(veryLong.length)} (level 6)`, async () => {
|
||||
await deflate(veryLongBuf, { level: 6 });
|
||||
});
|
||||
|
||||
// Decompression tests
|
||||
bench(`inflate ${format.format(short.length)}`, async () => {
|
||||
await inflate(shortCompressed);
|
||||
});
|
||||
|
||||
bench(`inflate ${format.format(long.length)}`, async () => {
|
||||
await inflate(longCompressed);
|
||||
});
|
||||
|
||||
bench(`inflate ${format.format(veryLong.length)}`, async () => {
|
||||
await inflate(veryLongCompressed);
|
||||
});
|
||||
|
||||
await run();
|
||||
@@ -1,92 +0,0 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "bench",
|
||||
"dependencies": {
|
||||
"better-sqlite3": "8.5.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||
|
||||
"better-sqlite3": ["better-sqlite3@8.5.0", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.0" } }, "sha512-vbPcv/Hx5WYdyNg/NbcfyaBZyv9s/NVbxb7yCeC5Bq1pVocNxeL2tZmSu3Rlm4IEOTjYdGyzWQgyx0OSdORBzw=="],
|
||||
|
||||
"bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
|
||||
|
||||
"bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
|
||||
|
||||
"buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
|
||||
|
||||
"chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
|
||||
|
||||
"decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
|
||||
|
||||
"deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.0.1", "", {}, "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w=="],
|
||||
|
||||
"end-of-stream": ["end-of-stream@1.4.4", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q=="],
|
||||
|
||||
"expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="],
|
||||
|
||||
"file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
|
||||
|
||||
"fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
|
||||
|
||||
"github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="],
|
||||
|
||||
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||
|
||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
|
||||
"ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
|
||||
|
||||
"lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
|
||||
|
||||
"mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
|
||||
|
||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
|
||||
"mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="],
|
||||
|
||||
"napi-build-utils": ["napi-build-utils@1.0.2", "", {}, "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="],
|
||||
|
||||
"node-abi": ["node-abi@3.35.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-jAlSOFR1Bls963NmFwxeQkNTzqjUF0NThm8Le7eRIRGzFUVJuMOFZDLv5Y30W/Oaw+KEebEJLAigwO9gQHoEmw=="],
|
||||
|
||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"prebuild-install": ["prebuild-install@7.1.1", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^1.0.1", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw=="],
|
||||
|
||||
"pump": ["pump@3.0.0", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww=="],
|
||||
|
||||
"rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
|
||||
|
||||
"readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
||||
|
||||
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
||||
|
||||
"semver": ["semver@7.4.0", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw=="],
|
||||
|
||||
"simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="],
|
||||
|
||||
"simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="],
|
||||
|
||||
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
||||
|
||||
"strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
|
||||
|
||||
"tar-fs": ["tar-fs@2.1.1", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng=="],
|
||||
|
||||
"tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
|
||||
|
||||
"tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
|
||||
|
||||
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
}
|
||||
}
|
||||
BIN
bench/sqlite/bun.lockb
Executable file
BIN
bench/sqlite/bun.lockb
Executable file
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
import { Database } from "https://deno.land/x/sqlite3@0.12.0/mod.ts";
|
||||
import { Database } from "https://deno.land/x/sqlite3@0.11.1/mod.ts";
|
||||
import { bench, run } from "../runner.mjs";
|
||||
|
||||
const db = new Database("./src/northwind.sqlite");
|
||||
|
||||
82
bench/sqlite/deno.lock
generated
82
bench/sqlite/deno.lock
generated
@@ -1,82 +0,0 @@
|
||||
{
|
||||
"version": "4",
|
||||
"specifiers": {
|
||||
"jsr:@denosaurs/plug@1": "1.0.6",
|
||||
"jsr:@std/assert@0.217": "0.217.0",
|
||||
"jsr:@std/assert@0.221": "0.221.0",
|
||||
"jsr:@std/encoding@0.221": "0.221.0",
|
||||
"jsr:@std/fmt@0.221": "0.221.0",
|
||||
"jsr:@std/fs@0.221": "0.221.0",
|
||||
"jsr:@std/path@0.217": "0.217.0",
|
||||
"jsr:@std/path@0.221": "0.221.0"
|
||||
},
|
||||
"jsr": {
|
||||
"@denosaurs/plug@1.0.6": {
|
||||
"integrity": "6cf5b9daba7799837b9ffbe89f3450510f588fafef8115ddab1ff0be9cb7c1a7",
|
||||
"dependencies": [
|
||||
"jsr:@std/encoding",
|
||||
"jsr:@std/fmt",
|
||||
"jsr:@std/fs",
|
||||
"jsr:@std/path@0.221"
|
||||
]
|
||||
},
|
||||
"@std/assert@0.217.0": {
|
||||
"integrity": "c98e279362ca6982d5285c3b89517b757c1e3477ee9f14eb2fdf80a45aaa9642"
|
||||
},
|
||||
"@std/assert@0.221.0": {
|
||||
"integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a"
|
||||
},
|
||||
"@std/encoding@0.221.0": {
|
||||
"integrity": "d1dd76ef0dc5d14088411e6dc1dede53bf8308c95d1537df1214c97137208e45"
|
||||
},
|
||||
"@std/fmt@0.221.0": {
|
||||
"integrity": "379fed69bdd9731110f26b9085aeb740606b20428ce6af31ef6bd45ef8efa62a"
|
||||
},
|
||||
"@std/fs@0.221.0": {
|
||||
"integrity": "028044450299de8ed5a716ade4e6d524399f035513b85913794f4e81f07da286",
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@0.221",
|
||||
"jsr:@std/path@0.221"
|
||||
]
|
||||
},
|
||||
"@std/path@0.217.0": {
|
||||
"integrity": "1217cc25534bca9a2f672d7fe7c6f356e4027df400c0e85c0ef3e4343bc67d11",
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@0.217"
|
||||
]
|
||||
},
|
||||
"@std/path@0.221.0": {
|
||||
"integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095",
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@0.221"
|
||||
]
|
||||
}
|
||||
},
|
||||
"remote": {
|
||||
"https://deno.land/x/sqlite3@0.11.1/deno.json": "77126f50d0efce1375173fae94d4df7f732cd25f05d8aa74f8ff801ef4d85caf",
|
||||
"https://deno.land/x/sqlite3@0.11.1/deps.ts": "d2f23a4489d27ed7ba1f601b86a85ff488a87603e4be7a15f3ea15154fc288ec",
|
||||
"https://deno.land/x/sqlite3@0.11.1/mod.ts": "3169f246c0eddd6ed82862758f4109f167b7ba5538236240fbb26a129f1bc16c",
|
||||
"https://deno.land/x/sqlite3@0.11.1/src/blob.ts": "3681353b3c97bc43f9b02f8d1c3269c0dc4eb9cb5d3af16c7ce4d1e1ec7507c4",
|
||||
"https://deno.land/x/sqlite3@0.11.1/src/constants.ts": "85fd27aa6e199093f25f5f437052e16fd0e0870b96ca9b24a98e04ddc8b7d006",
|
||||
"https://deno.land/x/sqlite3@0.11.1/src/database.ts": "063281b9b4340c781ba611cb5fef7ab0fc885cb87ed4c8ec123fd772e0da5f8b",
|
||||
"https://deno.land/x/sqlite3@0.11.1/src/ffi.ts": "6648dc15f10312df9d2fc8e6e2be230d82a552f28b8f77d03f32bbfba9198888",
|
||||
"https://deno.land/x/sqlite3@0.11.1/src/statement.ts": "5fe86e1a0136a259c055a03988e74490d9d131c058b4c1a18385a6770cd47e2a",
|
||||
"https://deno.land/x/sqlite3@0.11.1/src/util.ts": "c6604183d2ec5fb17fa0a018572ed5f2317b319dbd7bf48d88a5d06ff25b2cc3",
|
||||
"https://deno.land/x/sqlite3@0.12.0/deno.json": "b03d6de05f953886662ea987212539af8456a91352684c84af2188520449d42a",
|
||||
"https://deno.land/x/sqlite3@0.12.0/deps.ts": "d2f23a4489d27ed7ba1f601b86a85ff488a87603e4be7a15f3ea15154fc288ec",
|
||||
"https://deno.land/x/sqlite3@0.12.0/mod.ts": "3169f246c0eddd6ed82862758f4109f167b7ba5538236240fbb26a129f1bc16c",
|
||||
"https://deno.land/x/sqlite3@0.12.0/src/blob.ts": "330886fae9714e4a612786f44d8117d65f91e778cf3f40de59b34879fc7ca9ab",
|
||||
"https://deno.land/x/sqlite3@0.12.0/src/constants.ts": "85fd27aa6e199093f25f5f437052e16fd0e0870b96ca9b24a98e04ddc8b7d006",
|
||||
"https://deno.land/x/sqlite3@0.12.0/src/database.ts": "4d380d7f0e5a2cf74635a9fcd2b4e27373533f2816cde5357067e51fd22ad8d0",
|
||||
"https://deno.land/x/sqlite3@0.12.0/src/ffi.ts": "795b598eeae4d12f182e7bcdab524b74b0f01d6deae7f4d8ce63f25c06a46154",
|
||||
"https://deno.land/x/sqlite3@0.12.0/src/statement.ts": "e8ccde898aef47c7a2514953aca5359a44a285bc3dc0de5819d66f891f477be1",
|
||||
"https://deno.land/x/sqlite3@0.12.0/src/util.ts": "c6604183d2ec5fb17fa0a018572ed5f2317b319dbd7bf48d88a5d06ff25b2cc3"
|
||||
},
|
||||
"workspace": {
|
||||
"packageJson": {
|
||||
"dependencies": [
|
||||
"npm:better-sqlite3@8.5.0"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"lockfileVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "websocket-server",
|
||||
"dependencies": {
|
||||
"bufferutil": "4.0.7",
|
||||
"utf-8-validate": "6.0.3",
|
||||
"ws": "8.13.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"bufferutil": ["bufferutil@4.0.7", "", { "dependencies": { "node-gyp-build": "^4.3.0" } }, "sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw=="],
|
||||
|
||||
"node-gyp-build": ["node-gyp-build@4.6.0", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ=="],
|
||||
|
||||
"utf-8-validate": ["utf-8-validate@6.0.3", "", { "dependencies": { "node-gyp-build": "^4.3.0" } }, "sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA=="],
|
||||
|
||||
"ws": ["ws@8.13.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["utf-8-validate"] }, "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA=="],
|
||||
}
|
||||
}
|
||||
BIN
bench/websocket-server/bun.lockb
Executable file
BIN
bench/websocket-server/bun.lockb
Executable file
Binary file not shown.
98
build.zig
98
build.zig
@@ -152,7 +152,6 @@ pub fn getCpuModel(os: OperatingSystem, arch: Arch) ?Target.Query.CpuModel {
|
||||
|
||||
pub fn build(b: *Build) !void {
|
||||
std.log.info("zig compiler v{s}", .{builtin.zig_version_string});
|
||||
checked_file_exists = std.AutoHashMap(u64, void).init(b.allocator);
|
||||
|
||||
b.zig_lib_dir = b.zig_lib_dir orelse b.path("vendor/zig/lib");
|
||||
|
||||
@@ -201,10 +200,7 @@ pub fn build(b: *Build) !void {
|
||||
b.option([]const u8, "codegen_path", "Set the generated code directory") orelse
|
||||
"build/debug/codegen",
|
||||
);
|
||||
const codegen_embed = b.option(bool, "codegen_embed", "If codegen files should be embedded in the binary") orelse switch (b.release_mode) {
|
||||
.off => false,
|
||||
else => true,
|
||||
};
|
||||
const codegen_embed = b.option(bool, "codegen_embed", "If codegen files should be embedded in the binary") orelse false;
|
||||
|
||||
const bun_version = b.option([]const u8, "version", "Value of `Bun.version`") orelse "0.0.0";
|
||||
|
||||
@@ -332,12 +328,6 @@ pub fn build(b: *Build) !void {
|
||||
});
|
||||
}
|
||||
|
||||
// zig build translate-c-headers
|
||||
{
|
||||
const step = b.step("translate-c", "Copy generated translated-c-headers.zig to zig-out");
|
||||
step.dependOn(&b.addInstallFile(getTranslateC(b, b.host, .Debug).getOutput(), "translated-c-headers.zig").step);
|
||||
}
|
||||
|
||||
// zig build enum-extractor
|
||||
{
|
||||
// const step = b.step("enum-extractor", "Extract enum definitions (invoked by a code generator)");
|
||||
@@ -390,25 +380,6 @@ pub fn addMultiCheck(
|
||||
}
|
||||
}
|
||||
|
||||
fn getTranslateC(b: *Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *Step.TranslateC {
|
||||
const translate_c = b.addTranslateC(.{
|
||||
.root_source_file = b.path("src/c-headers-for-zig.h"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
});
|
||||
inline for ([_](struct { []const u8, bool }){
|
||||
.{ "WINDOWS", translate_c.target.result.os.tag == .windows },
|
||||
.{ "POSIX", translate_c.target.result.os.tag != .windows },
|
||||
.{ "LINUX", translate_c.target.result.os.tag == .linux },
|
||||
.{ "DARWIN", translate_c.target.result.os.tag.isDarwin() },
|
||||
}) |entry| {
|
||||
const str, const value = entry;
|
||||
translate_c.defineCMacroRaw(b.fmt("{s}={d}", .{ str, @intFromBool(value) }));
|
||||
}
|
||||
return translate_c;
|
||||
}
|
||||
|
||||
pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile {
|
||||
const obj = b.addObject(.{
|
||||
.name = if (opts.optimize == .Debug) "bun-debug" else "bun",
|
||||
@@ -457,8 +428,13 @@ pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile {
|
||||
addInternalPackages(b, obj, opts);
|
||||
obj.root_module.addImport("build_options", opts.buildOptionsModule(b));
|
||||
|
||||
const translate_c = getTranslateC(b, opts.target, opts.optimize);
|
||||
obj.root_module.addImport("translated-c-headers", translate_c.createModule());
|
||||
const translate_plugin_api = b.addTranslateC(.{
|
||||
.root_source_file = b.path("./packages/bun-native-bundler-plugin-api/bundler_plugin.h"),
|
||||
.target = opts.target,
|
||||
.optimize = opts.optimize,
|
||||
.link_libc = true,
|
||||
});
|
||||
obj.root_module.addImport("bun-native-bundler-plugin-api", translate_plugin_api.createModule());
|
||||
|
||||
return obj;
|
||||
}
|
||||
@@ -482,15 +458,9 @@ pub fn addInstallObjectFile(
|
||||
}, b.fmt("{s}.o", .{name})).step;
|
||||
}
|
||||
|
||||
var checked_file_exists: std.AutoHashMap(u64, void) = undefined;
|
||||
fn exists(path: []const u8) bool {
|
||||
const entry = checked_file_exists.getOrPut(std.hash.Wyhash.hash(0, path)) catch unreachable;
|
||||
if (entry.found_existing) {
|
||||
// It would've panicked.
|
||||
return true;
|
||||
}
|
||||
|
||||
std.fs.accessAbsolute(path, .{ .mode = .read_only }) catch return false;
|
||||
const file = std.fs.openFileAbsolute(path, .{ .mode = .read_only }) catch return false;
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -532,36 +502,36 @@ fn addInternalPackages(b: *Build, obj: *Compile, opts: *BunBuildOptions) void {
|
||||
.{ .file = "ZigGeneratedClasses.zig", .import = "ZigGeneratedClasses" },
|
||||
.{ .file = "ResolvedSourceTag.zig", .import = "ResolvedSourceTag" },
|
||||
.{ .file = "ErrorCode.zig", .import = "ErrorCode" },
|
||||
.{ .file = "runtime.out.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "runtime.out.js" },
|
||||
.{ .file = "bake.client.js", .import = "bake-codegen/bake.client.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "bake.error.js", .import = "bake-codegen/bake.error.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "bake.server.js", .import = "bake-codegen/bake.server.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "bun-error/index.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "bun-error/bun-error.css", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "fallback-decoder.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/assert.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/buffer.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/console.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/constants.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/crypto.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/domain.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/events.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/http.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/https.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/net.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/os.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/path.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/process.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/punycode.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/querystring.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/stream.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/string_decoder.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/sys.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/timers.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/tty.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/url.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/util.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/zlib.js", .enable = opts.shouldEmbedCode() },
|
||||
.{ .file = "node-fallbacks/assert.js" },
|
||||
.{ .file = "node-fallbacks/buffer.js" },
|
||||
.{ .file = "node-fallbacks/console.js" },
|
||||
.{ .file = "node-fallbacks/constants.js" },
|
||||
.{ .file = "node-fallbacks/crypto.js" },
|
||||
.{ .file = "node-fallbacks/domain.js" },
|
||||
.{ .file = "node-fallbacks/events.js" },
|
||||
.{ .file = "node-fallbacks/http.js" },
|
||||
.{ .file = "node-fallbacks/https.js" },
|
||||
.{ .file = "node-fallbacks/net.js" },
|
||||
.{ .file = "node-fallbacks/os.js" },
|
||||
.{ .file = "node-fallbacks/path.js" },
|
||||
.{ .file = "node-fallbacks/process.js" },
|
||||
.{ .file = "node-fallbacks/punycode.js" },
|
||||
.{ .file = "node-fallbacks/querystring.js" },
|
||||
.{ .file = "node-fallbacks/stream.js" },
|
||||
.{ .file = "node-fallbacks/string_decoder.js" },
|
||||
.{ .file = "node-fallbacks/sys.js" },
|
||||
.{ .file = "node-fallbacks/timers.js" },
|
||||
.{ .file = "node-fallbacks/tty.js" },
|
||||
.{ .file = "node-fallbacks/url.js" },
|
||||
.{ .file = "node-fallbacks/util.js" },
|
||||
.{ .file = "node-fallbacks/zlib.js" },
|
||||
}) |entry| {
|
||||
if (!@hasField(@TypeOf(entry), "enable") or entry.enable) {
|
||||
const path = b.pathJoin(&.{ opts.codegen_path, entry.file });
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# FIXME: move this back to test/js/node
|
||||
# https://github.com/oven-sh/bun/issues/16289
|
||||
[test]
|
||||
preload = ["./test/js/node/harness.ts", "./test/preload.ts"]
|
||||
@@ -228,7 +228,6 @@ set(BUN_ZIG_GENERATED_CLASSES_OUTPUTS
|
||||
${CODEGEN_PATH}/ZigGeneratedClasses+DOMIsoSubspaces.h
|
||||
${CODEGEN_PATH}/ZigGeneratedClasses+lazyStructureImpl.h
|
||||
${CODEGEN_PATH}/ZigGeneratedClasses.zig
|
||||
${CODEGEN_PATH}/ZigGeneratedClasses.lut.txt
|
||||
)
|
||||
|
||||
register_command(
|
||||
@@ -407,7 +406,6 @@ set(BUN_OBJECT_LUT_SOURCES
|
||||
${CWD}/src/bun.js/bindings/ProcessBindingConstants.cpp
|
||||
${CWD}/src/bun.js/bindings/ProcessBindingNatives.cpp
|
||||
${CWD}/src/bun.js/modules/NodeModuleModule.cpp
|
||||
${CODEGEN_PATH}/ZigGeneratedClasses.lut.txt
|
||||
)
|
||||
|
||||
set(BUN_OBJECT_LUT_OUTPUTS
|
||||
@@ -418,7 +416,6 @@ set(BUN_OBJECT_LUT_OUTPUTS
|
||||
${CODEGEN_PATH}/ProcessBindingConstants.lut.h
|
||||
${CODEGEN_PATH}/ProcessBindingNatives.lut.h
|
||||
${CODEGEN_PATH}/NodeModuleModule.lut.h
|
||||
${CODEGEN_PATH}/ZigGeneratedClasses.lut.h
|
||||
)
|
||||
|
||||
macro(WEBKIT_ADD_SOURCE_DEPENDENCIES _source _deps)
|
||||
@@ -450,8 +447,6 @@ foreach(i RANGE 0 ${BUN_OBJECT_LUT_SOURCES_MAX_INDEX})
|
||||
bun-codegen-lut-${filename}
|
||||
COMMENT
|
||||
"Generating ${filename}.lut.h"
|
||||
DEPENDS
|
||||
${BUN_OBJECT_LUT_SOURCE}
|
||||
COMMAND
|
||||
${BUN_EXECUTABLE}
|
||||
run
|
||||
@@ -483,8 +478,6 @@ WEBKIT_ADD_SOURCE_DEPENDENCIES(
|
||||
${CODEGEN_PATH}/ZigGlobalObject.lut.h
|
||||
)
|
||||
|
||||
|
||||
|
||||
WEBKIT_ADD_SOURCE_DEPENDENCIES(
|
||||
${CWD}/src/bun.js/bindings/InternalModuleRegistry.cpp
|
||||
${CODEGEN_PATH}/InternalModuleRegistryConstants.h
|
||||
@@ -607,8 +600,7 @@ file(GLOB BUN_C_SOURCES ${CONFIGURE_DEPENDS}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND BUN_CXX_SOURCES ${CWD}/src/bun.js/bindings/windows/rescle.cpp)
|
||||
list(APPEND BUN_CXX_SOURCES ${CWD}/src/bun.js/bindings/windows/rescle-binding.cpp)
|
||||
list(APPEND BUN_C_SOURCES ${CWD}/src/bun.js/bindings/windows/musl-memmem.c)
|
||||
endif()
|
||||
|
||||
register_repository(
|
||||
@@ -658,19 +650,11 @@ if(WIN32)
|
||||
set(Bun_VERSION_WITH_TAG ${VERSION})
|
||||
endif()
|
||||
set(BUN_ICO_PATH ${CWD}/src/bun.ico)
|
||||
configure_file(${CWD}/src/bun.ico ${CODEGEN_PATH}/bun.ico COPYONLY)
|
||||
configure_file(
|
||||
${CWD}/src/windows-app-info.rc
|
||||
${CODEGEN_PATH}/windows-app-info.rc
|
||||
@ONLY
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${CODEGEN_PATH}/windows-app-info.res
|
||||
COMMAND rc.exe /fo ${CODEGEN_PATH}/windows-app-info.res ${CODEGEN_PATH}/windows-app-info.rc
|
||||
DEPENDS ${CODEGEN_PATH}/windows-app-info.rc ${CODEGEN_PATH}/bun.ico
|
||||
COMMENT "Adding Windows resource file ${CODEGEN_PATH}/windows-app-info.res with ico in ${CODEGEN_PATH}/bun.ico"
|
||||
)
|
||||
set(WINDOWS_RESOURCES ${CODEGEN_PATH}/windows-app-info.res)
|
||||
list(APPEND BUN_CPP_SOURCES ${CODEGEN_PATH}/windows-app-info.rc)
|
||||
endif()
|
||||
|
||||
# --- Executable ---
|
||||
@@ -678,7 +662,7 @@ endif()
|
||||
set(BUN_CPP_OUTPUT ${BUILD_PATH}/${CMAKE_STATIC_LIBRARY_PREFIX}${bun}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
|
||||
if(BUN_LINK_ONLY)
|
||||
add_executable(${bun} ${BUN_CPP_OUTPUT} ${BUN_ZIG_OUTPUT} ${WINDOWS_RESOURCES})
|
||||
add_executable(${bun} ${BUN_CPP_OUTPUT} ${BUN_ZIG_OUTPUT})
|
||||
set_target_properties(${bun} PROPERTIES LINKER_LANGUAGE CXX)
|
||||
target_link_libraries(${bun} PRIVATE ${BUN_CPP_OUTPUT})
|
||||
elseif(BUN_CPP_ONLY)
|
||||
@@ -696,7 +680,7 @@ elseif(BUN_CPP_ONLY)
|
||||
${BUN_CPP_OUTPUT}
|
||||
)
|
||||
else()
|
||||
add_executable(${bun} ${BUN_CPP_SOURCES} ${WINDOWS_RESOURCES})
|
||||
add_executable(${bun} ${BUN_CPP_SOURCES})
|
||||
target_link_libraries(${bun} PRIVATE ${BUN_ZIG_OUTPUT})
|
||||
endif()
|
||||
|
||||
@@ -866,7 +850,7 @@ endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_options(${bun} PUBLIC
|
||||
/STACK:0x1200000,0x200000
|
||||
/STACK:0x1200000,0x100000
|
||||
/errorlimit:0
|
||||
)
|
||||
if(RELEASE)
|
||||
|
||||
@@ -4,7 +4,7 @@ register_repository(
|
||||
REPOSITORY
|
||||
ebiggers/libdeflate
|
||||
COMMIT
|
||||
733848901289eca058804ca0737f8796875204c8
|
||||
9d624d1d8ba82c690d6d6be1d0a961fc5a983ea4
|
||||
)
|
||||
|
||||
register_cmake_command(
|
||||
|
||||
@@ -46,6 +46,5 @@ if(CI)
|
||||
# FIXME: Does not work on Ubuntu 18.04
|
||||
# setenv(CCACHE_SLOPPINESS "pch_defines,time_macros,locale,clang_index_store,gcno_cwd,include_file_ctime,include_file_mtime")
|
||||
else()
|
||||
setenv(CCACHE_MAXSIZE 100G)
|
||||
setenv(CCACHE_SLOPPINESS "pch_defines,time_macros,locale,random_seed,clang_index_store,gcno_cwd")
|
||||
endif()
|
||||
|
||||
@@ -41,11 +41,11 @@ if(APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND LLVM_PATHS ${HOMEBREW_PREFIX}/opt/llvm/bin)
|
||||
|
||||
if(USE_LLVM_VERSION)
|
||||
list(APPEND LLVM_PATHS ${HOMEBREW_PREFIX}/opt/llvm@${LLVM_VERSION_MAJOR}/bin)
|
||||
endif()
|
||||
|
||||
list(APPEND LLVM_PATHS ${HOMEBREW_PREFIX}/opt/llvm/bin)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
|
||||
@@ -2,15 +2,13 @@ option(WEBKIT_VERSION "The version of WebKit to use")
|
||||
option(WEBKIT_LOCAL "If a local version of WebKit should be used instead of downloading")
|
||||
|
||||
if(NOT WEBKIT_VERSION)
|
||||
set(WEBKIT_VERSION e6cb36cabed465c28c7bcbb28d86e8466ea36e8d)
|
||||
set(WEBKIT_VERSION 58549ddc4d9e7164823fe9d4e86c46c003e46a19)
|
||||
endif()
|
||||
|
||||
string(SUBSTRING ${WEBKIT_VERSION} 0 16 WEBKIT_VERSION_PREFIX)
|
||||
|
||||
if(WEBKIT_LOCAL)
|
||||
set(DEFAULT_WEBKIT_PATH ${VENDOR_PATH}/WebKit/WebKitBuild/${CMAKE_BUILD_TYPE})
|
||||
else()
|
||||
set(DEFAULT_WEBKIT_PATH ${CACHE_PATH}/webkit-${WEBKIT_VERSION_PREFIX})
|
||||
set(DEFAULT_WEBKIT_PATH ${CACHE_PATH}/webkit-${WEBKIT_VERSION})
|
||||
endif()
|
||||
|
||||
option(WEBKIT_PATH "The path to the WebKit directory")
|
||||
@@ -32,8 +30,6 @@ if(WEBKIT_LOCAL)
|
||||
${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders
|
||||
${WEBKIT_PATH}/bmalloc/Headers
|
||||
${WEBKIT_PATH}/WTF/Headers
|
||||
${WEBKIT_PATH}/JavaScriptCore/DerivedSources/inspector
|
||||
${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders/JavaScriptCore
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ _bun_completions() {
|
||||
GLOBAL_OPTIONS[LONG_OPTIONS]="--use --cwd --bunfile --server-bunfile --config --disable-react-fast-refresh --disable-hmr --env-file --extension-order --jsx-factory --jsx-fragment --extension-order --jsx-factory --jsx-fragment --jsx-import-source --jsx-production --jsx-runtime --main-fields --no-summary --version --platform --public-dir --tsconfig-override --define --external --help --inject --loader --origin --port --dump-environment-variables --dump-limits --disable-bun-js";
|
||||
GLOBAL_OPTIONS[SHORT_OPTIONS]="-c -v -d -e -h -i -l -u -p";
|
||||
|
||||
PACKAGE_OPTIONS[ADD_OPTIONS_LONG]="--development --optional --peer";
|
||||
PACKAGE_OPTIONS[ADD_OPTIONS_LONG]="--development --optional";
|
||||
PACKAGE_OPTIONS[ADD_OPTIONS_SHORT]="-d";
|
||||
PACKAGE_OPTIONS[REMOVE_OPTIONS_LONG]="";
|
||||
PACKAGE_OPTIONS[REMOVE_OPTIONS_SHORT]="";
|
||||
|
||||
@@ -33,7 +33,7 @@ function __fish__get_bun_bun_js_files
|
||||
end
|
||||
|
||||
set -l bun_install_boolean_flags yarn production optional development no-save dry-run force no-cache silent verbose global
|
||||
set -l bun_install_boolean_flags_descriptions "Write a yarn.lock file (yarn v1)" "Don't install devDependencies" "Add dependency to optionalDependencies" "Add dependency to devDependencies" "Don't update package.json or save a lockfile" "Don't install anything" "Always request the latest versions from the registry & reinstall all dependencies" "Ignore manifest cache entirely" "Don't output anything" "Excessively verbose logging" "Use global folder"
|
||||
set -l bun_install_boolean_flags_descriptions "Write a yarn.lock file (yarn v1)" "Don't install devDependencies" "Add dependency to optionalDependencies" "Add dependency to devDependencies" "Don't install devDependencies" "Don't install anything" "Always request the latest versions from the registry & reinstall all dependencies" "Ignore manifest cache entirely" "Don't output anything" "Excessively verbose logging" "Use global folder"
|
||||
|
||||
set -l bun_builtin_cmds_without_run dev create help bun upgrade discord install remove add init pm x
|
||||
set -l bun_builtin_cmds_accepting_flags create help bun upgrade discord run init link unlink pm x
|
||||
@@ -183,4 +183,3 @@ complete -c bun -n "__fish_use_subcommand" -a "unlink" -d "Unregister a local np
|
||||
complete -c bun -n "__fish_use_subcommand" -a "pm" -d "Additional package management utilities" -f
|
||||
complete -c bun -n "__fish_use_subcommand" -a "x" -d "Execute a package binary, installing if needed" -f
|
||||
complete -c bun -n "__fish_use_subcommand" -a "outdated" -d "Display the latest versions of outdated dependencies" -f
|
||||
complete -c bun -n "__fish_use_subcommand" -a "publish" -d "Publish your package from local to npm" -f
|
||||
|
||||
@@ -35,7 +35,6 @@ _bun_add_completion() {
|
||||
'-D[]' \
|
||||
'--development[]' \
|
||||
'--optional[Add dependency to "optionalDependencies]' \
|
||||
'--peer[Add dependency to "peerDependencies]' \
|
||||
'--exact[Add the exact version instead of the ^range]' &&
|
||||
ret=0
|
||||
|
||||
@@ -340,7 +339,6 @@ _bun_install_completion() {
|
||||
'--development[]' \
|
||||
'-D[]' \
|
||||
'--optional[Add dependency to "optionalDependencies]' \
|
||||
'--peer[Add dependency to "peerDependencies]' \
|
||||
'--exact[Add the exact version instead of the ^range]' &&
|
||||
ret=0
|
||||
|
||||
|
||||
@@ -57,8 +57,6 @@ ENV BUN_INSTALL_BIN=${BUN_INSTALL_BIN}
|
||||
|
||||
COPY --from=build /usr/local/bin/bun /usr/local/bin/
|
||||
COPY docker-entrypoint.sh /usr/local/bin/
|
||||
RUN mkdir -p /usr/local/bun-node-fallback-bin && ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node
|
||||
ENV PATH "${PATH}:/usr/local/bun-node-fallback-bin"
|
||||
|
||||
# Temporarily use the `build`-stage /tmp folder to access the glibc APKs:
|
||||
RUN --mount=type=bind,from=build,source=/tmp,target=/tmp \
|
||||
|
||||
@@ -68,8 +68,6 @@ ENV BUN_INSTALL_BIN=${BUN_INSTALL_BIN}
|
||||
|
||||
COPY docker-entrypoint.sh /usr/local/bin
|
||||
COPY --from=build /usr/local/bin/bun /usr/local/bin/bun
|
||||
RUN mkdir -p /usr/local/bun-node-fallback-bin && ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node
|
||||
ENV PATH "${PATH}:/usr/local/bun-node-fallback-bin"
|
||||
|
||||
RUN groupadd bun \
|
||||
--gid 1000 \
|
||||
|
||||
@@ -60,8 +60,6 @@ FROM debian:bullseye
|
||||
|
||||
COPY docker-entrypoint.sh /usr/local/bin
|
||||
COPY --from=build /usr/local/bin/bun /usr/local/bin/bun
|
||||
RUN mkdir -p /usr/local/bun-node-fallback-bin && ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node
|
||||
ENV PATH "${PATH}:/usr/local/bun-node-fallback-bin"
|
||||
|
||||
# Disable the runtime transpiler cache by default inside Docker containers.
|
||||
# On ephemeral containers, the cache is not useful
|
||||
|
||||
@@ -67,8 +67,6 @@ ARG BUN_INSTALL_BIN=/usr/local/bin
|
||||
ENV BUN_INSTALL_BIN=${BUN_INSTALL_BIN}
|
||||
|
||||
COPY --from=build /usr/local/bin/bun /usr/local/bin/
|
||||
RUN mkdir -p /usr/local/bun-node-fallback-bin && ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node
|
||||
ENV PATH "${PATH}:/usr/local/bun-node-fallback-bin"
|
||||
|
||||
# Temporarily use the `build`-stage image binaries to create a symlink:
|
||||
RUN --mount=type=bind,from=build,source=/usr/bin,target=/usr/bin \
|
||||
|
||||
@@ -235,7 +235,7 @@ The following classes are typed arrays, along with a description of how they int
|
||||
---
|
||||
|
||||
- [`BigInt64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array)
|
||||
- Every eight (8) bytes are interpreted as a signed `BigInt`. Range -9223372036854775808 to 9223372036854775807 (though `BigInt` is capable of representing larger numbers).
|
||||
- Every eight (8) bytes are interpreted as an unsigned `BigInt`. Range -9223372036854775808 to 9223372036854775807 (though `BigInt` is capable of representing larger numbers).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -179,16 +179,16 @@ type Flags = string | string[];
|
||||
|
||||
These are flags like `-I` for include directories and `-D` for preprocessor definitions.
|
||||
|
||||
#### `define: Record<string, string>`
|
||||
#### `defines: Record<string, string>`
|
||||
|
||||
The `define` is an optional object that should be passed to the TinyCC compiler.
|
||||
The `defines` is an optional object that should be passed to the TinyCC compiler.
|
||||
|
||||
```ts
|
||||
type Defines = Record<string, string>;
|
||||
|
||||
cc({
|
||||
source: "hello.c",
|
||||
define: {
|
||||
defines: {
|
||||
"NDEBUG": "1",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -111,38 +111,6 @@ const reader = stream.getReader();
|
||||
const { value, done } = await reader.read();
|
||||
```
|
||||
|
||||
### Streaming request bodies
|
||||
|
||||
You can also stream data in request bodies using a `ReadableStream`:
|
||||
|
||||
```ts
|
||||
const stream = new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue("Hello");
|
||||
controller.enqueue(" ");
|
||||
controller.enqueue("World");
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
|
||||
const response = await fetch("http://example.com", {
|
||||
method: "POST",
|
||||
body: stream,
|
||||
});
|
||||
```
|
||||
|
||||
When using streams with HTTP(S):
|
||||
|
||||
- The data is streamed directly to the network without buffering the entire body in memory
|
||||
- If the connection is lost, the stream will be canceled
|
||||
- The `Content-Length` header is not automatically set unless the stream has a known size
|
||||
|
||||
When using streams with S3:
|
||||
|
||||
- For PUT/POST requests, Bun automatically uses multipart upload
|
||||
- The stream is consumed in chunks and uploaded in parallel
|
||||
- Progress can be monitored through the S3 options
|
||||
|
||||
### Fetching a URL with a timeout
|
||||
|
||||
To fetch a URL with a timeout, use `AbortSignal.timeout`:
|
||||
@@ -212,116 +180,6 @@ await fetch("https://example.com", {
|
||||
|
||||
This is similar to how it works in Node's `net` module.
|
||||
|
||||
#### Disable TLS validation
|
||||
|
||||
To disable TLS validation, set `rejectUnauthorized` to `false`:
|
||||
|
||||
```ts
|
||||
await fetch("https://example.com", {
|
||||
tls: {
|
||||
rejectUnauthorized: false,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
This is especially useful to avoid SSL errors when using self-signed certificates, but this disables TLS validation and should be used with caution.
|
||||
|
||||
### Request options
|
||||
|
||||
In addition to the standard fetch options, Bun provides several extensions:
|
||||
|
||||
```ts
|
||||
const response = await fetch("http://example.com", {
|
||||
// Control automatic response decompression (default: true)
|
||||
decompress: true,
|
||||
|
||||
// Disable connection reuse for this request
|
||||
keepalive: false,
|
||||
|
||||
// Debug logging level
|
||||
verbose: true, // or "curl" for more detailed output
|
||||
});
|
||||
```
|
||||
|
||||
### Protocol support
|
||||
|
||||
Beyond HTTP(S), Bun's fetch supports several additional protocols:
|
||||
|
||||
#### S3 URLs - `s3://`
|
||||
|
||||
Bun supports fetching from S3 buckets directly.
|
||||
|
||||
```ts
|
||||
// Using environment variables for credentials
|
||||
const response = await fetch("s3://my-bucket/path/to/object");
|
||||
|
||||
// Or passing credentials explicitly
|
||||
const response = await fetch("s3://my-bucket/path/to/object", {
|
||||
s3: {
|
||||
accessKeyId: "YOUR_ACCESS_KEY",
|
||||
secretAccessKey: "YOUR_SECRET_KEY",
|
||||
region: "us-east-1",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Note: Only PUT and POST methods support request bodies when using S3. For uploads, Bun automatically uses multipart upload for streaming bodies.
|
||||
|
||||
You can read more about Bun's S3 support in the [S3](https://bun.sh/docs/api/s3) documentation.
|
||||
|
||||
#### File URLs - `file://`
|
||||
|
||||
You can fetch local files using the `file:` protocol:
|
||||
|
||||
```ts
|
||||
const response = await fetch("file:///path/to/file.txt");
|
||||
const text = await response.text();
|
||||
```
|
||||
|
||||
On Windows, paths are automatically normalized:
|
||||
|
||||
```ts
|
||||
// Both work on Windows
|
||||
const response = await fetch("file:///C:/path/to/file.txt");
|
||||
const response2 = await fetch("file:///c:/path\\to/file.txt");
|
||||
```
|
||||
|
||||
#### Data URLs - `data:`
|
||||
|
||||
Bun supports the `data:` URL scheme:
|
||||
|
||||
```ts
|
||||
const response = await fetch("data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==");
|
||||
const text = await response.text(); // "Hello, World!"
|
||||
```
|
||||
|
||||
#### Blob URLs - `blob:`
|
||||
|
||||
You can fetch blobs using URLs created by `URL.createObjectURL()`:
|
||||
|
||||
```ts
|
||||
const blob = new Blob(["Hello, World!"], { type: "text/plain" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const response = await fetch(url);
|
||||
```
|
||||
|
||||
### Error handling
|
||||
|
||||
Bun's fetch implementation includes several specific error cases:
|
||||
|
||||
- Using a request body with GET/HEAD methods will throw an error (which is expected for the fetch API)
|
||||
- Attempting to use both `proxy` and `unix` options together will throw an error
|
||||
- TLS certificate validation failures when `rejectUnauthorized` is true (or undefined)
|
||||
- S3 operations may throw specific errors related to authentication or permissions
|
||||
|
||||
### Content-Type handling
|
||||
|
||||
Bun automatically sets the `Content-Type` header for request bodies when not explicitly provided:
|
||||
|
||||
- For `Blob` objects, uses the blob's `type`
|
||||
- For `FormData`, sets appropriate multipart boundary
|
||||
- For JSON objects, sets `application/json`
|
||||
|
||||
## Debugging
|
||||
|
||||
To help with debugging, you can pass `verbose: true` to `fetch`:
|
||||
@@ -337,7 +195,7 @@ This will print the request and response headers to your terminal:
|
||||
```sh
|
||||
[fetch] > HTTP/1.1 GET http://example.com/
|
||||
[fetch] > Connection: keep-alive
|
||||
[fetch] > User-Agent: Bun/$BUN_LATEST_VERSION
|
||||
[fetch] > User-Agent: Bun/1.1.21
|
||||
[fetch] > Accept: */*
|
||||
[fetch] > Host: example.com
|
||||
[fetch] > Accept-Encoding: gzip, deflate, br
|
||||
@@ -448,16 +306,3 @@ import { write } from "bun";
|
||||
|
||||
await write("output.txt", response);
|
||||
```
|
||||
|
||||
### Implementation details
|
||||
|
||||
- Connection pooling is enabled by default but can be disabled per-request with `keepalive: false`. The `"Connection: close"` header can also be used to disable keep-alive.
|
||||
- Large file uploads are optimized using the operating system's `sendfile` syscall under specific conditions:
|
||||
- The file must be larger than 32KB
|
||||
- The request must not be using a proxy
|
||||
- On macOS, only regular files (not pipes, sockets, or devices) can use `sendfile`
|
||||
- When these conditions aren't met, or when using S3/streaming uploads, Bun falls back to reading the file into memory
|
||||
- This optimization is particularly effective for HTTP (not HTTPS) requests where the file can be sent directly from the kernel to the network stack
|
||||
- S3 operations automatically handle signing requests and merging authentication headers
|
||||
|
||||
Note: Many of these features are Bun-specific extensions to the standard fetch API.
|
||||
|
||||
@@ -297,20 +297,6 @@ setTimeout(() => {
|
||||
|
||||
When you're done with a JSCallback, you should call `close()` to free the memory.
|
||||
|
||||
### Experimental thread-safe callbacks
|
||||
`JSCallback` has experimental support for thread-safe callbacks. This will be needed if you pass a callback function into a different thread from it's instantiation context. You can enable it with the optional `threadsafe` option flag.
|
||||
```ts
|
||||
const searchIterator = new JSCallback(
|
||||
(ptr, length) => /hello/.test(new CString(ptr, length)),
|
||||
{
|
||||
returns: "bool",
|
||||
args: ["ptr", "usize"],
|
||||
threadsafe: true, // Optional. Defaults to `false`
|
||||
},
|
||||
);
|
||||
```
|
||||
Be aware that there are still cases where this does not 100% work.
|
||||
|
||||
{% callout %}
|
||||
|
||||
**⚡️ Performance tip** — For a slight performance boost, directly pass `JSCallback.prototype.ptr` instead of the `JSCallback` object:
|
||||
|
||||
@@ -62,14 +62,6 @@ Bun.stdout;
|
||||
Bun.stderr;
|
||||
```
|
||||
|
||||
### Deleting files (`file.delete()`)
|
||||
|
||||
You can delete a file by calling the `.delete()` function.
|
||||
|
||||
```ts
|
||||
await Bun.file("logs.json").delete()
|
||||
```
|
||||
|
||||
## Writing files (`Bun.write()`)
|
||||
|
||||
`Bun.write(destination, data): Promise<number>`
|
||||
|
||||
@@ -169,9 +169,6 @@ Bun.hash.crc32("data", 1234);
|
||||
Bun.hash.adler32("data", 1234);
|
||||
Bun.hash.cityHash32("data", 1234);
|
||||
Bun.hash.cityHash64("data", 1234);
|
||||
Bun.hash.xxHash32("data", 1234);
|
||||
Bun.hash.xxHash64("data", 1234);
|
||||
Bun.hash.xxHash3("data", 1234);
|
||||
Bun.hash.murmur32v3("data", 1234);
|
||||
Bun.hash.murmur32v2("data", 1234);
|
||||
Bun.hash.murmur64v2("data", 1234);
|
||||
|
||||
@@ -1,334 +1,31 @@
|
||||
HTMLRewriter lets you use CSS selectors to transform HTML documents. It works with `Request`, `Response`, as well as `string`. Bun's implementation is based on Cloudflare's [lol-html](https://github.com/cloudflare/lol-html).
|
||||
|
||||
## Usage
|
||||
|
||||
A common usecase is rewriting URLs in HTML content. Here's an example that rewrites image sources and link URLs to use a CDN domain:
|
||||
Bun provides a fast native implementation of the `HTMLRewriter` pattern developed by Cloudflare. It provides a convenient, `EventListener`-like API for traversing and transforming HTML documents.
|
||||
|
||||
```ts
|
||||
// Replace all images with a rickroll
|
||||
const rewriter = new HTMLRewriter().on("img", {
|
||||
element(img) {
|
||||
// Famous rickroll video thumbnail
|
||||
img.setAttribute(
|
||||
"src",
|
||||
"https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
|
||||
);
|
||||
const rewriter = new HTMLRewriter();
|
||||
|
||||
// Wrap the image in a link to the video
|
||||
img.before(
|
||||
'<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank">',
|
||||
{ html: true },
|
||||
);
|
||||
img.after("</a>", { html: true });
|
||||
|
||||
// Add some fun alt text
|
||||
img.setAttribute("alt", "Definitely not a rickroll");
|
||||
},
|
||||
});
|
||||
|
||||
// An example HTML document
|
||||
const html = `
|
||||
<html>
|
||||
<body>
|
||||
<img src="/cat.jpg">
|
||||
<img src="dog.png">
|
||||
<img src="https://example.com/bird.webp">
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
const result = rewriter.transform(html);
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
This replaces all images with a thumbnail of Rick Astley and wraps each `<img>` in a link, producing a diff like this:
|
||||
|
||||
```html-diff
|
||||
<html>
|
||||
<body>
|
||||
- <img src="/cat.jpg">
|
||||
- <img src="dog.png">
|
||||
- <img src="https://example.com/bird.webp">
|
||||
+ <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank">
|
||||
+ <img src="https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg" alt="Definitely not a rickroll">
|
||||
+ </a>
|
||||
+ <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank">
|
||||
+ <img src="https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg" alt="Definitely not a rickroll">
|
||||
+ </a>
|
||||
+ <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank">
|
||||
+ <img src="https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg" alt="Definitely not a rickroll">
|
||||
+ </a>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Now every image on the page will be replaced with a thumbnail of Rick Astley, and clicking any image will lead to [a very famous video](https://www.youtube.com/watch?v=dQw4w9WgXcQ).
|
||||
|
||||
### Input types
|
||||
|
||||
HTMLRewriter can transform HTML from various sources. The input is automatically handled based on its type:
|
||||
|
||||
```ts
|
||||
// From Response
|
||||
rewriter.transform(new Response("<div>content</div>"));
|
||||
|
||||
// From string
|
||||
rewriter.transform("<div>content</div>");
|
||||
|
||||
// From ArrayBuffer
|
||||
rewriter.transform(new TextEncoder().encode("<div>content</div>").buffer);
|
||||
|
||||
// From Blob
|
||||
rewriter.transform(new Blob(["<div>content</div>"]));
|
||||
|
||||
// From File
|
||||
rewriter.transform(Bun.file("index.html"));
|
||||
```
|
||||
|
||||
Note that Cloudflare Workers implementation of HTMLRewriter only supports `Response` objects.
|
||||
|
||||
### Element Handlers
|
||||
|
||||
The `on(selector, handlers)` method allows you to register handlers for HTML elements that match a CSS selector. The handlers are called for each matching element during parsing:
|
||||
|
||||
```ts
|
||||
rewriter.on("div.content", {
|
||||
// Handle elements
|
||||
element(element) {
|
||||
element.setAttribute("class", "new-content");
|
||||
element.append("<p>New content</p>", { html: true });
|
||||
},
|
||||
// Handle text nodes
|
||||
text(text) {
|
||||
text.replace("new text");
|
||||
},
|
||||
// Handle comments
|
||||
comments(comment) {
|
||||
comment.remove();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The handlers can be asynchronous and return a Promise. Note that async operations will block the transformation until they complete:
|
||||
|
||||
```ts
|
||||
rewriter.on("div", {
|
||||
async element(element) {
|
||||
await Bun.sleep(1000);
|
||||
element.setInnerContent("<span>replace</span>", { html: true });
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### CSS Selector Support
|
||||
|
||||
The `on()` method supports a wide range of CSS selectors:
|
||||
|
||||
```ts
|
||||
// Tag selectors
|
||||
rewriter.on("p", handler);
|
||||
|
||||
// Class selectors
|
||||
rewriter.on("p.red", handler);
|
||||
|
||||
// ID selectors
|
||||
rewriter.on("h1#header", handler);
|
||||
|
||||
// Attribute selectors
|
||||
rewriter.on("p[data-test]", handler); // Has attribute
|
||||
rewriter.on('p[data-test="one"]', handler); // Exact match
|
||||
rewriter.on('p[data-test="one" i]', handler); // Case-insensitive
|
||||
rewriter.on('p[data-test="one" s]', handler); // Case-sensitive
|
||||
rewriter.on('p[data-test~="two"]', handler); // Word match
|
||||
rewriter.on('p[data-test^="a"]', handler); // Starts with
|
||||
rewriter.on('p[data-test$="1"]', handler); // Ends with
|
||||
rewriter.on('p[data-test*="b"]', handler); // Contains
|
||||
rewriter.on('p[data-test|="a"]', handler); // Dash-separated
|
||||
|
||||
// Combinators
|
||||
rewriter.on("div span", handler); // Descendant
|
||||
rewriter.on("div > span", handler); // Direct child
|
||||
|
||||
// Pseudo-classes
|
||||
rewriter.on("p:nth-child(2)", handler);
|
||||
rewriter.on("p:first-child", handler);
|
||||
rewriter.on("p:nth-of-type(2)", handler);
|
||||
rewriter.on("p:first-of-type", handler);
|
||||
rewriter.on("p:not(:first-child)", handler);
|
||||
|
||||
// Universal selector
|
||||
rewriter.on("*", handler);
|
||||
```
|
||||
|
||||
### Element Operations
|
||||
|
||||
Elements provide various methods for manipulation. All modification methods return the element instance for chaining:
|
||||
|
||||
```ts
|
||||
rewriter.on("div", {
|
||||
element(el) {
|
||||
// Attributes
|
||||
el.setAttribute("class", "new-class").setAttribute("data-id", "123");
|
||||
|
||||
const classAttr = el.getAttribute("class"); // "new-class"
|
||||
const hasId = el.hasAttribute("id"); // boolean
|
||||
el.removeAttribute("class");
|
||||
|
||||
// Content manipulation
|
||||
el.setInnerContent("New content"); // Escapes HTML by default
|
||||
el.setInnerContent("<p>HTML content</p>", { html: true }); // Parses HTML
|
||||
el.setInnerContent(""); // Clear content
|
||||
|
||||
// Position manipulation
|
||||
el.before("Content before")
|
||||
.after("Content after")
|
||||
.prepend("First child")
|
||||
.append("Last child");
|
||||
|
||||
// HTML content insertion
|
||||
el.before("<span>before</span>", { html: true })
|
||||
.after("<span>after</span>", { html: true })
|
||||
.prepend("<span>first</span>", { html: true })
|
||||
.append("<span>last</span>", { html: true });
|
||||
|
||||
// Removal
|
||||
el.remove(); // Remove element and contents
|
||||
el.removeAndKeepContent(); // Remove only the element tags
|
||||
|
||||
// Properties
|
||||
console.log(el.tagName); // Lowercase tag name
|
||||
console.log(el.namespaceURI); // Element's namespace URI
|
||||
console.log(el.selfClosing); // Whether element is self-closing (e.g. <div />)
|
||||
console.log(el.canHaveContent); // Whether element can contain content (false for void elements like <br>)
|
||||
console.log(el.removed); // Whether element was removed
|
||||
|
||||
// Attributes iteration
|
||||
for (const [name, value] of el.attributes) {
|
||||
console.log(name, value);
|
||||
}
|
||||
|
||||
// End tag handling
|
||||
el.onEndTag(endTag => {
|
||||
endTag.before("Before end tag");
|
||||
endTag.after("After end tag");
|
||||
endTag.remove(); // Remove the end tag
|
||||
console.log(endTag.name); // Tag name in lowercase
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Text Operations
|
||||
|
||||
Text handlers provide methods for text manipulation. Text chunks represent portions of text content and provide information about their position in the text node:
|
||||
|
||||
```ts
|
||||
rewriter.on("p", {
|
||||
text(text) {
|
||||
// Content
|
||||
console.log(text.text); // Text content
|
||||
console.log(text.lastInTextNode); // Whether this is the last chunk
|
||||
console.log(text.removed); // Whether text was removed
|
||||
|
||||
// Manipulation
|
||||
text.before("Before text").after("After text").replace("New text").remove();
|
||||
|
||||
// HTML content insertion
|
||||
text
|
||||
.before("<span>before</span>", { html: true })
|
||||
.after("<span>after</span>", { html: true })
|
||||
.replace("<span>replace</span>", { html: true });
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Comment Operations
|
||||
|
||||
Comment handlers allow comment manipulation with similar methods to text nodes:
|
||||
|
||||
```ts
|
||||
rewriter.on("*", {
|
||||
comments(comment) {
|
||||
// Content
|
||||
console.log(comment.text); // Comment text
|
||||
comment.text = "New comment text"; // Set comment text
|
||||
console.log(comment.removed); // Whether comment was removed
|
||||
|
||||
// Manipulation
|
||||
comment
|
||||
.before("Before comment")
|
||||
.after("After comment")
|
||||
.replace("New comment")
|
||||
.remove();
|
||||
|
||||
// HTML content insertion
|
||||
comment
|
||||
.before("<span>before</span>", { html: true })
|
||||
.after("<span>after</span>", { html: true })
|
||||
.replace("<span>replace</span>", { html: true });
|
||||
element(el) {
|
||||
console.log(el.tagName); // "body" | "div" | ...
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Document Handlers
|
||||
To parse and/or transform the HTML:
|
||||
|
||||
The `onDocument(handlers)` method allows you to handle document-level events. These handlers are called for events that occur at the document level rather than within specific elements:
|
||||
|
||||
```ts
|
||||
rewriter.onDocument({
|
||||
// Handle doctype
|
||||
doctype(doctype) {
|
||||
console.log(doctype.name); // "html"
|
||||
console.log(doctype.publicId); // public identifier if present
|
||||
console.log(doctype.systemId); // system identifier if present
|
||||
},
|
||||
// Handle text nodes
|
||||
text(text) {
|
||||
console.log(text.text);
|
||||
},
|
||||
// Handle comments
|
||||
comments(comment) {
|
||||
console.log(comment.text);
|
||||
},
|
||||
// Handle document end
|
||||
end(end) {
|
||||
end.append("<!-- Footer -->", { html: true });
|
||||
},
|
||||
});
|
||||
```ts#rewriter.ts
|
||||
rewriter.transform(
|
||||
new Response(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!-- comment -->
|
||||
<head>
|
||||
<title>My First HTML Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>My First Heading</h1>
|
||||
<p>My first paragraph.</p>
|
||||
</body>
|
||||
`));
|
||||
```
|
||||
|
||||
### Response Handling
|
||||
|
||||
When transforming a Response:
|
||||
|
||||
- The status code, headers, and other response properties are preserved
|
||||
- The body is transformed while maintaining streaming capabilities
|
||||
- Content-encoding (like gzip) is handled automatically
|
||||
- The original response body is marked as used after transformation
|
||||
- Headers are cloned to the new response
|
||||
|
||||
## Error Handling
|
||||
|
||||
HTMLRewriter operations can throw errors in several cases:
|
||||
|
||||
- Invalid selector syntax in `on()` method
|
||||
- Invalid HTML content in transformation methods
|
||||
- Stream errors when processing Response bodies
|
||||
- Memory allocation failures
|
||||
- Invalid input types (e.g., passing Symbol)
|
||||
- Body already used errors
|
||||
|
||||
Errors should be caught and handled appropriately:
|
||||
|
||||
```ts
|
||||
try {
|
||||
const result = rewriter.transform(input);
|
||||
// Process result
|
||||
} catch (error) {
|
||||
console.error("HTMLRewriter error:", error);
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
You can also read the [Cloudflare documentation](https://developers.cloudflare.com/workers/runtime-apis/html-rewriter/), which this API is intended to be compatible with.
|
||||
View the full documentation on the [Cloudflare website](https://developers.cloudflare.com/workers/runtime-apis/html-rewriter/).
|
||||
|
||||
459
docs/api/http.md
459
docs/api/http.md
@@ -513,241 +513,6 @@ Bun.serve({
|
||||
});
|
||||
```
|
||||
|
||||
## Server Lifecycle Methods
|
||||
|
||||
### server.stop() - Stop the server
|
||||
|
||||
To stop the server from accepting new connections:
|
||||
|
||||
```ts
|
||||
const server = Bun.serve({
|
||||
fetch(req) {
|
||||
return new Response("Hello!");
|
||||
},
|
||||
});
|
||||
|
||||
// Gracefully stop the server (waits for in-flight requests)
|
||||
await server.stop();
|
||||
|
||||
// Force stop and close all active connections
|
||||
await server.stop(true);
|
||||
```
|
||||
|
||||
By default, `stop()` allows in-flight requests and WebSocket connections to complete. Pass `true` to immediately terminate all connections.
|
||||
|
||||
### server.ref() and server.unref() - Process lifecycle control
|
||||
|
||||
Control whether the server keeps the Bun process alive:
|
||||
|
||||
```ts
|
||||
// Don't keep process alive if server is the only thing running
|
||||
server.unref();
|
||||
|
||||
// Restore default behavior - keep process alive
|
||||
server.ref();
|
||||
```
|
||||
|
||||
### server.reload() - Hot reload handlers
|
||||
|
||||
Update the server's handlers without restarting:
|
||||
|
||||
```ts
|
||||
const server = Bun.serve({
|
||||
static: {
|
||||
"/api/version": Response.json({ version: "v1" }),
|
||||
},
|
||||
fetch(req) {
|
||||
return new Response("v1");
|
||||
},
|
||||
});
|
||||
|
||||
// Update to new handler
|
||||
server.reload({
|
||||
static: {
|
||||
"/api/version": Response.json({ version: "v2" }),
|
||||
},
|
||||
fetch(req) {
|
||||
return new Response("v2");
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
This is useful for development and hot reloading. Only `fetch`, `error`, and `static` handlers can be updated.
|
||||
|
||||
## Per-Request Controls
|
||||
|
||||
<!-- ### server.abort(Request) - Abort requests
|
||||
|
||||
The `server.abort(request: Request)` method:
|
||||
|
||||
- Returns `true` if request was aborted, `false` if already aborted/completed
|
||||
- Triggers the request's `AbortSignal`
|
||||
- Cancels any attached `ReadableStream`
|
||||
- Rejects any pending body promises (like `.text()`)
|
||||
|
||||
```ts
|
||||
const server = Bun.serve({
|
||||
fetch(req, server) {
|
||||
// abort if the url contains "slow"
|
||||
if (req.url.includes("slow")) {
|
||||
server.abort(req);
|
||||
|
||||
// When aborted, the server will not error due to the lack of a `Response` object
|
||||
// If you return a `Response` anyway, it will be ignored.
|
||||
return;
|
||||
}
|
||||
|
||||
return new Response("Processing...");
|
||||
},
|
||||
});
|
||||
``` -->
|
||||
|
||||
### server.timeout(Request, seconds) - Custom request timeouts
|
||||
|
||||
Set a custom idle timeout for individual requests:
|
||||
|
||||
```ts
|
||||
const server = Bun.serve({
|
||||
fetch(req, server) {
|
||||
// Set 60 second timeout for this request
|
||||
server.timeout(req, 60);
|
||||
|
||||
// If they take longer than 60 seconds to send the body, the request will be aborted
|
||||
await req.text();
|
||||
|
||||
return new Response("Done!");
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Pass `0` to disable the timeout for a request.
|
||||
|
||||
### server.requestIP(Request) - Get client information
|
||||
|
||||
Get client IP and port information:
|
||||
|
||||
```ts
|
||||
const server = Bun.serve({
|
||||
fetch(req, server) {
|
||||
const address = server.requestIP(req);
|
||||
if (address) {
|
||||
return new Response(
|
||||
`Client IP: ${address.address}, Port: ${address.port}`,
|
||||
);
|
||||
}
|
||||
return new Response("Unknown client");
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Returns `null` for closed requests or Unix domain sockets.
|
||||
|
||||
## Server Metrics
|
||||
|
||||
### server.pendingRequests and server.pendingWebSockets
|
||||
|
||||
Monitor server activity with built-in counters:
|
||||
|
||||
```ts
|
||||
const server = Bun.serve({
|
||||
fetch(req, server) {
|
||||
return new Response(
|
||||
`Active requests: ${server.pendingRequests}\n` +
|
||||
`Active WebSockets: ${server.pendingWebSockets}`,
|
||||
);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### server.subscriberCount(topic) - WebSocket subscribers
|
||||
|
||||
Get count of subscribers for a WebSocket topic:
|
||||
|
||||
```ts
|
||||
const server = Bun.serve({
|
||||
fetch(req, server) {
|
||||
const chatUsers = server.subscriberCount("chat");
|
||||
return new Response(`${chatUsers} users in chat`);
|
||||
},
|
||||
websocket: {
|
||||
message(ws) {
|
||||
ws.subscribe("chat");
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## WebSocket Configuration
|
||||
|
||||
### server.publish(topic, data, compress) - WebSocket Message Publishing
|
||||
|
||||
The server can publish messages to all WebSocket clients subscribed to a topic:
|
||||
|
||||
```ts
|
||||
const server = Bun.serve({
|
||||
websocket: {
|
||||
message(ws) {
|
||||
// Publish to all "chat" subscribers
|
||||
server.publish("chat", "Hello everyone!");
|
||||
},
|
||||
},
|
||||
|
||||
fetch(req) {
|
||||
// ...
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The `publish()` method returns:
|
||||
|
||||
- Number of bytes sent if successful
|
||||
- `0` if the message was dropped
|
||||
- `-1` if backpressure was applied
|
||||
|
||||
### WebSocket Handler Options
|
||||
|
||||
When configuring WebSockets, several advanced options are available through the `websocket` handler:
|
||||
|
||||
```ts
|
||||
Bun.serve({
|
||||
websocket: {
|
||||
// Maximum message size (in bytes)
|
||||
maxPayloadLength: 64 * 1024,
|
||||
|
||||
// Backpressure limit before messages are dropped
|
||||
backpressureLimit: 1024 * 1024,
|
||||
|
||||
// Close connection if backpressure limit is hit
|
||||
closeOnBackpressureLimit: true,
|
||||
|
||||
// Handler called when backpressure is relieved
|
||||
drain(ws) {
|
||||
console.log("Backpressure relieved");
|
||||
},
|
||||
|
||||
// Enable per-message deflate compression
|
||||
perMessageDeflate: {
|
||||
compress: true,
|
||||
decompress: true,
|
||||
},
|
||||
|
||||
// Send ping frames to keep connection alive
|
||||
sendPings: true,
|
||||
|
||||
// Handlers for ping/pong frames
|
||||
ping(ws, data) {
|
||||
console.log("Received ping");
|
||||
},
|
||||
pong(ws, data) {
|
||||
console.log("Received pong");
|
||||
},
|
||||
|
||||
// Whether server receives its own published messages
|
||||
publishToSelf: false,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Benchmarks
|
||||
|
||||
Below are Bun and Node.js implementations of a simple HTTP server that responds `Bun!` to each incoming `Request`.
|
||||
@@ -796,174 +561,100 @@ The `Bun.serve` server can handle roughly 2.5x more requests per second than Nod
|
||||
{% details summary="See TypeScript definitions" %}
|
||||
|
||||
```ts
|
||||
interface Server extends Disposable {
|
||||
/**
|
||||
* Stop the server from accepting new connections.
|
||||
* @param closeActiveConnections If true, immediately terminates all connections
|
||||
* @returns Promise that resolves when the server has stopped
|
||||
*/
|
||||
stop(closeActiveConnections?: boolean): Promise<void>;
|
||||
interface Bun {
|
||||
serve(options: {
|
||||
development?: boolean;
|
||||
error?: (
|
||||
request: ErrorLike,
|
||||
) => Response | Promise<Response> | undefined | Promise<undefined>;
|
||||
fetch(request: Request, server: Server): Response | Promise<Response>;
|
||||
hostname?: string;
|
||||
id?: string | null;
|
||||
maxRequestBodySize?: number;
|
||||
port?: string | number;
|
||||
reusePort?: boolean;
|
||||
tls?: TLSOptions | Array<TLSOptions>;
|
||||
unix: string;
|
||||
websocket: WebSocketHandler<WebSocketDataType>;
|
||||
}): Server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update handlers without restarting the server.
|
||||
* Only fetch and error handlers can be updated.
|
||||
*/
|
||||
reload(options: Serve): void;
|
||||
|
||||
/**
|
||||
* Make a request to the running server.
|
||||
* Useful for testing or internal routing.
|
||||
*/
|
||||
fetch(request: Request | string): Response | Promise<Response>;
|
||||
|
||||
/**
|
||||
* Upgrade an HTTP request to a WebSocket connection.
|
||||
* @returns true if upgrade successful, false if failed
|
||||
*/
|
||||
upgrade<T = undefined>(
|
||||
request: Request,
|
||||
options?: {
|
||||
headers?: Bun.HeadersInit;
|
||||
data?: T;
|
||||
},
|
||||
): boolean;
|
||||
|
||||
/**
|
||||
* Publish a message to all WebSocket clients subscribed to a topic.
|
||||
* @returns Bytes sent, 0 if dropped, -1 if backpressure applied
|
||||
*/
|
||||
publish(
|
||||
topic: string,
|
||||
data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
|
||||
compress?: boolean,
|
||||
): ServerWebSocketSendStatus;
|
||||
|
||||
/**
|
||||
* Get count of WebSocket clients subscribed to a topic.
|
||||
*/
|
||||
subscriberCount(topic: string): number;
|
||||
|
||||
/**
|
||||
* Get client IP address and port.
|
||||
* @returns null for closed requests or Unix sockets
|
||||
*/
|
||||
requestIP(request: Request): SocketAddress | null;
|
||||
|
||||
/**
|
||||
* Set custom idle timeout for a request.
|
||||
* @param seconds Timeout in seconds, 0 to disable
|
||||
*/
|
||||
timeout(request: Request, seconds: number): void;
|
||||
|
||||
/**
|
||||
* Keep process alive while server is running.
|
||||
*/
|
||||
ref(): void;
|
||||
|
||||
/**
|
||||
* Allow process to exit if server is only thing running.
|
||||
*/
|
||||
unref(): void;
|
||||
|
||||
/** Number of in-flight HTTP requests */
|
||||
readonly pendingRequests: number;
|
||||
|
||||
/** Number of active WebSocket connections */
|
||||
readonly pendingWebSockets: number;
|
||||
|
||||
/** Server URL including protocol, hostname and port */
|
||||
readonly url: URL;
|
||||
|
||||
/** Port server is listening on */
|
||||
readonly port: number;
|
||||
|
||||
/** Hostname server is bound to */
|
||||
readonly hostname: string;
|
||||
|
||||
/** Whether server is in development mode */
|
||||
readonly development: boolean;
|
||||
|
||||
/** Server instance identifier */
|
||||
readonly id: string;
|
||||
interface TLSOptions {
|
||||
ca?: string | Buffer | BunFile | Array<string | Buffer | BunFile> | undefined;
|
||||
cert?:
|
||||
| string
|
||||
| Buffer
|
||||
| BunFile
|
||||
| Array<string | Buffer | BunFile>
|
||||
| undefined;
|
||||
dhParamsFile?: string;
|
||||
key?:
|
||||
| string
|
||||
| Buffer
|
||||
| BunFile
|
||||
| Array<string | Buffer | BunFile>
|
||||
| undefined;
|
||||
lowMemoryMode?: boolean;
|
||||
passphrase?: string;
|
||||
secureOptions?: number | undefined;
|
||||
serverName?: string;
|
||||
}
|
||||
|
||||
interface WebSocketHandler<T = undefined> {
|
||||
/** Maximum WebSocket message size in bytes */
|
||||
maxPayloadLength?: number;
|
||||
|
||||
/** Bytes of queued messages before applying backpressure */
|
||||
backpressureLimit?: number;
|
||||
|
||||
/** Whether to close connection when backpressure limit hit */
|
||||
close?(
|
||||
ws: ServerWebSocket<T>,
|
||||
code: number,
|
||||
reason: string,
|
||||
): void | Promise<void>;
|
||||
closeOnBackpressureLimit?: boolean;
|
||||
|
||||
/** Called when backpressure is relieved */
|
||||
drain?(ws: ServerWebSocket<T>): void | Promise<void>;
|
||||
|
||||
/** Seconds before idle timeout */
|
||||
idleTimeout?: number;
|
||||
|
||||
/** Enable per-message deflate compression */
|
||||
maxPayloadLength?: number;
|
||||
message(
|
||||
ws: ServerWebSocket<T>,
|
||||
message: string | Buffer,
|
||||
): void | Promise<void>;
|
||||
open?(ws: ServerWebSocket<T>): void | Promise<void>;
|
||||
perMessageDeflate?:
|
||||
| boolean
|
||||
| {
|
||||
compress?: WebSocketCompressor | boolean;
|
||||
decompress?: WebSocketCompressor | boolean;
|
||||
};
|
||||
|
||||
/** Send ping frames to keep connection alive */
|
||||
sendPings?: boolean;
|
||||
|
||||
/** Whether server receives its own published messages */
|
||||
publishToSelf?: boolean;
|
||||
|
||||
/** Called when connection opened */
|
||||
open?(ws: ServerWebSocket<T>): void | Promise<void>;
|
||||
|
||||
/** Called when message received */
|
||||
message(
|
||||
ws: ServerWebSocket<T>,
|
||||
message: string | Buffer,
|
||||
): void | Promise<void>;
|
||||
|
||||
/** Called when connection closed */
|
||||
close?(
|
||||
ws: ServerWebSocket<T>,
|
||||
code: number,
|
||||
reason: string,
|
||||
): void | Promise<void>;
|
||||
|
||||
/** Called when ping frame received */
|
||||
ping?(ws: ServerWebSocket<T>, data: Buffer): void | Promise<void>;
|
||||
|
||||
/** Called when pong frame received */
|
||||
pong?(ws: ServerWebSocket<T>, data: Buffer): void | Promise<void>;
|
||||
publishToSelf?: boolean;
|
||||
sendPings?: boolean;
|
||||
}
|
||||
|
||||
interface TLSOptions {
|
||||
/** Certificate authority chain */
|
||||
ca?: string | Buffer | BunFile | Array<string | Buffer | BunFile>;
|
||||
interface Server {
|
||||
fetch(request: Request | string): Response | Promise<Response>;
|
||||
publish(
|
||||
compress?: boolean,
|
||||
data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
|
||||
topic: string,
|
||||
): ServerWebSocketSendStatus;
|
||||
ref(): void;
|
||||
reload(options: Serve): void;
|
||||
requestIP(request: Request): SocketAddress | null;
|
||||
stop(closeActiveConnections?: boolean): void;
|
||||
unref(): void;
|
||||
upgrade<T = undefined>(
|
||||
options?: {
|
||||
data?: T;
|
||||
headers?: Bun.HeadersInit;
|
||||
},
|
||||
request: Request,
|
||||
): boolean;
|
||||
|
||||
/** Server certificate */
|
||||
cert?: string | Buffer | BunFile | Array<string | Buffer | BunFile>;
|
||||
|
||||
/** Path to DH parameters file */
|
||||
dhParamsFile?: string;
|
||||
|
||||
/** Private key */
|
||||
key?: string | Buffer | BunFile | Array<string | Buffer | BunFile>;
|
||||
|
||||
/** Reduce TLS memory usage */
|
||||
lowMemoryMode?: boolean;
|
||||
|
||||
/** Private key passphrase */
|
||||
passphrase?: string;
|
||||
|
||||
/** OpenSSL options flags */
|
||||
secureOptions?: number;
|
||||
|
||||
/** Server name for SNI */
|
||||
serverName?: string;
|
||||
readonly development: boolean;
|
||||
readonly hostname: string;
|
||||
readonly id: string;
|
||||
readonly pendingRequests: number;
|
||||
readonly pendingWebSockets: number;
|
||||
readonly port: number;
|
||||
readonly url: URL;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
700
docs/api/s3.md
700
docs/api/s3.md
@@ -1,700 +0,0 @@
|
||||
Production servers often read, upload, and write files to S3-compatible object storage services instead of the local filesystem. Historically, that means local filesystem APIs you use in development can't be used in production. When you use Bun, things are different.
|
||||
|
||||
{% callout %}
|
||||
|
||||
### Bun's S3 API is fast
|
||||
|
||||
{% image src="https://bun.sh/bun-s3-node.gif" alt="Bun's S3 API is fast" caption="Left: Bun v1.1.44. Right: Node.js v23.6.0" /%}
|
||||
|
||||
{% /callout %}
|
||||
|
||||
Bun provides fast, native bindings for interacting with S3-compatible object storage services. Bun's S3 API is designed to be simple and feel similar to fetch's `Response` and `Blob` APIs (like Bun's local filesystem APIs).
|
||||
|
||||
```ts
|
||||
import { s3, write, S3Client } from "bun";
|
||||
|
||||
// Bun.s3 reads environment variables for credentials
|
||||
// file() returns a lazy reference to a file on S3
|
||||
const metadata = s3.file("123.json");
|
||||
|
||||
// Download from S3 as JSON
|
||||
const data = await metadata.json();
|
||||
|
||||
// Upload to S3
|
||||
await write(metadata, JSON.stringify({ name: "John", age: 30 }));
|
||||
|
||||
// Presign a URL (synchronous - no network request needed)
|
||||
const url = metadata.presign({
|
||||
acl: "public-read",
|
||||
expiresIn: 60 * 60 * 24, // 1 day
|
||||
});
|
||||
|
||||
// Delete the file
|
||||
await metadata.delete();
|
||||
```
|
||||
|
||||
S3 is the [de facto standard](https://en.wikipedia.org/wiki/De_facto_standard) internet filesystem. Bun's S3 API works with S3-compatible storage services like:
|
||||
|
||||
- AWS S3
|
||||
- Cloudflare R2
|
||||
- DigitalOcean Spaces
|
||||
- MinIO
|
||||
- Backblaze B2
|
||||
- ...and any other S3-compatible storage service
|
||||
|
||||
## Basic Usage
|
||||
|
||||
There are several ways to interact with Bun's S3 API.
|
||||
|
||||
### `Bun.S3Client` & `Bun.s3`
|
||||
|
||||
`Bun.s3` is equivalent to `new Bun.S3Client()`, relying on environment variables for credentials.
|
||||
|
||||
To explicitly set credentials, pass them to the `Bun.S3Client` constructor.
|
||||
|
||||
```ts
|
||||
import { S3Client } from "bun";
|
||||
|
||||
const client = new S3Client({
|
||||
accessKeyId: "your-access-key",
|
||||
secretAccessKey: "your-secret-key",
|
||||
bucket: "my-bucket",
|
||||
// sessionToken: "..."
|
||||
// acl: "public-read",
|
||||
// endpoint: "https://s3.us-east-1.amazonaws.com",
|
||||
// endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
|
||||
// endpoint: "https://<region>.digitaloceanspaces.com", // DigitalOcean Spaces
|
||||
// endpoint: "http://localhost:9000", // MinIO
|
||||
});
|
||||
|
||||
// Bun.s3 is a global singleton that is equivalent to `new Bun.S3Client()`
|
||||
```
|
||||
|
||||
### Working with S3 Files
|
||||
|
||||
The **`file`** method in `S3Client` returns a **lazy reference to a file on S3**.
|
||||
|
||||
```ts
|
||||
// A lazy reference to a file on S3
|
||||
const s3file: S3File = client.file("123.json");
|
||||
```
|
||||
|
||||
Like `Bun.file(path)`, the `S3Client`'s `file` method is synchronous. It does zero network requests until you call a method that depends on a network request.
|
||||
|
||||
### Reading files from S3
|
||||
|
||||
If you've used the `fetch` API, you're familiar with the `Response` and `Blob` APIs. `S3File` extends `Blob`. The same methods that work on `Blob` also work on `S3File`.
|
||||
|
||||
```ts
|
||||
// Read an S3File as text
|
||||
const text = await s3file.text();
|
||||
|
||||
// Read an S3File as JSON
|
||||
const json = await s3file.json();
|
||||
|
||||
// Read an S3File as an ArrayBuffer
|
||||
const buffer = await s3file.arrayBuffer();
|
||||
|
||||
// Get only the first 1024 bytes
|
||||
const partial = await s3file.slice(0, 1024).text();
|
||||
|
||||
// Stream the file
|
||||
const stream = s3file.stream();
|
||||
for await (const chunk of stream) {
|
||||
console.log(chunk);
|
||||
}
|
||||
```
|
||||
|
||||
#### Memory optimization
|
||||
|
||||
Methods like `text()`, `json()`, `bytes()`, or `arrayBuffer()` avoid duplicating the string or bytes in memory when possible.
|
||||
|
||||
If the text happens to be ASCII, Bun directly transfers the string to JavaScriptCore (the engine) without transcoding and without duplicating the string in memory. When you use `.bytes()` or `.arrayBuffer()`, it will also avoid duplicating the bytes in memory.
|
||||
|
||||
These helper methods not only simplify the API, they also make it faster.
|
||||
|
||||
### Writing & uploading files to S3
|
||||
|
||||
Writing to S3 is just as simple.
|
||||
|
||||
```ts
|
||||
// Write a string (replacing the file)
|
||||
await s3file.write("Hello World!");
|
||||
|
||||
// Write a Buffer (replacing the file)
|
||||
await s3file.write(Buffer.from("Hello World!"));
|
||||
|
||||
// Write a Response (replacing the file)
|
||||
await s3file.write(new Response("Hello World!"));
|
||||
|
||||
// Write with content type
|
||||
await s3file.write(JSON.stringify({ name: "John", age: 30 }), {
|
||||
type: "application/json",
|
||||
});
|
||||
|
||||
// Write using a writer (streaming)
|
||||
const writer = s3file.writer({ type: "application/json" });
|
||||
writer.write("Hello");
|
||||
writer.write(" World!");
|
||||
await writer.end();
|
||||
|
||||
// Write using Bun.write
|
||||
await Bun.write(s3file, "Hello World!");
|
||||
```
|
||||
|
||||
### Working with large files (streams)
|
||||
|
||||
Bun automatically handles multipart uploads for large files and provides streaming capabilities. The same API that works for local files also works for S3 files.
|
||||
|
||||
```ts
|
||||
// Write a large file
|
||||
const bigFile = Buffer.alloc(10 * 1024 * 1024); // 10MB
|
||||
const writer = s3file.writer({
|
||||
// Automatically retry on network errors up to 3 times
|
||||
retry: 3,
|
||||
|
||||
// Queue up to 10 requests at a time
|
||||
queueSize: 10,
|
||||
|
||||
// Upload in 5 MB chunks
|
||||
partSize: 5 * 1024 * 1024,
|
||||
});
|
||||
for (let i = 0; i < 10; i++) {
|
||||
await writer.write(bigFile);
|
||||
}
|
||||
await writer.end();
|
||||
```
|
||||
|
||||
## Presigning URLs
|
||||
|
||||
When your production service needs to let users upload files to your server, it's often more reliable for the user to upload directly to S3 instead of your server acting as an intermediary.
|
||||
|
||||
To facilitate this, you can presign URLs for S3 files. This generates a URL with a signature that allows a user to securely upload that specific file to S3, without exposing your credentials or granting them unnecessary access to your bucket.
|
||||
|
||||
The default behaviour is to generate a `GET` URL that expires in 24 hours. Bun attempts to infer the content type from the file extension. If inference is not possible, it will default to `application/octet-stream`.
|
||||
|
||||
```ts
|
||||
import { s3 } from "bun";
|
||||
|
||||
// Generate a presigned URL that expires in 24 hours (default)
|
||||
const download = s3.presign("my-file.txt"); // GET, text/plain, expires in 24 hours
|
||||
|
||||
const upload = s3.presign("my-file", {
|
||||
expiresIn: 3600, // 1 hour
|
||||
method: 'PUT',
|
||||
type: 'application/json', // No extension for inferring, so we can specify the content type to be JSON
|
||||
});
|
||||
|
||||
// You can call .presign() if on a file reference, but avoid doing so
|
||||
// unless you already have a reference (to avoid memory usage).
|
||||
const myFile = s3.file("my-file.txt");
|
||||
const presignedFile = myFile.presign({
|
||||
expiresIn: 3600, // 1 hour
|
||||
});
|
||||
```
|
||||
|
||||
### Setting ACLs
|
||||
|
||||
To set an ACL (access control list) on a presigned URL, pass the `acl` option:
|
||||
|
||||
```ts
|
||||
const url = s3file.presign({
|
||||
acl: "public-read",
|
||||
expiresIn: 3600,
|
||||
});
|
||||
```
|
||||
|
||||
You can pass any of the following ACLs:
|
||||
|
||||
| ACL | Explanation |
|
||||
| ----------------------------- | ------------------------------------------------------------------- |
|
||||
| `"public-read"` | The object is readable by the public. |
|
||||
| `"private"` | The object is readable only by the bucket owner. |
|
||||
| `"public-read-write"` | The object is readable and writable by the public. |
|
||||
| `"authenticated-read"` | The object is readable by the bucket owner and authenticated users. |
|
||||
| `"aws-exec-read"` | The object is readable by the AWS account that made the request. |
|
||||
| `"bucket-owner-read"` | The object is readable by the bucket owner. |
|
||||
| `"bucket-owner-full-control"` | The object is readable and writable by the bucket owner. |
|
||||
| `"log-delivery-write"` | The object is writable by AWS services used for log delivery. |
|
||||
|
||||
### Expiring URLs
|
||||
|
||||
To set an expiration time for a presigned URL, pass the `expiresIn` option.
|
||||
|
||||
```ts
|
||||
const url = s3file.presign({
|
||||
// Seconds
|
||||
expiresIn: 3600, // 1 hour
|
||||
|
||||
// access control list
|
||||
acl: "public-read",
|
||||
|
||||
// HTTP method
|
||||
method: "PUT",
|
||||
});
|
||||
```
|
||||
|
||||
### `method`
|
||||
|
||||
To set the HTTP method for a presigned URL, pass the `method` option.
|
||||
|
||||
```ts
|
||||
const url = s3file.presign({
|
||||
method: "PUT",
|
||||
// method: "DELETE",
|
||||
// method: "GET",
|
||||
// method: "HEAD",
|
||||
// method: "POST",
|
||||
// method: "PUT",
|
||||
});
|
||||
```
|
||||
|
||||
### `new Response(S3File)`
|
||||
|
||||
To quickly redirect users to a presigned URL for an S3 file, pass an `S3File` instance to a `Response` object as the body.
|
||||
|
||||
```ts
|
||||
const response = new Response(s3file);
|
||||
console.log(response);
|
||||
```
|
||||
|
||||
This will automatically redirect the user to the presigned URL for the S3 file, saving you the memory, time, and bandwidth cost of downloading the file to your server and sending it back to the user.
|
||||
|
||||
```ts
|
||||
Response (0 KB) {
|
||||
ok: false,
|
||||
url: "",
|
||||
status: 302,
|
||||
statusText: "",
|
||||
headers: Headers {
|
||||
"location": "https://<account-id>.r2.cloudflarestorage.com/...",
|
||||
},
|
||||
redirected: true,
|
||||
bodyUsed: false
|
||||
}
|
||||
```
|
||||
|
||||
## Support for S3-Compatible Services
|
||||
|
||||
Bun's S3 implementation works with any S3-compatible storage service. Just specify the appropriate endpoint:
|
||||
|
||||
### Using Bun's S3Client with AWS S3
|
||||
|
||||
AWS S3 is the default. You can also pass a `region` option instead of an `endpoint` option for AWS S3.
|
||||
|
||||
```ts
|
||||
import { S3Client } from "bun";
|
||||
|
||||
// AWS S3
|
||||
const s3 = new S3Client({
|
||||
accessKeyId: "access-key",
|
||||
secretAccessKey: "secret-key",
|
||||
bucket: "my-bucket",
|
||||
// endpoint: "https://s3.us-east-1.amazonaws.com",
|
||||
// region: "us-east-1",
|
||||
});
|
||||
```
|
||||
|
||||
### Using Bun's S3Client with Google Cloud Storage
|
||||
|
||||
To use Bun's S3 client with [Google Cloud Storage](https://cloud.google.com/storage), set `endpoint` to `"https://storage.googleapis.com"` in the `S3Client` constructor.
|
||||
|
||||
```ts
|
||||
import { S3Client } from "bun";
|
||||
|
||||
// Google Cloud Storage
|
||||
const gcs = new S3Client({
|
||||
accessKeyId: "access-key",
|
||||
secretAccessKey: "secret-key",
|
||||
bucket: "my-bucket",
|
||||
endpoint: "https://storage.googleapis.com",
|
||||
});
|
||||
```
|
||||
|
||||
### Using Bun's S3Client with Cloudflare R2
|
||||
|
||||
To use Bun's S3 client with [Cloudflare R2](https://developers.cloudflare.com/r2/), set `endpoint` to the R2 endpoint in the `S3Client` constructor. The R2 endpoint includes your account ID.
|
||||
|
||||
```ts
|
||||
import { S3Client } from "bun";
|
||||
|
||||
// CloudFlare R2
|
||||
const r2 = new S3Client({
|
||||
accessKeyId: "access-key",
|
||||
secretAccessKey: "secret-key",
|
||||
bucket: "my-bucket",
|
||||
endpoint: "https://<account-id>.r2.cloudflarestorage.com",
|
||||
});
|
||||
```
|
||||
|
||||
### Using Bun's S3Client with DigitalOcean Spaces
|
||||
|
||||
To use Bun's S3 client with [DigitalOcean Spaces](https://www.digitalocean.com/products/spaces/), set `endpoint` to the DigitalOcean Spaces endpoint in the `S3Client` constructor.
|
||||
|
||||
```ts
|
||||
import { S3Client } from "bun";
|
||||
|
||||
const spaces = new S3Client({
|
||||
accessKeyId: "access-key",
|
||||
secretAccessKey: "secret-key",
|
||||
bucket: "my-bucket",
|
||||
// region: "nyc3",
|
||||
endpoint: "https://<region>.digitaloceanspaces.com",
|
||||
});
|
||||
```
|
||||
|
||||
### Using Bun's S3Client with MinIO
|
||||
|
||||
To use Bun's S3 client with [MinIO](https://min.io/), set `endpoint` to the URL that MinIO is running on in the `S3Client` constructor.
|
||||
|
||||
```ts
|
||||
import { S3Client } from "bun";
|
||||
|
||||
const minio = new S3Client({
|
||||
accessKeyId: "access-key",
|
||||
secretAccessKey: "secret-key",
|
||||
bucket: "my-bucket",
|
||||
|
||||
// Make sure to use the correct endpoint URL
|
||||
// It might not be localhost in production!
|
||||
endpoint: "http://localhost:9000",
|
||||
});
|
||||
```
|
||||
|
||||
## Credentials
|
||||
|
||||
Credentials are one of the hardest parts of using S3, and we've tried to make it as easy as possible. By default, Bun reads the following environment variables for credentials.
|
||||
|
||||
| Option name | Environment variable |
|
||||
| ----------------- | ---------------------- |
|
||||
| `accessKeyId` | `S3_ACCESS_KEY_ID` |
|
||||
| `secretAccessKey` | `S3_SECRET_ACCESS_KEY` |
|
||||
| `region` | `S3_REGION` |
|
||||
| `endpoint` | `S3_ENDPOINT` |
|
||||
| `bucket` | `S3_BUCKET` |
|
||||
| `sessionToken` | `S3_SESSION_TOKEN` |
|
||||
|
||||
If the `S3_*` environment variable is not set, Bun will also check for the `AWS_*` environment variable, for each of the above options.
|
||||
|
||||
| Option name | Fallback environment variable |
|
||||
| ----------------- | ----------------------------- |
|
||||
| `accessKeyId` | `AWS_ACCESS_KEY_ID` |
|
||||
| `secretAccessKey` | `AWS_SECRET_ACCESS_KEY` |
|
||||
| `region` | `AWS_REGION` |
|
||||
| `endpoint` | `AWS_ENDPOINT` |
|
||||
| `bucket` | `AWS_BUCKET` |
|
||||
| `sessionToken` | `AWS_SESSION_TOKEN` |
|
||||
|
||||
These environment variables are read from [`.env` files](/docs/runtime/env) or from the process environment at initialization time (`process.env` is not used for this).
|
||||
|
||||
These defaults are overridden by the options you pass to `s3.file(credentials)`, `new Bun.S3Client(credentials)`, or any of the methods that accept credentials. So if, for example, you use the same credentials for different buckets, you can set the credentials once in your `.env` file and then pass `bucket: "my-bucket"` to the `s3.file()` function without having to specify all the credentials again.
|
||||
|
||||
### `S3Client` objects
|
||||
|
||||
When you're not using environment variables or using multiple buckets, you can create a `S3Client` object to explicitly set credentials.
|
||||
|
||||
```ts
|
||||
import { S3Client } from "bun";
|
||||
|
||||
const client = new S3Client({
|
||||
accessKeyId: "your-access-key",
|
||||
secretAccessKey: "your-secret-key",
|
||||
bucket: "my-bucket",
|
||||
// sessionToken: "..."
|
||||
endpoint: "https://s3.us-east-1.amazonaws.com",
|
||||
// endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
|
||||
// endpoint: "http://localhost:9000", // MinIO
|
||||
});
|
||||
|
||||
// Write using a Response
|
||||
await file.write(new Response("Hello World!"));
|
||||
|
||||
// Presign a URL
|
||||
const url = file.presign({
|
||||
expiresIn: 60 * 60 * 24, // 1 day
|
||||
acl: "public-read",
|
||||
});
|
||||
|
||||
// Delete the file
|
||||
await file.delete();
|
||||
```
|
||||
|
||||
### `S3Client.prototype.write`
|
||||
|
||||
To upload or write a file to S3, call `write` on the `S3Client` instance.
|
||||
|
||||
```ts
|
||||
const client = new Bun.S3Client({
|
||||
accessKeyId: "your-access-key",
|
||||
secretAccessKey: "your-secret-key",
|
||||
endpoint: "https://s3.us-east-1.amazonaws.com",
|
||||
bucket: "my-bucket",
|
||||
});
|
||||
await client.write("my-file.txt", "Hello World!");
|
||||
await client.write("my-file.txt", new Response("Hello World!"));
|
||||
|
||||
// equivalent to
|
||||
// await client.file("my-file.txt").write("Hello World!");
|
||||
```
|
||||
|
||||
### `S3Client.prototype.delete`
|
||||
|
||||
To delete a file from S3, call `delete` on the `S3Client` instance.
|
||||
|
||||
```ts
|
||||
const client = new Bun.S3Client({
|
||||
accessKeyId: "your-access-key",
|
||||
secretAccessKey: "your-secret-key",
|
||||
bucket: "my-bucket",
|
||||
});
|
||||
|
||||
await client.delete("my-file.txt");
|
||||
// equivalent to
|
||||
// await client.file("my-file.txt").delete();
|
||||
```
|
||||
|
||||
### `S3Client.prototype.exists`
|
||||
|
||||
To check if a file exists in S3, call `exists` on the `S3Client` instance.
|
||||
|
||||
```ts
|
||||
const client = new Bun.S3Client({
|
||||
accessKeyId: "your-access-key",
|
||||
secretAccessKey: "your-secret-key",
|
||||
bucket: "my-bucket",
|
||||
});
|
||||
|
||||
const exists = await client.exists("my-file.txt");
|
||||
// equivalent to
|
||||
// const exists = await client.file("my-file.txt").exists();
|
||||
```
|
||||
|
||||
## `S3File`
|
||||
|
||||
`S3File` instances are created by calling the `S3Client` instance method or the `s3.file()` function. Like `Bun.file()`, `S3File` instances are lazy. They don't refer to something that necessarily exists at the time of creation. That's why all the methods that don't involve network requests are fully synchronous.
|
||||
|
||||
```ts
|
||||
interface S3File extends Blob {
|
||||
slice(start: number, end?: number): S3File;
|
||||
exists(): Promise<boolean>;
|
||||
unlink(): Promise<void>;
|
||||
presign(options: S3Options): string;
|
||||
text(): Promise<string>;
|
||||
json(): Promise<any>;
|
||||
bytes(): Promise<Uint8Array>;
|
||||
arrayBuffer(): Promise<ArrayBuffer>;
|
||||
stream(options: S3Options): ReadableStream;
|
||||
write(
|
||||
data:
|
||||
| string
|
||||
| Uint8Array
|
||||
| ArrayBuffer
|
||||
| Blob
|
||||
| ReadableStream
|
||||
| Response
|
||||
| Request,
|
||||
options?: BlobPropertyBag,
|
||||
): Promise<number>;
|
||||
|
||||
exists(options?: S3Options): Promise<boolean>;
|
||||
unlink(options?: S3Options): Promise<void>;
|
||||
delete(options?: S3Options): Promise<void>;
|
||||
presign(options?: S3Options): string;
|
||||
|
||||
stat(options?: S3Options): Promise<S3Stat>;
|
||||
/**
|
||||
* Size is not synchronously available because it requires a network request.
|
||||
*
|
||||
* @deprecated Use `stat()` instead.
|
||||
*/
|
||||
size: NaN;
|
||||
|
||||
// ... more omitted for brevity
|
||||
}
|
||||
```
|
||||
|
||||
Like `Bun.file()`, `S3File` extends [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob), so all the methods that are available on `Blob` are also available on `S3File`. The same API for reading data from a local file is also available for reading data from S3.
|
||||
|
||||
| Method | Output |
|
||||
| ---------------------------- | ---------------- |
|
||||
| `await s3File.text()` | `string` |
|
||||
| `await s3File.bytes()` | `Uint8Array` |
|
||||
| `await s3File.json()` | `JSON` |
|
||||
| `await s3File.stream()` | `ReadableStream` |
|
||||
| `await s3File.arrayBuffer()` | `ArrayBuffer` |
|
||||
|
||||
That means using `S3File` instances with `fetch()`, `Response`, and other web APIs that accept `Blob` instances just works.
|
||||
|
||||
### Partial reads with `slice`
|
||||
|
||||
To read a partial range of a file, you can use the `slice` method.
|
||||
|
||||
```ts
|
||||
const partial = s3file.slice(0, 1024);
|
||||
|
||||
// Read the partial range as a Uint8Array
|
||||
const bytes = await partial.bytes();
|
||||
|
||||
// Read the partial range as a string
|
||||
const text = await partial.text();
|
||||
```
|
||||
|
||||
Internally, this works by using the HTTP `Range` header to request only the bytes you want. This `slice` method is the same as [`Blob.prototype.slice`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice).
|
||||
|
||||
### Deleting files from S3
|
||||
|
||||
To delete a file from S3, you can use the `delete` method.
|
||||
|
||||
```ts
|
||||
await s3file.delete();
|
||||
// await s3File.unlink();
|
||||
```
|
||||
|
||||
`delete` is the same as `unlink`.
|
||||
|
||||
## Error codes
|
||||
|
||||
When Bun's S3 API throws an error, it will have a `code` property that matches one of the following values:
|
||||
|
||||
- `ERR_S3_MISSING_CREDENTIALS`
|
||||
- `ERR_S3_INVALID_METHOD`
|
||||
- `ERR_S3_INVALID_PATH`
|
||||
- `ERR_S3_INVALID_ENDPOINT`
|
||||
- `ERR_S3_INVALID_SIGNATURE`
|
||||
- `ERR_S3_INVALID_SESSION_TOKEN`
|
||||
|
||||
When the S3 Object Storage service returns an error (that is, not Bun), it will be an `S3Error` instance (an `Error` instance with the name `"S3Error"`).
|
||||
|
||||
## `S3Client` static methods
|
||||
|
||||
The `S3Client` class provides several static methods for interacting with S3.
|
||||
|
||||
### `S3Client.presign` (static)
|
||||
|
||||
To generate a presigned URL for an S3 file, you can use the `S3Client.presign` static method.
|
||||
|
||||
```ts
|
||||
import { S3Client } from "bun";
|
||||
|
||||
const credentials = {
|
||||
accessKeyId: "your-access-key",
|
||||
secretAccessKey: "your-secret-key",
|
||||
bucket: "my-bucket",
|
||||
// endpoint: "https://s3.us-east-1.amazonaws.com",
|
||||
// endpoint: "https://<account-id>.r2.cloudflarestorage.com", // Cloudflare R2
|
||||
};
|
||||
|
||||
const url = S3Client.presign("my-file.txt", {
|
||||
...credentials,
|
||||
expiresIn: 3600,
|
||||
});
|
||||
```
|
||||
|
||||
This is equivalent to calling `new S3Client(credentials).presign("my-file.txt", { expiresIn: 3600 })`.
|
||||
|
||||
### `S3Client.exists` (static)
|
||||
|
||||
To check if an S3 file exists, you can use the `S3Client.exists` static method.
|
||||
|
||||
```ts
|
||||
import { S3Client } from "bun";
|
||||
|
||||
const credentials = {
|
||||
accessKeyId: "your-access-key",
|
||||
secretAccessKey: "your-secret-key",
|
||||
bucket: "my-bucket",
|
||||
// endpoint: "https://s3.us-east-1.amazonaws.com",
|
||||
};
|
||||
|
||||
const exists = await S3Client.exists("my-file.txt", credentials);
|
||||
```
|
||||
|
||||
The same method also works on `S3File` instances.
|
||||
|
||||
```ts
|
||||
import { s3 } from "bun";
|
||||
|
||||
const s3file = s3.file("my-file.txt", {
|
||||
...credentials,
|
||||
});
|
||||
const exists = await s3file.exists();
|
||||
```
|
||||
|
||||
### `S3Client.stat` (static)
|
||||
|
||||
To get the size, etag, and other metadata of an S3 file, you can use the `S3Client.stat` static method.
|
||||
|
||||
```ts
|
||||
import { S3Client } from "bun";
|
||||
|
||||
const credentials = {
|
||||
accessKeyId: "your-access-key",
|
||||
secretAccessKey: "your-secret-key",
|
||||
bucket: "my-bucket",
|
||||
// endpoint: "https://s3.us-east-1.amazonaws.com",
|
||||
};
|
||||
|
||||
const stat = await S3Client.stat("my-file.txt", credentials);
|
||||
// {
|
||||
// etag: "\"7a30b741503c0b461cc14157e2df4ad8\"",
|
||||
// lastModified: 2025-01-07T00:19:10.000Z,
|
||||
// size: 1024,
|
||||
// type: "text/plain;charset=utf-8",
|
||||
// }
|
||||
```
|
||||
|
||||
### `S3Client.delete` (static)
|
||||
|
||||
To delete an S3 file, you can use the `S3Client.delete` static method.
|
||||
|
||||
```ts
|
||||
import { S3Client } from "bun";
|
||||
|
||||
const credentials = {
|
||||
accessKeyId: "your-access-key",
|
||||
secretAccessKey: "your-secret-key",
|
||||
bucket: "my-bucket",
|
||||
// endpoint: "https://s3.us-east-1.amazonaws.com",
|
||||
};
|
||||
|
||||
await S3Client.delete("my-file.txt", credentials);
|
||||
// equivalent to
|
||||
// await new S3Client(credentials).delete("my-file.txt");
|
||||
|
||||
// S3Client.unlink is alias of S3Client.delete
|
||||
await S3Client.unlink("my-file.txt", credentials);
|
||||
```
|
||||
|
||||
## s3:// protocol
|
||||
|
||||
To make it easier to use the same code for local files and S3 files, the `s3://` protocol is supported in `fetch` and `Bun.file()`.
|
||||
|
||||
```ts
|
||||
const response = await fetch("s3://my-bucket/my-file.txt");
|
||||
const file = Bun.file("s3://my-bucket/my-file.txt");
|
||||
```
|
||||
|
||||
You can additionally pass `s3` options to the `fetch` and `Bun.file` functions.
|
||||
|
||||
```ts
|
||||
const response = await fetch("s3://my-bucket/my-file.txt", {
|
||||
s3: {
|
||||
accessKeyId: "your-access-key",
|
||||
secretAccessKey: "your-secret-key",
|
||||
endpoint: "https://s3.us-east-1.amazonaws.com",
|
||||
},
|
||||
headers: {
|
||||
"range": "bytes=0-1023",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### UTF-8, UTF-16, and BOM (byte order mark)
|
||||
|
||||
Like `Response` and `Blob`, `S3File` assumes UTF-8 encoding by default.
|
||||
|
||||
When calling one of the `text()` or `json()` methods on an `S3File`:
|
||||
|
||||
- When a UTF-16 byte order mark (BOM) is detected, it will be treated as UTF-16. JavaScriptCore natively supports UTF-16, so it skips the UTF-8 transcoding process (and strips the BOM). This is mostly good, but it does mean if you have invalid surrogate pairs characters in your UTF-16 string, they will be passed through to JavaScriptCore (same as source code).
|
||||
- When a UTF-8 BOM is detected, it gets stripped before the string is passed to JavaScriptCore and invalid UTF-8 codepoints are replaced with the Unicode replacement character (`\uFFFD`).
|
||||
- UTF-32 is not supported.
|
||||
@@ -110,7 +110,7 @@ You can read results from the subprocess via the `stdout` and `stderr` propertie
|
||||
```ts
|
||||
const proc = Bun.spawn(["bun", "--version"]);
|
||||
const text = await new Response(proc.stdout).text();
|
||||
console.log(text); // => "$BUN_LATEST_VERSION"
|
||||
console.log(text); // => "1.1.7"
|
||||
```
|
||||
|
||||
Configure the output stream by passing one of the following values to `stdout/stderr`:
|
||||
|
||||
571
docs/api/sql.md
571
docs/api/sql.md
@@ -1,571 +0,0 @@
|
||||
Bun provides native bindings for working with PostgreSQL databases with a modern, Promise-based API. The interface is designed to be simple and performant, using tagged template literals for queries and offering features like connection pooling, transactions, and prepared statements.
|
||||
|
||||
```ts
|
||||
import { sql } from "bun";
|
||||
|
||||
const users = await sql`
|
||||
SELECT * FROM users
|
||||
WHERE active = ${true}
|
||||
LIMIT ${10}
|
||||
`;
|
||||
|
||||
// Select with multiple conditions
|
||||
const activeUsers = await sql`
|
||||
SELECT *
|
||||
FROM users
|
||||
WHERE active = ${true}
|
||||
AND age >= ${18}
|
||||
`;
|
||||
```
|
||||
|
||||
{% features title="Features" %}
|
||||
|
||||
{% icon size=20 name="Shield" /%} Tagged template literals to protect against SQL injection
|
||||
|
||||
{% icon size=20 name="GitMerge" /%} Transactions
|
||||
|
||||
{% icon size=20 name="Variable" /%} Named & positional parameters
|
||||
|
||||
{% icon size=20 name="Network" /%} Connection pooling
|
||||
|
||||
{% icon size=20 name="Binary" /%} `BigInt` support
|
||||
|
||||
{% icon size=20 name="Key" /%} SASL Auth support (SCRAM-SHA-256), MD5, and Clear Text
|
||||
|
||||
{% icon size=20 name="Timer" /%} Connection timeouts
|
||||
|
||||
{% icon size=20 name="Database" /%} Returning rows as data objects, arrays of arrays, or `Buffer`
|
||||
|
||||
{% icon size=20 name="Code" /%} Binary protocol support makes it faster
|
||||
|
||||
{% icon size=20 name="Lock" /%} TLS support (and auth mode)
|
||||
|
||||
{% icon size=20 name="Settings" /%} Automatic configuration with environment variable
|
||||
|
||||
{% /features %}
|
||||
|
||||
### Inserting data
|
||||
|
||||
You can pass JavaScript values directly to the SQL template literal and escaping will be handled for you.
|
||||
|
||||
```ts
|
||||
import { sql } from "bun";
|
||||
|
||||
// Basic insert with direct values
|
||||
const [user] = await sql`
|
||||
INSERT INTO users (name, email)
|
||||
VALUES (${name}, ${email})
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
// Using object helper for cleaner syntax
|
||||
const userData = {
|
||||
name: "Alice",
|
||||
email: "alice@example.com",
|
||||
};
|
||||
|
||||
const [newUser] = await sql`
|
||||
INSERT INTO users ${sql(userData)}
|
||||
RETURNING *
|
||||
`;
|
||||
// Expands to: INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')
|
||||
```
|
||||
|
||||
### Bulk Insert
|
||||
|
||||
You can also pass arrays of objects to the SQL template literal and it will be expanded to a `INSERT INTO ... VALUES ...` statement.
|
||||
|
||||
```ts
|
||||
const users = [
|
||||
{ name: "Alice", email: "alice@example.com" },
|
||||
{ name: "Bob", email: "bob@example.com" },
|
||||
{ name: "Charlie", email: "charlie@example.com" },
|
||||
];
|
||||
|
||||
await sql`INSERT INTO users ${sql(users)}`;
|
||||
```
|
||||
|
||||
### Picking columns to insert
|
||||
|
||||
You can use `sql(object, Array<string>)` to pick which columns to insert. Each of the columns must be defined on the object.
|
||||
|
||||
```ts
|
||||
const user = {
|
||||
name: "Alice",
|
||||
email: "alice@example.com",
|
||||
age: 25,
|
||||
};
|
||||
|
||||
await sql`INSERT INTO users ${sql(user, ["name", "email"])}`;
|
||||
// Only inserts name and email columns, ignoring other fields
|
||||
```
|
||||
|
||||
## Query Results
|
||||
|
||||
By default, Bun's SQL client returns query results as arrays of objects, where each object represents a row with column names as keys. However, there are cases where you might want the data in a different format. The client provides two additional methods for this purpose.
|
||||
|
||||
### `sql``.values()` format
|
||||
|
||||
The `sql``.values()` method returns rows as arrays of values rather than objects. Each row becomes an array where the values are in the same order as the columns in your query.
|
||||
|
||||
```ts
|
||||
const rows = await sql`SELECT * FROM users`.values();
|
||||
console.log(rows);
|
||||
```
|
||||
|
||||
This returns something like:
|
||||
|
||||
```ts
|
||||
[
|
||||
["Alice", "alice@example.com"],
|
||||
["Bob", "bob@example.com"],
|
||||
];
|
||||
```
|
||||
|
||||
`sql``.values()` is especially useful if duplicate column names are returned in the query results. When using objects (the default), the last column name is used as the key in the object, which means duplicate column names overwrite each other — but when using `sql``.values()`, each column is present in the array so you can access the values of duplicate columns by index.
|
||||
|
||||
### `sql``.raw()` format
|
||||
|
||||
The `.raw()` method returns rows as arrays of `Buffer` objects. This can be useful for working with binary data or for performance reasons.
|
||||
|
||||
```ts
|
||||
const rows = await sql`SELECT * FROM users`.raw();
|
||||
console.log(rows); // [[Buffer, Buffer], [Buffer, Buffer], [Buffer, Buffer]]
|
||||
```
|
||||
|
||||
## SQL Fragments
|
||||
|
||||
A common need in database applications is the ability to construct queries dynamically based on runtime conditions. Bun provides safe ways to do this without risking SQL injection.
|
||||
|
||||
### Dynamic Table Names
|
||||
|
||||
When you need to reference tables or schemas dynamically, use the `sql()` helper to ensure proper escaping:
|
||||
|
||||
```ts
|
||||
// Safely reference tables dynamically
|
||||
await sql`SELECT * FROM ${sql("users")}`;
|
||||
|
||||
// With schema qualification
|
||||
await sql`SELECT * FROM ${sql("public.users")}`;
|
||||
```
|
||||
|
||||
### Conditional Queries
|
||||
|
||||
You can use the `sql()` helper to build queries with conditional clauses. This allows you to create flexible queries that adapt to your application's needs:
|
||||
|
||||
```ts
|
||||
// Optional WHERE clauses
|
||||
const filterAge = true;
|
||||
const minAge = 21;
|
||||
const ageFilter = sql`AND age > ${minAge}`;
|
||||
await sql`
|
||||
SELECT * FROM users
|
||||
WHERE active = ${true}
|
||||
${filterAge ? ageFilter : sql``}
|
||||
`;
|
||||
```
|
||||
|
||||
### Unsafe Queries
|
||||
|
||||
You can use the `sql.unsafe` function to execute raw SQL strings. Use this with caution, as it will not escape user input.
|
||||
|
||||
```ts
|
||||
const result = await sql.unsafe(
|
||||
"SELECT " + columns + " FROM users WHERE id = " + id,
|
||||
);
|
||||
```
|
||||
|
||||
#### What is SQL Injection?
|
||||
|
||||
{% image href="https://xkcd.com/327/" src="https://imgs.xkcd.com/comics/exploits_of_a_mom.png" /%}
|
||||
|
||||
### Execute and Cancelling Queries
|
||||
|
||||
Bun's SQL is lazy that means its will only start executing when awaited or executed with `.execute()`.
|
||||
You can cancel a query that is currently executing by calling the `cancel()` method on the query object.
|
||||
|
||||
```ts
|
||||
const query = await sql`SELECT * FROM users`.execute();
|
||||
setTimeout(() => query.cancel(), 100);
|
||||
await query;
|
||||
```
|
||||
|
||||
## Database Environment Variables
|
||||
|
||||
`sql` connection parameters can be configured using environment variables. The client checks these variables in a specific order of precedence.
|
||||
|
||||
The following environment variables can be used to define the connection URL:
|
||||
|
||||
| Environment Variable | Description |
|
||||
| --------------------------- | ------------------------------------------ |
|
||||
| `POSTGRES_URL` | Primary connection URL for PostgreSQL |
|
||||
| `DATABASE_URL` | Alternative connection URL |
|
||||
| `PGURL` | Alternative connection URL |
|
||||
| `PG_URL` | Alternative connection URL |
|
||||
| `TLS_POSTGRES_DATABASE_URL` | SSL/TLS-enabled connection URL |
|
||||
| `TLS_DATABASE_URL` | Alternative SSL/TLS-enabled connection URL |
|
||||
|
||||
If no connection URL is provided, the system checks for the following individual parameters:
|
||||
|
||||
| Environment Variable | Fallback Variables | Default Value | Description |
|
||||
| -------------------- | ---------------------------- | ------------- | ----------------- |
|
||||
| `PGHOST` | - | `localhost` | Database host |
|
||||
| `PGPORT` | - | `5432` | Database port |
|
||||
| `PGUSERNAME` | `PGUSER`, `USER`, `USERNAME` | `postgres` | Database user |
|
||||
| `PGPASSWORD` | - | (empty) | Database password |
|
||||
| `PGDATABASE` | - | username | Database name |
|
||||
|
||||
## Connection Options
|
||||
|
||||
You can configure your database connection manually by passing options to the SQL constructor:
|
||||
|
||||
```ts
|
||||
import { SQL } from "bun";
|
||||
|
||||
const db = new SQL({
|
||||
// Required
|
||||
url: "postgres://user:pass@localhost:5432/dbname",
|
||||
|
||||
// Optional configuration
|
||||
hostname: "localhost",
|
||||
port: 5432,
|
||||
database: "myapp",
|
||||
username: "dbuser",
|
||||
password: "secretpass",
|
||||
|
||||
// Connection pool settings
|
||||
max: 20, // Maximum connections in pool
|
||||
idleTimeout: 30, // Close idle connections after 30s
|
||||
maxLifetime: 0, // Connection lifetime in seconds (0 = forever)
|
||||
connectionTimeout: 30, // Timeout when establishing new connections
|
||||
|
||||
// SSL/TLS options
|
||||
tls: true,
|
||||
// tls: {
|
||||
// rejectUnauthorized: true,
|
||||
// requestCert: true,
|
||||
// ca: "path/to/ca.pem",
|
||||
// key: "path/to/key.pem",
|
||||
// cert: "path/to/cert.pem",
|
||||
// checkServerIdentity(hostname, cert) {
|
||||
// ...
|
||||
// },
|
||||
// },
|
||||
|
||||
// Callbacks
|
||||
onconnect: client => {
|
||||
console.log("Connected to database");
|
||||
},
|
||||
onclose: client => {
|
||||
console.log("Connection closed");
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Transactions
|
||||
|
||||
To start a new transaction, use `sql.begin`. This method reserves a dedicated connection for the duration of the transaction and provides a scoped `sql` instance to use within the callback function. Once the callback completes, `sql.begin` resolves with the return value of the callback.
|
||||
|
||||
The `BEGIN` command is sent automatically, including any optional configurations you specify. If an error occurs during the transaction, a `ROLLBACK` is triggered to release the reserved connection and ensure the process continues smoothly.
|
||||
|
||||
### Basic Transactions
|
||||
|
||||
```ts
|
||||
await sql.begin(async tx => {
|
||||
// All queries in this function run in a transaction
|
||||
await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
|
||||
await tx`UPDATE accounts SET balance = balance - 100 WHERE user_id = 1`;
|
||||
|
||||
// Transaction automatically commits if no errors are thrown
|
||||
// Rolls back if any error occurs
|
||||
});
|
||||
```
|
||||
|
||||
It's also possible to pipeline the requests in a transaction if needed by returning an array with queries from the callback function like this:
|
||||
|
||||
```ts
|
||||
await sql.begin(async tx => {
|
||||
return [
|
||||
tx`INSERT INTO users (name) VALUES (${"Alice"})`,
|
||||
tx`UPDATE accounts SET balance = balance - 100 WHERE user_id = 1`,
|
||||
];
|
||||
});
|
||||
```
|
||||
|
||||
### Savepoints
|
||||
|
||||
Savepoints in SQL create intermediate checkpoints within a transaction, enabling partial rollbacks without affecting the entire operation. They are useful in complex transactions, allowing error recovery and maintaining consistent results.
|
||||
|
||||
```ts
|
||||
await sql.begin(async tx => {
|
||||
await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
|
||||
|
||||
await tx.savepoint(async sp => {
|
||||
// This part can be rolled back separately
|
||||
await sp`UPDATE users SET status = 'active'`;
|
||||
if (someCondition) {
|
||||
throw new Error("Rollback to savepoint");
|
||||
}
|
||||
});
|
||||
|
||||
// Continue with transaction even if savepoint rolled back
|
||||
await tx`INSERT INTO audit_log (action) VALUES ('user_created')`;
|
||||
});
|
||||
```
|
||||
|
||||
### Distributed Transactions
|
||||
|
||||
Two-Phase Commit (2PC) is a distributed transaction protocol where Phase 1 has the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes either committing or rolling back based on the coordinator's decision. This process ensures data durability and proper lock management.
|
||||
|
||||
In PostgreSQL and MySQL, distributed transactions persist beyond their original session, allowing privileged users or coordinators to commit or rollback them later. This supports robust distributed transactions, recovery processes, and administrative operations.
|
||||
|
||||
Each database system implements distributed transactions differently:
|
||||
|
||||
PostgreSQL natively supports them through prepared transactions, while MySQL uses XA Transactions.
|
||||
|
||||
If any exceptions occur during the distributed transaction and aren't caught, the system will automatically rollback all changes. When everything proceeds normally, you maintain the flexibility to either commit or rollback the transaction later.
|
||||
|
||||
```ts
|
||||
// Begin a distributed transaction
|
||||
await sql.beginDistributed("tx1", async tx => {
|
||||
await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
|
||||
});
|
||||
|
||||
// Later, commit or rollback
|
||||
await sql.commitDistributed("tx1");
|
||||
// or
|
||||
await sql.rollbackDistributed("tx1");
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
Bun supports SCRAM-SHA-256 (SASL), MD5, and Clear Text authentication. SASL is recommended for better security. Check [Postgres SASL Authentication](https://www.postgresql.org/docs/current/sasl-authentication.html) for more information.
|
||||
|
||||
### SSL Modes Overview
|
||||
|
||||
PostgreSQL supports different SSL/TLS modes to control how secure connections are established. These modes determine the behavior when connecting and the level of certificate verification performed.
|
||||
|
||||
```ts
|
||||
const sql = new SQL({
|
||||
hostname: "localhost",
|
||||
username: "user",
|
||||
password: "password",
|
||||
ssl: "disable", // | "prefer" | "require" | "verify-ca" | "verify-full"
|
||||
});
|
||||
```
|
||||
|
||||
| SSL Mode | Description |
|
||||
| ------------- | -------------------------------------------------------------------------------------------------------------------- |
|
||||
| `disable` | No SSL/TLS used. Connections fail if server requires SSL. |
|
||||
| `prefer` | Tries SSL first, falls back to non-SSL if SSL fails. Default mode if none specified. |
|
||||
| `require` | Requires SSL without certificate verification. Fails if SSL cannot be established. |
|
||||
| `verify-ca` | Verifies server certificate is signed by trusted CA. Fails if verification fails. |
|
||||
| `verify-full` | Most secure mode. Verifies certificate and hostname match. Protects against untrusted certificates and MITM attacks. |
|
||||
|
||||
### Using With Connection Strings
|
||||
|
||||
The SSL mode can also be specified in connection strings:
|
||||
|
||||
```ts
|
||||
// Using prefer mode
|
||||
const sql = new SQL("postgres://user:password@localhost/mydb?sslmode=prefer");
|
||||
|
||||
// Using verify-full mode
|
||||
const sql = new SQL(
|
||||
"postgres://user:password@localhost/mydb?sslmode=verify-full",
|
||||
);
|
||||
```
|
||||
|
||||
## Connection Pooling
|
||||
|
||||
Bun's SQL client automatically manages a connection pool, which is a pool of database connections that are reused for multiple queries. This helps to reduce the overhead of establishing and closing connections for each query, and it also helps to manage the number of concurrent connections to the database.
|
||||
|
||||
```ts
|
||||
const db = new SQL({
|
||||
// Pool configuration
|
||||
max: 20, // Maximum 20 concurrent connections
|
||||
idleTimeout: 30, // Close idle connections after 30s
|
||||
maxLifetime: 3600, // Max connection lifetime 1 hour
|
||||
connectionTimeout: 10, // Connection timeout 10s
|
||||
});
|
||||
```
|
||||
|
||||
No connection will be made until a query is made.
|
||||
|
||||
```ts
|
||||
const sql = Bun.sql(); // no connection are created
|
||||
|
||||
await sql`...`; // pool is started until max is reached (if possible), first available connection is used
|
||||
await sql`...`; // previous connection is reused
|
||||
|
||||
// two connections are used now at the same time
|
||||
await Promise.all([
|
||||
sql`INSERT INTO users ${sql({ name: "Alice" })}`,
|
||||
sql`UPDATE users SET name = ${user.name} WHERE id = ${user.id}`,
|
||||
]);
|
||||
|
||||
await sql.close(); // await all queries to finish and close all connections from the pool
|
||||
await sql.close({ timeout: 5 }); // wait 5 seconds and close all connections from the pool
|
||||
await sql.close({ timeout: 0 }); // close all connections from the pool immediately
|
||||
```
|
||||
|
||||
## Reserved Connections
|
||||
|
||||
Bun enables you to reserve a connection from the pool, and returns a client that wraps the single connection. This can be used for running queries on an isolated connection.
|
||||
|
||||
```ts
|
||||
// Get exclusive connection from pool
|
||||
const reserved = await sql.reserve();
|
||||
|
||||
try {
|
||||
await reserved`INSERT INTO users (name) VALUES (${"Alice"})`;
|
||||
} finally {
|
||||
// Important: Release connection back to pool
|
||||
reserved.release();
|
||||
}
|
||||
|
||||
// Or using Symbol.dispose
|
||||
{
|
||||
using reserved = await sql.reserve();
|
||||
await reserved`SELECT 1`;
|
||||
} // Automatically released
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The client provides typed errors for different failure scenarios:
|
||||
|
||||
### Connection Errors
|
||||
|
||||
| Connection Errors | Description |
|
||||
| --------------------------------- | ---------------------------------------------------- |
|
||||
| `ERR_POSTGRES_CONNECTION_CLOSED` | Connection was terminated or never established |
|
||||
| `ERR_POSTGRES_CONNECTION_TIMEOUT` | Failed to establish connection within timeout period |
|
||||
| `ERR_POSTGRES_IDLE_TIMEOUT` | Connection closed due to inactivity |
|
||||
| `ERR_POSTGRES_LIFETIME_TIMEOUT` | Connection exceeded maximum lifetime |
|
||||
| `ERR_POSTGRES_TLS_NOT_AVAILABLE` | SSL/TLS connection not available |
|
||||
| `ERR_POSTGRES_TLS_UPGRADE_FAILED` | Failed to upgrade connection to SSL/TLS |
|
||||
|
||||
### Authentication Errors
|
||||
|
||||
| Authentication Errors | Description |
|
||||
| ------------------------------------------------ | ---------------------------------------- |
|
||||
| `ERR_POSTGRES_AUTHENTICATION_FAILED_PBKDF2` | Password authentication failed |
|
||||
| `ERR_POSTGRES_UNKNOWN_AUTHENTICATION_METHOD` | Server requested unknown auth method |
|
||||
| `ERR_POSTGRES_UNSUPPORTED_AUTHENTICATION_METHOD` | Server requested unsupported auth method |
|
||||
| `ERR_POSTGRES_INVALID_SERVER_KEY` | Invalid server key during authentication |
|
||||
| `ERR_POSTGRES_INVALID_SERVER_SIGNATURE` | Invalid server signature |
|
||||
| `ERR_POSTGRES_SASL_SIGNATURE_INVALID_BASE64` | Invalid SASL signature encoding |
|
||||
| `ERR_POSTGRES_SASL_SIGNATURE_MISMATCH` | SASL signature verification failed |
|
||||
|
||||
### Query Errors
|
||||
|
||||
| Query Errors | Description |
|
||||
| ------------------------------------ | ------------------------------------------ |
|
||||
| `ERR_POSTGRES_SYNTAX_ERROR` | Invalid SQL syntax (extends `SyntaxError`) |
|
||||
| `ERR_POSTGRES_SERVER_ERROR` | General error from PostgreSQL server |
|
||||
| `ERR_POSTGRES_INVALID_QUERY_BINDING` | Invalid parameter binding |
|
||||
| `ERR_POSTGRES_QUERY_CANCELLED` | Query was cancelled |
|
||||
|
||||
### Data Type Errors
|
||||
|
||||
| Data Type Errors | Description |
|
||||
| ------------------------------------------------------- | ------------------------------------- |
|
||||
| `ERR_POSTGRES_INVALID_BINARY_DATA` | Invalid binary data format |
|
||||
| `ERR_POSTGRES_INVALID_BYTE_SEQUENCE` | Invalid byte sequence |
|
||||
| `ERR_POSTGRES_INVALID_BYTE_SEQUENCE_FOR_ENCODING` | Encoding error |
|
||||
| `ERR_POSTGRES_INVALID_CHARACTER` | Invalid character in data |
|
||||
| `ERR_POSTGRES_OVERFLOW` | Numeric overflow |
|
||||
| `ERR_POSTGRES_UNSUPPORTED_BYTEA_FORMAT` | Unsupported binary format |
|
||||
| `ERR_POSTGRES_UNSUPPORTED_INTEGER_SIZE` | Integer size not supported |
|
||||
| `ERR_POSTGRES_MULTIDIMENSIONAL_ARRAY_NOT_SUPPORTED_YET` | Multidimensional arrays not supported |
|
||||
| `ERR_POSTGRES_NULLS_IN_ARRAY_NOT_SUPPORTED_YET` | NULL values in arrays not supported |
|
||||
|
||||
### Protocol Errors
|
||||
|
||||
| Protocol Errors | Description |
|
||||
| --------------------------------------- | --------------------------- |
|
||||
| `ERR_POSTGRES_EXPECTED_REQUEST` | Expected client request |
|
||||
| `ERR_POSTGRES_EXPECTED_STATEMENT` | Expected prepared statement |
|
||||
| `ERR_POSTGRES_INVALID_BACKEND_KEY_DATA` | Invalid backend key data |
|
||||
| `ERR_POSTGRES_INVALID_MESSAGE` | Invalid protocol message |
|
||||
| `ERR_POSTGRES_INVALID_MESSAGE_LENGTH` | Invalid message length |
|
||||
| `ERR_POSTGRES_UNEXPECTED_MESSAGE` | Unexpected message type |
|
||||
|
||||
### Transaction Errors
|
||||
|
||||
| Transaction Errors | Description |
|
||||
| ---------------------------------------- | ------------------------------------- |
|
||||
| `ERR_POSTGRES_UNSAFE_TRANSACTION` | Unsafe transaction operation detected |
|
||||
| `ERR_POSTGRES_INVALID_TRANSACTION_STATE` | Invalid transaction state |
|
||||
|
||||
## Numbers and BigInt
|
||||
|
||||
Bun's SQL client includes special handling for large numbers that exceed the range of a 53-bit integer. Here’s how it works:
|
||||
|
||||
```ts
|
||||
import { sql } from "bun";
|
||||
|
||||
const [{ x, y }] = await sql`SELECT 9223372036854777 as x, 12345 as y`;
|
||||
|
||||
console.log(typeof x, x); // "string" "9223372036854777"
|
||||
console.log(typeof y, y); // "number" 12345
|
||||
```
|
||||
|
||||
## BigInt Instead of Strings
|
||||
|
||||
If you need large numbers as BigInt instead of strings, you can enable this by setting the `bigint` option to `true` when initializing the SQL client:
|
||||
|
||||
```ts
|
||||
const sql = new SQL({
|
||||
bigint: true,
|
||||
});
|
||||
|
||||
const [{ x }] = await sql`SELECT 9223372036854777 as x`;
|
||||
|
||||
console.log(typeof x, x); // "bigint" 9223372036854777n
|
||||
```
|
||||
|
||||
## Roadmap
|
||||
|
||||
There's still some things we haven't finished yet.
|
||||
|
||||
- Connection preloading via `--db-preconnect` Bun CLI flag
|
||||
- MySQL support: [we're working on it](https://github.com/oven-sh/bun/pull/15274)
|
||||
- SQLite support: planned, but not started. Ideally, we implement it natively instead of wrapping `bun:sqlite`.
|
||||
- Column name transforms (e.g. `snake_case` to `camelCase`). This is mostly blocked on a unicode-aware implementation of changing the case in C++ using WebKit's `WTF::String`.
|
||||
- Column type transforms
|
||||
|
||||
### Postgres-specific features
|
||||
|
||||
We haven't implemented these yet:
|
||||
|
||||
- `COPY` support
|
||||
- `LISTEN` support
|
||||
- `NOTIFY` support
|
||||
|
||||
We also haven't implemented some of the more uncommon features like:
|
||||
|
||||
- GSSAPI authentication
|
||||
- `SCRAM-SHA-256-PLUS` support
|
||||
- Point & PostGIS types
|
||||
- All the multi-dimensional integer array types (only a couple of the types are supported)
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
> Why is this `Bun.sql` and not `Bun.postgres`?
|
||||
|
||||
The plan is to add more database drivers in the future.
|
||||
|
||||
> Why not just use an existing library?
|
||||
|
||||
npm packages like postgres.js, pg, and node-postgres can be used in Bun too. They're great options.
|
||||
|
||||
Two reasons why:
|
||||
|
||||
1. We think it's simpler for developers to have a database driver built into Bun. The time you spend library shopping is time you could be building your app.
|
||||
2. We leverage some JavaScriptCore engine internals to make it faster to create objects that would be difficult to implement in a library
|
||||
|
||||
## Credits
|
||||
|
||||
Huge thanks to [@porsager](https://github.com/porsager)'s [postgres.js](https://github.com/porsager/postgres) for the inspiration for the API interface.
|
||||
@@ -82,7 +82,7 @@ const strict = new Database(
|
||||
// throws error because of the typo:
|
||||
const query = strict
|
||||
.query("SELECT $message;")
|
||||
.all({ message: "Hello world" });
|
||||
.all({ messag: "Hello world" });
|
||||
|
||||
const notStrict = new Database(
|
||||
":memory:"
|
||||
@@ -90,7 +90,7 @@ const notStrict = new Database(
|
||||
// does not throw error:
|
||||
notStrict
|
||||
.query("SELECT $message;")
|
||||
.all({ message: "Hello world" });
|
||||
.all({ messag: "Hello world" });
|
||||
```
|
||||
|
||||
### Load via ES module import
|
||||
|
||||
@@ -137,8 +137,7 @@ Each import in the `imports` array has a `path` and `kind`. Bun categories impor
|
||||
- `import-rule`: `@import 'foo.css'`
|
||||
- `url-token`: `url('./foo.png')`
|
||||
<!-- - `internal`: `import {foo} from 'bun:internal'`
|
||||
- `entry-point-build`: `import {foo} from 'bun:entry'`
|
||||
- `entry-point-run`: `bun ./mymodule` -->
|
||||
- `entry-point`: `import {foo} from 'bun:entry'` -->
|
||||
|
||||
## `.scanImports()`
|
||||
|
||||
@@ -268,8 +267,7 @@ type Import = {
|
||||
// The import was injected by Bun
|
||||
| "internal"
|
||||
// Entry point (not common)
|
||||
| "entry-point-build"
|
||||
| "entry-point-run"
|
||||
| "entry-point"
|
||||
}
|
||||
|
||||
const transpiler = new Bun.Transpiler({ loader: "jsx" });
|
||||
|
||||
@@ -121,7 +121,7 @@ const id = randomUUIDv7();
|
||||
|
||||
A UUID v7 is a 128-bit value that encodes the current timestamp, a random value, and a counter. The timestamp is encoded using the lowest 48 bits, and the random value and counter are encoded using the remaining bits.
|
||||
|
||||
The `timestamp` parameter defaults to the current time in milliseconds. When the timestamp changes, the counter is reset to a pseudo-random integer wrapped to 4096. This counter is atomic and threadsafe, meaning that using `Bun.randomUUIDv7()` in many Workers within the same process running at the same timestamp will not have colliding counter values.
|
||||
The `timestamp` parameter defaults to the current time in milliseconds. When the timestamp changes, the counter is reset to a psuedo-random integer wrapped to 4096. This counter is atomic and threadsafe, meaning that using `Bun.randomUUIDv7()` in many Workers within the same process running at the same timestamp will not have colliding counter values.
|
||||
|
||||
The final 8 bytes of the UUID are a cryptographically secure random value. It uses the same random number generator used by `crypto.randomUUID()` (which comes from BoringSSL, which in turn comes from the platform-specific system random number generator usually provided by the underlying hardware).
|
||||
|
||||
@@ -771,28 +771,3 @@ console.log(obj); // => { foo: "bar" }
|
||||
```
|
||||
|
||||
Internally, [`structuredClone`](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) and [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) serialize and deserialize the same way. This exposes the underlying [HTML Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) to JavaScript as an ArrayBuffer.
|
||||
|
||||
## `estimateShallowMemoryUsageOf` in `bun:jsc`
|
||||
|
||||
The `estimateShallowMemoryUsageOf` function returns a best-effort estimate of the memory usage of an object in bytes, excluding the memory usage of properties or other objects it references. For accurate per-object memory usage, use `Bun.generateHeapSnapshot`.
|
||||
|
||||
```js
|
||||
import { estimateShallowMemoryUsageOf } from "bun:jsc";
|
||||
|
||||
const obj = { foo: "bar" };
|
||||
const usage = estimateShallowMemoryUsageOf(obj);
|
||||
console.log(usage); // => 16
|
||||
|
||||
const buffer = Buffer.alloc(1024 * 1024);
|
||||
estimateShallowMemoryUsageOf(buffer);
|
||||
// => 1048624
|
||||
|
||||
const req = new Request("https://bun.sh");
|
||||
estimateShallowMemoryUsageOf(req);
|
||||
// => 167
|
||||
|
||||
const array = Array(1024).fill({ a: 1 });
|
||||
// Arrays are usually not stored contiguously in memory, so this will not return a useful value (which isn't a bug).
|
||||
estimateShallowMemoryUsageOf(array);
|
||||
// => 16
|
||||
```
|
||||
|
||||
@@ -279,19 +279,6 @@ $ bun build --compile --asset-naming="[name].[ext]" ./index.ts
|
||||
|
||||
To trim down the size of the executable a little, pass `--minify` to `bun build --compile`. This uses Bun's minifier to reduce the code size. Overall though, Bun's binary is still way too big and we need to make it smaller.
|
||||
|
||||
## Windows-specific flags
|
||||
|
||||
When compiling a standalone executable on Windows, there are two platform-specific options that can be used to customize metadata on the generated `.exe` file:
|
||||
|
||||
- `--windows-icon=path/to/icon.ico` to customize the executable file icon.
|
||||
- `--windows-hide-console` to disable the background terminal, which can be used for applications that do not need a TTY.
|
||||
|
||||
{% callout %}
|
||||
|
||||
These flags currently cannot be used when cross-compiling because they depend on Windows APIs.
|
||||
|
||||
{% /callout %}
|
||||
|
||||
## Unsupported CLI arguments
|
||||
|
||||
Currently, the `--compile` flag can only accept a single entrypoint at a time and does not support the following flags:
|
||||
|
||||
@@ -1,296 +0,0 @@
|
||||
As of Bun v1.1.44, we've added initial support for bundling frontend apps directly in Bun's HTTP server: `Bun.serve()`. Run your frontend and backend in the same app with no extra steps.
|
||||
|
||||
To get started, import your HTML files and pass them to the `static` option in `Bun.serve()`.
|
||||
|
||||
```ts
|
||||
import dashboard from "./dashboard.html";
|
||||
import homepage from "./index.html";
|
||||
|
||||
const server = Bun.serve({
|
||||
// Add HTML imports to `static`
|
||||
static: {
|
||||
// Bundle & route index.html to "/"
|
||||
"/": homepage,
|
||||
// Bundle & route dashboard.html to "/dashboard"
|
||||
"/dashboard": dashboard,
|
||||
},
|
||||
|
||||
// Enable development mode for:
|
||||
// - Detailed error messages
|
||||
// - Rebuild on request
|
||||
development: true,
|
||||
|
||||
// Handle API requests
|
||||
async fetch(req) {
|
||||
// ...your API code
|
||||
if (req.url.endsWith("/api/users")) {
|
||||
const users = await Bun.sql`SELECT * FROM users`;
|
||||
return Response.json(users);
|
||||
}
|
||||
|
||||
// Return 404 for unmatched routes
|
||||
return new Response("Not Found", { status: 404 });
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`Listening on ${server.url}`)
|
||||
```
|
||||
|
||||
```bash
|
||||
$ bun run app.ts
|
||||
```
|
||||
|
||||
## HTML imports are routes
|
||||
|
||||
The web starts with HTML, and so does Bun's fullstack dev server.
|
||||
|
||||
To specify entrypoints to your frontend, import HTML files into your JavaScript/TypeScript/TSX/JSX files.
|
||||
|
||||
```ts
|
||||
import dashboard from "./dashboard.html";
|
||||
import homepage from "./index.html";
|
||||
```
|
||||
|
||||
These HTML files are used as routes in Bun's dev server you can pass to `Bun.serve()`.
|
||||
|
||||
```ts
|
||||
Bun.serve({
|
||||
static: {
|
||||
"/": homepage,
|
||||
"/dashboard": dashboard,
|
||||
}
|
||||
|
||||
fetch(req) {
|
||||
// ... api requests
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
When you make a request to `/dashboard` or `/`, Bun automatically bundles the `<script>` and `<link>` tags in the HTML files, exposes them as static routes, and serves the result.
|
||||
|
||||
An index.html file like this:
|
||||
|
||||
```html#index.html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Home</title>
|
||||
<link rel="stylesheet" href="./reset.css" />
|
||||
<link rel="stylesheet" href="./styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="./sentry-and-preloads.ts"></script>
|
||||
<script type="module" src="./my-app.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Becomes something like this:
|
||||
|
||||
```html#index.html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Home</title>
|
||||
<link rel="stylesheet" href="/index-[hash].css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/index-[hash].js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### How to use with React
|
||||
|
||||
To use React in your client-side code, import `react-dom/client` and render your app.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#src/backend.ts
|
||||
import dashboard from "../public/dashboard.html";
|
||||
import { serve } from "bun";
|
||||
|
||||
serve({
|
||||
static: {
|
||||
"/": dashboard,
|
||||
},
|
||||
|
||||
async fetch(req) {
|
||||
// ...api requests
|
||||
return new Response("hello world");
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```ts#src/frontend.tsx
|
||||
import "./styles.css";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { App } from "./app.tsx";
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const root = createRoot(document.getElementById("root"));
|
||||
root.render(<App />);
|
||||
});
|
||||
```
|
||||
|
||||
```html#public/dashboard.html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Dashboard</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="../src/frontend.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```css#src/styles.css
|
||||
body {
|
||||
background-color: red;
|
||||
}
|
||||
```
|
||||
|
||||
```tsx#src/app.tsx
|
||||
export function App() {
|
||||
return <div>Hello World</div>;
|
||||
}
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### Development mode
|
||||
|
||||
When building locally, enable development mode by setting `development: true` in `Bun.serve()`.
|
||||
|
||||
```js-diff
|
||||
import homepage from "./index.html";
|
||||
import dashboard from "./dashboard.html";
|
||||
|
||||
Bun.serve({
|
||||
static: {
|
||||
"/": homepage,
|
||||
"/dashboard": dashboard,
|
||||
}
|
||||
|
||||
+ development: true,
|
||||
|
||||
fetch(req) {
|
||||
// ... api requests
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
When `development` is `true`, Bun will:
|
||||
|
||||
- Include the `SourceMap` header in the response so that devtools can show the original source code
|
||||
- Disable minification
|
||||
- Re-bundle assets on each request to a .html file
|
||||
|
||||
#### Production mode
|
||||
|
||||
When serving your app in production, set `development: false` in `Bun.serve()`.
|
||||
|
||||
- Enable in-memory caching of bundled assets. Bun will bundle assets lazily on the first request to an `.html` file, and cache the result in memory until the server restarts.
|
||||
- Enables `Cache-Control` headers and `ETag` headers
|
||||
- Minifies JavaScript/TypeScript/TSX/JSX files
|
||||
|
||||
## Plugins
|
||||
|
||||
Bun's [bundler plugins](https://bun.sh/docs/bundler/plugins) are also supported when bundling static routes.
|
||||
|
||||
To configure plugins for `Bun.serve`, add a `plugins` array in the `[serve.static]` section of your `bunfig.toml`.
|
||||
|
||||
### Using TailwindCSS in HTML routes
|
||||
|
||||
For example, enable TailwindCSS on your routes by installing and adding the `bun-plugin-tailwind` plugin:
|
||||
|
||||
```sh
|
||||
$ bun add bun-plugin-tailwind
|
||||
```
|
||||
```toml#bunfig.toml
|
||||
[serve.static]
|
||||
plugins = ["bun-plugin-tailwind"]
|
||||
```
|
||||
|
||||
This will allow you to use TailwindCSS utility classes in your HTML and CSS files. All you need to do is import `tailwindcss` somewhere:
|
||||
|
||||
```html#index.html
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Home</title>
|
||||
<link rel="stylesheet" href="tailwindcss" />
|
||||
</head>
|
||||
<body>
|
||||
<!-- the rest of your HTML... -->
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Or in your CSS:
|
||||
|
||||
```css#style.css
|
||||
@import "tailwindcss";
|
||||
```
|
||||
|
||||
### Custom plugins
|
||||
|
||||
Any JS file or module which exports a [valid bundler plugin object](https://bun.sh/docs/bundler/plugins#usage) (essentially an object with a `name` and `setup` field) can be placed inside the `plugins` array:
|
||||
|
||||
```toml#bunfig.toml
|
||||
[serve.static]
|
||||
plugins = ["./my-plugin-implementation.ts"]
|
||||
```
|
||||
|
||||
Bun will lazily resolve and load each plugin and use them to bundle your routes.
|
||||
|
||||
## How this works
|
||||
|
||||
Bun uses [`HTMLRewriter`](/docs/api/html-rewriter) to scan for `<script>` and `<link>` tags in HTML files, uses them as entrypoints for [Bun's bundler](/docs/bundler), generates an optimized bundle for the JavaScript/TypeScript/TSX/JSX and CSS files, and serves the result.
|
||||
|
||||
1. **`<script>` processing**
|
||||
|
||||
- Transpiles TypeScript, JSX, and TSX in `<script>` tags
|
||||
- Bundles imported dependencies
|
||||
- Generates sourcemaps for debugging
|
||||
- Minifies when `development` is not `true` in `Bun.serve()`
|
||||
|
||||
```html
|
||||
<script type="module" src="./counter.tsx"></script>
|
||||
```
|
||||
|
||||
2. **`<link>` processing**
|
||||
|
||||
- Processes CSS imports and `<link>` tags
|
||||
- Concatenates CSS files
|
||||
- Rewrites `url` and asset paths to include content-addressable hashes in URLs
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="./styles.css" />
|
||||
```
|
||||
|
||||
3. **`<img>` & asset processing**
|
||||
|
||||
- Links to assets are rewritten to include content-addressable hashes in URLs
|
||||
- Small assets in CSS files are inlined into `data:` URLs, reducing the total number of HTTP requests sent over the wire
|
||||
|
||||
4. **Rewrite HTML**
|
||||
|
||||
- Combines all `<script>` tags into a single `<script>` tag with a content-addressable hash in the URL
|
||||
- Combines all `<link>` tags into a single `<link>` tag with a content-addressable hash in the URL
|
||||
- Outputs a new HTML file
|
||||
|
||||
5. **Serve**
|
||||
|
||||
- All the output files from the bundler are exposed as static routes, using the same mechanism internally as when you pass a `Response` object to [`static` in `Bun.serve()`](/docs/api/http#static-routes).
|
||||
|
||||
This works similarly to how [`Bun.build` processes HTML files](/docs/bundler/html).
|
||||
|
||||
## This is a work in progress
|
||||
|
||||
- Client-side hot reloading isn't wired up yet. It will be in the future.
|
||||
- This doesn't support `bun build` yet. It also will in the future.
|
||||
@@ -1,104 +0,0 @@
|
||||
As of Bun v1.1.43, Bun's bundler now has first-class support for HTML. Build static sites, landing pages, and web applications with zero configuration. Just point Bun at your HTML file and it handles everything else.
|
||||
|
||||
```html#index.html
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="./styles.css" />
|
||||
<script src="./app.ts" type="module"></script>
|
||||
</head>
|
||||
<body>
|
||||
<img src="./logo.png" />
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
One command is all you need (won't be experimental after Bun v1.2):
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```bash#CLI
|
||||
$ bun build ./index.html --outdir=dist
|
||||
```
|
||||
|
||||
```ts#API
|
||||
Bun.build({
|
||||
entrypoints: ["./index.html"],
|
||||
outdir: "./dist",
|
||||
});
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
Bun automatically:
|
||||
|
||||
- Bundles, tree-shakes, and optimizes your JavaScript, JSX and TypeScript
|
||||
- Bundles and optimizes your CSS
|
||||
- Copies & hashes images and other assets
|
||||
- Updates all references to local files or packages in your HTML
|
||||
|
||||
## Zero Config, Maximum Performance
|
||||
|
||||
The HTML bundler is enabled by default after Bun v1.2+. Drop in your existing HTML files and Bun will handle:
|
||||
|
||||
- **TypeScript & JSX** - Write modern JavaScript for browsers without the setup
|
||||
- **CSS** - Bundle CSS stylesheets directly from `<link rel="stylesheet">` or `@import`
|
||||
- **Images & Assets** - Automatic copying & hashing & rewriting of assets in JavaScript, CSS, and HTML
|
||||
|
||||
## Watch mode
|
||||
|
||||
You can run `bun build --watch` to watch for changes and rebuild automatically.
|
||||
|
||||
You've never seen a watch mode this fast.
|
||||
|
||||
## Plugin API
|
||||
|
||||
Need more control? Configure the bundler through the JavaScript API and use Bun's builtin `HTMLRewriter` to preprocess HTML.
|
||||
|
||||
```ts
|
||||
await Bun.build({
|
||||
entrypoints: ["./index.html"],
|
||||
outdir: "./dist",
|
||||
minify: true,
|
||||
|
||||
plugins: [
|
||||
{
|
||||
// A plugin that makes every HTML tag lowercase
|
||||
name: "lowercase-html-plugin",
|
||||
setup({ onLoad }) {
|
||||
const rewriter = new HTMLRewriter().on("*", {
|
||||
element(element) {
|
||||
element.tagName = element.tagName.toLowerCase();
|
||||
},
|
||||
text(element) {
|
||||
element.replace(element.text.toLowerCase());
|
||||
},
|
||||
});
|
||||
|
||||
onLoad({ filter: /\.html$/ }, async args => {
|
||||
const html = await Bun.file(args.path).text();
|
||||
|
||||
return {
|
||||
// Bun's bundler will scan the HTML for <script> tags, <link rel="stylesheet"> tags, and other assets
|
||||
// and bundle them automatically
|
||||
contents: rewriter.transform(html),
|
||||
loader: "html",
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## What Gets Processed?
|
||||
|
||||
Bun automatically handles all common web assets:
|
||||
|
||||
- Scripts (`<script src>`) are run through Bun's JavaScript/TypeScript/JSX bundler
|
||||
- Stylesheets (`<link rel="stylesheet">`) are run through Bun's CSS parser & bundler
|
||||
- Images (`<img>`, `<picture>`) are copied and hashed
|
||||
- Media (`<video>`, `<audio>`, `<source>`) are copied and hashed
|
||||
- Any `<link>` tag with an `href` attribute pointing to a local file is rewritten to the new path, and hashed
|
||||
|
||||
All paths are resolved relative to your HTML file, making it easy to organize your project however you want.
|
||||
@@ -533,8 +533,7 @@ export type BuildManifest = {
|
||||
};
|
||||
|
||||
export type ImportKind =
|
||||
| "entry-point-build"
|
||||
| "entry-point-run"
|
||||
| "entry-point"
|
||||
| "import-statement"
|
||||
| "require-call"
|
||||
| "dynamic-import"
|
||||
@@ -1258,6 +1257,24 @@ $ bun build ./index.tsx --outdir ./out --drop=console --drop=debugger --drop=any
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### `experimentalCss`
|
||||
|
||||
Whether to enable _experimental_ support for bundling CSS files. Defaults to `false`.
|
||||
|
||||
This supports bundling CSS files imported from JS, as well as CSS entrypoints.
|
||||
|
||||
{% codetabs group="a" %}
|
||||
|
||||
```ts#JavaScript
|
||||
const result = await Bun.build({
|
||||
entrypoints: ["./index.ts"],
|
||||
experimentalCss: true,
|
||||
});
|
||||
// => { success: boolean, outputs: BuildArtifact[], logs: BuildMessage[] }
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
## Outputs
|
||||
|
||||
The `Bun.build` function returns a `Promise<BuildOutput>`, defined as:
|
||||
@@ -1397,36 +1414,24 @@ Refer to [Bundler > Executables](https://bun.sh/docs/bundler/executables) for co
|
||||
|
||||
## Logs and errors
|
||||
|
||||
<!-- 1.2 documentation -->
|
||||
|
||||
On failure, `Bun.build` returns a rejected promise with an `AggregateError`. This can be logged to the console for pretty printing of the error list, or programmatically read with a `try`/`catch` block.
|
||||
`Bun.build` only throws if invalid options are provided. Read the `success` property to determine if the build was successful; the `logs` property will contain additional details.
|
||||
|
||||
```ts
|
||||
try {
|
||||
const result = await Bun.build({
|
||||
entrypoints: ["./index.tsx"],
|
||||
outdir: "./out",
|
||||
});
|
||||
} catch (e) {
|
||||
// TypeScript does not allow annotations on the catch clause
|
||||
const error = e as AggregateError;
|
||||
console.error("Build Failed");
|
||||
const result = await Bun.build({
|
||||
entrypoints: ["./index.tsx"],
|
||||
outdir: "./out",
|
||||
});
|
||||
|
||||
// Example: Using the built-in formatter
|
||||
console.error(error);
|
||||
|
||||
// Example: Serializing the failure as a JSON string.
|
||||
console.error(JSON.stringify(error, null, 2));
|
||||
if (!result.success) {
|
||||
console.error("Build failed");
|
||||
for (const message of result.logs) {
|
||||
// Bun will pretty print the message object
|
||||
console.error(message);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
|
||||
Most of the time, an explicit `try`/`catch` is not needed, as Bun will neatly print uncaught exceptions. It is enough to just use a top-level `await` on the `Bun.build` call.
|
||||
|
||||
{% /callout %}
|
||||
|
||||
Each item in `error.errors` is an instance of `BuildMessage` or `ResolveMessage` (subclasses of Error), containing detailed information for each error.
|
||||
Each message is either a `BuildMessage` or `ResolveMessage` object, which can be used to trace what problems happened in the build.
|
||||
|
||||
```ts
|
||||
class BuildMessage {
|
||||
@@ -1444,20 +1449,11 @@ class ResolveMessage extends BuildMessage {
|
||||
}
|
||||
```
|
||||
|
||||
On build success, the returned object contains a `logs` property, which contains bundler warnings and info messages.
|
||||
If you want to throw an error from a failed build, consider passing the logs to an `AggregateError`. If uncaught, Bun will pretty-print the contained messages nicely.
|
||||
|
||||
```ts
|
||||
const result = await Bun.build({
|
||||
entrypoints: ["./index.tsx"],
|
||||
outdir: "./out",
|
||||
});
|
||||
|
||||
if (result.logs.length > 0) {
|
||||
console.warn("Build succeeded with warnings:");
|
||||
for (const message of result.logs) {
|
||||
// Bun will pretty print the message object
|
||||
console.warn(message);
|
||||
}
|
||||
if (!result.success) {
|
||||
throw new AggregateError(result.logs, "Build failed");
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1482,23 +1478,39 @@ interface BuildConfig {
|
||||
*
|
||||
* @default "esm"
|
||||
*/
|
||||
format?: "esm" | "cjs" | "iife";
|
||||
format?: /**
|
||||
|
||||
* ECMAScript Module format
|
||||
*/
|
||||
| "esm"
|
||||
/**
|
||||
* CommonJS format
|
||||
* **Experimental**
|
||||
*/
|
||||
| "cjs"
|
||||
/**
|
||||
* IIFE format
|
||||
* **Experimental**
|
||||
*/
|
||||
| "iife";
|
||||
naming?:
|
||||
| string
|
||||
| {
|
||||
chunk?: string;
|
||||
entry?: string;
|
||||
asset?: string;
|
||||
};
|
||||
}; // | string;
|
||||
root?: string; // project root
|
||||
splitting?: boolean; // default true, enable code splitting
|
||||
plugins?: BunPlugin[];
|
||||
// manifest?: boolean; // whether to return manifest
|
||||
external?: string[];
|
||||
packages?: "bundle" | "external";
|
||||
publicPath?: string;
|
||||
define?: Record<string, string>;
|
||||
// origin?: string; // e.g. http://mydomain.com
|
||||
loader?: { [k in string]: Loader };
|
||||
sourcemap?: "none" | "linked" | "inline" | "external" | "linked" | boolean; // default: "none", true -> "inline"
|
||||
sourcemap?: "none" | "linked" | "inline" | "external" | "linked"; // default: "none", true -> "inline"
|
||||
/**
|
||||
* package.json `exports` conditions used when resolving imports
|
||||
*
|
||||
@@ -1507,18 +1519,6 @@ interface BuildConfig {
|
||||
* https://nodejs.org/api/packages.html#exports
|
||||
*/
|
||||
conditions?: Array<string> | string;
|
||||
|
||||
/**
|
||||
* Controls how environment variables are handled during bundling.
|
||||
*
|
||||
* Can be one of:
|
||||
* - `"inline"`: Injects environment variables into the bundled output by converting `process.env.FOO`
|
||||
* references to string literals containing the actual environment variable values
|
||||
* - `"disable"`: Disables environment variable injection entirely
|
||||
* - A string ending in `*`: Inlines environment variables that match the given prefix.
|
||||
* For example, `"MY_PUBLIC_*"` will only include env vars starting with "MY_PUBLIC_"
|
||||
*/
|
||||
env?: "inline" | "disable" | `${string}*`;
|
||||
minify?:
|
||||
| boolean
|
||||
| {
|
||||
@@ -1536,6 +1536,20 @@ interface BuildConfig {
|
||||
* Force emitting @__PURE__ annotations even if minify.whitespace is true.
|
||||
*/
|
||||
emitDCEAnnotations?: boolean;
|
||||
// treeshaking?: boolean;
|
||||
|
||||
// jsx?:
|
||||
// | "automatic"
|
||||
// | "classic"
|
||||
// | /* later: "preserve" */ {
|
||||
// runtime?: "automatic" | "classic"; // later: "preserve"
|
||||
// /** Only works when runtime=classic */
|
||||
// factory?: string; // default: "React.createElement"
|
||||
// /** Only works when runtime=classic */
|
||||
// fragment?: string; // default: "React.Fragment"
|
||||
// /** Only works when runtime=automatic */
|
||||
// importSource?: string; // default: "react"
|
||||
// };
|
||||
|
||||
/**
|
||||
* Generate bytecode for the output. This can dramatically improve cold
|
||||
@@ -1548,30 +1562,6 @@ interface BuildConfig {
|
||||
* @default false
|
||||
*/
|
||||
bytecode?: boolean;
|
||||
/**
|
||||
* Add a banner to the bundled code such as "use client";
|
||||
*/
|
||||
banner?: string;
|
||||
/**
|
||||
* Add a footer to the bundled code such as a comment block like
|
||||
*
|
||||
* `// made with bun!`
|
||||
*/
|
||||
footer?: string;
|
||||
|
||||
/**
|
||||
* Drop function calls to matching property accesses.
|
||||
*/
|
||||
drop?: string[];
|
||||
|
||||
/**
|
||||
* When set to `true`, the returned promise rejects with an AggregateError when a build failure happens.
|
||||
* When set to `false`, the `success` property of the returned object will be `false` when a build failure happens.
|
||||
*
|
||||
* This defaults to `false` in Bun 1.1 and will change to `true` in Bun 1.2
|
||||
* as most usage of `Bun.build` forgets to check for errors.
|
||||
*/
|
||||
throw?: boolean;
|
||||
}
|
||||
|
||||
interface BuildOutput {
|
||||
@@ -1629,3 +1619,32 @@ declare class ResolveMessage {
|
||||
toString(): string;
|
||||
}
|
||||
```
|
||||
|
||||
<!--
|
||||
interface BuildManifest {
|
||||
inputs: {
|
||||
[path: string]: {
|
||||
output: {
|
||||
path: string;
|
||||
};
|
||||
imports: {
|
||||
path: string;
|
||||
kind: ImportKind;
|
||||
external?: boolean;
|
||||
asset?: boolean; // whether the import defaulted to "file" loader
|
||||
}[];
|
||||
};
|
||||
};
|
||||
outputs: {
|
||||
[path: string]: {
|
||||
type: "chunk" | "entrypoint" | "asset";
|
||||
inputs: { path: string }[];
|
||||
imports: {
|
||||
path: string;
|
||||
kind: ImportKind;
|
||||
external?: boolean;
|
||||
}[];
|
||||
exports: string[];
|
||||
};
|
||||
};
|
||||
} -->
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The Bun bundler implements a set of default loaders out of the box. As a rule of thumb, the bundler and the runtime both support the same set of file types out of the box.
|
||||
|
||||
`.js` `.cjs` `.mjs` `.mts` `.cts` `.ts` `.tsx` `.jsx` `.toml` `.json` `.txt` `.wasm` `.node` `.html`
|
||||
`.js` `.cjs` `.mjs` `.mts` `.cts` `.ts` `.tsx` `.jsx` `.toml` `.json` `.txt` `.wasm` `.node`
|
||||
|
||||
Bun uses the file extension to determine which built-in _loader_ should be used to parse the file. Every loader has a name, such as `js`, `tsx`, or `json`. These names are used when building [plugins](https://bun.sh/docs/bundler/plugins) that extend Bun with custom loaders.
|
||||
|
||||
@@ -152,6 +152,19 @@ export default "Hello, world!";
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### `wasm`
|
||||
|
||||
**WebAssembly loader**. Default for `.wasm`.
|
||||
|
||||
In the runtime, WebAssembly files can be directly imported. The file is read and returned as a `WebAssembly.Module`.
|
||||
|
||||
```ts
|
||||
import wasm from "./module.wasm";
|
||||
console.log(wasm); // => WebAssembly.Module
|
||||
```
|
||||
|
||||
In the bundler, `.wasm` files are handled using the [`file`](#file) loader.
|
||||
|
||||
### `napi`
|
||||
|
||||
**Native addon loader**. Default for `.node`.
|
||||
@@ -190,74 +203,6 @@ When using a [standalone executable](https://bun.sh/docs/bundler/executables), t
|
||||
|
||||
Otherwise, the database to embed is copied into the `outdir` with a hashed filename.
|
||||
|
||||
### `html`
|
||||
|
||||
**HTML loader**. Default for `.html` after Bun v1.2.0.
|
||||
|
||||
The html loader processes HTML files and bundles any referenced assets. It will:
|
||||
|
||||
- Bundle and hash referenced JavaScript files (`<script src="...">`)
|
||||
- Bundle and hash referenced CSS files (`<link rel="stylesheet" href="...">`)
|
||||
- Hash referenced images (`<img src="...">`)
|
||||
- Preserve external URLs (by default, anything starting with `http://` or `https://`)
|
||||
|
||||
For example, given this HTML file:
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```html#src/index.html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<img src="./image.jpg" alt="Local image">
|
||||
<img src="https://example.com/image.jpg" alt="External image">
|
||||
<script type="module" src="./script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
It will output a new HTML file with the bundled assets:
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```html#dist/output.html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<img src="./image-HASHED.jpg" alt="Local image">
|
||||
<img src="https://example.com/image.jpg" alt="External image">
|
||||
<script type="module" src="./output-ALSO-HASHED.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
Under the hood, it uses [`lol-html`](https://github.com/cloudflare/lol-html) to extract script and link tags as entrypoints, and other assets as external.
|
||||
|
||||
Currently, the list of selectors is:
|
||||
|
||||
- `audio[src]`
|
||||
- `iframe[src]`
|
||||
- `img[src]`
|
||||
- `img[srcset]`
|
||||
- `link:not([rel~='stylesheet']):not([rel~='modulepreload']):not([rel~='manifest']):not([rel~='icon']):not([rel~='apple-touch-icon'])[href]`
|
||||
- `link[as='font'][href], link[type^='font/'][href]`
|
||||
- `link[as='image'][href]`
|
||||
- `link[as='style'][href]`
|
||||
- `link[as='video'][href], link[as='audio'][href]`
|
||||
- `link[as='worker'][href]`
|
||||
- `link[rel='icon'][href], link[rel='apple-touch-icon'][href]`
|
||||
- `link[rel='manifest'][href]`
|
||||
- `link[rel='stylesheet'][href]`
|
||||
- `script[src]`
|
||||
- `source[src]`
|
||||
- `source[srcset]`
|
||||
- `video[poster]`
|
||||
- `video[src]`
|
||||
|
||||
### `sh` loader
|
||||
|
||||
**Bun Shell loader**. Default for `.sh` files
|
||||
|
||||
@@ -2,47 +2,11 @@ Bun provides a universal plugin API that can be used to extend both the _runtime
|
||||
|
||||
Plugins intercept imports and perform custom loading logic: reading files, transpiling code, etc. They can be used to add support for additional file types, like `.scss` or `.yaml`. In the context of Bun's bundler, plugins can be used to implement framework-level features like CSS extraction, macros, and client-server code co-location.
|
||||
|
||||
## Lifecycle hooks
|
||||
|
||||
Plugins can register callbacks to be run at various points in the lifecycle of a bundle:
|
||||
|
||||
- [`onStart()`](#onstart): Run once the bundler has started a bundle
|
||||
- [`onResolve()`](#onresolve): Run before a module is resolved
|
||||
- [`onLoad()`](#onload): Run before a module is loaded.
|
||||
- [`onBeforeParse()`](#onbeforeparse): Run zero-copy native addons in the parser thread before a file is parsed.
|
||||
|
||||
### Reference
|
||||
|
||||
A rough overview of the types (please refer to Bun's `bun.d.ts` for the full type definitions):
|
||||
|
||||
```ts
|
||||
type PluginBuilder = {
|
||||
onStart(callback: () => void): void;
|
||||
onResolve: (
|
||||
args: { filter: RegExp; namespace?: string },
|
||||
callback: (args: { path: string; importer: string }) => {
|
||||
path: string;
|
||||
namespace?: string;
|
||||
} | void,
|
||||
) => void;
|
||||
onLoad: (
|
||||
args: { filter: RegExp; namespace?: string },
|
||||
defer: () => Promise<void>,
|
||||
callback: (args: { path: string }) => {
|
||||
loader?: Loader;
|
||||
contents?: string;
|
||||
exports?: Record<string, any>;
|
||||
},
|
||||
) => void;
|
||||
config: BuildConfig;
|
||||
};
|
||||
|
||||
type Loader = "js" | "jsx" | "ts" | "tsx" | "css" | "json" | "toml";
|
||||
```
|
||||
For more complete documentation of the Plugin API, see [Runtime > Plugins](https://bun.sh/docs/runtime/plugins).
|
||||
|
||||
## Usage
|
||||
|
||||
A plugin is defined as simple JavaScript object containing a `name` property and a `setup` function.
|
||||
A plugin is defined as simple JavaScript object containing a `name` property and a `setup` function. Register a plugin with Bun using the `plugin` function.
|
||||
|
||||
```tsx#myPlugin.ts
|
||||
import type { BunPlugin } from "bun";
|
||||
@@ -58,343 +22,9 @@ const myPlugin: BunPlugin = {
|
||||
This plugin can be passed into the `plugins` array when calling `Bun.build`.
|
||||
|
||||
```ts
|
||||
await Bun.build({
|
||||
Bun.build({
|
||||
entrypoints: ["./app.ts"],
|
||||
outdir: "./out",
|
||||
plugins: [myPlugin],
|
||||
});
|
||||
```
|
||||
|
||||
## Plugin lifecycle
|
||||
|
||||
### Namespaces
|
||||
|
||||
`onLoad` and `onResolve` accept an optional `namespace` string. What is a namespace?
|
||||
|
||||
Every module has a namespace. Namespaces are used to prefix the import in transpiled code; for instance, a loader with a `filter: /\.yaml$/` and `namespace: "yaml:"` will transform an import from `./myfile.yaml` into `yaml:./myfile.yaml`.
|
||||
|
||||
The default namespace is `"file"` and it is not necessary to specify it, for instance: `import myModule from "./my-module.ts"` is the same as `import myModule from "file:./my-module.ts"`.
|
||||
|
||||
Other common namespaces are:
|
||||
|
||||
- `"bun"`: for Bun-specific modules (e.g. `"bun:test"`, `"bun:sqlite"`)
|
||||
- `"node"`: for Node.js modules (e.g. `"node:fs"`, `"node:path"`)
|
||||
|
||||
### `onStart`
|
||||
|
||||
```ts
|
||||
onStart(callback: () => void): Promise<void> | void;
|
||||
```
|
||||
|
||||
Registers a callback to be run when the bundler starts a new bundle.
|
||||
|
||||
```ts
|
||||
import { plugin } from "bun";
|
||||
|
||||
plugin({
|
||||
name: "onStart example",
|
||||
|
||||
setup(build) {
|
||||
build.onStart(() => {
|
||||
console.log("Bundle started!");
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The callback can return a `Promise`. After the bundle process has initialized, the bundler waits until all `onStart()` callbacks have completed before continuing.
|
||||
|
||||
For example:
|
||||
|
||||
```ts
|
||||
const result = await Bun.build({
|
||||
entrypoints: ["./app.ts"],
|
||||
outdir: "./dist",
|
||||
sourcemap: "external",
|
||||
plugins: [
|
||||
{
|
||||
name: "Sleep for 10 seconds",
|
||||
setup(build) {
|
||||
build.onStart(async () => {
|
||||
await Bunlog.sleep(10_000);
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Log bundle time to a file",
|
||||
setup(build) {
|
||||
build.onStart(async () => {
|
||||
const now = Date.now();
|
||||
await Bun.$`echo ${now} > bundle-time.txt`;
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
In the above example, Bun will wait until the first `onStart()` (sleeping for 10 seconds) has completed, _as well as_ the second `onStart()` (writing the bundle time to a file).
|
||||
|
||||
Note that `onStart()` callbacks (like every other lifecycle callback) do not have the ability to modify the `build.config` object. If you want to mutate `build.config`, you must do so directly in the `setup()` function.
|
||||
|
||||
### `onResolve`
|
||||
|
||||
```ts
|
||||
onResolve(
|
||||
args: { filter: RegExp; namespace?: string },
|
||||
callback: (args: { path: string; importer: string }) => {
|
||||
path: string;
|
||||
namespace?: string;
|
||||
} | void,
|
||||
): void;
|
||||
```
|
||||
|
||||
To bundle your project, Bun walks down the dependency tree of all modules in your project. For each imported module, Bun actually has to find and read that module. The "finding" part is known as "resolving" a module.
|
||||
|
||||
The `onResolve()` plugin lifecycle callback allows you to configure how a module is resolved.
|
||||
|
||||
The first argument to `onResolve()` is an object with a `filter` and [`namespace`](#what-is-a-namespace) property. The filter is a regular expression which is run on the import string. Effectively, these allow you to filter which modules your custom resolution logic will apply to.
|
||||
|
||||
The second argument to `onResolve()` is a callback which is run for each module import Bun finds that matches the `filter` and `namespace` defined in the first argument.
|
||||
|
||||
The callback receives as input the _path_ to the matching module. The callback can return a _new path_ for the module. Bun will read the contents of the _new path_ and parse it as a module.
|
||||
|
||||
For example, redirecting all imports to `images/` to `./public/images/`:
|
||||
|
||||
```ts
|
||||
import { plugin } from "bun";
|
||||
|
||||
plugin({
|
||||
name: "onResolve example",
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /.*/, namespace: "file" }, args => {
|
||||
if (args.path.startsWith("images/")) {
|
||||
return {
|
||||
path: args.path.replace("images/", "./public/images/"),
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### `onLoad`
|
||||
|
||||
```ts
|
||||
onLoad(
|
||||
args: { filter: RegExp; namespace?: string },
|
||||
defer: () => Promise<void>,
|
||||
callback: (args: { path: string, importer: string, namespace: string, kind: ImportKind }) => {
|
||||
loader?: Loader;
|
||||
contents?: string;
|
||||
exports?: Record<string, any>;
|
||||
},
|
||||
): void;
|
||||
```
|
||||
|
||||
After Bun's bundler has resolved a module, it needs to read the contents of the module and parse it.
|
||||
|
||||
The `onLoad()` plugin lifecycle callback allows you to modify the _contents_ of a module before it is read and parsed by Bun.
|
||||
|
||||
Like `onResolve()`, the first argument to `onLoad()` allows you to filter which modules this invocation of `onLoad()` will apply to.
|
||||
|
||||
The second argument to `onLoad()` is a callback which is run for each matching module _before_ Bun loads the contents of the module into memory.
|
||||
|
||||
This callback receives as input the _path_ to the matching module, the _importer_ of the module (the module that imported the module), the _namespace_ of the module, and the _kind_ of the module.
|
||||
|
||||
The callback can return a new `contents` string for the module as well as a new `loader`.
|
||||
|
||||
For example:
|
||||
|
||||
```ts
|
||||
import { plugin } from "bun";
|
||||
|
||||
const envPlugin: BunPlugin = {
|
||||
name: "env plugin",
|
||||
setup(build) {
|
||||
build.onLoad({ filter: /env/, namespace: "file" }, args => {
|
||||
return {
|
||||
contents: `export default ${JSON.stringify(process.env)}`,
|
||||
loader: "js",
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Bun.build({
|
||||
entrypoints: ["./app.ts"],
|
||||
outdir: "./dist",
|
||||
plugins: [envPlugin],
|
||||
});
|
||||
|
||||
// import env from "env"
|
||||
// env.FOO === "bar"
|
||||
```
|
||||
|
||||
This plugin will transform all imports of the form `import env from "env"` into a JavaScript module that exports the current environment variables.
|
||||
|
||||
#### `.defer()`
|
||||
|
||||
One of the arguments passed to the `onLoad` callback is a `defer` function. This function returns a `Promise` that is resolved when all _other_ modules have been loaded.
|
||||
|
||||
This allows you to delay execution of the `onLoad` callback until all other modules have been loaded.
|
||||
|
||||
This is useful for returning contents of a module that depends on other modules.
|
||||
|
||||
##### Example: tracking and reporting unused exports
|
||||
|
||||
```ts
|
||||
import { plugin } from "bun";
|
||||
|
||||
plugin({
|
||||
name: "track imports",
|
||||
setup(build) {
|
||||
const transpiler = new Bun.Transpiler();
|
||||
|
||||
let trackedImports: Record<string, number> = {};
|
||||
|
||||
// Each module that goes through this onLoad callback
|
||||
// will record its imports in `trackedImports`
|
||||
build.onLoad({ filter: /\.ts/ }, async ({ path }) => {
|
||||
const contents = await Bun.file(path).arrayBuffer();
|
||||
|
||||
const imports = transpiler.scanImports(contents);
|
||||
|
||||
for (const i of imports) {
|
||||
trackedImports[i.path] = (trackedImports[i.path] || 0) + 1;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
build.onLoad({ filter: /stats\.json/ }, async ({ defer }) => {
|
||||
// Wait for all files to be loaded, ensuring
|
||||
// that every file goes through the above `onLoad()` function
|
||||
// and their imports tracked
|
||||
await defer();
|
||||
|
||||
// Emit JSON containing the stats of each import
|
||||
return {
|
||||
contents: `export default ${JSON.stringify(trackedImports)}`,
|
||||
loader: "json",
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Note that the `.defer()` function currently has the limitation that it can only be called once per `onLoad` callback.
|
||||
|
||||
## Native plugins
|
||||
|
||||
One of the reasons why Bun's bundler is so fast is that it is written in native code and leverages multi-threading to load and parse modules in parallel.
|
||||
|
||||
However, one limitation of plugins written in JavaScript is that JavaScript itself is single-threaded.
|
||||
|
||||
Native plugins are written as [NAPI](https://bun.sh/docs/api/node-api) modules and can be run on multiple threads. This allows native plugins to run much faster than JavaScript plugins.
|
||||
|
||||
In addition, native plugins can skip unnecessary work such as the UTF-8 -> UTF-16 conversion needed to pass strings to JavaScript.
|
||||
|
||||
These are the following lifecycle hooks which are available to native plugins:
|
||||
|
||||
- [`onBeforeParse()`](#onbeforeparse): Called on any thread before a file is parsed by Bun's bundler.
|
||||
|
||||
Native plugins are NAPI modules which expose lifecycle hooks as C ABI functions.
|
||||
|
||||
To create a native plugin, you must export a C ABI function which matches the signature of the native lifecycle hook you want to implement.
|
||||
|
||||
### Creating a native plugin in Rust
|
||||
|
||||
Native plugins are NAPI modules which expose lifecycle hooks as C ABI functions.
|
||||
|
||||
To create a native plugin, you must export a C ABI function which matches the signature of the native lifecycle hook you want to implement.
|
||||
|
||||
```bash
|
||||
bun add -g @napi-rs/cli
|
||||
napi new
|
||||
```
|
||||
|
||||
Then install this crate:
|
||||
|
||||
```bash
|
||||
cargo add bun-native-plugin
|
||||
```
|
||||
|
||||
Now, inside the `lib.rs` file, we'll use the `bun_native_plugin::bun` proc macro to define a function which
|
||||
will implement our native plugin.
|
||||
|
||||
Here's an example implementing the `onBeforeParse` hook:
|
||||
|
||||
```rs
|
||||
use bun_native_plugin::{define_bun_plugin, OnBeforeParse, bun, Result, anyhow, BunLoader};
|
||||
use napi_derive::napi;
|
||||
|
||||
/// Define the plugin and its name
|
||||
define_bun_plugin!("replace-foo-with-bar");
|
||||
|
||||
/// Here we'll implement `onBeforeParse` with code that replaces all occurrences of
|
||||
/// `foo` with `bar`.
|
||||
///
|
||||
/// We use the #[bun] macro to generate some of the boilerplate code.
|
||||
///
|
||||
/// The argument of the function (`handle: &mut OnBeforeParse`) tells
|
||||
/// the macro that this function implements the `onBeforeParse` hook.
|
||||
#[bun]
|
||||
pub fn replace_foo_with_bar(handle: &mut OnBeforeParse) -> Result<()> {
|
||||
// Fetch the input source code.
|
||||
let input_source_code = handle.input_source_code()?;
|
||||
|
||||
// Get the Loader for the file
|
||||
let loader = handle.output_loader();
|
||||
|
||||
|
||||
let output_source_code = input_source_code.replace("foo", "bar");
|
||||
|
||||
handle.set_output_source_code(output_source_code, BunLoader::BUN_LOADER_JSX);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
And to use it in Bun.build():
|
||||
|
||||
```typescript
|
||||
import myNativeAddon from "./my-native-addon";
|
||||
Bun.build({
|
||||
entrypoints: ["./app.tsx"],
|
||||
plugins: [
|
||||
{
|
||||
name: "my-plugin",
|
||||
|
||||
setup(build) {
|
||||
build.onBeforeParse(
|
||||
{
|
||||
namespace: "file",
|
||||
filter: "**/*.tsx",
|
||||
},
|
||||
{
|
||||
napiModule: myNativeAddon,
|
||||
symbol: "replace_foo_with_bar",
|
||||
// external: myNativeAddon.getSharedState()
|
||||
},
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
### `onBeforeParse`
|
||||
|
||||
```ts
|
||||
onBeforeParse(
|
||||
args: { filter: RegExp; namespace?: string },
|
||||
callback: { napiModule: NapiModule; symbol: string; external?: unknown },
|
||||
): void;
|
||||
```
|
||||
|
||||
This lifecycle callback is run immediately before a file is parsed by Bun's bundler.
|
||||
|
||||
As input, it receives the file's contents and can optionally return new source code.
|
||||
|
||||
This callback can be called from any thread and so the napi module implementation must be thread-safe.
|
||||
|
||||
@@ -695,7 +695,7 @@ In Bun's CLI, simple boolean flags like `--minify` do not accept an argument. Ot
|
||||
- In Bun, `minify` can be a boolean or an object.
|
||||
|
||||
```ts
|
||||
await Bun.build({
|
||||
Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
// enable all minification
|
||||
minify: true
|
||||
|
||||
@@ -33,14 +33,6 @@ To add a package as an optional dependency (`"optionalDependencies"`):
|
||||
$ bun add --optional lodash
|
||||
```
|
||||
|
||||
## `--peer`
|
||||
|
||||
To add a package as a peer dependency (`"peerDependencies"`):
|
||||
|
||||
```bash
|
||||
$ bun add --peer @types/bun
|
||||
```
|
||||
|
||||
## `--exact`
|
||||
|
||||
{% callout %}
|
||||
|
||||
@@ -47,9 +47,6 @@ registry = "https://registry.yarnpkg.com/"
|
||||
# Install for production? This is the equivalent to the "--production" CLI argument
|
||||
production = false
|
||||
|
||||
# Save a text-based lockfile? This is equivalent to the "--save-text-lockfile" CLI argument
|
||||
saveTextLockfile = false
|
||||
|
||||
# Disallow changes to lockfile? This is the equivalent to the "--frozen-lockfile" CLI argument
|
||||
frozenLockfile = false
|
||||
|
||||
@@ -57,15 +54,12 @@ frozenLockfile = false
|
||||
dryRun = true
|
||||
|
||||
# Install optionalDependencies (default: true)
|
||||
# Setting this to false is equivalent to the `--omit=optional` CLI argument
|
||||
optional = true
|
||||
|
||||
# Install local devDependencies (default: true)
|
||||
# Setting this to false is equivalent to the `--omit=dev` CLI argument
|
||||
dev = true
|
||||
|
||||
# Install peerDependencies (default: true)
|
||||
# Setting this to false is equivalent to the `--omit=peer` CLI argument
|
||||
peer = true
|
||||
|
||||
# Max number of concurrent lifecycle scripts (default: (cpu count or GOMAXPROCS) x2)
|
||||
@@ -95,7 +89,7 @@ disableManifest = false
|
||||
[install.lockfile]
|
||||
|
||||
# Print a yarn v1 lockfile
|
||||
# Note: it does not load the lockfile, it just converts bun.lock into a yarn.lock
|
||||
# Note: it does not load the lockfile, it just converts bun.lockb into a yarn.lock
|
||||
print = "yarn"
|
||||
|
||||
# Save the lockfile to disk
|
||||
@@ -114,7 +108,6 @@ export interface Install {
|
||||
scopes: Scopes;
|
||||
registry: Registry;
|
||||
production: boolean;
|
||||
saveTextLockfile: boolean;
|
||||
frozenLockfile: boolean;
|
||||
dryRun: boolean;
|
||||
optional: boolean;
|
||||
@@ -170,9 +163,9 @@ Bun stores installed packages from npm in `~/.bun/install/cache/${name}@${versio
|
||||
|
||||
When the `node_modules` folder exists, before installing, Bun checks if the `"name"` and `"version"` in `package/package.json` in the expected node_modules folder matches the expected `name` and `version`. This is how it determines whether it should install. It uses a custom JSON parser which stops parsing as soon as it finds `"name"` and `"version"`.
|
||||
|
||||
When a `bun.lock` doesn’t exist or `package.json` has changed dependencies, tarballs are downloaded & extracted eagerly while resolving.
|
||||
When a `bun.lockb` doesn’t exist or `package.json` has changed dependencies, tarballs are downloaded & extracted eagerly while resolving.
|
||||
|
||||
When a `bun.lock` exists and `package.json` hasn’t changed, Bun downloads missing dependencies lazily. If the package with a matching `name` & `version` already exists in the expected location within `node_modules`, Bun won’t attempt to download the tarball.
|
||||
When a `bun.lockb` exists and `package.json` hasn’t changed, Bun downloads missing dependencies lazily. If the package with a matching `name` & `version` already exists in the expected location within `node_modules`, Bun won’t attempt to download the tarball.
|
||||
|
||||
## Platform-specific dependencies?
|
||||
|
||||
@@ -184,9 +177,23 @@ Peer dependencies are handled similarly to yarn. `bun install` will automaticall
|
||||
|
||||
## Lockfile
|
||||
|
||||
`bun.lock` is Bun’s lockfile format. See [our blogpost about the text lockfile](https://bun.sh/blog/bun-lock-text-lockfile).
|
||||
`bun.lockb` is Bun’s binary lockfile format.
|
||||
|
||||
Prior to Bun 1.2, the lockfile was binary and called `bun.lockb`. Old lockfiles can be upgraded to the new format by running `bun install --save-text-lockfile --frozen-lockfile --lockfile-only`, and then deleting `bun.lockb`.
|
||||
## Why is it binary?
|
||||
|
||||
In a word: Performance. Bun’s lockfile saves & loads incredibly quickly, and saves a lot more data than what is typically inside lockfiles.
|
||||
|
||||
## How do I inspect it?
|
||||
|
||||
For now, the easiest thing is to run `bun install -y`. That prints a Yarn v1-style yarn.lock file.
|
||||
|
||||
## What does the lockfile store?
|
||||
|
||||
Packages, metadata for those packages, the hoisted install order, dependencies for each package, what packages those dependencies resolved to, an integrity hash (if available), what each package was resolved to and which version (or equivalent).
|
||||
|
||||
## Why is it fast?
|
||||
|
||||
It uses linear arrays for all data. [Packages](https://github.com/oven-sh/bun/blob/be03fc273a487ac402f19ad897778d74b6d72963/src/install/install.zig#L1825) are referenced by an auto-incrementing integer ID or a hash of the package name. Strings longer than 8 characters are de-duplicated. Prior to saving on disk, the lockfile is garbage-collected & made deterministic by walking the package tree and cloning the packages in dependency order.
|
||||
|
||||
## Cache
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user