Package Exports
- @nex-app/bun-server
- @nex-app/bun-server/index.ts
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@nex-app/bun-server) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Bun Server
A lightweight and flexible HTTP & WebSocket server built with Bun. This server provides an Express-like API for handling HTTP requests, managing WebSockets, and serving static files with minimal dependencies.
Features
- Express-like API: Define routes with
get
,post
,put
,delete
, and more. - WebSocket Support: Easily manage WebSocket connections with custom handlers.
- Middleware-like Request Validation: Hook into requests before they hit your route handlers.
- Static File Serving: Serve files from a public directory with minimal setup.
- Custom Error Handling: Define custom responses for errors across the server.
- Built-in JSON & Form Parsing: Automatically parses
application/json
,x-www-form-urlencoded
, andmultipart/form-data
requests. - Global State Management: Define global server state variables accessible in request handlers.
- Lightweight & Fast: Runs efficiently with minimal overhead.
Installation
bun add @nex-app/bun-server
Quick Start
import { createServer } from '@nex-app/bun-server';
const server = createServer({
port: 3000,
globalHeaders: {
'Access-Control-Allow-Origin': '*',
},
state: {
someProp: 'my-global-prop'
someFunc: function() {
return 'hello!'
},
},
onRequest: (req) => {
console.log(`${req.request.method} ${req.request.url}`);
return true; // Allow request to proceed
},
});
// an unnessecarily verbose demo
server.get('/hello', (req, res) => {
const user = req.state.someFunc();
const db = req.state.db();
console.log(req.params.query);
console.log(req.state);
res.setStatus(400);
res.setHeader('custom', 'custom value');
return res.send({
message: 'Hello World',
headers: req.headers['user-agent'],
});
});
server.start();
console.log('Server running on http://localhost:3000');
API Reference
createServer(options)
Creates and configures a new Bun server.
Options:
Option | Type | Description |
---|---|---|
port |
number |
Port for the server to listen on. |
webSocket |
WebSocketConfig (optional) |
WebSocket configuration. |
state |
Record<string, any> (optional) |
Global server state object. |
globalHeaders |
Record<string, any> (optional) |
Headers applied to all responses. |
debug |
boolean (optional) |
Enable debugging logs. |
onRequest |
(req: RequestHandler) => boolean (optional) |
Middleware-like request validator. Can be used for authentication or any other thing you may want to do with it. Returning false will send a 400 error back to the client. |
HTTP Methods
The server provides methods for handling different HTTP requests:
server.get("/route", (req, res) => { ... });
server.post("/route", (req, res) => { ... });
server.put("/route", (req, res) => { ... });
server.patch("/route", (req, res) => { ... });
server.delete("/route", (req, res) => { ... });
server.options("/route", (req, res) => { ... });
server.head("/route", (req, res) => { ... });
server.get('/route/:id', (req, res) => { ... });
server.get('/route/*', (req, res) => { ... });
Each handler receives:
req
: Request object containingparams
,headers
,state
,pathname
, andrequest
.res
: Response object withsend()
,setStatus()
, andsetHeader()
.
Example:
server.get('/users/:id', (req, res) => {
res.send({ userId: req.params.path.id });
});
There is a hierarchy of matching params and wildcards:
- Exact match first (
/route/test
) - Parameter match second (
/route/:param
) - Wildcard match last (
/route/*
)
For example if you were to perform a GET request on /route/test
, then the handler for /route/test
would be called. If you
called /route/foo
, it would go to the parameter match. Finally, if you were to call /route/foo/bar
, the wildcard handler would be
executed. If the wildcard handler is called, you will need to parse the path yourself:
server.get('/route/*', (req, res) => {
const { pathname } = req;
const parts = pathname.split('/');
// do something with parts
return res.send('done!');
});
WebSocket Support
To enable WebSockets, pass a webSocket
config:
server = createServer({
port: 3000,
webSocket: {
path: '/ws',
onUpgrade: (req) => {
console.log('WebSocket upgrade');
return { userId: '1234' };
},
onConnected: (socket) => {
console.log('Client connected');
},
onMessage: (socket, message) => {
console.log(socket.data.userId);
console.log('Received message', message);
socket.send({ echo: message });
},
onClose: (socket) => console.log('Client disconnected'),
},
});
The websocket config's onUpgrade method will allow you to define custom data that will be
present in the onMessage function via socket.data
. This is useful for authentication or carrying
state across multiple messages.
Currently socket.data
is mutable, but in future updates I plan to use a state management function to
perform mutations, similar to how setState works in React.
Static File Serving
You can serve a folder as a public directory:
server.addPublicDirectory('public');
This allows access to files via:
http://localhost:3000/index.html
http://localhost:3000/styles.css
Custom Error Handling
Define a global error handler:
server.onError((err) => {
console.log('Error handler', err.message);
return new Response('error', { status: err.status || 500 });
});
License
MIT