Skip to main content
Glama
app.ts8.7 kB
// NestJS Complete Application Template import { Controller, Get, Post, Put, Delete, Body, Param, Query, UseGuards, Injectable, Module, NestFactory } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiQuery, ApiParam } from '@nestjs/swagger'; import { IsString, IsEmail, IsOptional, IsEnum, MinLength } from 'class-validator'; import { JwtAuthGuard } from './auth/jwt-auth.guard'; // ============================================ // DTOs (Data Transfer Objects) // ============================================ export class CreateUserDto { @IsEmail() email: string; @IsString() @MinLength(2) name: string; @IsString() @MinLength(8) password: string; } export class UpdateUserDto { @IsOptional() @IsString() name?: string; @IsOptional() @IsString() bio?: string; } export class CreatePostDto { @IsString() @MinLength(1) title: string; @IsString() content: string; @IsOptional() @IsEnum(['draft', 'published']) status?: 'draft' | 'published'; } export class QueryPostDto { @IsOptional() @IsString() search?: string; @IsOptional() @IsEnum(['draft', 'published']) status?: 'draft' | 'published'; @IsOptional() limit?: number = 20; @IsOptional() offset?: number = 0; } // ============================================ // Entities // ============================================ export interface User { id: string; email: string; name: string; bio?: string; createdAt: Date; updatedAt: Date; } export interface Post { id: string; title: string; content: string; authorId: string; status: 'draft' | 'published'; views: number; createdAt: Date; publishedAt?: Date; } // ============================================ // Services // ============================================ @Injectable() export class UsersService { private users: Map<string, User> = new Map(); private idCounter = 1; async findAll(): Promise<User[]> { return Array.from(this.users.values()); } async findById(id: string): Promise<User | undefined> { return this.users.get(id); } async findByEmail(email: string): Promise<User | undefined> { return Array.from(this.users.values()).find(u => u.email === email); } async create(dto: CreateUserDto): Promise<User> { const id = String(this.idCounter++); const user: User = { id, email: dto.email, name: dto.name, createdAt: new Date(), updatedAt: new Date(), }; this.users.set(id, user); return user; } async update(id: string, dto: UpdateUserDto): Promise<User | undefined> { const user = this.users.get(id); if (!user) return undefined; const updated = { ...user, ...dto, updatedAt: new Date() }; this.users.set(id, updated); return updated; } async delete(id: string): Promise<boolean> { return this.users.delete(id); } } @Injectable() export class PostsService { private posts: Map<string, Post> = new Map(); private idCounter = 1; async findAll(query: QueryPostDto): Promise<{ data: Post[]; total: number }> { let posts = Array.from(this.posts.values()); if (query.status) { posts = posts.filter(p => p.status === query.status); } if (query.search) { const search = query.search.toLowerCase(); posts = posts.filter(p => p.title.toLowerCase().includes(search) || p.content.toLowerCase().includes(search) ); } const total = posts.length; const data = posts.slice(query.offset, query.offset! + query.limit!); return { data, total }; } async findById(id: string): Promise<Post | undefined> { return this.posts.get(id); } async create(dto: CreatePostDto, authorId: string): Promise<Post> { const id = String(this.idCounter++); const post: Post = { id, title: dto.title, content: dto.content, authorId, status: dto.status || 'draft', views: 0, createdAt: new Date(), }; this.posts.set(id, post); return post; } async publish(id: string): Promise<Post | undefined> { const post = this.posts.get(id); if (!post) return undefined; post.status = 'published'; post.publishedAt = new Date(); return post; } async incrementViews(id: string): Promise<number> { const post = this.posts.get(id); if (!post) return 0; post.views++; return post.views; } async delete(id: string): Promise<boolean> { return this.posts.delete(id); } } // ============================================ // Controllers // ============================================ @ApiTags('users') @Controller('users') export class UsersController { constructor(private readonly usersService: UsersService) { } @Get() @ApiOperation({ summary: 'Get all users' }) @ApiResponse({ status: 200, description: 'List of users' }) async findAll(): Promise<User[]> { return this.usersService.findAll(); } @Get(':id') @ApiOperation({ summary: 'Get user by ID' }) @ApiParam({ name: 'id', description: 'User ID' }) @ApiResponse({ status: 200, description: 'User found' }) @ApiResponse({ status: 404, description: 'User not found' }) async findOne(@Param('id') id: string): Promise<User | undefined> { return this.usersService.findById(id); } @Post() @ApiOperation({ summary: 'Create a new user' }) @ApiResponse({ status: 201, description: 'User created' }) async create(@Body() dto: CreateUserDto): Promise<User> { return this.usersService.create(dto); } @Put(':id') @UseGuards(JwtAuthGuard) @ApiBearerAuth() @ApiOperation({ summary: 'Update user' }) async update(@Param('id') id: string, @Body() dto: UpdateUserDto): Promise<User | undefined> { return this.usersService.update(id, dto); } @Delete(':id') @UseGuards(JwtAuthGuard) @ApiBearerAuth() @ApiOperation({ summary: 'Delete user' }) async delete(@Param('id') id: string): Promise<{ deleted: boolean }> { const deleted = await this.usersService.delete(id); return { deleted }; } } @ApiTags('posts') @Controller('posts') export class PostsController { constructor(private readonly postsService: PostsService) { } @Get() @ApiOperation({ summary: 'Get all posts' }) @ApiQuery({ name: 'search', required: false }) @ApiQuery({ name: 'status', required: false, enum: ['draft', 'published'] }) async findAll(@Query() query: QueryPostDto) { return this.postsService.findAll(query); } @Get(':id') @ApiOperation({ summary: 'Get post by ID' }) async findOne(@Param('id') id: string) { const post = await this.postsService.findById(id); if (post) { await this.postsService.incrementViews(id); } return post; } @Post() @UseGuards(JwtAuthGuard) @ApiBearerAuth() @ApiOperation({ summary: 'Create a new post' }) async create(@Body() dto: CreatePostDto) { // In real app, get authorId from request user return this.postsService.create(dto, 'current-user-id'); } @Post(':id/publish') @UseGuards(JwtAuthGuard) @ApiBearerAuth() @ApiOperation({ summary: 'Publish a post' }) async publish(@Param('id') id: string) { return this.postsService.publish(id); } @Delete(':id') @UseGuards(JwtAuthGuard) @ApiBearerAuth() async delete(@Param('id') id: string) { return { deleted: await this.postsService.delete(id) }; } } // ============================================ // Module // ============================================ @Module({ controllers: [UsersController, PostsController], providers: [UsersService, PostsService], exports: [UsersService, PostsService], }) export class AppModule { } // ============================================ // Bootstrap // ============================================ async function bootstrap() { const app = await NestFactory.create(AppModule); // Enable CORS app.enableCors(); // Global prefix app.setGlobalPrefix('api'); // Swagger setup would go here await app.listen(3000); console.log('Application running on http://localhost:3000'); } // bootstrap();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/millsydotdev/Code-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server