mirror of
https://github.com/oven-sh/bun
synced 2026-02-19 15:21:54 +00:00
Compare commits
235 Commits
bun-v0.5.9
...
jarred/exp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
406ffb9e19 | ||
|
|
96e113f41c | ||
|
|
bc0c0f7d20 | ||
|
|
98583972df | ||
|
|
994c715700 | ||
|
|
e3a0c4e06d | ||
|
|
bc43d33be9 | ||
|
|
73d499ed22 | ||
|
|
912ae8d2b5 | ||
|
|
26d81fc5ba | ||
|
|
396416a91f | ||
|
|
4515a6373e | ||
|
|
c383638ddd | ||
|
|
af02b75f79 | ||
|
|
a06e90eec3 | ||
|
|
35d470d98a | ||
|
|
05abe8eabe | ||
|
|
48671b77be | ||
|
|
b7c13f2ccc | ||
|
|
64b9967fe6 | ||
|
|
ef894c57cf | ||
|
|
5734889cc7 | ||
|
|
59daabb6e7 | ||
|
|
36df170348 | ||
|
|
6cf4cabab1 | ||
|
|
1483d73c3a | ||
|
|
52c50e3737 | ||
|
|
3ee22065f0 | ||
|
|
0060e49923 | ||
|
|
87921520e4 | ||
|
|
73467a5736 | ||
|
|
5a8a418ef4 | ||
|
|
df59fe2843 | ||
|
|
990f53f986 | ||
|
|
9383333799 | ||
|
|
4558ea712a | ||
|
|
f1c1f556a3 | ||
|
|
6142f6eb61 | ||
|
|
316a75005b | ||
|
|
5b76ee769e | ||
|
|
3a203abc10 | ||
|
|
75e3546f3a | ||
|
|
6c6118e210 | ||
|
|
55c05c0a1f | ||
|
|
7d7748f69f | ||
|
|
8ba13f273c | ||
|
|
68ab71eb13 | ||
|
|
ab447e4ff7 | ||
|
|
149f097ffd | ||
|
|
3e374c0ee4 | ||
|
|
f42663ce9a | ||
|
|
c48f7e2663 | ||
|
|
0846a4fa80 | ||
|
|
2256d43a32 | ||
|
|
947634c9ed | ||
|
|
126885e1fe | ||
|
|
5353d41014 | ||
|
|
460563ee89 | ||
|
|
3c4f0920b9 | ||
|
|
6e16bb67eb | ||
|
|
e9e7645048 | ||
|
|
f2112fc0de | ||
|
|
923ac39c0b | ||
|
|
98209b8e10 | ||
|
|
4b24bb464c | ||
|
|
7d6b5f5358 | ||
|
|
9423693a6e | ||
|
|
8b9462fde5 | ||
|
|
caa90ba98e | ||
|
|
55d50565a5 | ||
|
|
dc55e11714 | ||
|
|
613bb4822e | ||
|
|
a4d0a1961a | ||
|
|
143ccdbeb6 | ||
|
|
b98f90fc6e | ||
|
|
281b810664 | ||
|
|
ffdac249ae | ||
|
|
541d16f8be | ||
|
|
b609f9be28 | ||
|
|
b473a0022d | ||
|
|
94cd68d7a6 | ||
|
|
6d5378566a | ||
|
|
c33df9e99f | ||
|
|
4dc0364201 | ||
|
|
aa4d47fe2d | ||
|
|
3a68ca775f | ||
|
|
d78ecc76c8 | ||
|
|
9e7bfdec8c | ||
|
|
f0dd5b8a43 | ||
|
|
ea47ed0ee5 | ||
|
|
36f9fd607a | ||
|
|
96a2ed1040 | ||
|
|
76deb51c29 | ||
|
|
5712fbd5b9 | ||
|
|
b5b4356d52 | ||
|
|
d1de291b2a | ||
|
|
af96e8fcdd | ||
|
|
9e1745ee1f | ||
|
|
05cb5bb659 | ||
|
|
dec5b07782 | ||
|
|
b758779c49 | ||
|
|
3a63fe457d | ||
|
|
a17624942e | ||
|
|
1ce60275d0 | ||
|
|
93a43c8fc1 | ||
|
|
bffe5e820b | ||
|
|
983d9428a6 | ||
|
|
fc539c278e | ||
|
|
d19005aa76 | ||
|
|
d2c64300f6 | ||
|
|
4cb739a8c5 | ||
|
|
01a03bcce4 | ||
|
|
6b758c809f | ||
|
|
746940d21e | ||
|
|
07b4b4ced0 | ||
|
|
e624dd6d4d | ||
|
|
ed2f24e409 | ||
|
|
c650b0b848 | ||
|
|
0514f59288 | ||
|
|
5a8cfd8390 | ||
|
|
a2d5e7c570 | ||
|
|
af0a4c5638 | ||
|
|
eec1a07907 | ||
|
|
30b0d006fe | ||
|
|
413ce0c7a5 | ||
|
|
c916a55ead | ||
|
|
31319c0177 | ||
|
|
255a805e00 | ||
|
|
eff48cd95c | ||
|
|
338565eea4 | ||
|
|
264f3b91b6 | ||
|
|
06dab241ef | ||
|
|
29cacb7da7 | ||
|
|
e05cc8db90 | ||
|
|
09357f55f9 | ||
|
|
33049fa6fd | ||
|
|
be5d21a4f1 | ||
|
|
2dc3f4e030 | ||
|
|
1a7c3cdf3b | ||
|
|
f1f7369897 | ||
|
|
4b3c483cd4 | ||
|
|
df88b998d6 | ||
|
|
b687c3ab88 | ||
|
|
d4436f278c | ||
|
|
530f5ef82c | ||
|
|
9e5efe61a3 | ||
|
|
82b2c5221b | ||
|
|
e977bfb5a7 | ||
|
|
81e11ae586 | ||
|
|
0d248568f6 | ||
|
|
96d522a7db | ||
|
|
b4989a316b | ||
|
|
8b897e1a6b | ||
|
|
730074b75d | ||
|
|
f6a4516d66 | ||
|
|
6c69c2b364 | ||
|
|
ba057e50c3 | ||
|
|
1e6dcef0c5 | ||
|
|
889462a891 | ||
|
|
3a2fd65f20 | ||
|
|
267a38f6fc | ||
|
|
011e157cac | ||
|
|
0cc56e8efc | ||
|
|
54ef58db48 | ||
|
|
476ab24081 | ||
|
|
8a2545a172 | ||
|
|
e9016415bc | ||
|
|
242aa0be12 | ||
|
|
041231d7ca | ||
|
|
bee743fd61 | ||
|
|
d7a8037899 | ||
|
|
d226a054ae | ||
|
|
aeb3bb949b | ||
|
|
db15a23a63 | ||
|
|
1cc4eb0e3f | ||
|
|
a03ee18262 | ||
|
|
108c54134c | ||
|
|
73216b10ce | ||
|
|
ff5c522712 | ||
|
|
14f87156a2 | ||
|
|
d8d4abb58e | ||
|
|
4b9b648f8a | ||
|
|
519f9aac80 | ||
|
|
a744f5369d | ||
|
|
14c6023e15 | ||
|
|
f91dc8c0d3 | ||
|
|
f4ab79d6bb | ||
|
|
373248ce9c | ||
|
|
5c37d0f2a5 | ||
|
|
7bd6a1f86d | ||
|
|
1e717dd941 | ||
|
|
e9d6a4042f | ||
|
|
c97cb4ec1e | ||
|
|
21acc50d88 | ||
|
|
b34f0da499 | ||
|
|
eb18101d84 | ||
|
|
2117723642 | ||
|
|
461ae27d31 | ||
|
|
ba7a8a9cb5 | ||
|
|
c764543af5 | ||
|
|
60fc80d4c4 | ||
|
|
6362414d65 | ||
|
|
c0c5f07218 | ||
|
|
0a91dd9f71 | ||
|
|
bed56ab406 | ||
|
|
4978a6b74d | ||
|
|
35b279a4bb | ||
|
|
c8e09f563f | ||
|
|
6baedd27bc | ||
|
|
5465a3980a | ||
|
|
b6bd7e24d7 | ||
|
|
e4e81bc49e | ||
|
|
b8aca35b76 | ||
|
|
68670eeb7b | ||
|
|
2b170c9d13 | ||
|
|
1d138057cb | ||
|
|
f788519263 | ||
|
|
8a73c2a453 | ||
|
|
21978dabe5 | ||
|
|
aa4c4a9b22 | ||
|
|
569d4940bb | ||
|
|
4af78c7d5a | ||
|
|
cfb1c661d5 | ||
|
|
864302a634 | ||
|
|
b50f3d3f6f | ||
|
|
65d646bc68 | ||
|
|
d8c467be42 | ||
|
|
fd680d6c1d | ||
|
|
f7d0eee0ac | ||
|
|
ac092a1e04 | ||
|
|
fd5bb6b201 | ||
|
|
d8360ab3cf | ||
|
|
a369fc8c89 | ||
|
|
54d6f95f43 | ||
|
|
76adc5be8a |
@@ -1,28 +0,0 @@
|
||||
# Bun's Dev Container
|
||||
|
||||
To get started, login to GitHub and clone bun's GitHub repo into `/build/bun`
|
||||
|
||||
# First time setup
|
||||
|
||||
```bash
|
||||
gh auth login # if it fails to open a browser, use Personal Access Token instead
|
||||
gh repo clone oven-sh/bun . -- --depth=1 --progress -j8
|
||||
```
|
||||
|
||||
# Compile bun dependencies (zig is already compiled)
|
||||
|
||||
```bash
|
||||
make devcontainer
|
||||
```
|
||||
|
||||
# Build bun for development
|
||||
|
||||
```bash
|
||||
make dev
|
||||
```
|
||||
|
||||
# Run bun
|
||||
|
||||
```bash
|
||||
bun-debug help
|
||||
```
|
||||
@@ -1,70 +0,0 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.209.6/containers/docker-existing-dockerfile
|
||||
{
|
||||
"name": "bun (Ubuntu)",
|
||||
|
||||
// Sets the run context to one level up instead of the .devcontainer folder.
|
||||
"context": "..",
|
||||
"hostRequirements": { "memory": "16gb" },
|
||||
|
||||
// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
|
||||
"dockerFile": "../Dockerfile.devcontainer",
|
||||
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {
|
||||
"terminal.integrated.shell.linux": "/bin/zsh",
|
||||
"zigLanguageClient.path": "/home/ubuntu/zls/zig-out/bin/zls",
|
||||
"zig.zigPath": "/build/zig/zig",
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"AugusteRame.zls-vscode",
|
||||
"ms-vscode.cpptools",
|
||||
"/home/ubuntu/vscode-zig.vsix",
|
||||
"vadimcn.vscode-lldb",
|
||||
"esbenp.prettier-vscode",
|
||||
"xaver.clang-format"
|
||||
],
|
||||
"postCreateCommand": "cd /build/bun; bash /build/getting-started.sh; cat /build/README.md",
|
||||
|
||||
"build": {
|
||||
"target": "bun.devcontainer",
|
||||
"cacheFrom": ["ghcr.io/oven-sh/bun.devcontainer:latest"],
|
||||
"args": {
|
||||
"BUILDARCH": "${localEnv:DOCKER_BUILDARCH:amd64}",
|
||||
"--platform": "linux/${localEnv:DOCKER_BUILDARCH:amd64}",
|
||||
"--tag": "ghcr.io/oven-sh/bun.devcontainer:latest"
|
||||
}
|
||||
},
|
||||
"runArgs": [
|
||||
"--ulimit",
|
||||
"memlock=-1:-1",
|
||||
"--ulimit",
|
||||
"nofile=65536:65536",
|
||||
"--cap-add=SYS_PTRACE",
|
||||
"--security-opt",
|
||||
"seccomp=unconfined"
|
||||
],
|
||||
"workspaceMount": "source=bun,target=/build/bun,type=volume",
|
||||
"workspaceFolder": "/build/bun",
|
||||
"mounts": [
|
||||
"source=bun-install,target=/home/ubuntu/.bun,type=volume",
|
||||
"source=bun-config,target=/home/ubuntu/.config,type=volume"
|
||||
],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [3000, 8081, 8080]
|
||||
|
||||
// Uncomment the next line to run commands after the container is created - for example installing curl.
|
||||
// "postCreateCommand": "apt-get update && apt-get install -y curl",
|
||||
|
||||
// Uncomment when using a ptrace-based debugger like C++, Go, and Rust
|
||||
|
||||
// Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker.
|
||||
// "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ],
|
||||
|
||||
// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
|
||||
// "remoteUser": "vscode"
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
# /etc/security/limits.conf
|
||||
#
|
||||
#Each line describes a limit for a user in the form:
|
||||
#
|
||||
#<domain> <type> <item> <value>
|
||||
#
|
||||
#Where:
|
||||
#<domain> can be:
|
||||
# - a user name
|
||||
# - a group name, with @group syntax
|
||||
# - the wildcard *, for default entry
|
||||
# - the wildcard %, can be also used with %group syntax,
|
||||
# for maxlogin limit
|
||||
# - NOTE: group and wildcard limits are not applied to root.
|
||||
# To apply a limit to the root user, <domain> must be
|
||||
# the literal username root.
|
||||
#
|
||||
#<type> can have the two values:
|
||||
# - "soft" for enforcing the soft limits
|
||||
# - "hard" for enforcing hard limits
|
||||
#
|
||||
#<item> can be one of the following:
|
||||
# - core - limits the core file size (KB)
|
||||
# - data - max data size (KB)
|
||||
# - fsize - maximum filesize (KB)
|
||||
# - memlock - max locked-in-memory address space (KB)
|
||||
# - nofile - max number of open file descriptors
|
||||
# - rss - max resident set size (KB)
|
||||
# - stack - max stack size (KB)
|
||||
# - cpu - max CPU time (MIN)
|
||||
# - nproc - max number of processes
|
||||
# - as - address space limit (KB)
|
||||
# - maxlogins - max number of logins for this user
|
||||
# - maxsyslogins - max number of logins on the system
|
||||
# - priority - the priority to run user process with
|
||||
# - locks - max number of file locks the user can hold
|
||||
# - sigpending - max number of pending signals
|
||||
# - msgqueue - max memory used by POSIX message queues (bytes)
|
||||
# - nice - max nice priority allowed to raise to values: [-20, 19]
|
||||
# - rtprio - max realtime priority
|
||||
# - chroot - change root to directory (Debian-specific)
|
||||
#
|
||||
#<domain> <type> <item> <value>
|
||||
#
|
||||
|
||||
* soft memlock 33554432
|
||||
* hard memlock 33554432
|
||||
* soft nofile 33554432
|
||||
* hard nofile 33554432
|
||||
|
||||
#* soft core 0
|
||||
#root hard core 100000
|
||||
#* hard rss 10000
|
||||
#@student hard nproc 20
|
||||
#@faculty soft nproc 20
|
||||
#@faculty hard nproc 50
|
||||
#ftp hard nproc 0
|
||||
#ftp - chroot /ftp
|
||||
#@student - maxlogins 4
|
||||
|
||||
# End of file
|
||||
@@ -1,454 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#-------------------------------------------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
|
||||
#-------------------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/common.md
|
||||
# Maintainer: The VS Code and Codespaces Teams
|
||||
#
|
||||
# Syntax: ./common-debian.sh [install zsh flag] [username] [user UID] [user GID] [upgrade packages flag] [install Oh My Zsh! flag] [Add non-free packages]
|
||||
|
||||
set -e
|
||||
|
||||
INSTALL_ZSH=${1:-"true"}
|
||||
USERNAME=${2:-"automatic"}
|
||||
USER_UID=${3:-"automatic"}
|
||||
USER_GID=${4:-"automatic"}
|
||||
UPGRADE_PACKAGES=${5:-"true"}
|
||||
INSTALL_OH_MYS=${6:-"true"}
|
||||
ADD_NON_FREE_PACKAGES=${7:-"false"}
|
||||
SCRIPT_DIR="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)"
|
||||
MARKER_FILE="/usr/local/etc/vscode-dev-containers/common"
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure that login shells get the correct path if the user updated the PATH using ENV.
|
||||
rm -f /etc/profile.d/00-restore-env.sh
|
||||
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
|
||||
chmod +x /etc/profile.d/00-restore-env.sh
|
||||
|
||||
# If in automatic mode, determine if a user already exists, if not use vscode
|
||||
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
|
||||
USERNAME=""
|
||||
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
|
||||
for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
|
||||
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
|
||||
USERNAME=${CURRENT_USER}
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "${USERNAME}" = "" ]; then
|
||||
USERNAME=vscode
|
||||
fi
|
||||
elif [ "${USERNAME}" = "none" ]; then
|
||||
USERNAME=root
|
||||
USER_UID=0
|
||||
USER_GID=0
|
||||
fi
|
||||
|
||||
# Load markers to see which steps have already run
|
||||
if [ -f "${MARKER_FILE}" ]; then
|
||||
echo "Marker file found:"
|
||||
cat "${MARKER_FILE}"
|
||||
source "${MARKER_FILE}"
|
||||
fi
|
||||
|
||||
# Ensure apt is in non-interactive to avoid prompts
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Function to call apt-get if needed
|
||||
apt_get_update_if_needed()
|
||||
{
|
||||
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
|
||||
echo "Running apt-get update..."
|
||||
apt-get update
|
||||
else
|
||||
echo "Skipping apt-get update."
|
||||
fi
|
||||
}
|
||||
|
||||
# Run install apt-utils to avoid debconf warning then verify presence of other common developer tools and dependencies
|
||||
if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
|
||||
|
||||
package_list="apt-utils \
|
||||
openssh-client \
|
||||
gnupg2 \
|
||||
dirmngr \
|
||||
iproute2 \
|
||||
procps \
|
||||
lsof \
|
||||
htop \
|
||||
net-tools \
|
||||
psmisc \
|
||||
curl \
|
||||
wget \
|
||||
rsync \
|
||||
ca-certificates \
|
||||
unzip \
|
||||
zip \
|
||||
nano \
|
||||
vim-tiny \
|
||||
less \
|
||||
jq \
|
||||
lsb-release \
|
||||
apt-transport-https \
|
||||
dialog \
|
||||
libc6 \
|
||||
libgcc1 \
|
||||
libkrb5-3 \
|
||||
libgssapi-krb5-2 \
|
||||
libicu[0-9][0-9] \
|
||||
liblttng-ust[0-9] \
|
||||
libstdc++6 \
|
||||
zlib1g \
|
||||
locales \
|
||||
sudo \
|
||||
ncdu \
|
||||
man-db \
|
||||
strace \
|
||||
manpages \
|
||||
manpages-dev \
|
||||
init-system-helpers"
|
||||
|
||||
# Needed for adding manpages-posix and manpages-posix-dev which are non-free packages in Debian
|
||||
if [ "${ADD_NON_FREE_PACKAGES}" = "true" ]; then
|
||||
# Bring in variables from /etc/os-release like VERSION_CODENAME
|
||||
. /etc/os-release
|
||||
sed -i -E "s/deb http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME} main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME} main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i -E "s/deb-src http:\/\/(deb|httredir)\.debian\.org\/debian ${VERSION_CODENAME} main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME} main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i -E "s/deb http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME}-updates main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME}-updates main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i -E "s/deb-src http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME}-updates main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME}-updates main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i "s/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i "s/deb-src http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i "s/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i "s/deb-src http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list
|
||||
# Handle bullseye location for security https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.en.html
|
||||
sed -i "s/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main contrib non-free/" /etc/apt/sources.list
|
||||
sed -i "s/deb-src http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main contrib non-free/" /etc/apt/sources.list
|
||||
echo "Running apt-get update..."
|
||||
apt-get update
|
||||
package_list="${package_list} manpages-posix manpages-posix-dev"
|
||||
else
|
||||
apt_get_update_if_needed
|
||||
fi
|
||||
|
||||
# Install libssl1.1 if available
|
||||
if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then
|
||||
package_list="${package_list} libssl1.1"
|
||||
fi
|
||||
|
||||
# Install appropriate version of libssl1.0.x if available
|
||||
libssl_package=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '')
|
||||
if [ "$(echo "$LIlibssl_packageBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then
|
||||
if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then
|
||||
# Debian 9
|
||||
package_list="${package_list} libssl1.0.2"
|
||||
elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then
|
||||
# Ubuntu 18.04, 16.04, earlier
|
||||
package_list="${package_list} libssl1.0.0"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Packages to verify are installed: ${package_list}"
|
||||
apt-get -y install --no-install-recommends ${package_list} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 )
|
||||
|
||||
# Install git if not already installed (may be more recent than distro version)
|
||||
if ! type git > /dev/null 2>&1; then
|
||||
apt-get -y install --no-install-recommends git
|
||||
fi
|
||||
|
||||
PACKAGES_ALREADY_INSTALLED="true"
|
||||
fi
|
||||
|
||||
# Get to latest versions of all packages
|
||||
if [ "${UPGRADE_PACKAGES}" = "true" ]; then
|
||||
apt_get_update_if_needed
|
||||
apt-get -y upgrade --no-install-recommends
|
||||
apt-get autoremove -y
|
||||
fi
|
||||
|
||||
# Ensure at least the en_US.UTF-8 UTF-8 locale is available.
|
||||
# Common need for both applications and things like the agnoster ZSH theme.
|
||||
if [ "${LOCALE_ALREADY_SET}" != "true" ] && ! grep -o -E '^\s*en_US.UTF-8\s+UTF-8' /etc/locale.gen > /dev/null; then
|
||||
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
|
||||
locale-gen
|
||||
LOCALE_ALREADY_SET="true"
|
||||
fi
|
||||
|
||||
# Create or update a non-root user to match UID/GID.
|
||||
group_name="${USERNAME}"
|
||||
if id -u ${USERNAME} > /dev/null 2>&1; then
|
||||
# User exists, update if needed
|
||||
if [ "${USER_GID}" != "automatic" ] && [ "$USER_GID" != "$(id -g $USERNAME)" ]; then
|
||||
group_name="$(id -gn $USERNAME)"
|
||||
groupmod --gid $USER_GID ${group_name}
|
||||
usermod --gid $USER_GID $USERNAME
|
||||
fi
|
||||
if [ "${USER_UID}" != "automatic" ] && [ "$USER_UID" != "$(id -u $USERNAME)" ]; then
|
||||
usermod --uid $USER_UID $USERNAME
|
||||
fi
|
||||
else
|
||||
# Create user
|
||||
if [ "${USER_GID}" = "automatic" ]; then
|
||||
groupadd $USERNAME
|
||||
else
|
||||
groupadd --gid $USER_GID $USERNAME
|
||||
fi
|
||||
if [ "${USER_UID}" = "automatic" ]; then
|
||||
useradd -s /bin/bash --gid $USERNAME -m $USERNAME
|
||||
else
|
||||
useradd -s /bin/bash --uid $USER_UID --gid $USERNAME -m $USERNAME
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add sudo support for non-root user
|
||||
if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then
|
||||
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
|
||||
chmod 0440 /etc/sudoers.d/$USERNAME
|
||||
EXISTING_NON_ROOT_USER="${USERNAME}"
|
||||
fi
|
||||
|
||||
# ** Shell customization section **
|
||||
if [ "${USERNAME}" = "root" ]; then
|
||||
user_rc_path="/root"
|
||||
else
|
||||
user_rc_path="/home/${USERNAME}"
|
||||
fi
|
||||
|
||||
# Restore user .bashrc defaults from skeleton file if it doesn't exist or is empty
|
||||
if [ ! -f "${user_rc_path}/.bashrc" ] || [ ! -s "${user_rc_path}/.bashrc" ] ; then
|
||||
cp /etc/skel/.bashrc "${user_rc_path}/.bashrc"
|
||||
fi
|
||||
|
||||
# Restore user .profile defaults from skeleton file if it doesn't exist or is empty
|
||||
if [ ! -f "${user_rc_path}/.profile" ] || [ ! -s "${user_rc_path}/.profile" ] ; then
|
||||
cp /etc/skel/.profile "${user_rc_path}/.profile"
|
||||
fi
|
||||
|
||||
# .bashrc/.zshrc snippet
|
||||
rc_snippet="$(cat << 'EOF'
|
||||
|
||||
if [ -z "${USER}" ]; then export USER=$(whoami); fi
|
||||
if [[ "${PATH}" != *"$HOME/.local/bin"* ]]; then export PATH="${PATH}:$HOME/.local/bin"; fi
|
||||
|
||||
# Display optional first run image specific notice if configured and terminal is interactive
|
||||
if [ -t 1 ] && [[ "${TERM_PROGRAM}" = "vscode" || "${TERM_PROGRAM}" = "codespaces" ]] && [ ! -f "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed" ]; then
|
||||
if [ -f "/usr/local/etc/vscode-dev-containers/first-run-notice.txt" ]; then
|
||||
cat "/usr/local/etc/vscode-dev-containers/first-run-notice.txt"
|
||||
elif [ -f "/workspaces/.codespaces/shared/first-run-notice.txt" ]; then
|
||||
cat "/workspaces/.codespaces/shared/first-run-notice.txt"
|
||||
fi
|
||||
mkdir -p "$HOME/.config/vscode-dev-containers"
|
||||
# Mark first run notice as displayed after 10s to avoid problems with fast terminal refreshes hiding it
|
||||
((sleep 10s; touch "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed") &)
|
||||
fi
|
||||
|
||||
# Set the default git editor if not already set
|
||||
if [ -z "$(git config --get core.editor)" ] && [ -z "${GIT_EDITOR}" ]; then
|
||||
if [ "${TERM_PROGRAM}" = "vscode" ]; then
|
||||
if [[ -n $(command -v code-insiders) && -z $(command -v code) ]]; then
|
||||
export GIT_EDITOR="code-insiders --wait"
|
||||
else
|
||||
export GIT_EDITOR="code --wait"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
EOF
|
||||
)"
|
||||
|
||||
# code shim, it fallbacks to code-insiders if code is not available
|
||||
cat << 'EOF' > /usr/local/bin/code
|
||||
#!/bin/sh
|
||||
|
||||
get_in_path_except_current() {
|
||||
which -a "$1" | grep -A1 "$0" | grep -v "$0"
|
||||
}
|
||||
|
||||
code="$(get_in_path_except_current code)"
|
||||
|
||||
if [ -n "$code" ]; then
|
||||
exec "$code" "$@"
|
||||
elif [ "$(command -v code-insiders)" ]; then
|
||||
exec code-insiders "$@"
|
||||
else
|
||||
echo "code or code-insiders is not installed" >&2
|
||||
exit 127
|
||||
fi
|
||||
EOF
|
||||
chmod +x /usr/local/bin/code
|
||||
|
||||
# systemctl shim - tells people to use 'service' if systemd is not running
|
||||
cat << 'EOF' > /usr/local/bin/systemctl
|
||||
#!/bin/sh
|
||||
set -e
|
||||
if [ -d "/run/systemd/system" ]; then
|
||||
exec /bin/systemctl "$@"
|
||||
else
|
||||
echo '\n"systemd" is not running in this container due to its overhead.\nUse the "service" command to start services instead. e.g.: \n\nservice --status-all'
|
||||
fi
|
||||
EOF
|
||||
chmod +x /usr/local/bin/systemctl
|
||||
|
||||
# Codespaces bash and OMZ themes - partly inspired by https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/robbyrussell.zsh-theme
|
||||
codespaces_bash="$(cat \
|
||||
<<'EOF'
|
||||
|
||||
# Codespaces bash prompt theme
|
||||
__bash_prompt() {
|
||||
local userpart='`export XIT=$? \
|
||||
&& [ ! -z "${GITHUB_USER}" ] && echo -n "\[\033[0;32m\]@${GITHUB_USER} " || echo -n "\[\033[0;32m\]\u " \
|
||||
&& [ "$XIT" -ne "0" ] && echo -n "\[\033[1;31m\]➜" || echo -n "\[\033[0m\]➜"`'
|
||||
local gitbranch='`\
|
||||
if [ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ]; then \
|
||||
export BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null); \
|
||||
if [ "${BRANCH}" != "" ]; then \
|
||||
echo -n "\[\033[0;36m\](\[\033[1;31m\]${BRANCH}" \
|
||||
&& if git ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \
|
||||
echo -n " \[\033[1;33m\]✗"; \
|
||||
fi \
|
||||
&& echo -n "\[\033[0;36m\]) "; \
|
||||
fi; \
|
||||
fi`'
|
||||
local lightblue='\[\033[1;34m\]'
|
||||
local removecolor='\[\033[0m\]'
|
||||
PS1="${userpart} ${lightblue}\w ${gitbranch}${removecolor}\$ "
|
||||
unset -f __bash_prompt
|
||||
}
|
||||
__bash_prompt
|
||||
|
||||
EOF
|
||||
)"
|
||||
|
||||
codespaces_zsh="$(cat \
|
||||
<<'EOF'
|
||||
# Codespaces zsh prompt theme
|
||||
__zsh_prompt() {
|
||||
local prompt_username
|
||||
if [ ! -z "${GITHUB_USER}" ]; then
|
||||
prompt_username="@${GITHUB_USER}"
|
||||
else
|
||||
prompt_username="%n"
|
||||
fi
|
||||
PROMPT="%{$fg[green]%}${prompt_username} %(?:%{$reset_color%}➜ :%{$fg_bold[red]%}➜ )" # User/exit code arrow
|
||||
PROMPT+='%{$fg_bold[blue]%}%(5~|%-1~/…/%3~|%4~)%{$reset_color%} ' # cwd
|
||||
PROMPT+='$([ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ] && git_prompt_info)' # Git status
|
||||
PROMPT+='%{$fg[white]%}$ %{$reset_color%}'
|
||||
unset -f __zsh_prompt
|
||||
}
|
||||
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[cyan]%}(%{$fg_bold[red]%}"
|
||||
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} "
|
||||
ZSH_THEME_GIT_PROMPT_DIRTY=" %{$fg_bold[yellow]%}✗%{$fg_bold[cyan]%})"
|
||||
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[cyan]%})"
|
||||
__zsh_prompt
|
||||
|
||||
EOF
|
||||
)"
|
||||
|
||||
# Add RC snippet and custom bash prompt
|
||||
if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then
|
||||
echo "${rc_snippet}" >> /etc/bash.bashrc
|
||||
echo "${codespaces_bash}" >> "${user_rc_path}/.bashrc"
|
||||
echo 'export PROMPT_DIRTRIM=4' >> "${user_rc_path}/.bashrc"
|
||||
if [ "${USERNAME}" != "root" ]; then
|
||||
echo "${codespaces_bash}" >> "/root/.bashrc"
|
||||
echo 'export PROMPT_DIRTRIM=4' >> "/root/.bashrc"
|
||||
fi
|
||||
chown ${USERNAME}:${group_name} "${user_rc_path}/.bashrc"
|
||||
RC_SNIPPET_ALREADY_ADDED="true"
|
||||
fi
|
||||
|
||||
# Optionally install and configure zsh and Oh My Zsh!
|
||||
if [ "${INSTALL_ZSH}" = "true" ]; then
|
||||
if ! type zsh > /dev/null 2>&1; then
|
||||
apt_get_update_if_needed
|
||||
apt-get install -y zsh
|
||||
fi
|
||||
if [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then
|
||||
echo "${rc_snippet}" >> /etc/zsh/zshrc
|
||||
ZSH_ALREADY_INSTALLED="true"
|
||||
fi
|
||||
|
||||
# Adapted, simplified inline Oh My Zsh! install steps that adds, defaults to a codespaces theme.
|
||||
# See https://github.com/ohmyzsh/ohmyzsh/blob/master/tools/install.sh for official script.
|
||||
oh_my_install_dir="${user_rc_path}/.oh-my-zsh"
|
||||
if [ ! -d "${oh_my_install_dir}" ] && [ "${INSTALL_OH_MYS}" = "true" ]; then
|
||||
template_path="${oh_my_install_dir}/templates/zshrc.zsh-template"
|
||||
user_rc_file="${user_rc_path}/.zshrc"
|
||||
umask g-w,o-w
|
||||
mkdir -p ${oh_my_install_dir}
|
||||
git clone --depth=1 \
|
||||
-c core.eol=lf \
|
||||
-c core.autocrlf=false \
|
||||
-c fsck.zeroPaddedFilemode=ignore \
|
||||
-c fetch.fsck.zeroPaddedFilemode=ignore \
|
||||
-c receive.fsck.zeroPaddedFilemode=ignore \
|
||||
"https://github.com/ohmyzsh/ohmyzsh" "${oh_my_install_dir}" 2>&1
|
||||
echo -e "$(cat "${template_path}")\nDISABLE_AUTO_UPDATE=true\nDISABLE_UPDATE_PROMPT=true" > ${user_rc_file}
|
||||
sed -i -e 's/ZSH_THEME=.*/ZSH_THEME="codespaces"/g' ${user_rc_file}
|
||||
|
||||
mkdir -p ${oh_my_install_dir}/custom/themes
|
||||
echo "${codespaces_zsh}" > "${oh_my_install_dir}/custom/themes/codespaces.zsh-theme"
|
||||
# Shrink git while still enabling updates
|
||||
cd "${oh_my_install_dir}"
|
||||
git repack -a -d -f --depth=1 --window=1
|
||||
# Copy to non-root user if one is specified
|
||||
if [ "${USERNAME}" != "root" ]; then
|
||||
cp -rf "${user_rc_file}" "${oh_my_install_dir}" /root
|
||||
chown -R ${USERNAME}:${group_name} "${user_rc_path}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Persist image metadata info, script if meta.env found in same directory
|
||||
meta_info_script="$(cat << 'EOF'
|
||||
#!/bin/sh
|
||||
. /usr/local/etc/vscode-dev-containers/meta.env
|
||||
|
||||
# Minimal output
|
||||
if [ "$1" = "version" ] || [ "$1" = "image-version" ]; then
|
||||
echo "${VERSION}"
|
||||
exit 0
|
||||
elif [ "$1" = "release" ]; then
|
||||
echo "${GIT_REPOSITORY_RELEASE}"
|
||||
exit 0
|
||||
elif [ "$1" = "content" ] || [ "$1" = "content-url" ] || [ "$1" = "contents" ] || [ "$1" = "contents-url" ]; then
|
||||
echo "${CONTENTS_URL}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#Full output
|
||||
echo
|
||||
echo "Development container image information"
|
||||
echo
|
||||
if [ ! -z "${VERSION}" ]; then echo "- Image version: ${VERSION}"; fi
|
||||
if [ ! -z "${DEFINITION_ID}" ]; then echo "- Definition ID: ${DEFINITION_ID}"; fi
|
||||
if [ ! -z "${VARIANT}" ]; then echo "- Variant: ${VARIANT}"; fi
|
||||
if [ ! -z "${GIT_REPOSITORY}" ]; then echo "- Source code repository: ${GIT_REPOSITORY}"; fi
|
||||
if [ ! -z "${GIT_REPOSITORY_RELEASE}" ]; then echo "- Source code release/branch: ${GIT_REPOSITORY_RELEASE}"; fi
|
||||
if [ ! -z "${BUILD_TIMESTAMP}" ]; then echo "- Timestamp: ${BUILD_TIMESTAMP}"; fi
|
||||
if [ ! -z "${CONTENTS_URL}" ]; then echo && echo "More info: ${CONTENTS_URL}"; fi
|
||||
echo
|
||||
EOF
|
||||
)"
|
||||
if [ -f "${SCRIPT_DIR}/meta.env" ]; then
|
||||
mkdir -p /usr/local/etc/vscode-dev-containers/
|
||||
cp -f "${SCRIPT_DIR}/meta.env" /usr/local/etc/vscode-dev-containers/meta.env
|
||||
echo "${meta_info_script}" > /usr/local/bin/devcontainer-info
|
||||
chmod +x /usr/local/bin/devcontainer-info
|
||||
fi
|
||||
|
||||
# Write marker file
|
||||
mkdir -p "$(dirname "${MARKER_FILE}")"
|
||||
echo -e "\
|
||||
PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\
|
||||
LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\
|
||||
EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\
|
||||
RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED}\n\
|
||||
ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}"
|
||||
|
||||
echo "Done!"
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "To get started, login to GitHub and clone bun's GitHub repo into /build/bun"
|
||||
echo "If it fails to open a browser, login with a Personal Access Token instead"
|
||||
echo "# First time setup"
|
||||
echo "gh auth login"
|
||||
echo "gh repo clone oven-sh/bun . -- --depth=1 --progress -j8"
|
||||
echo ""
|
||||
echo "# Compile bun dependencies (zig is already compiled)"
|
||||
echo "make devcontainer"
|
||||
echo ""
|
||||
echo "# Build bun for development"
|
||||
echo "make dev"
|
||||
echo ""
|
||||
echo "# Run bun"
|
||||
echo "bun-debug"
|
||||
@@ -1,207 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#-------------------------------------------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
|
||||
#-------------------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/github.md
|
||||
# Maintainer: The VS Code and Codespaces Teams
|
||||
#
|
||||
# Syntax: ./github-debian.sh [version]
|
||||
|
||||
CLI_VERSION=${1:-"latest"}
|
||||
|
||||
GITHUB_CLI_ARCHIVE_GPG_KEY=C99B11DEB97541F0
|
||||
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80
|
||||
keyserver hkps://keys.openpgp.org
|
||||
keyserver hkp://keyserver.pgp.com"
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get central common setting
|
||||
get_common_setting() {
|
||||
if [ "${common_settings_file_loaded}" != "true" ]; then
|
||||
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" -o /tmp/vsdc-settings.env 2>/dev/null || echo "Could not download settings file. Skipping."
|
||||
common_settings_file_loaded=true
|
||||
fi
|
||||
if [ -f "/tmp/vsdc-settings.env" ]; then
|
||||
local multi_line=""
|
||||
if [ "$2" = "true" ]; then multi_line="-z"; fi
|
||||
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
|
||||
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
|
||||
fi
|
||||
echo "$1=${!1}"
|
||||
}
|
||||
|
||||
# Import the specified key in a variable name passed in as
|
||||
receive_gpg_keys() {
|
||||
get_common_setting $1
|
||||
local keys=${!1}
|
||||
get_common_setting GPG_KEY_SERVERS true
|
||||
|
||||
# Use a temporary locaiton for gpg keys to avoid polluting image
|
||||
export GNUPGHOME="/tmp/tmp-gnupg"
|
||||
mkdir -p ${GNUPGHOME}
|
||||
chmod 700 ${GNUPGHOME}
|
||||
echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" >${GNUPGHOME}/dirmngr.conf
|
||||
# GPG key download sometimes fails for some reason and retrying fixes it.
|
||||
local retry_count=0
|
||||
local gpg_ok="false"
|
||||
set +e
|
||||
until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ]; do
|
||||
echo "(*) Downloading GPG key..."
|
||||
(echo "${keys}" | xargs -n 1 gpg --recv-keys) 2>&1 && gpg_ok="true"
|
||||
if [ "${gpg_ok}" != "true" ]; then
|
||||
echo "(*) Failed getting key, retring in 10s..."
|
||||
((retry_count++))
|
||||
sleep 10s
|
||||
fi
|
||||
done
|
||||
set -e
|
||||
if [ "${gpg_ok}" = "false" ]; then
|
||||
echo "(!) Failed to get gpg key."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Figure out correct version of a three part version number is not passed
|
||||
find_version_from_git_tags() {
|
||||
local variable_name=$1
|
||||
local requested_version=${!variable_name}
|
||||
if [ "${requested_version}" = "none" ]; then return; fi
|
||||
local repository=$2
|
||||
local prefix=${3:-"tags/v"}
|
||||
local separator=${4:-"."}
|
||||
local last_part_optional=${5:-"false"}
|
||||
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
|
||||
local escaped_separator=${separator//./\\.}
|
||||
local last_part
|
||||
if [ "${last_part_optional}" = "true" ]; then
|
||||
last_part="(${escaped_separator}[0-9]+)?"
|
||||
else
|
||||
last_part="${escaped_separator}[0-9]+"
|
||||
fi
|
||||
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
|
||||
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
|
||||
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
|
||||
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
|
||||
else
|
||||
set +e
|
||||
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
|
||||
set -e
|
||||
fi
|
||||
fi
|
||||
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" >/dev/null 2>&1; then
|
||||
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "${variable_name}=${!variable_name}"
|
||||
}
|
||||
|
||||
# Import the specified key in a variable name passed in as
|
||||
receive_gpg_keys() {
|
||||
get_common_setting $1
|
||||
local keys=${!1}
|
||||
get_common_setting GPG_KEY_SERVERS true
|
||||
local keyring_args=""
|
||||
if [ ! -z "$2" ]; then
|
||||
keyring_args="--no-default-keyring --keyring $2"
|
||||
fi
|
||||
|
||||
# Use a temporary locaiton for gpg keys to avoid polluting image
|
||||
export GNUPGHOME="/tmp/tmp-gnupg"
|
||||
mkdir -p ${GNUPGHOME}
|
||||
chmod 700 ${GNUPGHOME}
|
||||
echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" >${GNUPGHOME}/dirmngr.conf
|
||||
# GPG key download sometimes fails for some reason and retrying fixes it.
|
||||
local retry_count=0
|
||||
local gpg_ok="false"
|
||||
set +e
|
||||
until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ]; do
|
||||
echo "(*) Downloading GPG key..."
|
||||
(echo "${keys}" | xargs -n 1 gpg -q ${keyring_args} --recv-keys) 2>&1 && gpg_ok="true"
|
||||
if [ "${gpg_ok}" != "true" ]; then
|
||||
echo "(*) Failed getting key, retring in 10s..."
|
||||
((retry_count++))
|
||||
sleep 10s
|
||||
fi
|
||||
done
|
||||
set -e
|
||||
if [ "${gpg_ok}" = "false" ]; then
|
||||
echo "(!) Failed to get gpg key."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to run apt-get if needed
|
||||
apt_get_update_if_needed() {
|
||||
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
|
||||
echo "Running apt-get update..."
|
||||
apt-get update
|
||||
else
|
||||
echo "Skipping apt-get update."
|
||||
fi
|
||||
}
|
||||
|
||||
# Checks if packages are installed and installs them if not
|
||||
check_packages() {
|
||||
if ! dpkg -s "$@" >/dev/null 2>&1; then
|
||||
apt_get_update_if_needed
|
||||
apt-get -y install --no-install-recommends "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# Fall back on direct download if no apt package exists
|
||||
# Fetches .deb file to be installed with dpkg
|
||||
install_deb_using_github() {
|
||||
check_packages wget
|
||||
arch=$(dpkg --print-architecture)
|
||||
|
||||
find_version_from_git_tags CLI_VERSION https://github.com/cli/cli
|
||||
cli_filename="gh_${CLI_VERSION}_linux_${arch}.deb"
|
||||
|
||||
mkdir -p /tmp/ghcli
|
||||
pushd /tmp/ghcli
|
||||
wget https://github.com/cli/cli/releases/download/v${CLI_VERSION}/${cli_filename}
|
||||
dpkg -i /tmp/ghcli/${cli_filename}
|
||||
popd
|
||||
rm -rf /tmp/ghcli
|
||||
}
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Install curl, apt-transport-https, curl, gpg, or dirmngr, git if missing
|
||||
check_packages curl ca-certificates apt-transport-https dirmngr gnupg2
|
||||
if ! type git >/dev/null 2>&1; then
|
||||
apt_get_update_if_needed
|
||||
apt-get -y install --no-install-recommends git
|
||||
fi
|
||||
|
||||
# Soft version matching
|
||||
if [ "${CLI_VERSION}" != "latest" ] && [ "${CLI_VERSION}" != "lts" ] && [ "${CLI_VERSION}" != "stable" ]; then
|
||||
find_version_from_git_tags CLI_VERSION "https://github.com/cli/cli"
|
||||
version_suffix="=${CLI_VERSION}"
|
||||
else
|
||||
version_suffix=""
|
||||
fi
|
||||
|
||||
# Install the GitHub CLI
|
||||
echo "Downloading github CLI..."
|
||||
|
||||
install_deb_using_github
|
||||
|
||||
# Method below does not work until cli/cli#6175 is fixed
|
||||
# # Import key safely (new method rather than deprecated apt-key approach) and install
|
||||
# . /etc/os-release
|
||||
# receive_gpg_keys GITHUB_CLI_ARCHIVE_GPG_KEY /usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
# echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" >/etc/apt/sources.list.d/github-cli.list
|
||||
# apt-get update
|
||||
# apt-get -y install "gh${version_suffix}"
|
||||
# rm -rf "/tmp/gh/gnupg"
|
||||
|
||||
echo "Done!"
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
chsh -s $(which zsh)
|
||||
sh -c "$(curl -fsSL https://starship.rs/install.sh) -- --platform linux_musl" -- --yes
|
||||
echo "eval \"$(starship init zsh)\"" >>~/.zshrc
|
||||
|
||||
curl https://github.com/Jarred-Sumner/vscode-zig/releases/download/march18/zig-0.2.5.vsix >/home/ubuntu/vscode-zig.vsix
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
git clone https://github.com/zigtools/zls /home/ubuntu/zls
|
||||
cd /home/ubuntu/zls
|
||||
git checkout 30869d7d8741656448e46fbf14f14da9ca7e5a21
|
||||
git submodule update --init --recursive --progress --depth=1
|
||||
zig build -Doptimize=ReleaseFast
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
// Source code
|
||||
"name": "bun",
|
||||
"path": "bun"
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"zig_exe_path": "/build/zig/zig",
|
||||
"enable_snippets": true,
|
||||
"warn_style": false,
|
||||
"enable_semantic_tokens": true,
|
||||
"operator_completions": true,
|
||||
"include_at_in_builtins": false,
|
||||
"max_detail_length": 1048576
|
||||
}
|
||||
1
.github/scripts/get-revision.js
vendored
Normal file
1
.github/scripts/get-revision.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
console.log(Bun.revision);
|
||||
3
.github/scripts/package.json
vendored
Normal file
3
.github/scripts/package.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
684
.github/scripts/test-runner.ts
vendored
Normal file
684
.github/scripts/test-runner.ts
vendored
Normal file
@@ -0,0 +1,684 @@
|
||||
// Dear reader
|
||||
//
|
||||
// The existence of this file is temporary, a hack.
|
||||
import { join, basename } from "node:path";
|
||||
import { readdirSync, writeSync, fsyncSync, appendFileSync } from "node:fs";
|
||||
import { spawn, spawnSync } from "node:child_process";
|
||||
|
||||
export { parseTest, runTest, formatTest };
|
||||
|
||||
export type ParseTestOptions = {
|
||||
cwd?: string;
|
||||
paths?: string[];
|
||||
};
|
||||
|
||||
export type ParseTestResult = {
|
||||
info: TestInfo;
|
||||
files: TestFile[];
|
||||
summary: TestSummary;
|
||||
};
|
||||
|
||||
export type RunTestOptions = ParseTestOptions & {
|
||||
args?: string[];
|
||||
timeout?: number;
|
||||
isolate?: boolean;
|
||||
};
|
||||
|
||||
export type RunTestResult = ParseTestResult & {
|
||||
exitCode: number | null;
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
};
|
||||
|
||||
export type TestInfo = {
|
||||
name: string;
|
||||
version: string;
|
||||
revision: string;
|
||||
os: string;
|
||||
arch: string;
|
||||
};
|
||||
|
||||
export type TestFile = {
|
||||
file: string;
|
||||
status: TestStatus;
|
||||
tests: Test[];
|
||||
summary: TestSummary;
|
||||
errors?: TestError[];
|
||||
};
|
||||
|
||||
export type TestError = {
|
||||
name: string;
|
||||
message: string;
|
||||
stack?: TestErrorStack[];
|
||||
};
|
||||
|
||||
export type TestErrorStack = {
|
||||
file: string;
|
||||
function?: string;
|
||||
line: number;
|
||||
column?: number;
|
||||
};
|
||||
|
||||
export type TestStatus = "pass" | "fail" | "skip";
|
||||
|
||||
export type Test = {
|
||||
name: string;
|
||||
status: TestStatus;
|
||||
errors?: TestError[];
|
||||
};
|
||||
|
||||
export type TestSummary = {
|
||||
pass: number;
|
||||
fail: number;
|
||||
skip: number;
|
||||
tests: number;
|
||||
files: number;
|
||||
duration: number;
|
||||
};
|
||||
|
||||
function parseTest(lines: string[], options?: ParseTestOptions): ParseTestResult {
|
||||
let i = 0;
|
||||
const isDone = () => {
|
||||
return i >= lines.length;
|
||||
};
|
||||
const readLine = () => {
|
||||
return lines[i++];
|
||||
};
|
||||
function readUntil<V>(cb: (line: string) => V | undefined): V | undefined {
|
||||
while (!isDone()) {
|
||||
const line = readLine();
|
||||
const result = cb(line);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
const { cwd, paths = cwd ? Array.from(listFiles(cwd, "")) : [] } = options ?? {};
|
||||
const info = readUntil(parseInfo);
|
||||
if (!info) {
|
||||
throw new Error("No tests found");
|
||||
}
|
||||
const files: TestFile[] = [];
|
||||
let file: TestFile | undefined;
|
||||
let test: Test | undefined;
|
||||
let error: TestError | undefined;
|
||||
let errorStart: number | undefined;
|
||||
let summary: TestSummary | undefined;
|
||||
const reset = () => {
|
||||
if (error) {
|
||||
if (file) {
|
||||
if (test) {
|
||||
if (!test?.errors) {
|
||||
test.errors = [error];
|
||||
} else {
|
||||
test.errors.push(error);
|
||||
}
|
||||
} else {
|
||||
if (!file.errors) {
|
||||
file.errors = [error];
|
||||
} else {
|
||||
file.errors.push(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
error = undefined;
|
||||
errorStart = undefined;
|
||||
}
|
||||
};
|
||||
while (!isDone()) {
|
||||
const line = readLine();
|
||||
if (error) {
|
||||
const newStack = parseStack(line, cwd);
|
||||
if (newStack) {
|
||||
if (errorStart !== undefined) {
|
||||
for (let j = errorStart; j < i - 1; j++) {
|
||||
error.message += `\n${lines[j]}`;
|
||||
}
|
||||
errorStart = undefined;
|
||||
}
|
||||
if (!error.stack) {
|
||||
error.stack = [newStack];
|
||||
} else {
|
||||
error.stack.push(newStack);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const newFile = parseFile(line, paths);
|
||||
if (newFile) {
|
||||
reset();
|
||||
file = newFile;
|
||||
files.push(file);
|
||||
continue;
|
||||
}
|
||||
const newTest = parseStatus(line);
|
||||
if (newTest) {
|
||||
if (newTest.status === "skip" && error) {
|
||||
continue;
|
||||
}
|
||||
test = newTest;
|
||||
if (file) {
|
||||
file.tests.push(test);
|
||||
file.summary[test.status]++;
|
||||
file.summary.tests++;
|
||||
if (test.status === "fail") {
|
||||
file.status = "fail";
|
||||
}
|
||||
}
|
||||
file?.tests.push(test);
|
||||
reset();
|
||||
continue;
|
||||
}
|
||||
const newError = parseError(line);
|
||||
if (newError) {
|
||||
reset();
|
||||
error = newError;
|
||||
errorStart = i;
|
||||
continue;
|
||||
}
|
||||
const newSkip = parseSkip(line);
|
||||
if (newSkip) {
|
||||
reset();
|
||||
i += parseSkip(line);
|
||||
continue;
|
||||
}
|
||||
const newSummary = parseSummary(line);
|
||||
if (newSummary) {
|
||||
summary = newSummary;
|
||||
break;
|
||||
}
|
||||
}
|
||||
summary = {
|
||||
tests: files.reduce((n, file) => n + file.tests.length, 0),
|
||||
files: files.length,
|
||||
duration: 0,
|
||||
...summary,
|
||||
pass: files.reduce((n, file) => n + file.tests.filter(test => test.status === "pass").length, 0),
|
||||
fail: files.reduce((n, file) => n + file.tests.filter(test => test.status === "fail").length, 0),
|
||||
skip: files.reduce((n, file) => n + file.tests.filter(test => test.status === "skip").length, 0),
|
||||
};
|
||||
if (files.length === 1) {
|
||||
files[0].summary = summary;
|
||||
}
|
||||
return {
|
||||
info,
|
||||
files,
|
||||
summary,
|
||||
};
|
||||
}
|
||||
|
||||
function getRevision(): string {
|
||||
if ("Bun" in globalThis) {
|
||||
return Bun.revision;
|
||||
}
|
||||
const { stdout } = spawnSync("bun", ["get-revision.js"], {
|
||||
cwd: new URL(".", import.meta.url),
|
||||
stdio: "pipe",
|
||||
encoding: "utf-8",
|
||||
});
|
||||
return stdout.trim();
|
||||
}
|
||||
|
||||
function parseInfo(line: string): TestInfo | undefined {
|
||||
const match = /^(bun (?:wip)?test) v([0-9\.]+) \(([0-9a-z]+)\)$/.exec(line);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
const [, name, version, sha] = match;
|
||||
return {
|
||||
name,
|
||||
version,
|
||||
revision: getRevision(),
|
||||
os: process.platform,
|
||||
arch: process.arch,
|
||||
};
|
||||
}
|
||||
|
||||
function parseFile(line: string, paths?: string[]): TestFile | undefined {
|
||||
const match = /^([a-z0-9_-]+\.(?:test|spec)\.(?:c|m)?(?:j|t)sx?)\:$/.exec(line);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
let [, file] = match;
|
||||
for (const path of paths ?? []) {
|
||||
if (path.endsWith(file)) {
|
||||
file = path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {
|
||||
file,
|
||||
tests: [],
|
||||
status: "pass",
|
||||
summary: {
|
||||
files: 1,
|
||||
tests: 0,
|
||||
pass: 0,
|
||||
fail: 0,
|
||||
skip: 0,
|
||||
duration: 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function parseStatus(line: string): Test | undefined {
|
||||
const match = /^(✓|✗|-) (.*)$/.exec(line);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
const [, icon, name] = match;
|
||||
return {
|
||||
name,
|
||||
status: icon === "✓" ? "pass" : icon === "✗" ? "fail" : "skip",
|
||||
};
|
||||
}
|
||||
|
||||
function parseError(line: string): TestError | undefined {
|
||||
const match = /^(.*error)\: (.*)$/i.exec(line);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
const [, name, message] = match;
|
||||
return {
|
||||
name: name === "error" ? "Error" : name,
|
||||
message,
|
||||
};
|
||||
}
|
||||
|
||||
function parseStack(line: string, cwd?: string): TestErrorStack | undefined {
|
||||
let match = /^\s*at (.*) \((.*)\:([0-9]+)\:([0-9]+)\)$/.exec(line);
|
||||
if (!match) {
|
||||
match = /^\s*at (.*)\:([0-9]+)\:([0-9]+)$/.exec(line);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
const [columnNo, lineNo, path, func] = match.reverse();
|
||||
let file = path;
|
||||
if (cwd && path.startsWith(cwd)) {
|
||||
file = path.slice(cwd.length);
|
||||
if (file.startsWith("/")) {
|
||||
file = file.slice(1);
|
||||
}
|
||||
}
|
||||
return {
|
||||
file,
|
||||
function: func !== line ? func : undefined,
|
||||
line: parseInt(lineNo),
|
||||
column: parseInt(columnNo),
|
||||
};
|
||||
}
|
||||
|
||||
function parseSkip(line: string): number {
|
||||
const match = /^([0-9]+) tests (?:skipped|failed)\:$/.exec(line);
|
||||
if (match) {
|
||||
return parseInt(match[1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function parseSummary(line: string): TestSummary | undefined {
|
||||
const match = /^Ran ([0-9]+) tests across ([0-9]+) files \[([0-9]+\.[0-9]+)(m?s)\]$/.exec(line);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
const [, tests, files, duration, unit] = match;
|
||||
return {
|
||||
pass: 0,
|
||||
fail: 0,
|
||||
skip: 0,
|
||||
tests: parseInt(tests),
|
||||
files: parseInt(files),
|
||||
duration: parseFloat(duration) * (unit === "s" ? 1000 : 1),
|
||||
};
|
||||
}
|
||||
|
||||
function* listFiles(cwd: string, dir: string): Generator<string> {
|
||||
const dirents = readdirSync(join(cwd, dir), { withFileTypes: true });
|
||||
for (const dirent of dirents) {
|
||||
const { name } = dirent;
|
||||
if (name === "node_modules" || name.startsWith(".")) {
|
||||
continue;
|
||||
}
|
||||
const path = join(dir, name);
|
||||
if (dirent.isDirectory()) {
|
||||
yield* listFiles(cwd, path);
|
||||
} else if (dirent.isFile()) {
|
||||
yield path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stripAnsi(string: string): string {
|
||||
return string.replace(/\x1b\[[0-9;]*m/g, "");
|
||||
}
|
||||
|
||||
function print(buffer: string | Uint8Array) {
|
||||
if (typeof buffer === "string") {
|
||||
buffer = new TextEncoder().encode(buffer);
|
||||
}
|
||||
let offset = 0;
|
||||
let length = buffer.byteLength;
|
||||
while (offset < length) {
|
||||
try {
|
||||
const n = writeSync(1, buffer);
|
||||
offset += n;
|
||||
if (offset < length) {
|
||||
try {
|
||||
fsyncSync(1);
|
||||
} catch {}
|
||||
buffer = buffer.slice(n);
|
||||
}
|
||||
} catch (error) {
|
||||
// @ts-ignore
|
||||
if (error.code === "EAGAIN") {
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: there is a bug that causes annotations to be duplicated
|
||||
const seen = new Set<string>();
|
||||
|
||||
function annotate(type: string, arg?: string, args?: Record<string, unknown>): void {
|
||||
let line = `::${type}`;
|
||||
if (args) {
|
||||
line += " ";
|
||||
line += Object.entries(args)
|
||||
.map(([key, value]) => `${key}=${value}`)
|
||||
.join(",");
|
||||
}
|
||||
line += "::";
|
||||
if (arg) {
|
||||
line += arg;
|
||||
}
|
||||
line = line.replace(/\n/g, "%0A");
|
||||
if (seen.has(line)) {
|
||||
return;
|
||||
}
|
||||
seen.add(line);
|
||||
print(`\n${line}\n`);
|
||||
}
|
||||
|
||||
async function* runTest(options: RunTestOptions): AsyncGenerator<RunTestResult, ParseTestResult> {
|
||||
const {
|
||||
cwd = process.cwd(),
|
||||
args = [],
|
||||
timeout = 60_000, // 1 min
|
||||
isolate = false,
|
||||
} = options;
|
||||
const paths: string[] = Array.from(listFiles(cwd, ""));
|
||||
const files: string[] = [];
|
||||
for (const path of paths) {
|
||||
if (!path.includes(".test.")) {
|
||||
continue;
|
||||
}
|
||||
if (!args.length) {
|
||||
files.push(path);
|
||||
continue;
|
||||
}
|
||||
for (const arg of args) {
|
||||
if (
|
||||
(arg.endsWith("/") && path.startsWith(arg)) ||
|
||||
(arg.includes(".") && path.endsWith(arg)) ||
|
||||
(!arg.endsWith("/") && !arg.includes(".") && path.includes(arg))
|
||||
) {
|
||||
files.push(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const runSingleTest = async (args: string[]) => {
|
||||
const runner = spawn("bun", ["test", ...args], {
|
||||
cwd,
|
||||
env: {
|
||||
...process.env,
|
||||
"FORCE_COLOR": "1",
|
||||
},
|
||||
stdio: "pipe",
|
||||
timeout,
|
||||
});
|
||||
let stderr = "";
|
||||
let stdout = "";
|
||||
const exitCode = await new Promise<number | null>(resolve => {
|
||||
runner.stdout.on("data", (data: Buffer) => {
|
||||
stdout += data.toString("utf-8");
|
||||
});
|
||||
runner.stderr.on("data", (data: Buffer) => {
|
||||
stderr += data.toString("utf-8");
|
||||
});
|
||||
runner.on("error", ({ name, message }) => {
|
||||
stderr += `${name}: ${message}`;
|
||||
resolve(null);
|
||||
});
|
||||
runner.on("exit", exitCode => {
|
||||
resolve(exitCode);
|
||||
});
|
||||
});
|
||||
const lines = stderr.split("\n").map(stripAnsi);
|
||||
const result = parseTest(lines, { cwd, paths });
|
||||
return {
|
||||
exitCode,
|
||||
stdout,
|
||||
stderr,
|
||||
...result,
|
||||
};
|
||||
};
|
||||
if (!isolate) {
|
||||
const result = await runSingleTest(args);
|
||||
yield result;
|
||||
return result;
|
||||
}
|
||||
const tests = files.map(file => runSingleTest([file]));
|
||||
const results: RunTestResult[] = [];
|
||||
for (const test of tests) {
|
||||
const result = await test;
|
||||
results.push(result);
|
||||
yield result;
|
||||
}
|
||||
if (!results.length) {
|
||||
throw new Error("No tests found");
|
||||
}
|
||||
return {
|
||||
info: results.map(result => result.info).pop()!,
|
||||
files: results.flatMap(result => result.files),
|
||||
summary: results
|
||||
.map(result => result.summary)
|
||||
.reduce((summary, result) => {
|
||||
summary.pass += result.pass;
|
||||
summary.fail += result.fail;
|
||||
summary.skip += result.skip;
|
||||
summary.tests += result.tests;
|
||||
summary.files += result.files;
|
||||
summary.duration += result.duration;
|
||||
return summary;
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
export type FormatTestOptions = {
|
||||
debug?: boolean;
|
||||
baseUrl?: string;
|
||||
};
|
||||
|
||||
function formatTest(result: ParseTestResult, options?: FormatTestOptions): string {
|
||||
const { debug, baseUrl } = options ?? {};
|
||||
const count = (n: number, label?: string) => {
|
||||
return n ? (label ? `${n} ${label}` : `${n}`) : "";
|
||||
};
|
||||
const code = (content: string, lang?: string) => {
|
||||
return `\`\`\`${lang ?? ""}\n${content}\n\`\`\`\n`;
|
||||
};
|
||||
const link = (title: string, href?: string) => {
|
||||
if (href && baseUrl) {
|
||||
href = `${new URL(href, baseUrl)}`;
|
||||
}
|
||||
return href ? `[${title}](${href})` : title;
|
||||
};
|
||||
const table = (headers: string[], rows: unknown[][]) => {
|
||||
return [headers, headers.map(() => "-"), ...rows].map(row => `| ${row.join(" | ")} |`).join("\n");
|
||||
};
|
||||
const header = (level: number, content: string) => {
|
||||
return `${"#".repeat(level)} ${content}\n`;
|
||||
};
|
||||
const icon = {
|
||||
pass: "✅",
|
||||
fail: "❌",
|
||||
skip: "⏭️",
|
||||
};
|
||||
const files = table(
|
||||
["File", "Status", "Pass", "Fail", "Skip", "Tests", "Duration"],
|
||||
result.files
|
||||
.filter(({ status }) => debug || status !== "pass")
|
||||
.sort((a, b) => {
|
||||
if (a.status === b.status) {
|
||||
return a.file.localeCompare(b.file);
|
||||
}
|
||||
return a.status.localeCompare(b.status);
|
||||
})
|
||||
.map(({ file, status, summary }) => [
|
||||
link(basename(file), file),
|
||||
icon[status],
|
||||
count(summary.pass),
|
||||
count(summary.fail),
|
||||
count(summary.skip),
|
||||
count(summary.tests),
|
||||
count(summary.duration, "ms"),
|
||||
]),
|
||||
);
|
||||
const errors = result.files
|
||||
.filter(({ status }) => status === "fail")
|
||||
.sort((a, b) => a.file.localeCompare(b.file))
|
||||
.flatMap(({ file, tests }) => {
|
||||
return [
|
||||
header(2, link(basename(file), file)),
|
||||
...tests
|
||||
.filter(({ status }) => status === "fail")
|
||||
.map(({ name, errors }) => {
|
||||
let content = header(3, name);
|
||||
if (errors) {
|
||||
content += errors
|
||||
.map(({ name, message, stack }) => {
|
||||
let preview = code(`${name}: ${message}`, "diff");
|
||||
if (stack?.length && baseUrl) {
|
||||
const { file, line } = stack[0];
|
||||
if (!is3rdParty(file)) {
|
||||
const { href } = new URL(`${file}?plain=1#L${Math.max(1, line - 5)}-L${line}`, baseUrl);
|
||||
preview += `\n${href}\n`;
|
||||
}
|
||||
}
|
||||
return preview;
|
||||
})
|
||||
.join("\n");
|
||||
} else {
|
||||
content += code("See logs for details");
|
||||
}
|
||||
return content;
|
||||
}),
|
||||
];
|
||||
})
|
||||
.join("\n");
|
||||
return `${header(1, "Files")}
|
||||
${files}
|
||||
|
||||
${header(1, "Errors")}
|
||||
${errors}`;
|
||||
}
|
||||
|
||||
function is3rdParty(file?: string): boolean {
|
||||
return !file || file.startsWith("/") || file.includes(":") || file.includes("..") || file.includes("node_modules/");
|
||||
}
|
||||
|
||||
function printTest(result: RunTestResult): void {
|
||||
const isAction = process.env["GITHUB_ACTIONS"] === "true";
|
||||
const isSingle = result.files.length === 1;
|
||||
if (isSingle) {
|
||||
const { file, status } = result.files[0];
|
||||
if (isAction) {
|
||||
annotate("group", `${status.toUpperCase()} - ${file}`);
|
||||
} else {
|
||||
print(`\n${file}:\n`);
|
||||
}
|
||||
}
|
||||
print(result.stderr);
|
||||
print(result.stdout);
|
||||
if (!isAction) {
|
||||
return;
|
||||
}
|
||||
result.files
|
||||
.filter(({ status }) => status === "fail")
|
||||
.flatMap(({ tests }) => tests)
|
||||
.filter(({ status }) => status === "fail")
|
||||
.flatMap(({ name: title, errors }) =>
|
||||
errors?.forEach(({ name, message, stack }) => {
|
||||
const { file, line } = stack?.[0] ?? {};
|
||||
if (is3rdParty(file)) {
|
||||
return;
|
||||
}
|
||||
annotate("error", `${name}: ${message}`, {
|
||||
file,
|
||||
line,
|
||||
title,
|
||||
});
|
||||
}),
|
||||
);
|
||||
if (isSingle) {
|
||||
annotate("endgroup");
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
let args = [...process.argv.slice(2)];
|
||||
let timeout;
|
||||
let isolate;
|
||||
let quiet;
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i];
|
||||
if (arg.startsWith("--timeout=")) {
|
||||
timeout = parseInt(arg.split("=").pop()!);
|
||||
} else if (arg.startsWith("--isolate")) {
|
||||
isolate = true;
|
||||
} else if (arg.startsWith("--quiet")) {
|
||||
quiet = true;
|
||||
}
|
||||
}
|
||||
args = args.filter(arg => !arg.startsWith("--"));
|
||||
const results = runTest({
|
||||
args,
|
||||
timeout,
|
||||
isolate,
|
||||
});
|
||||
let result: ParseTestResult;
|
||||
while (true) {
|
||||
const { value, done } = await results.next();
|
||||
if (done) {
|
||||
result = value;
|
||||
break;
|
||||
} else if (!quiet) {
|
||||
printTest(value);
|
||||
}
|
||||
}
|
||||
const summaryPath = process.env["GITHUB_STEP_SUMMARY"];
|
||||
if (!summaryPath) {
|
||||
return;
|
||||
}
|
||||
const sha = process.env["GITHUB_SHA"] ?? result.info.revision;
|
||||
const repo = process.env["GITHUB_REPOSITORY"] ?? "oven-sh/bun";
|
||||
const serverUrl = process.env["GITHUB_SERVER_URL"] ?? "https://github.com";
|
||||
const summary = formatTest(result, {
|
||||
debug: process.env["ACTIONS_STEP_DEBUG"] === "true",
|
||||
baseUrl: `${serverUrl}/${repo}/blob/${sha}/`,
|
||||
});
|
||||
appendFileSync(summaryPath, summary, "utf-8");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
function isMain() {
|
||||
return import.meta.main || import.meta.url === `file://${process.argv[1]}`;
|
||||
}
|
||||
|
||||
if (isMain()) {
|
||||
await main();
|
||||
}
|
||||
2
.github/workflows/bun-linux-aarch64.yml
vendored
2
.github/workflows/bun-linux-aarch64.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
arch: aarch64
|
||||
build_arch: arm64
|
||||
runner: linux-arm64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-linux-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-linux-arm64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-arm64-lto"
|
||||
build_machine_arch: aarch64
|
||||
|
||||
|
||||
6
.github/workflows/bun-linux-build.yml
vendored
6
.github/workflows/bun-linux-build.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
arch: x86_64
|
||||
build_arch: amd64
|
||||
runner: big-ubuntu
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-amd64-lto"
|
||||
build_machine_arch: x86_64
|
||||
- cpu: nehalem
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
arch: x86_64
|
||||
build_arch: amd64
|
||||
runner: big-ubuntu
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-linux-amd64-lto.tar.gz"
|
||||
webkit_basename: "bun-webkit-linux-amd64-lto"
|
||||
build_machine_arch: x86_64
|
||||
|
||||
@@ -152,7 +152,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [linux]
|
||||
if: github.event_name == 'pull_request'
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 20
|
||||
outputs:
|
||||
failing_tests: ${{ steps.test.outputs.failing_tests }}
|
||||
failing_tests_count: ${{ steps.test.outputs.failing_tests_count }}
|
||||
|
||||
16
.github/workflows/bun-mac-aarch64.yml
vendored
16
.github/workflows/bun-mac-aarch64.yml
vendored
@@ -110,7 +110,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
# - cpu: haswell
|
||||
@@ -119,7 +119,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
# - cpu: nehalem
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
# - cpu: haswell
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
- cpu: native
|
||||
@@ -145,7 +145,7 @@ jobs:
|
||||
tag: bun-darwin-aarch64
|
||||
obj: bun-obj-darwin-aarch64
|
||||
artifact: bun-obj-darwin-aarch64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
runner: macos-arm64
|
||||
dependencies: true
|
||||
compile_obj: true
|
||||
@@ -249,7 +249,7 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: haswell
|
||||
# arch: x86_64
|
||||
# tag: bun-darwin-x64
|
||||
@@ -257,14 +257,14 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
- cpu: native
|
||||
arch: aarch64
|
||||
tag: bun-darwin-aarch64
|
||||
obj: bun-obj-darwin-aarch64
|
||||
package: bun-darwin-aarch64
|
||||
artifact: bun-obj-darwin-aarch64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
18
.github/workflows/bun-mac-x64-baseline.yml
vendored
18
.github/workflows/bun-mac-x64-baseline.yml
vendored
@@ -110,7 +110,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64-baseline
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64-baseline
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: true
|
||||
compile_obj: false
|
||||
# - cpu: haswell
|
||||
@@ -119,7 +119,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
- cpu: nehalem
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64-baseline
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64-baseline
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: false
|
||||
compile_obj: true
|
||||
# - cpu: haswell
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
# - cpu: native
|
||||
@@ -145,7 +145,7 @@ jobs:
|
||||
# tag: bun-darwin-aarch64
|
||||
# obj: bun-obj-darwin-aarch64
|
||||
# artifact: bun-obj-darwin-aarch64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
# dependencies: true
|
||||
# compile_obj: true
|
||||
@@ -250,7 +250,7 @@ jobs:
|
||||
package: bun-darwin-x64
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64-baseline
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: haswell
|
||||
# arch: x86_64
|
||||
# tag: bun-darwin-x64
|
||||
@@ -258,14 +258,14 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: native
|
||||
# arch: aarch64
|
||||
# tag: bun-darwin-aarch64
|
||||
# obj: bun-obj-darwin-aarch64
|
||||
# package: bun-darwin-aarch64
|
||||
# artifact: bun-obj-darwin-aarch64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -393,7 +393,7 @@ jobs:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
needs: [macOS]
|
||||
if: github.event_name == 'pull_request'
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 30
|
||||
outputs:
|
||||
failing_tests: ${{ steps.test.outputs.failing_tests }}
|
||||
failing_tests_count: ${{ steps.test.outputs.failing_tests_count }}
|
||||
|
||||
18
.github/workflows/bun-mac-x64.yml
vendored
18
.github/workflows/bun-mac-x64.yml
vendored
@@ -110,7 +110,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: true
|
||||
# compile_obj: false
|
||||
- cpu: haswell
|
||||
@@ -119,7 +119,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: true
|
||||
compile_obj: false
|
||||
# - cpu: nehalem
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
# obj: bun-obj-darwin-x64-baseline
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# dependencies: false
|
||||
# compile_obj: true
|
||||
- cpu: haswell
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
obj: bun-obj-darwin-x64
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
dependencies: false
|
||||
compile_obj: true
|
||||
# - cpu: native
|
||||
@@ -145,7 +145,7 @@ jobs:
|
||||
# tag: bun-darwin-aarch64
|
||||
# obj: bun-obj-darwin-aarch64
|
||||
# artifact: bun-obj-darwin-aarch64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
# dependencies: true
|
||||
# compile_obj: true
|
||||
@@ -252,7 +252,7 @@ jobs:
|
||||
# package: bun-darwin-x64
|
||||
# runner: macos-11
|
||||
# artifact: bun-obj-darwin-x64-baseline
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
- cpu: haswell
|
||||
arch: x86_64
|
||||
tag: bun-darwin-x64
|
||||
@@ -260,14 +260,14 @@ jobs:
|
||||
package: bun-darwin-x64
|
||||
runner: macos-11
|
||||
artifact: bun-obj-darwin-x64
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-amd64-lto.tar.gz"
|
||||
# - cpu: native
|
||||
# arch: aarch64
|
||||
# tag: bun-darwin-aarch64
|
||||
# obj: bun-obj-darwin-aarch64
|
||||
# package: bun-darwin-aarch64
|
||||
# artifact: bun-obj-darwin-aarch64
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# webkit_url: "https://github.com/oven-sh/WebKit/releases/download/apr12-23/bun-webkit-macos-arm64-lto.tar.gz"
|
||||
# runner: macos-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -395,7 +395,7 @@ jobs:
|
||||
runs-on: ${{ matrix.runner }}
|
||||
needs: [macOS]
|
||||
if: github.event_name == 'pull_request'
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 30
|
||||
outputs:
|
||||
failing_tests: ${{ steps.test.outputs.failing_tests }}
|
||||
failing_tests_count: ${{ steps.test.outputs.failing_tests_count }}
|
||||
|
||||
29
.github/workflows/bun-release-canary.yml
vendored
29
.github/workflows/bun-release-canary.yml
vendored
@@ -39,6 +39,7 @@ jobs:
|
||||
npm:
|
||||
name: Release to NPM
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-release
|
||||
@@ -144,3 +145,31 @@ jobs:
|
||||
labels: ${{ steps.metadata.outputs.labels }}
|
||||
build-args: |
|
||||
BUN_VERSION=canary
|
||||
s3:
|
||||
name: Upload to S3
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-release
|
||||
steps:
|
||||
- id: checkout
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- id: setup-bun
|
||||
name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: canary
|
||||
- id: bun-install
|
||||
name: Install Dependencies
|
||||
run: bun install
|
||||
- id: bun-run
|
||||
name: Release
|
||||
run: bun upload-s3 -- canary
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY}}
|
||||
AWS_ENDPOINT: ${{ secrets.AWS_ENDPOINT }}
|
||||
AWS_BUCKET: bun
|
||||
|
||||
38
.github/workflows/bun-release.yml
vendored
38
.github/workflows/bun-release.yml
vendored
@@ -52,6 +52,7 @@ jobs:
|
||||
npm:
|
||||
name: Release to NPM
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-release
|
||||
@@ -83,6 +84,7 @@ jobs:
|
||||
npm-types:
|
||||
name: Release types to NPM
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-types
|
||||
@@ -174,6 +176,7 @@ jobs:
|
||||
homebrew:
|
||||
name: Release to Homebrew
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
steps:
|
||||
- id: checkout
|
||||
name: Checkout
|
||||
@@ -211,3 +214,38 @@ jobs:
|
||||
commit_user_name: robobun
|
||||
commit_user_email: robobun@oven.sh
|
||||
commit_author: robobun <robobun@oven.sh>
|
||||
s3:
|
||||
name: Upload to S3
|
||||
runs-on: ubuntu-latest
|
||||
needs: sign
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/bun-release
|
||||
steps:
|
||||
- id: checkout
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- id: setup-env
|
||||
name: Setup Environment
|
||||
run: |
|
||||
TAG="${{ github.event.inputs.tag }}"
|
||||
TAG="${TAG:-"${{ github.event.release.tag_name }}"}"
|
||||
echo "Setup tag: ${TAG}"
|
||||
echo "TAG=${TAG}" >> ${GITHUB_ENV}
|
||||
- id: setup-bun
|
||||
name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: canary
|
||||
- id: bun-install
|
||||
name: Install Dependencies
|
||||
run: bun install
|
||||
- id: bun-run
|
||||
name: Release
|
||||
run: bun upload-s3 -- "${{ env.TAG }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY}}
|
||||
AWS_ENDPOINT: ${{ secrets.AWS_ENDPOINT }}
|
||||
AWS_BUCKET: bun
|
||||
|
||||
58
.github/workflows/bun-test.yml
vendored
Normal file
58
.github/workflows/bun-test.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "The version of Bun to run"
|
||||
required: true
|
||||
default: "canary"
|
||||
type: string
|
||||
path:
|
||||
description: "The path to the test files"
|
||||
required: true
|
||||
default: "test/"
|
||||
type: string
|
||||
timeout:
|
||||
description: "The timeout per file in milliseconds"
|
||||
required: true
|
||||
default: "15000"
|
||||
type: number
|
||||
jobs:
|
||||
test:
|
||||
name: ${{ matrix.tag }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
tag: linux-x64
|
||||
url: linux/x64?avx2=true
|
||||
- os: ubuntu-latest
|
||||
tag: linux-x64-baseline
|
||||
url: linux/x64?baseline=true
|
||||
- os: macos-latest
|
||||
tag: darwin-x64
|
||||
url: darwin/x64?avx2=true
|
||||
- os: macos-latest
|
||||
tag: darwin-x64-baseline
|
||||
url: darwin/x64?baseline=true
|
||||
steps:
|
||||
- id: checkout
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
- id: setup
|
||||
name: Setup
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-download-url: https://bun.sh/download/${{ github.event.inputs.version }}/${{ matrix.url }}
|
||||
- id: test
|
||||
name: Test
|
||||
run: |
|
||||
bun install
|
||||
bun install --cwd test
|
||||
bun x ts-node --esm .github/scripts/test-runner.ts ${{ github.event.inputs.path }} --isolated --timeout=${{ github.event.inputs.timeout }}
|
||||
9
.github/workflows/bun-typecheck.yml
vendored
9
.github/workflows/bun-typecheck.yml
vendored
@@ -7,6 +7,8 @@ on:
|
||||
- "test/**"
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "packages/bun-types/**"
|
||||
- "test/**"
|
||||
@@ -15,9 +17,7 @@ jobs:
|
||||
tests:
|
||||
name: check-tests
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: test
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
@@ -27,5 +27,8 @@ jobs:
|
||||
bun-version: canary
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
working-directory: test
|
||||
- name: Typecheck tests
|
||||
run: bun run typecheck
|
||||
|
||||
59
.github/workflows/run-test-manually.yml
vendored
59
.github/workflows/run-test-manually.yml
vendored
@@ -1,59 +0,0 @@
|
||||
name: Run Tests Manually
|
||||
|
||||
on:
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Version"
|
||||
required: true
|
||||
default: "canary"
|
||||
type: string
|
||||
use_bun:
|
||||
description: "Use Bun?"
|
||||
required: true
|
||||
default: true
|
||||
type: boolean
|
||||
jobs:
|
||||
linux-test:
|
||||
name: Tests ${{matrix.tag}} ${{github.event.inputs.version}}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- tag: linux-x64
|
||||
- tag: linux-x64-baseline
|
||||
steps:
|
||||
- id: checkout
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
- id: install-npm
|
||||
name: Install (npm)
|
||||
run: |
|
||||
npm install @oven/bun-${{matrix.tag}}@${{github.event.inputs.version}}
|
||||
chmod +x node_modules/@oven/bun-${{matrix.tag}}/bin/bun
|
||||
sudo cp node_modules/@oven/bun-${{matrix.tag}}/bin/bun /usr/bin/bun
|
||||
- id: test
|
||||
name: Test
|
||||
if: ${{github.event.inputs.use_bun == 'true'}}
|
||||
run: |
|
||||
bun install
|
||||
bun install --cwd test/bun.js
|
||||
bun install --cwd test/bun.js/third-party/body-parser-test
|
||||
cd packages/bun-internal-test
|
||||
bun install
|
||||
bun run test
|
||||
- id: test-node-runner
|
||||
name: Test (node runner)
|
||||
if: ${{github.event.inputs.use_bun == 'false'}}
|
||||
run: |
|
||||
bun install
|
||||
bun install --cwd test/bun.js
|
||||
bun install --cwd test/bun.js/third-party/body-parser-test
|
||||
cd packages/bun-internal-test
|
||||
bun install
|
||||
node src/runner.node.mjs
|
||||
2
.github/workflows/zig-fmt.yml
vendored
2
.github/workflows/zig-fmt.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: zig-fmt
|
||||
|
||||
env:
|
||||
ZIG_VERSION: 0.11.0-dev.1783+436e99d13
|
||||
ZIG_VERSION: 0.11.0-dev.2571+31738de28
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -13,7 +13,7 @@ dist
|
||||
*.log
|
||||
*.out.js
|
||||
*.out.refresh.js
|
||||
/package-lock.json
|
||||
**/package-lock.json
|
||||
build
|
||||
*.wat
|
||||
zig-out
|
||||
@@ -45,6 +45,7 @@ outcss
|
||||
txt.js
|
||||
.idea
|
||||
.vscode/cpp*
|
||||
.vscode/clang*
|
||||
|
||||
node_modules_*
|
||||
*.jsb
|
||||
|
||||
@@ -7,3 +7,7 @@ if [ -d ./node_modules/bun-webkit ]; then
|
||||
# get the first matching bun-webkit-* directory name
|
||||
ln -s ./node_modules/$(ls ./node_modules | grep bun-webkit- | head -n 1) ./bun-webkit
|
||||
fi
|
||||
|
||||
# sets up vscode C++ intellisense
|
||||
rm -f .vscode/clang++
|
||||
ln -s $(which clang++-15 || which clang++) .vscode/clang++ 2>/dev/null
|
||||
|
||||
6
.vscode/c_cpp_properties.json
vendored
6
.vscode/c_cpp_properties.json
vendored
@@ -2,9 +2,7 @@
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Mac",
|
||||
"forcedInclude": [
|
||||
"${workspaceFolder}/src/bun.js/bindings/root.h"
|
||||
],
|
||||
"forcedInclude": ["${workspaceFolder}/src/bun.js/bindings/root.h"],
|
||||
"includePath": [
|
||||
"${workspaceFolder}/../webkit-build/include/",
|
||||
"${workspaceFolder}/bun-webkit/include/",
|
||||
@@ -57,7 +55,7 @@
|
||||
"DU_DISABLE_RENAMING=1"
|
||||
],
|
||||
"macFrameworkPath": [],
|
||||
"compilerPath": "/opt/homebrew/opt/llvm/bin/clang++",
|
||||
"compilerPath": "${workspaceFolder}/.vscode/clang++",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++20"
|
||||
}
|
||||
|
||||
9
.vscode/extensions.json
vendored
9
.vscode/extensions.json
vendored
@@ -1,3 +1,10 @@
|
||||
{
|
||||
"recommendations": ["ziglang.vscode-zig", "esbenp.prettier-vscode", "xaver.clang-format", "vadimcn.vscode-lldb"]
|
||||
"recommendations": [
|
||||
"ziglang.vscode-zig",
|
||||
"esbenp.prettier-vscode",
|
||||
"xaver.clang-format",
|
||||
"vadimcn.vscode-lldb",
|
||||
"bierner.comment-tagged-templates",
|
||||
"ms-vscode.cpptools"
|
||||
]
|
||||
}
|
||||
|
||||
91
.vscode/launch.json
generated
vendored
91
.vscode/launch.json
generated
vendored
@@ -138,13 +138,100 @@
|
||||
"request": "launch",
|
||||
"name": "bun build debug",
|
||||
"program": "bun-debug",
|
||||
"args": ["build", "--platform=bun", "--outdir=/tmp/testout", "${file}"],
|
||||
"cwd": "${file}/../../",
|
||||
"args": ["bun", "./test/fixtures/bundle/trivial/index.js"],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "internalConsole",
|
||||
"env": {
|
||||
"BUN_CONFIG_MINIFY_WHITESPACE": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun build debug out.js",
|
||||
"program": "bun-debug",
|
||||
"args": ["--outfile=out.js", "bun", "${file}"],
|
||||
"cwd": "${file}/../",
|
||||
"console": "internalConsole",
|
||||
"env": {
|
||||
"BUN_CONFIG_MINIFY_WHITESPACE": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun build debug STDOUT",
|
||||
"program": "bun-debug",
|
||||
"args": ["bun", "${file}"],
|
||||
"cwd": "${file}/../",
|
||||
"console": "internalConsole",
|
||||
"env": {}
|
||||
},
|
||||
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun build debug (no splitting, browser entry)",
|
||||
"program": "bun-debug",
|
||||
"args": [
|
||||
"--entry-names=./[name].[ext]",
|
||||
"--outdir=/Users/jarred/Code/bun-rsc/.rsc-no-split",
|
||||
"--platform=browser",
|
||||
"bun",
|
||||
"./quick.tsx"
|
||||
],
|
||||
"cwd": "/Users/jarred/Code/bun-rsc",
|
||||
"console": "internalConsole",
|
||||
"env": {
|
||||
"NODE_ENV": "production"
|
||||
// "BUN_DEBUG_QUIET_LOGS": "1"
|
||||
// "BUN_DUMP_SYMBOLS": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun build debug (splitting, rsc)",
|
||||
"program": "bun-debug",
|
||||
"args": [
|
||||
"--entry-names=./[name].[ext]",
|
||||
"--outdir=/Users/jarred/Code/bun-rsc/.rsc-split",
|
||||
"--server-components",
|
||||
"--platform=bun",
|
||||
"--splitting",
|
||||
"bun",
|
||||
"/Users/jarred/Code/bun-rsc/components/Message.tsx",
|
||||
"/Users/jarred/Code/bun-rsc/components/Button.tsx",
|
||||
],
|
||||
"cwd": "/Users/jarred/Code/bun-rsc",
|
||||
"console": "internalConsole",
|
||||
"env": {
|
||||
"NODE_ENV": "production"
|
||||
// "BUN_DEBUG_QUIET_LOGS": "1"
|
||||
// "BUN_DUMP_SYMBOLS": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "bun build debug (NO splitting, rsc)",
|
||||
"program": "bun-debug",
|
||||
"args": [
|
||||
"--entry-names=./[name].[ext]",
|
||||
"--outdir=/Users/jarred/Code/bun-rsc/.rsccheck",
|
||||
"--server-components",
|
||||
"--platform=bun",
|
||||
"bun",
|
||||
"/Users/jarred/Code/bun-rsc/pages/index.js"
|
||||
],
|
||||
"cwd": "/Users/jarred/Code/bun-rsc",
|
||||
"console": "internalConsole",
|
||||
"env": {
|
||||
"NODE_ENV": "production"
|
||||
// "BUN_DEBUG_QUIET_LOGS": "1"
|
||||
// "BUN_DUMP_SYMBOLS": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
|
||||
19
.vscode/settings.json
vendored
19
.vscode/settings.json
vendored
@@ -7,10 +7,7 @@
|
||||
"search.followSymlinks": false,
|
||||
"search.useIgnoreFiles": true,
|
||||
"zig.buildOnSave": false,
|
||||
"zig.buildArgs": [
|
||||
"obj",
|
||||
"-Dfor-editor"
|
||||
],
|
||||
"zig.buildArgs": ["obj", "-Dfor-editor"],
|
||||
"zig.buildOption": "build",
|
||||
"zig.buildFilePath": "${workspaceFolder}/build.zig",
|
||||
"[zig]": {
|
||||
@@ -27,6 +24,8 @@
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"zig.zls.enableInlayHints": false,
|
||||
|
||||
"[jsx]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
@@ -44,7 +43,7 @@
|
||||
"editor.unicodeHighlight.ambiguousCharacters": false,
|
||||
"editor.unicodeHighlight.invisibleCharacters": false,
|
||||
"diffEditor.ignoreTrimWhitespace": false,
|
||||
"editor.defaultFormatter": "yzhang.markdown-all-in-one",
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.wordWrap": "on",
|
||||
"editor.quickSuggestions": {
|
||||
@@ -208,9 +207,7 @@
|
||||
"__verbose_abort": "cpp"
|
||||
},
|
||||
"cmake.configureOnOpen": false,
|
||||
"C_Cpp.errorSquiggles": "Enabled",
|
||||
"eslint.workingDirectories": [
|
||||
"packages/bun-types"
|
||||
],
|
||||
"files.insertFinalNewline": true
|
||||
}
|
||||
"C_Cpp.errorSquiggles": "enabled",
|
||||
"eslint.workingDirectories": ["packages/bun-types"],
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contributing to Bun
|
||||
|
||||
All contributions need test coverage. If you are adding a new feature, please add a test. If you are fixing a bug, please add a test that fails before your fix and passes after your fix.
|
||||
> **Important:** All contributions need test coverage. If you are adding a new feature, please add a test. If you are fixing a bug, please add a test that fails before your fix and passes after your fix.
|
||||
|
||||
## Bun's codebase
|
||||
|
||||
@@ -16,6 +16,10 @@ Today (February 2023), Bun's codebase has five distinct parts:
|
||||
|
||||
The JavaScript transpiler & module resolver is mostly independent from the runtime. It predates the runtime and is entirely in Zig. The JavaScript parser is mostly in [`src/js_parser.zig`](src/js_parser.zig). The JavaScript AST data structures are mostly in [`src/js_ast.zig`](src/js_ast.zig). The JavaScript lexer is in [`src/js_lexer.zig`](src/js_lexer.zig). A lot of this code started as a port of esbuild's equivalent code from Go to Zig, but has had many small changes since then.
|
||||
|
||||
## Getting started
|
||||
|
||||
Please refer to [Bun's Development Guide](https://bun.sh/docs/project/development) to get your dev environment setup!
|
||||
|
||||
## Memory management in Bun
|
||||
|
||||
For the Zig code, please:
|
||||
|
||||
@@ -12,7 +12,7 @@ ARG TRIPLET=${ARCH}-linux-gnu
|
||||
ARG BUILDARCH=amd64
|
||||
ARG WEBKIT_TAG=feb9
|
||||
ARG ZIG_TAG=jul1
|
||||
ARG ZIG_VERSION="0.11.0-dev.1783+436e99d13"
|
||||
ARG ZIG_VERSION="0.11.0-dev.2571+31738de28"
|
||||
ARG WEBKIT_BASENAME="bun-webkit-linux-$BUILDARCH"
|
||||
|
||||
ARG ZIG_FOLDERNAME=zig-linux-${BUILD_MACHINE_ARCH}-${ZIG_VERSION}
|
||||
@@ -20,7 +20,7 @@ ARG ZIG_FILENAME=${ZIG_FOLDERNAME}.tar.xz
|
||||
ARG WEBKIT_URL="https://github.com/oven-sh/WebKit/releases/download/$WEBKIT_TAG/${WEBKIT_BASENAME}.tar.gz"
|
||||
ARG ZIG_URL="https://ziglang.org/builds/${ZIG_FILENAME}"
|
||||
ARG GIT_SHA=""
|
||||
ARG BUN_BASE_VERSION=0.5
|
||||
ARG BUN_BASE_VERSION=0.6
|
||||
|
||||
FROM bitnami/minideb:bullseye as bun-base
|
||||
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG GITHUB_WORKSPACE=/build
|
||||
ARG BUILDARCH=amd64
|
||||
ARG ARCH=x86_64
|
||||
ARG ZIG_PATH=${GITHUB_WORKSPACE}/zig
|
||||
ARG WEBKIT_DIR=${GITHUB_WORKSPACE}/bun-webkit
|
||||
ARG BUN_RELEASE_DIR=${GITHUB_WORKSPACE}/bun-release
|
||||
ARG BUN_DEPS_OUT_DIR=${GITHUB_WORKSPACE}/bun-deps
|
||||
ARG BUN_DIR=${GITHUB_WORKSPACE}/bun
|
||||
ARG BUN_PACKAGES_DIR=${BUN_DIR}/packages
|
||||
ARG ZIG_VERSION="0.11.0-dev.1783+436e99d13"
|
||||
|
||||
ARG ZIG_FOLDERNAME=zig-linux-${ARCH}-${ZIG_VERSION}
|
||||
ARG ZIG_FILENAME=${ZIG_FOLDERNAME}.tar.xz
|
||||
ARG ZIG_URL="https://ziglang.org/builds/${ZIG_FILENAME}"
|
||||
|
||||
FROM --platform=linux/${BUILDARCH} ubuntu:22.04 as bun.devcontainer
|
||||
|
||||
ARG DEBIAN_FRONTEND
|
||||
ARG GITHUB_WORKSPACE
|
||||
ARG BUILDARCH
|
||||
ARG ZIG_PATH
|
||||
ARG WEBKIT_DIR
|
||||
ARG BUN_RELEASE_DIR
|
||||
ARG BUN_DEPS_OUT_DIR
|
||||
ARG BUN_DIR
|
||||
ARG BUN_PACKAGES_DIR
|
||||
|
||||
ENV WEBKIT_OUT_DIR ${WEBKIT_DIR}
|
||||
ENV PATH "$ZIG_PATH:$PATH"
|
||||
ENV JSC_BASE_DIR $WEBKIT_OUT_DIR
|
||||
ENV LIB_ICU_PATH ${WEBKIT_OUT_DIR}/lib
|
||||
ENV BUN_RELEASE_DIR ${BUN_RELEASE_DIR}
|
||||
ENV PATH "${BUN_PACKAGES_DIR}/bun-linux-x64:${BUN_PACKAGES_DIR}/bun-linux-aarch64:${BUN_PACKAGES_DIR}/debug-bun-linux-x64:${BUN_PACKAGES_DIR}/debug-bun-linux-aarch64:$PATH"
|
||||
ENV PATH "/home/ubuntu/zls/zig-out/bin:$PATH"
|
||||
ENV BUN_INSTALL /home/ubuntu/.bun
|
||||
ENV XDG_CONFIG_HOME /home/ubuntu/.config
|
||||
|
||||
WORKDIR ${GITHUB_WORKSPACE}
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install --no-install-recommends -y wget gnupg2 curl lsb-release wget software-properties-common && \
|
||||
add-apt-repository ppa:longsleep/golang-backports && \
|
||||
wget https://apt.llvm.org/llvm.sh --no-check-certificate && \
|
||||
chmod +x llvm.sh && \
|
||||
./llvm.sh 15 && \
|
||||
curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
|
||||
apt-get update && \
|
||||
apt-get install --no-install-recommends -y \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg2 \
|
||||
software-properties-common \
|
||||
cmake \
|
||||
build-essential \
|
||||
git \
|
||||
libssl-dev \
|
||||
ruby \
|
||||
liblld-15-dev \
|
||||
libclang-15-dev \
|
||||
nodejs \
|
||||
gcc \
|
||||
g++ \
|
||||
clang-15 \
|
||||
clang-format-15 \
|
||||
libc++-15-dev \
|
||||
libc++abi-15-dev \
|
||||
lld-15 \
|
||||
libicu-dev \
|
||||
wget \
|
||||
rustc \
|
||||
cargo \
|
||||
unzip \
|
||||
tar \
|
||||
golang-go ninja-build pkg-config automake autoconf libtool curl && \
|
||||
update-alternatives --install /usr/bin/cc cc /usr/bin/clang-15 90 && \
|
||||
update-alternatives --install /usr/bin/cpp cpp /usr/bin/clang++-15 90 && \
|
||||
update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-15 90 && \
|
||||
npm install -g esbuild
|
||||
|
||||
ENV CC=clang-15
|
||||
ENV CXX=clang++-15
|
||||
ENV ZIG "${ZIG_PATH}/zig"
|
||||
|
||||
WORKDIR $GITHUB_WORKSPACE
|
||||
|
||||
RUN cd / && mkdir -p $BUN_RELEASE_DIR $BUN_DEPS_OUT_DIR ${BUN_DIR} ${BUN_DEPS_OUT_DIR}
|
||||
|
||||
WORKDIR $GITHUB_WORKSPACE
|
||||
|
||||
|
||||
ARG ZIG_FOLDERNAME
|
||||
ARG ZIG_FILENAME
|
||||
ARG ZIG_URL
|
||||
|
||||
ADD $ZIG_URL .
|
||||
RUN tar -xf ${ZIG_FILENAME} && \
|
||||
rm ${ZIG_FILENAME} && \
|
||||
mv ${ZIG_FOLDERNAME} ${ZIG_PATH};
|
||||
|
||||
RUN cd $GITHUB_WORKSPACE && \
|
||||
curl -o bun-webkit-linux-$BUILDARCH.tar.gz -L https://github.com/oven-sh/WebKit/releases/download/feb25/bun-webkit-linux-$BUILDARCH.tar.gz && \
|
||||
tar -xzf bun-webkit-linux-$BUILDARCH.tar.gz && \
|
||||
rm bun-webkit-linux-$BUILDARCH.tar.gz && \
|
||||
cat $WEBKIT_OUT_DIR/include/cmakeconfig.h > /dev/null
|
||||
|
||||
RUN apt-get -y update && update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-15 90
|
||||
|
||||
COPY .devcontainer/workspace.code-workspace $GITHUB_WORKSPACE/workspace.code-workspace
|
||||
COPY .devcontainer/zls.json $GITHUB_WORKSPACE/workspace.code-workspace
|
||||
COPY .devcontainer/limits.conf /etc/security/limits.conf
|
||||
COPY ".devcontainer/scripts/" /scripts/
|
||||
COPY ".devcontainer/scripts/getting-started.sh" $GITHUB_WORKSPACE/getting-started.sh
|
||||
COPY ".devcontainer/README.md" $GITHUB_WORKSPACE/README.md
|
||||
|
||||
ENV JSC_BASE_DIR=$WEBKIT_DIR
|
||||
ENV WEBKIT_RELEASE_DIR=$WEBKIT_DIR
|
||||
ENV WEBKIT_DEBUG_DIR=$WEBKIT_DIR
|
||||
ENV WEBKIT_RELEASE_DIR_LTO=$WEBKIT_DIR
|
||||
|
||||
RUN mkdir -p /home/ubuntu/.bun /home/ubuntu/.config $GITHUB_WORKSPACE/bun && \
|
||||
bash /scripts/common-debian.sh && \
|
||||
bash /scripts/github.sh && \
|
||||
bash /scripts/nice.sh && \
|
||||
bash /scripts/zig-env.sh
|
||||
COPY .devcontainer/zls.json /home/ubuntu/.config/zls.json
|
||||
135
Makefile
135
Makefile
@@ -1,4 +1,4 @@
|
||||
SHELL := $(shell which bash) # Use bash syntax to be consistent
|
||||
SHELL := $(shell which bash) # Use bash syntax to be consistent
|
||||
|
||||
OS_NAME := $(shell uname -s | tr '[:upper:]' '[:lower:]')
|
||||
ARCH_NAME_RAW := $(shell uname -m)
|
||||
@@ -39,11 +39,11 @@ NATIVE_OR_OLD_MARCH = -march=nehalem
|
||||
endif
|
||||
|
||||
MIN_MACOS_VERSION ?= $(DEFAULT_MIN_MACOS_VERSION)
|
||||
BUN_BASE_VERSION = 0.5
|
||||
BUN_BASE_VERSION = 0.6
|
||||
|
||||
AR=
|
||||
|
||||
BUN_OR_NODE = $(shell which bun || which node)
|
||||
BUN_OR_NODE = $(shell which bun 2>/dev/null || which node 2>/dev/null)
|
||||
|
||||
CXX_VERSION=c++2a
|
||||
TRIPLET = $(OS_NAME)-$(ARCH_NAME)
|
||||
@@ -52,30 +52,31 @@ PACKAGES_REALPATH = $(realpath packages)
|
||||
PACKAGE_DIR = $(PACKAGES_REALPATH)/$(PACKAGE_NAME)
|
||||
DEBUG_PACKAGE_DIR = $(PACKAGES_REALPATH)/debug-$(PACKAGE_NAME)
|
||||
RELEASE_BUN = $(PACKAGE_DIR)/bun
|
||||
DEBUG_BIN = $(DEBUG_PACKAGE_DIR)/
|
||||
DEBUG_BIN = $(DEBUG_PACKAGE_DIR)
|
||||
DEBUG_BUN = $(DEBUG_BIN)/bun-debug
|
||||
BUILD_ID = $(shell cat ./src/build-id)
|
||||
PACKAGE_JSON_VERSION = $(BUN_BASE_VERSION).$(BUILD_ID)
|
||||
BUN_BUILD_TAG = bun-v$(PACKAGE_JSON_VERSION)
|
||||
BUN_RELEASE_BIN = $(PACKAGE_DIR)/bun
|
||||
PRETTIER ?= $(shell which prettier || echo "./node_modules/.bin/prettier")
|
||||
DSYMUTIL ?= $(shell which dsymutil || which dsymutil-15)
|
||||
PRETTIER ?= $(shell which prettier 2>/dev/null || echo "./node_modules/.bin/prettier")
|
||||
ESBUILD = $(shell which esbuild 2>/dev/null || echo "./node_modules/.bin/esbuild")
|
||||
DSYMUTIL ?= $(shell which dsymutil 2>/dev/null || which dsymutil-15 2>/dev/null)
|
||||
WEBKIT_DIR ?= $(realpath src/bun.js/WebKit)
|
||||
WEBKIT_RELEASE_DIR ?= $(WEBKIT_DIR)/WebKitBuild/Release
|
||||
WEBKIT_DEBUG_DIR ?= $(WEBKIT_DIR)/WebKitBuild/Debug
|
||||
WEBKIT_RELEASE_DIR_LTO ?= $(WEBKIT_DIR)/WebKitBuild/ReleaseLTO
|
||||
|
||||
|
||||
NPM_CLIENT ?= $(shell which bun || which npm)
|
||||
ZIG ?= $(shell which zig || echo -e "error: Missing zig. Please make sure zig is in PATH. Or set ZIG=/path/to-zig-executable")
|
||||
NPM_CLIENT ?= $(shell which bun 2>/dev/null || which npm 2>/dev/null)
|
||||
ZIG ?= $(shell which zig 2>/dev/null || echo -e "error: Missing zig. Please make sure zig is in PATH. Or set ZIG=/path/to-zig-executable")
|
||||
|
||||
# We must use the same compiler version for the JavaScriptCore bindings and JavaScriptCore
|
||||
# If we don't do this, strange memory allocation failures occur.
|
||||
# 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-15 || which clang)
|
||||
REAL_CXX = $(shell which clang++-15 || which clang++)
|
||||
REAL_CC = $(shell which clang-15 2>/dev/null || which clang 2>/dev/null)
|
||||
REAL_CXX = $(shell which clang++-15 2>/dev/null || which clang++ 2>/dev/null)
|
||||
|
||||
CC = $(REAL_CC)
|
||||
CXX = $(REAL_CXX)
|
||||
@@ -85,7 +86,7 @@ CCACHE_PATH := $(shell which ccache 2>/dev/null)
|
||||
|
||||
CCACHE_CC_FLAG = CC=$(CCACHE_CC_OR_CC)
|
||||
|
||||
ifeq (,$(findstring,$(shell which ccache),ccache))
|
||||
ifeq (,$(findstring,$(shell which ccache 2>/dev/null),ccache))
|
||||
CMAKE_CXX_COMPILER_LAUNCHER_FLAG := -DCMAKE_CXX_COMPILER_LAUNCHER=$(CCACHE_PATH) -DCMAKE_C_COMPILER_LAUNCHER=$(CCACHE_PATH)
|
||||
CCACHE_CC_OR_CC := "$(CCACHE_PATH) $(REAL_CC)"
|
||||
export CCACHE_COMPILERTYPE = clang
|
||||
@@ -117,7 +118,7 @@ ifeq ($(OS_NAME),darwin)
|
||||
endif
|
||||
|
||||
# macOS sed is different
|
||||
SED = $(shell which gsed || which sed)
|
||||
SED = $(shell which gsed 2>/dev/null || which sed 2>/dev/null)
|
||||
|
||||
BUN_DIR ?= $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
BUN_DEPS_DIR ?= $(shell pwd)/src/deps
|
||||
@@ -146,7 +147,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-15-ranlib || which llvm-ranlib)
|
||||
-DCMAKE_RANLIB=$(which llvm-15-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null)
|
||||
|
||||
|
||||
|
||||
@@ -168,7 +169,7 @@ endif
|
||||
|
||||
ifeq ($(OS_NAME),linux)
|
||||
LIBICONV_PATH =
|
||||
AR = $(shell which llvm-ar-15 || which llvm-ar || which ar)
|
||||
AR = $(shell which llvm-ar-15 2>/dev/null || which llvm-ar 2>/dev/null || which ar 2>/dev/null)
|
||||
endif
|
||||
|
||||
OPTIMIZATION_LEVEL=-O3 $(MARCH_NATIVE)
|
||||
@@ -184,14 +185,13 @@ DEFAULT_USE_BMALLOC := 1
|
||||
USE_BMALLOC ?= DEFAULT_USE_BMALLOC
|
||||
|
||||
# Set via postinstall
|
||||
AUTO_JSX_BASE_DIR ?= $(realpath $(firstword $(wildcard bun-webkit)))
|
||||
|
||||
ifeq (,$(AUTO_JSX_BASE_DIR))
|
||||
AUTO_JSX_BASE_DIR ?= $(HOME)/webkit-build
|
||||
ifeq (,$(realpath $(JSC_BASE_DIR)))
|
||||
JSC_BASE_DIR = $(realpath $(firstword $(wildcard bun-webkit)))
|
||||
ifeq (,$(JSC_BASE_DIR))
|
||||
JSC_BASE_DIR = $(HOME)/webkit-build
|
||||
endif
|
||||
endif
|
||||
|
||||
JSC_BASE_DIR ?= $(AUTO_JSX_BASE_DIR)
|
||||
|
||||
DEFAULT_JSC_LIB :=
|
||||
DEFAULT_JSC_LIB_DEBUG :=
|
||||
|
||||
@@ -266,7 +266,7 @@ STRIP=/usr/bin/strip
|
||||
endif
|
||||
|
||||
ifeq ($(OS_NAME),linux)
|
||||
STRIP=$(shell which llvm-strip || which llvm-strip-15 || which strip || echo "Missing strip")
|
||||
STRIP=$(shell which llvm-strip 2>/dev/null || which llvm-strip-15 2>/dev/null || which strip 2>/dev/null || echo "Missing strip")
|
||||
endif
|
||||
|
||||
|
||||
@@ -518,6 +518,11 @@ bun:
|
||||
npm-install:
|
||||
$(NPM_CLIENT) install --ignore-scripts --production
|
||||
|
||||
npm-install-dev:
|
||||
$(NPM_CLIENT) install
|
||||
cd test && $(NPM_CLIENT) install
|
||||
cd packages/bun-types && $(NPM_CLIENT) install --production
|
||||
|
||||
print-% : ; @echo $* = $($*)
|
||||
get-% : ; @echo $($*)
|
||||
print-version:
|
||||
@@ -540,13 +545,16 @@ tinycc:
|
||||
make -j10 && \
|
||||
cp $(TINYCC_DIR)/*.a $(BUN_DEPS_OUT_DIR)
|
||||
|
||||
PYTHON=$(shell which python 2>/dev/null || which python3 2>/dev/null || which python2 2>/dev/null)
|
||||
|
||||
.PHONY: builtins
|
||||
builtins: ## to generate builtins
|
||||
@if [ -z "$(WEBKIT_DIR)" ] || [ ! -d "$(WEBKIT_DIR)/Source" ]; then echo "WebKit is not cloned. Please run make init-submodules"; exit 1; fi
|
||||
rm -f src/bun.js/bindings/*Builtin*.cpp src/bun.js/bindings/*Builtin*.h src/bun.js/bindings/*Builtin*.cpp
|
||||
rm -rf src/bun.js/builtins/cpp
|
||||
mkdir -p src/bun.js/builtins/cpp
|
||||
$(shell which python || which python2) $(realpath $(WEBKIT_DIR)/Source/JavaScriptCore/Scripts/generate-js-builtins.py) -i $(realpath src)/bun.js/builtins/js -o $(realpath src)/bun.js/builtins/cpp --framework WebCore --force
|
||||
$(shell which python || which python2) $(realpath $(WEBKIT_DIR)/Source/JavaScriptCore/Scripts/generate-js-builtins.py) -i $(realpath src)/bun.js/builtins/js -o $(realpath src)/bun.js/builtins/cpp --framework WebCore --wrappers-only
|
||||
$(PYTHON) $(realpath $(WEBKIT_DIR)/Source/JavaScriptCore/Scripts/generate-js-builtins.py) -i $(realpath src)/bun.js/builtins/js -o $(realpath src)/bun.js/builtins/cpp --framework WebCore --force
|
||||
$(PYTHON) $(realpath $(WEBKIT_DIR)/Source/JavaScriptCore/Scripts/generate-js-builtins.py) -i $(realpath src)/bun.js/builtins/js -o $(realpath src)/bun.js/builtins/cpp --framework WebCore --wrappers-only
|
||||
rm -rf /tmp/1.h src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h.1
|
||||
echo -e '// clang-format off\nnamespace Zig { class GlobalObject; }\n#include "root.h"\n' >> /tmp/1.h
|
||||
cat /tmp/1.h src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h > src/bun.js/builtins/cpp/WebCoreJSBuiltinInternals.h.1
|
||||
@@ -665,7 +673,8 @@ require:
|
||||
@echo "Checking if the required utilities are available..."
|
||||
@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@15"; exit 1; fi
|
||||
@cmake --version >/dev/null 2>&1 || (echo -e "ERROR: cmake is required."; exit 1)
|
||||
@esbuild --version >/dev/null 2>&1 || (echo -e "ERROR: esbuild 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)
|
||||
@$(NPM_CLIENT) --version >/dev/null 2>&1 || (echo -e "ERROR: NPM client (bun or npm) is required."; exit 1)
|
||||
@go version >/dev/null 2>&1 || (echo -e "ERROR: go is required."; exit 1)
|
||||
@which aclocal > /dev/null || (echo -e "ERROR: automake is required. Install with:\n\n $(POSIX_PKG_MANAGER) install automake"; exit 1)
|
||||
@@ -674,7 +683,7 @@ require:
|
||||
@echo "You have the dependencies installed! Woo"
|
||||
|
||||
init-submodules:
|
||||
git submodule update --init --recursive --progress --depth=1
|
||||
git submodule update --init --recursive --progress --depth=1 --checkout
|
||||
|
||||
.PHONY: build-obj
|
||||
build-obj:
|
||||
@@ -720,10 +729,10 @@ wasm: api build-obj-wasm-small
|
||||
@cp src/api/schema.d.ts packages/bun-wasm/schema.d.ts
|
||||
@cp src/api/schema.js packages/bun-wasm/schema.js
|
||||
@cd packages/bun-wasm && $(NPM_CLIENT) run tsc -- -p .
|
||||
@esbuild --sourcemap=external --external:fs --define:process.env.NODE_ENV='"production"' --outdir=packages/bun-wasm --target=esnext --bundle packages/bun-wasm/index.ts --format=esm --minify 2> /dev/null
|
||||
@$(ESBUILD) --sourcemap=external --external:fs --define:process.env.NODE_ENV='"production"' --outdir=packages/bun-wasm --target=esnext --bundle packages/bun-wasm/index.ts --format=esm --minify 2> /dev/null
|
||||
@mv packages/bun-wasm/index.js packages/bun-wasm/index.mjs
|
||||
@mv packages/bun-wasm/index.js.map packages/bun-wasm/index.mjs.map
|
||||
@esbuild --sourcemap=external --external:fs --define:process.env.NODE_ENV='"production"' --outdir=packages/bun-wasm --target=esnext --bundle packages/bun-wasm/index.ts --format=cjs --minify --platform=node 2> /dev/null
|
||||
@$(ESBUILD) --sourcemap=external --external:fs --define:process.env.NODE_ENV='"production"' --outdir=packages/bun-wasm --target=esnext --bundle packages/bun-wasm/index.ts --format=cjs --minify --platform=node 2> /dev/null
|
||||
@mv packages/bun-wasm/index.js packages/bun-wasm/index.cjs
|
||||
@mv packages/bun-wasm/index.js.map packages/bun-wasm/index.cjs.map
|
||||
@rm -rf packages/bun-wasm/*.tsbuildinfo
|
||||
@@ -806,21 +815,21 @@ node-fallbacks:
|
||||
|
||||
.PHONY: fallback_decoder
|
||||
fallback_decoder:
|
||||
@esbuild --target=esnext --bundle src/fallback.ts --format=iife --platform=browser --minify > src/fallback.out.js
|
||||
@$(ESBUILD) --target=esnext --bundle src/fallback.ts --format=iife --platform=browser --minify > src/fallback.out.js
|
||||
|
||||
.PHONY: runtime_js
|
||||
runtime_js:
|
||||
@NODE_ENV=production esbuild --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.out.js; cat src/runtime.footer.js >> src/runtime.out.js
|
||||
@NODE_ENV=production esbuild --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index-with-refresh.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.out.refresh.js; cat src/runtime.footer.with-refresh.js >> src/runtime.out.refresh.js
|
||||
@NODE_ENV=production esbuild --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.node.pre.out.js; cat src/runtime.node.pre.out.js src/runtime.footer.node.js > src/runtime.node.out.js
|
||||
@NODE_ENV=production esbuild --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.bun.pre.out.js; cat src/runtime.bun.pre.out.js src/runtime.footer.bun.js > src/runtime.bun.out.js
|
||||
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.out.js; cat src/runtime.footer.js >> src/runtime.out.js
|
||||
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index-with-refresh.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.out.refresh.js; cat src/runtime.footer.with-refresh.js >> src/runtime.out.refresh.js
|
||||
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.node.pre.out.js; cat src/runtime.node.pre.out.js src/runtime.footer.node.js > src/runtime.node.out.js
|
||||
@NODE_ENV=production $(ESBUILD) --define:process.env.NODE_ENV="production" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.bun.pre.out.js; cat src/runtime.bun.pre.out.js src/runtime.footer.bun.js > src/runtime.bun.out.js
|
||||
|
||||
.PHONY: runtime_js_dev
|
||||
runtime_js_dev:
|
||||
@NODE_ENV=development esbuild --define:process.env.NODE_ENV="development" --target=esnext --bundle src/runtime/index.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --external:/bun:* > src/runtime.out.js; cat src/runtime.footer.js >> src/runtime.out.js
|
||||
@NODE_ENV=development esbuild --define:process.env.NODE_ENV="development" --target=esnext --bundle src/runtime/index-with-refresh.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --external:/bun:* > src/runtime.out.refresh.js; cat src/runtime.footer.with-refresh.js >> src/runtime.out.refresh.js
|
||||
@NODE_ENV=development esbuild --define:process.env.NODE_ENV="development" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --external:/bun:* > src/runtime.node.pre.out.js; cat src/runtime.node.pre.out.js src/runtime.footer.node.js > src/runtime.node.out.js
|
||||
@NODE_ENV=development esbuild --define:process.env.NODE_ENV="development" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --external:/bun:* > src/runtime.bun.pre.out.js; cat src/runtime.bun.pre.out.js src/runtime.footer.bun.js > src/runtime.bun.out.js
|
||||
@NODE_ENV=development $(ESBUILD) --define:process.env.NODE_ENV="development" --target=esnext --bundle src/runtime/index.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --external:/bun:* > src/runtime.out.js; cat src/runtime.footer.js >> src/runtime.out.js
|
||||
@NODE_ENV=development $(ESBUILD) --define:process.env.NODE_ENV="development" --target=esnext --bundle src/runtime/index-with-refresh.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --external:/bun:* > src/runtime.out.refresh.js; cat src/runtime.footer.with-refresh.js >> src/runtime.out.refresh.js
|
||||
@NODE_ENV=development $(ESBUILD) --define:process.env.NODE_ENV="development" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --external:/bun:* > src/runtime.node.pre.out.js; cat src/runtime.node.pre.out.js src/runtime.footer.node.js > src/runtime.node.out.js
|
||||
@NODE_ENV=development $(ESBUILD) --define:process.env.NODE_ENV="development" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --external:/bun:* > src/runtime.bun.pre.out.js; cat src/runtime.bun.pre.out.js src/runtime.footer.bun.js > src/runtime.bun.out.js
|
||||
|
||||
.PHONY: bun_error
|
||||
bun_error:
|
||||
@@ -829,7 +838,7 @@ bun_error:
|
||||
.PHONY: generate-install-script
|
||||
generate-install-script:
|
||||
@rm -f $(PACKAGES_REALPATH)/bun/install.js
|
||||
@esbuild --log-level=error --define:BUN_VERSION="\"$(PACKAGE_JSON_VERSION)\"" --define:process.env.NODE_ENV="\"production\"" --platform=node --format=cjs $(PACKAGES_REALPATH)/bun/install.ts > $(PACKAGES_REALPATH)/bun/install.js
|
||||
@$(ESBUILD) --log-level=error --define:BUN_VERSION="\"$(PACKAGE_JSON_VERSION)\"" --define:process.env.NODE_ENV="\"production\"" --platform=node --format=cjs $(PACKAGES_REALPATH)/bun/install.ts > $(PACKAGES_REALPATH)/bun/install.js
|
||||
|
||||
.PHONY: fetch
|
||||
fetch: $(IO_FILES)
|
||||
@@ -911,25 +920,6 @@ jsc-bindings: headers bindings
|
||||
clone-submodules:
|
||||
git -c submodule."src/bun.js/WebKit".update=none submodule update --init --recursive --depth=1 --progress
|
||||
|
||||
.PHONY: devcontainer
|
||||
devcontainer: $(OBJ_DIR) $(DEBUG_OBJ_DIR) clone-submodules mimalloc zlib libarchive boringssl picohttp identifier-cache node-fallbacks npm-install api analytics bun_error fallback_decoder bindings uws lolhtml usockets tinycc c-ares runtime_js_dev sqlite
|
||||
|
||||
.PHONY: devcontainer-build
|
||||
devcontainer-build:
|
||||
DOCKER_BUILDARCH="$(DOCKER_BUILDARCH)" devcontainer build --workspace-folder .
|
||||
|
||||
.PHONY: devcontainer-up
|
||||
devcontainer-up:
|
||||
DOCKER_BUILDARCH="$(DOCKER_BUILDARCH)" devcontainer up --workspace-folder .
|
||||
|
||||
.PHONY: devcontainer-rebuild
|
||||
devcontainer-rebuild:
|
||||
DOCKER_BUILDARCH="$(DOCKER_BUILDARCH)" devcontainer up --workspace-folder . --remove-existing-container
|
||||
|
||||
.PHONY: devcontainer-sh
|
||||
devcontainer-sh:
|
||||
DOCKER_BUILDARCH="$(DOCKER_BUILDARCH)" devcontainer exec --workspace-folder . zsh
|
||||
|
||||
CLANG_FORMAT := $(shell command -v clang-format 2> /dev/null)
|
||||
|
||||
.PHONY: headers
|
||||
@@ -1098,7 +1088,7 @@ dev-obj-linux:
|
||||
dev: mkdir-dev dev-obj bun-link-lld-debug
|
||||
|
||||
mkdir-dev:
|
||||
mkdir -p $(DEBUG_PACKAGE_DIR)/bin
|
||||
mkdir -p $(DEBUG_PACKAGE_DIR)
|
||||
|
||||
test-all:
|
||||
$(RELEASE_BUN) test
|
||||
@@ -1121,10 +1111,10 @@ jsc-copy-headers:
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/JSModuleNamespaceObject.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/JSModuleNamespaceObject.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/jit/JIT.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/JIT.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/bytecode/StructureStubInfo.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/StructureStubInfo.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/bytecode/PolymorphicAccess.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/PolymorphicAccess.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/bytecode/AccessCase.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/AccessCase.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/ObjectPropertyConditionSet.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/bytecode/PolyProtoAccessChain.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/PolyProtoAccessChain.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/bytecode/InlineCacheCompiler.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/InlineCacheCompiler.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/bytecode/PutKind.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/PutKind.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/StructureStubClearingWatchpoint.h
|
||||
cp $(WEBKIT_DIR)/Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBase.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/AdaptiveInferredPropertyValueWatchpointBase.h
|
||||
@@ -1330,8 +1320,9 @@ mimalloc-debug:
|
||||
-DMI_OVERRIDE=OFF \
|
||||
-DCMAKE_C_FLAGS="$(CFLAGS)" \
|
||||
-DCMAKE_CXX_FLAGS="$(CFLAGS)" \
|
||||
-GNinja \
|
||||
. \
|
||||
&& make -j $(CPUS);
|
||||
&& ninja
|
||||
cp $(BUN_DEPS_DIR)/mimalloc/$(_MIMALLOC_DEBUG_FILE) $(BUN_DEPS_OUT_DIR)/$(MIMALLOC_FILE)
|
||||
|
||||
|
||||
@@ -1353,8 +1344,9 @@ mimalloc:
|
||||
-DMI_OVERRIDE=OFF \
|
||||
-DMI_OSX_ZONE=OFF \
|
||||
-DCMAKE_C_FLAGS="$(CFLAGS)" \
|
||||
.\
|
||||
&& make -j $(CPUS);
|
||||
-GNinja \
|
||||
. \
|
||||
&& ninja;
|
||||
cp $(BUN_DEPS_DIR)/mimalloc/$(MIMALLOC_INPUT_PATH) $(BUN_DEPS_OUT_DIR)/$(MIMALLOC_FILE)
|
||||
|
||||
|
||||
@@ -1835,12 +1827,31 @@ copy-to-bun-release-dir-bin:
|
||||
PACKAGE_MAP = --pkg-begin async_io $(BUN_DIR)/src/io/io_darwin.zig --pkg-begin bun $(BUN_DIR)/src/bun_redirect.zig --pkg-end --pkg-end --pkg-begin javascript_core $(BUN_DIR)/src/jsc.zig --pkg-begin bun $(BUN_DIR)/src/bun_redirect.zig --pkg-end --pkg-end --pkg-begin bun $(BUN_DIR)/src/bun_redirect.zig --pkg-end
|
||||
|
||||
|
||||
.PHONY: vendor-without-npm
|
||||
vendor-without-npm: node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp zlib boringssl libarchive lolhtml sqlite usockets uws tinycc c-ares
|
||||
|
||||
.PHONY: vendor-without-check
|
||||
vendor-without-check: npm-install node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp zlib boringssl libarchive lolhtml sqlite usockets uws tinycc c-ares
|
||||
vendor-without-check: npm-install vendor-without-npm
|
||||
|
||||
.PHONY: vendor
|
||||
vendor: require init-submodules vendor-without-check
|
||||
|
||||
.PHONY: vendor-dev
|
||||
vendor-dev: require init-submodules npm-install-dev vendor-without-npm
|
||||
|
||||
.PHONY: bun
|
||||
bun: vendor identifier-cache build-obj bun-link-lld-release bun-codesign-release-local
|
||||
|
||||
.PHONY: regenerate-bindings
|
||||
regenerate-bindings:
|
||||
@make clean-bindings builtins
|
||||
@make bindings -j$(CPU_COUNT)
|
||||
|
||||
.PHONY: setup
|
||||
setup: vendor-dev builtins identifier-cache clean-bindings
|
||||
make jsc-check
|
||||
make bindings -j$(CPU_COUNT)
|
||||
@echo ""
|
||||
@echo "Development environment setup complete"
|
||||
@echo "Run \`make dev\` to build \`bun-debug\`"
|
||||
@echo ""
|
||||
|
||||
@@ -40,7 +40,7 @@ bun run index.tsx # TS and JSX supported out of the box
|
||||
bun test # run tests
|
||||
bun run start # run the `start` script in `package.json`
|
||||
bun install <pkg> # install a package
|
||||
bunx cowsay "Hello, world!" # execute a package
|
||||
bunx cowsay 'Hello, world!' # execute a package
|
||||
```
|
||||
|
||||
## Install
|
||||
@@ -130,7 +130,7 @@ bun upgrade --canary
|
||||
|
||||
## Contributing
|
||||
|
||||
Refer to the [Project > Contributing](https://bun.sh/docs/project/developing) guide to start contributing to Bun.
|
||||
Refer to the [Project > Development](https://bun.sh/docs/project/development) guide to start contributing to Bun.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
4
bench/install/.eslintrc.js
Normal file
4
bench/install/.eslintrc.js
Normal file
@@ -0,0 +1,4 @@
|
||||
/** @type {import('eslint').Linter.Config} */
|
||||
module.exports = {
|
||||
extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"],
|
||||
};
|
||||
10
bench/install/.gitignore
vendored
Normal file
10
bench/install/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
node_modules
|
||||
|
||||
/.cache
|
||||
/build
|
||||
/public/build
|
||||
.env
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
pnpm-lock.yaml
|
||||
bun.lockb
|
||||
18
bench/install/README.md
Normal file
18
bench/install/README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# `install` benchmark
|
||||
|
||||
Requires [`hyperfine`](https://github.com/sharkdp/hyperfine)
|
||||
|
||||
```
|
||||
$ hyperfine --prepare 'rm -rf node_modules' --warmup 1 --runs 3 'bun install' 'pnpm install' 'yarn' 'npm install'
|
||||
```
|
||||
|
||||
To check that the app is working as expected:
|
||||
|
||||
```
|
||||
$ bun run dev
|
||||
$ npm run dev
|
||||
$ yarn dev
|
||||
$ pnpm dev
|
||||
```
|
||||
|
||||
Then visit [http://localhost:3000](http://localhost:3000).
|
||||
18
bench/install/app/entry.client.tsx
Normal file
18
bench/install/app/entry.client.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* By default, Remix will handle hydrating your app on the client for you.
|
||||
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
|
||||
* For more information, see https://remix.run/docs/en/main/file-conventions/entry.client
|
||||
*/
|
||||
|
||||
import { RemixBrowser } from "@remix-run/react";
|
||||
import { startTransition, StrictMode } from "react";
|
||||
import { hydrateRoot } from "react-dom/client";
|
||||
|
||||
startTransition(() => {
|
||||
hydrateRoot(
|
||||
document,
|
||||
<StrictMode>
|
||||
<RemixBrowser />
|
||||
</StrictMode>,
|
||||
);
|
||||
});
|
||||
101
bench/install/app/entry.server.tsx
Normal file
101
bench/install/app/entry.server.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* By default, Remix will handle generating the HTTP Response for you.
|
||||
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
|
||||
* For more information, see https://remix.run/docs/en/main/file-conventions/entry.server
|
||||
*/
|
||||
|
||||
import { PassThrough } from "node:stream";
|
||||
import type { EntryContext } from "@remix-run/node";
|
||||
import { Response } from "@remix-run/node";
|
||||
import { RemixServer } from "@remix-run/react";
|
||||
import isbot from "isbot";
|
||||
import { renderToPipeableStream } from "react-dom/server";
|
||||
|
||||
const ABORT_DELAY = 5_000;
|
||||
|
||||
export default function handleRequest(
|
||||
request: Request,
|
||||
responseStatusCode: number,
|
||||
responseHeaders: Headers,
|
||||
remixContext: EntryContext,
|
||||
) {
|
||||
return isbot(request.headers.get("user-agent"))
|
||||
? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext)
|
||||
: handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext);
|
||||
}
|
||||
|
||||
function handleBotRequest(
|
||||
request: Request,
|
||||
responseStatusCode: number,
|
||||
responseHeaders: Headers,
|
||||
remixContext: EntryContext,
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { pipe, abort } = renderToPipeableStream(
|
||||
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />,
|
||||
{
|
||||
onAllReady() {
|
||||
const body = new PassThrough();
|
||||
|
||||
responseHeaders.set("Content-Type", "text/html");
|
||||
|
||||
resolve(
|
||||
new Response(body, {
|
||||
headers: responseHeaders,
|
||||
status: responseStatusCode,
|
||||
}),
|
||||
);
|
||||
|
||||
pipe(body);
|
||||
},
|
||||
onShellError(error: unknown) {
|
||||
reject(error);
|
||||
},
|
||||
onError(error: unknown) {
|
||||
responseStatusCode = 500;
|
||||
console.error(error);
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
setTimeout(abort, ABORT_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
function handleBrowserRequest(
|
||||
request: Request,
|
||||
responseStatusCode: number,
|
||||
responseHeaders: Headers,
|
||||
remixContext: EntryContext,
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { pipe, abort } = renderToPipeableStream(
|
||||
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />,
|
||||
{
|
||||
onShellReady() {
|
||||
const body = new PassThrough();
|
||||
|
||||
responseHeaders.set("Content-Type", "text/html");
|
||||
|
||||
resolve(
|
||||
new Response(body, {
|
||||
headers: responseHeaders,
|
||||
status: responseStatusCode,
|
||||
}),
|
||||
);
|
||||
|
||||
pipe(body);
|
||||
},
|
||||
onShellError(error: unknown) {
|
||||
reject(error);
|
||||
},
|
||||
onError(error: unknown) {
|
||||
console.error(error);
|
||||
responseStatusCode = 500;
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
setTimeout(abort, ABORT_DELAY);
|
||||
});
|
||||
}
|
||||
20
bench/install/app/root.tsx
Normal file
20
bench/install/app/root.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react";
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<Meta />
|
||||
<Links />
|
||||
</head>
|
||||
<body>
|
||||
<Outlet />
|
||||
<ScrollRestoration />
|
||||
<Scripts />
|
||||
<LiveReload />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
30
bench/install/app/routes/_index.tsx
Normal file
30
bench/install/app/routes/_index.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import type { V2_MetaFunction } from "@remix-run/node";
|
||||
|
||||
export const meta: V2_MetaFunction = () => {
|
||||
return [{ title: "New Remix App" }];
|
||||
};
|
||||
|
||||
export default function Index() {
|
||||
return (
|
||||
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
|
||||
<h1>Welcome to Remix</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<a target="_blank" href="https://remix.run/tutorials/blog" rel="noreferrer">
|
||||
15m Quickstart Blog Tutorial
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://remix.run/tutorials/jokes" rel="noreferrer">
|
||||
Deep Dive Jokes App Tutorial
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://remix.run/docs" rel="noreferrer">
|
||||
Remix Docs
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
31
bench/install/package.json
Normal file
31
bench/install/package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"private": true,
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"build": "remix build",
|
||||
"dev": "remix dev",
|
||||
"start": "remix-serve build",
|
||||
"typecheck": "tsc",
|
||||
"clean": "rm -rf node_modules",
|
||||
"bench": "hyperfine --prepare 'rm -rf node_modules' --warmup 1 --runs 3 'bun install' 'pnpm install' 'yarn' 'npm install'"
|
||||
},
|
||||
"dependencies": {
|
||||
"@remix-run/node": "^1.15.0",
|
||||
"@remix-run/react": "^1.15.0",
|
||||
"@remix-run/serve": "^1.15.0",
|
||||
"isbot": "^3.6.5",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@remix-run/dev": "^1.15.0",
|
||||
"@remix-run/eslint-config": "^1.15.0",
|
||||
"@types/react": "^18.0.25",
|
||||
"@types/react-dom": "^18.0.8",
|
||||
"eslint": "^8.27.0",
|
||||
"typescript": "^4.8.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
}
|
||||
BIN
bench/install/public/favicon.ico
Normal file
BIN
bench/install/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
14
bench/install/remix.config.js
Normal file
14
bench/install/remix.config.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/** @type {import('@remix-run/dev').AppConfig} */
|
||||
module.exports = {
|
||||
ignoredRouteFiles: ["**/.*"],
|
||||
// appDirectory: "app",
|
||||
// assetsBuildDirectory: "public/build",
|
||||
// serverBuildPath: "build/index.js",
|
||||
// publicPath: "/build/",
|
||||
future: {
|
||||
v2_errorBoundary: true,
|
||||
v2_meta: true,
|
||||
v2_normalizeFormMethod: true,
|
||||
v2_routeConvention: true,
|
||||
},
|
||||
};
|
||||
2
bench/install/remix.env.d.ts
vendored
Normal file
2
bench/install/remix.env.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/// <reference types="@remix-run/dev" />
|
||||
/// <reference types="@remix-run/node" />
|
||||
22
bench/install/tsconfig.json
Normal file
22
bench/install/tsconfig.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"compilerOptions": {
|
||||
"lib": ["DOM", "DOM.Iterable", "ES2019"],
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react-jsx",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"target": "ES2019",
|
||||
"strict": true,
|
||||
"allowJs": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"~/*": ["./app/*"]
|
||||
},
|
||||
|
||||
// Remix takes care of building everything in `remix build`.
|
||||
"noEmit": true
|
||||
}
|
||||
}
|
||||
42
bench/snippets/write-file-huge.mjs
Normal file
42
bench/snippets/write-file-huge.mjs
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Buffer } from "node:buffer";
|
||||
import { writeFile } from "node:fs/promises";
|
||||
import { bench, run } from "mitata";
|
||||
|
||||
var hugeFile = Buffer.alloc(1024 * 1024 * 64);
|
||||
var medFile = Buffer.alloc(1024 * 1024 * 16);
|
||||
var humongousFile = Buffer.alloc(1024 * 1024 * 256);
|
||||
|
||||
bench(
|
||||
`fs.writeFile ${new Intl.NumberFormat("en-US", {
|
||||
style: "unit",
|
||||
unit: "megabyte",
|
||||
unitDisplay: "narrow",
|
||||
}).format(humongousFile.byteLength / 1024 / 1024)}`,
|
||||
async () => {
|
||||
await writeFile("/tmp/bun.bench-out.humongousFile.txt" + ((Math.random() * 65432) | 0).toString(16), humongousFile);
|
||||
},
|
||||
);
|
||||
|
||||
bench(
|
||||
`fs.writeFile ${new Intl.NumberFormat("en-US", {
|
||||
style: "unit",
|
||||
unit: "megabyte",
|
||||
unitDisplay: "narrow",
|
||||
}).format(hugeFile.byteLength / 1024 / 1024)}`,
|
||||
async () => {
|
||||
await writeFile("/tmp/bun.bench-out.huge.txt" + ((Math.random() * 65432) | 0).toString(16), hugeFile);
|
||||
},
|
||||
);
|
||||
|
||||
bench(
|
||||
`fs.writeFile ${new Intl.NumberFormat("en-US", {
|
||||
style: "unit",
|
||||
unit: "megabyte",
|
||||
unitDisplay: "narrow",
|
||||
}).format(medFile.byteLength / 1024 / 1024)}`,
|
||||
async () => {
|
||||
await writeFile("/tmp/bun.bench-out.medium.txt" + ((Math.random() * 65432) | 0).toString(16), medFile);
|
||||
},
|
||||
);
|
||||
|
||||
await run();
|
||||
25
build.zig
25
build.zig
@@ -44,10 +44,6 @@ const color_map = std.ComptimeStringMap([]const u8, .{
|
||||
});
|
||||
|
||||
fn addInternalPackages(b: *Build, step: *CompileStep, _: std.mem.Allocator, _: []const u8, target: anytype) !void {
|
||||
var bun = b.createModule(.{
|
||||
.source_file = FileSource.relative("src/bun_redirect.zig"),
|
||||
});
|
||||
|
||||
var io: *Module = brk: {
|
||||
if (target.isDarwin()) {
|
||||
break :brk b.createModule(.{
|
||||
@@ -65,7 +61,6 @@ fn addInternalPackages(b: *Build, step: *CompileStep, _: std.mem.Allocator, _: [
|
||||
};
|
||||
|
||||
step.addModule("async_io", io);
|
||||
step.addModule("bun", bun);
|
||||
}
|
||||
|
||||
const BunBuildOptions = struct {
|
||||
@@ -218,6 +213,7 @@ pub fn build(b: *Build) !void {
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
var default_build_options: BunBuildOptions = brk: {
|
||||
const is_baseline = arch.isX86() and (target.cpu_model == .baseline or
|
||||
!std.Target.x86.featureSetHas(target.getCpuFeatures(), .avx2));
|
||||
@@ -285,11 +281,12 @@ pub fn build(b: *Build) !void {
|
||||
std.io.getStdErr().writer().print("Output: {s}/{s}\n\n", .{ output_dir, bun_executable_name }) catch unreachable;
|
||||
|
||||
defer obj_step.dependOn(&obj.step);
|
||||
|
||||
obj.emit_bin = .{
|
||||
.emit_to = b.fmt("{s}/{s}.o", .{ output_dir, bun_executable_name }),
|
||||
};
|
||||
var actual_build_options = default_build_options;
|
||||
if (b.option(bool, "generate-sizes", "Generate sizes of things") orelse false) {
|
||||
actual_build_options.sizegen = true;
|
||||
obj.setOutputDir(b.pathFromRoot("misctools/sizegen"));
|
||||
}
|
||||
|
||||
obj.addOptions("build_options", actual_build_options.step(b));
|
||||
@@ -299,7 +296,6 @@ pub fn build(b: *Build) !void {
|
||||
obj.strip = false;
|
||||
obj.bundle_compiler_rt = false;
|
||||
obj.omit_frame_pointer = optimize != .Debug;
|
||||
|
||||
// Disable stack probing on x86 so we don't need to include compiler_rt
|
||||
if (target.getCpuArch().isX86()) obj.disable_stack_probing = true;
|
||||
|
||||
@@ -449,10 +445,12 @@ pub fn build(b: *Build) !void {
|
||||
.root_source_file = FileSource.relative(test_file orelse "src/main.zig"),
|
||||
.target = target,
|
||||
});
|
||||
headers_obj.setFilter(test_filter);
|
||||
headers_obj.filter = test_filter;
|
||||
if (test_bin_) |test_bin| {
|
||||
headers_obj.name = std.fs.path.basename(test_bin);
|
||||
if (std.fs.path.dirname(test_bin)) |dir| headers_obj.setOutputDir(dir);
|
||||
if (std.fs.path.dirname(test_bin)) |dir| headers_obj.emit_bin = .{
|
||||
.emit_to = b.fmt("{s}/{s}", .{ dir, headers_obj.name }),
|
||||
};
|
||||
}
|
||||
|
||||
try configureObjectStep(b, headers_obj, @TypeOf(target), target, obj.main_pkg_path.?);
|
||||
@@ -489,8 +487,6 @@ pub fn build(b: *Build) !void {
|
||||
// headers_step.dependOn(&after.step);
|
||||
// }
|
||||
}
|
||||
if (obj.emit_bin != .no_emit)
|
||||
obj.setOutputDir(output_dir);
|
||||
|
||||
b.default_step.dependOn(obj_step);
|
||||
}
|
||||
@@ -568,9 +564,12 @@ pub fn configureObjectStep(b: *std.build.Builder, obj: *CompileStep, comptime Ta
|
||||
|
||||
obj.strip = false;
|
||||
|
||||
obj.setOutputDir(output_dir);
|
||||
// obj.setBuildMode(optimize);
|
||||
obj.bundle_compiler_rt = false;
|
||||
if (obj.emit_bin == .default)
|
||||
obj.emit_bin = .{
|
||||
.emit_to = b.fmt("{s}/{s}.o", .{ output_dir, obj.name }),
|
||||
};
|
||||
|
||||
if (target.getOsTag() != .freestanding) obj.linkLibC();
|
||||
if (target.getOsTag() != .freestanding) obj.bundle_compiler_rt = false;
|
||||
|
||||
@@ -119,7 +119,7 @@ _bun_completions() {
|
||||
--jsx-runtime)
|
||||
COMPREPLY=( $(compgen -W "automatic classic" -- "${cur_word}") );
|
||||
return;;
|
||||
--platform)
|
||||
--target)
|
||||
COMPREPLY=( $(compgen -W "browser node bun" -- "${cur_word}") );
|
||||
return;;
|
||||
-l|--loader)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
Use the built-in `bun:ffi` module to efficiently call native libraries from JavaScript. It works with languages that support the C ABI (Zig, Rust, C/C++, C#, Nim, Kotlin, etc).
|
||||
|
||||
## Usage (`bun:ffi`)
|
||||
|
||||
To print the version number of `sqlite3`:
|
||||
|
||||
```ts
|
||||
@@ -227,11 +229,7 @@ const lib = linkSymbols({
|
||||
},
|
||||
});
|
||||
|
||||
const [major, minor, patch] = [
|
||||
lib.symbols.getMajor(),
|
||||
lib.symbols.getMinor(),
|
||||
lib.symbols.getPatch(),
|
||||
];
|
||||
const [major, minor, patch] = [lib.symbols.getMajor(), lib.symbols.getMinor(), lib.symbols.getPatch()];
|
||||
```
|
||||
|
||||
## Callbacks
|
||||
@@ -251,13 +249,10 @@ const {
|
||||
},
|
||||
});
|
||||
|
||||
const searchIterator = new JSCallback(
|
||||
(ptr, length) => /hello/.test(new CString(ptr, length)),
|
||||
{
|
||||
returns: "bool",
|
||||
args: ["ptr", "usize"],
|
||||
},
|
||||
);
|
||||
const searchIterator = new JSCallback((ptr, length) => /hello/.test(new CString(ptr, length)), {
|
||||
returns: "bool",
|
||||
args: ["ptr", "usize"],
|
||||
});
|
||||
|
||||
const str = Buffer.from("wwutwutwutwutwutwutwutwutwutwutut\0", "utf8");
|
||||
if (search(ptr(str), searchIterator)) {
|
||||
@@ -278,7 +273,7 @@ When you're done with a JSCallback, you should call `close()` to free the memory
|
||||
**⚡️ Performance tip** — For a slight performance boost, directly pass `JSCallback.prototype.ptr` instead of the `JSCallback` object:
|
||||
|
||||
```ts
|
||||
const onResolve = new JSCallback((arg) => arg === 42, {
|
||||
const onResolve = new JSCallback(arg => arg === 42, {
|
||||
returns: "bool",
|
||||
args: ["i32"],
|
||||
});
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
{% callout %}
|
||||
**Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. Existing Node.js projects may use Bun's [nearly complete](/docs/ecosystem/nodejs#node_fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module.
|
||||
|
||||
<!-- **Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. Existing Node.js projects may use Bun's [nearly complete](/docs/runtime/nodejs-apis#node_fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module. -->
|
||||
|
||||
**Note** — The `Bun.file` and `Bun.write` APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. For operations that are not yet available with `Bun.file`, such as `mkdir`, you can use Bun's [nearly complete](/docs/runtime/nodejs-apis#node_fs) implementation of the [`node:fs`](https://nodejs.org/api/fs.html) module.
|
||||
|
||||
{% /callout %}
|
||||
|
||||
Bun provides a set of optimized APIs for reading and writing files.
|
||||
|
||||
## Reading files
|
||||
## Reading files (`Bun.file()`)
|
||||
|
||||
`Bun.file(path): BunFile`
|
||||
|
||||
@@ -56,7 +60,7 @@ Bun.stdout;
|
||||
Bun.stderr;
|
||||
```
|
||||
|
||||
## Writing files
|
||||
## Writing files (`Bun.write()`)
|
||||
|
||||
`Bun.write(destination, data): Promise<number>`
|
||||
|
||||
@@ -233,7 +237,7 @@ interface Bun {
|
||||
file(path: string | number | URL, options?: { type?: string }): BunFile;
|
||||
|
||||
write(
|
||||
destination: string | number | FileBlob | URL,
|
||||
destination: string | number | BunFile | URL,
|
||||
input: string | Blob | ArrayBuffer | SharedArrayBuffer | TypedArray | Response,
|
||||
): Promise<number>;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ Bun implements the following globals.
|
||||
|
||||
- [`Buffer`](https://nodejs.org/api/buffer.html#class-buffer)
|
||||
- Node.js
|
||||
- See [Node.js > `Buffer`](/docs/ecosystem/nodejs#node_buffer)
|
||||
- See [Node.js > `Buffer`](/docs/runtime/nodejs-apis#node_buffer)
|
||||
|
||||
---
|
||||
|
||||
@@ -172,7 +172,7 @@ Bun implements the following globals.
|
||||
|
||||
- [`global`](https://nodejs.org/api/globals.html#global)
|
||||
- Node.js
|
||||
- See [Node.js > `global`](/docs/ecosystem/nodejs#node_global).
|
||||
- See [Node.js > `global`](/docs/runtime/nodejs-apis#node_global).
|
||||
|
||||
---
|
||||
|
||||
@@ -214,7 +214,7 @@ Bun implements the following globals.
|
||||
|
||||
- [`process`](https://nodejs.org/api/process.html)
|
||||
- Node.js
|
||||
- See [Node.js > `process`](/docs/ecosystem/nodejs#node_process)
|
||||
- See [Node.js > `process`](/docs/runtime/nodejs-apis#node_process)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{% callout %}
|
||||
**Note** — This page documents the `Bun.serve` API. This API is heavily optimized and represents the recommended way to build HTTP servers in Bun. Existing Node.js projects may use Bun's [nearly complete](/docs/ecosystem/nodejs#node_http) implementation of the Node.js [`http`](https://nodejs.org/api/http.html) and [`https`](https://nodejs.org/api/https.html) modules.
|
||||
**Note** — This page documents the `Bun.serve` API. This API is heavily optimized and represents the recommended way to build HTTP servers in Bun. Existing Node.js projects may use Bun's [nearly complete](/docs/runtime/nodejs-apis#node_http) implementation of the Node.js [`http`](https://nodejs.org/api/http.html) and [`https`](https://nodejs.org/api/https.html) modules.
|
||||
{% /callout %}
|
||||
|
||||
## Send a request
|
||||
## Send a request (`fetch()`)
|
||||
|
||||
Bun implements the Web `fetch` API for making HTTP requests. The `fetch` function is available in the global scope.
|
||||
|
||||
@@ -13,7 +13,7 @@ console.log(result.icons[0].src);
|
||||
// => "/logo-square.jpg"
|
||||
```
|
||||
|
||||
## Start a server
|
||||
## Start a server (`Bun.serve()`)
|
||||
|
||||
Start an HTTP server in Bun with `Bun.serve`.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Spawn child processes with `Bun.spawn` or `Bun.spawnSync`.
|
||||
|
||||
## Spawn a process
|
||||
## Spawn a process (`Bun.spawn()`)
|
||||
|
||||
Provide a command as an array of strings. The result of `Bun.spawn()` is a `Bun.Subprocess` object.
|
||||
|
||||
@@ -28,9 +28,7 @@ By default, the input stream of the subprocess is undefined; it can be configure
|
||||
|
||||
```ts
|
||||
const proc = Bun.spawn(["cat"], {
|
||||
stdin: await fetch(
|
||||
"https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js",
|
||||
),
|
||||
stdin: await fetch("https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js"),
|
||||
});
|
||||
|
||||
const text = await new Response(proc.stdout).text();
|
||||
@@ -89,17 +87,17 @@ const proc = Bun.spawn(["cat"], {
|
||||
});
|
||||
|
||||
// enqueue string data
|
||||
proc.stdin!.write("hello");
|
||||
proc.stdin.write("hello");
|
||||
|
||||
// enqueue binary data
|
||||
const enc = new TextEncoder();
|
||||
proc.stdin!.write(enc.encode(" world!"));
|
||||
proc.stdin.write(enc.encode(" world!"));
|
||||
|
||||
// send buffered data
|
||||
proc.stdin!.flush();
|
||||
proc.stdin.flush();
|
||||
|
||||
// close the input stream
|
||||
proc.stdin!.end();
|
||||
proc.stdin.end();
|
||||
```
|
||||
|
||||
## Output streams
|
||||
@@ -183,7 +181,7 @@ const proc = Bun.spawn(["echo", "hello"]);
|
||||
proc.unref();
|
||||
```
|
||||
|
||||
## Blocking API
|
||||
## Blocking API (`Bun.spawnSync()`)
|
||||
|
||||
Bun provides a synchronous equivalent of `Bun.spawn` called `Bun.spawnSync`. This is a blocking API that supports the same inputs and parameters as `Bun.spawn`. It returns a `SyncSubprocess` object, which differs from `Subprocess` in a few ways.
|
||||
|
||||
@@ -194,7 +192,7 @@ Bun provides a synchronous equivalent of `Bun.spawn` called `Bun.spawnSync`. Thi
|
||||
```ts
|
||||
const proc = Bun.spawnSync(["echo", "hello"]);
|
||||
|
||||
console.log(proc.stdout!.toString());
|
||||
console.log(proc.stdout.toString());
|
||||
// => "hello\n"
|
||||
```
|
||||
|
||||
@@ -227,55 +225,58 @@ spawnSync echo hi 1.47 ms/iter (1.14 ms … 2.64 ms) 1.57 ms 2.37 ms
|
||||
|
||||
## Reference
|
||||
|
||||
A simple reference of the Spawn API and types are shown below. The real types have complex generics to strongly type the `Subprocess` streams with the options passed to `Bun.spawn` and `Bun.spawnSync`. For full details, find these types as defined [bun.d.ts](https://github.com/oven-sh/bun/blob/main/packages/bun-types/bun.d.ts).
|
||||
|
||||
```ts
|
||||
interface Bun {
|
||||
spawn(command: string[], options?: SpawnOptions): Subprocess;
|
||||
spawnSync(command: string[], options?: SpawnOptions): SyncSubprocess;
|
||||
spawn(command: string[], options?: SpawnOptions.OptionsObject): Subprocess;
|
||||
spawnSync(command: string[], options?: SpawnOptions.OptionsObject): SyncSubprocess;
|
||||
|
||||
spawn(options: { cmd: string[] } & SpawnOptions.OptionsObject): Subprocess;
|
||||
spawnSync(options: { cmd: string[] } & SpawnOptions.OptionsObject): SyncSubprocess;
|
||||
}
|
||||
|
||||
interface SpawnOptions {
|
||||
cwd?: string;
|
||||
env?: Record<string, string>;
|
||||
stdin?:
|
||||
namespace SpawnOptions {
|
||||
interface OptionsObject {
|
||||
cwd?: string;
|
||||
env?: Record<string, string>;
|
||||
stdin?: SpawnOptions.Readable;
|
||||
stdout?: SpawnOptions.Writable;
|
||||
stderr?: SpawnOptions.Writable;
|
||||
onExit?: (proc: Subprocess, exitCode: number | null, signalCode: string | null, error: Error | null) => void;
|
||||
}
|
||||
|
||||
type Readable =
|
||||
| "pipe"
|
||||
| "inherit"
|
||||
| "ignore"
|
||||
| ReadableStream
|
||||
| null // equivalent to "ignore"
|
||||
| undefined // to use default
|
||||
| BunFile
|
||||
| ArrayBufferView
|
||||
| number;
|
||||
|
||||
type Writable =
|
||||
| "pipe"
|
||||
| "inherit"
|
||||
| "ignore"
|
||||
| null // equivalent to "ignore"
|
||||
| undefined // to use default
|
||||
| BunFile
|
||||
| ArrayBufferView
|
||||
| number
|
||||
| ReadableStream
|
||||
| Blob
|
||||
| Response
|
||||
| Request
|
||||
| number
|
||||
| null;
|
||||
stdout?:
|
||||
| "pipe"
|
||||
| "inherit"
|
||||
| "ignore"
|
||||
| BunFile
|
||||
| TypedArray
|
||||
| DataView
|
||||
| null;
|
||||
stderr?:
|
||||
| "pipe"
|
||||
| "inherit"
|
||||
| "ignore"
|
||||
| BunFile
|
||||
| TypedArray
|
||||
| DataView
|
||||
| null;
|
||||
onExit?: (
|
||||
proc: Subprocess,
|
||||
exitCode: number | null,
|
||||
signalCode: string | null,
|
||||
error: Error | null,
|
||||
) => void;
|
||||
| Request;
|
||||
}
|
||||
|
||||
interface Subprocess {
|
||||
interface Subprocess<Stdin, Stdout, Stderr> {
|
||||
readonly pid: number;
|
||||
readonly stdin?: number | ReadableStream | FileSink;
|
||||
readonly stdout?: number | ReadableStream;
|
||||
readonly stderr?: number | ReadableStream;
|
||||
// the exact stream types here are derived from the generic parameters
|
||||
readonly stdin: number | ReadableStream | FileSink | undefined;
|
||||
readonly stdout: number | ReadableStream | undefined;
|
||||
readonly stderr: number | ReadableStream | undefined;
|
||||
|
||||
readonly exited: Promise<number>;
|
||||
|
||||
@@ -288,13 +289,22 @@ interface Subprocess {
|
||||
kill(code?: number): void;
|
||||
}
|
||||
|
||||
interface SyncSubprocess {
|
||||
interface SyncSubprocess<Stdout, Stderr> {
|
||||
readonly pid: number;
|
||||
readonly success: boolean;
|
||||
readonly stdout: Buffer;
|
||||
readonly stderr: Buffer;
|
||||
// the exact buffer types here are derived from the generic parameters
|
||||
readonly stdout: Buffer | undefined;
|
||||
readonly stderr: Buffer | undefined;
|
||||
}
|
||||
|
||||
type ReadableSubprocess = Subprocess<any, "pipe", "pipe">;
|
||||
type WritableSubprocess = Subprocess<"pipe", any, any>;
|
||||
type PipedSubprocess = Subprocess<"pipe", "pipe", "pipe">;
|
||||
type NullSubprocess = Subprocess<null, null, null>;
|
||||
|
||||
type ReadableSyncSubprocess = SyncSubprocess<"pipe", "pipe">;
|
||||
type NullSyncSubprocess = SyncSubprocess<null, null>;
|
||||
|
||||
type Signal =
|
||||
| "SIGABRT"
|
||||
| "SIGALRM"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Use Bun's native TCP API implement performance sensitive systems like database clients, game servers, or anything that needs to communicate over TCP (instead of HTTP). This is a low-level API intended for library authors and for advanced use cases.
|
||||
Use Bun's native TCP API to implement performance sensitive systems like database clients, game servers, or anything that needs to communicate over TCP (instead of HTTP). This is a low-level API intended for library authors and for advanced use cases.
|
||||
|
||||
## Start a server
|
||||
## Start a server (`Bun.listen()`)
|
||||
|
||||
To start a TCP server with `Bun.listen`:
|
||||
|
||||
@@ -90,7 +90,7 @@ server.stop(true);
|
||||
server.unref();
|
||||
```
|
||||
|
||||
## Create a connection
|
||||
## Create a connection (`Bun.connect()`)
|
||||
|
||||
Use `Bun.connect` to connect to a TCP server. Specify the server to connect to with `hostname` and `port`. TCP clients can define the same set of handlers as `Bun.listen`, plus a couple client-specific handlers.
|
||||
|
||||
@@ -136,7 +136,7 @@ const server = Bun.listen({ /* config */ })
|
||||
|
||||
// reloads handlers for all active server-side sockets
|
||||
server.reload({
|
||||
socket:
|
||||
socket: {
|
||||
data(){
|
||||
// new 'data' handler
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ interface TranspilerOptions {
|
||||
|
||||
// Default platform to target
|
||||
// This affects how import and/or require is used
|
||||
platform?: "browser" | "bun" | "macro" | "node",
|
||||
target?: "browser" | "bun" | "node",
|
||||
|
||||
// Specify a tsconfig.json file as stringified JSON or an object
|
||||
// Use this to set a custom JSX factory, fragment, or import source
|
||||
|
||||
@@ -94,9 +94,7 @@ test("peek", () => {
|
||||
// If we peek a rejected promise, it:
|
||||
// - returns the error
|
||||
// - does not mark the promise as handled
|
||||
const rejected = Promise.reject(
|
||||
new Error("Successfully tested promise rejection"),
|
||||
);
|
||||
const rejected = Promise.reject(new Error("Successfully tested promise rejection"));
|
||||
expect(peek(rejected).message).toBe("Successfully tested promise rejection");
|
||||
});
|
||||
```
|
||||
@@ -128,7 +126,7 @@ const currentFile = import.meta.url;
|
||||
Bun.openInEditor(currentFile);
|
||||
```
|
||||
|
||||
You can override this via the `debug.editor` setting in your [`bunfig.toml`](/docs/project/configuration)
|
||||
You can override this via the `debug.editor` setting in your [`bunfig.toml`](/docs/runtime/configuration)
|
||||
|
||||
```toml-diff#bunfig.toml
|
||||
+ [debug]
|
||||
@@ -142,5 +140,5 @@ Bun.openInEditor(import.meta.url, {
|
||||
editor: "vscode", // or "subl"
|
||||
line: 10,
|
||||
column: 5,
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
Internally Bun's WebSocket implementation is built on [uWebSockets](https://github.com/uNetworking/uWebSockets).
|
||||
{% /callout %}
|
||||
|
||||
## Create a client
|
||||
## Connect to a WebSocket server
|
||||
|
||||
To connect to an external socket server, create an instance of `WebSocket` with the constructor.
|
||||
|
||||
@@ -46,7 +46,7 @@ socket.addEventListener("close", event => {});
|
||||
socket.addEventListener("error", event => {});
|
||||
```
|
||||
|
||||
## Create a server
|
||||
## Create a WebSocket server
|
||||
|
||||
Below is a simple WebSocket server built with `Bun.serve`, in which all incoming requests are [upgraded](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism) to WebSocket connections in the `fetch` handler. The socket handlers are declared in the `websocket` parameter.
|
||||
|
||||
|
||||
75
docs/bundler/intro.md
Normal file
75
docs/bundler/intro.md
Normal file
@@ -0,0 +1,75 @@
|
||||
<!-- This document is a work in progress. It's not currently included in the actual docs. -->
|
||||
|
||||
The goal of this document is to break down why bundling is necessary, how it works, and how the bundler became such a key part of modern JavaScript development. The content is not specific to Bun's bundler, but is rather aimed at anyone looking for a greater understanding of how bundlers work and, by extension, how most modern frameworks are implemented.
|
||||
|
||||
## What is bundling
|
||||
|
||||
With the adoption of ECMAScript modules (ESM), browsers can now resolve `import`/`export` statements in JavaScript files loaded via `<script>` tags.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```html#index.html
|
||||
<html>
|
||||
<head>
|
||||
<script type="module" src="/index.js" ></script>
|
||||
</head>
|
||||
</html>
|
||||
```
|
||||
|
||||
```js#index.js
|
||||
import {sayHello} from "./hello.js";
|
||||
|
||||
sayHello();
|
||||
```
|
||||
|
||||
```js#hello.js
|
||||
export function sayHello() {
|
||||
console.log("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
When a user visits this website, the files are loaded in the following order:
|
||||
|
||||
{% image src="/images/module_loading_unbundled.png" /%}
|
||||
|
||||
{% callout %}
|
||||
**Relative imports** — Relative imports are resolved relative to the URL of the importing file. Because we're importing `./hello.js` from `/index.js`, the browser resolves it to `/hello.js`. If instead we'd imported `./hello.js` from `/src/index.js`, the browser would have resolved it to `/src/hello.js`.
|
||||
{% /callout %}
|
||||
|
||||
This approach works, it requires three round-trip HTTP requests before the browser is ready to render the page. On slow internet connections, this may add up to a non-trivial delay.
|
||||
|
||||
This example is extremely simplistic. A modern app may be loading dozens of modules from `node_modules`, each consisting of hundrends of files. Loading each of these files with a separate HTTP request becomes untenable very quickly. While most of these requests will be running in parallel, the number of round-trip requests can still be very high; plus, there are limits on how many simultaneous requests a browser can make.
|
||||
|
||||
{% callout %}
|
||||
Some recent advances like modulepreload and HTTP/3 are intended to solve some of these problems, but at the moment bundling is still the most performant approach.
|
||||
{% /callout %}
|
||||
|
||||
The answer: bundling.
|
||||
|
||||
## Entrypoints
|
||||
|
||||
A bundler accepts an "entrypoint" to your source code (in this case, `/index.js`) and outputs a single file containing all of the code needed to run your app. If does so by parsing your source code, reading the `import`/`export` statements, and building a "module graph" of your app's dependencies.
|
||||
|
||||
{% image src="/images/bundling.png" /%}
|
||||
|
||||
We can now load `/bundle.js` from our `index.html` file and eliminate a round trip request, decreasing load times for our app.
|
||||
|
||||
{% image src="/images/module_loading_bundled.png" /%}
|
||||
|
||||
## Loaders
|
||||
|
||||
Bundlers typically have some set of built-in "loaders".
|
||||
|
||||
## Transpilation
|
||||
|
||||
The JavaScript files above are just that: plain JavaScript. They can be directly executed by any modern browser.
|
||||
|
||||
But modern tooling goes far beyond HTML, JavaScript, and CSS. JSX, TypeScript, and PostCSS/CSS-in-JS are all popular technologies that involve non-standard syntax that must be converted into vanilla JavaScript and CSS before if can be consumed by a browser.
|
||||
|
||||
## Chunking
|
||||
|
||||
## Module resolution
|
||||
|
||||
## Plugins
|
||||
234
docs/bundler/loaders.md
Normal file
234
docs/bundler/loaders.md
Normal file
@@ -0,0 +1,234 @@
|
||||
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`
|
||||
|
||||
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](/docs/bundler/plugins) that extend Bun with custom loaders.
|
||||
|
||||
## Built-in loaders
|
||||
|
||||
### `js`
|
||||
|
||||
**JavaScript**. Default for `.cjs` and `.mjs`.
|
||||
|
||||
Parses the code and applies a set if default transforms, like dead-code elimination, tree shaking, and environment variable inlining. Note that Bun does not attempt to down-convert syntax at the moment.
|
||||
|
||||
### `jsx`
|
||||
|
||||
**JavaScript + JSX.**. Default for `.js` and `.jsx`.
|
||||
|
||||
Same as the `js` loader, but JSX syntax is supported. By default, JSX is downconverted to plain JavaScript; the details of how this is done depends on the `jsx*` compiler options in your `tsconfig.json`. Refer to the TypeScript documentation [on JSX](https://www.typescriptlang.org/docs/handbook/jsx.html) for more information.
|
||||
|
||||
### `ts`
|
||||
|
||||
**TypeScript loader**. Default for `.ts`, `.mts`, and `.cts`.
|
||||
|
||||
Strips out all TypeScript syntax, then behaves identically to the `js` loader. Bun does not perform typechecking.
|
||||
|
||||
### `tsx`
|
||||
|
||||
**TypeScript + JSX loader**. Default for `.tsx`. Transpiles both TypeScript and JSX to vanilla JavaScript.
|
||||
|
||||
### `json`
|
||||
|
||||
**JSON loader**. Default for `.json`.
|
||||
|
||||
JSON files can be directly imported.
|
||||
|
||||
```ts
|
||||
import pkg from "./package.json";
|
||||
pkg.name; // => "my-package"
|
||||
```
|
||||
|
||||
During bundling, the parsed JSON is inlined into the bundle as a JavaScript object.
|
||||
|
||||
```ts
|
||||
var pkg = {
|
||||
name: "my-package",
|
||||
// ... other fields
|
||||
};
|
||||
pkg.name;
|
||||
```
|
||||
|
||||
If a `.json` file is passed as an entrypoint to the bundler, it will be converted to a `.js` module that `export default`s the parsed object.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```json#Input
|
||||
{
|
||||
"name": "John Doe",
|
||||
"age": 35,
|
||||
"email": "johndoe@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
```js#Output
|
||||
export default {
|
||||
name: "John Doe",
|
||||
age: 35,
|
||||
email: "johndoe@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### `toml`
|
||||
|
||||
**TOML loader**. Default for `.toml`.
|
||||
|
||||
TOML files can be directly imported. Bun will parse them with its fast native TOML parser.
|
||||
|
||||
```ts
|
||||
import config from "./bunfig.toml";
|
||||
config.logLevel; // => "debug"
|
||||
```
|
||||
|
||||
During bundling, the parsed TOML is inlined into the bundle as a JavaScript object.
|
||||
|
||||
```ts
|
||||
var config = {
|
||||
logLevel: "debug",
|
||||
// ...other fields
|
||||
};
|
||||
config.logLevel;
|
||||
```
|
||||
|
||||
If a `.toml` file is passed as an entrypoint, it will be converted to a `.js` module that `export default`s the parsed object.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```toml#Input
|
||||
name = "John Doe"
|
||||
age = 35
|
||||
email = "johndoe@example.com"
|
||||
```
|
||||
|
||||
```js#Output
|
||||
export default {
|
||||
name: "John Doe",
|
||||
age: 35,
|
||||
email: "johndoe@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
### `text`
|
||||
|
||||
**Text loader**. Default for `.txt`.
|
||||
|
||||
The contents of the text file are read and inlined into the bundle as a string.
|
||||
Text files can be directly imported. The file is read and returned as a string.
|
||||
|
||||
```ts
|
||||
import contents from "./file.txt";
|
||||
console.log(contents); // => "Hello, world!"
|
||||
```
|
||||
|
||||
When referenced during a build, the contents are into the bundle as a string.
|
||||
|
||||
```ts
|
||||
var contents = `Hello, world!`;
|
||||
console.log(contents);
|
||||
```
|
||||
|
||||
If a `.txt` file is passed as an entrypoint, it will be converted to a `.js` module that `export default`s the file contents.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```txt#Input
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
```js#Output
|
||||
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`.
|
||||
|
||||
In the runtime, native addons can be directly imported.
|
||||
|
||||
```ts
|
||||
import addon from "./addon.node";
|
||||
console.log(addon);
|
||||
```
|
||||
|
||||
In the bundler, `.node` files are handled using the [`file`](#file) loader.
|
||||
|
||||
### `file`
|
||||
|
||||
**File loader**. Default for all unrecognized file types.
|
||||
|
||||
The file loader resolves the import as a _path/URL_ to the imported file. It's commonly used for referencing media or font assets.
|
||||
|
||||
```ts#logo.ts
|
||||
import logo from "./logo.svg";
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
_In the runtime_, Bun checks that the `logo.svg` file exists and converts it to an absolute path to the location of `logo.svg` on disk.
|
||||
|
||||
```bash
|
||||
$ bun run logo.ts
|
||||
/path/to/project/logo.svg
|
||||
```
|
||||
|
||||
_In the bundler_, things are slightly different. The file is copied into `outdir` as-is, and the import is resolved as a relative path pointing to the copied file.
|
||||
|
||||
```ts#Output
|
||||
var logo = "./logo.svg";
|
||||
console.log(logo);
|
||||
```
|
||||
|
||||
If a value is specified for `publicPath`, the import will use value as a prefix to construct an absolute path/URL.
|
||||
|
||||
{% table %}
|
||||
|
||||
- Public path
|
||||
- Resolved import
|
||||
|
||||
---
|
||||
|
||||
- `""` (default)
|
||||
- `/logo.svg`
|
||||
|
||||
---
|
||||
|
||||
- `"/assets"`
|
||||
- `/assets/logo.svg`
|
||||
|
||||
---
|
||||
|
||||
- `"https://cdn.example.com/"`
|
||||
- `https://cdn.example.com/`
|
||||
|
||||
{% /table %}
|
||||
|
||||
{% callout %}
|
||||
The location and file name of the copied file is determined by the value of [`naming.asset`](/docs/cli/build#naming).
|
||||
{% callout %}
|
||||
This loader is copied into the `outdir` as-is. The name of the copied file is determined using the value of `naming.asset`.
|
||||
|
||||
{% details summary="Fixing TypeScript import errors" %}
|
||||
If you're using TypeScript, you may get an error like this:
|
||||
|
||||
```ts
|
||||
// TypeScript error
|
||||
// Cannot find module './logo.svg' or its corresponding type declarations.
|
||||
```
|
||||
@@ -2,30 +2,55 @@
|
||||
**Note** — Introduced in Bun v0.1.11.
|
||||
{% /callout %}
|
||||
|
||||
Bun's runtime can be extended to support additional file types using _plugins_. Plugins can intercept imports and perform custom loading logic: reading files, transpiling code, etc. They can be used to extend Bun's runtime with _loaders_ for additional file types.
|
||||
Bun provides a universal plugin API that can be used to extend both the _runtime_ and _bundler_.
|
||||
|
||||
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.
|
||||
|
||||
## Usage
|
||||
|
||||
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#yamlPlugin.ts
|
||||
import { plugin } from "bun";
|
||||
import type { BunPlugin } from "bun";
|
||||
|
||||
plugin({
|
||||
const myPlugin: BunPlugin = {
|
||||
name: "YAML loader",
|
||||
setup(build) {
|
||||
// implementation
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
This plugin can be passed into the `plugins` array when calling `Bun.build`.
|
||||
|
||||
```ts
|
||||
Bun.build({
|
||||
entrypoints: ["./app.ts"],
|
||||
outdir: "./out",
|
||||
plugins: [myPlugin],
|
||||
});
|
||||
```
|
||||
|
||||
To consume this plugin, add this file to the `preload` option in your [`bunfig.toml`](/docs/project/configuration). Bun automatically loads the files/modules specified in `preload` before running a file.
|
||||
It can also be "registered" with the Bun runtime using the `Bun.plugin()` function. Once registered, the currently executing `bun` process will incorporate the plugin into its module resolution algorithm.
|
||||
|
||||
```ts
|
||||
Bun.plugin(myPlugin);
|
||||
```
|
||||
|
||||
To consume this plugin, add this file to the `preload` option in your [`bunfig.toml`](/docs/runtime/configuration). Bun automatically loads the files/modules specified in `preload` before running a file.
|
||||
|
||||
```toml
|
||||
preload = ["./yamlPlugin.ts"]
|
||||
```
|
||||
|
||||
{% details summary="Usage without preload" %}
|
||||
To preload files during `bun test`:
|
||||
|
||||
```toml
|
||||
[test]
|
||||
preload = ["./loader.ts"]
|
||||
```
|
||||
|
||||
{% details summary="Usage without preload" %}
|
||||
|
||||
Alternatively, you can import this file manually at the top of your project's entrypoint, before any application code is imported.
|
||||
|
||||
@@ -243,15 +268,24 @@ namespace Bun {
|
||||
}
|
||||
|
||||
type PluginBuilder = {
|
||||
onResolve: (
|
||||
args: { filter: RegExp; namespace?: string },
|
||||
callback: (args: { path: string; importer: string }) => {
|
||||
path: string;
|
||||
namespace?: string;
|
||||
} | void,
|
||||
) => void;
|
||||
onLoad: (
|
||||
args: { filter: RegExp; namespace?: string },
|
||||
callback: (args: { path: string }) => {
|
||||
loader?: "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "object";
|
||||
loader?: Loader;
|
||||
contents?: string;
|
||||
exports?: Record<string, any>;
|
||||
},
|
||||
) => void;
|
||||
};
|
||||
|
||||
type Loader = "js" | "jsx" | "ts" | "tsx" | "json" | "toml" | "object";
|
||||
```
|
||||
|
||||
The `onLoad` method optionally accepts a `namespace` in addition to the `filter` regex. This namespace will be be 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`.
|
||||
1002
docs/cli/build.md
Normal file
1002
docs/cli/build.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,8 @@
|
||||
Use `bunx` to auto-install and run packages from `npm`. The `bunx` CLI will be auto-installed when you install `bun`.
|
||||
{% callout %}
|
||||
**Note** — `bunx` is an alias for `bun x`. The `bunx` CLI will be auto-installed when you install `bun`.
|
||||
{% /callout %}
|
||||
|
||||
Use `bunx` to auto-install and run packages from `npm`. It's Bun's equivalent of `npx` or `yarn dlx`.
|
||||
|
||||
```bash
|
||||
$ bunx cowsay "Hello world!"
|
||||
@@ -46,23 +50,20 @@ $ bunx my-cli --foo bar
|
||||
|
||||
## Shebangs
|
||||
|
||||
By default, Bun respects shebangs. If an executable is marked with `#!/usr/bin/env node`, Bun will spin up a `node` process to execute the file. However, in some cases it may be desirable to run executables using [Bun's runtime](/docs/runtime), even if the executable indicates otherwise. To do so, include the `--bun` flag.
|
||||
By default, Bun respects shebangs. If an executable is marked with `#!/usr/bin/env node`, Bun will spin up a `node` process to execute the file. However, in some cases it may be desirable to run executables using Bun's runtime, even if the executable indicates otherwise. To do so, include the `--bun` flag.
|
||||
|
||||
```bash
|
||||
$ bunx --bun my-cli
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
**Note** — The `--bun` flag must occur _before_ the executable name. Flags that appear _after_ the name are passed through to the executable.
|
||||
The `--bun` flag must occur _before_ the executable name. Flags that appear _after_ the name are passed through to the executable.
|
||||
|
||||
```bash
|
||||
$ bunx --bun my-cli # good
|
||||
$ bunx my-cli --bun # bad
|
||||
```
|
||||
|
||||
{% /callout %}
|
||||
|
||||
## Environment variables
|
||||
<!-- ## Environment variables
|
||||
|
||||
Bun automatically loads environment variables from `.env` files before running a file, script, or executable. The following files are checked, in order:
|
||||
|
||||
@@ -70,4 +71,4 @@ Bun automatically loads environment variables from `.env` files before running a
|
||||
2. `NODE_ENV` === `"production"` ? `.env.production` : `.env.development`
|
||||
3. `.env`
|
||||
|
||||
To debug environment variables, run `bun run env` to view a list of resolved environment variables.
|
||||
To debug environment variables, run `bun run env` to view a list of resolved environment variables. -->
|
||||
|
||||
@@ -1,3 +1,29 @@
|
||||
## `bun init`
|
||||
|
||||
Scaffold an empty project with `bun init`. It's an interactive tool.
|
||||
|
||||
```bash
|
||||
$ bun init
|
||||
bun init helps you get started with a minimal project and tries to
|
||||
guess sensible defaults. Press ^C anytime to quit.
|
||||
|
||||
package name (quickstart):
|
||||
entry point (index.ts):
|
||||
|
||||
Done! A package.json file was saved in the current directory.
|
||||
+ index.ts
|
||||
+ .gitignore
|
||||
+ tsconfig.json (for editor auto-complete)
|
||||
+ README.md
|
||||
|
||||
To get started, run:
|
||||
bun run index.ts
|
||||
```
|
||||
|
||||
Press `enter` to accept the default answer for each prompt, or pass the `-y` flag to auto-accept the defaults.
|
||||
|
||||
## `bun create`
|
||||
|
||||
Template a new Bun project with `bun create`.
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
The `bun` CLI contains an `npm`-compatible package manager designed to be a faster replacement for existing package management tools like `npm`, `yarn`, and `pnpm`. It's designed for Node.js compatibility; use it in any Bun or Node.js project.
|
||||
The `bun` CLI contains a Node.js-compatible package manager designed to be a dramatically faster replacement for `npm`, `yarn`, and `pnpm`. It's a standalone tool that will work in pre-existing Node.js projects; if your project has a `package.json`, `bun install` can help you speed up your workflow.
|
||||
|
||||
{% callout %}
|
||||
|
||||
**⚡️ 80x faster** — Switch from `npm install` to `bun install` in any Node.js project to make your installations up to 80x faster.
|
||||
**⚡️ 25x faster** — Switch from `npm install` to `bun install` in any Node.js project to make your installations up to 25x faster.
|
||||
|
||||
{% image src="https://user-images.githubusercontent.com/709451/147004342-571b6123-17a9-49a2-8bfd-dcfc5204047e.png" height="200" /%}
|
||||
|
||||
@@ -23,7 +23,9 @@ sudo apt install --install-recommends linux-generic-hwe-20.04
|
||||
|
||||
{% /details %}
|
||||
|
||||
## Install dependencies
|
||||
## Manage dependencies
|
||||
|
||||
### `bun install`
|
||||
|
||||
To install all dependencies of a project:
|
||||
|
||||
@@ -84,13 +86,12 @@ dryRun = false
|
||||
|
||||
{% /details %}
|
||||
|
||||
## Add and remove packages
|
||||
### `bun add`
|
||||
|
||||
To add or remove a particular package:
|
||||
To add a particular package:
|
||||
|
||||
```bash
|
||||
$ bun add preact
|
||||
$ bun remove preact
|
||||
```
|
||||
|
||||
To specify a version, version range, or tag:
|
||||
@@ -147,222 +148,15 @@ To view a complete list of options for a given command:
|
||||
$ bun add --help
|
||||
```
|
||||
|
||||
## Git dependencies
|
||||
### `bun remove`
|
||||
|
||||
To add a dependency from a git repository:
|
||||
To remove a dependency:
|
||||
|
||||
```bash
|
||||
$ bun install git@github.com:moment/moment.git
|
||||
$ bun remove preact
|
||||
```
|
||||
|
||||
Bun supports a variety of protocols, including [`github`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#github-urls), [`git`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#git-urls-as-dependencies), `git+ssh`, `git+https`, and many more.
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"dayjs": "git+https://github.com/iamkun/dayjs.git",
|
||||
"lodash": "git+ssh://github.com/lodash/lodash.git#4.17.21",
|
||||
"moment": "git@github.com:moment/moment.git",
|
||||
"zod": "github:colinhacks/zod"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Global cache
|
||||
|
||||
All packages downloaded from the registry are stored in a global cache at `~/.bun/install/cache`. They are stored in subdirectories named like `${name}@${version}`, so multiple versions of a package can be cached.
|
||||
|
||||
{% details summary="Configuring cache behavior" %}
|
||||
|
||||
```toml
|
||||
[install.cache]
|
||||
# the directory to use for the cache
|
||||
dir = "~/.bun/install/cache"
|
||||
|
||||
# when true, don't load from the global cache.
|
||||
# Bun may still write to node_modules/.cache
|
||||
disable = false
|
||||
|
||||
# when true, always resolve the latest versions from the registry
|
||||
disableManifest = false
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
### Minimizing re-downloads
|
||||
|
||||
Bun strives to avoid re-downloading packages mutiple times. When installing a package, if the cache already contains a version in the range specified by `package.json`, Bun will use the cached package instead of downloading it again.
|
||||
|
||||
{% details summary="Installation details" %}
|
||||
If the semver version has pre-release suffix (`1.0.0-beta.0`) or a build suffix (`1.0.0+20220101`), it is replaced with a hash of that value instead, to reduce the chances of errors associated with long file paths.
|
||||
|
||||
When the `node_modules` folder exists, before installing, Bun checks that `node_modules` contains all expected packages with appropriate versions. If so `bun install` completes. Bun uses a custom JSON parser which stops parsing as soon as it finds `"name"` and `"version"`.
|
||||
|
||||
If a package is missing or has a version incompatible with the `package.json`, Bun checks for a compatible module in the cache. If found, it is installed into `node_modules`. Otherwise, the package will be downloaded from the registry then installed.
|
||||
{% /details %}
|
||||
|
||||
### Fast copying
|
||||
|
||||
Once a package is downloaded into the cache, Bun still needs to copy those files into `node_modules`. Bun uses the fastest syscalls available to perform this task. On Linux, it uses hardlinks; on macOS, it uses `clonefile`.
|
||||
|
||||
### Saving disk space
|
||||
|
||||
Since Bun uses hardlinks to "copy" a module into a project's `node_modules` directory on Linux, the contents of the package only exist in a single location on disk, greatly reducing the amount of disk space dedicated to `node_modules`.
|
||||
|
||||
This benefit does not extend to macOS, which uses `clonefile` for performance reasons.
|
||||
|
||||
{% details summary="Installation strategies" %}
|
||||
This behavior is configurable with the `--backend` flag, which is respected by all of Bun's package management commands.
|
||||
|
||||
- **`hardlink`**: Default on Linux.
|
||||
- **`clonefile`** Default on macOS.
|
||||
- **`clonefile_each_dir`**: Similar to `clonefile`, except it clones each file individually per directory. It is only available on macOS and tends to perform slower than `clonefile`.
|
||||
- **`copyfile`**: The fallback used when any of the above fail. It is the slowest option. On macOS, it uses `fcopyfile()`; on Linux it uses `copy_file_range()`.
|
||||
**`symlink`**: Currently used only `file:` (and eventually `link:`) dependencies. To prevent infinite loops, it skips symlinking the `node_modules` folder.
|
||||
|
||||
If you install with `--backend=symlink`, Node.js won't resolve node_modules of dependencies unless each dependency has its own `node_modules` folder or you pass `--preserve-symlinks` to `node`. See [Node.js documentation on `--preserve-symlinks`](https://nodejs.org/api/cli.html#--preserve-symlinks).
|
||||
|
||||
```bash
|
||||
$ bun install --backend symlink
|
||||
$ node --preserve-symlinks ./foo.js
|
||||
```
|
||||
|
||||
Bun's runtime does not currently expose an equivalent of `--preserve-symlinks`.
|
||||
{% /details %}
|
||||
|
||||
## Lockfile
|
||||
|
||||
Running `bun install` will create a binary lockfile called `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?
|
||||
|
||||
Run `bun install -y` to generate a Yarn-compatible `yarn.lock` (v1) that can be inspected more easily.
|
||||
|
||||
#### Platform-specific dependencies?
|
||||
|
||||
Bun stores normalized `cpu` and `os` values from npm in the lockfile, along with the resolved packages. It skips downloading, extracting, and installing packages disabled for the current target at runtime. This means the lockfile won’t change between platforms/architectures even if the packages ultimately installed do change.
|
||||
|
||||
#### 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.
|
||||
|
||||
#### Can I opt out?
|
||||
|
||||
To install without creating a lockfile:
|
||||
|
||||
```bash
|
||||
$ bun install --no-save
|
||||
```
|
||||
|
||||
To install a Yarn lockfile _in addition_ to `bun.lockb`.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```bash#CLI flag
|
||||
$ bun install --yarn
|
||||
```
|
||||
|
||||
```toml#bunfig.toml
|
||||
[install.lockfile]
|
||||
# whether to save a non-Bun lockfile alongside bun.lockb
|
||||
# only "yarn" is supported
|
||||
print = "yarn"
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
{% details summary="Configuring lockfile" %}
|
||||
|
||||
```toml
|
||||
[install.lockfile]
|
||||
|
||||
# path to read bun.lockb from
|
||||
path = "bun.lockb"
|
||||
|
||||
# path to save bun.lockb to
|
||||
savePath = "bun.lockb"
|
||||
|
||||
# whether to save the lockfile to disk
|
||||
save = true
|
||||
|
||||
# whether to save a non-Bun lockfile alongside bun.lockb
|
||||
# only "yarn" is supported
|
||||
print = "yarn"
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
## Workspaces
|
||||
|
||||
Bun supports [`workspaces`](https://docs.npmjs.com/cli/v9/using-npm/workspaces?v=true#description) in `package.json`. Workspaces make it easy to develop complex software as a _monorepo_ consisting of several independent packages.
|
||||
|
||||
To try it, specify a list of sub-packages in the `workspaces` field of your `package.json`; it's conventional to place these sub-packages in a directory called `packages`.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-project",
|
||||
"version": "1.0.0",
|
||||
"workspaces": ["packages/*"]
|
||||
}
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
**Glob support** — Bun v0.5.8 added support for simple globs for workspace names, with a "*/" at the end. Nothing too fancy.
|
||||
{% /callout %}
|
||||
|
||||
This has a couple major benefits.
|
||||
|
||||
- **Code can be split into logical parts.** If one package relies on another, you can simply add it as a dependency with `bun add`. If package `b` depends on `a`, `bun install` will symlink your local `packages/a` directory into the `node_modules` folder of `b`, instead of trying to download it from the npm registry.
|
||||
- **Dependencies can be de-duplicated.** If `a` and `b` share a common dependency, it will be _hoisted_ to the root `node_modules` directory. This reduces redundant disk usage and minimizes "dependency hell" issues associated with having multiple versions of a package installed simultaneously.
|
||||
|
||||
{% callout %}
|
||||
⚡️ **Speed** — Installs are fast, even for big monorepos. Bun installs the [Remix](https://github.com/remix-run/remix) monorepo in about `500ms` on Linux.
|
||||
|
||||
- 28x faster than `npm install`
|
||||
- 12x faster than `yarn install` (v1)
|
||||
- 8x faster than `pnpm install`
|
||||
|
||||
{% image src="https://user-images.githubusercontent.com/709451/212829600-77df9544-7c9f-4d8d-a984-b2cd0fd2aa52.png" /%}
|
||||
{% /callout %}
|
||||
|
||||
## Registries
|
||||
|
||||
The default registry is `registry.npmjs.org`. This can be globally configured in `bunfig.toml`:
|
||||
|
||||
```toml
|
||||
[install]
|
||||
# set default registry as a string
|
||||
registry = "https://registry.npmjs.org"
|
||||
# set a token
|
||||
registry = { url = "https://registry.npmjs.org", token = "123456" }
|
||||
# set a username/password
|
||||
registry = "https://username:password@registry.npmjs.org"
|
||||
```
|
||||
|
||||
To configure a private registry scoped to a particular organization:
|
||||
|
||||
```toml
|
||||
[install.scopes]
|
||||
# registry as string
|
||||
"@myorg1" = "https://username:password@registry.myorg.com/"
|
||||
|
||||
# registry with username/password
|
||||
# you can reference environment variables
|
||||
"@myorg2" = { username = "myusername", password = "$NPM_PASS", url = "https://registry.myorg.com/" }
|
||||
|
||||
# registry with token
|
||||
"@myorg3" = { token = "$npm_token", url = "https://registry.myorg.com/" }
|
||||
```
|
||||
|
||||
## Linking and unlinking
|
||||
## Local packages (`bun link`)
|
||||
|
||||
Use `bun link` in a local directory to register the current package as a "linkable" package.
|
||||
|
||||
@@ -403,44 +197,56 @@ This will add `cool-pkg` to the `dependencies` field of your app's package.json
|
||||
}
|
||||
```
|
||||
|
||||
## Utilities
|
||||
## Git dependencies
|
||||
|
||||
The `bun pm` command group provides a set of utilities for working with Bun's package manager.
|
||||
|
||||
To print the path to the `bin` directory for the local project:
|
||||
To add a dependency from a git repository:
|
||||
|
||||
```bash
|
||||
$ bun pm bin
|
||||
/path/to/current/project/node_modules/.bin
|
||||
$ bun install git@github.com:moment/moment.git
|
||||
```
|
||||
|
||||
To get the path to the global `bin` directory:
|
||||
Bun supports a variety of protocols, including [`github`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#github-urls), [`git`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#git-urls-as-dependencies), `git+ssh`, `git+https`, and many more.
|
||||
|
||||
```bash
|
||||
$ bun pm bin
|
||||
<$HOME>/.bun/bin
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"dayjs": "git+https://github.com/iamkun/dayjs.git",
|
||||
"lodash": "git+ssh://github.com/lodash/lodash.git#4.17.21",
|
||||
"moment": "git@github.com:moment/moment.git",
|
||||
"zod": "github:colinhacks/zod"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To print a list of packages installed in the current project and their resolved versions, excluding their dependencies. Use the `--all` flag to print the entire tree, including all nth-order dependencies.
|
||||
## Tarball dependencies
|
||||
|
||||
```bash
|
||||
$ bun pm ls
|
||||
/path/to/project node_modules (5)
|
||||
├── eslint@8.33.0
|
||||
├── react@18.2.0
|
||||
├── react-dom@18.2.0
|
||||
├── typescript@4.8.4
|
||||
└── zod@3.20.1
|
||||
A package name can correspond to a publically hosted `.tgz` file. During `bun install`, Bun will download and install the package from the specified tarball URL, rather than from the package registry.
|
||||
|
||||
```json#package.json
|
||||
{
|
||||
"dependencies": {
|
||||
"zod": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To print the path to Bun's global module cache:
|
||||
## CI/CD
|
||||
|
||||
```bash
|
||||
$ bun pm cache
|
||||
```
|
||||
|
||||
To clear Bun's global module cache:
|
||||
|
||||
```bash
|
||||
$ bun pm cache rm
|
||||
Looking to speed up your CI? Use the official `oven-sh/setup-bun` action to install `bun` in a GitHub Actions pipeline.
|
||||
|
||||
```yaml#.github/workflows/release.yml
|
||||
name: bun-types
|
||||
jobs:
|
||||
build:
|
||||
name: build-app
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
- name: Install bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
- name: Build app
|
||||
run: bun run build
|
||||
```
|
||||
|
||||
@@ -1,31 +1,38 @@
|
||||
The `bun` CLI can be used to execute JavaScript/TypeScript files, `package.json` scripts, and [executable packages](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#bin).
|
||||
|
||||
## Running a file
|
||||
<!-- ## Speed -->
|
||||
|
||||
<!--
|
||||
Performance sensitive APIs like `Buffer`, `fetch`, and `Response` are heavily profiled and optimized. Under the hood Bun uses the [JavaScriptCore engine](https://developer.apple.com/documentation/javascriptcore), which is developed by Apple for Safari. It starts and runs faster than V8, the engine used by Node.js and Chromium-based browsers. -->
|
||||
|
||||
## Run a file
|
||||
|
||||
{% callout %}
|
||||
Compare to `node <file>`
|
||||
{% /callout %}
|
||||
|
||||
Bun can execute `.js`, `.jsx`, `.ts`, and `.tsx` files. Every file is transpiled to vanilla JavaScript by Bun's fast native transpiler before being executed. For details on Bun's runtime, refer to the [Bun runtime](/docs/runtime) documentation.
|
||||
|
||||
```ts#foo.ts
|
||||
import { z } from "zod";
|
||||
|
||||
const schema = z.string()
|
||||
const result = schema.parse("Billie Eilish");
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
To run a file in Bun:
|
||||
Use `bun run` to execute a source file.
|
||||
|
||||
```bash
|
||||
$ bun foo.ts
|
||||
Billie Eilish
|
||||
$ bun run index.js
|
||||
```
|
||||
|
||||
If no `node_modules` directory is found in the working directory or above, Bun will abandon Node.js-style module resolution in favor of the `Bun module resolution algorithm`. Under Bun-style module resolution, all packages are _auto-installed_ on the fly into a [global module cache](/docs/cli/install#global-cache). For full details on this algorithm, refer to [Runtime > Modules](/docs/runtime/modules).
|
||||
Bun supports TypeScript and JSX out of the box. Every file is transpiled on the fly by Bun's fast native transpiler before being executed.
|
||||
|
||||
## Running a package script
|
||||
```bash
|
||||
$ bun run index.js
|
||||
$ bun run index.jsx
|
||||
$ bun run index.ts
|
||||
$ bun run index.tsx
|
||||
```
|
||||
|
||||
The "naked" `bun` command is equivalent to `bun run`.
|
||||
|
||||
```bash
|
||||
$ bun index.tsx
|
||||
```
|
||||
|
||||
## Run a `package.json` script
|
||||
|
||||
{% note %}
|
||||
Compare to `npm run <script>` or `yarn <script>`
|
||||
@@ -80,3 +87,23 @@ quickstart scripts:
|
||||
```
|
||||
|
||||
Bun respects lifecycle hooks. For instance, `bun run clean` will execute `preclean` and `postclean`, if defined. If the `pre<script>` fails, Bun will not execute the script itself.
|
||||
|
||||
## Environment variables
|
||||
|
||||
Bun automatically loads environment variables from `.env` files before running a file, script, or executable. The following files are checked, in order:
|
||||
|
||||
1. `.env.local` (first)
|
||||
2. `NODE_ENV` === `"production"` ? `.env.production` : `.env.development`
|
||||
3. `.env`
|
||||
|
||||
To debug environment variables, run `bun run env` to view a list of resolved environment variables.
|
||||
|
||||
## Performance
|
||||
|
||||
Bun is designed to start fast and run fast.
|
||||
|
||||
Under the hood Bun uses the [JavaScriptCore engine](https://developer.apple.com/documentation/javascriptcore), which is developed by Apple for Safari. In most cases, the startup and running performance is faster than V8, the engine used by Node.js and Chromium-based browsers. It's transpiler and runtime are written in Zig, a modern, high-performance language. On Linux, this translates into startup times [4x faster](https://twitter.com/jarredsumner/status/1499225725492076544) than Node.js.
|
||||
|
||||
{% image src="/images/bun-run-speed.jpeg" caption="Bun vs Node.js vs Deno running Hello World" /%}
|
||||
|
||||
<!-- If no `node_modules` directory is found in the working directory or above, Bun will abandon Node.js-style module resolution in favor of the `Bun module resolution algorithm`. Under Bun-style module resolution, all packages are _auto-installed_ on the fly into a [global module cache](/docs/cli/install#global-cache). For full details on this algorithm, refer to [Runtime > Modules](/docs/runtime/modules). -->
|
||||
|
||||
221
docs/cli/test.md
221
docs/cli/test.md
@@ -1,10 +1,12 @@
|
||||
Bun ships with a built-in test runner.
|
||||
|
||||
## Run tests
|
||||
|
||||
```bash
|
||||
$ bun test
|
||||
```
|
||||
|
||||
Tests are written in JavaScript or TypeScript with a Jest-like API.
|
||||
Tests are written in JavaScript or TypeScript with a Jest-like API. Refer to [Writing tests](/docs/test/writing) for full documentation.
|
||||
|
||||
```ts#math.test.ts
|
||||
import { expect, test } from "bun:test";
|
||||
@@ -14,10 +16,6 @@ test("2 + 2", () => {
|
||||
});
|
||||
```
|
||||
|
||||
It's fast.
|
||||
|
||||
{% image src="/images/buntest.jpeg" caption="Bun runs 266 React SSR tests faster than Jest can print its version number." /%}
|
||||
|
||||
The runner recursively searches the working directory for files that match the following patterns:
|
||||
|
||||
- `*.test.{js|jsx|ts|tsx}`
|
||||
@@ -31,6 +29,40 @@ You can filter the set of tests to run by passing additional positional argument
|
||||
$ bun test <filter> <filter> ...
|
||||
```
|
||||
|
||||
## Snapshot testing
|
||||
|
||||
Snapshots are supported by `bun test`. First, write a test using the `.toMatchSnapshot()` matcher:
|
||||
|
||||
```ts
|
||||
import { test, expect } from "bun:test";
|
||||
|
||||
test("snap", () => {
|
||||
expect("foo").toMatchSnapshot();
|
||||
});
|
||||
```
|
||||
|
||||
Then generate snapshots with the following command:
|
||||
|
||||
```bash
|
||||
bun test --update-snapshots
|
||||
```
|
||||
|
||||
Snapshots will be stored in a `__snapshots__` directory next to the test file.
|
||||
|
||||
## Watch mode
|
||||
|
||||
Similar to `bun run`, you can pass the `--watch` flag to `bun test` to watch for changes and re-run tests.
|
||||
|
||||
```bash
|
||||
$ bun test --watch
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
Bun's test runner is fast.
|
||||
|
||||
{% image src="/images/buntest.jpeg" caption="Running 266 React SSR tests faster than Jest can print its version number." /%}
|
||||
|
||||
<!--
|
||||
Consider the following directory structure:
|
||||
|
||||
@@ -57,182 +89,3 @@ $ bun test foo
|
||||
```
|
||||
|
||||
Any test file in the directory with an _absolute path_ that contains one of the targets will run. Glob patterns are not yet supported. -->
|
||||
|
||||
## Writing tests
|
||||
|
||||
Define tests with a Jest-like API imported from the built-in `bun:test` module.
|
||||
|
||||
```ts#math.test.ts
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
test("2 + 2", () => {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
```
|
||||
|
||||
Group tests into suites with `describe`.
|
||||
|
||||
```ts#math.test.ts
|
||||
import { expect, test, describe } from "bun:test";
|
||||
|
||||
describe("arithmetic", () => {
|
||||
test("2 + 2", () => {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
|
||||
test("2 * 2", () => {
|
||||
expect(2 * 2).toBe(4);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Tests can be `async`.
|
||||
|
||||
```ts
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
test("2 * 2", async () => {
|
||||
const result = await Promise.resolve(2 * 2);
|
||||
expect(result).toEqual(4);
|
||||
});
|
||||
```
|
||||
|
||||
Alternatively, use the `done` callback to signal completion. If you include the `done` callback as a parameter in your test definition, you _must_ call it or the test will hang.
|
||||
|
||||
```ts
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
test("2 * 2", done => {
|
||||
Promise.resolve(2 * 2).then(result => {
|
||||
expect(result).toEqual(4);
|
||||
done();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Perform per-test setup and teardown logic with `beforeEach` and `afterEach`.
|
||||
|
||||
```ts
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
beforeEach(() => {
|
||||
console.log("running test.");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
console.log("done with test.");
|
||||
});
|
||||
|
||||
// tests...
|
||||
```
|
||||
|
||||
Perform per-scope setup and teardown logic with `beforeAll` and `afterAll`. At the top-level, the _scope_ is the current file; in a `describe` block, the scope is the block itself.
|
||||
|
||||
```ts
|
||||
import { expect, test, beforeAll, afterAll } from "bun:test";
|
||||
|
||||
let db: Database;
|
||||
beforeAll(() => {
|
||||
// connect to database
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
// close connection
|
||||
});
|
||||
|
||||
// tests...
|
||||
```
|
||||
|
||||
Skip individual tests with `test.skip`.
|
||||
|
||||
```ts
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
test.skip("wat", () => {
|
||||
// TODO: fix this
|
||||
expect(0.1 + 0.2).toEqual(0.3);
|
||||
});
|
||||
```
|
||||
|
||||
## Expect matchers
|
||||
|
||||
Bun implements the following matchers. Full Jest compatibility is on the roadmap; track progress [here](https://github.com/oven-sh/bun/issues/1825).
|
||||
|
||||
- [x] [`.not`](https://jestjs.io/docs/expect#not)
|
||||
- [x] [`.toBe()`](https://jestjs.io/docs/expect#tobevalue)
|
||||
- [x] [`.toEqual()`](https://jestjs.io/docs/expect#toequalvalue)
|
||||
- [x] [`.toBeNull()`](https://jestjs.io/docs/expect#tobenull)
|
||||
- [x] [`.toBeUndefined()`](https://jestjs.io/docs/expect#tobeundefined)
|
||||
- [x] [`.toBeNaN()`](https://jestjs.io/docs/expect#tobenan)
|
||||
- [x] [`.toBeDefined()`](https://jestjs.io/docs/expect#tobedefined)
|
||||
- [x] [`.toBeFalsy()`](https://jestjs.io/docs/expect#tobefalsy)
|
||||
- [x] [`.toBeTruthy()`](https://jestjs.io/docs/expect#tobetruthy)
|
||||
- [x] [`.toContain()`](https://jestjs.io/docs/expect#tocontainitem)
|
||||
- [x] [`.toStrictEqual()`](https://jestjs.io/docs/expect#tostrictequalvalue)
|
||||
- [x] [`.toThrow()`](https://jestjs.io/docs/expect#tothrowerror)
|
||||
- [x] [`.toHaveLength()`](https://jestjs.io/docs/expect#tohavelengthnumber)
|
||||
- [x] [`.toHaveProperty()`](https://jestjs.io/docs/expect#tohavepropertykeypath-value)
|
||||
- [ ] [`.extend`](https://jestjs.io/docs/expect#expectextendmatchers)
|
||||
- [ ] [`.anything()`](https://jestjs.io/docs/expect#expectanything)
|
||||
- [ ] [`.any()`](https://jestjs.io/docs/expect#expectanyconstructor)
|
||||
- [ ] [`.arrayContaining()`](https://jestjs.io/docs/expect#expectarraycontainingarray)
|
||||
- [ ] [`.assertions()`](https://jestjs.io/docs/expect#expectassertionsnumber)
|
||||
- [ ] [`.closeTo()`](https://jestjs.io/docs/expect#expectclosetonumber-numdigits)
|
||||
- [ ] [`.hasAssertions()`](https://jestjs.io/docs/expect#expecthasassertions)
|
||||
- [ ] [`.objectContaining()`](https://jestjs.io/docs/expect#expectobjectcontainingobject)
|
||||
- [ ] [`.stringContaining()`](https://jestjs.io/docs/expect#expectstringcontainingstring)
|
||||
- [ ] [`.stringMatching()`](https://jestjs.io/docs/expect#expectstringmatchingstring--regexp)
|
||||
- [ ] [`.addSnapshotSerializer()`](https://jestjs.io/docs/expect#expectaddsnapshotserializerserializer)
|
||||
- [ ] [`.resolves()`](https://jestjs.io/docs/expect#resolves)
|
||||
- [ ] [`.rejects()`](https://jestjs.io/docs/expect#rejects)
|
||||
- [ ] [`.toHaveBeenCalled()`](https://jestjs.io/docs/expect#tohavebeencalled)
|
||||
- [ ] [`.toHaveBeenCalledTimes()`](https://jestjs.io/docs/expect#tohavebeencalledtimesnumber)
|
||||
- [ ] [`.toHaveBeenCalledWith()`](https://jestjs.io/docs/expect#tohavebeencalledwitharg1-arg2-)
|
||||
- [ ] [`.toHaveBeenLastCalledWith()`](https://jestjs.io/docs/expect#tohavebeenlastcalledwitharg1-arg2-)
|
||||
- [ ] [`.toHaveBeenNthCalledWith()`](https://jestjs.io/docs/expect#tohavebeennthcalledwithnthcall-arg1-arg2-)
|
||||
- [ ] [`.toHaveReturned()`](https://jestjs.io/docs/expect#tohavereturned)
|
||||
- [ ] [`.toHaveReturnedTimes()`](https://jestjs.io/docs/expect#tohavereturnedtimesnumber)
|
||||
- [ ] [`.toHaveReturnedWith()`](https://jestjs.io/docs/expect#tohavereturnedwithvalue)
|
||||
- [ ] [`.toHaveLastReturnedWith()`](https://jestjs.io/docs/expect#tohavelastreturnedwithvalue)
|
||||
- [ ] [`.toHaveNthReturnedWith()`](https://jestjs.io/docs/expect#tohaventhreturnedwithnthcall-value)
|
||||
- [ ] [`.toBeCloseTo()`](https://jestjs.io/docs/expect#tobeclosetonumber-numdigits)
|
||||
- [x] [`.toBeGreaterThan()`](https://jestjs.io/docs/expect#tobegreaterthannumber--bigint)
|
||||
- [x] [`.toBeGreaterThanOrEqual()`](https://jestjs.io/docs/expect#tobegreaterthanorequalnumber--bigint)
|
||||
- [x] [`.toBeLessThan()`](https://jestjs.io/docs/expect#tobelessthannumber--bigint)
|
||||
- [x] [`.toBeLessThanOrEqual()`](https://jestjs.io/docs/expect#tobelessthanorequalnumber--bigint)
|
||||
- [x] [`.toBeInstanceOf()`](https://jestjs.io/docs/expect#tobeinstanceofclass) (Bun v0.5.8+)
|
||||
- [ ] [`.toContainEqual()`](https://jestjs.io/docs/expect#tocontainequalitem)
|
||||
- [ ] [`.toMatch()`](https://jestjs.io/docs/expect#tomatchregexp--string)
|
||||
- [ ] [`.toMatchObject()`](https://jestjs.io/docs/expect#tomatchobjectobject)
|
||||
- [x] [`.toMatchSnapshot()`](https://jestjs.io/docs/expect#tomatchsnapshotpropertymatchers-hint) (Bun v0.5.8+)
|
||||
- [ ] [`.toMatchInlineSnapshot()`](https://jestjs.io/docs/expect#tomatchinlinesnapshotpropertymatchers-inlinesnapshot)
|
||||
- [ ] [`.toThrowErrorMatchingSnapshot()`](https://jestjs.io/docs/expect#tothrowerrormatchingsnapshothint)
|
||||
- [ ] [`.toThrowErrorMatchingInlineSnapshot()`](https://jestjs.io/docs/expect#tothrowerrormatchinginlinesnapshotinlinesnapshot)
|
||||
|
||||
<!-- ```ts
|
||||
test('matchers', ()=>{
|
||||
|
||||
expect(5).toBe(5);
|
||||
expect("do re mi").toContain("mi");
|
||||
expect("do re mi").toEqual("do re mi");
|
||||
expect({}).toStrictEqual({}); // uses Bun.deepEquals()
|
||||
expect([1,2,3]).toHaveLength(3);
|
||||
expect({ name: "foo" }).toHaveProperty("name");
|
||||
expect({ name: "foo" }).toHaveProperty("name", "foo");
|
||||
expect(5).toBeTruthy();
|
||||
expect(0).toBeFalsy();
|
||||
expect("").toBeDefined();
|
||||
expect(undefined).toBeUndefined();
|
||||
expect(parseInt('tuna')).toBeNaN();
|
||||
expect(null).toBeNull();
|
||||
expect(5).toBeGreaterThan(4);
|
||||
expect(5).toBeGreaterThanOrEqual(5);
|
||||
expect(5).toBeLessThan(6);
|
||||
expect(5).toBeLessThanOrEqual(5);
|
||||
expect(()=>throw new Error()).toThrow();
|
||||
|
||||
// negation
|
||||
expect(5).not.toBe(4)
|
||||
|
||||
})
|
||||
``` -->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Projects that use Express and other major Node.js HTTP libraries should work out of the box.
|
||||
Projects that use Express and other major Node.js HTTP libraries should work out of the box.
|
||||
|
||||
{% callout %}
|
||||
If you run into bugs, [please file an issue](https://bun.sh/issues) *in Bun's repo*, not the library. It is Bun's responsibility to address Node.js compatibility issues.
|
||||
If you run into bugs, [please file an issue](https://bun.sh/issues) _in Bun's repo_, not the library. It is Bun's responsibility to address Node.js compatibility issues.
|
||||
{% /callout %}
|
||||
|
||||
```ts
|
||||
@@ -22,7 +22,7 @@ app.listen(port, () => {
|
||||
Bun implements the [`node:http`](https://nodejs.org/api/http.html) and [`node:https`](https://nodejs.org/api/https.html) modules that these libraries rely on. These modules can also be used directly, though [`Bun.serve`](/docs/api/http) is recommended for most use cases.
|
||||
|
||||
{% callout %}
|
||||
**Note** — Refer to the [Runtime > Node.js APIs](/docs/ecosystem/nodejs#node_http) page for more detailed compatibility information.
|
||||
**Note** — Refer to the [Runtime > Node.js APIs](/docs/runtime/nodejs-apis#node_http) page for more detailed compatibility information.
|
||||
{% /callout %}
|
||||
|
||||
```ts
|
||||
|
||||
@@ -19,23 +19,23 @@ $ bun run react.tsx
|
||||
<Component message="Hello world!" />
|
||||
```
|
||||
|
||||
### Prop punning
|
||||
### Prop punning
|
||||
|
||||
The Bun runtime also supports "prop punning for JSX. This is a shorthand syntax useful for assigning a variable to a prop with the same name.
|
||||
The Bun runtime also supports "prop punning" for JSX. This is a shorthand syntax useful for assigning a variable to a prop with the same name.
|
||||
|
||||
```tsx
|
||||
function Div(props: {className: string;}) {
|
||||
const {className} = props;
|
||||
|
||||
|
||||
// without punning
|
||||
return <div className={className} />;
|
||||
// with punning
|
||||
return <div {className} />;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Server-side rendering
|
||||
|
||||
To server-side render (SSR) React in an [HTTP server](/docs/api/http):
|
||||
|
||||
```tsx#ssr.tsx
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
Bun can directly execute `.ts` and `.tsx` files just like vanilla JavaScript, with no extra configuration. If you import a `.ts` or `.tsx` file (or an `npm` module that exports these files), Bun internally transpiles it into JavaScript then executes the file.
|
||||
|
||||
{% callout %}
|
||||
**Note** — Similar to other build tools, Bun does not typecheck the files. Use [`tsc --noEmit`](https://www.typescriptlang.org/docs/handbook/compiler-options.html) (the official TypeScript CLI) if you're looking to catch static type errors.
|
||||
{% /callout %}
|
||||
|
||||
## Type definitions
|
||||
|
||||
To install TypeScript definitions for Bun's built-in APIs, first install `bun-types`.
|
||||
|
||||
```sh
|
||||
$ bun add -d bun-types # dev dependency
|
||||
```
|
||||
|
||||
Then include `"bun-types"` in the `compilerOptions.types` in your `tsconfig.json`:
|
||||
|
||||
```json-diff
|
||||
{
|
||||
"compilerOptions": {
|
||||
+ "types": ["bun-types"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Compiler options
|
||||
|
||||
Bun's runtime implements [modern ECMAScript features](https://github.com/sudheerj/ECMAScript-features), like bigint literals, nullish coalescing, dynamic imports, `import.meta`, `globalThis`, ES modules, top-level await, and more. To use these features without seeing TypeScript errors in your IDE, your `tsconfig.json` needs to be properly configured.
|
||||
|
||||
These are the recommended `compilerOptions` for a Bun project.
|
||||
|
||||
> The config below sets `moduleResolution` to `bundler` which requires TypeScript option is set to `"bundler"` to support [path mapping](#path-mapping).
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"compilerOptions": {
|
||||
// enable latest features
|
||||
"lib": ["esnext"],
|
||||
"module": "esnext",
|
||||
"target": "esnext",
|
||||
|
||||
// requires typescript 5.x+
|
||||
// use "nodenext" for earlier versions
|
||||
"moduleResolution": "bundler",
|
||||
|
||||
// support JSX, CommonJS
|
||||
"jsx": "react-jsx", // support JSX (value doesn't matter)
|
||||
"allowJs": true, // allow importing `.js` from `.ts`
|
||||
"esModuleInterop": true, // allow default imports for CommonJS modules
|
||||
|
||||
// best practices
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"skipLibCheck": true,
|
||||
|
||||
// add Bun type definitions
|
||||
"types": ["bun-types"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you use `bun init`, an appropriate `tsconfig.json` is automatically generated for you.
|
||||
|
||||
## Path mapping
|
||||
|
||||
When resolving modules, Bun's runtime respects path mappings defined in [`compilerOptions.paths`](https://www.typescriptlang.org/tsconfig#paths) in your `tsconfig.json`. No other runtime does this.
|
||||
|
||||
Given the following `tsconfig.json`...
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"data": ["./data.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
...the import from `"data"` will work as expected.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#index.ts
|
||||
import { foo } from "data";
|
||||
console.log(foo); // => "Hello world!"
|
||||
```
|
||||
|
||||
```ts#data.ts
|
||||
export const foo = "Hello world!"
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
@@ -19,7 +19,7 @@ $ bunx cowsay "Hello, world!" # execute a package
|
||||
**Bun is still under development.** Use it to speed up your development workflows or run simpler production code in resource-constrained environments like serverless functions. We're working on more complete Node.js compatibility and integration with existing frameworks. Join the [Discord](https://bun.sh/discord) and watch the [GitHub repository](https://github.com/oven-sh/bun) to keep tabs on future releases.
|
||||
{% /callout %}
|
||||
|
||||
### Get started
|
||||
Get started with one of the quick links below, or read on to learn more about Bun.
|
||||
|
||||
{% block className="gap-2 grid grid-flow-row grid-cols-1 md:grid-cols-2" %}
|
||||
{% arrowbutton href="/docs/installation" text="Install Bun" /%}
|
||||
@@ -38,7 +38,7 @@ JavaScript (or, more formally, ECMAScript) is just a _specification_ for a progr
|
||||
|
||||
### Browsers
|
||||
|
||||
But most JavaScript programs don't run in a vacuum. They need a way to access to the outside world to perform useful tasks. This is where _runtimes_ come in. They implement additional APIs that are then made available to the JavaScript programs they execute. Notably, browsers ship with JavaScript runtimes that implement a set of Web-specific APIs that are exposed via the global `window` object. Any JavaScript code executed by the browser can use these APIs to implement interactive or dynamic behavior in the context of the current webpage.
|
||||
But most JavaScript programs don't run in a vacuum. They need a way to access the outside world to perform useful tasks. This is where _runtimes_ come in. They implement additional APIs that are then made available to the JavaScript programs they execute. Notably, browsers ship with JavaScript runtimes that implement a set of Web-specific APIs that are exposed via the global `window` object. Any JavaScript code executed by the browser can use these APIs to implement interactive or dynamic behavior in the context of the current webpage.
|
||||
|
||||
<!-- JavaScript runtime that exposes JavaScript engines are designed to run "vanilla" JavaScript programs, but it's often JavaScript _runtimes_ use an engine internally to execute the code and implement additional APIs that are then made available to executed programs.
|
||||
JavaScript was [initially designed](https://en.wikipedia.org/wiki/JavaScript) as a language to run in web browsers to implement interactivity and dynamic behavior in web pages. Browsers are the first JavaScript runtimes. JavaScript programs that are executed in browsers have access to a set of Web-specific global APIs on the `window` object. -->
|
||||
|
||||
59
docs/install/cache.md
Normal file
59
docs/install/cache.md
Normal file
@@ -0,0 +1,59 @@
|
||||
All packages downloaded from the registry are stored in a global cache at `~/.bun/install/cache`. They are stored in subdirectories named like `${name}@${version}`, so multiple versions of a package can be cached.
|
||||
|
||||
{% details summary="Configuring cache behavior" %}
|
||||
|
||||
```toml
|
||||
[install.cache]
|
||||
# the directory to use for the cache
|
||||
dir = "~/.bun/install/cache"
|
||||
|
||||
# when true, don't load from the global cache.
|
||||
# Bun may still write to node_modules/.cache
|
||||
disable = false
|
||||
|
||||
# when true, always resolve the latest versions from the registry
|
||||
disableManifest = false
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
## Minimizing re-downloads
|
||||
|
||||
Bun strives to avoid re-downloading packages mutiple times. When installing a package, if the cache already contains a version in the range specified by `package.json`, Bun will use the cached package instead of downloading it again.
|
||||
|
||||
{% details summary="Installation details" %}
|
||||
If the semver version has pre-release suffix (`1.0.0-beta.0`) or a build suffix (`1.0.0+20220101`), it is replaced with a hash of that value instead, to reduce the chances of errors associated with long file paths.
|
||||
|
||||
When the `node_modules` folder exists, before installing, Bun checks that `node_modules` contains all expected packages with appropriate versions. If so `bun install` completes. Bun uses a custom JSON parser which stops parsing as soon as it finds `"name"` and `"version"`.
|
||||
|
||||
If a package is missing or has a version incompatible with the `package.json`, Bun checks for a compatible module in the cache. If found, it is installed into `node_modules`. Otherwise, the package will be downloaded from the registry then installed.
|
||||
{% /details %}
|
||||
|
||||
## Fast copying
|
||||
|
||||
Once a package is downloaded into the cache, Bun still needs to copy those files into `node_modules`. Bun uses the fastest syscalls available to perform this task. On Linux, it uses hardlinks; on macOS, it uses `clonefile`.
|
||||
|
||||
## Saving disk space
|
||||
|
||||
Since Bun uses hardlinks to "copy" a module into a project's `node_modules` directory on Linux, the contents of the package only exist in a single location on disk, greatly reducing the amount of disk space dedicated to `node_modules`.
|
||||
|
||||
This benefit does not extend to macOS, which uses `clonefile` for performance reasons.
|
||||
|
||||
{% details summary="Installation strategies" %}
|
||||
This behavior is configurable with the `--backend` flag, which is respected by all of Bun's package management commands.
|
||||
|
||||
- **`hardlink`**: Default on Linux.
|
||||
- **`clonefile`** Default on macOS.
|
||||
- **`clonefile_each_dir`**: Similar to `clonefile`, except it clones each file individually per directory. It is only available on macOS and tends to perform slower than `clonefile`.
|
||||
- **`copyfile`**: The fallback used when any of the above fail. It is the slowest option. On macOS, it uses `fcopyfile()`; on Linux it uses `copy_file_range()`.
|
||||
**`symlink`**: Currently used only `file:` (and eventually `link:`) dependencies. To prevent infinite loops, it skips symlinking the `node_modules` folder.
|
||||
|
||||
If you install with `--backend=symlink`, Node.js won't resolve node_modules of dependencies unless each dependency has its own `node_modules` folder or you pass `--preserve-symlinks` to `node`. See [Node.js documentation on `--preserve-symlinks`](https://nodejs.org/api/cli.html#--preserve-symlinks).
|
||||
|
||||
```bash
|
||||
$ bun install --backend symlink
|
||||
$ node --preserve-symlinks ./foo.js
|
||||
```
|
||||
|
||||
Bun's runtime does not currently expose an equivalent of `--preserve-symlinks`.
|
||||
{% /details %}
|
||||
190
docs/install/index.md
Normal file
190
docs/install/index.md
Normal file
@@ -0,0 +1,190 @@
|
||||
The `bun` CLI contains an `npm`-compatible package manager designed to be a faster replacement for existing package management tools like `npm`, `yarn`, and `pnpm`. It's designed for Node.js compatibility; use it in any Bun or Node.js project.
|
||||
|
||||
{% callout %}
|
||||
|
||||
**⚡️ 80x faster** — Switch from `npm install` to `bun install` in any Node.js project to make your installations up to 80x faster.
|
||||
|
||||
{% image src="https://user-images.githubusercontent.com/709451/147004342-571b6123-17a9-49a2-8bfd-dcfc5204047e.png" height="200" /%}
|
||||
|
||||
{% /callout %}
|
||||
|
||||
{% details summary="For Linux users" %}
|
||||
The minimum Linux Kernel version is 5.1. If you're on Linux kernel 5.1 - 5.5, `bun install` should still work, but HTTP requests will be slow due to a lack of support for io_uring's `connect()` operation.
|
||||
|
||||
If you're using Ubuntu 20.04, here's how to install a [newer kernel](https://wiki.ubuntu.com/Kernel/LTSEnablementStack):
|
||||
|
||||
```bash
|
||||
# If this returns a version >= 5.6, you don't need to do anything
|
||||
uname -r
|
||||
|
||||
# Install the official Ubuntu hardware enablement kernel
|
||||
sudo apt install --install-recommends linux-generic-hwe-20.04
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
## Manage dependencies
|
||||
|
||||
### `bun install`
|
||||
|
||||
To install all dependencies of a project:
|
||||
|
||||
```bash
|
||||
$ bun install
|
||||
```
|
||||
|
||||
On Linux, `bun install` tends to install packages 20-100x faster than `npm install`. On macOS, it's more like 4-80x.
|
||||
|
||||

|
||||
|
||||
Running `bun install` will:
|
||||
|
||||
- **Install** all `dependencies`, `devDependencies`, and `optionalDependencies`. Bun does not install `peerDependencies` by default.
|
||||
- **Run** your project's `{pre|post}install` scripts at the appropriate time. For security reasons Bun _does not execute_ lifecycle scripts of installed dependencies.
|
||||
- **Write** a `bun.lockb` lockfile to the project root.
|
||||
|
||||
To install in production mode (i.e. without `devDependencies`):
|
||||
|
||||
```bash
|
||||
$ bun install --production
|
||||
```
|
||||
|
||||
To perform a dry run (i.e. don't actually install anything):
|
||||
|
||||
```bash
|
||||
$ bun install --dry-run
|
||||
```
|
||||
|
||||
To modify logging verbosity:
|
||||
|
||||
```bash
|
||||
$ bun install --verbose # debug logging
|
||||
$ bun install --silent # no logging
|
||||
```
|
||||
|
||||
{% details summary="Configuring behavior" %}
|
||||
The default behavior of `bun install` can be configured in `bun.toml`:
|
||||
|
||||
```toml
|
||||
[install]
|
||||
|
||||
# whether to install optionalDependencies
|
||||
optional = true
|
||||
|
||||
# whether to install devDependencies
|
||||
dev = true
|
||||
|
||||
# whether to install peerDependencies
|
||||
peer = false
|
||||
|
||||
# equivalent to `--production` flag
|
||||
production = false
|
||||
|
||||
# equivalent to `--dry-run` flag
|
||||
dryRun = false
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
### `bun add`
|
||||
|
||||
To add a particular package:
|
||||
|
||||
```bash
|
||||
$ bun add preact
|
||||
```
|
||||
|
||||
To specify a version, version range, or tag:
|
||||
|
||||
```bash
|
||||
$ bun add zod@3.20.0
|
||||
$ bun add zod@^3.0.0
|
||||
$ bun add zod@latest
|
||||
```
|
||||
|
||||
To add a package as a dev dependency (`"devDependencies"`):
|
||||
|
||||
```bash
|
||||
$ bun add --development @types/react
|
||||
$ bun add -d @types/react
|
||||
```
|
||||
|
||||
To add a package as an optional dependency (`"optionalDependencies"`):
|
||||
|
||||
```bash
|
||||
$ bun add --optional lodash
|
||||
```
|
||||
|
||||
To install a package globally:
|
||||
|
||||
```bash
|
||||
$ bun add --global cowsay # or `bun add -g cowsay`
|
||||
$ cowsay "Bun!"
|
||||
______
|
||||
< Bun! >
|
||||
------
|
||||
\ ^__^
|
||||
\ (oo)\_______
|
||||
(__)\ )\/\
|
||||
||----w |
|
||||
|| ||
|
||||
```
|
||||
|
||||
{% details summary="Configuring global installation behavior" %}
|
||||
|
||||
```toml
|
||||
[install]
|
||||
# where `bun install --global` installs packages
|
||||
globalDir = "~/.bun/install/global"
|
||||
|
||||
# where globally-installed package bins are linked
|
||||
globalBinDir = "~/.bun/bin"
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
To view a complete list of options for a given command:
|
||||
|
||||
```bash
|
||||
$ bun add --help
|
||||
```
|
||||
|
||||
### `bun remove`
|
||||
|
||||
To remove a dependency:
|
||||
|
||||
```bash
|
||||
$ bun remove preact
|
||||
```
|
||||
|
||||
## Git dependencies
|
||||
|
||||
To add a dependency from a git repository:
|
||||
|
||||
```bash
|
||||
$ bun install git@github.com:moment/moment.git
|
||||
```
|
||||
|
||||
Bun supports a variety of protocols, including [`github`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#github-urls), [`git`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#git-urls-as-dependencies), `git+ssh`, `git+https`, and many more.
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"dayjs": "git+https://github.com/iamkun/dayjs.git",
|
||||
"lodash": "git+ssh://github.com/lodash/lodash.git#4.17.21",
|
||||
"moment": "git@github.com:moment/moment.git",
|
||||
"zod": "github:colinhacks/zod"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Tarball dependencies
|
||||
|
||||
A package name can correspond to a publically hosted `.tgz` file. During `bun install`, Bun will download and install the package from the specified tarball URL, rather than from the package registry.
|
||||
|
||||
```json#package.json
|
||||
{
|
||||
"dependencies": {
|
||||
"zod": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz"
|
||||
}
|
||||
}
|
||||
```
|
||||
67
docs/install/lockfile.md
Normal file
67
docs/install/lockfile.md
Normal file
@@ -0,0 +1,67 @@
|
||||
Running `bun install` will create a binary lockfile called `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?
|
||||
|
||||
Run `bun install -y` to generate a Yarn-compatible `yarn.lock` (v1) that can be inspected more easily.
|
||||
|
||||
#### Platform-specific dependencies?
|
||||
|
||||
Bun stores normalized `cpu` and `os` values from npm in the lockfile, along with the resolved packages. It skips downloading, extracting, and installing packages disabled for the current target at runtime. This means the lockfile won’t change between platforms/architectures even if the packages ultimately installed do change.
|
||||
|
||||
#### 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.
|
||||
|
||||
#### Can I opt out?
|
||||
|
||||
To install without creating a lockfile:
|
||||
|
||||
```bash
|
||||
$ bun install --no-save
|
||||
```
|
||||
|
||||
To install a Yarn lockfile _in addition_ to `bun.lockb`.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```bash#CLI flag
|
||||
$ bun install --yarn
|
||||
```
|
||||
|
||||
```toml#bunfig.toml
|
||||
[install.lockfile]
|
||||
# whether to save a non-Bun lockfile alongside bun.lockb
|
||||
# only "yarn" is supported
|
||||
print = "yarn"
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
{% details summary="Configuring lockfile" %}
|
||||
|
||||
```toml
|
||||
[install.lockfile]
|
||||
|
||||
# path to read bun.lockb from
|
||||
path = "bun.lockb"
|
||||
|
||||
# path to save bun.lockb to
|
||||
savePath = "bun.lockb"
|
||||
|
||||
# whether to save the lockfile to disk
|
||||
save = true
|
||||
|
||||
# whether to save a non-Bun lockfile alongside bun.lockb
|
||||
# only "yarn" is supported
|
||||
print = "yarn"
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
26
docs/install/registries.md
Normal file
26
docs/install/registries.md
Normal file
@@ -0,0 +1,26 @@
|
||||
The default registry is `registry.npmjs.org`. This can be globally configured in `bunfig.toml`:
|
||||
|
||||
```toml
|
||||
[install]
|
||||
# set default registry as a string
|
||||
registry = "https://registry.npmjs.org"
|
||||
# set a token
|
||||
registry = { url = "https://registry.npmjs.org", token = "123456" }
|
||||
# set a username/password
|
||||
registry = "https://username:password@registry.npmjs.org"
|
||||
```
|
||||
|
||||
To configure a private registry scoped to a particular organization:
|
||||
|
||||
```toml
|
||||
[install.scopes]
|
||||
# registry as string
|
||||
"@myorg1" = "https://username:password@registry.myorg.com/"
|
||||
|
||||
# registry with username/password
|
||||
# you can reference environment variables
|
||||
"@myorg2" = { username = "myusername", password = "$NPM_PASS", url = "https://registry.myorg.com/" }
|
||||
|
||||
# registry with token
|
||||
"@myorg3" = { token = "$npm_token", url = "https://registry.myorg.com/" }
|
||||
```
|
||||
58
docs/install/utilities.md
Normal file
58
docs/install/utilities.md
Normal file
@@ -0,0 +1,58 @@
|
||||
The `bun pm` command group provides a set of utilities for working with Bun's package manager.
|
||||
|
||||
To print the path to the `bin` directory for the local project:
|
||||
|
||||
```bash
|
||||
$ bun pm bin
|
||||
/path/to/current/project/node_modules/.bin
|
||||
```
|
||||
|
||||
To print the path to the global `bin` directory:
|
||||
|
||||
```bash
|
||||
$ bun pm bin -g
|
||||
<$HOME>/.bun/bin
|
||||
```
|
||||
|
||||
To print a list of installed dependencies in the current project and their resolved versions, excluding their dependencies.
|
||||
|
||||
```bash
|
||||
$ bun pm ls
|
||||
/path/to/project node_modules (135)
|
||||
├── eslint@8.38.0
|
||||
├── react@18.2.0
|
||||
├── react-dom@18.2.0
|
||||
├── typescript@5.0.4
|
||||
└── zod@3.21.4
|
||||
```
|
||||
|
||||
To print all installed dependencies, including nth-order dependencies.
|
||||
|
||||
```bash
|
||||
$ bun pm ls --all
|
||||
/path/to/project node_modules (135)
|
||||
├── @eslint-community/eslint-utils@4.4.0
|
||||
├── @eslint-community/regexpp@4.5.0
|
||||
├── @eslint/eslintrc@2.0.2
|
||||
├── @eslint/js@8.38.0
|
||||
├── @nodelib/fs.scandir@2.1.5
|
||||
├── @nodelib/fs.stat@2.0.5
|
||||
├── @nodelib/fs.walk@1.2.8
|
||||
├── acorn@8.8.2
|
||||
├── acorn-jsx@5.3.2
|
||||
├── ajv@6.12.6
|
||||
├── ansi-regex@5.0.1
|
||||
├── ...
|
||||
```
|
||||
|
||||
To print the path to Bun's global module cache:
|
||||
|
||||
```bash
|
||||
$ bun pm cache
|
||||
```
|
||||
|
||||
To clear Bun's global module cache:
|
||||
|
||||
```bash
|
||||
$ bun pm cache rm
|
||||
```
|
||||
30
docs/install/workspaces.md
Normal file
30
docs/install/workspaces.md
Normal file
@@ -0,0 +1,30 @@
|
||||
Bun supports [`workspaces`](https://docs.npmjs.com/cli/v9/using-npm/workspaces?v=true#description) in `package.json`. Workspaces make it easy to develop complex software as a _monorepo_ consisting of several independent packages.
|
||||
|
||||
To try it, specify a list of sub-packages in the `workspaces` field of your `package.json`; it's conventional to place these sub-packages in a directory called `packages`.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-project",
|
||||
"version": "1.0.0",
|
||||
"workspaces": ["packages/*"]
|
||||
}
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
**Glob support** — Bun v0.5.8 added support for simple `<directory>/*` globs in `"workspaces"`. Full glob syntax (e.g. `**` and `?`) is not yet supported (soon!).
|
||||
{% /callout %}
|
||||
|
||||
This has a couple major benefits.
|
||||
|
||||
- **Code can be split into logical parts.** If one package relies on another, you can simply add it as a dependency with `bun add`. If package `b` depends on `a`, `bun install` will symlink your local `packages/a` directory into the `node_modules` folder of `b`, instead of trying to download it from the npm registry.
|
||||
- **Dependencies can be de-duplicated.** If `a` and `b` share a common dependency, it will be _hoisted_ to the root `node_modules` directory. This reduces redundant disk usage and minimizes "dependency hell" issues associated with having multiple versions of a package installed simultaneously.
|
||||
|
||||
{% callout %}
|
||||
⚡️ **Speed** — Installs are fast, even for big monorepos. Bun installs the [Remix](https://github.com/remix-run/remix) monorepo in about `500ms` on Linux.
|
||||
|
||||
- 28x faster than `npm install`
|
||||
- 12x faster than `yarn install` (v1)
|
||||
- 8x faster than `pnpm install`
|
||||
|
||||
{% image src="https://user-images.githubusercontent.com/709451/212829600-77df9544-7c9f-4d8d-a984-b2cd0fd2aa52.png" /%}
|
||||
{% /callout %}
|
||||
@@ -99,6 +99,14 @@ $ docker run --rm --init --ulimit memlock=-1:-1 oven/bun:edge
|
||||
this is some output
|
||||
``` -->
|
||||
|
||||
## Uninstalling
|
||||
|
||||
Bun's binary and install cache is located in `~/.bun` by default. To uninstall bun, delete this directory and edit your shell config (`.bashrc`, `.zshrc`, or similar) to remove `~/.bun/bin` from the `$PATH` variable.
|
||||
|
||||
```sh
|
||||
$ rm -rf ~/.bun # make sure to remove ~/.bun/bin from $PATH
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
To install TypeScript definitions for Bun's built-in APIs in your project, install `bun-types`.
|
||||
@@ -117,7 +125,7 @@ Then include `"bun-types"` in the `compilerOptions.types` in your `tsconfig.json
|
||||
}
|
||||
```
|
||||
|
||||
Refer to [Ecosystem > TypeScript](/docs/ecosystem/typescript) for a complete guide to TypeScript support in Bun.
|
||||
Refer to [Ecosystem > TypeScript](/docs/runtime/typescript) for a complete guide to TypeScript support in Bun.
|
||||
|
||||
## Completions
|
||||
|
||||
|
||||
182
docs/nav.ts
182
docs/nav.ts
@@ -33,32 +33,35 @@ export default {
|
||||
description: "Install Bun with npm, Homebrew, Docker, or the official install script.",
|
||||
}),
|
||||
page("quickstart", "Quickstart", {
|
||||
description: "Get started with Bun by building and running a simple HTTP server in 5 lines of TypeScript.",
|
||||
description: "Get started with Bun by building and running a simple HTTP server in 6 lines of TypeScript.",
|
||||
}),
|
||||
page("templates", "Templates", {
|
||||
description: "Hit the ground running with one of Bun's official templates, or download a template from GitHub.",
|
||||
}),
|
||||
// page("typescript", "TypeScript"),
|
||||
|
||||
divider("CLI"),
|
||||
page("cli/run", "`bun run`", {
|
||||
description:
|
||||
"Use `bun run` to execute JavaScript/TypeScript files, package.json scripts, and executable packages.",
|
||||
}),
|
||||
page("cli/install", "`bun install`", {
|
||||
description: "A 100x faster npm client with workspaces, git dependencies, and private registry support.",
|
||||
}),
|
||||
page("cli/test", "`bun test`", {
|
||||
description: "Bun's test runner uses Jest-compatible syntax but runs 100x faster.",
|
||||
}),
|
||||
page("cli/create", "`bun create`", {
|
||||
description: "Scaffold a new Bun project from an official template or GitHub repo.",
|
||||
}),
|
||||
page("cli/bunx", "`bunx`", {
|
||||
description:
|
||||
"Use `bunx` to auto-install and run executable packages from npm, or use locally installed command-line tools.",
|
||||
}),
|
||||
page("cli/deploy", "`bun deploy`", {
|
||||
disabled: true,
|
||||
description: "Deploy your Bun app to the cloud (eventually)",
|
||||
}),
|
||||
// divider("CLI"),
|
||||
// page("cli/run", "`bun run`", {
|
||||
// description:
|
||||
// "Use `bun run` to execute JavaScript/TypeScript files, package.json scripts, and executable packages.",
|
||||
// }),
|
||||
// page("cli/install", "`bun install`", {
|
||||
// description: "A 100x faster npm client with workspaces, git dependencies, and private registry support.",
|
||||
// }),
|
||||
// page("cli/test", "`bun test`", {
|
||||
// description: "Bun's test runner uses Jest-compatible syntax but runs 100x faster.",
|
||||
// }),
|
||||
// page("cli/create", "`bun create`", {
|
||||
// description: "Scaffold a new Bun project from an official template or GitHub repo.",
|
||||
// }),
|
||||
// page("cli/bunx", "`bunx`", {
|
||||
// description:
|
||||
// "Use `bunx` to auto-install and run executable packages from npm, or use locally installed command-line tools.",
|
||||
// }),
|
||||
// page("cli/deploy", "`bun deploy`", {
|
||||
// disabled: true,
|
||||
// description: "Deploy your Bun app to the cloud (eventually)",
|
||||
// }),
|
||||
|
||||
// page("bundler", "Bundler"),
|
||||
// page("cli/bun-install", "`bun install`"),
|
||||
@@ -70,37 +73,122 @@ export default {
|
||||
// page("bundev", "Dev server"),
|
||||
// page("benchmarks", "Benchmarks"),
|
||||
|
||||
// divider("Runtime"),
|
||||
divider("Runtime"),
|
||||
page("runtime/index", "Runtime", {
|
||||
description: `Bun is a new JavaScript runtime designed to be a faster, leaner, more modern replacement for Node.js.`,
|
||||
page("cli/run", "`bun run`", {
|
||||
description: "Use `bun run` to execute JavaScript/TypeScript files and package.json scripts.",
|
||||
}),
|
||||
// page("runtime/index", "Overview", {
|
||||
// description: `Bun is a new JavaScript runtime designed to be a faster, leaner, more modern replacement for Node.js.`,
|
||||
// }),
|
||||
// page("runtime/performance", "Performance", {
|
||||
// description: `Bun is a new JavaScript runtime designed to be a faster, leaner, more modern replacement for Node.js.`,
|
||||
// }),
|
||||
page("runtime/loaders", "File types", {
|
||||
description: `Bun's runtime supports JavaScript/TypeScript files, JSX syntax, Wasm, JSON/TOML imports, and more.`,
|
||||
}),
|
||||
page("runtime/typescript", "TypeScript", {
|
||||
description: `Bun can directly execute TypeScript files without additional configuration.`,
|
||||
}),
|
||||
// page("runtime/jsx", "JSX", {
|
||||
// description: `Bun can directly execute TypeScript files without additional configuration.`,
|
||||
// }),
|
||||
// page("runtime/apis", "APIs", {
|
||||
// description: `Bun is a new JavaScript runtime designed to be a faster, leaner, more modern replacement for Node.js.`,
|
||||
// }),
|
||||
page("runtime/bun-apis", "Bun APIs", {
|
||||
description: `Bun provides a set of highly optimized native APIs for performing common tasks.`,
|
||||
}),
|
||||
page("runtime/web-apis", "Web APIs", {
|
||||
description: `Bun implements an array of Web-standard APIs like fetch, URL, and WebSocket.`,
|
||||
}),
|
||||
page("runtime/nodejs-apis", "Node.js compatibility", {
|
||||
description: `Bun aims for full Node.js compatibility. This page tracks the current compatibility status.`,
|
||||
}),
|
||||
|
||||
// page("runtime/nodejs", "Node.js compatibility", {
|
||||
// description: `Track the status of Bun's API compatibility with Node.js.`,
|
||||
// }),
|
||||
// page("runtime/web-apis", "Web APIs"),
|
||||
page("runtime/modules", "Module resolution", {
|
||||
description: `Bun uses ESM and implements an extended version of the Node.js module resolution algorithm.`,
|
||||
}),
|
||||
// page("runtime/loaders", "Loaders"),
|
||||
|
||||
page("runtime/hot", "Watch mode", {
|
||||
description: `Reload your application & tests automatically.`,
|
||||
}),
|
||||
// page("runtime/loaders", "Loaders"),
|
||||
page("runtime/plugins", "Plugins", {
|
||||
description: `Implement custom loaders and module resolution logic with Bun's plugin system.`,
|
||||
page("runtime/modules", "Module resolution", {
|
||||
description: `Bun uses ESM and implements an extended version of the Node.js module resolution algorithm.`,
|
||||
}),
|
||||
page("runtime/autoimport", "Auto-install", {
|
||||
description: `Never use node_modules again. Bun can optionally auto-install your dependencies on the fly.`,
|
||||
}),
|
||||
page("runtime/configuration", "Configuration", {
|
||||
description: `Bun's runtime is configurable with environment variables and the bunfig.toml config file.`,
|
||||
}),
|
||||
page("runtime/framework", "Framework API", {
|
||||
disabled: true,
|
||||
description:
|
||||
"Coming soon. Use the Framework API to build a fast, cloud-ready framework on top of Bun's bundler and runtime.",
|
||||
}),
|
||||
|
||||
divider("Package manager"),
|
||||
page("cli/install", "`bun install`", {
|
||||
description:
|
||||
"Install all dependencies with `bun install`, or manage dependencies with `bun add` and `bun remove`.",
|
||||
}),
|
||||
page("install/workspaces", "Workspaces", {
|
||||
description: "Bun's package manager supports workspaces and mono-repo development workflows.",
|
||||
}),
|
||||
page("install/cache", "Global cache", {
|
||||
description:
|
||||
"Bun's package manager installs all packages into a shared global cache to avoid redundant re-downloads.",
|
||||
}),
|
||||
page("install/lockfile", "Lockfile", {
|
||||
description:
|
||||
"Bun's binary lockfile `bun.lockb` tracks your resolved dependency ytrr, making future installs fast and repeatable.",
|
||||
}),
|
||||
page("install/registries", "Scopes and registries", {
|
||||
description: "How to configure private scopes and custom package registries.",
|
||||
}),
|
||||
page("install/utilities", "Utilities", {
|
||||
description: "Use `bun pm` to introspect your global module cache or project dependency tree.",
|
||||
}),
|
||||
|
||||
divider("Bundler"),
|
||||
page("cli/build", "`Bun.build`", {
|
||||
description: "Bundle code for comsumption in the browser with Bun's native bundler.",
|
||||
}),
|
||||
// page("bundler/intro", "How bundlers work", {
|
||||
// description: "A visual introduction to bundling",
|
||||
// }),
|
||||
page("bundler/loaders", "Loaders", {
|
||||
description: "Bun's built-in loaders for the bundler and runtime",
|
||||
}),
|
||||
page("bundler/plugins", "Plugins", {
|
||||
description: `Implement custom loaders and module resolution logic with Bun's plugin system.`,
|
||||
}),
|
||||
|
||||
divider("Test runner"),
|
||||
page("cli/test", "`bun test`", {
|
||||
description: "Bun's test runner uses Jest-compatible syntax but runs 100x faster.",
|
||||
}),
|
||||
page("test/writing", "Writing tests", {
|
||||
description:
|
||||
"Write your tests using Jest-like expect matchers, plus setup/teardown hooks, snapshot testing, and more",
|
||||
}),
|
||||
|
||||
divider("Package runner"),
|
||||
page("cli/bunx", "`bunx`", {
|
||||
description: "Use `bunx` to auto-install and run executable packages from npm.",
|
||||
}),
|
||||
|
||||
// page("runtime/nodejs", "Node.js APIs"),
|
||||
|
||||
divider("Ecosystem"),
|
||||
page("ecosystem/nodejs", "Node.js", {
|
||||
description: `Track the status of Bun's API compatibility with Node.js.`,
|
||||
}),
|
||||
page("ecosystem/typescript", "TypeScript", {
|
||||
description: `Bun can directly execute TypeScript files without additional configuration.`,
|
||||
}),
|
||||
page("ecosystem/react", "React", {
|
||||
description: `The Bun runtime supports JSX syntax out of the box and optimizes server-side rendering.`,
|
||||
// page("ecosystem/react", "React", {
|
||||
// description: `The Bun runtime supports JSX syntax out of the box and optimizes server-side rendering.`,
|
||||
// }),
|
||||
page("ecosystem/express", "Express", {
|
||||
description: `Servers built with Express and other major Node.js HTTP libraries work out of the box.`,
|
||||
}),
|
||||
page("ecosystem/elysia", "Elysia", {
|
||||
description: `Get started with Elysia, a Bun-native framework designed for the edge.`,
|
||||
@@ -111,9 +199,7 @@ export default {
|
||||
page("ecosystem/buchta", "Buchta", {
|
||||
description: `Buchta is a Bun-native fullstack framework for Svelte and Preact apps.`,
|
||||
}),
|
||||
page("ecosystem/express", "Express", {
|
||||
description: `Servers built with Express and other major Node.js HTTP libraries work out of the box.`,
|
||||
}),
|
||||
|
||||
page("ecosystem/awesome", "Awesome", {
|
||||
href: "https://github.com/apvarun/awesome-bun",
|
||||
description: ``,
|
||||
@@ -162,9 +248,9 @@ export default {
|
||||
page("api/utils", "Utils", {
|
||||
description: `Bun implements a set of utilities that are commonly required by developers.`,
|
||||
}), // "`Bun.peek`"),
|
||||
page("api/dns", "DNS", {
|
||||
description: `Resolve domain names to IP addresses.`,
|
||||
}), // "`bun:dns`"),
|
||||
// page("api/dns", "DNS", {
|
||||
// description: `Resolve domain names to IP addresses.`,
|
||||
// }), // "`bun:dns`"),
|
||||
page("api/node-api", "Node-API", {
|
||||
description: `Bun implements the Node-API spec for building native addons.`,
|
||||
}), // "`Node-API`"),
|
||||
@@ -180,13 +266,11 @@ export default {
|
||||
page("project/roadmap", "Roadmap", {
|
||||
description: `Track Bun's near-term and long-term goals.`,
|
||||
}),
|
||||
page("project/configuration", "Configuration", {
|
||||
description: `Bun's runtime is configurable with environment variables and the bunfig.toml config file.`,
|
||||
}),
|
||||
|
||||
page("project/benchmarking", "Benchmarking", {
|
||||
description: `Bun is designed for performance. Learn how to benchmark Bun yourself.`,
|
||||
}),
|
||||
page("project/developing", "Development", {
|
||||
page("project/development", "Development", {
|
||||
description: "Learn how to contribute to Bun and get your local development environment up and running.",
|
||||
}),
|
||||
page("project/licensing", "License", {
|
||||
|
||||
@@ -12,17 +12,18 @@ To precisely measure time, Bun offers two runtime APIs functions:
|
||||
When writing your own benchmarks, it's important to choose the right tool.
|
||||
|
||||
- For microbenchmarks, a great general-purpose tool is [`mitata`](https://github.com/evanwashere/mitata).
|
||||
- For load testing, you *must use* an HTTP benchmarking tool that is at least as fast as `Bun.serve()`, or your results will be skewed. Some popular Node.js-based benchmarking tools like [`autocannon`](https://github.com/mcollina/autocannon) are not fast enough. We recommend one of the following:
|
||||
- For load testing, you _must use_ an HTTP benchmarking tool that is at least as fast as `Bun.serve()`, or your results will be skewed. Some popular Node.js-based benchmarking tools like [`autocannon`](https://github.com/mcollina/autocannon) are not fast enough. We recommend one of the following:
|
||||
- [`bombardier`](https://github.com/codesenberg/bombardier)
|
||||
- [`oha`](https://github.com/hatoo/oha)
|
||||
- [`http_load_test`](https://github.com/uNetworking/uSockets/blob/master/examples/http_load_test.c)
|
||||
- For benchmarking scripts or CLI commands, we recommend [`hyperfine`](https://github.com/sharkdp/hyperfine). It's an easy way to compare
|
||||
|
||||
- For benchmarking scripts or CLI commands, we recommend [`hyperfine`](https://github.com/sharkdp/hyperfine).
|
||||
|
||||
## Measuring memory usage
|
||||
|
||||
Bun has two heaps. One heap is for the JavaScript runtime and the other heap is for everything else.
|
||||
|
||||
{% anchor id="bunjsc" /%}
|
||||
|
||||
### JavaScript heap stats
|
||||
|
||||
The `bun:jsc` module exposes a few functions for measuring memory usage:
|
||||
@@ -31,7 +32,9 @@ The `bun:jsc` module exposes a few functions for measuring memory usage:
|
||||
import { heapStats } from "bun:jsc";
|
||||
console.log(heapStats());
|
||||
```
|
||||
|
||||
{% details summary="View example statistics" %}
|
||||
|
||||
```ts
|
||||
{
|
||||
heapSize: 1657575,
|
||||
@@ -134,14 +137,15 @@ console.log(heapStats());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% /details %}
|
||||
|
||||
JavaScript is a garbage-collected language, not reference counted. It's normal and correct for objects to not be freed immediately in all cases, though it's not normal for objects to never be freed.
|
||||
|
||||
Tp force garbage collection to run manually:
|
||||
To force garbage collection to run manually:
|
||||
|
||||
```js
|
||||
Bun.gc(true); // synchronous
|
||||
Bun.gc(true); // synchronous
|
||||
Bun.gc(false); // asynchronous
|
||||
```
|
||||
|
||||
@@ -161,15 +165,12 @@ To view the snapshot, open the `heap.json` file in Safari's Developer Tools (or
|
||||
3. Click "JavaScript Allocations" in the menu on the left. It might not be visible until you click the pencil icon to show all the timelines
|
||||
4. Click "Import" and select your heap snapshot JSON
|
||||
|
||||
|
||||
{% image alt="Import heap json" src="https://user-images.githubusercontent.com/709451/204428943-ba999e8f-8984-4f23-97cb-b4e3e280363e.png" caption="Importing a heap snapshot" /%}
|
||||
|
||||
Once imported, you should see something like this:
|
||||
|
||||
|
||||
{% image alt="Viewing heap snapshot in Safari" src="https://user-images.githubusercontent.com/709451/204429337-b0d8935f-3509-4071-b991-217794d1fb27.png" caption="Viewing heap snapshot in Safari Dev Tools" /%}
|
||||
|
||||
|
||||
### Native heap stats
|
||||
|
||||
Bun uses mimalloc for the other heap. To report a summary of non-JavaScript memory usage, set the `MIMALLOC_SHOW_STATS=1` environment variable. and stats will print on exit.
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
|
||||
Configuring a development environment for Bun usually takes 30-90 minutes depending on your operating system.
|
||||
|
||||
## Linux/Windows
|
||||
|
||||
The best way to build Bun on Linux and Windows is with the official [Dev Container](https://containers.dev). It ships with Zig, JavaScriptCore, Zig Language Server, and more pre-installed on an instance of Ubuntu.
|
||||
|
||||
{% image src="https://user-images.githubusercontent.com/709451/147319227-6446589c-a4d9-480d-bd5b-43037a9e56fd.png" /%}
|
||||
|
||||
To develop on Linux/Windows, [Docker](https://www.docker.com) is required. If using WSL on Windows, it is recommended to use [Docker Desktop](https://docs.microsoft.com/en-us/windows/wsl/tutorials/wsl-containers) for its WSL2 integration.
|
||||
|
||||
### VSCode
|
||||
|
||||
If you're using VSCode, you'll need to have the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension installed.
|
||||
|
||||
To get started, open VS Code in the `bun` repository. The first time you try to open the dev container, the extension will automatically build it for you, based on [`Dockerfile.devcontainer`](https://github.com/oven-sh/bun/blob/main/Dockerfile.devcontainer).
|
||||
|
||||
To open the dev container, open the command palette (`Ctrl` + `Shift` + `P`) and run: `Dev Containers: Reopen in Container`. To later rebuild it (only needed when the devcontainer itself changes, not the Bun code), run: `Dev Containers: Rebuild and Reopen in Container`.
|
||||
|
||||
### Other editors and CLI
|
||||
|
||||
If you're using another editor or want to manually control the dev container from the command line or a script, you'll need to install the [Dev Container CLI](https://www.npmjs.com/package/@devcontainers/cli): `npm install -g @devcontainers/cli`.
|
||||
|
||||
To create and start the dev container, in the `bun` repository, locally run:
|
||||
|
||||
```bash
|
||||
# `make devcontainer-<command>` should be equivalent
|
||||
# to `devcontainer <command>`, it just sets the architecture
|
||||
# so if you're on ARM64, it'll do the right thing
|
||||
$ make devcontainer-up
|
||||
```
|
||||
|
||||
To just build the dev container image, run:
|
||||
|
||||
```bash
|
||||
$ make devcontainer-build
|
||||
```
|
||||
|
||||
To start a shell inside the container, run:
|
||||
|
||||
```bash
|
||||
$ make devcontainer-sh
|
||||
|
||||
# if it attaches to the container non-interactively,
|
||||
# instead use the regular docker exec command:
|
||||
$ docker exec -it <container-name/id> zsh
|
||||
```
|
||||
|
||||
### Cloning
|
||||
|
||||
You will then need to clone the GitHub repository inside that container.
|
||||
|
||||
```bash
|
||||
# First time setup
|
||||
$ gh auth login # if it fails to open a browser, use Personal Access Token instead
|
||||
$ gh repo clone oven-sh/bun . -- --depth=1 --progress -j8
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
```bash
|
||||
# Compile Bun dependencies (zig is already compiled)
|
||||
$ make devcontainer
|
||||
|
||||
# It initializes and updates all submodules except WebKit, because WebKit
|
||||
# takes a while and it's already compiled for you. To do it manually, use:
|
||||
$ git -c submodule."src/bun.js/WebKit".update=none submodule update --init --recursive --depth=1 --progress
|
||||
|
||||
# Build Bun for development
|
||||
$ make dev
|
||||
|
||||
# Run Bun
|
||||
$ bun-debug
|
||||
```
|
||||
|
||||
## MacOS
|
||||
|
||||
Install LLVM 15 and `homebrew` dependencies:
|
||||
|
||||
```bash
|
||||
$ brew install llvm@15 coreutils libtool cmake libiconv automake ninja gnu-sed pkg-config esbuild go rust
|
||||
```
|
||||
|
||||
Bun (& the version of Zig) need LLVM 15 and Clang 15 (`clang` is part of LLVM). Make sure LLVM 15 is in your `$PATH`:
|
||||
|
||||
```bash
|
||||
$ which clang-15
|
||||
```
|
||||
|
||||
If not, run this to manually link it:
|
||||
|
||||
```bash#bash
|
||||
# use fish_add_path if you're using fish
|
||||
$ export PATH="$PATH:$(brew --prefix llvm@15)/bin"
|
||||
$ export LDFLAGS="$LDFLAGS -L$(brew --prefix llvm@15)/lib"
|
||||
$ export CPPFLAGS="$CPPFLAGS -I$(brew --prefix llvm@15)/include"
|
||||
```
|
||||
|
||||
### Install Zig
|
||||
|
||||
{% callout %}
|
||||
**⚠️ Warning** — You must use the same version of Zig used by Bun in [oven-sh/zig](https://github.com/oven-sh/zig). Installing with `brew` or via Zig's download page will not work!
|
||||
{% /callout %}
|
||||
|
||||
Use [`zigup`](https://github.com/marler8997/zigup) to install the version of Zig (`ZIG_VERSION`) specified in the official [`Dockerfile`](https://github.com/oven-sh/bun/blob/main/Dockerfile). For example:
|
||||
|
||||
```bash
|
||||
$ zigup 0.11.0-dev.1783+436e99d13
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
To install and build dependencies:
|
||||
|
||||
```bash
|
||||
# without --depth=1 this will take 20+ minutes on 1gbps internet
|
||||
# mostly due to WebKit
|
||||
$ git submodule update --init --recursive --progress --depth=1 --checkout
|
||||
$ bun install
|
||||
$ make vendor identifier-cache
|
||||
```
|
||||
|
||||
To compile the C++ bindings:
|
||||
|
||||
```bash
|
||||
# without -j this will take 30+ minutes
|
||||
$ make bindings -j12
|
||||
```
|
||||
|
||||
<!-- If you're building on a macOS device, you'll need to have a valid Developer Certificate, or else the code signing step will fail. To check if you have one, open the `Keychain Access` app, go to the `login` profile and search for `Apple Development`. You should have at least one certificate with a name like `Apple Development: user@example.com (WDYABC123)`. If you don't have one, follow [this guide](https://ioscodesigning.com/generating-code-signing-files/#generate-a-code-signing-certificate-using-xcode) to get one. -->
|
||||
|
||||
<!-- You can still work with the generated binary locally at `packages/debug-bun-*/bun-debug` even if the code signing fails. -->
|
||||
|
||||
### Testing
|
||||
|
||||
To verify the build worked, lets print the version number on the development build of Bun.
|
||||
|
||||
```bash
|
||||
$ packages/debug-bun-darwin-*/bun-debug --version
|
||||
bun 0.x.y__dev
|
||||
```
|
||||
|
||||
You will want to add `packages/debug-bun-darwin-arm64/` or `packages/debug-bun-darwin-x64/` (depending on your architecture) to `$PATH` so you can run `bun-debug` from anywhere.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
If you see an error when compiling `libarchive`, run this:
|
||||
|
||||
```bash
|
||||
$ brew install pkg-config
|
||||
```
|
||||
|
||||
If you see an error about missing files on `zig build obj`, make sure you built the headers.
|
||||
|
||||
```bash
|
||||
$ make headers
|
||||
```
|
||||
|
||||
## JavaScript builtins
|
||||
|
||||
When you change anything in `src/bun.js/builtins/js/*`, run this:
|
||||
|
||||
```bash
|
||||
$ make clean-bindings generate-builtins && make bindings -j12
|
||||
```
|
||||
|
||||
That inlines the JavaScript code into C++ headers using the same builtins generator script that Safari uses.
|
||||
|
||||
## Code generation scripts
|
||||
|
||||
Bun leverages a lot of code generation scripts.
|
||||
|
||||
The [./src/bun.js/bindings/headers.h](https://github.com/oven-sh/bun/blob/main/src/bun.js/bindings/headers.h) file has bindings to & from Zig <> C++ code. This file is generated by running the following:
|
||||
|
||||
```bash
|
||||
$ make headers
|
||||
```
|
||||
|
||||
This ensures that the types for Zig and the types for C++ match up correctly, by using comptime reflection over functions exported/imported.
|
||||
|
||||
TypeScript files that end with `*.classes.ts` are another code generation script. They generate C++ boilerplate for classes implemented in Zig. The generated code lives in:
|
||||
|
||||
- [src/bun.js/bindings/ZigGeneratedClasses.cpp](https://github.com/oven-sh/bun/tree/main/src/bun.js/bindings/ZigGeneratedClasses.cpp)
|
||||
- [src/bun.js/bindings/ZigGeneratedClasses.h](https://github.com/oven-sh/bun/tree/main/src/bun.js/bindings/ZigGeneratedClasses.h)
|
||||
- [src/bun.js/bindings/generated_classes.zig](https://github.com/oven-sh/bun/tree/main/src/bun.js/bindings/generated_classes.zig)
|
||||
To generate the code, run:
|
||||
|
||||
```bash
|
||||
$ make codegen
|
||||
```
|
||||
|
||||
Lastly, we also have a [code generation script](src/bun.js/scripts/generate-jssink.js) for our native stream implementations.
|
||||
To run that, run:
|
||||
|
||||
```bash
|
||||
$ make generate-sink
|
||||
```
|
||||
|
||||
You probably won't need to run that one much.
|
||||
|
||||
## Modifying ESM core modules
|
||||
|
||||
Certain modules like `node:fs`, `node:path`, `node:stream`, and `bun:sqlite` are implemented in JavaScript. These live in `src/bun.js/*.exports.js` files.
|
||||
|
||||
While Bun is in beta, you can modify them at runtime in release builds via the environment variable `BUN_OVERRIDE_MODULE_PATH`. When set, Bun will look in the override directory for `<name>.exports.js` before checking the files from `src/bun.js` (which are now baked in to the binary). This lets you test changes to the ESM modules without needing to re-compile Bun.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you encounter `error: the build command failed with exit code 9` during the build process, this means you ran out of memory or swap. Bun currently needs about 22 GB of RAM to compile.
|
||||
225
docs/project/development.md
Normal file
225
docs/project/development.md
Normal file
@@ -0,0 +1,225 @@
|
||||
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, you must use a WSL environment as Bun does not yet compile on Windows natively.
|
||||
|
||||
## Install LLVM
|
||||
|
||||
Bun requires LLVM 15 and Clang 15 (`clang` is part of LLVM). This version requirement is to match WebKit (precompiled), as mismatching versions will cause memory allocation failures at runtime. In most cases, you can install LLVM through your system package manager:
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```bash#macOS (Homebrew)
|
||||
$ brew install llvm@15
|
||||
```
|
||||
|
||||
```bash#Ubuntu/Debian
|
||||
# On Ubuntu 22.04 and newer, LLVM 15 is available in the default repositories
|
||||
$ sudo apt install llvm-15 lld-15
|
||||
# On older versions,
|
||||
$ wget https://apt.llvm.org/llvm.sh -O - | sudo bash -s -- 15 all
|
||||
```
|
||||
|
||||
```bash#Arch
|
||||
$ sudo pacman -S llvm clang lld
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
If none of the above solutions apply, you will have to install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-15.0.7).
|
||||
|
||||
Make sure LLVM 15 is in your path:
|
||||
|
||||
```bash
|
||||
$ which clang-15
|
||||
```
|
||||
|
||||
If not, run this to manually link it:
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```bash#macOS (Homebrew)
|
||||
# use fish_add_path if you're using fish
|
||||
$ export PATH="$PATH:$(brew --prefix llvm@15)/bin"
|
||||
$ export LDFLAGS="$LDFLAGS -L$(brew --prefix llvm@15)/lib"
|
||||
$ export CPPFLAGS="$CPPFLAGS -I$(brew --prefix llvm@15)/include"
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
## Install Dependencies
|
||||
|
||||
Using your system's package manager, install the rest of Bun's dependencies:
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```bash#macOS (Homebrew)
|
||||
$ brew install automake ccache cmake coreutils esbuild gnu-sed go libiconv libtool ninja pkg-config rust
|
||||
```
|
||||
|
||||
```bash#Ubuntu/Debian
|
||||
$ sudo apt install cargo ccache cmake esbuild git golang libtool ninja-build pkg-config rustc
|
||||
```
|
||||
|
||||
```bash#Arch
|
||||
$ pacman -S base-devel ccache cmake esbuild git go libiconv libtool make ninja pkg-config python rust sed unzip
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
In addition to this, you will need either `bun` or `npm` installed to install the package.json dependencies.
|
||||
|
||||
## Install Zig
|
||||
|
||||
Zig can be installed either with our npm package [`@oven/zig`](https://www.npmjs.com/package/@oven/zig), or by using [zigup](https://github.com/marler8997/zigup).
|
||||
|
||||
```bash
|
||||
$ bun install -g @oven/zig
|
||||
$ zigup master
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
After cloning the repository, prepare bun to be built:
|
||||
|
||||
```bash
|
||||
$ make setup
|
||||
```
|
||||
|
||||
Then to build Bun:
|
||||
|
||||
```bash
|
||||
$ make dev
|
||||
```
|
||||
|
||||
The binary will be located at `packages/debug-bun-{platform}-{arch}/bun-debug`. It is recommended to add this to your `$PATH`. To verify the build worked, lets print the version number on the development build of Bun.
|
||||
|
||||
```bash
|
||||
$ packages/debug-bun-*/bun-debug --version
|
||||
bun 0.x.y__dev
|
||||
```
|
||||
|
||||
## VSCode
|
||||
|
||||
VSCode is the recommended IDE for working on Bun, as it has been configured. Once opening, you can run `Extensions: Show Recommended Extensions` to install the recommended extensions for Zig and C++. ZLS is automatically configured.
|
||||
|
||||
## JavaScript builtins
|
||||
|
||||
When you change anything in `src/bun.js/builtins/js/*` or switch branches, run this:
|
||||
|
||||
```bash
|
||||
$ make regenerate-bindings
|
||||
```
|
||||
|
||||
That inlines the JavaScript code into C++ headers using the same builtins generator script that Safari uses.
|
||||
|
||||
{% callout %}
|
||||
Make sure you have `ccache` installed, otherwise regeneration will take much longer than it should.
|
||||
{% /callout %}
|
||||
|
||||
## Code generation scripts
|
||||
|
||||
Bun leverages a lot of code generation scripts.
|
||||
|
||||
The [./src/bun.js/bindings/headers.h](https://github.com/oven-sh/bun/blob/main/src/bun.js/bindings/headers.h) file has bindings to & from Zig <> C++ code. This file is generated by running the following:
|
||||
|
||||
```bash
|
||||
$ make headers
|
||||
```
|
||||
|
||||
This ensures that the types for Zig and the types for C++ match up correctly, by using comptime reflection over functions exported/imported.
|
||||
|
||||
TypeScript files that end with `*.classes.ts` are another code generation script. They generate C++ boilerplate for classes implemented in Zig. The generated code lives in:
|
||||
|
||||
- [src/bun.js/bindings/ZigGeneratedClasses.cpp](https://github.com/oven-sh/bun/tree/main/src/bun.js/bindings/ZigGeneratedClasses.cpp)
|
||||
- [src/bun.js/bindings/ZigGeneratedClasses.h](https://github.com/oven-sh/bun/tree/main/src/bun.js/bindings/ZigGeneratedClasses.h)
|
||||
- [src/bun.js/bindings/generated_classes.zig](https://github.com/oven-sh/bun/tree/main/src/bun.js/bindings/generated_classes.zig)
|
||||
To generate the code, run:
|
||||
|
||||
```bash
|
||||
$ make codegen
|
||||
```
|
||||
|
||||
Lastly, we also have a [code generation script](src/bun.js/scripts/generate-jssink.js) for our native stream implementations.
|
||||
To run that, run:
|
||||
|
||||
```bash
|
||||
$ make generate-sink
|
||||
```
|
||||
|
||||
You probably won't need to run that one much.
|
||||
|
||||
## Modifying ESM core modules
|
||||
|
||||
Certain modules like `node:fs`, `node:path`, `node:stream`, and `bun:sqlite` are implemented in JavaScript. These live in `src/bun.js/*.exports.js` files.
|
||||
|
||||
While Bun is in beta, you can modify them at runtime in release builds via the environment variable `BUN_OVERRIDE_MODULE_PATH`. When set, Bun will look in the override directory for `<name>.exports.js` before checking the files from `src/bun.js` (which are now baked in to the binary). This lets you test changes to the ESM modules without needing to re-compile Bun.
|
||||
|
||||
## Release build
|
||||
|
||||
To build a release build of Bun, run:
|
||||
|
||||
```bash
|
||||
$ make release-bindings -j12
|
||||
$ make release
|
||||
```
|
||||
|
||||
The binary will be located at `packages/bun-{platform}-{arch}/bun`.
|
||||
|
||||
## Valgrind
|
||||
|
||||
On Linux, valgrind can help find memory issues.
|
||||
|
||||
Keep in mind:
|
||||
|
||||
- JavaScriptCore doesn't support valgrind. It will report spurious errors.
|
||||
- Valgrind is slow
|
||||
- Mimalloc will sometimes cause spurious errors when debug build is enabled
|
||||
|
||||
You'll need a very recent version of Valgrind due to DWARF 5 debug symbols. You may need to manually compile Valgrind instead of using it from your Linux package manager.
|
||||
|
||||
`--fair-sched=try` is necessary if running multithreaded code in Bun (such as the bundler). Otherwise it will hang.
|
||||
|
||||
```bash
|
||||
$ valgrind --fair-sched=try --track-origins=yes bun-debug <args>
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### libarchive
|
||||
|
||||
If you see an error when compiling `libarchive`, run this:
|
||||
|
||||
```bash
|
||||
$ brew install pkg-config
|
||||
```
|
||||
|
||||
### missing files on `zig build obj`
|
||||
|
||||
If you see an error about missing files on `zig build obj`, make sure you built the headers.
|
||||
|
||||
```bash
|
||||
$ make headers
|
||||
```
|
||||
|
||||
### cmakeconfig.h not found
|
||||
|
||||
If you see an error about `cmakeconfig.h` not being found, this is because the precompiled WebKit did not install properly.
|
||||
|
||||
```bash
|
||||
$ bun install
|
||||
```
|
||||
|
||||
Check to see the command installed webkit, and you can manully look for `node_modules/bun-webkit-{platform}-{arch}`:
|
||||
|
||||
```bash
|
||||
# this should reveal two directories. if not, something went wrong
|
||||
$ echo node_modules/bun-webkit*
|
||||
```
|
||||
|
||||
### macOS `library not found for -lSystem`
|
||||
|
||||
If you see this error when compiling, run:
|
||||
|
||||
```bash
|
||||
$ xcode-select --install
|
||||
```
|
||||
98
docs/runtime/autoimport.md
Normal file
98
docs/runtime/autoimport.md
Normal file
@@ -0,0 +1,98 @@
|
||||
{% callout %}
|
||||
**Note** — Added in Bun v0.3.0
|
||||
{% /callout %}
|
||||
|
||||
If no `node_modules` directory is found in the working directory or higher, Bun will abandon Node.js-style module resolution in favor of the **Bun module resolution algorithm**.
|
||||
|
||||
Under Bun-style module resolution, all imported packages are auto-installed on the fly into a [global module cache](/docs/cli/install#global-cache) during execution (the same cache used by [`bun install`](/docs/cli/install)).
|
||||
|
||||
```ts
|
||||
import { foo } from "foo"; // install `latest` version
|
||||
|
||||
foo();
|
||||
```
|
||||
|
||||
The first time you run this script, Bun will auto-install `"foo"` and cache it. The next time you run the script, it will use the cached version.
|
||||
|
||||
## Version resolution
|
||||
|
||||
To determine which version to install, Bun follows the following algorithm:
|
||||
|
||||
1. Check for a `bun.lockb` file in the project root. If it exists, use the version specified in the lockfile.
|
||||
2. Otherwise, scan up the tree for a `package.json` that includes `"foo"` as a dependency. If found, use the specified semver version or version range.
|
||||
3. Otherwise, use `latest`.
|
||||
|
||||
## Cache behavior
|
||||
|
||||
Once a version or version range has been determined, Bun will:
|
||||
|
||||
1. Check the module cache for a compatible version. If one exists, use it.
|
||||
2. When resolving `latest`, Bun will check if `package@latest` has been downloaded and cached in the last _24 hours_. If so, use it.
|
||||
3. Otherwise, download and install the appropriate version from the `npm` registry.
|
||||
|
||||
## Installation
|
||||
|
||||
Packages are installed and cached into `<cache>/<pkg>@<version>`, so multiple versions of the same package can be cached at once. Additionally, a symlink is created under `<cache>/<pkg>/<version>` to make it faster to look up all versions of a package that exist in the cache.
|
||||
|
||||
## Version specifiers
|
||||
|
||||
This entire resolution algorithm can be short-circuited by specifying a version or version range directly in your import statement.
|
||||
|
||||
```ts
|
||||
import { z } from "zod@3.0.0"; // specific version
|
||||
import { z } from "zod@next"; // npm tag
|
||||
import { z } from "zod@^3.20.0"; // semver range
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
This auto-installation approach is useful for a few reasons:
|
||||
|
||||
- **Space efficiency** — Each version of a dependency only exists in one place on disk. This is a huge space and time savings compared to redundant per-project installations.
|
||||
- **Portability** — To share simple scripts and gists, your source file is _self-contained_. No need to `zip` together a directory containing your code and config files. With version specifiers in `import` statements, even a `package.json` isn't necessary.
|
||||
- **Convenience** — There's no need to run `npm install` or `bun install` before running a file or script. Just `bun run` it.
|
||||
- **Backwards compatibility** — Because Bun still respects the versions specified in `package.json` if one exists, you can switch to Bun-style resolution with a single command: `rm -rf node_modules`.
|
||||
|
||||
## Limitations
|
||||
|
||||
- No Intellisense. TypeScript auto-completion in IDEs relies on the existence of type declaration files inside `node_modules`. We are investigating various solutions to this.
|
||||
- No [patch-package](https://github.com/ds300/patch-package) support
|
||||
|
||||
<!-- - The implementation details of Bun's install cache will change between versions. Don't think of it as an API. To reliably resolve packages, use Bun's builtin APIs (such as `Bun.resolveSync` or `import.meta.resolve`) instead of relying on the filesystem directly. Bun will likely move to a binary archive format where packages may not correspond to files/folders on disk at all - so if you depend on the filesystem structure instead of the JavaScript API, your code will eventually break. -->
|
||||
|
||||
<!-- ## Customizing behavior
|
||||
|
||||
To prefer locally-installed versions of packages. Instead of checking npm for latest versions, you can pass the `--prefer-offline` flag to prefer locally-installed versions of packages.
|
||||
|
||||
```bash
|
||||
$ bun run --prefer-offline my-script.ts
|
||||
```
|
||||
|
||||
This will check the install cache for installed versions of packages before checking the npm registry. If no matching version of a package is installed, only then will it check npm for the latest version.
|
||||
|
||||
#### Prefer latest
|
||||
|
||||
To always use the latest version of a package, you can pass the `--prefer-latest` flag.
|
||||
|
||||
```bash
|
||||
$ bun run --prefer-latest my-script.ts
|
||||
``` -->
|
||||
|
||||
## FAQ
|
||||
|
||||
{% details summary="How is this different from what pnpm does?" %}
|
||||
|
||||
With pnpm, you have to run `pnpm install`, which creates a `node_modules` folder of symlinks for the runtime to resolve. By contrast, Bun resolves dependencies on the fly when you run a file; there's no need to run any `install` command ahead of time. Bun also doesn't create a `node_modules` folder.
|
||||
|
||||
{% /details %}
|
||||
|
||||
{% details summary="How is this different from Yarn Plug'N'Play does?" %}
|
||||
With Yarn, you must run `yarn install` before you run a script. By contrast, Bun resolves dependencies on the fly when you run a file; there's no need to run any `install` command ahead of time.
|
||||
|
||||
Yarn Plug'N'Play also uses zip files to store dependencies. This makes dependency loading [slower at runtime](https://twitter.com/jarredsumner/status/1458207919636287490), as random access reads on zip files tend to be slower than the equivalent disk lookup.
|
||||
{% /details %}
|
||||
|
||||
{% details summary="How is this different from what Deno does?" %}
|
||||
|
||||
Deno requires an `npm:` specifier before each npm `import`, lacks support for import maps via `compilerOptions.paths` in `tsconfig.json`, and has incomplete support for `package.json` settings. Unlike Deno, Bun does not currently support URL imports.
|
||||
{% /details %}
|
||||
75
docs/runtime/bun-apis.md
Normal file
75
docs/runtime/bun-apis.md
Normal file
@@ -0,0 +1,75 @@
|
||||
Bun implements a set of native APIs on the `Bun` global object and through a number of built-in modules. These APIs represent the canonical "Bun-native" way to perform some common development tasks. They are all heavily optimized for performance. Click the link in the left column to view the associated documentation.
|
||||
|
||||
{% table %}
|
||||
|
||||
- Topic
|
||||
- APIs
|
||||
|
||||
---
|
||||
|
||||
- [HTTP](/docs/api/http)
|
||||
- `Bun.serve`
|
||||
|
||||
---
|
||||
|
||||
- [File I/O](/docs/api/file-io)
|
||||
- `Bun.file` `Bun.write`
|
||||
|
||||
---
|
||||
|
||||
- [Processes](/docs/api/spawn)
|
||||
- `Bun.spawn` `Bun.spawnSync`
|
||||
|
||||
---
|
||||
|
||||
- [TCP](/docs/api/tcp)
|
||||
- `Bun.listen` `Bun.connect`
|
||||
|
||||
---
|
||||
|
||||
- [Transpiler](/docs/api/transpiler)
|
||||
- `Bun.Transpiler`
|
||||
|
||||
---
|
||||
|
||||
- [Routing](/docs/api/file-system-router)
|
||||
- `Bun.FileSystemRouter`
|
||||
|
||||
---
|
||||
|
||||
- [HTMLRewriter](/docs/api/html-rewriter)
|
||||
- `HTMLRewriter`
|
||||
|
||||
---
|
||||
|
||||
<!-- - [DNS](/docs/api/dns)
|
||||
- `Bun.dns`
|
||||
|
||||
--- -->
|
||||
|
||||
- [Utils](/docs/api/utils)
|
||||
- `Bun.peek` `Bun.which`
|
||||
|
||||
---
|
||||
|
||||
- [SQLite](/docs/api/sqlite)
|
||||
- `bun:sqlite`
|
||||
|
||||
---
|
||||
|
||||
- [FFI](/docs/api/ffi)
|
||||
- `bun:ffi`
|
||||
|
||||
---
|
||||
|
||||
- [Testing](/docs/api/test)
|
||||
- `bun:test`
|
||||
|
||||
---
|
||||
|
||||
- [Node-API](/docs/api/node-api)
|
||||
- `Node-API`
|
||||
|
||||
---
|
||||
|
||||
{% /table %}
|
||||
@@ -1,23 +1,27 @@
|
||||
## Environment variables
|
||||
There are two primary mechanisms for configuring the behavior of Bun.
|
||||
|
||||
- `GOMAXPROCS`: For `bun bun`, this sets the maximum number of threads to use. If you’re experiencing an issue with `bun bun`, try setting `GOMAXPROCS=1` to force Bun to run single-threaded
|
||||
- `DISABLE_BUN_ANALYTICS=1` this disables Bun's analytics. Bun records bundle timings (so we can answer with data, "is Bun getting faster?") and feature usage (e.g., "are people actually using macros?"). The request body size is about 60 bytes, so it’s not a lot of data
|
||||
- `TMPDIR`: Before `bun bun` completes, it stores the new `.bun` in `$TMPDIR`. If unset, `TMPDIR` defaults to the platform-specific temporary directory (on Linux, `/tmp` and on macOS `/private/tmp`)
|
||||
- environment variables
|
||||
- `bunfig.toml`: Bun's configuration file
|
||||
|
||||
## `bunfig.toml`
|
||||
Configuring with `bunfig.toml` is optional. Bun aims to be zero-configuration out of the box, but is also highly configurable for advanced use cases. Your `bunfig.toml` should live in your project root alongside `package.json`.
|
||||
|
||||
Bun's configuration file is called `bunfig.toml`. Configuring with `bunfig.toml` is optional. Bun aims to be zero-configuration out of the box, but is also highly configurable for advanced use cases..
|
||||
|
||||
Your `bunfig.toml` should live in your project root alongside `package.json`. You can also create a global configuration file at the following paths:
|
||||
You can also create a global configuration file at the following paths:
|
||||
|
||||
- `$HOME/.bunfig.toml`
|
||||
- `$XDG_CONFIG_HOME/.bunfig.toml`
|
||||
|
||||
If both a global and local `bunfig` are detected, the results are shallow-merged, with local overridding global. CLI flags will override `bunfig` setting where applicable.
|
||||
|
||||
## Environment variables
|
||||
|
||||
<!-- - `GOMAXPROCS`: For `bun bun`, this sets the maximum number of threads to use. If you’re experiencing an issue with `bun bun`, try setting `GOMAXPROCS=1` to force Bun to run single-threaded -->
|
||||
|
||||
- `DISABLE_BUN_ANALYTICS=1` this disables Bun's analytics. Bun records bundle timings (so we can answer with data, "is Bun getting faster?") and feature usage (e.g., "are people actually using macros?"). The request body size is about 60 bytes, so it’s not a lot of data
|
||||
- `TMPDIR`: Bun occasionally requires a directory to store intermediate assets during bundling or other operations. If unset, `TMPDIR` defaults to the platform-specific temporary directory (on Linux, `/tmp` and on macOS `/private/tmp`).
|
||||
|
||||
## Configure `bun install`
|
||||
|
||||
Package management is a complex issue; to support a range of use cases, the behavior of `bun install` can be configured in [`bunfig.toml`](/docs/project/configuration).
|
||||
Package management is a complex issue; to support a range of use cases, the behavior of `bun install` can be configured in [`bunfig.toml`](/docs/runtime/configuration).
|
||||
|
||||
### Default flags
|
||||
|
||||
@@ -42,7 +46,7 @@ production = false
|
||||
dryRun = false
|
||||
```
|
||||
|
||||
### Registries
|
||||
### Private scopes and registries
|
||||
|
||||
The default registry is `https://registry.npmjs.org/`. This can be globally configured in `bunfig.toml`:
|
||||
|
||||
@@ -99,7 +103,7 @@ disableManifest = false
|
||||
|
||||
To configure lockfile behavior:
|
||||
|
||||
```toml {% disabled %}
|
||||
```toml
|
||||
[install.lockfile]
|
||||
|
||||
# path to read bun.lockb from
|
||||
@@ -7,16 +7,17 @@ Bun supports two kinds of automatic reloading via CLI flags:
|
||||
|
||||
Watch mode can be used with `bun test` or when running TypeScript, JSX, and JavaScript files.
|
||||
|
||||
|
||||
To run a file in `--watch` mode:
|
||||
|
||||
```bash
|
||||
$ bun index.tsx --watch
|
||||
$ bun --watch index.tsx
|
||||
```
|
||||
|
||||
To run your tests in `--watch` mode:
|
||||
|
||||
```bash
|
||||
$ bun test --watch
|
||||
$ bun --watch test
|
||||
```
|
||||
|
||||
In `--watch` mode, Bun keeps track of all imported files and watches them for changes. When a change is detected, Bun restarts the process, preserving the same set of CLI arguments and environment variables used in the initial run. If Bun crashes, `--watch` will attempt to automatically restart the process.
|
||||
@@ -34,7 +35,7 @@ The following examples show Bun live-reloading a file as it is edited, with VSCo
|
||||
{% codetabs %}
|
||||
|
||||
```bash
|
||||
$ bun run watchy.tsx --watch
|
||||
$ bun run --watch watchy.tsx
|
||||
```
|
||||
|
||||
```tsx#watchy.tsx
|
||||
@@ -57,7 +58,7 @@ serve({
|
||||
Running `bun test` in watch mode and `save-on-keypress` enabled:
|
||||
|
||||
```bash
|
||||
$ bun test --watch
|
||||
$ bun --watch test
|
||||
```
|
||||
|
||||

|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
Bun is a new JavaScript runtime designed to be a faster, leaner, more modern replacement for Node.js.
|
||||
Bun is a new JavaScript & TypeScript runtime designed to be a faster, leaner, and more modern drop-in replacement for Node.js.
|
||||
|
||||
## Speed
|
||||
|
||||
Bun is designed to start fast and run fast. It's transpiler and runtime are written in Zig, a modern, high-performance language. On Linux, this translates into startup times [4x faster](https://twitter.com/jarredsumner/status/1499225725492076544) than Node.js. Performance sensitive APIs like `Buffer`, `fetch`, and `Response` are heavily profiled and optimized. Under the hood Bun uses the [JavaScriptCore engine](https://developer.apple.com/documentation/javascriptcore), which is developed by Apple for Safari. It starts and runs faster than V8, the engine used by Node.js and Chromium-based browsers.
|
||||
Bun is designed to start fast and run fast. It's transpiler and runtime are written in Zig, a modern, high-performance language. On Linux, this translates into startup times [4x faster](https://twitter.com/jarredsumner/status/1499225725492076544) than Node.js.
|
||||
|
||||
## File types
|
||||
{% image src="/images/bun-run-speed.jpeg" caption="Bun vs Node.js vs Deno running Hello World" /%}
|
||||
|
||||
Bun natively supports TypeScript and JSX out of the box.
|
||||
<!-- If no `node_modules` directory is found in the working directory or above, Bun will abandon Node.js-style module resolution in favor of the `Bun module resolution algorithm`. Under Bun-style module resolution, all packages are _auto-installed_ on the fly into a [global module cache](/docs/cli/install#global-cache). For full details on this algorithm, refer to [Runtime > Modules](/docs/runtime/modules). -->
|
||||
|
||||
Performance sensitive APIs like `Buffer`, `fetch`, and `Response` are heavily profiled and optimized. Under the hood Bun uses the [JavaScriptCore engine](https://developer.apple.com/documentation/javascriptcore), which is developed by Apple for Safari. It starts and runs faster than V8, the engine used by Node.js and Chromium-based browsers.
|
||||
|
||||
## TypeScript
|
||||
|
||||
Bun natively supports TypeScript out of the box. All files are transpiled on the fly by Bun's fast native transpiler before being executed. Similar to other build tools, Bun does not perform typechecking; it simply removes type annotations from the file.
|
||||
|
||||
```bash
|
||||
$ bun server.tsx
|
||||
$ bun index.js
|
||||
$ bun index.jsx
|
||||
$ bun index.ts
|
||||
$ bun index.tsx
|
||||
```
|
||||
|
||||
Some aspects of Bun's runtime behavior are affected by the contents of your `tsconfig.json` file. Refer to [Runtime > TypeScript](/docs/runtime/typescript) page for details.
|
||||
|
||||
<!-- Before execution, Bun internally transforms all source files to vanilla JavaScript using its fast native transpiler. The transpiler looks at the files extension to determine how to handle it. -->
|
||||
|
||||
<!--
|
||||
@@ -79,6 +90,10 @@ every file before execution. It's transpiler can directly run TypeScript and JS
|
||||
|
||||
{% /table %} -->
|
||||
|
||||
## JSX
|
||||
|
||||
## JSON and TOML
|
||||
|
||||
Source files can import a `*.json` or `*.toml` file to load its contents as a plain old JavaScript object.
|
||||
|
||||
```ts
|
||||
@@ -86,7 +101,9 @@ import pkg from "./package.json";
|
||||
import bunfig from "./bunfig.toml";
|
||||
```
|
||||
|
||||
As of v0.5.2, experimental support has been for the [WebAssembly System Interface](https://github.com/WebAssembly/WASI) (WASI), you can run `.wasm` binaries.
|
||||
## WASM
|
||||
|
||||
As of v0.5.2, experimental support exists for WASI, the [WebAssembly System Interface](https://github.com/WebAssembly/WASI). To run a `.wasm` binary with Bun:
|
||||
|
||||
```bash
|
||||
$ bun ./my-wasm-app.wasm
|
||||
@@ -95,14 +112,13 @@ $ bun run ./my-wasm-app.whatever
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
**Note** — WASI support is based on [wasi-js](https://github.com/sagemathinc/cowasm/tree/main/packages/wasi-js). Currently, it only supports WASI binaries that use the `wasi_snapshot_preview1` or `wasi_unstable` APIs. Bun's implementation is not optimized for performance, but if this feature gets popular, we'll definitely invest time in making it faster.
|
||||
{% /callout %}
|
||||
|
||||
Support for additional file types can be implemented with [Plugins](/docs/runtime/plugins).
|
||||
**Note** — WASI support is based on [wasi-js](https://github.com/sagemathinc/cowasm/tree/main/packages/wasi-js). Currently, it only supports WASI binaries that use the `wasi_snapshot_preview1` or `wasi_unstable` APIs. Bun's implementation is not fully optimized for performance; this will become more of a priority as WASM grows in popularity.
|
||||
{% /callout %}
|
||||
|
||||
## Node.js compatibility
|
||||
|
||||
Long-term, Bun aims for complete Node.js compatibility. Most Node.js packages already work with Bun out of the box, but certain low-level APIs like `dgram` are still unimplemented. Track the current compatibility status at [Ecosystem > Node.js](/docs/ecosystem/nodejs).
|
||||
Long-term, Bun aims for complete Node.js compatibility. Most Node.js packages already work with Bun out of the box, but certain low-level APIs like `dgram` are still unimplemented. Track the current compatibility status at [Ecosystem > Node.js](/docs/runtime/nodejs-apis).
|
||||
|
||||
Bun implements the Node.js module resolution algorithm, so dependencies can still be managed with `package.json`, `node_modules`, and CommonJS-style imports.
|
||||
|
||||
@@ -110,7 +126,7 @@ Bun implements the Node.js module resolution algorithm, so dependencies can stil
|
||||
**Note** — We recommend using Bun's [built-in package manager](/docs/cli/install) for a performance boost over other npm clients.
|
||||
{% /callout %}
|
||||
|
||||
## Web-standard
|
||||
## Web APIs
|
||||
|
||||
<!-- When prudent, Bun attempts to implement Web-standard APIs instead of introducing new APIs. Refer to [Runtime > Web APIs](/docs/web-apis) for a list of Web APIs that are available in Bun. -->
|
||||
|
||||
@@ -207,7 +223,7 @@ The following Web APIs are partially or completely supported.
|
||||
|
||||
{% /table %}
|
||||
|
||||
## Bun-native APIs
|
||||
## Bun APIs
|
||||
|
||||
Bun exposes a set of Bun-specific APIs on the `Bun` global object and through a number of built-in modules. These APIs represent the canonical "Bun-native" way to perform some common development tasks. They are all heavily optimized for performance. Click the link in the left column to view the associated documentation.
|
||||
|
||||
@@ -284,3 +300,7 @@ Bun exposes a set of Bun-specific APIs on the `Bun` global object and through a
|
||||
---
|
||||
|
||||
{% /table %}
|
||||
|
||||
## Plugins
|
||||
|
||||
Support for additional file types can be implemented with plugins. Refer to [Runtime > Plugins](/docs/runtime/plugins) for full documentation.
|
||||
|
||||
35
docs/runtime/jsx.md
Normal file
35
docs/runtime/jsx.md
Normal file
@@ -0,0 +1,35 @@
|
||||
Bun supports `.jsx` and `.tsx` files out of the box. Bun's internal transpiler converts JSX syntax into vanilla JavaScript before execution.
|
||||
|
||||
```tsx#react.tsx
|
||||
function Component(props: {message: string}) {
|
||||
return (
|
||||
<body>
|
||||
<h1 style={{color: 'red'}}>{props.message}</h1>
|
||||
</body>
|
||||
);
|
||||
}
|
||||
|
||||
console.log(<Component message="Hello world!" />);
|
||||
```
|
||||
|
||||
Bun implements special logging for JSX to make debugging easier.
|
||||
|
||||
```bash
|
||||
$ bun run react.tsx
|
||||
<Component message="Hello world!" />
|
||||
```
|
||||
|
||||
<!-- ### Prop punning
|
||||
|
||||
The Bun runtime also supports "prop punning" for JSX. This is a shorthand syntax useful for assigning a variable to a prop with the same name.
|
||||
|
||||
```tsx
|
||||
function Div(props: {className: string;}) {
|
||||
const {className} = props;
|
||||
|
||||
// without punning
|
||||
return <div className={className} />;
|
||||
// with punning
|
||||
return <div {className} />;
|
||||
}
|
||||
``` -->
|
||||
@@ -1,3 +1,91 @@
|
||||
## TypeScript
|
||||
|
||||
Bun natively supports TypeScript out of the box. All files are transpiled on the fly by Bun's fast native transpiler before being executed. Similar to other build tools, Bun does not perform typechecking; it simply removes type annotations from the file.
|
||||
|
||||
```bash
|
||||
$ bun index.js
|
||||
$ bun index.jsx
|
||||
$ bun index.ts
|
||||
$ bun index.tsx
|
||||
```
|
||||
|
||||
Some aspects of Bun's runtime behavior are affected by the contents of your `tsconfig.json` file. Refer to [Runtime > TypeScript](/docs/runtime/typescript) page for details.
|
||||
|
||||
## JSX
|
||||
|
||||
Bun supports `.jsx` and `.tsx` files out of the box. Bun's internal transpiler converts JSX syntax into vanilla JavaScript before execution.
|
||||
|
||||
```tsx#react.tsx
|
||||
function Component(props: {message: string}) {
|
||||
return (
|
||||
<body>
|
||||
<h1 style={{color: 'red'}}>{props.message}</h1>
|
||||
</body>
|
||||
);
|
||||
}
|
||||
|
||||
console.log(<Component message="Hello world!" />);
|
||||
```
|
||||
|
||||
Bun implements special logging for JSX to make debugging easier.
|
||||
|
||||
```bash
|
||||
$ bun run react.tsx
|
||||
<Component message="Hello world!" />
|
||||
```
|
||||
|
||||
## Text files
|
||||
|
||||
{% callout %}
|
||||
Supported in Bun v0.6.0 canary.
|
||||
{% /callout %}
|
||||
|
||||
Text files can be imported as strings.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#index.ts
|
||||
import text from "./text.txt";
|
||||
console.log(text);
|
||||
// => "Hello world!"
|
||||
```
|
||||
|
||||
```txt#text.txt
|
||||
Hello world!
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
## JSON and TOML
|
||||
|
||||
JSON and TOML files can be directly imported from a source file. The contents will be loaded and returned as a JavaScript object.
|
||||
|
||||
```ts
|
||||
import pkg from "./package.json";
|
||||
import data from "./data.toml";
|
||||
```
|
||||
|
||||
## WASM
|
||||
|
||||
As of v0.5.2, experimental support exists for WASI, the [WebAssembly System Interface](https://github.com/WebAssembly/WASI). To run a `.wasm` binary with Bun:
|
||||
|
||||
```bash
|
||||
$ bun ./my-wasm-app.wasm
|
||||
# if the filename doesn't end with ".wasm"
|
||||
$ bun run ./my-wasm-app.whatever
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
|
||||
**Note** — WASI support is based on [wasi-js](https://github.com/sagemathinc/cowasm/tree/main/packages/wasi-js). Currently, it only supports WASI binaries that use the `wasi_snapshot_preview1` or `wasi_unstable` APIs. Bun's implementation is not fully optimized for performance; this will become more of a priority as WASM grows in popularity.
|
||||
{% /callout %}
|
||||
|
||||
## Custom loaders
|
||||
|
||||
Support for additional file types can be implemented with plugins. Refer to [Runtime > Plugins](/docs/runtime/plugins) for full documentation.
|
||||
|
||||
<!--
|
||||
|
||||
A loader determines how to map imports & file extensions to transforms and output.
|
||||
|
||||
Currently, Bun implements the following loaders:
|
||||
@@ -25,4 +113,4 @@ You can configure which loaders map to which extensions by passing `--loaders` t
|
||||
$ bun --loader=.js:js
|
||||
```
|
||||
|
||||
This will disable JSX transforms for `.js` files.
|
||||
This will disable JSX transforms for `.js` files. -->
|
||||
|
||||
@@ -156,104 +156,3 @@ In the spirit of treating TypeScript as a first-class citizen, the Bun runtime w
|
||||
```
|
||||
|
||||
If you aren't a TypeScript user, you can create a [`jsconfig.json`](https://code.visualstudio.com/docs/languages/jsconfig) in your project root to achieve the same behavior.
|
||||
|
||||
## Bun-style resolution
|
||||
|
||||
{% callout %}
|
||||
**Note** — Added in Bun v0.3.0
|
||||
{% /callout %}
|
||||
|
||||
If no `node_modules` directory is found in the working directory or higher, Bun will abandon Node.js-style module resolution in favor of the **Bun module resolution algorithm**.
|
||||
|
||||
Under Bun-style module resolution, all imported packages are auto-installed on the fly into a [global module cache](/docs/cli/install#global-cache) during execution (the same cache used by [`bun install`](/docs/cli/install)).
|
||||
|
||||
```ts
|
||||
import { foo } from "foo"; // install `latest` version
|
||||
|
||||
foo();
|
||||
```
|
||||
|
||||
The first time you run this script, Bun will auto-install `"foo"` and cache it. The next time you run the script, it will use the cached version.
|
||||
|
||||
### Version resolution
|
||||
|
||||
To determine which version to install, Bun follows the following algorithm:
|
||||
|
||||
1. Check for a `bun.lockb` file in the project root. If it exists, use the version specified in the lockfile.
|
||||
2. Otherwise, scan up the tree for a `package.json` that includes `"foo"` as a dependency. If found, use the specified semver version or version range.
|
||||
3. Otherwise, use `latest`.
|
||||
|
||||
### Cache behavior
|
||||
|
||||
Once a version or version range has been determined, Bun will:
|
||||
|
||||
1. Check the module cache for a compatible version. If one exists, use it.
|
||||
2. When resolving `latest`, Bun will check if `package@latest` has been downloaded and cached in the last _24 hours_. If so, use it.
|
||||
3. Otherwise, download and install the appropriate version from the `npm` registry.
|
||||
|
||||
### Installation
|
||||
|
||||
Packages are installed and cached into `<cache>/<pkg>@<version>`, so multiple versions of the same package can be cached at once. Additionally, a symlink is created under `<cache>/<pkg>/<version>` to make it faster to look up all versions of a package that exist in the cache.
|
||||
|
||||
### Version specifiers
|
||||
|
||||
This entire resolution algorithm can be short-circuited by specifying a version or version range directly in your import statement.
|
||||
|
||||
```ts
|
||||
import { z } from "zod@3.0.0"; // specific version
|
||||
import { z } from "zod@next"; // npm tag
|
||||
import { z } from "zod@^3.20.0"; // semver range
|
||||
```
|
||||
|
||||
### Benefits
|
||||
|
||||
This auto-installation approach is useful for a few reasons:
|
||||
|
||||
- **Space efficiency** — Each version of a dependency only exists in one place on disk. This is a huge space and time savings compared to redundant per-project installations.
|
||||
- **Portability** — To share simple scripts and gists, your source file is _self-contained_. No need to `zip` together a directory containing your code and config files. With version specifiers in `import` statements, even a `package.json` isn't necessary.
|
||||
- **Convenience** — There's no need to run `npm install` or `bun install` before running a file or script. Just `bun run` it.
|
||||
- **Backwards compatibility** — Because Bun still respects the versions specified in `package.json` if one exists, you can switch to Bun-style resolution with a single command: `rm -rf node_modules`.
|
||||
|
||||
### Limitations
|
||||
|
||||
- No Intellisense. TypeScript auto-completion in IDEs relies on the existence of type declaration files inside `node_modules`. We are investigating various solutions to this.
|
||||
- No [patch-package](https://github.com/ds300/patch-package) support
|
||||
|
||||
<!-- - The implementation details of Bun's install cache will change between versions. Don't think of it as an API. To reliably resolve packages, use Bun's builtin APIs (such as `Bun.resolveSync` or `import.meta.resolve`) instead of relying on the filesystem directly. Bun will likely move to a binary archive format where packages may not correspond to files/folders on disk at all - so if you depend on the filesystem structure instead of the JavaScript API, your code will eventually break. -->
|
||||
|
||||
<!-- ### Customizing behavior
|
||||
|
||||
To prefer locally-installed versions of packages. Instead of checking npm for latest versions, you can pass the `--prefer-offline` flag to prefer locally-installed versions of packages.
|
||||
|
||||
```bash
|
||||
$ bun run --prefer-offline my-script.ts
|
||||
```
|
||||
|
||||
This will check the install cache for installed versions of packages before checking the npm registry. If no matching version of a package is installed, only then will it check npm for the latest version.
|
||||
|
||||
#### Prefer latest
|
||||
|
||||
To always use the latest version of a package, you can pass the `--prefer-latest` flag.
|
||||
|
||||
```bash
|
||||
$ bun run --prefer-latest my-script.ts
|
||||
``` -->
|
||||
|
||||
### FAQ
|
||||
|
||||
{% details summary="How is this different from what pnpm does?" %}
|
||||
|
||||
With pnpm, you have to run `pnpm install`, which creates a `node_modules` folder of symlinks for the runtime to resolve. By contrast, Bun resolves dependencies on the fly when you run a file; there's no need to run any `install` command ahead of time. Bun also doesn't create a `node_modules` folder.
|
||||
|
||||
{% /details %}
|
||||
|
||||
{% details summary="How is this different from Yarn Plug'N'Play does?" %}
|
||||
With Yarn, you must run `yarn install` before you run a script. By contrast, Bun resolves dependencies on the fly when you run a file; there's no need to run any `install` command ahead of time.
|
||||
|
||||
Yarn Plug'N'Play also uses zip files to store dependencies. This makes dependency loading [slower at runtime](https://twitter.com/jarredsumner/status/1458207919636287490), as random access reads on zip files tend to be slower than the equivalent disk lookup.
|
||||
{% /details %}
|
||||
|
||||
{% details summary="How is this different from what Deno does?" %}
|
||||
|
||||
Deno requires an `npm:` specifier before each npm `import`, lacks support for import maps via `compilerOptions.paths` in `tsconfig.json`, and has incomplete support for `package.json` settings. Unlike Deno, Bun does not currently support URL imports.
|
||||
{% /details %}
|
||||
|
||||
@@ -87,7 +87,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
|
||||
|
||||
- {% anchor id="node_fs" %} [`node:fs`](https://nodejs.org/api/fs.html) {% /anchor %}
|
||||
- 🟡
|
||||
- Missing `fs.constants` `fs.fdatasync{Sync}` `fs.opendir{Sync}` `fs.readv{Sync}` `fs.{watch|watchFile|unwatchFile}` `fs.writev{Sync}`.
|
||||
- Missing `fs.fdatasync{Sync}` `fs.opendir{Sync}` `fs.readv{Sync}` `fs.{watch|watchFile|unwatchFile}` `fs.writev{Sync}`.
|
||||
|
||||
---
|
||||
|
||||
@@ -183,6 +183,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
|
||||
|
||||
- {% anchor id="node_string_decoder" %} [`node:string_decoder`](https://nodejs.org/api/string_decoder.html) {% /anchor %}
|
||||
- 🟢
|
||||
- Fully implemented.
|
||||
|
||||
---
|
||||
|
||||
@@ -230,7 +231,7 @@ This page is updated regularly to reflect compatibility status of the latest ver
|
||||
|
||||
- {% anchor id="node_v8" %} [`node:v8`](https://nodejs.org/api/v8.html) {% /anchor %}
|
||||
- 🔴
|
||||
- Not implemented or planned. For profiling, use `bun:jsc` instead.
|
||||
- Not implemented or planned. For profiling, use [`bun:jsc`](/docs/project/benchmarking#bunjsc) instead.
|
||||
|
||||
---
|
||||
|
||||
125
docs/runtime/typescript.md
Normal file
125
docs/runtime/typescript.md
Normal file
@@ -0,0 +1,125 @@
|
||||
Bun treats TypeScript as a first-class citizen.
|
||||
|
||||
## Running `.ts` files
|
||||
|
||||
Bun can directly execute `.ts` and `.tsx` files just like vanilla JavaScript, with no extra configuration. If you import a `.ts` or `.tsx` file (or an `npm` module that exports these files), Bun internally transpiles it into JavaScript then executes the file.
|
||||
|
||||
**Note** — Similar to other build tools, Bun does not typecheck the files. Use [`tsc`](https://www.typescriptlang.org/docs/handbook/compiler-options.html) (the official TypeScript CLI) if you're looking to catch static type errors.
|
||||
|
||||
{% callout %}
|
||||
|
||||
**Is transpiling still necessary?** — Because Bun can directly execute TypeScript, you may not need to transpile your TypeScript to run in production. Bun internally transpiles every file it executes (both `.js` and `.ts`), so the additional overhead of directly executing your `.ts/.tsx` source files is negligible.
|
||||
|
||||
That said, if you are using Bun as a development tool but still targeting Node.js or browsers in production, you'll still need to transpile.
|
||||
|
||||
{% /callout %}
|
||||
|
||||
## Configuring `tsconfig.json`
|
||||
|
||||
Bun supports a number of features that TypeScript doesn't support by default, such as extensioned imports, top-level await, and `exports` conditions. It also implements global APIs like the `Bun`. To enable these features, your `tsconfig.json` must be configured properly.
|
||||
|
||||
{% callout %}
|
||||
If you initialized your project with `bun init`, everything is already configured properly.
|
||||
{% /callout %}
|
||||
|
||||
To get started, install the `bun-types` package.
|
||||
|
||||
```sh
|
||||
$ bun add -d bun-types # dev dependency
|
||||
```
|
||||
|
||||
If you're using a canary build of Bun, use the `canary` tag. The canary package is updated on every commit to the `main` branch.
|
||||
|
||||
```sh
|
||||
$ bun add -d bun-types@canary
|
||||
```
|
||||
|
||||
<!-- ### Quick setup
|
||||
|
||||
{% callout %}
|
||||
|
||||
**Note** — This approach requires TypeScript 5.0 or later!
|
||||
|
||||
{% /callout %}
|
||||
|
||||
Add the following to your `tsconfig.json`.
|
||||
|
||||
```json-diff
|
||||
{
|
||||
+ "extends": ["bun-types"]
|
||||
// other options...
|
||||
}
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
**Note** — The `"extends"` field in your `tsconfig.json` can accept an array of values. If you're already using `"extends"`, just add `"bun-types"` to the array.
|
||||
{% /callout %}
|
||||
|
||||
That's it! You should be able to use Bun's full feature set without seeing any TypeScript compiler errors.
|
||||
|
||||
### Manual setup -->
|
||||
|
||||
### Recommended `compilerOptions`
|
||||
|
||||
These are the recommended `compilerOptions` for a Bun project.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"compilerOptions": {
|
||||
// add Bun type definitions
|
||||
"types": ["bun-types"],
|
||||
|
||||
// enable latest features
|
||||
"lib": ["esnext"],
|
||||
"module": "esnext",
|
||||
"target": "esnext",
|
||||
|
||||
// if TS 5.x+
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"moduleDetection": "force",
|
||||
// if TS 4.x or earlier
|
||||
"moduleResolution": "nodenext",
|
||||
|
||||
"jsx": "react-jsx", // support JSX
|
||||
"allowJs": true, // allow importing `.js` from `.ts`
|
||||
"esModuleInterop": true, // allow default imports for CommonJS modules
|
||||
|
||||
// best practices
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Path mapping
|
||||
|
||||
When resolving modules, Bun's runtime respects path mappings defined in [`compilerOptions.paths`](https://www.typescriptlang.org/tsconfig#paths) in your `tsconfig.json`. No other runtime does this.
|
||||
|
||||
Given the following `tsconfig.json`...
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"data": ["./data.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
...the import from `"data"` will work as expected.
|
||||
|
||||
{% codetabs %}
|
||||
|
||||
```ts#index.ts
|
||||
import { foo } from "data";
|
||||
console.log(foo); // => "Hello world!"
|
||||
```
|
||||
|
||||
```ts#data.ts
|
||||
export const foo = "Hello world!"
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
@@ -1,22 +1,33 @@
|
||||
Many web APIs aren't relevant in the context of a server-first runtime like Bun, such as the [DOM API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API#html_dom_api_interfaces), [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), and [`History`](https://developer.mozilla.org/en-US/docs/Web/API/History_API). Many others, though, are broadly useful outside of the browser context; when possible, Bun implements these Web-standard APIs instead of introducing new APIs.
|
||||
Some Web APIs aren't relevant in the context of a server-first runtime like Bun, such as the [DOM API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API#html_dom_api_interfaces) or [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API). Many others, though, are broadly useful outside of the browser context; when possible, Bun implements these Web-standard APIs instead of introducing new APIs.
|
||||
|
||||
The following Web APIs are partially or completely supported.
|
||||
|
||||
## Globals
|
||||
|
||||
{% table %}
|
||||
|
||||
---
|
||||
|
||||
- Crypto
|
||||
- [`crypto`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)
|
||||
[`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey)
|
||||
- HTTP
|
||||
- [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
|
||||
|
||||
---
|
||||
|
||||
- Debugging
|
||||
- URLs
|
||||
- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
|
||||
|
||||
- [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console)[`performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance)
|
||||
---
|
||||
|
||||
- Streams
|
||||
- [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream) [`ByteLengthQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/ByteLengthQueuingStrategy) [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy) and associated classes
|
||||
|
||||
---
|
||||
|
||||
- Blob
|
||||
- [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
|
||||
|
||||
---
|
||||
|
||||
- WebSockets
|
||||
- [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
|
||||
|
||||
---
|
||||
|
||||
@@ -35,8 +46,15 @@ The following Web APIs are partially or completely supported.
|
||||
|
||||
---
|
||||
|
||||
- HTTP
|
||||
- [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
|
||||
- Crypto
|
||||
- [`crypto`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)
|
||||
[`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey)
|
||||
|
||||
---
|
||||
|
||||
- Debugging
|
||||
|
||||
- [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console) [`performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance)
|
||||
|
||||
---
|
||||
|
||||
@@ -52,15 +70,12 @@ The following Web APIs are partially or completely supported.
|
||||
---
|
||||
|
||||
- User interaction
|
||||
- [`alert`](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert) [`confirm`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm) [`prompt`](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt)
|
||||
- [`alert`](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert) [`confirm`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm) [`prompt`](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt) (intended for interactive CLIs)
|
||||
|
||||
<!-- - Blocking. Prints the alert message to terminal and awaits `[ENTER]` before proceeding. -->
|
||||
<!-- - Blocking. Prints confirmation message and awaits `[y/N]` input from user. Returns `true` if user entered `y` or `Y`, `false` otherwise.
|
||||
- Blocking. Prints prompt message and awaits user input. Returns the user input as a string. -->
|
||||
|
||||
- Blob
|
||||
- [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
|
||||
|
||||
---
|
||||
|
||||
- Realms
|
||||
@@ -74,227 +89,4 @@ The following Web APIs are partially or completely supported.
|
||||
|
||||
---
|
||||
|
||||
- WebSockets
|
||||
- [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
|
||||
|
||||
---
|
||||
|
||||
- URLs
|
||||
- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
|
||||
|
||||
---
|
||||
|
||||
- Streams
|
||||
- [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream) [`ByteLengthQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/ByteLengthQueuingStrategy) [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy) plus associated `*Reader`, `*Writer`, and `*Controller` classes.
|
||||
|
||||
<!-- ## Globals
|
||||
|
||||
{% table %}
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
- [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console)
|
||||
|
||||
---
|
||||
|
||||
- [`crypto`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto)
|
||||
|
||||
---
|
||||
|
||||
- [`performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance)
|
||||
|
||||
{% /table %}
|
||||
|
||||
## Functions
|
||||
|
||||
{% table %}
|
||||
|
||||
- [`atob`](https://developer.mozilla.org/en-US/docs/Web/API/atob)
|
||||
|
||||
---
|
||||
|
||||
- [`btoa`](https://developer.mozilla.org/en-US/docs/Web/API/btoa)
|
||||
|
||||
---
|
||||
|
||||
- [`clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval)
|
||||
|
||||
---
|
||||
|
||||
- [`clearTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout)
|
||||
|
||||
---
|
||||
|
||||
- [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch)
|
||||
|
||||
---
|
||||
|
||||
- [`queueMicrotask`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
|
||||
|
||||
---
|
||||
|
||||
- [`reportError`](https://developer.mozilla.org/en-US/docs/Web/API/reportError)
|
||||
|
||||
---
|
||||
|
||||
- [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval)
|
||||
|
||||
---
|
||||
|
||||
- [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout)
|
||||
|
||||
---
|
||||
|
||||
- [`alert`](https://developer.mozilla.org/en-US/docs/Web/API/alert)
|
||||
- Blocking. Prints the alert message to terminal and awaits `[ENTER]` before proceeding.
|
||||
|
||||
---
|
||||
|
||||
- [`confirm`](https://developer.mozilla.org/en-US/docs/Web/API/confirm)
|
||||
- Blocking. Prints confirmation message and awaits `[y/N]` input from user. Returns `true` if user entered `y` or `Y`, `false` otherwise.
|
||||
|
||||
---
|
||||
|
||||
- [`prompt`](https://developer.mozilla.org/en-US/docs/Web/API/prompt)
|
||||
- Blocking. Prints prompt message and awaits user input. Returns the user input as a string.
|
||||
|
||||
---
|
||||
|
||||
- [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console)
|
||||
|
||||
{% /table %}
|
||||
|
||||
## Classes
|
||||
|
||||
{% table %}
|
||||
|
||||
---
|
||||
|
||||
- [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
|
||||
|
||||
---
|
||||
|
||||
- [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
||||
|
||||
---
|
||||
|
||||
- [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
|
||||
|
||||
---
|
||||
|
||||
- [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) and [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder)
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
- [`ShadowRealm`](https://github.com/tc39/proposal-shadowrealm)
|
||||
- A ["better `eval`](https://2ality.com/2022/04/shadow-realms.html). Currently a Stage 3 TC39 proposal
|
||||
|
||||
---
|
||||
|
||||
- [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers)
|
||||
|
||||
---
|
||||
|
||||
- [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget)
|
||||
|
||||
---
|
||||
|
||||
- [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event)
|
||||
|
||||
---
|
||||
|
||||
- [`ErrorEvent`](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent)
|
||||
|
||||
---
|
||||
|
||||
- [`CloseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent)
|
||||
|
||||
---
|
||||
|
||||
- [`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent)
|
||||
|
||||
---
|
||||
|
||||
- [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
|
||||
|
||||
---
|
||||
|
||||
- [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
|
||||
|
||||
---
|
||||
|
||||
- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL)
|
||||
|
||||
---
|
||||
|
||||
- [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)
|
||||
|
||||
---
|
||||
|
||||
- [`Loader`](https://developer.mozilla.org/en-US/docs/Web/API/Loader)
|
||||
|
||||
---
|
||||
|
||||
- [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
|
||||
|
||||
---
|
||||
|
||||
- [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
|
||||
|
||||
---
|
||||
|
||||
- [`ByteLengthQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/ByteLengthQueuingStrategy)
|
||||
|
||||
---
|
||||
|
||||
- [`ReadableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultController)
|
||||
|
||||
---
|
||||
|
||||
- [`ReadableStreamDefaultReader`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader)
|
||||
|
||||
---
|
||||
|
||||
- [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream)
|
||||
|
||||
---
|
||||
|
||||
- [`WritableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultController)
|
||||
|
||||
---
|
||||
|
||||
- [`WritableStreamDefaultWriter`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter)
|
||||
|
||||
---
|
||||
|
||||
- [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream)
|
||||
|
||||
---
|
||||
|
||||
- [`TransformStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStreamDefaultController)
|
||||
|
||||
---
|
||||
|
||||
- [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy)
|
||||
|
||||
---
|
||||
|
||||
- [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)
|
||||
|
||||
---
|
||||
|
||||
- [`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey)
|
||||
|
||||
---
|
||||
|
||||
- [`ResolveError`](https://developer.mozilla.org/en-US/docs/Web/API/ResolveError)
|
||||
|
||||
---
|
||||
|
||||
- [`BuildError`](https://developer.mozilla.org/en-US/docs/Web/API/BuildError)
|
||||
|
||||
{% /table %} -->
|
||||
|
||||
256
docs/templates.md
Normal file
256
docs/templates.md
Normal file
@@ -0,0 +1,256 @@
|
||||
## `bun init`
|
||||
|
||||
Scaffold an empty project with the interactive `bun init` command.
|
||||
|
||||
```bash
|
||||
$ bun init
|
||||
bun init helps you get started with a minimal project and tries to
|
||||
guess sensible defaults. Press ^C anytime to quit.
|
||||
|
||||
package name (quickstart):
|
||||
entry point (index.ts):
|
||||
|
||||
Done! A package.json file was saved in the current directory.
|
||||
+ index.ts
|
||||
+ .gitignore
|
||||
+ tsconfig.json (for editor auto-complete)
|
||||
+ README.md
|
||||
|
||||
To get started, run:
|
||||
bun run index.ts
|
||||
```
|
||||
|
||||
Press `enter` to accept the default answer for each prompt, or pass the `-y` flag to auto-accept the defaults.
|
||||
|
||||
## `bun create`
|
||||
|
||||
Template a new Bun project with `bun create`.
|
||||
|
||||
```bash
|
||||
$ bun create <template> <destination>
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
**Note** — You don’t need `bun create` to use Bun. You don’t need any configuration at all. This command exists to make getting started a bit quicker and easier.
|
||||
{% /callout %}
|
||||
|
||||
A template can take a number of forms:
|
||||
|
||||
```bash
|
||||
$ bun create <template> # an official template (remote)
|
||||
$ bun create <username>/<repo> # a GitHub repo (remote)
|
||||
$ bun create <local-template> # a custom template (local)
|
||||
```
|
||||
|
||||
Running `bun create` performs the following steps:
|
||||
|
||||
- Download the template (remote templates only)
|
||||
- Copy all template files into the destination folder. By default Bun will _not overwrite_ any existing files. Use the `--force` flag to overwrite existing files.
|
||||
- Install dependencies with `bun install`.
|
||||
- Initialize a fresh Git repo. Opt out with the `--no-git` flag.
|
||||
- Run the template's configured `start` script, if defined.
|
||||
|
||||
### Official templates
|
||||
|
||||
The following official templates are available.
|
||||
|
||||
```bash
|
||||
bun create next ./myapp
|
||||
bun create react ./myapp
|
||||
bun create svelte-kit ./myapp
|
||||
bun create elysia ./myapp
|
||||
bun create hono ./myapp
|
||||
bun create kingworld ./myapp
|
||||
```
|
||||
|
||||
Each of these corresponds to a directory in the [bun-community/create-templates](https://github.com/bun-community/create-templates) repo. If you think a major framework is missing, please open a PR there. This list will change over time as additional examples are added. To see an up-to-date list, run `bun create` with no arguments.
|
||||
|
||||
```bash
|
||||
$ bun create
|
||||
Welcome to bun! Create a new project by pasting any of the following:
|
||||
<list of templates>
|
||||
```
|
||||
|
||||
{% callout %}
|
||||
⚡️ **Speed** — At the time of writing, `bun create react app` runs ~11x faster on a M1 Macbook Pro than `yarn create react-app app`.
|
||||
{% /callout %}
|
||||
|
||||
### GitHub repos
|
||||
|
||||
A template of the form `<username>/<repo>` will be downloaded from GitHub.
|
||||
|
||||
```bash
|
||||
$ bun create ahfarmer/calculator ./myapp
|
||||
```
|
||||
|
||||
Complete GitHub URLs will also work:
|
||||
|
||||
```bash
|
||||
$ bun create github.com/ahfarmer/calculator ./myapp
|
||||
$ bun create https://github.com/ahfarmer/calculator ./myapp
|
||||
```
|
||||
|
||||
Bun installs the files as they currently exist current default branch (usually `main` or `master`). Unlike `git clone` it doesn't download the commit history or configure a remote.
|
||||
|
||||
### Local templates
|
||||
|
||||
{% callout %}
|
||||
**⚠️ Warning** — Unlike remote templates, running `bun create` with a local template will delete the entire destination folder if it already exists! Be careful.
|
||||
{% /callout %}
|
||||
Bun's templater can be extended to support custom templates defined on your local file system. These templates should live in one of the following directories:
|
||||
|
||||
- `$HOME/.bun-create/<name>`: global templates
|
||||
- `<project root>/.bun-create/<name>`: project-specific templates
|
||||
|
||||
{% callout %}
|
||||
**Note** — You can customize the global template path by setting the `BUN_CREATE_DIR` environment variable.
|
||||
{% /callout %}
|
||||
|
||||
To create a local template, navigate to `$HOME/.bun-create` and create a new directory with the desired name of your template.
|
||||
|
||||
```bash
|
||||
$ cd $HOME/.bun-create
|
||||
$ mkdir foo
|
||||
$ cd foo
|
||||
```
|
||||
|
||||
Then, create a `package.json` file in that directory with the following contents:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "foo"
|
||||
}
|
||||
```
|
||||
|
||||
You can run `bun create foo` elsewhere on your file system to verify that Bun is correctly finding your local template.
|
||||
|
||||
{% table %}
|
||||
|
||||
---
|
||||
|
||||
- `postinstall`
|
||||
- runs after installing dependencies
|
||||
|
||||
---
|
||||
|
||||
- `preinstall`
|
||||
- runs before installing dependencies
|
||||
|
||||
<!-- ---
|
||||
|
||||
- `start`
|
||||
- a command to auto-start the application -->
|
||||
|
||||
{% /table %}
|
||||
|
||||
Each of these can correspond to a string or array of strings. An array of commands will be executed in order. Here is an example:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "@bun-examples/simplereact",
|
||||
"version": "0.0.1",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
},
|
||||
"bun-create": {
|
||||
"preinstall": "echo 'Installing...'", // a single command
|
||||
"postinstall": ["echo 'Done!'"], // an array of commands
|
||||
"start": "bun run echo 'Hello world!'"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When cloning a template, `bun create` will automatically remove the `"bun-create"` section from `package.json` before writing it to the destination folder.
|
||||
|
||||
### Reference
|
||||
|
||||
#### CLI flags
|
||||
|
||||
{% table %}
|
||||
|
||||
- Flag
|
||||
- Description
|
||||
|
||||
---
|
||||
|
||||
- `--force`
|
||||
- Overwrite existing files
|
||||
|
||||
---
|
||||
|
||||
- `--no-install`
|
||||
- Skip installing `node_modules` & tasks
|
||||
|
||||
---
|
||||
|
||||
- `--no-git`
|
||||
- Don’t initialize a git repository
|
||||
|
||||
---
|
||||
|
||||
- `--open`
|
||||
- Start & open in-browser after finish
|
||||
|
||||
{% /table %}
|
||||
|
||||
#### Environment variables
|
||||
|
||||
{% table %}
|
||||
|
||||
- Name
|
||||
- Description
|
||||
|
||||
---
|
||||
|
||||
- `GITHUB_API_DOMAIN`
|
||||
- If you’re using a GitHub enterprise or a proxy, you can customize the GitHub domain Bun pings for downloads
|
||||
|
||||
---
|
||||
|
||||
- `GITHUB_API_TOKEN`
|
||||
- This lets `bun create` work with private repositories or if you get rate-limited
|
||||
|
||||
{% /table %}
|
||||
|
||||
{% details summary="How `bun create` works" %}
|
||||
|
||||
When you run `bun create ${template} ${destination}`, here’s what happens:
|
||||
|
||||
IF remote template
|
||||
|
||||
1. GET `registry.npmjs.org/@bun-examples/${template}/latest` and parse it
|
||||
2. GET `registry.npmjs.org/@bun-examples/${template}/-/${template}-${latestVersion}.tgz`
|
||||
3. Decompress & extract `${template}-${latestVersion}.tgz` into `${destination}`
|
||||
|
||||
- If there are files that would overwrite, warn and exit unless `--force` is passed
|
||||
|
||||
IF GitHub repo
|
||||
|
||||
1. Download the tarball from GitHub’s API
|
||||
2. Decompress & extract into `${destination}`
|
||||
|
||||
- If there are files that would overwrite, warn and exit unless `--force` is passed
|
||||
|
||||
ELSE IF local template
|
||||
|
||||
1. Open local template folder
|
||||
2. Delete destination directory recursively
|
||||
3. Copy files recursively using the fastest system calls available (on macOS `fcopyfile` and Linux, `copy_file_range`). Do not copy or traverse into `node_modules` folder if exists (this alone makes it faster than `cp`)
|
||||
|
||||
4. Parse the `package.json` (again!), update `name` to be `${basename(destination)}`, remove the `bun-create` section from the `package.json` and save the updated `package.json` to disk.
|
||||
- IF Next.js is detected, add `bun-framework-next` to the list of dependencies
|
||||
- IF Create React App is detected, add the entry point in /src/index.{js,jsx,ts,tsx} to `public/index.html`
|
||||
- IF Relay is detected, add `bun-macro-relay` so that Relay works
|
||||
5. Auto-detect the npm client, preferring `pnpm`, `yarn` (v1), and lastly `npm`
|
||||
6. Run any tasks defined in `"bun-create": { "preinstall" }` with the npm client
|
||||
7. Run `${npmClient} install` unless `--no-install` is passed OR no dependencies are in package.json
|
||||
8. Run any tasks defined in `"bun-create": { "preinstall" }` with the npm client
|
||||
9. Run `git init; git add -A .; git commit -am "Initial Commit";`
|
||||
|
||||
- Rename `gitignore` to `.gitignore`. NPM automatically removes `.gitignore` files from appearing in packages.
|
||||
- If there are dependencies, this runs in a separate thread concurrently while node_modules are being installed
|
||||
- Using libgit2 if available was tested and performed 3x slower in microbenchmarks
|
||||
|
||||
{% /details %}
|
||||
357
docs/test/writing.md
Normal file
357
docs/test/writing.md
Normal file
@@ -0,0 +1,357 @@
|
||||
Define tests with a Jest-like API imported from the built-in `bun:test` module. Long term, Bun aims for complete Jest compatibility; at the moment, a [limited set](#matchers) of `expect` matchers are supported.
|
||||
|
||||
## Basic usage
|
||||
|
||||
To define a simple test:
|
||||
|
||||
```ts#math.test.ts
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
test("2 + 2", () => {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
```
|
||||
|
||||
Tests can be grouped into suites with `describe`.
|
||||
|
||||
```ts#math.test.ts
|
||||
import { expect, test, describe } from "bun:test";
|
||||
|
||||
describe("arithmetic", () => {
|
||||
test("2 + 2", () => {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
|
||||
test("2 * 2", () => {
|
||||
expect(2 * 2).toBe(4);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Tests can be `async`.
|
||||
|
||||
```ts
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
test("2 * 2", async () => {
|
||||
const result = await Promise.resolve(2 * 2);
|
||||
expect(result).toEqual(4);
|
||||
});
|
||||
```
|
||||
|
||||
Alternatively, use the `done` callback to signal completion. If you include the `done` callback as a parameter in your test definition, you _must_ call it or the test will hang.
|
||||
|
||||
```ts
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
test("2 * 2", done => {
|
||||
Promise.resolve(2 * 2).then(result => {
|
||||
expect(result).toEqual(4);
|
||||
done();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Skip individual tests with `test.skip`.
|
||||
|
||||
```ts
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
test.skip("wat", () => {
|
||||
// TODO: fix this
|
||||
expect(0.1 + 0.2).toEqual(0.3);
|
||||
});
|
||||
```
|
||||
|
||||
## Setup and teardown
|
||||
|
||||
Perform per-test setup and teardown logic with `beforeEach` and `afterEach`.
|
||||
|
||||
```ts
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
beforeEach(() => {
|
||||
console.log("running test.");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
console.log("done with test.");
|
||||
});
|
||||
|
||||
// tests...
|
||||
```
|
||||
|
||||
Perform per-scope setup and teardown logic with `beforeAll` and `afterAll`. At the top-level, the _scope_ is the current file; in a `describe` block, the scope is the block itself.
|
||||
|
||||
```ts
|
||||
import { expect, test, beforeAll, afterAll } from "bun:test";
|
||||
|
||||
let db: Database;
|
||||
beforeAll(() => {
|
||||
// connect to database
|
||||
db = initializeDatabase();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
// close connection
|
||||
db.close();
|
||||
});
|
||||
|
||||
// tests...
|
||||
```
|
||||
|
||||
## Matchers
|
||||
|
||||
Bun implements the following matchers. Full Jest compatibility is on the roadmap; track progress [here](https://github.com/oven-sh/bun/issues/1825).
|
||||
|
||||
{% table %}
|
||||
|
||||
- 🟢
|
||||
- [`.not`](https://jestjs.io/docs/expect#not)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBe()`](https://jestjs.io/docs/expect#tobevalue)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toEqual()`](https://jestjs.io/docs/expect#toequalvalue)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBeNull()`](https://jestjs.io/docs/expect#tobenull)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBeUndefined()`](https://jestjs.io/docs/expect#tobeundefined)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBeNaN()`](https://jestjs.io/docs/expect#tobenan)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBeDefined()`](https://jestjs.io/docs/expect#tobedefined)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBeFalsy()`](https://jestjs.io/docs/expect#tobefalsy)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBeTruthy()`](https://jestjs.io/docs/expect#tobetruthy)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toContain()`](https://jestjs.io/docs/expect#tocontainitem)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toStrictEqual()`](https://jestjs.io/docs/expect#tostrictequalvalue)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toThrow()`](https://jestjs.io/docs/expect#tothrowerror)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toHaveLength()`](https://jestjs.io/docs/expect#tohavelengthnumber)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toHaveProperty()`](https://jestjs.io/docs/expect#tohavepropertykeypath-value)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.extend`](https://jestjs.io/docs/expect#expectextendmatchers)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.anything()`](https://jestjs.io/docs/expect#expectanything)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.any()`](https://jestjs.io/docs/expect#expectanyconstructor)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.arrayContaining()`](https://jestjs.io/docs/expect#expectarraycontainingarray)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.assertions()`](https://jestjs.io/docs/expect#expectassertionsnumber)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.closeTo()`](https://jestjs.io/docs/expect#expectclosetonumber-numdigits)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.hasAssertions()`](https://jestjs.io/docs/expect#expecthasassertions)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.objectContaining()`](https://jestjs.io/docs/expect#expectobjectcontainingobject)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.stringContaining()`](https://jestjs.io/docs/expect#expectstringcontainingstring)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.stringMatching()`](https://jestjs.io/docs/expect#expectstringmatchingstring--regexp)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.addSnapshotSerializer()`](https://jestjs.io/docs/expect#expectaddsnapshotserializerserializer)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.resolves()`](https://jestjs.io/docs/expect#resolves)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.rejects()`](https://jestjs.io/docs/expect#rejects)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toHaveBeenCalled()`](https://jestjs.io/docs/expect#tohavebeencalled)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toHaveBeenCalledTimes()`](https://jestjs.io/docs/expect#tohavebeencalledtimesnumber)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toHaveBeenCalledWith()`](https://jestjs.io/docs/expect#tohavebeencalledwitharg1-arg2-)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toHaveBeenLastCalledWith()`](https://jestjs.io/docs/expect#tohavebeenlastcalledwitharg1-arg2-)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toHaveBeenNthCalledWith()`](https://jestjs.io/docs/expect#tohavebeennthcalledwithnthcall-arg1-arg2-)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toHaveReturned()`](https://jestjs.io/docs/expect#tohavereturned)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toHaveReturnedTimes()`](https://jestjs.io/docs/expect#tohavereturnedtimesnumber)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toHaveReturnedWith()`](https://jestjs.io/docs/expect#tohavereturnedwithvalue)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toHaveLastReturnedWith()`](https://jestjs.io/docs/expect#tohavelastreturnedwithvalue)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toHaveNthReturnedWith()`](https://jestjs.io/docs/expect#tohaventhreturnedwithnthcall-value)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toBeCloseTo()`](https://jestjs.io/docs/expect#tobeclosetonumber-numdigits)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBeGreaterThan()`](https://jestjs.io/docs/expect#tobegreaterthannumber--bigint)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBeGreaterThanOrEqual()`](https://jestjs.io/docs/expect#tobegreaterthanorequalnumber--bigint)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBeLessThan()`](https://jestjs.io/docs/expect#tobelessthannumber--bigint)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBeLessThanOrEqual()`](https://jestjs.io/docs/expect#tobelessthanorequalnumber--bigint)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toBeInstanceOf()`](https://jestjs.io/docs/expect#tobeinstanceofclass) (Bun v0.5.8+)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toContainEqual()`](https://jestjs.io/docs/expect#tocontainequalitem)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toMatch()`](https://jestjs.io/docs/expect#tomatchregexp--string)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toMatchObject()`](https://jestjs.io/docs/expect#tomatchobjectobject)
|
||||
|
||||
---
|
||||
|
||||
- 🟢
|
||||
- [`.toMatchSnapshot()`](https://jestjs.io/docs/expect#tomatchsnapshotpropertymatchers-hint) (Bun v0.5.8+)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toMatchInlineSnapshot()`](https://jestjs.io/docs/expect#tomatchinlinesnapshotpropertymatchers-inlinesnapshot)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toThrowErrorMatchingSnapshot()`](https://jestjs.io/docs/expect#tothrowerrormatchingsnapshothint)
|
||||
|
||||
---
|
||||
|
||||
- 🔴
|
||||
- [`.toThrowErrorMatchingInlineSnapshot()`](https://jestjs.io/docs/expect#tothrowerrormatchinginlinesnapshotinlinesnapshot)
|
||||
|
||||
{% /table %}
|
||||
@@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
|
||||
const path_handler = @import("../src/resolver/resolve_path.zig");
|
||||
const bun = @import("bun");
|
||||
const bun = @import("root").bun;
|
||||
const string = bun.string;
|
||||
const Output = bun.Output;
|
||||
const Global = bun.Global;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const bun = @import("bun");
|
||||
const bun = @import("root").bun;
|
||||
const string = bun.string;
|
||||
const Output = bun.Output;
|
||||
const Global = bun.Global;
|
||||
@@ -9,18 +9,18 @@ const MutableString = bun.MutableString;
|
||||
const stringZ = bun.stringZ;
|
||||
const default_allocator = bun.default_allocator;
|
||||
const C = bun.C;
|
||||
pub usingnamespace @import("bun");
|
||||
pub usingnamespace @import("root").bun;
|
||||
|
||||
const clap = bun.clap;
|
||||
|
||||
const URL = @import("../src/url.zig").URL;
|
||||
const Headers = @import("bun").HTTP.Headers;
|
||||
const Headers = @import("root").bun.HTTP.Headers;
|
||||
const Method = @import("../src/http/method.zig").Method;
|
||||
const ColonListType = @import("../src/cli/colon_list_type.zig").ColonListType;
|
||||
const HeadersTuple = ColonListType(string, noop_resolver);
|
||||
const path_handler = @import("../src/resolver/resolve_path.zig");
|
||||
const HTTPThread = @import("bun").HTTP.HTTPThread;
|
||||
const HTTP = @import("bun").HTTP;
|
||||
const HTTPThread = @import("root").bun.HTTP.HTTPThread;
|
||||
const HTTP = @import("root").bun.HTTP;
|
||||
fn noop_resolver(in: string) !string {
|
||||
return in;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const bun = @import("bun");
|
||||
const bun = @import("root").bun;
|
||||
const string = bun.string;
|
||||
const Output = bun.Output;
|
||||
const Global = bun.Global;
|
||||
@@ -177,7 +177,7 @@ pub const Arguments = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const HTTP = @import("bun").HTTP;
|
||||
const HTTP = @import("root").bun.HTTP;
|
||||
const NetworkThread = HTTP.NetworkThread;
|
||||
|
||||
var stdout_: std.fs.File = undefined;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user