Backend API Documentation
NestJS Backend API for GoGrab Space platform - Architecture, Best Practices, and Common Issues
Backend API Documentation
The GoGrab Space Backend API is built with NestJS and MongoDB. This documentation covers architecture, best practices, and common issues to avoid.
📁 Documentation Structure
- MongoDB Best Practices - Database patterns and anti-patterns
- Common Issues - Known issues and solutions
- API Reference - Endpoint documentation
🏗️ Architecture Overview
apis/backend-api/
├── src/
│ ├── app/
│ │ ├── spaces/ # Space management (SpacesController, SpaceModulesController)
│ │ ├── global-modules/ # Global module registry
│ │ ├── backend-auth/ # Authentication (JWT)
│ │ ├── analytics/ # User analytics
│ │ └── common/ # Shared utilities
│ └── main.ts # App bootstrap
⚡ Quick Links
- Space Modules API:
/api/spaces/:spaceId/modules - Global Modules API:
/api/global-modules - Universes API:
/api/spaces/:spaceId/universes
🔴 Critical Rules
1. MongoDB Upsert Operations
NEVER include the same field in both $set and $setOnInsert:
// ❌ WRONG - Causes MongoDB conflict
await collection.updateOne(
{ _id: docId },
{
$set: {
...module, // Contains createdAt!
updatedAt: now
},
$setOnInsert: {
createdAt: now // CONFLICT! Same field in $set
}
},
{ upsert: true }
);
// ✅ CORRECT - createdAt only in $setOnInsert
await collection.updateOne(
{ _id: docId },
{
$set: {
// All fields EXCEPT createdAt
name: dto.name,
updatedAt: now,
// ...other fields
},
$setOnInsert: {
createdAt: now // Only set on insert
}
},
{ upsert: true }
);
See MongoDB Best Practices for more details.
2. ValidationPipe Configuration
The global ValidationPipe must allow flexible DTOs:
// main.ts
app.useGlobalPipes(
new ValidationPipe({
whitelist: false, // DON'T strip unknown properties
forbidNonWhitelisted: false, // DON'T throw on unknown properties
transform: true,
transformOptions: {
enableImplicitConversion: true
}
})
);
Why? Our DTOs are TypeScript interfaces (not classes with decorators), so whitelist: true would strip all properties!
3. Controller Registration
All controllers must be registered in their module:
// spaces.module.ts
@Module({
controllers: [SpacesController, SpaceModulesController], // Both registered!
providers: [SpacesService, SpaceModulesService],
})
export class SpacesModule {}