Getting Started with EdgeMaster
This guide will help you build your first edge application with EdgeMaster in just a few minutes.
Prerequisites
Before you begin, ensure you have:
- Node.js 16 or higher
- npm or yarn
- Cloudflare account (for deployment)
- Basic understanding of TypeScript/JavaScript
- Familiarity with async/await
Installation
1. Install EdgeMaster
npm install edge-master
2. Install Development Dependencies
For Cloudflare Workers:
npm install -D wrangler @cloudflare/workers-types typescript
Your First Route
Let's create a simple "Hello World" API.
Step 1: Create Project Structure
mkdir my-edge-app
cd my-edge-app
npm init -y
npm install edge-master
Step 2: Create src/index.ts
import { EdgeController, RouteHandler, Task, json } from 'edge-master';
// Create the app
const app = new EdgeController();
// Add a simple route
app.GET('/hello', new RouteHandler(new Task({
do: async () => json({ message: 'Hello World!' })
})));
// Export for Cloudflare Workers
export default {
fetch: (request: Request) => app.handleRequest({ req: request })
};
Step 3: Create wrangler.toml
name = "my-edge-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"
Step 4: Create tsconfig.json
{
"compilerOptions": {
"target": "ES2021",
"module": "ES2022",
"lib": ["ES2021"],
"types": ["@cloudflare/workers-types"],
"strict": true
}
}
Step 5: Run Locally
npx wrangler dev
Visit http://localhost:8787/hello - you should see:
{
"message": "Hello World!"
}
🎉 Congratulations! You've created your first EdgeMaster application!
Adding More Routes
Let's add more functionality to your application.
HTTP Method Helpers
import { json, badRequest, parseJSON } from 'edge-master';
// GET route
app.GET('/users', new RouteHandler(new Task({
do: async () => json({ users: [] })
})));
// POST route
app.POST('/users', new RouteHandler(new Task({
do: async ({ req }) => {
const body = await parseJSON(req);
if (!body.name || !body.email) {
return badRequest('Name and email are required');
}
return json({ user: body }, { status: 201 });
}
})));
// PUT route
app.PUT('/users/:id', new RouteHandler(new Task({
do: async ({ req }) => {
const id = new URL(req.url).pathname.split('/').pop();
const body = await parseJSON(req);
return json({ user: { id, ...body } });
}
})));
// DELETE route
app.DELETE('/users/:id', new RouteHandler(new Task({
do: async ({ req }) => {
const id = new URL(req.url).pathname.split('/').pop();
return json({ message: 'User deleted', id });
}
})));
Adding Interceptors
Interceptors are middleware that run before or after route handling.
CORS Support
import { corsInterceptor } from 'edge-master';
app.addInterceptor(corsInterceptor({
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: false
}));
Request Logging
import { loggingInterceptor } from 'edge-master';
const { request, response } = loggingInterceptor({
level: 'info',
logTiming: true
});
app.addInterceptor(request); // Log incoming requests
app.addInterceptor(response); // Log outgoing responses
Request & Response Handling
Parsing Request Bodies
import { parseJSON, parseFormData, parseText } from 'edge-master';
app.POST('/api/data', new RouteHandler(new Task({
do: async ({ req }) => {
// Parse JSON body
const jsonData = await parseJSON(req);
// Or parse form data
// const formData = await parseFormData(req);
// Or parse as text
// const textData = await parseText(req);
return json({ received: jsonData });
}
})));
Query Parameters
import { getQuery, parseQuery } from 'edge-master';
app.GET('/search', new RouteHandler(new Task({
do: async ({ req }) => {
// Get single parameter
const query = getQuery(req, 'q');
const page = getQuery(req, 'page') || '1';
// Or get all parameters
const allParams = parseQuery(req);
return json({
query,
page: parseInt(page),
params: Object.fromEntries(allParams)
});
}
})));
Response Helpers
import {
json,
text,
html,
redirect,
notFound,
badRequest,
unauthorized
} from 'edge-master';
// JSON response
app.GET('/data', new RouteHandler(new Task({
do: async () => json({ data: [1, 2, 3] })
})));
// Text response
app.GET('/plain', new RouteHandler(new Task({
do: async () => text('Plain text response')
})));
// HTML response
app.GET('/page', new RouteHandler(new Task({
do: async () => html('<h1>Hello World</h1>')
})));
// Redirect
app.GET('/old-path', new RouteHandler(new Task({
do: async () => redirect('/new-path')
})));
// Error responses
app.GET('/not-found', new RouteHandler(new Task({
do: async () => notFound('Resource not found')
})));
Route Organization
Route Grouping
Organize related routes under a common prefix:
app.group('/api/v1', (api) => {
api.GET('/users', listUsersHandler);
api.POST('/users', createUserHandler);
api.GET('/posts', listPostsHandler);
api.POST('/posts', createPostHandler);
});
// Results in:
// GET /api/v1/users
// POST /api/v1/users
// GET /api/v1/posts
// POST /api/v1/posts
Nested Groups
app.group('/api', (api) => {
api.group('/v1', (v1) => {
v1.GET('/users', usersHandlerV1);
});
api.group('/v2', (v2) => {
v2.GET('/users', usersHandlerV2);
});
});
// Results in:
// GET /api/v1/users
// GET /api/v2/users
Error Handling
Default Error Handling
EdgeMaster automatically handles errors:
- 404 for unmatched routes
- 500 for uncaught errors
Custom Error Handlers
// Custom 404 handler
app.onNotFound(async ({ req }) => {
const url = new URL(req.url);
return json({
error: 'Not Found',
path: url.pathname,
message: `Route ${url.pathname} does not exist`
}, { status: 404 });
});
// Custom error handler
app.onError(async (error, ctx) => {
console.error('Error:', error);
return json({
error: 'Internal Server Error',
message: error.message
}, { status: 500 });
});
Complete Example
Here's a complete REST API with all features:
import {
EdgeController,
RouteHandler,
Task,
json,
parseJSON,
getQuery,
corsInterceptor,
loggingInterceptor,
badRequest,
notFound,
} from 'edge-master';
const app = new EdgeController();
// Add interceptors
app.addInterceptor(corsInterceptor({ origin: '*' }));
const { request, response } = loggingInterceptor();
app.addInterceptor(request);
app.addInterceptor(response);
// In-memory storage
const users = new Map();
// Initialize with sample data
users.set('1', { id: '1', name: 'Alice', email: 'alice@example.com' });
users.set('2', { id: '2', name: 'Bob', email: 'bob@example.com' });
// API routes
app.group('/api', (api) => {
// List users with pagination
api.GET('/users', new RouteHandler(new Task({
do: async ({ req }) => {
const page = parseInt(getQuery(req, 'page') || '1');
const limit = 10;
const userList = Array.from(users.values());
const start = (page - 1) * limit;
const paginatedUsers = userList.slice(start, start + limit);
return json({
users: paginatedUsers,
page,
total: userList.length
});
}
})));
// Get user by ID
api.GET('/users/', new RouteHandler(new Task({
do: async ({ req }) => {
const id = new URL(req.url).pathname.split('/').pop();
const user = users.get(id);
if (!user) {
return notFound(`User ${id} not found`);
}
return json({ user });
}
})));
// Create user
api.POST('/users', new RouteHandler(new Task({
do: async ({ req }) => {
const body = await parseJSON(req);
if (!body.name || !body.email) {
return badRequest('Name and email are required');
}
const user = {
id: (users.size + 1).toString(),
name: body.name,
email: body.email
};
users.set(user.id, user);
return json({ user }, { status: 201 });
}
})));
});
// Error handlers
app.onNotFound(async () => notFound('Endpoint not found'));
app.onError(async (error) => json({ error: error.message }, { status: 500 }));
// Export
export default {
fetch: (request: Request) => app.handleRequest({ req: request })
};
Deployment
Deploy to Cloudflare Workers
# Login to Cloudflare (first time only)
npx wrangler login
# Deploy
npx wrangler deploy
Your application will be deployed to: https://my-edge-app.<your-subdomain>.workers.dev
Environment Variables
Create .dev.vars for local development:
API_KEY=your-api-key-here
JWT_SECRET=your-jwt-secret
For production, use Wrangler secrets:
npx wrangler secret put API_KEY
npx wrangler secret put JWT_SECRET
Access in code:
export default {
fetch: (request: Request, env: any) => {
const apiKey = env.API_KEY;
return app.handleRequest({ req: request, env });
}
};
Next Steps
Now that you have a basic application running, explore more features:
📖 Learn Core Concepts
🔒 Add Authentication
⚡ Improve Performance
💡 Explore Examples
Need Help?
Happy coding! 🚀