This document describes the OpenAPI/NestJS Swagger decorators that have been added to the Warframe WorldState Parser library to enable automatic API documentation and validation.
npm install @nestjs/swagger class-validator class-transformer reflect-metadataUpdated tsconfig.json to enable decorators:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
// ... other options
}
}The following model files have been fully decorated:
-
WorldStateObject.ts (Base Class)
@ApiPropertyOptionalfor id, activation, expiry@IsString,@IsDate,@IsOptionalvalidators- All child classes inherit these decorators
-
Alert.ts
@ApiPropertyfor mission, rewardTypes@ApiPropertyOptionalfor tag@ValidateNestedfor nested Mission object@Typetransformers for proper class instantiation
-
Mission.ts
- Complete property decorators for all 20+ properties
- Includes validators:
@IsString,@IsInt,@IsBoolean,@IsArray,@Min - Nested validation for Reward object
-
Reward.ts
- Property decorators for items, countedItems, credits, thumbnail, color
- Array validation with
@IsArrayand@IsString({ each: true }) - Complex object schema for countedItems
-
WorldState.ts (Partial)
- Main class with decorators on key properties:
- timestamp, buildLabel, news, events, alerts, sortie, syndicateMissions, fissures
- Demonstrates pattern for array properties with nested objects
- Main class with decorators on key properties:
@ApiProperty({ description: 'Property description' })
@IsString()
propertyName: string;@ApiPropertyOptional({ description: 'Optional property' })
@IsOptional()
@IsString()
optionalProperty?: string;@ApiProperty({ description: 'Date property', type: Date })
@IsDate()
@Type(() => Date)
dateProperty: Date;@ApiProperty({ description: 'Minimum level' })
@IsInt()
@Min(0)
level: number;@ApiProperty({ description: 'Array of items', type: [String] })
@IsArray()
@IsString({ each: true })
items: string[];@ApiProperty({ description: 'Array of objects', type: [ChildClass] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => ChildClass)
objects: ChildClass[];@ApiProperty({ description: 'Nested object', type: () => NestedClass })
@ValidateNested()
@Type(() => NestedClass)
nested: NestedClass;@ApiProperty({
description: 'Complex object',
type: 'array',
items: {
properties: {
field1: { type: 'string', description: 'Field 1' },
field2: { type: 'number', description: 'Field 2' }
}
}
})
@IsArray()
complexObjects: { field1: string; field2: number }[];The following 35+ model files still need decorator implementation:
High Priority (Frequently used in APIs):
- News.ts
- Invasion.ts
- Fissure.ts
- Sortie.ts
- VoidTrader.ts
- Nightwave.ts
- WorldEvent.ts
- DailyDeal.ts
- SyndicateMission.ts
- EarthCycle.ts
- CetusCycle.ts
Medium Priority:
- SortieVariant.ts
- VoidTraderItem.ts
- NightwaveChallenge.ts
- PersistentEnemy.ts
- FlashSale.ts
- GlobalUpgrade.ts
- DarkSector.ts
- ConclaveChallenge.ts
- ConstructionProgress.ts
- CambionCycle.ts
- VallisCycle.ts
- ZarimanCycle.ts
- DuviriCycle.ts
Lower Priority:
- Remaining 15+ supporting models
The WorldState class has 30+ properties that still need decorators. Properties include:
- globalUpgrades, flashSales, invasions, darkSectors
- voidTraders, dailyDeals, simaris, conclaveChallenges
- persistentEnemies, earthCycle, cetusCycle, cambionCycle
- zarimanCycle, weeklyChallenges, constructionProgress
- vallisCycle, nightwave, kuva, arbitration
- sentientOutposts, steelPath, vaultTrader, archonHunt
- duviriCycle, archimedea, calendar, tmp
Once all decorators are in place, you can use these models in a NestJS controller:
import { Controller, Get } from "@nestjs/common";
import { ApiOperation, ApiResponse } from "@nestjs/swagger";
import { WorldState } from "warframe-worldstate-parser";
@Controller("worldstate")
export class WorldStateController {
@Get()
@ApiOperation({ summary: "Get current worldstate" })
@ApiResponse({
status: 200,
description: "Returns current worldstate",
type: WorldState,
})
async getWorldState(): Promise<WorldState> {
// Your logic here
}
@Get("alerts")
@ApiOperation({ summary: "Get active alerts" })
@ApiResponse({
status: 200,
description: "Returns active alerts",
type: [Alert],
})
async getAlerts(): Promise<Alert[]> {
// Your logic here
}
}To generate an OpenAPI specification document:
import { NestFactory } from "@nestjs/core";
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
import { AppModule } from "./app.module";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle("Warframe WorldState API")
.setDescription("Warframe WorldState API using parsed worldstate data")
.setVersion("1.0")
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup("api", app, document);
await app.listen(3000);
}
bootstrap();Access the Swagger UI at http://localhost:3000/api
You can also generate the OpenAPI schema without running a server:
import { NestFactory } from "@nestjs/core";
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
import { writeFileSync } from "fs";
async function generateSchema() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle("Warframe WorldState API")
.setVersion("1.0")
.build();
const document = SwaggerModule.createDocument(app, config);
writeFileSync("./openapi.json", JSON.stringify(document, null, 2));
await app.close();
}
generateSchema();The class-validator decorators enable runtime validation:
import { validate } from "class-validator";
import { plainToClass } from "class-transformer";
import { Alert } from "warframe-worldstate-parser";
// Convert plain object to class instance
const alert = plainToClass(Alert, jsonData);
// Validate
const errors = await validate(alert);
if (errors.length > 0) {
console.log("Validation failed:", errors);
} else {
console.log("Validation successful!");
}- Automatic API Documentation: OpenAPI/Swagger docs generated from decorators
- Type Safety: Ensures API contracts match TypeScript types
- Runtime Validation: Validates incoming data matches expected schema
- Auto-completion: Better IDE support when using these types
- Client Generation: Can generate API clients from OpenAPI spec
- Interoperability: Works with NestJS, Express, Fastify, etc.
You may see TypeScript LSP errors like:
Module '"@nestjs/swagger"' has no exported member 'ApiProperty'
These are false positives caused by module resolution. The code compiles and runs correctly. The build output confirms:
✓ Build successful
✓ All models compiled to dist/
To verify the build works:
npm run build- Continue adding decorators to remaining model files using the patterns above
- Complete WorldState.ts with all property decorators
- Create API example showing how to use these models in a NestJS application
- Generate OpenAPI schema to validate completeness
- Add integration tests to ensure decorators work correctly
For questions about:
- Decorators: See NestJS Swagger docs: https://docs.nestjs.com/openapi/introduction
- Validation: See class-validator docs: https://github.com/typestack/class-validator
- Transformers: See class-transformer docs: https://github.com/typestack/class-transformer