Guides
NestJS
Injectable Mr. Doge service for clean DI inside Nest modules.
Install
npm i @mrdoge/nodeThe service
Wrap the MrDoge class in an injectable service so controllers don't reach
for the API key directly:
import { Injectable } from "@nestjs/common";
import { MrDoge } from "@mrdoge/node";
@Injectable()
export class MrDogeService {
readonly client: MrDoge;
constructor() {
this.client = new MrDoge({
apiKey: process.env.MRDOGE_API_KEY!,
});
}
get matches() {
return this.client.matches;
}
get picks() {
return this.client.ai.picks;
}
get tokens() {
return this.client.tokens;
}
}The module
import { Module, Global } from "@nestjs/common";
import { MrDogeService } from "./mrdoge.service";
@Global()
@Module({
providers: [MrDogeService],
exports: [MrDogeService],
})
export class MrDogeModule {}@Global() so any feature module can inject MrDogeService without
re-importing.
Register in AppModule:
import { Module } from "@nestjs/common";
import { MrDogeModule } from "./mrdoge/mrdoge.module";
@Module({
imports: [MrDogeModule],
})
export class AppModule {}Controller
import { Controller, Get, Query, Post } from "@nestjs/common";
import { MrDogeService } from "../mrdoge/mrdoge.service";
@Controller("matches")
export class MatchesController {
constructor(private readonly mrdoge: MrDogeService) {}
@Get()
async list(
@Query("sport") sport: string,
@Query("limit") limit = "20",
) {
return this.mrdoge.matches.list({
sports: [sport],
limit: Number(limit),
});
}
@Post("token")
async mintToken() {
return this.mrdoge.tokens.create({ ttl: 600 });
}
}Exception filter
Catch SDK errors with a Nest exception filter so they map to clean HTTP status codes:
import {
Catch,
ArgumentsHost,
ExceptionFilter,
HttpStatus,
} from "@nestjs/common";
import {
RateLimitError,
ForbiddenError,
UnauthorizedError,
ValidationError,
} from "@mrdoge/node";
@Catch(RateLimitError, ForbiddenError, UnauthorizedError, ValidationError)
export class SdkErrorFilter implements ExceptionFilter {
catch(err: unknown, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const res = ctx.getResponse();
if (err instanceof RateLimitError) {
return res.status(HttpStatus.TOO_MANY_REQUESTS).json({
error: "rate_limited",
data: err.data,
});
}
if (err instanceof ForbiddenError) {
return res.status(HttpStatus.FORBIDDEN).json({
error: "forbidden",
data: err.data,
});
}
if (err instanceof UnauthorizedError) {
return res.status(HttpStatus.UNAUTHORIZED).json({ error: "unauthorized" });
}
if (err instanceof ValidationError) {
return res.status(HttpStatus.BAD_REQUEST).json({
error: "validation",
data: err.data,
});
}
}
}Register globally:
import { SdkErrorFilter } from "./common/sdk-error.filter";
app.useGlobalFilters(new SdkErrorFilter());