Express Compatibility
The Express compatibility layer is experimental and may change in future versions. Use it primarily for integrating third-party Express libraries. For new code, prefer using Balda's native APIs.
Balda.js provides an Express compatibility layer that allows you to integrate Express-based libraries like AdminJS, Passport, and other Express middleware into your Balda application.
Installation
Install the Express types for TypeScript support:
npm install express
npm install -D @types/express
Quick Start
Mounting an Express Router
Use mountExpressRouter to mount an entire Express router at a specific path:
import { Server } from 'balda-js';
import AdminJS from 'adminjs';
import AdminJSExpress from '@adminjs/express';
const admin = new AdminJS({ resources: [] });
const adminRouter = AdminJSExpress.buildRouter(admin);
const server = new Server({ port: 3000 });
server.mountExpressRouter('/admin', adminRouter);
server.listen();
Using Express Middleware
Convert Express middleware to Balda middleware with useExpress:
import { Server } from 'balda-js';
import helmet from 'helmet';
import compression from 'compression';
const server = new Server({ port: 3000 });
// Mount middleware at root
server.useExpress(helmet());
// Mount middleware at specific path
server.useExpress('/api', compression());
server.listen();
API Reference
server.useExpress(middleware)
Mount Express middleware or router at the root path.
server.useExpress(someExpressMiddleware);
server.useExpress(someExpressRouter);
server.useExpress(path, middleware)
Mount Express middleware or router at a specific path.
server.useExpress('/admin', adminRouter);
server.useExpress('/api', apiMiddleware);
server.mountExpressRouter(basePath, router)
Directly mount an Express router, extracting all routes.
server.mountExpressRouter('/admin', adminJsRouter);
server.expressMiddleware(middleware)
Convert an Express middleware to a Balda-compatible middleware (ServerRouteMiddleware) for use with server.use().
Returns: ServerRouteMiddleware - A Balda-native middleware function
const baldaMiddleware = server.expressMiddleware(someExpressMiddleware);
server.use(baldaMiddleware);
Low-Level Functions
These functions are exported for advanced use cases but should typically be accessed via the server instance:
import {
expressMiddleware,
expressHandler,
} from 'balda-js';
// Convert Express middleware → Balda middleware (ServerRouteMiddleware)
const baldaMw = expressMiddleware(someExpressMiddleware);
// Convert Express handler → Balda handler (ServerRouteHandler)
const baldaHandler = expressHandler(someExpressHandler);
Use the server instance methods instead of standalone functions:
const server = new Server({ port: 3000 });
// ✅ Preferred: Use server methods
server.mountExpressApp(expressApp);
server.mountExpressApp(expressApp, '/api/v1');
server.mountExpressRouter('/admin', adminRouter);
server.useExpress(someExpressMiddleware);
// For middleware conversion
const baldaMw = server.expressMiddleware(someExpressMiddleware);
Common Use Cases
AdminJS Integration
import { Server } from 'balda-js';
import AdminJS from 'adminjs';
import AdminJSExpress from '@adminjs/express';
import * as AdminJSSequelize from '@adminjs/sequelize';
AdminJS.registerAdapter(AdminJSSequelize);
const admin = new AdminJS({
resources: [User, Post, Comment],
rootPath: '/admin',
});
const adminRouter = AdminJSExpress.buildRouter(admin);
const server = new Server({ port: 3000 });
server.mountExpressRouter('/admin', adminRouter);
server.listen();
Limitations
The Express compatibility layer has some limitations you should be aware of:
Not Supported
| Feature | Status | Notes |
|---|---|---|
res.render() | ❌ | Template engines not supported |
app.engine() | ❌ | View engines not available |
app.set() / app.get() settings | ❌ | Express app settings not implemented |
res.sendFile() streaming | ⚠️ | Works but no streaming callbacks |
req.signedCookies | ❌ | Use Balda's cookie plugin instead |
| Express sub-apps | ❌ | Nested app.use(app) not supported |
| Express error middleware | ⚠️ | 4-argument (err, req, res, next) partially supported |
res.format() | ⚠️ | Returns empty, content negotiation not implemented |
| Trust proxy inheritance | ❌ | Use Balda's trustProxy plugin |
Partial Support
res.redirect()- Works, but always uses 302 unless status explicitly setres.cookie()- Requires Balda's cookie plugin to be enabled- File uploads - Use Balda's
fileParserplugin, not multer - Sessions - Use Balda's session plugin, Express session middleware may not work
Recommended Approach
For best results, use Balda native features when possible and reserve the Express compatibility layer for third-party libraries:
// ✅ Good: Use Express compat for third-party libraries
server.mountExpressRouter('/admin', adminJsRouter);
// ✅ Good: Use Balda native for your own routes
server.get('/api/users', (req, res) => {
res.json({ users: [] });
});
// ❌ Avoid: Don't use Express compat for simple middleware
// server.useExpress(cors()); // Use Balda's cors plugin instead
server.use(cors({ origin: '*' })); // Native Balda
Troubleshooting
HTML Not Rendering
If HTML appears as raw text, the Content-Type header may not be set. The adapter auto-detects HTML starting with <!DOCTYPE or <html>, but you can explicitly set it:
// In Express handler
res.type('text/html').send(htmlContent);
Middleware Not Executing
Ensure Express routers are mounted before calling server.listen():
const server = new Server({ port: 3000 });
// ✅ Correct: Mount before listen
server.mountExpressRouter('/admin', adminRouter);
server.listen();
// ❌ Wrong: Mounting after listen won't work correctly
Cookie/Session Issues
Enable Balda's cookie plugin for Express middleware that uses cookies:
const server = new Server({
port: 3000,
plugins: {
cookie: {}, // Enable cookie parsing
},
});
Runtime Support
The Express compatibility layer works across all Balda-supported runtimes:
| Runtime | Support |
|---|---|
| Node.js | ✅ Full |
| Bun | ✅ Full |
| Deno | ✅ Full |
Note: Some Express middleware may have runtime-specific dependencies that only work in Node.js.