Skip to content

Examples

Learn by example with practical CurisJS applications.

Overview

This section contains complete, working examples of CurisJS applications. Each example demonstrates specific features and best practices.

Quick Examples

Hello World

The simplest CurisJS application:

typescript
import { Application } from '@curisjs/core';

const app = new Application();

app.get('/', (ctx) => {
  return ctx.json({ message: 'Hello World' });
});

app.listen({ port: 3000 });

JSON API

A basic JSON API with multiple routes:

typescript
import { Application } from '@curisjs/core';

const app = new Application();

// List items
app.get('/api/items', async (ctx) => {
  const items = await db.items.findMany();
  return ctx.json({ items });
});

// Get single item
app.get('/api/items/:id', async (ctx) => {
  const item = await db.items.findById(ctx.params.id);
  
  if (!item) {
    return ctx.json({ error: 'Not found' }, { status: 404 });
  }
  
  return ctx.json({ item });
});

// Create item
app.post('/api/items', async (ctx) => {
  const data = await ctx.request.json();
  const item = await db.items.create(data);
  return ctx.json({ item }, { status: 201 });
});

app.listen({ port: 3000 });

With Middleware

Using middleware for logging and error handling:

typescript
import { Application, logger, cors } from '@curisjs/core';

const app = new Application();

// Global middleware
app.use(logger());
app.use(cors());

// Error handling
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (error) {
    console.error(error);
    return ctx.json(
      { error: 'Internal Server Error' },
      { status: 500 }
    );
  }
});

// Routes
app.get('/api/users', async (ctx) => {
  const users = await getUsers();
  return ctx.json({ users });
});

app.listen({ port: 3000 });

With Validation

Input validation using schemas:

typescript
import { Application, z } from '@curisjs/core';

const app = new Application();

const createUserSchema = z.object({
  name: z.string().min(2).max(100),
  email: z.string().email(),
  age: z.number().min(18).max(120),
});

app.post('/api/users', async (ctx) => {
  const body = await ctx.request.json();
  
  // Validate input
  const result = createUserSchema.safeParse(body);
  
  if (!result.success) {
    return ctx.json(
      { 
        error: 'Validation failed',
        issues: result.error.issues 
      },
      { status: 422 }
    );
  }
  
  const user = await createUser(result.data);
  return ctx.json({ user }, { status: 201 });
});

app.listen({ port: 3000 });

Complete Applications

RESTful API

A complete REST API with CRUD operations:

typescript
import { Application, z } from '@curisjs/core';
import { User } from './models/User';

const app = new Application();

// Schemas
const createUserSchema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
});

const updateUserSchema = createUserSchema.partial();

// List users
app.get('/api/users', async (ctx) => {
  const page = parseInt(ctx.url.searchParams.get('page') || '1');
  const limit = parseInt(ctx.url.searchParams.get('limit') || '10');
  
  const users = await User.findMany({
    limit,
    offset: (page - 1) * limit,
  });
  
  const total = await User.count();
  
  return ctx.json({
    data: users,
    meta: {
      page,
      limit,
      total,
      totalPages: Math.ceil(total / limit),
    },
  });
});

// Get user
app.get('/api/users/:id', async (ctx) => {
  const user = await User.findById(ctx.params.id);
  
  if (!user) {
    return ctx.json({ error: 'User not found' }, { status: 404 });
  }
  
  return ctx.json({ data: user });
});

// Create user
app.post('/api/users', async (ctx) => {
  const body = await ctx.request.json();
  const result = createUserSchema.safeParse(body);
  
  if (!result.success) {
    return ctx.json({
      error: 'Validation failed',
      issues: result.error.issues,
    }, { status: 422 });
  }
  
  const user = await User.create(result.data);
  return ctx.json({ data: user }, { status: 201 });
});

// Update user
app.put('/api/users/:id', async (ctx) => {
  const user = await User.findById(ctx.params.id);
  
  if (!user) {
    return ctx.json({ error: 'User not found' }, { status: 404 });
  }
  
  const body = await ctx.request.json();
  const result = updateUserSchema.safeParse(body);
  
  if (!result.success) {
    return ctx.json({
      error: 'Validation failed',
      issues: result.error.issues,
    }, { status: 422 });
  }
  
  await user.update(result.data);
  return ctx.json({ data: user });
});

// Delete user
app.delete('/api/users/:id', async (ctx) => {
  const user = await User.findById(ctx.params.id);
  
  if (!user) {
    return ctx.json({ error: 'User not found' }, { status: 404 });
  }
  
  await user.delete();
  return new Response(null, { status: 204 });
});

