Skip to main content

backend

Backend development with Node.js, Express, NestJS, and server patterns

Quellinformationen

Repository
miles990/claude-software-skills
Letzte Quellaktivität
8. Januar 2026 um 05:30
Erkannte Sprache von SKILL.md
Chinesisch
Sterne
26
Forks
6

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
6 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
backend
description
Backend development with Node.js, Express, NestJS, and server patterns
domain
development-stacks
version
1.0.0
tags
["nodejs","express","nestjs","fastify","api","middleware","authentication"]
triggers
{"keywords":{"primary":["backend","server","nodejs","express","nestjs","api","microservice"],"secondary":["fastify","middleware","authentication","rest","graphql","queue"]},"context_boost":["service","endpoint","database","http"],"context_penalty":["frontend","css","ui","mobile"],"priority":"high"}
collaboration
{"prerequisites":[{"skill":"typescript","reason":"Type-safe backend development"}],"delegation_triggers":[{"trigger":"API endpoint design decisions","delegate_to":"api-design","context":"RESTful conventions, versioning, error formats"},{"trigger":"Database schema design or query optimization","delegate_to":"database","context":"Data modeling, indexing strategy"},{"trigger":"Writing tests for services or controllers","delegate_to":"testing-strategies","context":"Integration test patterns, mocking strategies"}],"receives_context_from":[{"skill":"api-design","receives":"[Truncated]"},{"skill":"database","receives":"[Truncated]"}],"provides_context_to":[{"skill":"frontend","provides":"[Truncated]"},{"skill":"testing-strategies","provides":"[Truncated]"}]}
# Backend Development ## Overview Server-side development patterns, frameworks, and best practices for building scalable APIs and services. --- ## Express.js ### Application Structure ```typescript // app.ts import express from 'express'; import helmet from 'helmet'; import cors from 'cors'; import compression from 'compression'; import { errorHandler } from './middleware/errorHandler'; import { requestLogger } from './middleware/requestLogger'; import routes from './routes'; const app = express(); // Security middleware app.use(helmet()); app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(',') || '*', credentials: true, })); // Request processing app.use(compression()); app.use(express.json({ limit: '10kb' })); app.use(express.urlencoded({ extended: true })); // Logging app.use(requestLogger); // Routes app.use('/api/v1', routes); // Health check app.get('/health', (req, res) => { res.json({ status: 'healthy', timestamp: new Date().toISOString() }); }); // Error handling (must be last) app.use(errorHandler); export default app; ``` ### Middleware Patterns ```typescript // Authentication middleware import { Request, Response, NextFunction } from 'express'; import jwt from 'jsonwebtoken'; interface AuthRequest extends Request { user?: { id: string; role: string }; } export function authenticate(req: AuthRequest, res: Response, next: NextFunction) { const token = req.headers.authorization?.replace('Bearer ', ''); if (!token) { return res.status(401).json({ error: 'Authentication required' }); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET!) as { id: string; role: string }; req.user = decoded; next(); } catch { return res.status(401).json({ error: 'Invalid token' }); } } // Authorization middleware export function authorize(...roles: string[]) { return (req: AuthRequest, res: Response, next: NextFunction) => { if (!req.user || !roles.includes(req.user.role)) { return res.status(403).json({ error: 'Forbidden' }); } next(); }; } // Rate limiting import rateLimit from 'express-rate-limit'; export const apiLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, message: { error: 'Too many requests' }, standardHeaders: true, }); // Validation middleware import { z } from 'zod'; export function validate(schema: z.ZodSchema) { return (req: Request, res: Response, next: NextFunction) => { const result = schema.safeParse({ body: req.body, query: req.query, params: req.params, }); if (!result.success) { return res.status(400).json({ error: 'Validation failed', details: result.error.flatten(), }); } req.body = result.data.body; req.query = result.data.query; req.params = result.data.params; next(); }; } ``` ### Error Handling ```typescript // Custom error classes export class AppError extends Error { constructor( public statusCode: number, public message: string, public isOperational = true ) { super(message); Error.captureStackTrace(this, this.constructor); } } export class NotFoundError extends AppError { constructor(resource: string) { super(404, `${resource} not found`); } } export class ValidationError extends AppError { constructor(message: string) { super(400, message); } } // Global error handler export function errorHandler( err: Error, req: Request, res: Response, next: NextFunction ) { console.error('Error:', err); if (err instanceof AppError) { return res.status(err.statusCode).json({ error: err.message, ...(process.env.NODE_ENV === 'development' && { stack: err.stack }), }); } // Mongoose/Prisma errors if (err.name === 'CastError') { return res.status(400).json({ error: 'Invalid ID format' }); } if (err.name === 'ValidationError') { return res.status(400).json({ error: err.message }); } // Default error res.status(500).json({ error: process.env.NODE_ENV === 'production' ? 'Internal server error' : err.message, }); } ``` --- ## NestJS ### Module Structure ```typescript // users/users.module.ts import { Module } from '@nestjs/common'; import { UsersController } from './users.controller'; import { UsersService } from './users.service'; import { PrismaModule } from '../prisma/prisma.module'; @Module({ imports: [PrismaModule], controllers: [UsersController], providers: [UsersService], exports: [UsersService], }) export class UsersModule {} // users/users.controller.ts import { Controller, Get, Post, Put, Delete, Body, Param, Query, UseGuards, HttpCode, HttpStatus, } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger'; import { UsersService } from './users.service'; import { CreateUserDto, UpdateUserDto, QueryUsersDto } from './dto'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { RolesGuard } from '../auth/guards/roles.guard'; import { Roles } from '../auth/decorators/roles.decorator'; @ApiTags('users') @Controller('users') @UseGuards(JwtAuthGuard, RolesGuard) @ApiBearerAuth() export class UsersController { constructor(private readonly usersService: UsersService) {} @Get() @ApiOperation({ summary: 'List users' }) async findAll(@Query() query: QueryUsersDto) { return this.usersService.findAll(query); } @Get(':id') @ApiOperation({ summary: 'Get user by ID' }) async findOne(@Param('id') id: string) { return this.usersService.findOne(id); } @Post() @Roles('admin') @ApiOperation({ summary: 'Create user' }) async create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); } @Put(':id') @ApiOperation({ summary: 'Update user' }) async update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) { return this.usersService.update(id, updateUserDto); } @Delete(':id') @Roles('admin') @HttpCode(HttpStatus.NO_CONTENT) @ApiOperation({ summary: 'Delete user' }) async remove(@Param('id') id: string) { await this.usersService.remove(id); } } ``` ### DTOs with Validation ```typescript // users/dto/create-user.dto.ts import { IsEmail, IsString, MinLength, IsOptional, IsEnum } from 'class-validator'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; export enum UserRole { USER = 'user', ADMIN = 'admin', } export class CreateUserDto { @ApiProperty({ example: 'user@example.com' }) @IsEmail() email: string; @ApiProperty({ minLength: 8 }) @IsString() @MinLength(8) password: string; @ApiPropertyOptional() @IsOptional() @IsString() name?: string; @ApiPropertyOptional({ enum: UserRole, default: UserRole.USER }) @IsOptional() @IsEnum(UserRole) role?: UserRole = UserRole.USER; } // Partial DTO for updates import { PartialType, OmitType } from '@nestjs/swagger'; export class UpdateUserDto extends PartialType( OmitType(CreateUserDto, ['password'] as const) ) {} ``` ### Services with Dependency Injection ```typescript // users/users.service.ts import { Injectable, NotFoundException } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { CreateUserDto, UpdateUserDto, QueryUsersDto } from './dto'; import * as argon2 from 'argon2'; @Injectable() export class UsersService { constructor(private prisma: PrismaService) {} async findAll(query: QueryUsersDto) { const { page = 1, limit = 10, search } = query; const where = search ? { OR: [ { name: { contains: search, mode: 'insensitive' } }, { email: { contains: search, mode: 'insensitive' } }, ], } : {}; const [users, total] = await Promise.all([ this.prisma.user.findMany({ where, skip: (page - 1) * limit, take: limit, select: { id: true, email: true, name: true, role: true, createdAt: true, }, }), this.prisma.user.count({ where }), ]); return { data: users, meta: { page, limit, total, totalPages: Math.ceil(total / limit), }, }; } async findOne(id: string) { const user = await this.prisma.user.findUnique({ where: { id }, select: { id: true, email: true, name: true, role: true, createdAt: true, }, }); if (!user) { throw new NotFoundException(`User with ID ${id} not found`); } return user; } async create(dto: CreateUserDto) { const hashedPassword = await argon2.hash(dto.password); return this.prisma.user.create({ data: { ...dto, password: hashedPassword, }, select: { id: true, email: true, name: true, role: true, }, }); } async update(id: string, dto: UpdateUserDto) { await this.findOne(id); // Throws if not found return this.prisma.user.update({ where: { id }, data: dto, select: { id: true, email: true, name: true, role: true, }, }); } async remove(id: string) { await this.findOne(id); // Throws if not found await this.prisma.user.delete({ where: { id } }); } } ``` --- ## Database Integration ### Prisma ORM ```typescript // prisma/schema.prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) email String @unique password String name String? role Role @default(USER) posts Post[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Post { id String @id @default(cuid()) title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } enum Role { USER ADMIN } // Prisma service import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; @Injectable()
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen