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:
- Navigate to the Routes section in the left sidebar
- Click the "Create Route" button
- Select the HTTP method (GET, POST, PUT, PATCH, DELETE)
- Define the route path (e.g. /blog/posts/:id)
- 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
-
Body: Define and edit request body with TypeScript support
// Example body TypeScript definition type Definition = { title: string; content: string; slug: string; };
-
Path Parameters: Configure values for path parameters defined in your route
-
Query Parameters: Set key-value pairs for query string parameters
since: 1/12/2022
-
Headers: Set request headers like Authorization
Authorization: Bearer token123
Real-Time Execution
- Implement your route handler
- Configure request parameters in the testing panel
- Pure Dev automatically executes the request as you type, providing instant feedback
- 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:
- Access the Variable Manager in the Pure Dev interface
- Define mock variables (like
user
,organization
, etc.) - Set default values for these variables
- 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
- Use TypeScript Definitions: Define types for request/response data
- Handle Errors: Wrap database operations in try/catch blocks
- Validate Input: Always validate and sanitize user input
- Consistent Responses: Maintain consistent response structures
- Use Resource Groups: Organize related routes together
- Descriptive Naming: Use clear, descriptive names for routes and handlers
- 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