bun-types 1.3.2-canary.20251106T140813 → 1.3.2-canary.20251108T140624
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.d.ts +102 -6
- package/docs/bundler/bytecode.mdx +465 -0
- package/docs/bundler/css.mdx +1024 -0
- package/docs/bundler/esbuild.mdx +253 -0
- package/docs/bundler/executables.mdx +535 -0
- package/docs/bundler/fullstack.mdx +1064 -0
- package/docs/bundler/hot-reloading.mdx +229 -0
- package/docs/bundler/html-static.mdx +386 -0
- package/docs/bundler/index.mdx +1499 -0
- package/docs/bundler/loaders.mdx +356 -0
- package/docs/bundler/macros.mdx +328 -0
- package/docs/bundler/minifier.mdx +1306 -0
- package/docs/bundler/plugins.mdx +411 -0
- package/docs/feedback.mdx +85 -0
- package/docs/guides/binary/arraybuffer-to-array.mdx +29 -0
- package/docs/guides/binary/arraybuffer-to-blob.mdx +26 -0
- package/docs/guides/binary/arraybuffer-to-buffer.mdx +27 -0
- package/docs/guides/binary/arraybuffer-to-string.mdx +17 -0
- package/docs/guides/binary/arraybuffer-to-typedarray.mdx +41 -0
- package/docs/guides/binary/blob-to-arraybuffer.mdx +16 -0
- package/docs/guides/binary/blob-to-dataview.mdx +16 -0
- package/docs/guides/binary/blob-to-stream.mdx +16 -0
- package/docs/guides/binary/blob-to-string.mdx +17 -0
- package/docs/guides/binary/blob-to-typedarray.mdx +16 -0
- package/docs/guides/binary/buffer-to-arraybuffer.mdx +16 -0
- package/docs/guides/binary/buffer-to-blob.mdx +16 -0
- package/docs/guides/binary/buffer-to-readablestream.mdx +43 -0
- package/docs/guides/binary/buffer-to-string.mdx +27 -0
- package/docs/guides/binary/buffer-to-typedarray.mdx +16 -0
- package/docs/guides/binary/dataview-to-string.mdx +17 -0
- package/docs/guides/binary/typedarray-to-arraybuffer.mdx +27 -0
- package/docs/guides/binary/typedarray-to-blob.mdx +18 -0
- package/docs/guides/binary/typedarray-to-buffer.mdx +16 -0
- package/docs/guides/binary/typedarray-to-dataview.mdx +16 -0
- package/docs/guides/binary/typedarray-to-readablestream.mdx +43 -0
- package/docs/guides/binary/typedarray-to-string.mdx +18 -0
- package/docs/guides/deployment/aws-lambda.mdx +204 -0
- package/docs/guides/deployment/digital-ocean.mdx +161 -0
- package/docs/guides/deployment/google-cloud-run.mdx +197 -0
- package/docs/guides/deployment/railway.mdx +145 -0
- package/docs/guides/deployment/render.mdx +82 -0
- package/docs/guides/deployment/vercel.mdx +99 -0
- package/docs/guides/ecosystem/astro.mdx +82 -0
- package/docs/guides/ecosystem/discordjs.mdx +80 -0
- package/docs/guides/ecosystem/docker.mdx +151 -0
- package/docs/guides/ecosystem/drizzle.mdx +195 -0
- package/docs/guides/ecosystem/edgedb.mdx +257 -0
- package/docs/guides/ecosystem/elysia.mdx +31 -0
- package/docs/guides/ecosystem/express.mdx +43 -0
- package/docs/guides/ecosystem/hono.mdx +47 -0
- package/docs/guides/ecosystem/mongoose.mdx +92 -0
- package/docs/guides/ecosystem/neon-drizzle.mdx +234 -0
- package/docs/guides/ecosystem/neon-serverless-postgres.mdx +60 -0
- package/docs/guides/ecosystem/nextjs.mdx +57 -0
- package/docs/guides/ecosystem/nuxt.mdx +90 -0
- package/docs/guides/ecosystem/pm2.mdx +55 -0
- package/docs/guides/ecosystem/prisma-postgres.mdx +169 -0
- package/docs/guides/ecosystem/prisma.mdx +164 -0
- package/docs/guides/ecosystem/qwik.mdx +114 -0
- package/docs/guides/ecosystem/react.mdx +52 -0
- package/docs/guides/ecosystem/remix.mdx +97 -0
- package/docs/guides/ecosystem/sentry.mdx +54 -0
- package/docs/guides/ecosystem/solidstart.mdx +66 -0
- package/docs/guides/ecosystem/ssr-react.mdx +49 -0
- package/docs/guides/ecosystem/stric.mdx +54 -0
- package/docs/guides/ecosystem/sveltekit.mdx +138 -0
- package/docs/guides/ecosystem/systemd.mdx +114 -0
- package/docs/guides/ecosystem/upstash.mdx +87 -0
- package/docs/guides/ecosystem/vite.mdx +77 -0
- package/docs/guides/html-rewriter/extract-links.mdx +72 -0
- package/docs/guides/html-rewriter/extract-social-meta.mdx +97 -0
- package/docs/guides/http/cluster.mdx +69 -0
- package/docs/guides/http/fetch-unix.mdx +35 -0
- package/docs/guides/http/fetch.mdx +26 -0
- package/docs/guides/http/file-uploads.mdx +97 -0
- package/docs/guides/http/hot.mdx +28 -0
- package/docs/guides/http/proxy.mdx +26 -0
- package/docs/guides/http/server.mdx +48 -0
- package/docs/guides/http/simple.mdx +20 -0
- package/docs/guides/http/stream-file.mdx +50 -0
- package/docs/guides/http/stream-iterator.mdx +49 -0
- package/docs/guides/http/stream-node-streams-in-bun.mdx +22 -0
- package/docs/guides/http/tls.mdx +32 -0
- package/docs/guides/index.mdx +10 -0
- package/docs/guides/install/add-dev.mdx +28 -0
- package/docs/guides/install/add-git.mdx +38 -0
- package/docs/guides/install/add-optional.mdx +27 -0
- package/docs/guides/install/add-peer.mdx +45 -0
- package/docs/guides/install/add-tarball.mdx +35 -0
- package/docs/guides/install/add.mdx +44 -0
- package/docs/guides/install/azure-artifacts.mdx +76 -0
- package/docs/guides/install/cicd.mdx +43 -0
- package/docs/guides/install/custom-registry.mdx +32 -0
- package/docs/guides/install/from-npm-install-to-bun-install.mdx +230 -0
- package/docs/guides/install/git-diff-bun-lockfile.mdx +47 -0
- package/docs/guides/install/jfrog-artifactory.mdx +28 -0
- package/docs/guides/install/npm-alias.mdx +25 -0
- package/docs/guides/install/registry-scope.mdx +40 -0
- package/docs/guides/install/trusted.mdx +50 -0
- package/docs/guides/install/workspaces.mdx +70 -0
- package/docs/guides/install/yarnlock.mdx +50 -0
- package/docs/guides/process/argv.mdx +66 -0
- package/docs/guides/process/ctrl-c.mdx +18 -0
- package/docs/guides/process/ipc.mdx +69 -0
- package/docs/guides/process/nanoseconds.mdx +15 -0
- package/docs/guides/process/os-signals.mdx +41 -0
- package/docs/guides/process/spawn-stderr.mdx +34 -0
- package/docs/guides/process/spawn-stdout.mdx +28 -0
- package/docs/guides/process/spawn.mdx +43 -0
- package/docs/guides/process/stdin.mdx +62 -0
- package/docs/guides/read-file/arraybuffer.mdx +30 -0
- package/docs/guides/read-file/buffer.mdx +21 -0
- package/docs/guides/read-file/exists.mdx +18 -0
- package/docs/guides/read-file/json.mdx +19 -0
- package/docs/guides/read-file/mime.mdx +22 -0
- package/docs/guides/read-file/stream.mdx +28 -0
- package/docs/guides/read-file/string.mdx +24 -0
- package/docs/guides/read-file/uint8array.mdx +23 -0
- package/docs/guides/read-file/watch.mdx +66 -0
- package/docs/guides/runtime/build-time-constants.mdx +295 -0
- package/docs/guides/runtime/cicd.mdx +45 -0
- package/docs/guides/runtime/codesign-macos-executable.mdx +61 -0
- package/docs/guides/runtime/define-constant.mdx +149 -0
- package/docs/guides/runtime/delete-directory.mdx +39 -0
- package/docs/guides/runtime/delete-file.mdx +21 -0
- package/docs/guides/runtime/heap-snapshot.mdx +28 -0
- package/docs/guides/runtime/import-html.mdx +17 -0
- package/docs/guides/runtime/import-json.mdx +46 -0
- package/docs/guides/runtime/import-toml.mdx +32 -0
- package/docs/guides/runtime/import-yaml.mdx +104 -0
- package/docs/guides/runtime/read-env.mdx +37 -0
- package/docs/guides/runtime/set-env.mdx +51 -0
- package/docs/guides/runtime/shell.mdx +42 -0
- package/docs/guides/runtime/timezone.mdx +38 -0
- package/docs/guides/runtime/tsconfig-paths.mdx +31 -0
- package/docs/guides/runtime/typescript.mdx +51 -0
- package/docs/guides/runtime/vscode-debugger.mdx +48 -0
- package/docs/guides/runtime/web-debugger.mdx +103 -0
- package/docs/guides/streams/node-readable-to-arraybuffer.mdx +13 -0
- package/docs/guides/streams/node-readable-to-blob.mdx +13 -0
- package/docs/guides/streams/node-readable-to-json.mdx +14 -0
- package/docs/guides/streams/node-readable-to-string.mdx +14 -0
- package/docs/guides/streams/node-readable-to-uint8array.mdx +13 -0
- package/docs/guides/streams/to-array.mdx +16 -0
- package/docs/guides/streams/to-arraybuffer.mdx +16 -0
- package/docs/guides/streams/to-blob.mdx +16 -0
- package/docs/guides/streams/to-buffer.mdx +17 -0
- package/docs/guides/streams/to-json.mdx +16 -0
- package/docs/guides/streams/to-string.mdx +16 -0
- package/docs/guides/streams/to-typedarray.mdx +24 -0
- package/docs/guides/test/bail.mdx +24 -0
- package/docs/guides/test/coverage-threshold.mdx +67 -0
- package/docs/guides/test/coverage.mdx +49 -0
- package/docs/guides/test/happy-dom.mdx +73 -0
- package/docs/guides/test/migrate-from-jest.mdx +125 -0
- package/docs/guides/test/mock-clock.mdx +50 -0
- package/docs/guides/test/mock-functions.mdx +70 -0
- package/docs/guides/test/rerun-each.mdx +16 -0
- package/docs/guides/test/run-tests.mdx +116 -0
- package/docs/guides/test/skip-tests.mdx +43 -0
- package/docs/guides/test/snapshot.mdx +102 -0
- package/docs/guides/test/spy-on.mdx +49 -0
- package/docs/guides/test/svelte-test.mdx +113 -0
- package/docs/guides/test/testing-library.mdx +93 -0
- package/docs/guides/test/timeout.mdx +17 -0
- package/docs/guides/test/todo-tests.mdx +74 -0
- package/docs/guides/test/update-snapshots.mdx +49 -0
- package/docs/guides/test/watch-mode.mdx +24 -0
- package/docs/guides/util/base64.mdx +17 -0
- package/docs/guides/util/deep-equals.mdx +41 -0
- package/docs/guides/util/deflate.mdx +20 -0
- package/docs/guides/util/detect-bun.mdx +25 -0
- package/docs/guides/util/entrypoint.mdx +19 -0
- package/docs/guides/util/escape-html.mdx +24 -0
- package/docs/guides/util/file-url-to-path.mdx +16 -0
- package/docs/guides/util/gzip.mdx +20 -0
- package/docs/guides/util/hash-a-password.mdx +56 -0
- package/docs/guides/util/import-meta-dir.mdx +15 -0
- package/docs/guides/util/import-meta-file.mdx +15 -0
- package/docs/guides/util/import-meta-path.mdx +15 -0
- package/docs/guides/util/javascript-uuid.mdx +25 -0
- package/docs/guides/util/main.mdx +43 -0
- package/docs/guides/util/path-to-file-url.mdx +16 -0
- package/docs/guides/util/sleep.mdx +24 -0
- package/docs/guides/util/version.mdx +23 -0
- package/docs/guides/util/which-path-to-executable-bin.mdx +17 -0
- package/docs/guides/websocket/compression.mdx +33 -0
- package/docs/guides/websocket/context.mdx +74 -0
- package/docs/guides/websocket/pubsub.mdx +40 -0
- package/docs/guides/websocket/simple.mdx +35 -0
- package/docs/guides/write-file/append.mdx +54 -0
- package/docs/guides/write-file/basic.mdx +46 -0
- package/docs/guides/write-file/blob.mdx +30 -0
- package/docs/guides/write-file/cat.mdx +19 -0
- package/docs/guides/write-file/file-cp.mdx +18 -0
- package/docs/guides/write-file/filesink.mdx +54 -0
- package/docs/guides/write-file/response.mdx +19 -0
- package/docs/guides/write-file/stdout.mdx +23 -0
- package/docs/guides/write-file/stream.mdx +19 -0
- package/docs/guides/write-file/unlink.mdx +18 -0
- package/docs/index.mdx +133 -0
- package/docs/installation.mdx +365 -0
- package/docs/pm/bunx.mdx +83 -0
- package/docs/pm/catalogs.mdx +292 -0
- package/docs/pm/cli/add.mdx +179 -0
- package/docs/pm/cli/audit.mdx +60 -0
- package/docs/pm/cli/install.mdx +471 -0
- package/docs/pm/cli/link.mdx +48 -0
- package/docs/pm/cli/outdated.mdx +197 -0
- package/docs/pm/cli/patch.mdx +69 -0
- package/docs/pm/cli/pm.mdx +319 -0
- package/docs/pm/cli/publish.mdx +123 -0
- package/docs/pm/cli/remove.mdx +16 -0
- package/docs/pm/cli/update.mdx +140 -0
- package/docs/pm/cli/why.mdx +84 -0
- package/docs/pm/filter.mdx +102 -0
- package/docs/pm/global-cache.mdx +72 -0
- package/docs/pm/isolated-installs.mdx +205 -0
- package/docs/pm/lifecycle.mdx +57 -0
- package/docs/pm/lockfile.mdx +64 -0
- package/docs/pm/npmrc.mdx +111 -0
- package/docs/pm/overrides.mdx +83 -0
- package/docs/pm/scopes-registries.mdx +35 -0
- package/docs/pm/security-scanner-api.mdx +95 -0
- package/docs/pm/workspaces.mdx +109 -0
- package/docs/project/benchmarking.mdx +218 -0
- package/docs/project/bindgen.mdx +223 -0
- package/docs/project/building-windows.mdx +133 -0
- package/docs/project/contributing.mdx +343 -0
- package/docs/project/feedback.mdx +20 -0
- package/docs/project/license.mdx +78 -0
- package/docs/project/roadmap.mdx +8 -0
- package/docs/quickstart.mdx +240 -0
- package/docs/runtime/auto-install.mdx +97 -0
- package/docs/runtime/binary-data.mdx +846 -0
- package/docs/runtime/bun-apis.mdx +59 -0
- package/docs/runtime/bunfig.mdx +642 -0
- package/docs/runtime/c-compiler.mdx +204 -0
- package/docs/runtime/child-process.mdx +532 -0
- package/docs/runtime/color.mdx +267 -0
- package/docs/runtime/console.mdx +67 -0
- package/docs/runtime/cookies.mdx +454 -0
- package/docs/runtime/debugger.mdx +335 -0
- package/docs/runtime/environment-variables.mdx +214 -0
- package/docs/runtime/ffi.mdx +565 -0
- package/docs/runtime/file-io.mdx +306 -0
- package/docs/runtime/file-system-router.mdx +118 -0
- package/docs/runtime/file-types.mdx +354 -0
- package/docs/runtime/glob.mdx +181 -0
- package/docs/runtime/globals.mdx +72 -0
- package/docs/runtime/hashing.mdx +315 -0
- package/docs/runtime/html-rewriter.mdx +340 -0
- package/docs/runtime/http/cookies.mdx +79 -0
- package/docs/runtime/http/error-handling.mdx +40 -0
- package/docs/runtime/http/metrics.mdx +36 -0
- package/docs/runtime/http/routing.mdx +289 -0
- package/docs/runtime/http/server.mdx +647 -0
- package/docs/runtime/http/tls.mdx +101 -0
- package/docs/runtime/http/websockets.mdx +404 -0
- package/docs/runtime/index.mdx +223 -0
- package/docs/runtime/jsx.mdx +115 -0
- package/docs/runtime/module-resolution.mdx +342 -0
- package/docs/runtime/networking/dns.mdx +111 -0
- package/docs/runtime/networking/fetch.mdx +468 -0
- package/docs/runtime/networking/tcp.mdx +239 -0
- package/docs/runtime/networking/udp.mdx +129 -0
- package/docs/runtime/node-api.mdx +19 -0
- package/docs/runtime/nodejs-compat.mdx +468 -0
- package/docs/runtime/plugins.mdx +405 -0
- package/docs/runtime/redis.mdx +582 -0
- package/docs/runtime/s3.mdx +863 -0
- package/docs/runtime/secrets.mdx +336 -0
- package/docs/runtime/semver.mdx +57 -0
- package/docs/runtime/shell.mdx +637 -0
- package/docs/runtime/sql.mdx +1404 -0
- package/docs/runtime/sqlite.mdx +699 -0
- package/docs/runtime/streams.mdx +232 -0
- package/docs/runtime/templating/create.mdx +269 -0
- package/docs/runtime/templating/init.mdx +58 -0
- package/docs/runtime/transpiler.mdx +288 -0
- package/docs/runtime/typescript.mdx +58 -0
- package/docs/runtime/utils.mdx +922 -0
- package/docs/runtime/watch-mode.mdx +161 -0
- package/docs/runtime/web-apis.mdx +29 -0
- package/docs/runtime/workers.mdx +328 -0
- package/docs/runtime/yaml.mdx +469 -0
- package/docs/snippets/cli/add.mdx +166 -0
- package/docs/snippets/cli/build.mdx +196 -0
- package/docs/snippets/cli/feedback.mdx +17 -0
- package/docs/snippets/cli/init.mdx +84 -0
- package/docs/snippets/cli/install.mdx +173 -0
- package/docs/snippets/cli/link.mdx +163 -0
- package/docs/snippets/cli/outdated.mdx +140 -0
- package/docs/snippets/cli/patch.mdx +171 -0
- package/docs/snippets/cli/publish.mdx +198 -0
- package/docs/snippets/cli/remove.mdx +146 -0
- package/docs/snippets/cli/run.mdx +293 -0
- package/docs/snippets/cli/test.mdx +100 -0
- package/docs/snippets/cli/update.mdx +144 -0
- package/docs/snippets/product-card.mdx +32 -0
- package/docs/snippets/product-tiles.mdx +94 -0
- package/docs/test/code-coverage.mdx +409 -0
- package/docs/test/configuration.mdx +467 -0
- package/docs/test/dates-times.mdx +129 -0
- package/docs/test/discovery.mdx +90 -0
- package/docs/test/dom.mdx +226 -0
- package/docs/test/index.mdx +380 -0
- package/docs/test/lifecycle.mdx +348 -0
- package/docs/test/mocks.mdx +637 -0
- package/docs/test/reporters.mdx +117 -0
- package/docs/test/runtime-behavior.mdx +342 -0
- package/docs/test/snapshots.mdx +434 -0
- package/docs/test/writing-tests.mdx +635 -0
- package/docs/typescript.mdx +54 -0
- package/package.json +8 -6
- package/test.d.ts +2 -2
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Run Bun as a daemon with systemd
|
|
3
|
+
sidebarTitle: "systemd with Bun"
|
|
4
|
+
mode: center
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
[systemd](https://systemd.io) is an init system and service manager for Linux operating systems that manages the startup and control of system processes and services.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
To run a Bun application as a daemon using **systemd** you'll need to create a _service file_ in `/lib/systemd/system/`.
|
|
12
|
+
|
|
13
|
+
```sh terminal icon="terminal"
|
|
14
|
+
cd /lib/systemd/system
|
|
15
|
+
touch my-app.service
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
Here is a typical service file that runs an application on system start. You can use this as a template for your own service. Replace `YOUR_USER` with the name of the user you want to run the application as. To run as `root`, replace `YOUR_USER` with `root`, though this is generally not recommended for security reasons.
|
|
21
|
+
|
|
22
|
+
Refer to the [systemd documentation](https://www.freedesktop.org/software/systemd/man/systemd.service.html) for more information on each setting.
|
|
23
|
+
|
|
24
|
+
```ini my-app.service icon="file-code"
|
|
25
|
+
[Unit]
|
|
26
|
+
# describe the app
|
|
27
|
+
Description=My App
|
|
28
|
+
# start the app after the network is available
|
|
29
|
+
After=network.target
|
|
30
|
+
|
|
31
|
+
[Service]
|
|
32
|
+
# usually you'll use 'simple'
|
|
33
|
+
# one of https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=
|
|
34
|
+
Type=simple
|
|
35
|
+
# which user to use when starting the app
|
|
36
|
+
User=YOUR_USER
|
|
37
|
+
# path to your application's root directory
|
|
38
|
+
WorkingDirectory=/home/YOUR_USER/path/to/my-app
|
|
39
|
+
# the command to start the app
|
|
40
|
+
# requires absolute paths
|
|
41
|
+
ExecStart=/home/YOUR_USER/.bun/bin/bun run index.ts
|
|
42
|
+
# restart policy
|
|
43
|
+
# one of {no|on-success|on-failure|on-abnormal|on-watchdog|on-abort|always}
|
|
44
|
+
Restart=always
|
|
45
|
+
|
|
46
|
+
[Install]
|
|
47
|
+
# start the app automatically
|
|
48
|
+
WantedBy=multi-user.target
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
If your application starts a webserver, note that non-`root` users are not able to listen on ports 80 or 443 by default. To permanently allow Bun to listen on these ports when executed by a non-`root` user, use the following command. This step isn't necessary when running as `root`.
|
|
54
|
+
|
|
55
|
+
```bash terminal icon="terminal"
|
|
56
|
+
setcap CAP_NET_BIND_SERVICE=+eip ~/.bun/bin/bun
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
With the service file configured, you can now _enable_ the service. Once enabled, it will start automatically on reboot. This requires `sudo` permissions.
|
|
62
|
+
|
|
63
|
+
```bash terminal icon="terminal"
|
|
64
|
+
systemctl enable my-app
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
To start the service without rebooting, you can manually _start_ it.
|
|
70
|
+
|
|
71
|
+
```bash terminal icon="terminal"
|
|
72
|
+
systemctl start my-app
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
Check the status of your application with `systemctl status`. If you've started your app successfully, you should see something like this:
|
|
78
|
+
|
|
79
|
+
```bash terminal icon="terminal"
|
|
80
|
+
systemctl status my-app
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```txt
|
|
84
|
+
● my-app.service - My App
|
|
85
|
+
Loaded: loaded (/lib/systemd/system/my-app.service; enabled; preset: enabled)
|
|
86
|
+
Active: active (running) since Thu 2023-10-12 11:34:08 UTC; 1h 8min ago
|
|
87
|
+
Main PID: 309641 (bun)
|
|
88
|
+
Tasks: 3 (limit: 503)
|
|
89
|
+
Memory: 40.9M
|
|
90
|
+
CPU: 1.093s
|
|
91
|
+
CGroup: /system.slice/my-app.service
|
|
92
|
+
└─309641 /home/YOUR_USER/.bun/bin/bun run /home/YOUR_USER/application/index.ts
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
To update the service, edit the contents of the service file, then reload the daemon.
|
|
98
|
+
|
|
99
|
+
```bash terminal icon="terminal"
|
|
100
|
+
systemctl daemon-reload
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
For a complete guide on the service unit configuration, you can check [this page](https://www.freedesktop.org/software/systemd/man/systemd.service.html). Or refer to this cheatsheet of common commands:
|
|
106
|
+
|
|
107
|
+
```bash terminal icon="terminal"
|
|
108
|
+
systemctl daemon-reload # tell systemd that some files got changed
|
|
109
|
+
systemctl enable my-app # enable the app (to allow auto-start)
|
|
110
|
+
systemctl disable my-app # disable the app (turns off auto-start)
|
|
111
|
+
systemctl start my-app # start the app if is stopped
|
|
112
|
+
systemctl stop my-app # stop the app
|
|
113
|
+
systemctl restart my-app # restart the app
|
|
114
|
+
```
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Bun Redis with Upstash
|
|
3
|
+
sidebarTitle: Upstash with Bun
|
|
4
|
+
mode: center
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
[Upstash](https://upstash.com/) is a fully managed Redis database as a service. Upstash works with the Redis® API, which means you can use Bun's native Redis client to connect to your Upstash database.
|
|
8
|
+
|
|
9
|
+
<Note>TLS is enabled by default for all Upstash Redis databases.</Note>
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<Steps>
|
|
14
|
+
<Step title="Create a new project">
|
|
15
|
+
Create a new project by running `bun init`:
|
|
16
|
+
|
|
17
|
+
```sh terminal icon="terminal"
|
|
18
|
+
bun init bun-upstash-redis
|
|
19
|
+
cd bun-upstash-redis
|
|
20
|
+
```
|
|
21
|
+
</Step>
|
|
22
|
+
<Step title="Create an Upstash Redis database">
|
|
23
|
+
Go to the [Upstash dashboard](https://console.upstash.com/) and create a new Redis database. After completing the [getting started guide](https://upstash.com/docs/redis/overall/getstarted), you'll see your database page with connection information.
|
|
24
|
+
|
|
25
|
+
The database page displays two connection methods; HTTP and TLS. For Bun's Redis client, you need the **TLS** connection details. This URL starts with `rediss://`.
|
|
26
|
+
|
|
27
|
+
<Frame>
|
|
28
|
+

|
|
29
|
+
</Frame>
|
|
30
|
+
|
|
31
|
+
</Step>
|
|
32
|
+
<Step title="Connect using Bun's Redis client">
|
|
33
|
+
You can connect to Upstash by setting environment variables with Bun's default `redis` client.
|
|
34
|
+
|
|
35
|
+
Set the `REDIS_URL` environment variable in your `.env` file using the Redis endpoint (not the REST URL):
|
|
36
|
+
|
|
37
|
+
```env .env icon="settings"
|
|
38
|
+
REDIS_URL=rediss://********@********.upstash.io:6379
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Bun's Redis client reads connection information from `REDIS_URL` by default:
|
|
42
|
+
|
|
43
|
+
```ts index.ts icon="/icons/typescript.svg"
|
|
44
|
+
import { redis } from "bun";
|
|
45
|
+
|
|
46
|
+
// Reads from process.env.REDIS_URL automatically
|
|
47
|
+
await redis.set("counter", "0"); // [!code ++]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Alternatively, you can create a custom client using `RedisClient`:
|
|
51
|
+
|
|
52
|
+
```ts index.ts icon="/icons/typescript.svg"
|
|
53
|
+
import { RedisClient } from "bun";
|
|
54
|
+
|
|
55
|
+
const redis = new RedisClient(process.env.REDIS_URL); // [!code ++]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
</Step>
|
|
59
|
+
<Step title="Use the Redis client">
|
|
60
|
+
You can now use the Redis client to interact with your Upstash Redis database:
|
|
61
|
+
|
|
62
|
+
```ts index.ts icon="/icons/typescript.svg"
|
|
63
|
+
import { redis } from "bun";
|
|
64
|
+
|
|
65
|
+
// Get a value
|
|
66
|
+
let counter = await redis.get("counter");
|
|
67
|
+
|
|
68
|
+
// Set a value if it doesn't exist
|
|
69
|
+
if (!counter) {
|
|
70
|
+
await redis.set("counter", "0");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Increment the counter
|
|
74
|
+
await redis.incr("counter");
|
|
75
|
+
|
|
76
|
+
// Get the updated value
|
|
77
|
+
counter = await redis.get("counter");
|
|
78
|
+
console.log(counter);
|
|
79
|
+
```
|
|
80
|
+
```txt
|
|
81
|
+
1
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The Redis client automatically handles connections in the background. No need to manually connect or disconnect for basic operations.
|
|
85
|
+
</Step>
|
|
86
|
+
|
|
87
|
+
</Steps>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Build a frontend using Vite and Bun
|
|
3
|
+
sidebarTitle: "Vite with Bun"
|
|
4
|
+
mode: center
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<Note>
|
|
8
|
+
You can use Vite with Bun, but many projects get faster builds & drop hundreds of dependencies by switching to [HTML
|
|
9
|
+
imports](/bundler/html-static).
|
|
10
|
+
</Note>
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Vite works out of the box with Bun. Get started with one of Vite's templates.
|
|
15
|
+
|
|
16
|
+
```bash terminal icon="terminal"
|
|
17
|
+
bun create vite my-app
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```txt
|
|
21
|
+
✔ Select a framework: › React
|
|
22
|
+
✔ Select a variant: › TypeScript + SWC
|
|
23
|
+
Scaffolding project in /path/to/my-app...
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
Then `cd` into the project directory and install dependencies.
|
|
29
|
+
|
|
30
|
+
```bash terminal icon="terminal"
|
|
31
|
+
cd my-app
|
|
32
|
+
bun install
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
Start the development server with the `vite` CLI using `bunx`.
|
|
38
|
+
|
|
39
|
+
The `--bun` flag tells Bun to run Vite's CLI using `bun` instead of `node`; by default Bun respects Vite's `#!/usr/bin/env node` [shebang line](<https://en.wikipedia.org/wiki/Shebang_(Unix)>).
|
|
40
|
+
|
|
41
|
+
```bash terminal icon="terminal"
|
|
42
|
+
bunx --bun vite
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
To simplify this command, update the `"dev"` script in `package.json` to the following.
|
|
48
|
+
|
|
49
|
+
```json package.json icon="file-json"
|
|
50
|
+
"scripts": {
|
|
51
|
+
"dev": "vite", // [!code --]
|
|
52
|
+
"dev": "bunx --bun vite", // [!code ++]
|
|
53
|
+
"build": "vite build",
|
|
54
|
+
"serve": "vite preview"
|
|
55
|
+
},
|
|
56
|
+
// ...
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
Now you can start the development server with `bun run dev`.
|
|
62
|
+
|
|
63
|
+
```bash terminal icon="terminal"
|
|
64
|
+
bun run dev
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
The following command will build your app for production.
|
|
70
|
+
|
|
71
|
+
```sh terminal icon="terminal"
|
|
72
|
+
bunx --bun vite build
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
This is a stripped down guide to get you started with Vite + Bun. For more information, see the [Vite documentation](https://vitejs.dev/guide/).
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Extract links from a webpage using HTMLRewriter
|
|
3
|
+
sidebarTitle: Extract links using HTMLRewriter
|
|
4
|
+
mode: center
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Extract links from a webpage
|
|
8
|
+
|
|
9
|
+
Bun's [HTMLRewriter](https://bun.com/docs/api/html-rewriter) API can be used to efficiently extract links from HTML content. It works by chaining together CSS selectors to match the elements, text, and attributes you want to process. This is a simple example of how to extract links from a webpage. You can pass `.transform` a `Response`, `Blob`, or `string`.
|
|
10
|
+
|
|
11
|
+
```ts extract-links.ts icon="/icons/typescript.svg"
|
|
12
|
+
async function extractLinks(url: string) {
|
|
13
|
+
const links = new Set<string>();
|
|
14
|
+
const response = await fetch(url);
|
|
15
|
+
|
|
16
|
+
const rewriter = new HTMLRewriter().on("a[href]", {
|
|
17
|
+
element(el) {
|
|
18
|
+
const href = el.getAttribute("href");
|
|
19
|
+
if (href) {
|
|
20
|
+
links.add(href);
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Wait for the response to be processed
|
|
26
|
+
await rewriter.transform(response).blob();
|
|
27
|
+
console.log([...links]); // ["https://bun.com", "/docs", ...]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Extract all links from the Bun website
|
|
31
|
+
await extractLinks("https://bun.com");
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Convert relative URLs to absolute
|
|
37
|
+
|
|
38
|
+
When scraping websites, you often want to convert relative URLs (like `/docs`) to absolute URLs. Here's how to handle URL resolution:
|
|
39
|
+
|
|
40
|
+
```ts extract-links.ts icon="/icons/typescript.svg"
|
|
41
|
+
async function extractLinksFromURL(url: string) {
|
|
42
|
+
const response = await fetch(url);
|
|
43
|
+
const links = new Set<string>();
|
|
44
|
+
|
|
45
|
+
const rewriter = new HTMLRewriter().on("a[href]", {
|
|
46
|
+
element(el) {
|
|
47
|
+
const href = el.getAttribute("href");
|
|
48
|
+
if (href) {
|
|
49
|
+
// Convert relative URLs to absolute // [!code ++]
|
|
50
|
+
try {
|
|
51
|
+
// [!code ++]
|
|
52
|
+
const absoluteURL = new URL(href, url).href; // [!code ++]
|
|
53
|
+
links.add(absoluteURL); // [!code ++]
|
|
54
|
+
} catch {
|
|
55
|
+
// [!code ++]
|
|
56
|
+
links.add(href);
|
|
57
|
+
} // [!code ++]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Wait for the response to be processed
|
|
63
|
+
await rewriter.transform(response).blob();
|
|
64
|
+
return [...links];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const websiteLinks = await extractLinksFromURL("https://example.com");
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
See [Docs > API > HTMLRewriter](https://bun.com/docs/api/html-rewriter) for complete documentation on HTML transformation with Bun.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Extract social share images and Open Graph tags
|
|
3
|
+
sidebarTitle: OpenGraph tags
|
|
4
|
+
mode: center
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Extract social share images and Open Graph tags
|
|
8
|
+
|
|
9
|
+
Bun's [HTMLRewriter](https://bun.com/docs/api/html-rewriter) API can be used to efficiently extract social share images and Open Graph metadata from HTML content. This is particularly useful for building link preview features, social media cards, or web scrapers. We can use HTMLRewriter to match CSS selectors to HTML elements, text, and attributes we want to process.
|
|
10
|
+
|
|
11
|
+
```ts extract-social-meta.ts icon="/icons/typescript.svg"
|
|
12
|
+
interface SocialMetadata {
|
|
13
|
+
title?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
image?: string;
|
|
16
|
+
url?: string;
|
|
17
|
+
siteName?: string;
|
|
18
|
+
type?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function extractSocialMetadata(url: string): Promise<SocialMetadata> {
|
|
22
|
+
const metadata: SocialMetadata = {};
|
|
23
|
+
const response = await fetch(url);
|
|
24
|
+
|
|
25
|
+
const rewriter = new HTMLRewriter()
|
|
26
|
+
// Extract Open Graph meta tags
|
|
27
|
+
.on('meta[property^="og:"]', {
|
|
28
|
+
element(el) {
|
|
29
|
+
const property = el.getAttribute("property");
|
|
30
|
+
const content = el.getAttribute("content");
|
|
31
|
+
if (property && content) {
|
|
32
|
+
// Convert "og:image" to "image" etc.
|
|
33
|
+
const key = property.replace("og:", "") as keyof SocialMetadata;
|
|
34
|
+
metadata[key] = content;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
// Extract Twitter Card meta tags as fallback
|
|
39
|
+
.on('meta[name^="twitter:"]', {
|
|
40
|
+
element(el) {
|
|
41
|
+
const name = el.getAttribute("name");
|
|
42
|
+
const content = el.getAttribute("content");
|
|
43
|
+
if (name && content) {
|
|
44
|
+
const key = name.replace("twitter:", "") as keyof SocialMetadata;
|
|
45
|
+
// Only use Twitter Card data if we don't have OG data
|
|
46
|
+
if (!metadata[key]) {
|
|
47
|
+
metadata[key] = content;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
// Fallback to regular meta tags
|
|
53
|
+
.on('meta[name="description"]', {
|
|
54
|
+
element(el) {
|
|
55
|
+
const content = el.getAttribute("content");
|
|
56
|
+
if (content && !metadata.description) {
|
|
57
|
+
metadata.description = content;
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
// Fallback to title tag
|
|
62
|
+
.on("title", {
|
|
63
|
+
text(text) {
|
|
64
|
+
if (!metadata.title) {
|
|
65
|
+
metadata.title = text.text;
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Process the response
|
|
71
|
+
await rewriter.transform(response).blob();
|
|
72
|
+
|
|
73
|
+
// Convert relative image URLs to absolute
|
|
74
|
+
if (metadata.image && !metadata.image.startsWith("http")) {
|
|
75
|
+
try {
|
|
76
|
+
metadata.image = new URL(metadata.image, url).href;
|
|
77
|
+
} catch {
|
|
78
|
+
// Keep the original URL if parsing fails
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return metadata;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```ts Example Usage icon="/icons/typescript.svg"
|
|
87
|
+
// Example usage
|
|
88
|
+
const metadata = await extractSocialMetadata("https://bun.com");
|
|
89
|
+
console.log(metadata);
|
|
90
|
+
// {
|
|
91
|
+
// title: "Bun — A fast all-in-one JavaScript runtime",
|
|
92
|
+
// description: "Bundle, transpile, install and run JavaScript & TypeScript projects — all in Bun. Bun is a fast all-in-one JavaScript runtime & toolkit designed for speed, complete with a bundler, test runner, and Node.js-compatible package manager.",
|
|
93
|
+
// image: "https://bun.com/share.jpg",
|
|
94
|
+
// type: "website",
|
|
95
|
+
// ...
|
|
96
|
+
// }
|
|
97
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Start a cluster of HTTP servers
|
|
3
|
+
description: Run multiple HTTP servers concurrently via the "reusePort" option to share the same port across multiple processes
|
|
4
|
+
sidebarTitle: Start a cluster of HTTP servers
|
|
5
|
+
mode: center
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
To run multiple HTTP servers concurrently, use the `reusePort` option in `Bun.serve()` which shares the same port across multiple processes.
|
|
9
|
+
|
|
10
|
+
This automatically load balances incoming requests across multiple instances of Bun.
|
|
11
|
+
|
|
12
|
+
```ts server.ts icon="/icons/typescript.svg"
|
|
13
|
+
import { serve } from "bun";
|
|
14
|
+
|
|
15
|
+
const id = Math.random().toString(36).slice(2);
|
|
16
|
+
|
|
17
|
+
serve({
|
|
18
|
+
port: process.env.PORT || 8080,
|
|
19
|
+
development: false,
|
|
20
|
+
|
|
21
|
+
// Share the same port across multiple processes
|
|
22
|
+
// This is the important part!
|
|
23
|
+
reusePort: true,
|
|
24
|
+
|
|
25
|
+
async fetch(request) {
|
|
26
|
+
return new Response("Hello from Bun #" + id + "!\n");
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
<Note>
|
|
34
|
+
**Linux only** — Windows and macOS ignore the `reusePort` option. This is an operating system limitation with
|
|
35
|
+
`SO_REUSEPORT`, unfortunately.
|
|
36
|
+
</Note>
|
|
37
|
+
|
|
38
|
+
After saving the file, start your servers on the same port.
|
|
39
|
+
|
|
40
|
+
Under the hood, this uses the Linux `SO_REUSEPORT` and `SO_REUSEADDR` socket options to ensure fair load balancing across multiple processes. [Learn more about `SO_REUSEPORT` and `SO_REUSEADDR`](https://lwn.net/Articles/542629/)
|
|
41
|
+
|
|
42
|
+
```ts cluster.ts icon="/icons/typescript.svg"
|
|
43
|
+
import { spawn } from "bun";
|
|
44
|
+
|
|
45
|
+
const cpus = navigator.hardwareConcurrency; // Number of CPU cores
|
|
46
|
+
const buns = new Array(cpus);
|
|
47
|
+
|
|
48
|
+
for (let i = 0; i < cpus; i++) {
|
|
49
|
+
buns[i] = spawn({
|
|
50
|
+
cmd: ["bun", "./server.ts"],
|
|
51
|
+
stdout: "inherit",
|
|
52
|
+
stderr: "inherit",
|
|
53
|
+
stdin: "inherit",
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function kill() {
|
|
58
|
+
for (const bun of buns) {
|
|
59
|
+
bun.kill();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
process.on("SIGINT", kill);
|
|
64
|
+
process.on("exit", kill);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
Bun has also implemented the `node:cluster` module, but this is a faster, simple, and limited alternative.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: fetch with unix domain sockets in Bun
|
|
3
|
+
sidebarTitle: Fetch with unix domain sockets
|
|
4
|
+
mode: center
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
In Bun, the `unix` option in `fetch()` lets you send HTTP requests over a [unix domain socket](https://en.wikipedia.org/wiki/Unix_domain_socket).
|
|
8
|
+
|
|
9
|
+
```ts fetch-unix.ts icon="/icons/typescript.svg"
|
|
10
|
+
const unix = "/var/run/docker.sock";
|
|
11
|
+
|
|
12
|
+
const response = await fetch("http://localhost/info", { unix });
|
|
13
|
+
|
|
14
|
+
const body = await response.json();
|
|
15
|
+
console.log(body); // { ... }
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
The `unix` option is a string that specifies the local file path to a unix domain socket. The `fetch()` function will use the socket to send the request to the server instead of using a TCP network connection. `https` is also supported by using the `https://` protocol in the URL instead of `http://`.
|
|
21
|
+
|
|
22
|
+
To send a `POST` request to an API endpoint over a unix domain socket:
|
|
23
|
+
|
|
24
|
+
```ts fetch-unix.ts icon="/icons/typescript.svg"
|
|
25
|
+
const response = await fetch("https://hostname/a/path", {
|
|
26
|
+
unix: "/var/run/path/to/unix.sock",
|
|
27
|
+
method: "POST",
|
|
28
|
+
body: JSON.stringify({ message: "Hello from Bun!" }),
|
|
29
|
+
headers: {
|
|
30
|
+
"Content-Type": "application/json",
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const body = await response.json();
|
|
35
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Send an HTTP request using fetch
|
|
3
|
+
sidebarTitle: Fetch with Bun
|
|
4
|
+
mode: center
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Bun implements the Web-standard [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) API for sending HTTP requests. To send a simple `GET` request to a URL:
|
|
8
|
+
|
|
9
|
+
```ts fetch.ts icon="/icons/typescript.svg"
|
|
10
|
+
const response = await fetch("https://bun.com");
|
|
11
|
+
const html = await response.text(); // HTML string
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
To send a `POST` request to an API endpoint.
|
|
17
|
+
|
|
18
|
+
```ts fetch.ts icon="/icons/typescript.svg"
|
|
19
|
+
const response = await fetch("https://bun.com/api", {
|
|
20
|
+
method: "POST",
|
|
21
|
+
body: JSON.stringify({ message: "Hello from Bun!" }),
|
|
22
|
+
headers: { "Content-Type": "application/json" },
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const body = await response.json();
|
|
26
|
+
```
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Upload files via HTTP using FormData
|
|
3
|
+
sidebarTitle: Upload files via HTTP using FormData
|
|
4
|
+
mode: center
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
To upload files via HTTP with Bun, use the [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) API. Let's start with a HTTP server that serves a simple HTML web form.
|
|
8
|
+
|
|
9
|
+
```ts index.ts icon="/icons/typescript.svg"
|
|
10
|
+
const server = Bun.serve({
|
|
11
|
+
port: 4000,
|
|
12
|
+
async fetch(req) {
|
|
13
|
+
const url = new URL(req.url);
|
|
14
|
+
|
|
15
|
+
// return index.html for root path
|
|
16
|
+
if (url.pathname === "/")
|
|
17
|
+
return new Response(Bun.file("index.html"), {
|
|
18
|
+
headers: {
|
|
19
|
+
"Content-Type": "text/html",
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return new Response("Not Found", { status: 404 });
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
console.log(`Listening on http://localhost:${server.port}`);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
We can define our HTML form in another file, `index.html`.
|
|
33
|
+
|
|
34
|
+
```html index.html icon="file-code"
|
|
35
|
+
<!DOCTYPE html>
|
|
36
|
+
<html>
|
|
37
|
+
<head>
|
|
38
|
+
<meta charset="utf-8" />
|
|
39
|
+
<title>Form</title>
|
|
40
|
+
</head>
|
|
41
|
+
<body>
|
|
42
|
+
<form action="/action" method="post" enctype="multipart/form-data">
|
|
43
|
+
<input type="text" name="name" placeholder="Name" />
|
|
44
|
+
<input type="file" name="profilePicture" />
|
|
45
|
+
<input type="submit" value="Submit" />
|
|
46
|
+
</form>
|
|
47
|
+
</body>
|
|
48
|
+
</html>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
At this point, we can run the server and visit [`localhost:4000`](http://localhost:4000) to see our form.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
bun run index.ts
|
|
57
|
+
Listening on http://localhost:4000
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
Our form will send a `POST` request to the `/action` endpoint with the form data. Let's handle that request in our server.
|
|
63
|
+
|
|
64
|
+
First we use the [`.formData()`](https://developer.mozilla.org/en-US/docs/Web/API/Request/formData) method on the incoming `Request` to asynchronously parse its contents to a `FormData` instance. Then we can use the [`.get()`](https://developer.mozilla.org/en-US/docs/Web/API/FormData/get) method to extract the value of the `name` and `profilePicture` fields. Here `name` corresponds to a `string` and `profilePicture` is a `Blob`.
|
|
65
|
+
|
|
66
|
+
Finally, we write the `Blob` to disk using [`Bun.write()`](https://bun.com/docs/api/file-io#writing-files-bun-write).
|
|
67
|
+
|
|
68
|
+
```ts index.ts icon="/icons/typescript.svg"
|
|
69
|
+
const server = Bun.serve({
|
|
70
|
+
port: 4000,
|
|
71
|
+
async fetch(req) {
|
|
72
|
+
const url = new URL(req.url);
|
|
73
|
+
|
|
74
|
+
// return index.html for root path
|
|
75
|
+
if (url.pathname === "/")
|
|
76
|
+
return new Response(Bun.file("index.html"), {
|
|
77
|
+
headers: {
|
|
78
|
+
"Content-Type": "text/html",
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// parse formdata at /action // [!code ++]
|
|
83
|
+
if (url.pathname === "/action") {
|
|
84
|
+
// [!code ++]
|
|
85
|
+
const formdata = await req.formData(); // [!code ++]
|
|
86
|
+
const name = formdata.get("name"); // [!code ++]
|
|
87
|
+
const profilePicture = formdata.get("profilePicture"); // [!code ++]
|
|
88
|
+
if (!profilePicture) throw new Error("Must upload a profile picture."); // [!code ++]
|
|
89
|
+
// write profilePicture to disk // [!code ++]
|
|
90
|
+
await Bun.write("profilePicture.png", profilePicture); // [!code ++]
|
|
91
|
+
return new Response("Success"); // [!code ++]
|
|
92
|
+
} // [!code ++]
|
|
93
|
+
|
|
94
|
+
return new Response("Not Found", { status: 404 });
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
```
|