api-endpoint
Personal backup of Claude Code skills and plugins
5 stars0 forksUpdated Jan 26, 2026
npx skills add https://github.com/vapvarun/claude-backup --skill api-endpointSKILL.md
API Endpoint Development
Best practices for building secure, maintainable REST APIs.
Endpoint Structure
Express/Node.js Template
import { Router, Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { authenticate, authorize } from '../middleware/auth';
import { validate } from '../middleware/validation';
import { asyncHandler } from '../utils/asyncHandler';
import { ApiError } from '../utils/ApiError';
const router = Router();
// Schema definitions
const createUserSchema = z.object({
body: z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
role: z.enum(['user', 'admin']).default('user'),
}),
});
const getUserSchema = z.object({
params: z.object({
id: z.string().uuid(),
}),
});
// Endpoints
router.post(
'/users',
authenticate,
authorize('admin'),
validate(createUserSchema),
asyncHandler(async (req: Request, res: Response) => {
const user = await UserService.create(req.body);
res.status(201).json({
success: true,
data: user,
});
})
);
router.get(
'/users/:id',
authenticate,
validate(getUserSchema),
asyncHandler(async (req: Request, res: Response) => {
const user = await UserService.findById(req.params.id);
if (!user) {
throw new ApiError(404, 'User not found');
}
res.json({
success: true,
data: user,
});
})
);
export default router;
Input Validation
Zod Schema Validation
import { z } from 'zod';
// Basic schemas
const emailSchema = z.string().email().toLowerCase();
const passwordSchema = z.string().min(8).max(100);
const uuidSchema = z.string().uuid();
// Complex object schema
const createPostSchema = z.object({
body: z.object({
title: z.string().min(1).max(255).trim(),
content: z.string().min(10).max(10000),
tags: z.array(z.string()).max(10).optional(),
status: z.enum(['draft', 'published']).default('draft'),
publishAt: z.string().datetime().optional(),
}),
});
// Query params schema
const listPostsSchema = z.object({
query: z.object({
page: z.coerce.number().int().positive().default(1),
limit: z.coerce.number().int().min(1).max(100).default(20),
status: z.enum(['draft', 'published', 'all']).default('all'),
sortBy: z.enum(['createdAt', 'updatedAt', 'title']).default('createdAt'),
order: z.enum(['asc', 'desc']).default('desc'),
search: z.string().max(100).optional(),
}),
});
// Validation middleware
function validate(schema: z.ZodSchema) {
return async (req: Request, res: Response, next: NextFunction) => {
try {
const validated = await schema.parseAsync({
body: req.body,
query: req.query,
params: req.params,
});
req.body = validated.body ?? req.body;
req.query = validated.query ?? req.query;
req.params = validated.params ?? req.params;
next();
} catch (error) {
if (error instanceof z.ZodError) {
return res.status(400).json({
success: false,
error: {
code: 'VALIDATION_ERROR',
message: 'Validation failed',
details: error.errors.map(e => ({
field: e.path.join('.'),
message: e.message,
})),
},
});
}
next(error);
}
};
}
Input Sanitization
import sanitizeHtml from 'sanitize-html';
import xss from 'xss';
// Sanitize HTML content
function sanitizeContent(content: string): string {
return sanitizeHtml(content, {
allowedTags: ['b', 'i', 'em', 'strong', 'a', 'p', 'br', 'ul', 'ol', 'li'],
allowedAttributes: {
'a': ['href', 'title'],
},
allowedSchemes: ['http', 'https', 'mailto'],
});
}
// Prevent XSS in plain text
function sanitizeText(text: string): string {
return xss(text);
}
// Sanitize file names
function sanitizeFileName(fileName: string): string {
return fileName
.replace(/[^a-zA-Z0-9.-]/g, '_')
.replace(/\.{2,}/g, '.')
.substring(0, 255);
}
Authentication
JWT Authentication
import jwt from 'jsonwebtoken';
import { Request, Response, NextFunction } from 'express';
interface JwtPayload {
userId: string;
role: string;
iat: number;
exp: number;
}
// Generate tokens
function generateTokens(user: User) {
const accessToken = jwt.sign(
{ userId: user.id, role: user.role },
process.env.JWT_SECRET!,
{ expiresIn: '15m' }
);
const refreshToken = jwt.sign(
{ userId: user.id, tokenVersion: user.tokenVersion },
process.env.REFRESH_SECRET!,
{ expiresIn: '7d' }
);
return { accessToken, refreshToken };
}
// Authentication middleware
async function authenticate(req: Request, res: Response, next: NextFunction) {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith('Bearer ')) {
return res.status(401).json({
success: false,
error: { code: 'UNAUTHORIZED', message: 'Miss
...
Repository
vapvarun/claude-backupParent repository
Repository Stats
Stars5
Forks0