Documentation

API Routes

Create RESTful APIs with flexible middleware support and built-in validation.

Creating API Routes

Create API routes by adding a route.ts file in the app/api directory:

app/api/posts/route.ts
import type { ApiContext } from "@lolyjs/core";

export async function GET(ctx: ApiContext) {
  const posts = await getPosts();
  return ctx.Response({ posts });
}

export async function POST(ctx: ApiContext) {
  const post = await createPost(ctx.req.body);
  return ctx.Response({ post }, 201);
}

HTTP Methods

Export functions named after HTTP methods to handle different request types:

app/api/posts/route.ts
import type { ApiContext } from "@lolyjs/core";

export async function GET(ctx: ApiContext) {
  // Handle GET requests
  return ctx.Response({ data: "value" });
}

export async function POST(ctx: ApiContext) {
  // Handle POST requests
  return ctx.Response({ created: true }, 201);
}

export async function PUT(ctx: ApiContext) {
  // Handle PUT requests
  return ctx.Response({ updated: true });
}

export async function DELETE(ctx: ApiContext) {
  // Handle DELETE requests
  return ctx.Response({ deleted: true }, 204);
}

export async function PATCH(ctx: ApiContext) {
  // Handle PATCH requests
  return ctx.Response({ patched: true });
}

Request & Response

Access request data and send responses:

import type { ApiContext } from "@lolyjs/core";

export async function POST(ctx: ApiContext) {
  // Access request data
  const { body, query, params, headers } = ctx.req;
  
  // Access locals (set by middlewares)
  const user = ctx.locals.user;
  
  // Send response
  return ctx.Response(
    { message: "Success", data: body },
    200,
    { "Custom-Header": "value" }
  );
}

API Middlewares

Define middlewares that run before your route handlers:

app/api/protected/route.ts
import type { ApiMiddleware, ApiContext } from "@lolyjs/core";

// Global middleware for all methods
export const beforeApi: ApiMiddleware[] = [
  async (ctx, next) => {
    // Authentication
    const user = await verifyUser(ctx.req);
    ctx.locals.user = user;
    await next();
  },
];

// Method-specific middleware
export const beforePOST: ApiMiddleware[] = [
  async (ctx, next) => {
    // Validation specific to POST
    await next();
  },
];

export async function GET(ctx: ApiContext) {
  const user = ctx.locals.user; // Available from middleware
  return ctx.Response({ user });
}

Validation

Validate request data using Zod schemas:

import type { ApiContext } from "@lolyjs/core";
import { validate } from "@lolyjs/core";
import { z } from "zod";

const postSchema = z.object({
  title: z.string().min(1),
  content: z.string().min(1),
  published: z.boolean().optional(),
});

export async function POST(ctx: ApiContext) {
  try {
    const data = validate(postSchema, ctx.req.body);
    const post = await createPost(data);
    return ctx.Response({ post }, 201);
  } catch (error) {
    // ValidationError is thrown by validate() function
    return ctx.Response({ error: "Validation failed" }, 400);
  }
}