asijs
v1.5.0
Published
Bun-first web framework — fast, type-safe, simple
Downloads
679
Maintainers
Readme
AsiJS
✨ Features
Core
- 🚀 Blazing Fast — Trie + Radix tree router, route compilation, static router, schema cache LRU
- 🎯 Type-safe — Full TypeScript with TypeBox validation, phantom types, type inference
- 🔌 Pluggable — Rich plugin ecosystem with dependency ordering, lazy init, lifecycle hooks
- 📦 Zero Config — Sensible defaults, works out of the box
- 🖥️ Multi-runtime — Bun, Node.js (HTTP/HTTPS+WebSocket), Edge (Cloudflare, Deno, Vercel, Lambda@Edge)
Developer Experience
- 🔥 Hot Reload 2.0 —
fs.watchwith 200ms debounce, module-level hot swap, HMR browser push via WebSocket - 💬 Interactive REPL —
asi repl: create routes on the fly, test requests, inspect state - 🌐 Web Playground — Browser-based IDE: code editor, output panel, request bar, 5 built-in examples
- 🛠️ CLI v2 —
asi create/dev/inspect/build/plugin/repl/generate/migrate/integrate/analyze/doctor/upgrade/db/template - 📊 Benchmark Dashboard — Chart.js dashboard with trend lines, CI pipeline
Resilience & Performance
- ⚡ Circuit Breaker — CLOSED/OPEN/HALF_OPEN with sliding window, timeout, fallback, healthcheck integration
- 🔁 Request Deduplication — Inflight manager, XFetch cache stampede protection, MemoryCache/Redis
- ❄️ Serverless Optimisation — Warm start emulation, lazy imports, bundle config for 6 platforms
- 🗺️ Radix Tree Router — Up to 2× faster for 1M+ routes
- 💾 Schema Cache LRU — Bounded memory for TypeBox compiled validators
- ⚙️ Response Serialization (3.2) —
schema.responsepre-compiles TypeBox → fast serializer (status-keyed{200, "2xx", default}+ per-content-typeserializersvia Accept negotiation); e2e ×1.4 vs plain JSON
API & Documentation
- 📄 OpenAPI / Swagger — Auto-generated OpenAPI 3.0/3.1, Swagger UI, security schemes
- 🔄 Data Formats —
app.setFormat("yaml")+registerFormat(): JSON native, YAML lazy (bun add yaml), custom formats (TOML/INI/…);ctx.parseBody()parses by Content-Type, responses/errors/404 serialize in the default format with Accept-negotiation; TOON (token-optimized LLM format) via thetoon-asijspackage —registerToonFormat()+setFormat("toon")out of the box - 📖 API Docs Portal — Full documentation portal: sidebar search, code samples (curl/Python/JS/Go), try-it-out proxy, dark/light theme
- 🔄 API Versioning — URL/Header/Combined strategies, fallback, deprecation headers (
Sunset,Deprecation) - 📝 API Changelog — Snapshot/diff between API versions, Markdown/HTML export for CI/CD
WebSocket
- 🔌 WebSocket — First-class
app.ws()with typed data, lifecycle hooks - 📡 Pub-Sub — Rooms (
ws.join(),ws.leave()), broadcast, presence tracking, typed events - 🔄 Redis Bridge — Cross-instance pub-sub via Redis for horizontal scaling
- 💤 Graceful Shutdown — Drain active connections with 1001 close frames
Security
- 🛡️ Built-in Security Module —
AsiConfig.securitywith zero-config sensible defaults:autoEscape— Automatic XSS prevention in HTML responsesmaxBodySize— Request body size limiting (configurable per unit)autoNonce— CSP nonce generation for inline scriptsstrictContentType— Content-Type enforcement with error/sanitize/off modes- OWASP Headers — CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy
- 🔐 Security Presets —
maxSecurity,apiSecurity,devSecurity - 🔑 JWT — Sign/verify/decode, bearer auth middleware, CSRF protection
- 🔒 Rate Limiting — Sliding window + token bucket, IP/API Key/User presets, per-tenant isolation
Static Site Generation
- 📄 SSG —
asi build --ssg: scan GET routes, render HTML, pretty URLs (/about/index.html) or flat format - 📦 JSON Export —
--export-apifor static API data - ⚡ Edge-ready — SPA + Hybrid rendering with islands architecture
Observability
- 📊 Metrics — Prometheus + OTLP exporters, request metrics collector, histograms
- 🕵️ Tracing — W3C Trace Context, Server-Timing headers, request IDs, span events
- 📋 Structured Logging — JSON log middleware for ELK/Datadog/Splunk, multi-level (debug/info/warn/error)
- 🐛 Sentry — Fetch-based error tracking (no SDK required), breadcrumbs, envelopes
- 🔬 OpenTelemetry — Full OTel instrumentation: spans, metrics, logs. W3C TraceContext propagation. Exporters: Console, OTLP, Jaeger, Zipkin
Ecosystem
- 🤖 MCP Ready — Model Context Protocol server for AI/LLM integration (7 built-in tools, 4 resources)
- 📦 Plugin Registry —
asi plugin search/install/create/list. 40+ curated plugins in 8 categories - 🧩 asijs-next — Next.js App Router, Pages Router, Edge Runtime adapter
- 🧩 asijs-astro — Astro server endpoints, method-specific endpoints, middleware
- 🧩 asijs-remix — Remix resource routes, loaders, actions
- 🧩 asijs-sveltekit — SvelteKit handle hook, server handler, universal handler
- 🧩 asijs-opentelemetry — OpenTelemetry automatic instrumentation
- 📋 ESLint Plugin —
eslint-plugin-asijswith 4 rules: no-duplicate-route, no-missing-handler, validate-schema, no-unused-route - 🎨 VS Code Extension — Snippets, route explorer, hover provider, debug config, template explorer, create wizard
- 🦀 Native / Polyglot Modules —
asi native scaffold <lang>+ctx.native— write functions in Rust/Go/C/C++/Zig/Nim/Haskell (viabun:ffi), Python/Ruby/PHP (sidecar viaBun.spawn+ JSON-RPC) or Lua (embedded interpreter via dlopen liblua — no compilation, no IPC); AsiJS generates stubs and typed wrappers — zero manual glue, no WASM. Zig requires 0.15–0.17; older versions will not work
Migration
- 🔄 Express → AsiJS —
expressPlugin.wrap(mw), codemod with 22 rules, CLI:asi integrate ./app.js - 🔄 Koa → AsiJS —
koaPlugin.wrap(mw), codemod with 22 rules - 🔄 Elysia/Hono/Fastify → AsiJS —
asi migratewith automatic transformation
📦 Installation
Bun:
bun add asijsnpm:
npm install asijsJSR:
bunx jsr add @baconana/asijsNode.js Adapter
For Node.js HTTP(S) + WebSocket support:
bun add asijs # same package, use asijs/nodeimport { Asi } from "asijs";
import { nodeAdapter } from "asijs/node";
const app = new Asi({ serverAdapter: nodeAdapter() });
app.listen(3000);🚀 Quick Start
import { Asi } from "asijs";
const app = new Asi();
// Simple route
app.get("/", () => "Hello, AsiJS! 👋");
// With validation
app.post("/users", async (ctx) => {
const body = await ctx.parseBody();
return { id: 1, ...body };
}, {
schema: {
body: Type.Object({
name: Type.String({ minLength: 1 }),
email: Type.String({ format: "email" }),
}),
},
});
// Start server
app.listen(3000);🛠️ CLI
# Create a new project
bunx asijs create my-app
# Development server (with hot reload)
bunx asijs dev
# Inspect routes/plugins/size
bunx asijs inspect --routes --verbose
bunx asijs inspect --plugins
bunx asijs inspect --size
# Build for production
bunx asijs build # SPA/SSR build
bunx asijs build --ssg # Static site generation
bunx asijs build --target cloudflare # Serverless build
# Interactive REPL
bunx asijs repl
# Plugin management
bunx asijs plugin search auth
bunx asijs plugin install cors
bunx asijs plugin create my-plugin
bunx asijs plugin list
# Migrate from other frameworks
bunx asijs integrate ./app.js
# Generate scaffold
bunx asijs generate route users
bunx asijs generate plugin auth
# CLI v2 — Smarter Developer Tools
bunx asijs analyze # Static analysis: dead routes, validation, bottlenecks
bunx asijs analyze --info --json
bunx asijs doctor # Project diagnostics: config, deps, strict, security
bunx asijs upgrade --dry-run # Check for AsiJS updates
bunx asijs upgrade --codemod # Update + breaking-changes codemod
bunx asijs template api # Install template into current dir
bunx asijs dev --inspect # Dev + DevTools hint (dashboard, REPL, analyze)Templates
| Template | Description |
|----------|-------------|
| minimal | Basic setup with routing |
| api | REST API with validation, CORS, OpenAPI |
| fullstack | API + JSX rendering |
| auth | JWT authentication + protected routes |
| realtime | WebSocket chat |
| workspace | Monorepo with multiple sub-apps |
📚 Examples
REST API with Validation
import { Asi, Type } from "asijs";
const app = new Asi();
const users: { id: number; name: string; email: string }[] = [];
app.get("/users", () => users);
app.get("/users/:id", (ctx) => {
const user = users.find(u => u.id === +ctx.params.id);
if (!user) return ctx.status(404).jsonResponse({ error: "Not found" });
return user;
}, {
params: Type.Object({ id: Type.String() }),
});
app.post("/users", async (ctx) => {
const body = await ctx.body<{ name: string; email: string }>();
const user = { id: users.length + 1, ...body };
users.push(user);
return ctx.status(201).jsonResponse(user);
}, {
schema: {
body: Type.Object({
name: Type.String({ minLength: 1 }),
email: Type.String({ format: "email" }),
}),
},
});
app.listen(3000);Circuit Breaker
import { Asi, circuitBreaker, apiCircuitBreaker } from "asijs";
const app = new Asi();
// Global: protect against external API failures (middleware, not a plugin)
app.use(circuitBreaker({
threshold: 5, // 5 failures → OPEN
window: 30000, // 30 second sliding window
recoveryTimeout: 10000, // 10s recovery
fallback: () => ({ cached: true, data: [] }),
}));
// Per-route with presets — apiCircuitBreaker(name) takes a breaker name
app.get("/api/external", apiCircuitBreaker("stripe-api"), async (ctx) => {
const data = await ctx.circuitBreaker!("stripe-api", () =>
fetch("https://api.stripe.com/v1/charges")
);
return data;
});
app.listen(3000);WebSocket Pub-Sub
import { Asi, createRoomManager } from "asijs";
const app = new Asi();
const rooms = createRoomManager({ maxRoomsPerConnection: 10 });
// Create a chat room
app.ws("/chat", {
open(ws) {
ws.data = { joinedAt: Date.now() };
ws.join("lobby");
},
message(ws, message) {
const msg = typeof message === "string" ? message : JSON.stringify(message);
rooms.broadcast(msg, { rooms: ["lobby"] });
},
close(ws) {
rooms.cleanup(ws);
},
}, { roomManager: rooms });
app.listen(3000);SSG — Static Site Generation
import { Asi, buildSSG, staticPath } from "asijs";
const app = new Asi();
app.get("/", () => "<h1>Home</h1>");
app.get("/about", () => "<h1>About</h1>");
// Dynamic routes: define static paths
const paths = [
staticPath("/blog/:slug", { slug: "hello-world" }),
staticPath("/blog/:slug", { slug: "second-post" }),
];
// CLI: bunx asijs build --ssg
// Or programmatically:
const result = await buildSSG(app, {
staticPaths: paths,
outDir: "./dist",
format: "pretty", // /about → about/index.html
});
// result: { totalPages: 4, successPages: 4, failedPages: 0, durationMs: 12 }API Versioning
import { Asi, apiVersion, versionPath } from "asijs";
const app = new Asi();
app.use(apiVersion({
defaultVersion: "2.0",
supportedVersions: ["1.0", "2.0"],
strategy: "url", // URL-based: /v1/users, /v2/users
fallback: "latest", // Unsupported version → latest
deprecationHeaders: true, // Add Sunset/Deprecation headers
}));
// v1 users endpoint
app.get(versionPath("/users", "1.0"), () =>
users.map(u => ({ id: u.id, name: u.name }))
);
// v2 users endpoint (richer response)
app.get(versionPath("/users", "2.0"), () => users);
app.listen(3000);Built-in Security
import { Asi } from "asijs";
// Zero-config: OWASP headers, XSS escape, body limits, CSP nonce
const app = new Asi({
security: {
autoEscape: true,
maxBodySize: "1mb",
strictContentType: "sanitize",
headers: {
contentSecurityPolicy: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
},
hsts: { maxAge: 31536000, includeSubDomains: true },
xFrameOptions: "DENY",
},
},
});
// Presets — plain SecurityConfig objects, merged into AsiConfig.security
import { maxSecurity, apiSecurityCore, devSecurity } from "asijs";
const strictApp = new Asi({ security: maxSecurity });
// Or merge with your own overrides:
// const app = new Asi({ security: { ...apiSecurityCore, maxBodySize: "2mb" } });
app.listen(3000);Serverless / Edge
import { Asi, serverless } from "asijs";
const app = new Asi();
// Warm start emulation
await serverless.warmUp(app);
// Routes...
app.get("/api/hello", () => ({ message: "Hello from edge!" }));
// Build for target
// CLI: bunx asijs build --target cloudflare
// CLI: bunx asijs build --target lambda-edge
// CLI: bunx asijs build --target vercel-edgeFramework Adapter — Next.js
// app/api/[[...asi]]/route.ts
import { createNextHandler } from "asijs-next";
import { Asi } from "asijs";
const app = new Asi();
app.get("/api/hello", () => ({ message: "Hello from AsiJS in Next.js!" }));
export const { GET, POST, PUT, DELETE } = createNextHandler(app);🔌 Plugins
Built-in Plugins
| Plugin | Description | Since |
|--------|-------------|-------|
| cors() | Cross-Origin Resource Sharing (advanced: dynamic origin, wildcard, PNA) | v1.0 |
| staticFiles() | Static file serving with ETag, cache, range requests | v1.0 |
| openapi() | OpenAPI/Swagger documentation | v1.0 |
| rateLimit() | Rate limiting with sliding window + token bucket | v1.0 |
| security() | Security headers (CSP, HSTS, XFO, etc.) | v1.0 |
| cache() | Response caching with ETags | v1.0 |
| trace() | Request tracing & metrics | v1.0 |
| lifecycle() | Graceful shutdown with drain | v1.0 |
| devMode() | Development tools (chaos, delay, debug) | v1.0 |
| mcp() | Model Context Protocol for AI/LLM | v1.0 |
| sessions() | Session middleware (Memory, Cookie, Redis stores) | v1.2 |
| requestLogger() | Coloured request logging (4 formats) | v1.2 |
| compression() | gzip/brotli response compression | v1.2 |
| negotiateResponse() | Content negotiation helper (JSON/HTML/XML) | v1.2 |
| healthCheck() | /health, /ready, /live endpoints | v1.2 |
| sse() | Server-Sent Events | v1.2 |
| graphql() | GraphQL (Yoga/Helix adapter) | v1.2 |
| sentry() | Sentry error tracking | v1.2 |
| structuredLogger() | JSON structured logging | v1.2 |
| circuitBreaker() | Circuit breaker with 3 states, presets | v1.3 |
| deduplicate() | Request dedup + cache stampede protection | v1.3 |
| playgroundPlugin() | Browser-based IDE with code editor | v1.3 |
| apiDocsPlugin() | Full API documentation portal | v1.3 |
| apiVersion() | API versioning (URL/Header/Combined) | v1.3 |
| authjs() | Auth.js integration (GitHub, Google, Credentials) | v1.3 |
| upload() | File upload (Local, S3, R2) — streaming: true for memory-efficient large files | v1.3 |
| autoAPI() | PostgREST-like auto CRUD from database | v1.3 |
| expressPlugin() / koaPlugin() | Express/Koa middleware wrapper | v1.3 |
| otelLogs() | OpenTelemetry instrumentation (spans, metrics, logs) | v1.3 |
| webhooks() | Stripe/GitHub/Svix signature verification | v1.2 |
| trustProxy() | Real IP extraction from X-Forwarded-For | v1.2 |
| domainRouting() | Subdomain-based routing | v1.2 |
| serverPush() | Link preload headers | v1.2 |
| native() | Native modules — Rust/Go/C/C++/Zig/Nim/Haskell via bun:ffi, Python/Ruby/PHP via sidecar, Lua via dlopen → ctx.native.* | v1.5 |
Core API (v1.5)
| API | Description |
|-----|-------------|
| app.setFormat("yaml" / DataFormat) + format option | Default response format: objects, errors & 404 serialize in it; ctx.parseBody() parses by Content-Type |
| registerFormat() / listFormats() | Data formats layer — JSON native, YAML lazy, TOON via toon-asijs, custom formats in 3 lines |
| schema.response + serializers | JSON Schema response serialization: status-keyed {200, "2xx", default} + per-content-type with Accept negotiation |
Plugin Ordering & Dependencies
import { createPlugin } from "asijs";
// Plugins can declare dependencies
const authPlugin = createPlugin({
name: "auth",
dependencies: ["sessions", "cors"],
setup(app) {
app.onBeforeHandle(async (ctx) => {
ctx.user = await authenticate(ctx);
});
},
});
app.plugin(authPlugin()); // Auto-ordered: sessions → cors → auth
app.pluginInfo(); // Visualize dependency graph📦 Ecosystem Packages
| Package | Description | Tests |
|---------|-------------|-------|
| asijs-next | Next.js App Router / Pages Router / Edge adapter | 10 ✅ |
| asijs-astro | Astro server endpoints + middleware | 7 ✅ |
| asijs-remix | Remix resource routes + loader/action | 8 ✅ |
| asijs-sveltekit | SvelteKit handle hook + server/universal handlers | 8 ✅ |
| asijs-opentelemetry | Full OTel: spans, metrics, logs. 5 exporters | 22 ✅ |
| eslint-plugin-asijs | 4 ESLint rules for AsiJS projects | ✅ |
| asijs-mcp | MCP v2 server — tools, resources, prompts, workflows | 67 ✅ |
| asijs-react | React Server Components — Flight, streaming SSR + hydration | 24 ✅ |
| asijs-vite | AsiJS inside a Vite dev server — one port, HMR bridge | 16 ✅ |
| graphql-asijs | Code-first GraphQL — TypeBox → SDL, WS subscriptions, Federation, DataLoader | 42 ✅ |
| toon-asijs | TOON (token-optimized LLM format) as a native DataFormat | 21 ✅ |
| miyocss | SSR-first utility CSS + SVG engine (framework-agnostic) | 129 ✅ |
VS Code Extension — asijs-code
- 15 code snippets (GET/POST, WebSocket, CORS, JWT, OpenAPI, etc.)
- Route Explorer webview with colour-coded method badges
- Hover provider showing method + path on
app.get()/post() - Debug Configuration Provider (Launch, Attach, Workspace)
- Template Explorer (9 templates, 4 categories, search, preview)
- Create Project Wizard (4-step GUI)
- Inline Diagnostics (6 checks: missing dep, missing app, async/await, TODO/FIXME)
🛡️ Security (Built-in)
AsiJS includes a zero-config security module as part of AsiConfig:
const app = new Asi({
security: {
autoEscape: true, // Auto-escape HTML in responses (XSS)
maxBodySize: "1mb", // Limit request body size
autoNonce: true, // Auto-generate CSP nonces
strictContentType: "sanitize", // Sanitize Content-Type headers
headers: {
contentSecurityPolicy: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
},
hsts: { maxAge: 31536000, includeSubDomains: true },
xFrameOptions: "DENY",
xContentTypeOptions: "nosniff",
referrerPolicy: "strict-origin-when-cross-origin",
},
},
});Presets (plain SecurityConfig objects — pass them to security: in AsiConfig):
maxSecurity— Maximum security for web apps (strict CSP, strict HSTS)apiSecurityCore— Minimal overhead for API-only servicesdevSecurity— Relaxed for development (inline scripts allowed)
Includes OWASP-recommended headers by default: CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy.
📊 Benchmarks
AsiJS is built for performance. Full benchmark dashboard available at /benchmarks/.
Numbers below are from the CI benchmark pipeline (GitHub Actions runner, bare metal) — see the dashboard for history across commits and trends normalized across all categories.
🧭 How to read these numbers. AsiJS and Hono are monolithic — every capability (CORS, security headers, ETag, rate limiting, caching, validation) ships in the core and is always loaded. Elysia is a microkernel: all of that lives in external plugins (
@elysiajs/cors,elysia-rate-limit, …), so its benchmark apps are bare routers with a couple of plugins attached. Comparing full-stack throughput across these two architectures is apples-to-oranges (a monolithic kernel is supposed to be bigger than a microkernel — the question is whether the price buys something). We therefore treat Hono as the primary competitor: it is self-contained like AsiJS, so percentages are apples-to-apples. Elysia columns are kept for reference only — see the1a/1bfully-loaded split for why raw Elysia numbers can mislead.
Where AsiJS Wins (vs best competitor, latest run)
| Scenario | AsiJS (compiled) | vs Hono | vs Elysia (ref) | |----------|-----------------|-----------|---------| | POST /users + validation | 225,763 req/s | — | 110.9% 🏆 (ref) | | Auth POST (JWT + val + CORS + security) | 94,104 req/s | 9.3× 🏆 | 8.1× (ref) | | CRUD POST /api/products (auth + val) | 98,731 req/s | 9.7× 🏆 | 8.6× (ref) | | JSX rendering (100-row table) | 57,457 req/s | 2.1× 🏆 | — | | Array validation (100 items, valid) | 37,000 req/s | — | 107.1% 🏆 (ref) | | Validation error path (invalid payload) | 6,796 req/s | — | 1.9× 🏆 (ref) | | Large JSON body 10KB (validated) | 24,139 req/s | — | 106.4% 🏆 (ref) | | Large JSON body 100KB (validated) | 2,684 req/s | — | 109.6% 🏆 (ref) | | File upload 1MB (multipart) | 5,093 req/s | 100.8% | 100.2% (ref) | | Static preload (in-memory cache, 2.2.7) | 77,898 req/s | — | AsiJS-only (1.26× vs own disk path) | | Upload + save to disk (256KB, streaming) | 538 req/s | — | AsiJS-only (streaming +28% vs buffered) | | Response serialization (3.2, compiled schema) | 117k ops/s | — | AsiJS-only (×1.4 vs own plain JSON path) |
Competitive / Near-Parity
| Scenario | AsiJS | vs Hono | vs Elysia (ref) | |----------|-------|---------|-----------------| | CRUD PUT /api/products/:id | 11,485 req/s | 115.8% | 99.8% (ref) | | Blog API POST /posts (auth + val) | 172,366 req/s | 119.7% | 96.2% (ref) | | File upload 5MB (multipart) | 920 req/s | 92.8% | 170.4% (ref) | | CRUD GET list + filter + pagination | 94,145 req/s | 11.7× | 88.5% (ref) | | CORS preflight OPTIONS | 101,546 req/s | 113.8% | 82.3% (ref) | | GET /search (query params) | 352,050 req/s | 168.6% | 71.7% (ref) | | Concurrency C=100 / C=1000 | 692k / 738k req/s | 1.9× | 59.3% / 59.7% (ref) | | Query cache hit (repeated query, 2.2.6) | 235,899 req/s | 111.6% | 71.9% (ref) |
Known Gaps (honest, vs Hono)
Where AsiJS loses to Hono, and exactly why. 13 of 18 categories AsiJS wins; these 5 are the remaining work:
| Scenario | AsiJS | vs Hono | Why |
|----------|-------|---------|-----|
| 404 fast path (no route match) | 207,505 req/s | 82.6% | AsiJS generates a JSON body {error, path, method} + searches similar routes in dev mode on every miss; Hono returns a pre-built bare NOT_FOUND Response with no body. AsiJS intentionally ships a useful 404 body — a bare-response fast path is a candidate. |
| Error path (handler throws → 500) | 162,516 req/s | 73.3% | AsiJS builds a structured error response (status, error class, message) and routes it through the error pipeline; Hono rethrows the minimal 500. A pre-built generic 500 body is a candidate. |
| Query cache miss (unique query) | 164,273 req/s | 66.8% | Unique query strings bypass the 2.2.6 cache, so the single-pass parser runs per request and builds a fresh object; Hono's fixed benchmark query hits its own fast path. |
| Static file serving (small / 2MB) | 107k / 136k req/s | 71.4% / 78.1% | AsiJS's static plugin goes through middleware + cache + header pipeline; Hono returns Bun.file() directly. A zero-copy fast path in the static plugin is a candidate. |
| Complex validation (4-level nested) | 33,350 req/s | — (Elysia only) | The 2.2.5 compiled validator still walks TypeBox's generic check pipeline per level. Narrowing codegen (object/array hot paths) is the tracked follow-up. |
⚠️ Numbers are from a single CI run; runner hardware and
bun-version: latestdrift between runs. Compare within one run (percentages), not absolute values across runs — use the dashboard trends (normalized avg % of best across all categories) for commit-to-commit comparisons.
Benchmark Suites
| Suite | Command | Covers |
|-------|---------|--------|
| Core | bun run bench | GET/params/query/POST, validation, compiled mode |
| Production | bun run bench:production | middleware chain, upload, static, JSX, blog API |
| Fullstack | bun run bench:fullstack | auth, gateway, CRUD, preflight, security headers, fair middleware-set comparison |
| P0 Hot-Path | bun run bench:p0 | concurrency, route scaling, static preload, array validation |
| P1 API-Case | bun run bench:p1 | query cache, 404, error path, large bodies |
| P2 Features | bun run bench:p2 | WebSocket pub/sub, cache layer, DB layer, allocations |
| Serialization | bun run bench:serialize | compiled schema serializer vs plain JSON (codegen + e2e through AsiJS) |
| SSR frameworks | bun run bench:ssr | production servers on ports (C=32 concurrent fetch): AsiJS (JSX + string) vs Hono vs Astro (standalone) vs SvelteKit (adapter-node) vs Nuxt (nitro bun) — 100-row table page |
SSR frameworks methodology. Port-based, production builds only — real TCP + HTTP stack, so numbers include server + network overhead (not just render cost, unlike the in-process JSX row above). Framework apps live in
bench/frameworks/*; build once withbun run bench:ssr:build(installs SvelteKit/Astro/Nuxt — heavy, opt-in in CI via therun_ssr_frameworksworkflow input). All competitors are pinned to current latest majors (astro 7, nuxt 4, sveltekit 2 + vite 7; hono 4.13 / elysia 1.4.29 in the core benches) so AsiJS never races year-old code. Next.js / Remix are a tracked follow-up: their build toolchains require Node (next build/remix build), which the Bun-only CI doesn't have.
Benchmark Dashboard
AsiJS includes an automated benchmark dashboard:
bun run bench:collect— run all benchmark suites (above; skips SSR when framework builds are absent)bun run bench:dashboard— generate Chart.js HTML dashboard- Historical trends: normalized avg score vs best across all categories (with lower-is-better groups inverted) + per-category RPS picker
- Integrated into vitepress docs at
/benchmarks/ - CI pipeline auto-generates on every push to main
📁 Project Structure
asijs/
├── src/
│ ├── asi.ts # Core framework
│ ├── router.ts # Trie router
│ ├── router-perf.ts # Radix tree + middleware flattener
│ ├── context.ts # Request context
│ ├── validation.ts # TypeBox validation
│ ├── compiler.ts # Route compiler
│ ├── security-core.ts # Built-in security module
│ ├── circuit-breaker.ts # Circuit breaker resilience
│ ├── deduplicate.ts # Request dedup + cache stampede
│ ├── ws-pubsub.ts # WebSocket pub/sub rooms
│ ├── ws-redis.ts # Redis pub-sub bridge
│ ├── api-version.ts # API versioning
│ ├── ssg.ts # Static site generation
│ ├── serverless.ts # Serverless optimisation
│ ├── api-docs.ts # API documentation portal
│ ├── hot-reload.ts # Hot reload 2.0
│ ├── hmr.ts # HMR browser push
│ ├── repl.ts # Interactive REPL
│ ├── playground.ts # Web playground
│ ├── plugin-deps.ts # Plugin dependency manager
│ ├── plugin-registry.ts # Plugin registry
│ ├── migrate-express.ts # Express migration
│ ├── migrate-koa.ts # Koa migration
│ ├── authjs.ts # Auth.js integration
│ ├── upload.ts # File upload provider
│ ├── auto-api.ts # PostgREST-like auto API
│ ├── codegen.ts # OpenAPI client codegen
│ ├── serialize.ts # JSON Schema response serialization (3.2)
│ ├── formats.ts # Data formats layer: JSON/YAML/custom + TOON
│ ├── native/ # Native/polyglot modules (FFI + sidecars + Lua)
│ └── plugins/
│ ├── cors.ts # CORS plugin
│ └── static.ts # Static files plugin
├── packages/
│ ├── vscode-asijs/ # VS Code extension
│ ├── eslint-plugin-asijs/ # ESLint rules
│ ├── next-asijs/ # Next.js adapter
│ ├── astro-asijs/ # Astro adapter
│ ├── remix-asijs/ # Remix adapter
│ ├── sveltekit-asijs/ # SvelteKit adapter
│ ├── opentelemetry-asijs/ # OpenTelemetry integration
│ ├── mcp-asijs/ # MCP v2 server
│ ├── asijs-react/ # React Server Components
│ ├── asijs-vite/ # Vite dev server
│ ├── graphql-asijs/ # GraphQL plugin v2
│ ├── toon-asijs/ # TOON format adapter
│ └── MiyoCSS/ # SSR-first CSS + SVG framework
├── examples/ # Example apps
├── test/ # 2036 tests (2018 pass, 18 skip)
│ ├── integration/ # Docker-based integration tests
│ ├── e2e/ # End-to-end tests
│ └── k6/ # k6 load testing scripts
├── bench/ # Benchmarks + dashboard + SSR frameworks
└── docs/ # VitePress documentation site🧪 Testing
# Run all tests (2036 tests)
bun test
# With coverage
bun test --coverage
# Integration tests (requires Docker)
bun test test/integration/
# E2E tests
bun test test/e2e/
# Load testing with k6
bun run test:k6
# TypeScript check
bun run typecheckTest Quality
- 2036 tests (2018 pass, 18 skip) — 0 failures
- Integration tests — Docker-based PostgreSQL, Redis, MinIO
- E2E tests — Full cycle: auth → upload → CRUD → WebSocket
- Load tests — k6 scenarios: auth flow, CRUD, WebSocket, file upload
- 0 TypeScript errors (
tsc --noEmit) - Pre-release security audit — All v1.3 modules reviewed: 3 CRITICAL fixes, 2 HIGH fixes, 3 MEDIUM fixes
🤖 MCP — AI/LLM Integration
AsiJS supports the Model Context Protocol for AI assistant integration:
import { Asi, mcp, createMCPServer } from "asijs";
const app = new Asi();
// Add routes...
app.get("/users", () => users);
// Add MCP plugin for AI assistants
app.plugin(mcp({
name: "my-api",
version: "1.0.0",
tools: [
{
name: "list_users",
description: "List all users",
inputSchema: { type: "object", properties: {} },
handler: async () => ({
content: [{ type: "text", text: JSON.stringify(users) }]
}),
},
],
}));
// Run as MCP server for Claude Desktop, Cursor, etc.
const mcpServer = createMCPServer(app);
await mcpServer.start();📘 Documentation
Full documentation available at the VitePress docs site:
- Getting Started
- Routing
- Validation
- Context
- Plugins
- Auth
- OpenAPI
- WebSocket
- Rate Limiting
- Caching
- Security
- SSG
- MCP
- MCP v2 — AI-Native Protocol
- Async Error Boundary
- Observability
- API Versioning
- Circuit Breaker
- Framework Adapters
- Benchmarks
- Migration Guide
🤝 Contributing
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing) - Open a Pull Request
📝 License
MIT License — see LICENSE file for details.
