FastAPI for Node.js & Bun
β‘ 3.8x faster with Bun | π 89.3% of Fastify with Node.js
π¨ This is an ALPHA version and proof of concept. Do not use in production!
- β Core functionality works - Basic API creation, validation, and testing.
β οΈ API may change - Breaking changes are expected in future versions.β οΈ Not production-ready - Missing features, optimizations, and stability improvements.
- Fix: Corrected issues in error handling (
handlerError) and updated theREADME.md. - Chore: Incremented project version.
SyntroJS is the world's first dual-runtime framework that brings the simplicity and developer experience of FastAPI to the TypeScript ecosystem. Write your code once and run it on either Node.js for stability or Bun for maximum performance.
It's designed for developers who value verifiable quality, providing a powerful, integrated testing suite that makes writing high-quality, mutation-resistant tests as easy as building endpoints.
- π Dual Runtime Support: Write once, run on both Node.js and Bun with auto-optimization. Zero code changes required.
- π₯ FastAPI-like Developer Experience: Get automatic validation with Zod, full TypeScript type safety, and elegant error handling (
HTTPException). - π¨ Automatic Interactive Docs: Just like FastAPI, get a beautiful landing page and interactive Swagger UI + ReDoc documentation out of the box at
/docs. - π§ͺ The Testing Superpower: A uniquely powerful testing suite featuring
TinyTestfor effortless API testing, built-in boundary and contract testing, andSmartMutatorfor mutation testing in seconds, not hours. - π Rich Ecosystem: Includes a functional middleware system, WebSocket support, simple dependency injection, background tasks, and seamless integration with
@syntrojs/loggerfor structured logging. - π Security First: Production-ready configurations to easily disable documentation (
docs: false), plus built-in support for JWT, OAuth2, API Keys, and other security plugins.
npm install syntrojs zod
# or
pnpm add syntrojs zodCreate a fully documented and validated API in just a few lines.
import { SyntroJS } from 'syntrojs';
import { z } from 'zod';
const app = new SyntroJS({ title: 'My API' });
// A simple GET endpoint
app.get('/hello', { handler: () => ({ message: 'Hello World!' }) });
// A POST endpoint with automatic Zod validation
app.post('/users', {
body: z.object({
name: z.string().min(1),
email: z.string().email(),
}),
handler: ({ body }) => ({ id: 1, ...body }),
});
await app.listen(3000);That's it! π Visit http://localhost:3000 for the welcome page or http://localhost:3000/docs for your interactive API documentation.
SyntroJS automatically detects your runtime and optimizes accordingly. The exact same code delivers the best of both worlds: stability on Node.js and extreme speed on Bun.
// app.js
import { SyntroJS } from 'syntrojs';
const app = new SyntroJS({ title: 'My API' });
app.get('/runtime', {
handler: () => ({
runtime: typeof Bun !== 'undefined' ? 'Bun (JavaScriptCore)' : 'Node.js (V8)',
performance: typeof Bun !== 'undefined' ? '3.8x faster than Fastify' : '89.3% of Fastify'
})
});
await app.listen(3000);Run with Node.js for stability:
node app.js
# π SyntroJS-NODE | Running on Node.js (V8)
# Performance: 89.3% of FastifyRun with Bun for maximum performance:
bun app.js
# π SyntroJS-BUN | Running on Bun (JavaScriptCore)
# Performance: 3.8x faster than Fastify| Runtime | Performance | Use Case |
|---|---|---|
| Node.js | 89.3% of Fastify | Production stability, full ecosystem |
| Bun | 3.8x faster than Fastify | Maximum performance, modern development |
SyntroJS believes testing should be a first-class citizen, not an afterthought. We make writing high-quality, verifiable tests as easy as creating the endpoints themselves.
TinyTest mirrors the SyntroJS API, so writing a test feels just like defining a route. It manages the server lifecycle for you.
import { TinyTest } from 'syntrojs/testing';
import { z } from 'zod';
test('POST /users creates a user successfully', async () => {
const api = new TinyTest();
api.post('/users', {
body: z.object({ name: z.string(), email: z.string().email() }),
handler: ({ body }) => ({ id: 1, ...body }),
});
const { status, data } = await api.expectSuccess('POST', '/users', {
body: { name: 'John', email: 'john@example.com' }
});
expect(status).toBe(201); // Or your desired status
expect(data.name).toBe('John');
await api.close();
});Mutation testing tools often create "mutants" by changing things like .min(18) to .min(17). Most tests won't catch this. SyntroJS provides testBoundaries to automatically test these exact edge cases, ensuring your validation logic is robust.
// This test kills mutants that other tests miss!
test('POST /users validates age boundary', async () => {
const api = new TinyTest();
api.post('/users', {
body: z.object({ age: z.number().min(18) }), // Must be 18+
handler: ({ body }) => ({ ...body }),
});
// Automatically tests the edges of your validation
await api.testBoundaries('POST', '/users', [
{ input: { body: { age: 17 } }, expected: { success: false } }, // β Must fail
{ input: { body: { age: 18 } }, expected: { success: true } }, // β
Must pass
]);
await api.close();
});Traditional mutation testing with Stryker can take 30-60 minutes, making it unusable for daily development. SmartMutator, our optimized runner, gives you the same results in seconds.
| Method | Mutants | Tests Executed | Time |
|---|---|---|---|
| Stryker (vanilla) | 1,247 | 187,050 | 43 min |
| SmartMutator | 142 | 284 | 12 sec |
| SmartMutator (incremental) | 8 | 16 | 3.2 sec |
This transforms mutation testing from a slow CI/CD step into a real-time quality feedback tool you can run every time you save a file.
# Run lightning-fast mutation testing
pnpm test:mutateThe SyntroJS Guarantee: We're the only framework where writing high-quality, mutation-resistant tests is a core, integrated part of the developer experience.
For production deployments, security is critical. SyntroJS makes it easy to lock down your application.
ALWAYS disable documentation in production:
const app = new SyntroJS({
title: 'Production API',
docs: false // β
REQUIRED for production
});- Disable all documentation (
docs: false) - Set proper CORS origins (not
*) - Enable rate limiting
- Configure structured logging without sensitive data (
@syntrojs/logger). - Use environment variables for secrets.
For production-ready examples, including microservices, benchmarks, and security patterns, see our dedicated Examples Repository.
SyntroJS follows Domain-Driven Design (DDD) and SOLID principles to ensure a clean, maintainable, and testable codebase. Key design principles include Simplicity, Type-Safety, and Quality First.
For a deeper dive, see our ARCHITECTURE.md document.
- Database integration (ORM/ODM adapters)
- GraphQL support
- File uploads & static file serving
- Official CLI tools
- Comprehensive documentation and migration guides
We welcome contributions! Please see CONTRIBUTING.md for details on how to set up your development environment and run tests.
Apache 2.0 - See LICENSE for details.