diff --git a/apps/api/src/common/interceptors/serialize-dates.interceptor.ts b/apps/api/src/common/interceptors/serialize-dates.interceptor.ts new file mode 100644 index 00000000..229659ed --- /dev/null +++ b/apps/api/src/common/interceptors/serialize-dates.interceptor.ts @@ -0,0 +1,42 @@ +/* eslint-disable */ +import { + CallHandler, + ExecutionContext, + Injectable, + NestInterceptor, +} from "@nestjs/common"; +import { Observable } from "rxjs"; +import { map } from "rxjs/operators"; + +@Injectable() +export class SerializeDatesInterceptor implements NestInterceptor { + intercept(context: ExecutionContext, next: CallHandler): Observable { + return next.handle().pipe(map((data) => this.serializeDates(data))); + } + + private serializeDates(object: any): any { + if (object === null || object === undefined) { + return object; + } + + if (object instanceof Date) { + return object.toISOString(); + } + + if (Array.isArray(object)) { + return object.map((item) => this.serializeDates(item)); + } + + if (typeof object === "object") { + const serialized: any = {}; + for (const key in object) { + if (object.hasOwnProperty(key)) { + serialized[key] = this.serializeDates(object[key]); + } + } + return serialized; + } + + return object; + } +} diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index d44e244e..3ad5eab9 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -27,6 +27,7 @@ import { AppModule } from "./app.module"; import { AuthModule } from "./auth/auth.module"; import { RolesGlobalGuard } from "./auth/role/roles.global.guard"; import { winstonOptions } from "./logger/config"; +import { SerializeDatesInterceptor } from "./common/interceptors/serialize-dates.interceptor"; if (process.env.NODE_ENV === "production") { instana({ @@ -103,6 +104,12 @@ async function bootstrap() { */ app.useGlobalGuards(app.select(AuthModule).get(RolesGlobalGuard)); + /** + * Global serialization interceptor + * Automatically serializes Date objects to ISO strings in API responses + */ + app.useGlobalInterceptors(new SerializeDatesInterceptor()); + /** * Swagger API documentation setup * Provides interactive API documentation at /api endpoint