Features
Docs
CLI
Benchmarks
Examples

© 2024 MoroJs

Intelligent Routing

Routes that optimize themselves. Middleware ordered automatically. Type safety built-in. No manual configuration needed.

Routing That Thinks for You

Define your routes. We handle the optimization.Middleware ordering, route compilation, and type safety—all automatic.

Simple Route Definition

Define routes - everything else is automatic

typescript

1import { createApp } from '@morojs/moro';
2
3const app = createApp();
4
5// Simple route - types inferred automatically
6app.get('/users/:id', ({ params }) => {
7  // params.id is automatically typed as string
8  return { userId: params.id };
9});
10
11// With validation - types from schema
12app.post('/users', {
13  body: z.object({
14    name: z.string(),
15    email: z.string().email()
16  }),
17  handler: ({ body }) => {
18    // body is fully typed and validated
19    return { success: true, user: body };
20  }
21});

Why Intelligent Routing Matters

Traditional frameworks make you manually order middleware and optimize routes. We do that automatically.

Without intelligent routing, you're manually ordering middleware, optimizing execution paths, and managing route compilation.

Traditional Frameworks

  • Manual middleware ordering
  • Route compilation at runtime
  • No automatic optimization
  • Type safety requires extra work

With MoroJS

  • Automatic middleware ordering
  • Routes compiled at startup
  • Optimized execution paths
  • Type safety built-in

It's This Easy

Define your route. Add middleware. We handle the rest.

Chainable API - Recommended

typescript

1app.post('/users')
2  .body(CreateUserSchema)
3  .auth({ roles: ['admin'] })
4  .rateLimit({ requests: 10, window: 60000 })
5  .handler(async ({ body }) => {
6    // Middleware runs in optimal order automatically
7    // body is typed and validated
8    return { success: true, user: body };
9  });

Why It Makes Sense

Automatic Optimization

Middleware ordered optimally. Routes compiled at startup. Maximum performance.

Type Safe

Parameters, query strings, and bodies are automatically typed. No manual type definitions.

Smart Middleware

Middleware runs in the right order automatically. No manual configuration needed.

How It Works

MoroJS analyzes your routes at startup and creates an optimized execution plan. Middleware is automatically ordered based on dependencies, routes are compiled for maximum performance, and types are inferred from your route patterns and schemas.

Basic Route Definition

typescript

1import { createApp } from '@morojs/moro';
2
3const app = createApp();
4
5// Simple GET route
6app.get('/', () => {
7  return { message: 'Hello World' };
8});
9
10// Route with parameters
11app.get('/users/:id', ({ params }) => {
12  // params.id is automatically typed as string
13  return { userId: params.id };
14});
15
16// Multiple HTTP methods
17app.post('/users', ({ body }) => {
18  return { success: true };
19});
20
21app.put('/users/:id', ({ params, body }) => {
22  return { userId: params.id, updated: true };
23});

Advanced Route Configuration

typescript

1import { createApp } from '@morojs/moro';
2import { z } from 'zod';
3
4const app = createApp();
5
6const CreateUserSchema = z.object({
7  name: z.string().min(1).max(100),
8  email: z.string().email(),
9  age: z.number().min(18).max(120)
10});
11
12// Chainable API style - Recommended
13app.post('/users')
14  .body(CreateUserSchema)
15  .auth({ roles: ['admin'] })
16  .rateLimit({ requests: 10, window: 60000 })
17  .handler(async ({ body }) => {
18    // body is now fully typed and validated
19    // Middleware runs in optimal order automatically
20    const user = await createUser(body);
21    return { success: true, user };
22  });

Route Patterns

MoroJS supports a variety of route patterns, from simple static routes to complex parameterized paths.

Supported Route Patterns

typescript

1// Static routes
2app.get('/api/health').handler(() => ({ status: 'ok' }));
3
4// Named parameters
5app.get('/users/:id').handler(({ params }) => ({ userId: params.id }));
6app.get('/users/:id/posts/:postId').handler(({ params }) => ({ ...params }));
7
8// Optional parameters
9app.get('/posts/:id?').handler(({ params }) => ({ postId: params.id }));
10
11// Wildcard routes
12app.get('/files/*').handler(({ params }) => ({ path: params['*'] }));
13
14// Query parameters (automatically parsed)
15app.get('/search')
16  .query(z.object({
17    q: z.string(),
18    limit: z.coerce.number().default(10)
19  }))
20  .handler(({ query }) => {
21    return { results: search(query.q, query.limit) };
22  });
23
24// Route groups with common prefix
25app.group('/api/v1', (group) => {
26  group.get('/users').handler(getUsersHandler);
27  group.post('/users').handler(createUserHandler);
28  group.get('/users/:id').handler(getUserHandler);
29});

Intelligent Middleware System

Middleware runs in an optimal order automatically. Authentication before authorization, validation early, caching optimally placed—all handled for you.

Middleware with Automatic Ordering

typescript

1app.get('/protected-data')
2  .use(async ({ headers }) => {
3    // Authentication runs first
4    const token = headers.authorization?.replace('Bearer ', '');
5    if (!token) throw new Error('No token provided');
6    return { user: await verifyToken(token) };
7  })
8  .use(async ({ context }) => {
9    // Authorization runs after authentication
10    if (!context.user.hasPermission('read:data')) {
11      throw new Error('Insufficient permissions');
12    }
13  })
14  .cache({ ttl: 300000, key: (ctx) => `data:${ctx.user.id}` })
15  .rateLimit({ requests: 100, window: 3600000, key: (ctx) => ctx.user.id })
16  .handler(async ({ context }) => {
17    // All middleware has run in optimal order
18    return await getProtectedData(context.user);
19  });

Automatic Ordering

  • 1Request parsing
  • 2Authentication
  • 3Authorization
  • 4Validation
  • 5Rate limiting
  • 6Caching
  • 7Handler execution

Performance Benefits

  • No manual ordering needed
  • Optimal execution path
  • Early exit on failures
  • Compile-time optimization
  • Type-safe context passing

Route Compilation & Performance

At application startup, MoroJS analyzes all your routes and creates an optimized execution plan. Routes are compiled, middleware chains are optimized, and type-safe handlers are generated.

Route Compilation Process

  • Builds optimal middleware chains
  • Pre-compiles route matchers
  • Generates type-safe handlers
  • Optimizes for common patterns

Route Compilation Example

typescript

1// Development: Route definition
2app.get('/users/:id')
3  .params(z.object({ id: z.string().uuid() }))
4  .handler(({ params }) => getUserById(params.id));
5
6// Runtime: Compiles to optimized function
7const compiledRoute = {
8  method: 'GET',
9  pattern: /^/users/([0-9a-f-]{36})$/,
10  paramNames: ['id'],
11  middlewareChain: [
12    validateParams,
13    executeHandler
14  ],
15  handler: (ctx) => {
16    // Pre-validated, type-safe execution
17    return getUserById(ctx.params.id);
18  }
19};

Best Practices

Do

  • • Use descriptive route patterns
  • • Define validation schemas
  • • Group related routes together
  • • Leverage automatic middleware ordering
  • • Use type-safe parameter extraction
  • • Define response schemas for documentation

Don't

  • • Manually order middleware unnecessarily
  • • Skip input validation
  • • Use overly complex route patterns
  • • Ignore TypeScript warnings
  • • Mix business logic in middleware
  • • Forget to handle errors properly

Next Steps