Examples
Simple API Example
A complete working REST API with CRUD operations, validation, and error handling. Copy and customize.
Complete Working Example
typescript
1import { createApp } from '@morojs/moro';
2import { z } from 'zod';
3
4const app = await 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 .handler((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 .handler((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 a success boolean
- Type-safe throughout - TypeScript knows what's available
Key Features Highlighted
Type-Safe Validationtypescript
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 .handler((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 Responsestypescript
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
Scaffold a project with the CLI, drop this code into src/index.ts, and run it:
bash
1# Scaffold a new project (Zod is included by default)
2npx @morojs/cli init my-api
3cd my-api
4
5# Replace src/index.ts with the example above, then:
6npm run devTest the API
GET http://localhost:3000/users
POST http://localhost:3000/users
GET http://localhost:3000/users/1