Loading repository dataβ¦
Loading repository dataβ¦
raihansharifrimon / repository
A fast, minimal, Express-like framework for AWS Lambda π
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
Zapix is a lightweight, AWS Lambdaβnative router for building APIs on any AWS framework (Serverless Framework, SST, CDK, or raw Lambda).
Inspired by Express.js, it gives you familiar routing and middleware on top of Lambda functions β simple, fast, and type-safe.
Build serverless APIs faster. No custom routing logic. Zero learning curve.
Express-style Routing
Simple .get(), .post(), .put(), .delete() route definitions.
Middleware Support
Chainable middleware functions for authentication, validation, logging, etc.
Error Handling
Global error capturing and customizable error responses.
Utility Helpers
Response(), body parsing, typed route handlers, and more.
TypeScript-First
Fully typed interface for safer development and better DX.
Framework-Agnostic
Works with any AWS deployment method or plain Lambda code.
Zapix helps you build clean, scalable serverless (AWS Lambda) APIs, without being tied to any framework or complex routing logic.
npm install zapix
If you are building a single Lambda function with many API Gateway routes, Zapix handles route matching for you β just like Express.
Zapix is ideal when:
Example API Gateway paths:
POST /users
GET /users
GET /users/{id}
PUT /users/{id}
DELETE /users/{id}
Zapix lets you define these routes exactly like you would in Express, without writing any custom router logic.
import { Router, Handler } from 'zapix';
const router = new Router();
router.post('/users', createUser);
router.get('/users', readUsers);
router.get('/users/{userId}', readUserInfo);
router.put('/users/{userId}', updateUser);
router.delete('/users/{userId}', deleteUser);
// Fallback route
router.all(() => ({
statusCode: 404,
body: JSON.stringify({ error: 'Route not found' }),
}));
export const handler = Handler(router);
A controller handles your business logic for a route.
import { Response, type RouteHandler } from 'zapix';
export const createUser: RouteHandler = async (event, ctx) => {
try {
const body = event.body; // Zapix automatically parses JSON
// Database logic...
return Response(body);
} catch (error) {
return Response(error, 500);
}
};
Tip: Any function returning Response() is considered a controller.
Middleware runs before a controller.
You can chain multiple middleware functions β each must call next() to continue.
import { type RouteMiddleware } from 'zapix';
const authMiddleware: RouteMiddleware = async (event, ctx, next) => {
try {
// Authentication logic...
return next();
} catch (error) {
return next(error);
}
};
router.post('/users', authMiddleware, createUser);
Tip: Calling next(error) stops the request and sends an error response.
The Router supports global middleware, allowing you to run middleware logic before any route-specific middleware or handler.
This is useful for cross-cutting concerns such as authentication, logging, request validation, rate limiting, and request context setup.
Use router.use() to register one or more global middleware functions.
const router = new Router();
router.use(async (event, context, next) => {
console.log(event, context);
await next();
});
Global middleware runs for every request, regardless of route. Global middleware fully supports async/await:
Global middleware uses the same signature as route middleware:
(event, context, next) =>Promise<void |APIGatewayProxyResultV2>
event β API Gateway eventcontext β Lambda contextnext(error?) β Continues execution or triggers error handlingMiddleware and handlers execute in the following order:
Example:
router.use(globalMiddleware);
router.get('/example', routeMiddleware, handler);
Execution order:
globalMiddleware β routeMiddleware β handler
router.use(async (event, context, next) => {
console.log('Incoming request:', event);
await next();
});
router.use(async (event, context, next) => {
if (!event.headers?.authorization) {
throw new Error('Unauthorized');
}
await next();
});
Payload validation is a common middleware use-case. Zapix middleware makes it simple & easy.
// @/helper/zod.ts
import { type z, ZodError } from 'zod';
const formatZodErrorMessages = (error: ZodError) => {
const errors: Record<string, string> = {};
error.issues.forEach((issue) => {
if (issue.path.length) {
errors[issue.path.join('.')] = issue.message;
} else {
errors['extraField'] = issue.message;
}
});
return errors;
};
export const validateRequest = (schema: z.ZodType, data: unknown) => {
try {
schema.parse(data);
return { success: true };
} catch (err) {
if (err instanceof ZodError) {
return { success: false, errors: formatZodErrorMessages(err) };
}
throw err;
}
};
// schema.ts
import { z } from 'zod';
export const UserValidationSchema = z.object({
name: z.string().min(2).max(20),
email: z.string().email(),
address: z.string().optional(),
});
// index.ts
import { Router, Handler } from 'zapix';
import { z } from 'zod';
import { validateRequest } from '@/helper/zod';
import { UserValidationSchema } from './schema';
const requestValidationMiddleware = (schema: z.ZodType) => {
return async (ctx: any, next: any) => {
const validation = validateRequest(schema, ctx.body);
if (!validation.success) {
return {
statusCode: 400,
body: JSON.stringify({
message: 'Validation failed',
errors: validation.errors,
}),
};
}
return next();
};
};
const router = new Router();
router.post(
'/users',
requestValidationMiddleware(UserValidationSchema),
createUser,
);
router.all(() => ({
statusCode: 404,
body: JSON.stringify({ error: 'Route not found' }),
}));
export const handler = Handler(router);
Tip: Reuse the middleware by passing your Zod schema to apply consistent request validation across multiple APIs.
You can test Lambda events locally using tools like:
Zapix works with any Lambda simulator.
MIT License
Β© Raihan Sharif, Software Engineer | BrillMark LLC