Features
Docs
CLI
Benchmarks
Examples

© 2024 MoroJs

Simple API Example

A complete working REST API with CRUD operations, validation, and error handling. Copy and customize.

Complete Working Example

1import { createApp } from '@morojs/moro';
2import { z } from 'zod';
3
4const app = createApp();
5
6// User schema for validation
7const UserSchema = z.object({
8  name: z.string().min(1),
9  email: z.string().email(),
10  age: z.number().min(18).optional()
11});
12
13// In-memory store (replace with database in production)
14const users: z.infer<typeof UserSchema>[] = [];
15let nextId = 1;
16
17// GET /users - List all users
18app.get('/users', () => {
19  return { success: true, data: users };
20});
21
22// GET /users/:id - Get user by ID
23app.get('/users/:id', ({ params }) => {
24  const user = users.find(u => u.id === parseInt(params.id));
25  if (!user) {
26    return { success: false, error: 'User not found' };
27  }
28  return { success: true, data: user };
29});
30
31// POST /users - Create new user
32app.post('/users')
33  .validate({ body: UserSchema })
34  .handle(({ req }) => {
35    const newUser = {
36      id: nextId++,
37      ...req.body
38    };
39    users.push(newUser);
40    return { success: true, data: newUser };
41  });
42
43// PUT /users/:id - Update user
44app.put('/users/:id')
45  .validate({ body: UserSchema.partial() })
46  .handle(({ req }) => {
47    const userIndex = users.findIndex(u => u.id === parseInt(req.params.id));
48    if (userIndex === -1) {
49      return { success: false, error: 'User not found' };
50    }
51    users[userIndex] = { ...users[userIndex], ...req.body };
52    return { success: true, data: users[userIndex] };
53  });
54
55// DELETE /users/:id - Delete user
56app.delete('/users/:id', ({ params }) => {
57  const userIndex = users.findIndex(u => u.id === parseInt(params.id));
58  if (userIndex === -1) {
59    return { success: false, error: 'User not found' };
60  }
61  users.splice(userIndex, 1);
62  return { success: true, message: 'User deleted' };
63});
64
65app.listen(3000, () => {
66  console.log('API running on http://localhost:3000');
67});

What This Does

  • Creates a complete REST API with CRUD operations
  • Uses Zod for validation and automatic type inference
  • Implements standardized response patterns with success boolean
  • Type-safe throughout - TypeScript knows what's available

Key Features Highlighted

Type-Safe Validation

1const UserSchema = z.object({
2  name: z.string().min(1),
3  email: z.string().email()
4});
5
6// TypeScript automatically knows the type!
7app.post('/users')
8  .validate({ body: UserSchema })
9  .handle(({ req }) => {
10    const body = req.body;
11    // body.name: string
12    // body.email: string
13    // TypeScript autocomplete works!
14    return { success: true, data: body };
15  });

Standardized Responses

1// Success response
2return { success: true, data: user };
3
4// Error response
5return { success: false, error: 'User not found' };
6
7// Frontend can use discriminated unions
8if (result.success) {
9  // TypeScript knows result.data exists
10} else {
11  // TypeScript knows result.error exists
12}

Try It Yourself

Copy the code above, save it as server.ts, and run:

1npm install @morojs/moro zod
2npx tsx server.ts

Test the API

GET http://localhost:3000/users
POST http://localhost:3000/users
GET http://localhost:3000/users/1

Next Steps