LoginGet Started

Routes

Overview

Routes in Pure Dev define how your API handles HTTP requests. Each route connects a URL path to a handler function that processes requests and returns responses. Pure Dev provides an integrated environment where you can define routes, implement handlers, and test your API - all in the same interface.

Creating Routes

To create a route in Pure Dev:

  1. Navigate to the Routes section in the left sidebar
  2. Click the "Create Route" button
  3. Select the HTTP method (GET, POST, PUT, PATCH, DELETE)
  4. Define the route path (e.g. /blog/posts/:id)
  5. Implement your handler function

Route Implementation

Routes in Pure Dev use a handler function that receives a pure object:

import { parse } from "date-fns";

export async function handler(pure: Pure): Promise<PureResponse> {
  const { user } = pure.var;
  const { since } = pure.req.queries;
  const sinceDate = parse(since, "mm/dd/yyyy", new Date());

  const blogs = await pure.db
    .selectFrom("blog.posts")
    .where("user_id", "=", user.id)
    .select(["slug"])
    .where("created_at", ">", sinceDate)
    .execute();

  return pure.json(blogs.map((a) => a.id));
}

Route Organization

Pure Dev organizes routes hierarchically:

  • Routes are grouped by resource (Auth, Blog, Portfolio, Pokemon)
  • Each group can be expanded/collapsed in the sidebar
  • Routes show their HTTP method and path for easy reference
  • You can use the search bar to find specific routes

Request Data Access

Path Parameters

Access URL parameters using pure.req.params:

// For route /blog/posts/:id
const { id } = pure.req.params;

Query Parameters

Access query parameters using pure.req.queries:

// For URL query ?since=01/15/2023
const { since } = pure.req.queries;

Request Body

Access the request body using pure.req.body:

// For JSON body
const { title, content, slug } = pure.req.body;

Headers

Access request headers using pure.req.headers:

const { authorization } = pure.req.headers;

Request Variables

Access variables set by middleware using pure.var:

const { user } = pure.var;

TypeScript Integration

Define types for request and response data to ensure type safety:

// Define request body type
type Definition = {
  title: string;
  content: string;
  slug: string;
};

// Use in your handler
const { title, content, slug } = pure.req.body as Definition;

Database Operations

Interact with your database using the pure.db object:

// Query data
const blogs = await pure.db
  .selectFrom("blog.posts")
  .where("user_id", "=", user.id)
  .select(["slug"])
  .where("created_at", ">", sinceDate)
  .execute();
  
// Insert data
const newPost = await pure.db
  .insertInto("blog.posts")
  .values({
    title,
    content,
    slug,
    user_id: user.id,
    created_at: new Date()
  })
  .returning(["id"])
  .executeTakeFirst();

Response Generation

Return responses using helper methods:

// Return JSON response
return pure.json(data);

// Return with status code
return pure.json(data, 201);

// Return text response
return pure.text("OK");

// Return HTML response
return pure.html("<h1>Hello World</h1>");

// Return error response
return pure.error("Not found", 404);

// Redirect response
return pure.redirect("/login");

Real-Time Testing

Test your routes directly in the Pure Dev interface using the integrated testing panel:

Request Configuration

  1. Body: Define and edit request body with TypeScript support

    // Example body TypeScript definition
    type Definition = {
      title: string;
      content: string;
      slug: string;
    };
    
  2. Path Parameters: Configure values for path parameters defined in your route

  3. Query Parameters: Set key-value pairs for query string parameters

    since: 1/12/2022
    
  4. Headers: Set request headers like Authorization

    Authorization: Bearer token123
    

Real-Time Execution

  1. Implement your route handler
  2. Configure request parameters in the testing panel
  3. Pure Dev automatically executes the request as you type, providing instant feedback
  4. View the response and interactive logs for debugging in real-time

Interactive Logs

Pure Dev provides real-time logs that show:

  • Database queries being executed
  • Query parameters and results
  • Request processing steps
  • Execution time and performance metrics

Cookie Management

Manage cookies in your routes:

// Read a cookie
const sessionId = pure.getCookie("session");

// Set a cookie
pure.setCookie("preference", "dark-mode", {
  maxAge: 60 * 60 * 24 * 30, // 30 days
  httpOnly: true,
  secure: true
});

// Delete a cookie
pure.deleteCookie("temporary");

Variable Storage

Pure Dev provides a powerful variable system that allows data to be shared between middleware and route handlers:

// Store data in a route handler
pure.set("user", { id: 123, role: "admin" });

// Access data
const { user } = pure.var;

Middleware Variables

A common pattern is to set up variables in middleware functions, making data available to all routes that use that middleware:

// In an authentication middleware
export async function authMiddleware(pure: Pure, next: NextFunction): Promise<PureResponse> {
  const token = pure.req.headers.authorization?.split(' ')[1];
  
  if (token) {
    const user = await verifyAndGetUser(token);
    pure.set("user", user); // Make user available to all route handlers
  }
  
  return next();
}

For more details on creating and using middlewares, see the Middlewares documentation.

Variable Manager

Pure Dev includes a Variable Manager that allows you to configure mock data for development and testing:

  1. Access the Variable Manager in the Pure Dev interface
  2. Define mock variables (like user, organization, etc.)
  3. Set default values for these variables
  4. Use these variables in your routes during development

This feature is particularly useful for:

  • Testing routes without authentication in place
  • Simulating different user roles and permissions
  • Developing features that depend on middleware-provided data
  • Creating consistent test environments

All routes can access variables set through the Variable Manager via pure.var, making development and testing more efficient.

Complete Example

Here's a complete route handling an API endpoint for blog posts:

import { parse } from "date-fns";

// Define type for blog post
type BlogPost = {
  title: string;
  content: string;
  slug: string;
};

export async function handler(pure: Pure): Promise<PureResponse> {
  // Get authenticated user from middleware
  const { user } = pure.var;
  
  // Get query parameters
  const { since } = pure.req.queries;
  const sinceDate = parse(since, "mm/dd/yyyy", new Date());
  
  try {
    // Query the database
    const blogs = await pure.db
      .selectFrom("blog.posts")
      .where("user_id", "=", user.id)
      .select(["id", "title", "content", "slug"])
      .where("created_at", ">", sinceDate)
      .execute();
    
    // Set a cookie to record the last visit
    pure.setCookie("last_visit", new Date().toISOString(), {
      httpOnly: true,
      maxAge: 60 * 60 * 24
    });
    
    // Return successful response
    return pure.json(blogs.map(blog => ({
      id: blog.id,
      title: blog.title,
      slug: blog.slug,
      url: `/blog/${blog.slug}`
    })));
  } catch (error) {
    // Handle errors
    console.error("Failed to fetch blogs:", error);
    return pure.error("Failed to fetch blogs", 500);
  }
}

Best Practices

  1. Use TypeScript Definitions: Define types for request/response data
  2. Handle Errors: Wrap database operations in try/catch blocks
  3. Validate Input: Always validate and sanitize user input
  4. Consistent Responses: Maintain consistent response structures
  5. Use Resource Groups: Organize related routes together
  6. Descriptive Naming: Use clear, descriptive names for routes and handlers
  7. Testing: Use the integrated testing panel to verify route behavior

Next Steps

To learn more about Pure Dev routes, explore these related topics:

  • Middleware Integration
  • Authentication and Authorization
  • Advanced Database Queries
  • Deployment and Publishing