Framework-agnostic HTTP abstraction layer for Superfunctions libraries
npm install @superfunctions/httpFramework-agnostic HTTP abstraction layer for building web APIs that work across Express, Hono, Fastify, Next.js, and more.
``bash`
npm install @superfunctions/http
For framework adapters:
`bashExpress
npm install @superfunctions/http-express
Quick Start
$3
`typescript
import { createRouter } from '@superfunctions/http';const apiRouter = createRouter({
routes: [
{
method: 'GET',
path: '/users',
handler: async () => {
const users = await db.query('SELECT * FROM users');
return Response.json(users);
},
},
{
method: 'GET',
path: '/users/:id',
handler: async (req, ctx) => {
const user = await db.query(
'SELECT * FROM users WHERE id = ?',
[ctx.params.id]
);
return Response.json(user);
},
},
{
method: 'POST',
path: '/users',
handler: async (req, ctx) => {
const data = await ctx.json();
const user = await db.insert('users', data);
return Response.json(user, { status: 201 });
},
},
],
});
`$3
`typescript
import express from 'express';
import { toExpress } from '@superfunctions/http-express';
import { apiRouter } from './api';const app = express();
app.use(express.json());
app.use('/api', toExpress(apiRouter));
app.listen(3000);
`$3
`typescript
import { Hono } from 'hono';
import { toHono } from '@superfunctions/http-hono';
import { apiRouter } from './api';const app = new Hono();
app.route('/api', toHono(apiRouter));
export default app;
`$3
For Fetch-native frameworks:
`typescript
import { createRouter } from '@superfunctions/http';const router = createRouter({ routes: [...] });
// Cloudflare Workers
export default {
fetch: router.handle
};
// Deno
Deno.serve(router.handle);
// Bun
Bun.serve({ fetch: router.handle });
`Features
$3
`typescript
const authMiddleware = async (req, ctx, next) => {
const token = req.headers.get('Authorization');
if (!token) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}
ctx.user = await verifyToken(token);
return next();
};const router = createRouter({
middleware: [authMiddleware],
routes: [...],
});
`$3
`typescript
interface AppContext {
db: Database;
user?: User;
}const router = createRouter({
context: async (req) => ({
db: adapter,
user: await getUser(req),
}),
routes: [
{
method: 'GET',
path: '/profile',
handler: async (req, ctx) => {
// ctx is typed as AppContext & RouteContext
return Response.json({ user: ctx.user });
},
},
],
});
`$3
`typescript
import { RouterError, UnauthorizedError } from '@superfunctions/http';const router = createRouter({
routes: [
{
method: 'GET',
path: '/protected',
handler: async () => {
throw new UnauthorizedError('Invalid token');
},
},
],
onError: (error, req) => {
console.error('Error:', error);
return Response.json(
{ error: error.message },
{ status: error instanceof RouterError ? error.statusCode : 500 }
);
},
});
`$3
⚠️ Important: Only use
basePath for standalone deployments without framework mounting.`typescript
// ✅ Good: Standalone deployment (Cloudflare Workers, Vercel Edge)
const router = createRouter({
basePath: '/api/v1',
routes: [
{ method: 'GET', path: '/users', handler: ... } // Accessible at /api/v1/users
]
});export default { fetch: router.handle }; // or router.handler
// ❌ Bad: With framework mounting (creates double prefixing)
const router = createRouter({
basePath: '/v1', // Don't do this!
routes: [...]
});
app.use('/api', toExpress(router)); // Would need /api/v1/users
// ✅ Good: With framework mounting (no basePath)
const router = createRouter({
routes: [
{ method: 'GET', path: '/users', handler: ... }
]
});
app.use('/api/v1', toExpress(router)); // Accessible at /api/v1/users
`Rule of thumb:
- Standalone deployment → Use
basePath in router
- Framework mounting → Use framework's mounting (e.g., app.use('/path', ...)) and omit basePath$3
`typescript
import { corsMiddleware } from '@superfunctions/http/middleware';const router = createRouter({
middleware: [
corsMiddleware({
origin: 'https://example.com',
methods: ['GET', 'POST'],
credentials: true,
}),
],
routes: [...],
});
`API Reference
$3
Creates a framework-agnostic router.
Options:
-
routes: Array of route definitions
- middleware?: Global middleware array
- context?: Static context or factory function
- onError?: Custom error handler
- basePath?: Base path prefix for all routes
- cors?: CORS configurationReturns:
Router$3
`typescript
interface Route {
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
path: string;
handler: RouteHandler;
middleware?: Middleware[];
meta?: Record;
}
`$3
Every handler receives a context with:
`typescript
interface RouteContext {
params: Record; // Path parameters
query: URLSearchParams; // Query string
url: URL; // Full URL
json: () => Promise; // Parse JSON body
formData: () => Promise; // Parse form data
text: () => Promise; // Get text body
}
`Framework Adapters
| Framework | Package | Function |
|-----------|---------|----------|
| Express |
@superfunctions/http-express | toExpress(), toExpressHandler() |
| Hono | @superfunctions/http-hono | toHono() |
| Fastify | @superfunctions/http-fastify | toFastify() |
| Next.js | @superfunctions/http-next | toNextHandlers() |
| SvelteKit | @superfunctions/http-sveltekit | toSvelteKitHandler(), toSvelteKitHandlers()` |MIT