app.listen({ port: 3000 });

Authentication API

API with authentication and protected routes:

typescript
import { Application, z } from '@curisjs/core';
import { sign, verify } from 'jsonwebtoken';

const app = new Application();

const JWT_SECRET = process.env.JWT_SECRET || 'secret';

// Auth middleware
const auth = async (ctx, next) => {
  const token = ctx.request.headers.get('Authorization')?.replace('Bearer ', '');
  
  if (!token) {
    return ctx.json({ error: 'Unauthorized' }, { status: 401 });
  }
  
  try {
    const payload = verify(token, JWT_SECRET);
    ctx.state.user = payload;
    await next();
  } catch (error) {
    return ctx.json({ error: 'Invalid token' }, { status: 401 });
  }
};

// Public routes
app.post('/api/register', async (ctx) => {
  const { email, password } = await ctx.request.json();
  
  // Hash password and create user
  const user = await createUser({ email, password });
  
  const token = sign({ userId: user.id }, JWT_SECRET, { expiresIn: '7d' });
  
  return ctx.json({ user, token }, { status: 201 });
});

app.post('/api/login', async (ctx) => {
  const { email, password } = await ctx.request.json();
  
  const user = await findUserByCredentials(email, password);
  
  if (!user) {
    return ctx.json({ error: 'Invalid credentials' }, { status: 401 });
  }
  
  const token = sign({ userId: user.id }, JWT_SECRET, { expiresIn: '7d' });
  
  return ctx.json({ user, token });
});

// Protected routes
app.get('/api/profile', auth, async (ctx) => {
  const user = await User.findById(ctx.state.user.userId);
  return ctx.json({ user });
});

app.put('/api/profile', auth, async (ctx) => {
  const user = await User.findById(ctx.state.user.userId);
  const updates = await ctx.request.json();
  
  await user.update(updates);
  return ctx.json({ user });
});

app.listen({ port: 3000 });

File Upload API

Handling file uploads:

typescript
import { Application } from '@curisjs/core';
import { writeFile } from 'node:fs/promises';
import { join } from 'node:path';

const app = new Application();

app.post('/api/upload', async (ctx) => {
  const formData = await ctx.request.formData();
  const file = formData.get('file') as File;
  
  if (!file) {
    return ctx.json({ error: 'No file provided' }, { status: 400 });
  }
  
  // Validate file type
  if (!file.type.startsWith('image/')) {
    return ctx.json({ error: 'Only images allowed' }, { status: 400 });
  }
  
  // Validate file size (5MB max)
  if (file.size > 5 * 1024 * 1024) {
    return ctx.json({ error: 'File too large' }, { status: 400 });
  }
  
  // Save file
  const filename = `${Date.now()}-${file.name}`;
  const filepath = join('uploads', filename);
  
  const buffer = await file.arrayBuffer();
  await writeFile(filepath, Buffer.from(buffer));
  
  return ctx.json({
    filename,
    size: file.size,
    type: file.type,
    url: `/uploads/${filename}`,
  }, { status: 201 });
});

// Serve uploaded files
app.get('/uploads/:filename', async (ctx) => {
  const filepath = join('uploads', ctx.params.filename);
  
  try {
    const file = await Bun.file(filepath);
    return new Response(file);
  } catch {
    return ctx.json({ error: 'File not found' }, { status: 404 });
  }
});

app.listen({ port: 3000 });

Runtime-Specific Examples

Node.js Server

typescript
import { Application } from '@curisjs/core';
import { nodeAdapter } from '@curisjs/core/adapters';
import { createServer } from 'node:http';

const app = new Application();

app.get('/', (ctx) => ctx.json({ runtime: 'Node.js' }));

const server = createServer(nodeAdapter(app));
server.listen(3000);

Bun Server

typescript
import { Application } from '@curisjs/core';

const app = new Application();

app.get('/', (ctx) => ctx.json({ runtime: 'Bun' }));

Bun.serve({
  port: 3000,
  fetch: app.fetch,
});

Deno Server

typescript
import { Application } from '@curisjs/core';

const app = new Application();

app.get('/', (ctx) => ctx.json({ runtime: 'Deno' }));

Deno.serve({ port: 3000 }, app.fetch);

Cloudflare Workers

typescript
import { Application } from '@curisjs/core';

const app = new Application();

app.get('/', (ctx) => ctx.json({ runtime: 'Cloudflare Workers' }));

export default {
  fetch: app.fetch,
};

Source Code

Full source code for these examples is available in the repository:

Next Steps

Released under the MIT License.