Skip to content

Coming from Express? ​

You already know bunWay. Same (req, res, next) signature, same middleware names, same routing patterns. Three things change on the way in:

1Change the importrequire() → import
2Rename the factoryexpress() → bunway()
3Delete npm middleware26 built-ins ship with bunWay — no installs needed
26Built-in middleware
0npm dependencies
~1.6×Faster than Express

The Diff ​

Here's a real Express app migrated to bunWay. Every unmarked line is untouched.

js
const express = require('express') 
const cors    = require('cors')    
const helmet  = require('helmet')  
const morgan  = require('morgan')  
import { bunway, cors, helmet, logger, json, session } from 'bunway'

const app = express() 
const app = bunway()  

app.use(cors())
app.use(helmet())
app.use(morgan('dev')) 
app.use(logger('dev')) 
app.use(express.json()) 
app.use(json())         
app.use(session({ secret: 'keyboard cat' }))

app.get('/users/:id', (req, res) => {
  res.json({ id: req.params.id })
})

app.listen(3000)

What's Different ​

Only two things change

  1. ES modules only — use import instead of require(). bunWay is TypeScript-first and ships no CommonJS build.
  2. Bun runtime — run with bun server.ts instead of node server.js.

The handler signature (req, res, next), every method, every property — identical.

Middleware Replacements ​

Delete the npm package and update the import. The API is identical unless noted in the full reference below.

Body Parsing ​

express.json()→json()
express.urlencoded()→urlencoded()
body-parser.text()→text()
body-parser.raw()→raw()

Security ​

helmet→helmet()
express-rate-limit→rateLimit()
csurf→csrf()
hpp→hpp()
express-session→session()
cookie-parser→cookieParser()

Files & Assets ​

express.static()→serveStatic()
multer→upload()
serve-favicon→favicon()
compression→compression()

Observability & Utilities ​

morgan→logger()
response-time→responseTime()
express-request-id→requestId()
method-override→methodOverride()
connect-timeout→timeout()
cors→cors()
express-validator→validate()
express-sse→sse()
custom 4-arg middleware→errorHandler()

API Reference ​

The request and response objects are 1:1 with Express. Open any section — identical means zero code changes, enhanced means bunWay is a superset.

Request — properties
PropertyStatus
req.paramsidentical
req.queryidentical
req.bodyidentical
req.cookiesidentical
req.pathidentical
req.methodidentical
req.ipidentical
req.sessionidentical
req.protocolidentical
req.secureidentical
Request — methods
MethodStatusNotes
req.get(header)identical
req.fresh / req.staleidenticalETag + Last-Modified cache validation
req.range(size)identicalRange header parsing
req.param(name)identicalparams → body → query
req.acceptsCharsets()identical
req.acceptsEncodings()identical
req.acceptsLanguages()identical
req.is(type)enhancedSupports text/* and application/* wildcards
req.accepts(type)enhancedRFC 7231 quality-value parsing
Response — methods
MethodStatusNotes
res.json()identical
res.send()enhancedAuto content-type detection + chainable
res.status()identical
res.set()identical
res.cookie()identical
res.redirect()identical
res.sendStatus()identical
res.sendFile()enhancedAutomatic 206 Partial Content
res.jsonp()identical
res.download()enhancedOptional error callback
res.attachment()enhancedAuto content-type detection
res.end()enhancedEncoding + callback support
Routing & server
APIStatusNotes
app.get/post/put/delete()identical
app.use()identicalArray path mounting supported
app.route(path)identicalChainable route definitions
import { Router } from "bunway"identicalWas express.Router()
Router({ mergeParams: true })identical
req.res / res.reqidenticalCross-references set during dispatch
res.appidentical
Regex routesnewapp.get(/\/fly$/, handler)
app.all('*', handler)identical
Sub-app mountingenhancedapp.mountpath + app.path()
app.listen({ tls: opts })enhancedNative TLS — no https.createServer()
app.close(cb)identical

Ready? Get started → or jump straight to Middleware →