diff --git a/apps/api/package.json b/apps/api/package.json new file mode 100644 index 0000000..539ea40 --- /dev/null +++ b/apps/api/package.json @@ -0,0 +1,34 @@ +{ + "name": "@drift/api", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "tsc -p tsconfig.build.json", + "start": "node dist/main.js", + "test": "vitest run --config vitest.config.ts --no-file-parallelism", + "test:e2e": "vitest run --config vitest.config.ts src/health/health.e2e-spec.ts --no-file-parallelism", + "typecheck": "tsc --noEmit -p tsconfig.json" + }, + "dependencies": { + "@drift/contracts": "workspace:*", + "@nestjs/common": "^11.1.6", + "@nestjs/core": "^11.1.6", + "@nestjs/platform-express": "^11.1.6", + "@prisma/client": "6.19.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.2", + "helmet": "^8.1.0", + "redis": "^5.8.2", + "reflect-metadata": "^0.2.2", + "rxjs": "^7.8.2" + }, + "devDependencies": { + "@nestjs/testing": "^11.1.6", + "@types/express": "^5.0.3", + "@types/supertest": "^6.0.3", + "supertest": "^7.1.4", + "typescript": "^5.6.3", + "vitest": "^4.1.11" + } +} diff --git a/apps/api/src/app.module.ts b/apps/api/src/app.module.ts new file mode 100644 index 0000000..6535cdc --- /dev/null +++ b/apps/api/src/app.module.ts @@ -0,0 +1,10 @@ +import { MiddlewareConsumer, Module, type NestModule } from "@nestjs/common"; +import { RequestIdMiddleware } from "./common/request-id.middleware.js"; +import { HealthModule } from "./health/health.module.js"; + +@Module({ imports: [HealthModule] }) +export class AppModule implements NestModule { + configure(consumer: MiddlewareConsumer): void { + consumer.apply(RequestIdMiddleware).forRoutes("{*path}"); + } +} diff --git a/apps/api/src/common/domain-exception.filter.ts b/apps/api/src/common/domain-exception.filter.ts new file mode 100644 index 0000000..4aaa89a --- /dev/null +++ b/apps/api/src/common/domain-exception.filter.ts @@ -0,0 +1,63 @@ +import { ErrorCode, type ErrorResponse } from "@drift/contracts"; +import { + ArgumentsHost, + Catch, + HttpException, + HttpStatus, + type ExceptionFilter, +} from "@nestjs/common"; +import type { Response } from "express"; +import { DomainException } from "./domain.exception.js"; +import type { RequestWithId } from "./request-id.middleware.js"; + +@Catch() +export class DomainExceptionFilter implements ExceptionFilter { + catch(exception: unknown, host: ArgumentsHost): void { + const http = host.switchToHttp(); + const request = http.getRequest(); + const response = http.getResponse(); + const normalized = this.normalize(exception); + const body: ErrorResponse = { + code: normalized.code, + message: normalized.message, + data: null, + requestId: request.requestId, + }; + response.status(normalized.status).json(body); + } + + private normalize(exception: unknown): { + status: number; + code: Exclude; + message: string; + } { + if (exception instanceof DomainException) { + return { + status: exception.status, + code: exception.code, + message: exception.message, + }; + } + if (exception instanceof HttpException) { + const status = exception.getStatus(); + if (status === 404) + return { status, code: ErrorCode.NOT_FOUND, message: "Not Found" }; + if (status === 400) + return { + status, + code: ErrorCode.VALIDATION_ERROR, + message: "Validation failed", + }; + return { + status, + code: ErrorCode.INTERNAL_ERROR, + message: "Request failed", + }; + } + return { + status: HttpStatus.INTERNAL_SERVER_ERROR, + code: ErrorCode.INTERNAL_ERROR, + message: "Internal server error", + }; + } +} diff --git a/apps/api/src/common/domain.exception.ts b/apps/api/src/common/domain.exception.ts new file mode 100644 index 0000000..6de14c6 --- /dev/null +++ b/apps/api/src/common/domain.exception.ts @@ -0,0 +1,12 @@ +import type { ErrorCode } from "@drift/contracts"; + +export class DomainException extends Error { + constructor( + readonly code: Exclude, + message: string, + readonly status: number, + ) { + super(message); + this.name = "DomainException"; + } +} diff --git a/apps/api/src/common/http-response.interceptor.ts b/apps/api/src/common/http-response.interceptor.ts new file mode 100644 index 0000000..b105403 --- /dev/null +++ b/apps/api/src/common/http-response.interceptor.ts @@ -0,0 +1,34 @@ +import { ok, type SuccessResponse } from "@drift/contracts"; +import { + Injectable, + type CallHandler, + type ExecutionContext, + type NestInterceptor, +} from "@nestjs/common"; +import type { Observable } from "rxjs"; +import { map } from "rxjs/operators"; +import type { RequestWithId } from "./request-id.middleware.js"; + +const isEnvelope = (value: unknown): value is SuccessResponse => + typeof value === "object" && + value !== null && + "code" in value && + "requestId" in value; + +@Injectable() +export class HttpResponseInterceptor implements NestInterceptor< + T, + T | SuccessResponse +> { + intercept( + context: ExecutionContext, + next: CallHandler, + ): Observable> { + const request = context.switchToHttp().getRequest(); + return next + .handle() + .pipe( + map((data) => (isEnvelope(data) ? data : ok(data, request.requestId))), + ); + } +} diff --git a/apps/api/src/common/request-id.middleware.ts b/apps/api/src/common/request-id.middleware.ts new file mode 100644 index 0000000..486252c --- /dev/null +++ b/apps/api/src/common/request-id.middleware.ts @@ -0,0 +1,22 @@ +import { Injectable, type NestMiddleware } from "@nestjs/common"; +import { randomUUID } from "node:crypto"; +import type { NextFunction, Request, Response } from "express"; + +export const REQUEST_ID_HEADER = "x-request-id"; +const SAFE_REQUEST_ID = /^[A-Za-z0-9._:-]{1,128}$/; + +export interface RequestWithId extends Request { + requestId: string; +} + +@Injectable() +export class RequestIdMiddleware implements NestMiddleware { + use(request: Request, response: Response, next: NextFunction): void { + const supplied = request.header(REQUEST_ID_HEADER); + const requestId = + supplied && SAFE_REQUEST_ID.test(supplied) ? supplied : randomUUID(); + (request as RequestWithId).requestId = requestId; + response.setHeader(REQUEST_ID_HEADER, requestId); + next(); + } +} diff --git a/apps/api/src/database/prisma.service.ts b/apps/api/src/database/prisma.service.ts index 749f483..d589285 100644 --- a/apps/api/src/database/prisma.service.ts +++ b/apps/api/src/database/prisma.service.ts @@ -1,7 +1,15 @@ +import { + Injectable, + type OnModuleDestroy, + type OnModuleInit, +} from "@nestjs/common"; import { PrismaClient } from "@prisma/client"; -/** Lightweight database lifecycle wrapper; Nest hooks can call these methods later. */ -export class PrismaService extends PrismaClient { +@Injectable() +export class PrismaService + extends PrismaClient + implements OnModuleInit, OnModuleDestroy +{ async onModuleInit(): Promise { await this.$connect(); } diff --git a/apps/api/src/health/health.controller.ts b/apps/api/src/health/health.controller.ts new file mode 100644 index 0000000..6d9ff57 --- /dev/null +++ b/apps/api/src/health/health.controller.ts @@ -0,0 +1,19 @@ +import { Controller, Get, Inject } from "@nestjs/common"; +import { HealthService } from "./health.service.js"; + +@Controller("health") +export class HealthController { + constructor( + @Inject(HealthService) private readonly healthService: HealthService, + ) {} + + @Get() + check(): Promise<{ status: "ok"; postgres: "up"; redis: "up" }> { + return this.healthService.check(); + } + + @Get("live") + live(): { status: "ok" } { + return { status: "ok" }; + } +} diff --git a/apps/api/src/health/health.e2e-spec.ts b/apps/api/src/health/health.e2e-spec.ts new file mode 100644 index 0000000..b3a7a80 --- /dev/null +++ b/apps/api/src/health/health.e2e-spec.ts @@ -0,0 +1,187 @@ +import "reflect-metadata"; +/* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access */ +import { Body, Controller, Get, HttpStatus, Post } from "@nestjs/common"; +import { Test } from "@nestjs/testing"; +import { IsString } from "class-validator"; +import request from "supertest"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import type { INestApplication } from "@nestjs/common"; +import { ErrorCode } from "@drift/contracts"; +import { AppModule } from "../app.module"; +import { DomainException } from "../common/domain.exception"; + +import { configureApp } from "../main"; + +class ProbeDto { + @IsString() + name!: string; +} + +@Controller("probe") +class ProbeController { + @Post() + echo(@Body() dto: ProbeDto): ProbeDto { + return dto; + } + + @Get("domain-error") + domainError(): never { + throw new DomainException( + ErrorCode.CONTENT_REJECTED, + "content rejected", + HttpStatus.UNPROCESSABLE_ENTITY, + ); + } + + @Get("internal-error") + internalError(): never { + throw new Error(`sensitive ${process.env.DATABASE_URL}`); + } +} + +Reflect.defineMetadata( + "design:paramtypes", + [ProbeDto], + ProbeController.prototype, + "echo", +); + +describe("API infrastructure", () => { + let app: INestApplication; + + beforeAll(async () => { + const module = await Test.createTestingModule({ + imports: [AppModule], + controllers: [ProbeController], + }).compile(); + app = module.createNestApplication(); + configureApp(app); + await app.init(); + }); + + afterAll(async () => { + await app?.close(); + }); + + it("reports real dependency readiness in the uniform success envelope", async () => { + const response = await request(app.getHttpServer()) + .get("/api/v1/health") + .expect(200); + expect(response.body).toMatchObject({ + code: "OK", + message: "success", + data: { status: "ok", postgres: "up", redis: "up" }, + }); + expect(response.body.requestId).toEqual(expect.any(String)); + expect(response.headers["x-request-id"]).toBe(response.body.requestId); + }); + + it("passes through a safe caller request id", async () => { + const response = await request(app.getHttpServer()) + .get("/api/v1/health/live") + .set("x-request-id", "client_req-123") + .expect(200); + expect(response.body.requestId).toBe("client_req-123"); + expect(response.headers["x-request-id"]).toBe("client_req-123"); + }); + + it.each(["x".repeat(129), "bad value"])( + "replaces unsafe request id %s", + async (unsafeId) => { + const response = await request(app.getHttpServer()) + .get("/api/v1/health/live") + .set("x-request-id", unsafeId) + .expect(200); + expect(response.body.requestId).toMatch(/^[0-9a-f-]{36}$/); + expect(response.body.requestId).not.toBe(unsafeId); + }, + ); + + it("returns a uniform 404 envelope", async () => { + const response = await request(app.getHttpServer()) + .get("/api/v1/missing") + .expect(404); + expect(response.body).toMatchObject({ + code: "NOT_FOUND", + message: "Not Found", + data: null, + }); + expect(response.body.requestId).toBe(response.headers["x-request-id"]); + }); + + it("returns a domain exception envelope and status", async () => { + const response = await request(app.getHttpServer()) + .get("/api/v1/probe/domain-error") + .expect(422); + expect(response.body).toMatchObject({ + code: "CONTENT_REJECTED", + message: "content rejected", + data: null, + }); + }); + + it("does not leak internal errors", async () => { + const response = await request(app.getHttpServer()) + .get("/api/v1/probe/internal-error") + .expect(500); + expect(response.body).toMatchObject({ + code: "INTERNAL_ERROR", + message: "Internal server error", + data: null, + }); + expect(JSON.stringify(response.body)).not.toContain("postgresql://"); + expect(response.body).not.toHaveProperty("stack"); + }); + + it("rejects non-whitelisted DTO properties in the uniform envelope", async () => { + const response = await request(app.getHttpServer()) + .post("/api/v1/probe") + .send({ name: "ok", extra: true }) + .expect(400); + expect(response.body).toMatchObject({ + code: "VALIDATION_ERROR", + data: null, + }); + }); + + it("applies helmet and same-origin credentialed CORS", async () => { + const allowedOrigin = process.env.WEB_ORIGIN ?? "http://localhost:3000"; + const allowed = await request(app.getHttpServer()) + .get("/api/v1/health/live") + .set("Origin", allowedOrigin) + .expect(200); + expect(allowed.headers["access-control-allow-origin"]).toBe(allowedOrigin); + expect(allowed.headers["access-control-allow-credentials"]).toBe("true"); + expect(allowed.headers["x-content-type-options"]).toBe("nosniff"); + const denied = await request(app.getHttpServer()) + .get("/api/v1/health/live") + .set("Origin", "https://evil.example") + .expect(200); + expect(denied.headers).not.toHaveProperty("access-control-allow-origin"); + }); + + it("returns a sanitized 503 when a real dependency is unavailable", async () => { + const originalRedisUrl = process.env.REDIS_URL; + process.env.REDIS_URL = "redis://127.0.0.1:1"; + const module = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + const unavailableApp = module.createNestApplication(); + configureApp(unavailableApp); + await unavailableApp.init(); + try { + const response = await request(unavailableApp.getHttpServer()) + .get("/api/v1/health") + .expect(503); + expect(response.body).toMatchObject({ + code: "SERVICE_UNAVAILABLE", + message: "Dependencies unavailable", + data: null, + }); + expect(JSON.stringify(response.body)).not.toContain("redis://"); + } finally { + await unavailableApp.close(); + process.env.REDIS_URL = originalRedisUrl; + } + }); +}); diff --git a/apps/api/src/health/health.module.ts b/apps/api/src/health/health.module.ts new file mode 100644 index 0000000..d70988d --- /dev/null +++ b/apps/api/src/health/health.module.ts @@ -0,0 +1,10 @@ +import { Module } from "@nestjs/common"; +import { PrismaService } from "../database/prisma.service.js"; +import { HealthController } from "./health.controller.js"; +import { HealthService } from "./health.service.js"; + +@Module({ + controllers: [HealthController], + providers: [HealthService, PrismaService], +}) +export class HealthModule {} diff --git a/apps/api/src/health/health.service.ts b/apps/api/src/health/health.service.ts new file mode 100644 index 0000000..694c84a --- /dev/null +++ b/apps/api/src/health/health.service.ts @@ -0,0 +1,37 @@ +import { Inject, Injectable, type OnModuleDestroy } from "@nestjs/common"; +import { createClient, type RedisClientType } from "redis"; +import { PrismaService } from "../database/prisma.service.js"; +import { DomainException } from "../common/domain.exception.js"; +import { ErrorCode } from "@drift/contracts"; +import { HttpStatus } from "@nestjs/common"; + +@Injectable() +export class HealthService implements OnModuleDestroy { + private readonly redis: RedisClientType; + + constructor(@Inject(PrismaService) private readonly prisma: PrismaService) { + this.redis = createClient({ + url: process.env.REDIS_URL ?? "redis://127.0.0.1:6379", + socket: { connectTimeout: 500, reconnectStrategy: false }, + }); + this.redis.on("error", () => undefined); + } + + async check(): Promise<{ status: "ok"; postgres: "up"; redis: "up" }> { + try { + if (!this.redis.isOpen) await this.redis.connect(); + await Promise.all([this.prisma.$queryRaw`SELECT 1`, this.redis.ping()]); + return { status: "ok", postgres: "up", redis: "up" }; + } catch { + throw new DomainException( + ErrorCode.SERVICE_UNAVAILABLE, + "Dependencies unavailable", + HttpStatus.SERVICE_UNAVAILABLE, + ); + } + } + + async onModuleDestroy(): Promise { + if (this.redis.isOpen) await this.redis.quit(); + } +} diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts new file mode 100644 index 0000000..6e1dbf7 --- /dev/null +++ b/apps/api/src/main.ts @@ -0,0 +1,40 @@ +import "reflect-metadata"; +import { ValidationPipe, type INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; +import helmet from "helmet"; +import { AppModule } from "./app.module.js"; +import { HttpResponseInterceptor } from "./common/http-response.interceptor.js"; +import { DomainExceptionFilter } from "./common/domain-exception.filter.js"; + +export function configureApp(app: INestApplication): void { + const allowedOrigin = process.env.WEB_ORIGIN ?? "http://localhost:3000"; + app.setGlobalPrefix("api/v1"); + app.use(helmet()); + app.useGlobalPipes( + new ValidationPipe({ + whitelist: true, + forbidNonWhitelisted: true, + transform: true, + }), + ); + app.useGlobalInterceptors(new HttpResponseInterceptor()); + app.useGlobalFilters(new DomainExceptionFilter()); + app.enableCors({ + origin( + origin: string | undefined, + callback: (error: Error | null, allow?: boolean) => void, + ) { + callback(null, origin === undefined || origin === allowedOrigin); + }, + credentials: true, + }); +} + +async function bootstrap(): Promise { + const app = await NestFactory.create(AppModule); + configureApp(app); + app.enableShutdownHooks(); + await app.listen(Number(process.env.PORT ?? 3001), "0.0.0.0"); +} + +if (process.env.NODE_ENV !== "test") void bootstrap(); diff --git a/apps/api/tsconfig.build.json b/apps/api/tsconfig.build.json new file mode 100644 index 0000000..f3ceb7b --- /dev/null +++ b/apps/api/tsconfig.build.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": false, + "outDir": "dist", + "rootDir": "src", + "sourceMap": true, + "types": ["node"] + }, + "include": ["src/**/*.ts"], + "exclude": ["src/**/*spec.ts"] +} diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json new file mode 100644 index 0000000..98a9e85 --- /dev/null +++ b/apps/api/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "noEmit": true, + "types": ["node", "vitest/globals"] + }, + "include": ["src/**/*.ts", "vitest.config.ts"] +} diff --git a/apps/api/vitest.config.ts b/apps/api/vitest.config.ts new file mode 100644 index 0000000..4b08f45 --- /dev/null +++ b/apps/api/vitest.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + esbuild: { + tsconfigRaw: { + compilerOptions: { + experimentalDecorators: true, + }, + }, + }, + test: { + environment: "node", + include: ["src/**/*spec.ts"], + }, +}); diff --git a/package.json b/package.json index 272e351..46e07fc 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "pnpm": { "overrides": { "deepmerge-ts@<8.0.0": "8.0.0", - "effect@<3.20.0": "3.20.0" + "effect@<3.20.0": "3.20.0", + "multer@<2.3.0": "2.3.0" } }, "devDependencies": { diff --git a/packages/contracts/src/index.test.ts b/packages/contracts/src/index.test.ts index 08d3c98..36cbddc 100644 --- a/packages/contracts/src/index.test.ts +++ b/packages/contracts/src/index.test.ts @@ -22,6 +22,10 @@ describe("contracts", () => { it("defines the complete error-code contract", () => { expect(Object.values(ErrorCode)).toEqual([ "OK", + "VALIDATION_ERROR", + "NOT_FOUND", + "SERVICE_UNAVAILABLE", + "INTERNAL_ERROR", "AUTH_TOKEN_EXPIRED", "AUTH_REFRESH_REUSED", "BOTTLE_DAILY_LIMIT", diff --git a/packages/contracts/src/index.ts b/packages/contracts/src/index.ts index fb31f12..3b30903 100644 --- a/packages/contracts/src/index.ts +++ b/packages/contracts/src/index.ts @@ -1,5 +1,9 @@ export enum ErrorCode { OK = "OK", + VALIDATION_ERROR = "VALIDATION_ERROR", + NOT_FOUND = "NOT_FOUND", + SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE", + INTERNAL_ERROR = "INTERNAL_ERROR", AUTH_TOKEN_EXPIRED = "AUTH_TOKEN_EXPIRED", AUTH_REFRESH_REUSED = "AUTH_REFRESH_REUSED", BOTTLE_DAILY_LIMIT = "BOTTLE_DAILY_LIMIT", @@ -18,6 +22,13 @@ export interface SuccessResponse { requestId: string; } +export interface ErrorResponse { + code: Exclude; + message: string; + data: null; + requestId: string; +} + export const ok = (data: T, requestId: string): SuccessResponse => ({ code: ErrorCode.OK, message: "success", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 04d76c8..bcb9212 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,7 @@ settings: overrides: deepmerge-ts@<8.0.0: 8.0.0 effect@<3.20.0: 3.20.0 + multer@<2.3.0: 2.3.0 importers: .: @@ -46,9 +47,70 @@ importers: specifier: ^4.1.11 version: 4.1.11(@types/node@22.19.3)(vite@7.3.6(@types/node@22.19.3)(jiti@2.7.0)(tsx@4.20.6)) + apps/api: + dependencies: + "@drift/contracts": + specifier: workspace:* + version: link:../../packages/contracts + "@nestjs/common": + specifier: ^11.1.6 + version: 11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) + "@nestjs/core": + specifier: ^11.1.6 + version: 11.2.3(@nestjs/common@11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.2.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) + "@nestjs/platform-express": + specifier: ^11.1.6 + version: 11.2.3(@nestjs/common@11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.2.3) + "@prisma/client": + specifier: 6.19.0 + version: 6.19.0(prisma@6.19.0(typescript@5.9.3))(typescript@5.9.3) + class-transformer: + specifier: ^0.5.1 + version: 0.5.1 + class-validator: + specifier: ^0.14.2 + version: 0.14.4 + helmet: + specifier: ^8.1.0 + version: 8.3.0 + redis: + specifier: ^5.8.2 + version: 5.12.1 + reflect-metadata: + specifier: ^0.2.2 + version: 0.2.2 + rxjs: + specifier: ^7.8.2 + version: 7.8.2 + devDependencies: + "@nestjs/testing": + specifier: ^11.1.6 + version: 11.2.3(@nestjs/common@11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.2.3)(@nestjs/platform-express@11.2.3) + "@types/express": + specifier: ^5.0.3 + version: 5.0.6 + "@types/supertest": + specifier: ^6.0.3 + version: 6.0.3 + supertest: + specifier: ^7.1.4 + version: 7.2.2 + typescript: + specifier: ^5.6.3 + version: 5.9.3 + vitest: + specifier: ^4.1.11 + version: 4.1.11(@types/node@22.19.3)(vite@7.3.6(@types/node@22.19.3)(jiti@2.7.0)(tsx@4.20.6)) + packages/contracts: {} packages: + "@borewit/text-codec@0.2.2": + resolution: + { + integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==, + } + "@esbuild/aix-ppc64@0.25.12": resolution: { @@ -575,6 +637,13 @@ packages: integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==, } + "@lukeed/csprng@1.1.0": + resolution: + { + integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==, + } + engines: { node: ">=8" } + "@napi-rs/lzma-linux-x64-gnu@1.5.1": resolution: { @@ -584,6 +653,75 @@ packages: cpu: [x64] os: [linux] + "@nestjs/common@11.2.3": + resolution: + { + integrity: sha512-obdauJXHfthhepbV+LpGe88OeBlR/Kw9lwjLo0Utzc//agoLXYb9DUGhPQWtm81IpBWMv+19eiwcve9MsBZwXA==, + } + peerDependencies: + class-transformer: ">=0.4.1" + class-validator: ">=0.13.2" + reflect-metadata: ^0.1.12 || ^0.2.0 + rxjs: ^7.1.0 + peerDependenciesMeta: + class-transformer: + optional: true + class-validator: + optional: true + + "@nestjs/core@11.2.3": + resolution: + { + integrity: sha512-vkA9/Ja0Z3hvqXErSa+HaxrfF+cNXthNFi8VPNEKVli4rMd009yExAl0gLmko/Kf8peDXr72u1RN+j9Da2ukHg==, + } + engines: { node: ">= 20" } + peerDependencies: + "@nestjs/common": ^11.0.0 + "@nestjs/microservices": ^11.0.0 + "@nestjs/platform-express": ^11.0.0 + "@nestjs/websockets": ^11.0.0 + reflect-metadata: ^0.1.12 || ^0.2.0 + rxjs: ^7.1.0 + peerDependenciesMeta: + "@nestjs/microservices": + optional: true + "@nestjs/platform-express": + optional: true + "@nestjs/websockets": + optional: true + + "@nestjs/platform-express@11.2.3": + resolution: + { + integrity: sha512-YFQvRXT2de1qNL9LJPUBQ31+RsfI4cJ+sbpU9ENM/hDCgoHSEhm7oxUuGGKmhTZBNZEYm8mDYdfoTFmAH1LIJg==, + } + peerDependencies: + "@nestjs/common": ^11.0.0 + "@nestjs/core": ^11.0.0 + + "@nestjs/testing@11.2.3": + resolution: + { + integrity: sha512-7ANDWlkm8Xw4CYIhCNZhtBzANsQUKqjteA2yx/6sjqGyWhekeBKz8wgCJykm0vo+ltrg6U34dZlm2NgiRcNHPQ==, + } + peerDependencies: + "@nestjs/common": ^11.0.0 + "@nestjs/core": ^11.0.0 + "@nestjs/microservices": ^11.0.0 + "@nestjs/platform-express": ^11.0.0 + peerDependenciesMeta: + "@nestjs/microservices": + optional: true + "@nestjs/platform-express": + optional: true + + "@noble/hashes@1.8.0": + resolution: + { + integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==, + } + engines: { node: ^14.21.3 || >=16 } + "@nodelib/fs.scandir@2.1.5": resolution: { @@ -605,6 +743,12 @@ packages: } engines: { node: ">= 8" } + "@paralleldrive/cuid2@2.3.1": + resolution: + { + integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==, + } + "@prisma/client@6.19.0": resolution: { @@ -656,6 +800,57 @@ packages: integrity: sha512-ym85WDO2yDhC3fIXHWYpG3kVMBA49cL1XD2GCsCF8xbwoy2OkDQY44gEbAt2X46IQ4Apq9H6g0Ex1iFfPqEkHA==, } + "@redis/bloom@5.12.1": + resolution: + { + integrity: sha512-PUUfv+ms7jgPSBVoo/DN4AkPHj4D5TZSd6SbJX7egzBplkYUcKmHRE8RKia7UtZ8bSQbLguLvxVO+asKtQfZWA==, + } + engines: { node: ">= 18.19.0" } + peerDependencies: + "@redis/client": ^5.12.1 + + "@redis/client@5.12.1": + resolution: + { + integrity: sha512-7aPGWeqA3uFm43o19umzdl16CEjK/JQGtSXVPevplTaOU3VJA/rseBC1QvYUz9lLDIMBimc4SW/zrW4S89BaCA==, + } + engines: { node: ">= 18.19.0" } + peerDependencies: + "@node-rs/xxhash": ^1.1.0 + "@opentelemetry/api": ">=1 <2" + peerDependenciesMeta: + "@node-rs/xxhash": + optional: true + "@opentelemetry/api": + optional: true + + "@redis/json@5.12.1": + resolution: + { + integrity: sha512-eOze75esLve4vfqDel7aMX08CNaiLLQS2fV8mpRN9NxPe1rVR4vQyYiW/OgtGUysF6QOr9ANhfxABKNOJfXdKg==, + } + engines: { node: ">= 18.19.0" } + peerDependencies: + "@redis/client": ^5.12.1 + + "@redis/search@5.12.1": + resolution: + { + integrity: sha512-ItlxbxC9cKI6IU1TLWoczwJCRb6TdmkEpWv05UrPawqaAnWGRu3rcIqsc5vN483T2fSociuyV1UkWIL5I4//2w==, + } + engines: { node: ">= 18.19.0" } + peerDependencies: + "@redis/client": ^5.12.1 + + "@redis/time-series@5.12.1": + resolution: + { + integrity: sha512-c6JL6E3EcZJuNqKFz+KM+l9l5mpcQiKvTwgA3blt5glWJ8hjDk0yeHN3beE/MpqYIQ8UEX44ItQzgkE/gCBELQ==, + } + engines: { node: ">= 18.19.0" } + peerDependencies: + "@redis/client": ^5.12.1 + "@rollup/rollup-android-arm-eabi@4.63.2": resolution: { @@ -862,12 +1057,43 @@ packages: integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==, } + "@tokenizer/inflate@0.4.1": + resolution: + { + integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==, + } + engines: { node: ">=18" } + + "@tokenizer/token@0.3.0": + resolution: + { + integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==, + } + + "@types/body-parser@1.19.6": + resolution: + { + integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==, + } + "@types/chai@5.2.3": resolution: { integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==, } + "@types/connect@3.4.38": + resolution: + { + integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==, + } + + "@types/cookiejar@2.1.5": + resolution: + { + integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==, + } + "@types/deep-eql@4.0.2": resolution: { @@ -880,12 +1106,78 @@ packages: integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==, } + "@types/express-serve-static-core@5.1.3": + resolution: + { + integrity: sha512-dPfW8NFiOF4wOHc7+N/QSxlY9cfSsenewGbAz8C8U/MULPd/YZ27LvJUIlzaXie7e6Ove9YunJGgC9tbHD2cKw==, + } + + "@types/express@5.0.6": + resolution: + { + integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==, + } + + "@types/http-errors@2.0.5": + resolution: + { + integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==, + } + + "@types/methods@1.1.4": + resolution: + { + integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==, + } + "@types/node@22.19.3": resolution: { integrity: sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==, } + "@types/qs@6.15.1": + resolution: + { + integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==, + } + + "@types/range-parser@1.2.7": + resolution: + { + integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==, + } + + "@types/send@1.2.1": + resolution: + { + integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==, + } + + "@types/serve-static@2.2.0": + resolution: + { + integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==, + } + + "@types/superagent@8.1.11": + resolution: + { + integrity: sha512-KA7srSW/HENDtOw9DOqaFLgWuMqN9WgjEw62lh9dpvRaZDkhdOkazASd7X7i2eMUYLHa1U37ZttnePsH5zTDHw==, + } + + "@types/supertest@6.0.3": + resolution: + { + integrity: sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==, + } + + "@types/validator@13.15.10": + resolution: + { + integrity: sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==, + } + "@typescript-eslint/eslint-plugin@8.70.0": resolution: { @@ -1031,6 +1323,13 @@ packages: integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==, } + accepts@2.0.0: + resolution: + { + integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==, + } + engines: { node: ">= 0.6" } + acorn-jsx@5.3.2: resolution: { @@ -1067,12 +1366,24 @@ packages: } engines: { node: ">=8" } + append-field@1.0.0: + resolution: + { + integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==, + } + argparse@2.0.1: resolution: { integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, } + asap@2.0.6: + resolution: + { + integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==, + } + assertion-error@2.0.1: resolution: { @@ -1080,6 +1391,12 @@ packages: } engines: { node: ">=12" } + asynckit@0.4.0: + resolution: + { + integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==, + } + balanced-match@1.0.2: resolution: { @@ -1093,6 +1410,13 @@ packages: } engines: { node: 18 || 20 || >=22 } + body-parser@2.3.0: + resolution: + { + integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==, + } + engines: { node: ">=18" } + brace-expansion@1.1.18: resolution: { @@ -1106,6 +1430,26 @@ packages: } engines: { node: 20 || >=22 } + buffer-from@1.1.2: + resolution: + { + integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==, + } + + busboy@1.6.0: + resolution: + { + integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==, + } + engines: { node: ">=10.16.0" } + + bytes@3.1.2: + resolution: + { + integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==, + } + engines: { node: ">= 0.8" } + c12@3.1.0: resolution: { @@ -1117,6 +1461,20 @@ packages: magicast: optional: true + call-bind-apply-helpers@1.0.2: + resolution: + { + integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==, + } + engines: { node: ">= 0.4" } + + call-bound@1.0.4: + resolution: + { + integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==, + } + engines: { node: ">= 0.4" } + callsites@3.1.0: resolution: { @@ -1157,6 +1515,25 @@ packages: integrity: sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==, } + class-transformer@0.5.1: + resolution: + { + integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==, + } + + class-validator@0.14.4: + resolution: + { + integrity: sha512-AwNusCCam51q703dW82x95tOqQp6oC9HNUl724KxJJOfnKscI8dOloXFgyez7LbTTKWuRBA37FScqVbJEoq8Yw==, + } + + cluster-key-slot@1.1.2: + resolution: + { + integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==, + } + engines: { node: ">=0.10.0" } + color-convert@2.0.1: resolution: { @@ -1170,12 +1547,32 @@ packages: integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, } + combined-stream@1.0.8: + resolution: + { + integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==, + } + engines: { node: ">= 0.8" } + + component-emitter@1.3.1: + resolution: + { + integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==, + } + concat-map@0.0.1: resolution: { integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, } + concat-stream@2.0.0: + resolution: + { + integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==, + } + engines: { "0": node >= 6.0 } + confbox@0.2.4: resolution: { @@ -1195,12 +1592,60 @@ packages: } engines: { node: ^14.18.0 || >=16.10.0 } + content-disposition@1.1.0: + resolution: + { + integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==, + } + engines: { node: ">=18" } + + content-type@1.0.5: + resolution: + { + integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==, + } + engines: { node: ">= 0.6" } + + content-type@2.1.0: + resolution: + { + integrity: sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==, + } + engines: { node: ">=18" } + convert-source-map@2.0.0: resolution: { integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, } + cookie-signature@1.2.2: + resolution: + { + integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==, + } + engines: { node: ">=6.6.0" } + + cookie@0.7.2: + resolution: + { + integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==, + } + engines: { node: ">= 0.6" } + + cookiejar@2.1.4: + resolution: + { + integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==, + } + + cors@2.8.6: + resolution: + { + integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==, + } + engines: { node: ">= 0.10" } + cross-spawn@7.0.6: resolution: { @@ -1239,12 +1684,32 @@ packages: integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==, } + delayed-stream@1.0.0: + resolution: + { + integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==, + } + engines: { node: ">=0.4.0" } + + depd@2.0.0: + resolution: + { + integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==, + } + engines: { node: ">= 0.8" } + destr@2.0.5: resolution: { integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==, } + dezalgo@1.0.4: + resolution: + { + integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==, + } + doctrine@3.0.0: resolution: { @@ -1259,6 +1724,19 @@ packages: } engines: { node: ">=12" } + dunder-proto@1.0.1: + resolution: + { + integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, + } + engines: { node: ">= 0.4" } + + ee-first@1.1.1: + resolution: + { + integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==, + } + effect@3.20.0: resolution: { @@ -1272,12 +1750,47 @@ packages: } engines: { node: ">=14" } + encodeurl@2.0.0: + resolution: + { + integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==, + } + engines: { node: ">= 0.8" } + + es-define-property@1.0.1: + resolution: + { + integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, + } + engines: { node: ">= 0.4" } + + es-errors@1.3.0: + resolution: + { + integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, + } + engines: { node: ">= 0.4" } + es-module-lexer@2.3.2: resolution: { integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==, } + es-object-atoms@1.1.2: + resolution: + { + integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==, + } + engines: { node: ">= 0.4" } + + es-set-tostringtag@2.1.0: + resolution: + { + integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==, + } + engines: { node: ">= 0.4" } + esbuild@0.25.12: resolution: { @@ -1294,6 +1807,12 @@ packages: engines: { node: ">=18" } hasBin: true + escape-html@1.0.3: + resolution: + { + integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==, + } + escape-string-regexp@4.0.0: resolution: { @@ -1372,6 +1891,13 @@ packages: } engines: { node: ">=0.10.0" } + etag@1.8.1: + resolution: + { + integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==, + } + engines: { node: ">= 0.6" } + expect-type@1.4.0: resolution: { @@ -1379,6 +1905,13 @@ packages: } engines: { node: ">=12.0.0" } + express@5.2.1: + resolution: + { + integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==, + } + engines: { node: ">= 18" } + exsolve@1.1.1: resolution: { @@ -1410,6 +1943,12 @@ packages: integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, } + fast-safe-stringify@2.1.1: + resolution: + { + integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==, + } + fastq@1.20.3: resolution: { @@ -1435,6 +1974,20 @@ packages: } engines: { node: ^10.12.0 || >=12.0.0 } + file-type@21.3.4: + resolution: + { + integrity: sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==, + } + engines: { node: ">=20" } + + finalhandler@2.1.1: + resolution: + { + integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==, + } + engines: { node: ">= 18.0.0" } + find-up@5.0.0: resolution: { @@ -1455,6 +2008,34 @@ packages: integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==, } + form-data@4.0.6: + resolution: + { + integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==, + } + engines: { node: ">= 6" } + + formidable@3.5.4: + resolution: + { + integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==, + } + engines: { node: ">=14.0.0" } + + forwarded@0.2.0: + resolution: + { + integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==, + } + engines: { node: ">= 0.6" } + + fresh@2.0.0: + resolution: + { + integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==, + } + engines: { node: ">= 0.8" } + fs.realpath@1.0.0: resolution: { @@ -1469,6 +2050,26 @@ packages: engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } os: [darwin] + function-bind@1.1.2: + resolution: + { + integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, + } + + get-intrinsic@1.3.0: + resolution: + { + integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==, + } + engines: { node: ">= 0.4" } + + get-proto@1.0.1: + resolution: + { + integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==, + } + engines: { node: ">= 0.4" } + get-tsconfig@4.14.3: resolution: { @@ -1503,6 +2104,13 @@ packages: } engines: { node: ">=8" } + gopd@1.2.0: + resolution: + { + integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==, + } + engines: { node: ">= 0.4" } + graphemer@1.4.0: resolution: { @@ -1516,6 +2124,54 @@ packages: } engines: { node: ">=8" } + has-symbols@1.1.0: + resolution: + { + integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==, + } + engines: { node: ">= 0.4" } + + has-tostringtag@1.0.2: + resolution: + { + integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==, + } + engines: { node: ">= 0.4" } + + hasown@2.0.4: + resolution: + { + integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==, + } + engines: { node: ">= 0.4" } + + helmet@8.3.0: + resolution: + { + integrity: sha512-Qgpiaws3Sm30Av8Eah6sjMCZZwjlBu+E68rhpCWBshY1lb09HtLwj5GviX0OyQIn+ulUS0iX0AxN5n3tLZzz1w==, + } + engines: { node: ">=18.0.0" } + + http-errors@2.0.1: + resolution: + { + integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==, + } + engines: { node: ">= 0.8" } + + iconv-lite@0.7.3: + resolution: + { + integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==, + } + engines: { node: ">=0.10.0" } + + ieee754@1.2.1: + resolution: + { + integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==, + } + ignore@5.3.2: resolution: { @@ -1557,6 +2213,13 @@ packages: integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, } + ipaddr.js@1.9.1: + resolution: + { + integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==, + } + engines: { node: ">= 0.10" } + is-extglob@2.1.1: resolution: { @@ -1578,12 +2241,25 @@ packages: } engines: { node: ">=8" } + is-promise@4.0.0: + resolution: + { + integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==, + } + isexe@2.0.0: resolution: { integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, } + iterare@1.2.1: + resolution: + { + integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==, + } + engines: { node: ">=6" } + jiti@2.7.0: resolution: { @@ -1629,6 +2305,19 @@ packages: } engines: { node: ">= 0.8.0" } + libphonenumber-js@1.13.13: + resolution: + { + integrity: sha512-hV6SmWnyQ8U1QXhhqbqYBHIStNnscG7A5XbGodgdHhf/8N5PwhYpJA5U/yHDjYwPYTd8uNGXqq416XctuvK2PA==, + } + + load-esm@1.0.3: + resolution: + { + integrity: sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==, + } + engines: { node: ">=13.2.0" } + locate-path@6.0.0: resolution: { @@ -1648,6 +2337,77 @@ packages: integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==, } + math-intrinsics@1.1.0: + resolution: + { + integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, + } + engines: { node: ">= 0.4" } + + media-typer@0.3.0: + resolution: + { + integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==, + } + engines: { node: ">= 0.6" } + + media-typer@1.1.1: + resolution: + { + integrity: sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==, + } + engines: { node: ">= 0.8" } + + merge-descriptors@2.0.0: + resolution: + { + integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==, + } + engines: { node: ">=18" } + + methods@1.1.2: + resolution: + { + integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==, + } + engines: { node: ">= 0.6" } + + mime-db@1.52.0: + resolution: + { + integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, + } + engines: { node: ">= 0.6" } + + mime-db@1.54.0: + resolution: + { + integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==, + } + engines: { node: ">= 0.6" } + + mime-types@2.1.35: + resolution: + { + integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, + } + engines: { node: ">= 0.6" } + + mime-types@3.0.2: + resolution: + { + integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==, + } + engines: { node: ">=18" } + + mime@2.6.0: + resolution: + { + integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==, + } + engines: { node: ">=4.0.0" } + hasBin: true + minimatch@10.2.6: resolution: { @@ -1667,6 +2427,13 @@ packages: integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, } + multer@2.3.0: + resolution: + { + integrity: sha512-cjNbm3sttszgZeGfJR124D+jFEfkXCVAsoPBmFn9X7UxmDSFHWqE2CoEj0vrmSpuAFnqWR1Szcm9QTsiHr60Xw==, + } + engines: { node: ">= 10.16.0" } + nanoid@3.3.19: resolution: { @@ -1681,6 +2448,13 @@ packages: integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, } + negotiator@1.1.0: + resolution: + { + integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==, + } + engines: { node: ">=18" } + node-fetch-native@1.6.7: resolution: { @@ -1695,6 +2469,20 @@ packages: engines: { node: ">=18" } hasBin: true + object-assign@4.1.1: + resolution: + { + integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==, + } + engines: { node: ">=0.10.0" } + + object-inspect@1.13.4: + resolution: + { + integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==, + } + engines: { node: ">= 0.4" } + obug@2.2.1: resolution: { @@ -1708,6 +2496,13 @@ packages: integrity: sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==, } + on-finished@2.4.1: + resolution: + { + integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==, + } + engines: { node: ">= 0.8" } + once@1.4.0: resolution: { @@ -1742,6 +2537,13 @@ packages: } engines: { node: ">=6" } + parseurl@1.3.3: + resolution: + { + integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==, + } + engines: { node: ">= 0.8" } + path-exists@4.0.0: resolution: { @@ -1763,6 +2565,12 @@ packages: } engines: { node: ">=8" } + path-to-regexp@8.4.2: + resolution: + { + integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==, + } + pathe@2.0.3: resolution: { @@ -1829,6 +2637,13 @@ packages: typescript: optional: true + proxy-addr@2.0.7: + resolution: + { + integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==, + } + engines: { node: ">= 0.10" } + punycode@2.3.1: resolution: { @@ -1842,18 +2657,46 @@ packages: integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==, } + qs@6.16.0: + resolution: + { + integrity: sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==, + } + engines: { node: ">=0.6" } + queue-microtask@1.2.3: resolution: { integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, } + range-parser@1.3.0: + resolution: + { + integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==, + } + engines: { node: ">= 0.6" } + + raw-body@3.0.2: + resolution: + { + integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==, + } + engines: { node: ">= 0.10" } + rc9@2.1.2: resolution: { integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==, } + readable-stream@3.6.2: + resolution: + { + integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==, + } + engines: { node: ">= 6" } + readdirp@4.1.2: resolution: { @@ -1861,6 +2704,19 @@ packages: } engines: { node: ">= 14.18.0" } + redis@5.12.1: + resolution: + { + integrity: sha512-LDsoVvb/CpoV9EN3FXvgvSHNJWuCIzl9MiO3ppOevuGLpSGJhwfQjpEwfFJcQvNSddHADDdZaWx0HnmMxRXG7g==, + } + engines: { node: ">= 18.19.0" } + + reflect-metadata@0.2.2: + resolution: + { + integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==, + } + resolve-from@4.0.0: resolution: { @@ -1897,12 +2753,37 @@ packages: engines: { node: ">=18.0.0", npm: ">=8.0.0" } hasBin: true + router@2.2.0: + resolution: + { + integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==, + } + engines: { node: ">= 18" } + run-parallel@1.2.0: resolution: { integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, } + rxjs@7.8.2: + resolution: + { + integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==, + } + + safe-buffer@5.2.1: + resolution: + { + integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, + } + + safer-buffer@2.1.2: + resolution: + { + integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, + } + semver@7.8.5: resolution: { @@ -1911,6 +2792,26 @@ packages: engines: { node: ">=10" } hasBin: true + send@1.2.1: + resolution: + { + integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==, + } + engines: { node: ">= 18" } + + serve-static@2.2.1: + resolution: + { + integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==, + } + engines: { node: ">= 18" } + + setprototypeof@1.2.0: + resolution: + { + integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==, + } + shebang-command@2.0.0: resolution: { @@ -1925,6 +2826,34 @@ packages: } engines: { node: ">=8" } + side-channel-list@1.0.1: + resolution: + { + integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==, + } + engines: { node: ">= 0.4" } + + side-channel-map@1.0.1: + resolution: + { + integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==, + } + engines: { node: ">= 0.4" } + + side-channel-weakmap@1.0.2: + resolution: + { + integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==, + } + engines: { node: ">= 0.4" } + + side-channel@1.1.1: + resolution: + { + integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==, + } + engines: { node: ">= 0.4" } + siginfo@2.0.0: resolution: { @@ -1944,12 +2873,32 @@ packages: integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==, } + statuses@2.0.2: + resolution: + { + integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==, + } + engines: { node: ">= 0.8" } + std-env@4.2.0: resolution: { integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==, } + streamsearch@1.1.0: + resolution: + { + integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==, + } + engines: { node: ">=10.0.0" } + + string_decoder@1.3.0: + resolution: + { + integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, + } + strip-ansi@6.0.1: resolution: { @@ -1964,6 +2913,27 @@ packages: } engines: { node: ">=8" } + strtok3@10.3.5: + resolution: + { + integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==, + } + engines: { node: ">=18" } + + superagent@10.3.0: + resolution: + { + integrity: sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==, + } + engines: { node: ">=14.18.0" } + + supertest@7.2.2: + resolution: + { + integrity: sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==, + } + engines: { node: ">=14.18.0" } + supports-color@7.2.0: resolution: { @@ -2004,6 +2974,20 @@ packages: } engines: { node: ">=14.0.0" } + toidentifier@1.0.1: + resolution: + { + integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==, + } + engines: { node: ">=0.6" } + + token-types@6.1.2: + resolution: + { + integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==, + } + engines: { node: ">=14.16" } + ts-api-utils@2.5.0: resolution: { @@ -2013,6 +2997,12 @@ packages: peerDependencies: typescript: ">=4.8.4" + tslib@2.8.1: + resolution: + { + integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, + } + tsx@4.20.6: resolution: { @@ -2035,6 +3025,26 @@ packages: } engines: { node: ">=10" } + type-is@1.6.18: + resolution: + { + integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==, + } + engines: { node: ">= 0.6" } + + type-is@2.1.0: + resolution: + { + integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==, + } + engines: { node: ">= 18" } + + typedarray@0.0.6: + resolution: + { + integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==, + } + typescript@5.9.3: resolution: { @@ -2043,18 +3053,59 @@ packages: engines: { node: ">=14.17" } hasBin: true + uid@2.0.2: + resolution: + { + integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==, + } + engines: { node: ">=8" } + + uint8array-extras@1.5.0: + resolution: + { + integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==, + } + engines: { node: ">=18" } + undici-types@6.21.0: resolution: { integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==, } + unpipe@1.0.0: + resolution: + { + integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==, + } + engines: { node: ">= 0.8" } + uri-js@4.4.1: resolution: { integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, } + util-deprecate@1.0.2: + resolution: + { + integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, + } + + validator@13.15.35: + resolution: + { + integrity: sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==, + } + engines: { node: ">= 0.10" } + + vary@1.1.2: + resolution: + { + integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==, + } + engines: { node: ">= 0.8" } + vite@7.3.6: resolution: { @@ -2179,6 +3230,8 @@ packages: engines: { node: ">=10" } snapshots: + "@borewit/text-codec@0.2.2": {} + "@esbuild/aix-ppc64@0.25.12": optional: true @@ -2372,9 +3425,61 @@ snapshots: "@jridgewell/sourcemap-codec@1.6.0": {} + "@lukeed/csprng@1.1.0": {} + "@napi-rs/lzma-linux-x64-gnu@1.5.1": optional: true + "@nestjs/common@11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)": + dependencies: + file-type: 21.3.4 + iterare: 1.2.1 + load-esm: 1.0.3 + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + tslib: 2.8.1 + uid: 2.0.2 + optionalDependencies: + class-transformer: 0.5.1 + class-validator: 0.14.4 + transitivePeerDependencies: + - supports-color + + "@nestjs/core@11.2.3(@nestjs/common@11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.2.3)(reflect-metadata@0.2.2)(rxjs@7.8.2)": + dependencies: + "@nestjs/common": 11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) + fast-safe-stringify: 2.1.1 + iterare: 1.2.1 + path-to-regexp: 8.4.2 + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + tslib: 2.8.1 + uid: 2.0.2 + optionalDependencies: + "@nestjs/platform-express": 11.2.3(@nestjs/common@11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.2.3) + + "@nestjs/platform-express@11.2.3(@nestjs/common@11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.2.3)": + dependencies: + "@nestjs/common": 11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) + "@nestjs/core": 11.2.3(@nestjs/common@11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.2.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) + cors: 2.8.6 + express: 5.2.1 + multer: 2.3.0 + path-to-regexp: 8.4.2 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + "@nestjs/testing@11.2.3(@nestjs/common@11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.2.3)(@nestjs/platform-express@11.2.3)": + dependencies: + "@nestjs/common": 11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) + "@nestjs/core": 11.2.3(@nestjs/common@11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.2.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) + tslib: 2.8.1 + optionalDependencies: + "@nestjs/platform-express": 11.2.3(@nestjs/common@11.2.3(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.2.3) + + "@noble/hashes@1.8.0": {} + "@nodelib/fs.scandir@2.1.5": dependencies: "@nodelib/fs.stat": 2.0.5 @@ -2387,6 +3492,10 @@ snapshots: "@nodelib/fs.scandir": 2.1.5 fastq: 1.20.3 + "@paralleldrive/cuid2@2.3.1": + dependencies: + "@noble/hashes": 1.8.0 + "@prisma/client@6.19.0(prisma@6.19.0(typescript@5.9.3))(typescript@5.9.3)": optionalDependencies: prisma: 6.19.0(typescript@5.9.3) @@ -2423,6 +3532,26 @@ snapshots: dependencies: "@prisma/debug": 6.19.0 + "@redis/bloom@5.12.1(@redis/client@5.12.1)": + dependencies: + "@redis/client": 5.12.1 + + "@redis/client@5.12.1": + dependencies: + cluster-key-slot: 1.1.2 + + "@redis/json@5.12.1(@redis/client@5.12.1)": + dependencies: + "@redis/client": 5.12.1 + + "@redis/search@5.12.1(@redis/client@5.12.1)": + dependencies: + "@redis/client": 5.12.1 + + "@redis/time-series@5.12.1(@redis/client@5.12.1)": + dependencies: + "@redis/client": 5.12.1 + "@rollup/rollup-android-arm-eabi@4.63.2": optional: true @@ -2500,19 +3629,83 @@ snapshots: "@standard-schema/spec@1.1.0": {} + "@tokenizer/inflate@0.4.1": + dependencies: + debug: 4.4.3 + token-types: 6.1.2 + transitivePeerDependencies: + - supports-color + + "@tokenizer/token@0.3.0": {} + + "@types/body-parser@1.19.6": + dependencies: + "@types/connect": 3.4.38 + "@types/node": 22.19.3 + "@types/chai@5.2.3": dependencies: "@types/deep-eql": 4.0.2 assertion-error: 2.0.1 + "@types/connect@3.4.38": + dependencies: + "@types/node": 22.19.3 + + "@types/cookiejar@2.1.5": {} + "@types/deep-eql@4.0.2": {} "@types/estree@1.0.9": {} + "@types/express-serve-static-core@5.1.3": + dependencies: + "@types/node": 22.19.3 + "@types/qs": 6.15.1 + "@types/range-parser": 1.2.7 + "@types/send": 1.2.1 + + "@types/express@5.0.6": + dependencies: + "@types/body-parser": 1.19.6 + "@types/express-serve-static-core": 5.1.3 + "@types/serve-static": 2.2.0 + + "@types/http-errors@2.0.5": {} + + "@types/methods@1.1.4": {} + "@types/node@22.19.3": dependencies: undici-types: 6.21.0 + "@types/qs@6.15.1": {} + + "@types/range-parser@1.2.7": {} + + "@types/send@1.2.1": + dependencies: + "@types/node": 22.19.3 + + "@types/serve-static@2.2.0": + dependencies: + "@types/http-errors": 2.0.5 + "@types/node": 22.19.3 + + "@types/superagent@8.1.11": + dependencies: + "@types/cookiejar": 2.1.5 + "@types/methods": 1.1.4 + "@types/node": 22.19.3 + form-data: 4.0.6 + + "@types/supertest@6.0.3": + dependencies: + "@types/methods": 1.1.4 + "@types/superagent": 8.1.11 + + "@types/validator@13.15.10": {} + "@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3)": dependencies: "@eslint-community/regexpp": 4.12.2 @@ -2647,6 +3840,11 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.1 + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.1.0 + acorn-jsx@5.3.2(acorn@8.18.0): dependencies: acorn: 8.18.0 @@ -2666,14 +3864,34 @@ snapshots: dependencies: color-convert: 2.0.1 + append-field@1.0.0: {} + argparse@2.0.1: {} + asap@2.0.6: {} + assertion-error@2.0.1: {} + asynckit@0.4.0: {} + balanced-match@1.0.2: {} balanced-match@4.0.4: {} + body-parser@2.3.0: + dependencies: + bytes: 3.1.2 + content-type: 2.1.0 + debug: 4.4.3 + http-errors: 2.0.1 + iconv-lite: 0.7.3 + on-finished: 2.4.1 + qs: 6.16.0 + raw-body: 3.0.2 + type-is: 2.1.0 + transitivePeerDependencies: + - supports-color + brace-expansion@1.1.18: dependencies: balanced-match: 1.0.2 @@ -2683,6 +3901,14 @@ snapshots: dependencies: balanced-match: 4.0.4 + buffer-from@1.1.2: {} + + busboy@1.6.0: + dependencies: + streamsearch: 1.1.0 + + bytes@3.1.2: {} + c12@3.1.0: dependencies: chokidar: 4.0.3 @@ -2698,6 +3924,16 @@ snapshots: pkg-types: 2.3.3 rc9: 2.1.2 + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + callsites@3.1.0: {} chai@6.2.2: {} @@ -2717,22 +3953,62 @@ snapshots: citty@0.2.2: {} + class-transformer@0.5.1: {} + + class-validator@0.14.4: + dependencies: + "@types/validator": 13.15.10 + libphonenumber-js: 1.13.13 + validator: 13.15.35 + + cluster-key-slot@1.1.2: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 color-name@1.1.4: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + component-emitter@1.3.1: {} + concat-map@0.0.1: {} + concat-stream@2.0.0: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.2 + typedarray: 0.0.6 + confbox@0.2.4: {} confbox@0.3.1: {} consola@3.4.2: {} + content-disposition@1.1.0: {} + + content-type@1.0.5: {} + + content-type@2.1.0: {} + convert-source-map@2.0.0: {} + cookie-signature@1.2.2: {} + + cookie@0.7.2: {} + + cookiejar@2.1.4: {} + + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -2749,14 +4025,31 @@ snapshots: defu@6.1.7: {} + delayed-stream@1.0.0: {} + + depd@2.0.0: {} + destr@2.0.5: {} + dezalgo@1.0.4: + dependencies: + asap: 2.0.6 + wrappy: 1.0.2 + doctrine@3.0.0: dependencies: esutils: 2.0.3 dotenv@16.6.1: {} + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + ee-first@1.1.1: {} + effect@3.20.0: dependencies: "@standard-schema/spec": 1.1.0 @@ -2764,8 +4057,25 @@ snapshots: empathic@2.0.0: {} + encodeurl@2.0.0: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + es-module-lexer@2.3.2: {} + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + esbuild@0.25.12: optionalDependencies: "@esbuild/aix-ppc64": 0.25.12 @@ -2824,6 +4134,8 @@ snapshots: "@esbuild/win32-ia32": 0.28.2 "@esbuild/win32-x64": 0.28.2 + escape-html@1.0.3: {} + escape-string-regexp@4.0.0: {} eslint-scope@7.2.2: @@ -2900,8 +4212,43 @@ snapshots: esutils@2.0.3: {} + etag@1.8.1: {} + expect-type@1.4.0: {} + express@5.2.1: + dependencies: + accepts: 2.0.0 + body-parser: 2.3.0 + content-disposition: 1.1.0 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.3 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.1 + fresh: 2.0.0 + http-errors: 2.0.1 + merge-descriptors: 2.0.0 + mime-types: 3.0.2 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.16.0 + range-parser: 1.3.0 + router: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 + statuses: 2.0.2 + type-is: 2.1.0 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + exsolve@1.1.1: {} fast-check@3.23.2: @@ -2914,6 +4261,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-safe-stringify@2.1.1: {} + fastq@1.20.3: dependencies: reusify: 1.1.0 @@ -2926,6 +4275,26 @@ snapshots: dependencies: flat-cache: 3.2.0 + file-type@21.3.4: + dependencies: + "@tokenizer/inflate": 0.4.1 + strtok3: 10.3.5 + token-types: 6.1.2 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color + + finalhandler@2.1.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -2939,11 +4308,49 @@ snapshots: flatted@3.4.4: {} + form-data@4.0.6: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.4 + mime-types: 2.1.35 + + formidable@3.5.4: + dependencies: + "@paralleldrive/cuid2": 2.3.1 + dezalgo: 1.0.4 + once: 1.4.0 + + forwarded@0.2.0: {} + + fresh@2.0.0: {} + fs.realpath@1.0.0: {} fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + get-tsconfig@4.14.3: dependencies: resolve-pkg-maps: 1.0.0 @@ -2974,10 +4381,38 @@ snapshots: dependencies: type-fest: 0.20.2 + gopd@1.2.0: {} + graphemer@1.4.0: {} has-flag@4.0.0: {} + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + helmet@8.3.0: {} + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + iconv-lite@0.7.3: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + ignore@5.3.2: {} ignore@7.0.9: {} @@ -2996,6 +4431,8 @@ snapshots: inherits@2.0.4: {} + ipaddr.js@1.9.1: {} + is-extglob@2.1.1: {} is-glob@4.0.3: @@ -3004,8 +4441,12 @@ snapshots: is-path-inside@3.0.3: {} + is-promise@4.0.0: {} + isexe@2.0.0: {} + iterare@1.2.1: {} + jiti@2.7.0: {} js-yaml@4.3.2: @@ -3027,6 +4468,10 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + libphonenumber-js@1.13.13: {} + + load-esm@1.0.3: {} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -3037,6 +4482,30 @@ snapshots: dependencies: "@jridgewell/sourcemap-codec": 1.6.0 + math-intrinsics@1.1.0: {} + + media-typer@0.3.0: {} + + media-typer@1.1.1: {} + + merge-descriptors@2.0.0: {} + + methods@1.1.2: {} + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + + mime@2.6.0: {} + minimatch@10.2.6: dependencies: brace-expansion: 5.0.9 @@ -3047,10 +4516,21 @@ snapshots: ms@2.1.3: {} + multer@2.3.0: + dependencies: + append-field: 1.0.0 + busboy: 1.6.0 + concat-stream: 2.0.0 + type-is: 1.6.18 + nanoid@3.3.19: {} natural-compare@1.4.0: {} + negotiator@1.1.0: + dependencies: + content-type: 2.1.0 + node-fetch-native@1.6.7: {} nypm@0.6.10: @@ -3059,10 +4539,18 @@ snapshots: pathe: 2.0.3 tinyexec: 1.3.1 + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + obug@2.2.1: {} ohash@2.0.12: {} + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -3088,12 +4576,16 @@ snapshots: dependencies: callsites: 3.1.0 + parseurl@1.3.3: {} + path-exists@4.0.0: {} path-is-absolute@1.0.1: {} path-key@3.1.1: {} + path-to-regexp@8.4.2: {} + pathe@2.0.3: {} perfect-debounce@1.0.0: {} @@ -3127,19 +4619,57 @@ snapshots: transitivePeerDependencies: - magicast + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + punycode@2.3.1: {} pure-rand@6.1.0: {} + qs@6.16.0: + dependencies: + es-define-property: 1.0.1 + side-channel: 1.1.1 + queue-microtask@1.2.3: {} + range-parser@1.3.0: {} + + raw-body@3.0.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.7.3 + unpipe: 1.0.0 + rc9@2.1.2: dependencies: defu: 6.1.7 destr: 2.0.5 + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + readdirp@4.1.2: {} + redis@5.12.1: + dependencies: + "@redis/bloom": 5.12.1(@redis/client@5.12.1) + "@redis/client": 5.12.1 + "@redis/json": 5.12.1(@redis/client@5.12.1) + "@redis/search": 5.12.1(@redis/client@5.12.1) + "@redis/time-series": 5.12.1(@redis/client@5.12.1) + transitivePeerDependencies: + - "@node-rs/xxhash" + - "@opentelemetry/api" + + reflect-metadata@0.2.2: {} + resolve-from@4.0.0: {} resolve-pkg-maps@1.0.0: {} @@ -3182,32 +4712,139 @@ snapshots: "@rollup/rollup-win32-x64-msvc": 4.63.2 fsevents: 2.3.3 + router@2.2.0: + dependencies: + debug: 4.4.3 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.4.2 + transitivePeerDependencies: + - supports-color + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + semver@7.8.5: {} + send@1.2.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.1 + mime-types: 3.0.2 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.3.0 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serve-static@2.2.1: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.1 + transitivePeerDependencies: + - supports-color + + setprototypeof@1.2.0: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 shebang-regex@3.0.0: {} + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} source-map-js@1.2.1: {} stackback@0.0.2: {} + statuses@2.0.2: {} + std-env@4.2.0: {} + streamsearch@1.1.0: {} + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 strip-json-comments@3.1.1: {} + strtok3@10.3.5: + dependencies: + "@tokenizer/token": 0.3.0 + + superagent@10.3.0: + dependencies: + component-emitter: 1.3.1 + cookiejar: 2.1.4 + debug: 4.4.3 + fast-safe-stringify: 2.1.1 + form-data: 4.0.6 + formidable: 3.5.4 + methods: 1.1.2 + mime: 2.6.0 + qs: 6.16.0 + transitivePeerDependencies: + - supports-color + + supertest@7.2.2: + dependencies: + cookie-signature: 1.2.2 + methods: 1.1.2 + superagent: 10.3.0 + transitivePeerDependencies: + - supports-color + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -3225,10 +4862,20 @@ snapshots: tinyrainbow@3.1.1: {} + toidentifier@1.0.1: {} + + token-types@6.1.2: + dependencies: + "@borewit/text-codec": 0.2.2 + "@tokenizer/token": 0.3.0 + ieee754: 1.2.1 + ts-api-utils@2.5.0(typescript@5.9.3): dependencies: typescript: 5.9.3 + tslib@2.8.1: {} + tsx@4.20.6: dependencies: esbuild: 0.25.12 @@ -3242,14 +4889,41 @@ snapshots: type-fest@0.20.2: {} + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + type-is@2.1.0: + dependencies: + content-type: 2.1.0 + media-typer: 1.1.1 + mime-types: 3.0.2 + + typedarray@0.0.6: {} + typescript@5.9.3: {} + uid@2.0.2: + dependencies: + "@lukeed/csprng": 1.1.0 + + uint8array-extras@1.5.0: {} + undici-types@6.21.0: {} + unpipe@1.0.0: {} + uri-js@4.4.1: dependencies: punycode: 2.3.1 + util-deprecate@1.0.2: {} + + validator@13.15.35: {} + + vary@1.1.2: {} + vite@7.3.6(@types/node@22.19.3)(jiti@2.7.0)(tsx@4.20.6): dependencies: esbuild: 0.28.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 924b55f..0e5a073 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,3 @@ packages: - - packages/* + - "packages/*" + - "apps/*" diff --git a/tests/integration/seed.spec.ts b/tests/integration/seed.spec.ts index 47919e3..d734a44 100644 --- a/tests/integration/seed.spec.ts +++ b/tests/integration/seed.spec.ts @@ -29,5 +29,5 @@ describe("seed", () => { prisma.bottle.count({ where: { poolStatus: "IN_POOL" } }), ]), ).resolves.toEqual([2, 2, 1]); - }); + }, 30_000); }); diff --git a/tsconfig.base.json b/tsconfig.base.json index 65251a7..b1ad68c 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -3,6 +3,8 @@ "target": "ES2022", "module": "ESNext", "moduleResolution": "Bundler", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, "strict": true, "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true,