feat(api): foundation canon JCS — Pino+CLS+RFC9457+health+ping (Frente A)

Estabelece a fundação operacional de apps/api conforme STACK.md v2.2 e
CODING-RULES.md v2.0, substituindo o hello-world scaffolded.

- tracing.ts primeiro import (PGD-OBS-001) — stub OTel ativável por env
- EnvSchema Zod 4 com fail-fast (superRefine guarda prod) + EnvModule global
- nestjs-pino com redact LGPD (*.cpf|*.cardNumber|*.password|auth|cookie)
- main.ts hardenizado: helmet, CORS por env, compression, versionamento URI
  /api/v1, graceful shutdown
- ProblemDetailsFilter global (RFC 9457 application/problem+json), Zod -> 422
- Health endpoints /api/v1/health/{live,ready} com memory.checkHeap(350MB)
  (ready skeleton documenta K=3 LRU pool conforme PGD-OBS-003)
- WorkspaceModule via ClsModule.forRootAsync — requestId+workspaceId no CLS,
  idGenerator alinhado com pino-http para mesmo UUID em header e body
- GET /api/v1/ping retornando workspaceId+requestId (alvo de smoke test e
  futuro healthcheck do docker compose)
- ZodValidationPipe (nestjs-zod) como APP_PIPE global
- tsconfig.app.json target ES2023 (alinhado ao base)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 17:50:42 +00:00
parent 3a42723c71
commit 055f9f98f0
21 changed files with 1148 additions and 80 deletions

View File

@@ -1,21 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';
describe('AppController', () => {
let app: TestingModule;
beforeAll(async () => {
app = await Test.createTestingModule({
controllers: [AppController],
providers: [AppService],
}).compile();
});
describe('getData', () => {
it('should return "Hello API"', () => {
const appController = app.get<AppController>(AppController);
expect(appController.getData()).toEqual({ message: 'Hello API' });
});
});
});

View File

@@ -1,12 +0,0 @@
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getData() {
return this.appService.getData();
}
}

View File

@@ -1,10 +1,28 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { AppController } from './app.controller'; import { APP_FILTER, APP_PIPE } from '@nestjs/core';
import { AppService } from './app.service'; import { ZodValidationPipe } from 'nestjs-zod';
import { EnvModule } from './config/env.module';
import { LoggerModule } from './logger/logger.module';
import { WorkspaceModule } from './workspace/workspace.module';
import { HealthModule } from './health/health.module';
import { PingModule } from './ping/ping.module';
import { ProblemDetailsFilter } from './filters/problem-details.filter';
@Module({ @Module({
imports: [], imports: [
controllers: [AppController], // Ordem importa: Env primeiro (fail-fast), depois Logger, CLS, módulos de domínio.
providers: [AppService], EnvModule,
LoggerModule,
WorkspaceModule,
HealthModule,
PingModule,
],
providers: [
// Pipe global: nestjs-zod converte ZodSchema (via createZodDto) em validação automática.
// CODING-RULES §06: schema é o contrato; DTO é a classe que o expõe.
{ provide: APP_PIPE, useClass: ZodValidationPipe },
// Filter global: RFC 9457. Zod → 422.
{ provide: APP_FILTER, useClass: ProblemDetailsFilter },
],
}) })
export class AppModule {} export class AppModule {}

View File

@@ -1,20 +0,0 @@
import { Test } from '@nestjs/testing';
import { AppService } from './app.service';
describe('AppService', () => {
let service: AppService;
beforeAll(async () => {
const app = await Test.createTestingModule({
providers: [AppService],
}).compile();
service = app.get<AppService>(AppService);
});
describe('getData', () => {
it('should return "Hello API"', () => {
expect(service.getData()).toEqual({ message: 'Hello API' });
});
});
});

View File

@@ -1,8 +0,0 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getData(): { message: string } {
return { message: 'Hello API' };
}
}

View File

@@ -0,0 +1,21 @@
import { ConfigModule, ConfigService } from '@nestjs/config';
import { Global, Module } from '@nestjs/common';
import type { Env } from './env.schema';
import { validateEnv } from './env.schema';
// Tipagem do ConfigService<Env, true> garante chaves sem `string | undefined` no caller.
export type AppConfigService = ConfigService<Env, true>;
@Global()
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
cache: true,
// CODING-RULES §08: validate com Zod — fail-fast.
validate: (raw) => validateEnv(raw),
}),
],
exports: [ConfigModule],
})
export class EnvModule {}

View File

@@ -0,0 +1,98 @@
import { z } from 'zod';
// CODING-RULES.md §08: validação Zod no boot (fail-fast). Sem default em prod.
// Em dev, defaults razoáveis facilitam o setup; em prod o Vault Agent injeta tudo.
const NodeEnv = z.enum(['development', 'test', 'staging', 'production']);
export const EnvSchema = z
.object({
NODE_ENV: NodeEnv.default('development'),
// API
API_PORT: z.coerce.number().int().positive().default(3000),
API_HOST: z.string().min(1).default('0.0.0.0'),
API_GLOBAL_PREFIX: z.string().min(1).default('api'),
API_VERSION: z.string().regex(/^v\d+$/).default('v1'),
// CORS — origens permitidas (Web em dev: http://localhost:4200)
CORS_ORIGINS: z
.string()
.default('http://localhost:4200')
.transform((s) =>
s
.split(',')
.map((o) => o.trim())
.filter(Boolean),
),
// Master-login (DEV stub — IdP real virá na próxima sessão)
MASTER_LOGIN_URL: z.url().default('http://localhost:3000/auth/dev'),
MASTER_LOGIN_JWT_SECRET: z.string().min(32).default('dev_jwt_secret_change_in_prod_use_vault_xxxxx'),
JWT_ACCESS_EXPIRATION: z.coerce.number().int().positive().default(900),
JWT_REFRESH_EXPIRATION: z.coerce.number().int().positive().default(2_592_000),
// Multi-tenancy — workspace de dev (até master-login real entrar)
DEFAULT_WORKSPACE_ID: z.string().min(1).default('dev-workspace'),
// Postgres (Prisma virá depois)
DATABASE_URL: z.string().optional(),
MIGRATION_DATABASE_URL: z.string().optional(),
// Valkey / BullMQ (entrarão com filas)
REDIS_URL: z.url().default('redis://localhost:6379'),
// MinIO (entrará com uploads)
S3_ENDPOINT: z.url().optional(),
S3_REGION: z.string().optional(),
S3_ACCESS_KEY: z.string().optional(),
S3_SECRET_KEY: z.string().optional(),
S3_BUCKET: z.string().optional(),
// SMTP (Mailpit dev / Resend prod)
SMTP_HOST: z.string().default('localhost'),
SMTP_PORT: z.coerce.number().int().positive().default(1025),
SMTP_FROM: z.email().default('noreply@sar.dev'),
// Telemetry
OTEL_SERVICE_NAME: z.string().default('sar-api'),
OTEL_EXPORTER_OTLP_ENDPOINT: z.url().optional(),
OTEL_TRACES_SAMPLER: z.string().default('parentbased_traceidratio'),
OTEL_TRACES_SAMPLER_ARG: z.coerce.number().min(0).max(1).default(1.0),
SENTRY_DSN: z.string().optional(),
// Feature flags
GROWTHBOOK_API_HOST: z.string().optional(),
GROWTHBOOK_CLIENT_KEY: z.string().optional(),
// Logger
LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),
})
.superRefine((env, ctx) => {
if (env.NODE_ENV === 'production') {
if (env.MASTER_LOGIN_JWT_SECRET.startsWith('dev_jwt_secret')) {
ctx.addIssue({
code: 'custom',
path: ['MASTER_LOGIN_JWT_SECRET'],
message: 'JWT secret de DEV não pode ser usada em produção (CODING-RULES §08, PGD-SEC-002).',
});
}
if (!env.DATABASE_URL) {
ctx.addIssue({ code: 'custom', path: ['DATABASE_URL'], message: 'obrigatório em produção' });
}
}
});
export type Env = z.infer<typeof EnvSchema>;
export function validateEnv(raw: Record<string, unknown>): Env {
const result = EnvSchema.safeParse(raw);
if (!result.success) {
// Fail-fast: agrupa erros legíveis antes do crash.
const issues = result.error.issues
.map((i) => ` - ${i.path.join('.') || '(root)'}: ${i.message}`)
.join('\n');
throw new Error(`[env] validação falhou — corrija .env:\n${issues}`);
}
return result.data;
}

View File

@@ -0,0 +1,170 @@
import {
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
HttpStatus,
Logger,
} from '@nestjs/common';
import type { Request, Response } from 'express';
import { ZodError } from 'zod';
// RFC 9457 Problem Details for HTTP APIs.
// CODING-RULES §05: Zod sempre 422 (nunca 400). 403 vira 404 onde o cliente
// não pode saber da existência (regra aplicada por guards de domínio — aqui
// só repassamos o status que o caller escolheu).
const PROBLEM_CONTENT_TYPE = 'application/problem+json';
const BASE_TYPE_URI = 'https://docs.sar.jcs.com.br/errors';
interface ProblemDetails {
type: string;
title: string;
status: number;
detail?: string;
instance: string;
requestId?: string;
errors?: ReadonlyArray<{ path: string; message: string; code?: string }>;
[key: string]: unknown;
}
@Catch()
export class ProblemDetailsFilter implements ExceptionFilter {
private readonly logger = new Logger(ProblemDetailsFilter.name);
catch(exception: unknown, host: ArgumentsHost): void {
const ctx = host.switchToHttp();
const req = ctx.getRequest<Request>();
const res = ctx.getResponse<Response>();
const problem = this.toProblem(exception, req);
if (problem.status >= 500) {
this.logger.error(
{ err: exception, requestId: problem.requestId, path: problem.instance },
problem.title,
);
}
res.setHeader('Content-Type', PROBLEM_CONTENT_TYPE);
res.status(problem.status).json(problem);
}
private toProblem(exception: unknown, req: Request): ProblemDetails {
const requestId = this.extractRequestId(req);
const instance = req.originalUrl ?? req.url ?? '/';
// Zod direto (validação manual ou rethrow de pipe sem nestjs-zod).
if (exception instanceof ZodError) {
return this.zodProblem(exception, instance, requestId);
}
if (exception instanceof HttpException) {
return this.httpProblem(exception, instance, requestId);
}
return {
type: `${BASE_TYPE_URI}/internal-server-error`,
title: 'Internal Server Error',
status: HttpStatus.INTERNAL_SERVER_ERROR,
detail: 'Erro interno. Reporte ao suporte com o requestId.',
instance,
requestId,
};
}
private zodProblem(err: ZodError, instance: string, requestId?: string): ProblemDetails {
return {
type: `${BASE_TYPE_URI}/validation`,
title: 'Unprocessable Entity',
status: HttpStatus.UNPROCESSABLE_ENTITY,
detail: 'Validação dos dados de entrada falhou.',
instance,
requestId,
errors: err.issues.map((i) => ({
path: i.path.join('.'),
message: i.message,
code: i.code,
})),
};
}
private httpProblem(err: HttpException, instance: string, requestId?: string): ProblemDetails {
const status = err.getStatus();
const response = err.getResponse();
// nestjs-zod lança ZodValidationException (HttpException 400/422) com payload já estruturado.
if (typeof response === 'object' && response !== null) {
const r = response as Record<string, unknown>;
// nestjs-zod 5.x: { statusCode, message, errors: ZodIssue[] }
if (Array.isArray(r['errors']) && r['errors'].length > 0) {
const issues = r['errors'] as Array<{ path?: unknown; message?: unknown; code?: unknown }>;
return {
type: `${BASE_TYPE_URI}/validation`,
title: 'Unprocessable Entity',
status: HttpStatus.UNPROCESSABLE_ENTITY,
detail: typeof r['message'] === 'string' ? (r['message'] as string) : 'Validação falhou.',
instance,
requestId,
errors: issues.map((i) => ({
path: Array.isArray(i.path) ? i.path.join('.') : String(i.path ?? ''),
message: String(i.message ?? ''),
code: typeof i.code === 'string' ? i.code : undefined,
})),
};
}
const title = this.titleFor(status);
return {
type: `${BASE_TYPE_URI}/${this.slug(title)}`,
title,
status,
detail: typeof r['message'] === 'string' ? (r['message'] as string) : title,
instance,
requestId,
};
}
const title = this.titleFor(status);
return {
type: `${BASE_TYPE_URI}/${this.slug(title)}`,
title,
status,
detail: typeof response === 'string' ? response : title,
instance,
requestId,
};
}
private extractRequestId(req: Request): string | undefined {
const fromHeader = req.headers['x-request-id'];
if (typeof fromHeader === 'string') return fromHeader;
const reqId = (req as Request & { id?: unknown }).id;
return typeof reqId === 'string' ? reqId : undefined;
}
private titleFor(status: number): string {
switch (status) {
case 400:
return 'Bad Request';
case 401:
return 'Unauthorized';
case 403:
return 'Forbidden';
case 404:
return 'Not Found';
case 409:
return 'Conflict';
case 422:
return 'Unprocessable Entity';
case 429:
return 'Too Many Requests';
default:
return status >= 500 ? 'Internal Server Error' : 'Error';
}
}
private slug(title: string): string {
return title.toLowerCase().replace(/\s+/g, '-');
}
}

View File

@@ -0,0 +1,42 @@
import { Controller, Get } from '@nestjs/common';
import {
HealthCheck,
HealthCheckResult,
HealthCheckService,
MemoryHealthIndicator,
} from '@nestjs/terminus';
// CODING-RULES §20 (PGD-OBS-003):
// /health/live → liveness só com memory.checkHeap(350MB).
// /health/ready → readiness pinga master-login + amostra LRU (K=3) dos pools
// quentes do WorkspacePrismaPool + Valkey + BullMQ.
// NUNCA percorrer todos os workspaces (O(N) → false negative).
//
// Hoje o "ready" só checa heap, idêntico ao live. Quando master-login,
// WorkspacePrismaPool, Valkey e BullMQ entrarem, cada um adiciona seu indicator
// aqui — sem nunca virar O(N) sobre workspaces.
@Controller({ path: 'health' })
export class HealthController {
constructor(
private readonly health: HealthCheckService,
private readonly memory: MemoryHealthIndicator,
) {}
@Get('live')
@HealthCheck()
live(): Promise<HealthCheckResult> {
return this.health.check([() => this.memory.checkHeap('heap', 350 * 1024 * 1024)]);
}
@Get('ready')
@HealthCheck()
ready(): Promise<HealthCheckResult> {
// Skeleton: por enquanto idêntico ao live. Próximas frentes:
// - MasterLoginHealthIndicator (obrigatório)
// - WorkspacePoolLruHealthIndicator (K=3 amostra)
// - ValkeyHealthIndicator
// - BullMQHealthIndicator
return this.health.check([() => this.memory.checkHeap('heap', 350 * 1024 * 1024)]);
}
}

View File

@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { TerminusModule } from '@nestjs/terminus';
import { HealthController } from './health.controller';
@Module({
imports: [TerminusModule],
controllers: [HealthController],
})
export class HealthModule {}

View File

@@ -0,0 +1,81 @@
import { Module } from '@nestjs/common';
import { LoggerModule as PinoLoggerModule } from 'nestjs-pino';
import { randomUUID } from 'node:crypto';
import type { IncomingMessage, ServerResponse } from 'node:http';
import { ConfigService } from '@nestjs/config';
import type { Env } from '../config/env.schema';
// CODING-RULES §09 (PGD-OBS-002): redact LGPD agressivo.
// Sempre cobrir: *.cpf, *.cardNumber, *.password, req.headers.authorization, req.headers.cookie.
const REDACT_PATHS = [
'*.cpf',
'*.cardNumber',
'*.password',
'*.passwordHash',
'*.token',
'*.secret',
'req.headers.authorization',
'req.headers.cookie',
'req.headers["set-cookie"]',
'res.headers["set-cookie"]',
];
@Module({
imports: [
PinoLoggerModule.forRootAsync({
inject: [ConfigService],
useFactory: (config: ConfigService<Env, true>) => {
const isProd = config.get('NODE_ENV', { infer: true }) === 'production';
const level = config.get('LOG_LEVEL', { infer: true });
const serviceName = config.get('OTEL_SERVICE_NAME', { infer: true });
return {
pinoHttp: {
level,
// pretty em dev; JSON estruturado em prod (Grafana LGTM consumirá).
transport: isProd
? undefined
: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'SYS:HH:MM:ss.l',
ignore: 'pid,hostname,req,res,responseTime',
messageFormat: '{msg} {req.method} {req.url} {res.statusCode} ({responseTime}ms)',
},
},
redact: {
paths: REDACT_PATHS,
censor: '[REDACTED]',
},
// Correlation ID: respeita header upstream ou gera UUID v4.
genReqId: (req: IncomingMessage, res: ServerResponse) => {
const headerVal =
req.headers['x-request-id'] ??
req.headers['x-correlation-id'] ??
req.headers['traceparent'];
const id = typeof headerVal === 'string' && headerVal.length > 0 ? headerVal : randomUUID();
res.setHeader('x-request-id', id);
return id;
},
customProps: () => ({ service: serviceName }),
// Reduz ruído em health checks.
customLogLevel: (_req, res, err) => {
if (err || res.statusCode >= 500) return 'error';
if (res.statusCode >= 400) return 'warn';
return 'info';
},
autoLogging: {
ignore: (req) => {
const url = req.url ?? '';
return url.startsWith('/api/v1/health');
},
},
},
};
},
}),
],
exports: [PinoLoggerModule],
})
export class LoggerModule {}

View File

@@ -0,0 +1,36 @@
import { Controller, Get } from '@nestjs/common';
import { ClsService } from 'nestjs-cls';
import type { WorkspaceClsStore } from '../workspace/workspace.types';
// Endpoint de verificação de fundação:
// - confirma que CLS está populando workspaceId + requestId;
// - serve como alvo do healthcheck do docker compose / smoke test;
// - usado pela Web (Frente B) para validar conectividade real.
interface PingResponse {
status: 'ok';
service: string;
version: string;
workspaceId: string;
requestId: string;
uptimeSeconds: number;
now: string;
}
@Controller({ path: 'ping' })
export class PingController {
constructor(private readonly cls: ClsService<WorkspaceClsStore>) {}
@Get()
ping(): PingResponse {
return {
status: 'ok',
service: 'sar-api',
version: process.env['npm_package_version'] ?? '0.1.0',
workspaceId: this.cls.get('workspaceId'),
requestId: this.cls.get('requestId'),
uptimeSeconds: Math.round(process.uptime()),
now: new Date().toISOString(),
};
}
}

View File

@@ -0,0 +1,7 @@
import { Module } from '@nestjs/common';
import { PingController } from './ping.controller';
@Module({
controllers: [PingController],
})
export class PingModule {}

View File

@@ -0,0 +1,48 @@
import { Module } from '@nestjs/common';
import { ClsModule } from 'nestjs-cls';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { randomUUID } from 'node:crypto';
import type { Request, Response } from 'express';
import type { WorkspaceClsStore } from './workspace.types';
import type { Env } from '../config/env.schema';
// CLS popula contexto por request. Hoje: requestId + DEFAULT_WORKSPACE_ID do env.
// Amanhã: workspaceId vem do JWT (PGD-AUTHZ-002); `prisma` é resolvido pelo
// WorkspacePrismaPool e injetado via cls.set('prisma', ...) aqui mesmo.
@Module({
imports: [
ClsModule.forRootAsync({
global: true,
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService<Env, true>) => ({
middleware: {
mount: true,
generateId: true,
idGenerator: (req: Request) => {
// Prioridade: req.id (pino-http já gerou/leu header) > header bruto > novo UUID.
const fromPino = (req as Request & { id?: unknown }).id;
if (typeof fromPino === 'string' && fromPino.length > 0) return fromPino;
const headerVal = req.headers['x-request-id'];
return typeof headerVal === 'string' && headerVal.length > 0
? headerVal
: randomUUID();
},
setup: (cls, req: Request, res: Response) => {
const store = cls as unknown as {
set: <K extends keyof WorkspaceClsStore>(key: K, value: WorkspaceClsStore[K]) => void;
getId: () => string;
};
const requestId = store.getId();
res.setHeader('x-request-id', requestId);
store.set('requestId', requestId);
store.set('workspaceId', config.get('DEFAULT_WORKSPACE_ID', { infer: true }));
},
},
}),
}),
],
exports: [ClsModule],
})
export class WorkspaceModule {}

View File

@@ -0,0 +1,13 @@
import type { ClsStore } from 'nestjs-cls';
// Forma do CLS store por request — fonte da verdade para qualquer caller
// que faça `cls.get(...)`. Quando o PrismaClient por workspace entrar
// (ADR 0006), `prisma` virará obrigatório aqui — por hora segue opcional.
export interface WorkspaceClsStore extends ClsStore {
requestId: string;
workspaceId: string;
// userId virá quando master-login estiver plugado.
userId?: string;
// prisma: PrismaClient — adicionar quando WorkspacePrismaPool entrar.
}

View File

@@ -1,19 +1,82 @@
/** // CODING-RULES §09 (PGD-OBS-001): tracing PRECISA ser o primeiro import.
* This is not a production server yet! // OTel NodeSDK faz monkey-patch dos módulos node:http/pg/etc. antes do Nest.
* This is only a minimal backend to get started. import './tracing';
*/
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core'; import { NestFactory } from '@nestjs/core';
import { VersioningType, type INestApplication } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Logger } from 'nestjs-pino';
import helmet from 'helmet';
import compression from 'compression';
import { AppModule } from './app/app.module'; import { AppModule } from './app/app.module';
import type { Env } from './app/config/env.schema';
async function bootstrap() { async function bootstrap(): Promise<void> {
const app = await NestFactory.create(AppModule); const app: INestApplication = await NestFactory.create(AppModule, {
const globalPrefix = 'api'; bufferLogs: true, // logs do boot vão pro Pino quando ele subir
});
// Logger Pino global (substitui o NestLogger padrão).
app.useLogger(app.get(Logger));
const config = app.get(ConfigService) as ConfigService<Env, true>;
// CORS — origens vindas do EnvSchema (já parseadas em array).
app.enableCors({
origin: config.get('CORS_ORIGINS', { infer: true }),
credentials: true,
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
allowedHeaders: [
'Content-Type',
'Authorization',
'X-Request-Id',
'X-Correlation-Id',
'Idempotency-Key',
],
exposedHeaders: ['X-Request-Id'],
maxAge: 600,
});
// Helmet — headers de segurança canônicos.
app.use(
helmet({
contentSecurityPolicy: false, // SPA serve CSP via Nginx; API JSON dispensa.
crossOriginEmbedderPolicy: false,
}),
);
// Compression — gzip/br.
app.use(compression());
// Versionamento via URI: /api/v1/...
const globalPrefix = config.get('API_GLOBAL_PREFIX', { infer: true });
const apiVersion = config.get('API_VERSION', { infer: true }).replace(/^v/, '');
app.setGlobalPrefix(globalPrefix); app.setGlobalPrefix(globalPrefix);
const port = process.env.PORT || 3000; app.enableVersioning({
await app.listen(port); type: VersioningType.URI,
Logger.log(`🚀 Application is running on: http://localhost:${port}/${globalPrefix}`); defaultVersion: apiVersion,
prefix: 'v',
});
// Graceful shutdown — Nest emite SIGTERM/SIGINT → hooks rodam → dreno de conexões.
// Compose: stop_grace_period: 30s + HAProxy drain 30s (CODING-RULES §18).
app.enableShutdownHooks();
const port = config.get('API_PORT', { infer: true });
const host = config.get('API_HOST', { infer: true });
await app.listen(port, host);
app
.get(Logger)
.log(
`SAR API pronta em http://${host}:${port}/${globalPrefix}/${apiVersion === '0' ? '' : `v${apiVersion}`}`,
'Bootstrap',
);
} }
bootstrap(); bootstrap().catch((err) => {
// Antes do Logger Pino estar disponível, qualquer erro de boot cai aqui.
console.error('[bootstrap] crash fatal — encerrando:', err);
process.exit(1);
});

22
apps/api/src/tracing.ts Normal file
View File

@@ -0,0 +1,22 @@
// CODING-RULES.md §09 (PGD-OBS-001):
// Este arquivo DEVE ser o primeiro import de main.ts — antes do NestJS.
// OTel NodeSDK precisa fazer monkey-patch dos módulos node:http, pg, etc.
// antes que qualquer outro código os carregue.
//
// Stub ativo:
// - Quando OTEL_EXPORTER_OTLP_ENDPOINT estiver definida, inicializa SDK real
// (a ser plugado quando @opentelemetry/sdk-node entrar no canon catalog).
// - Caso contrário, no-op silencioso (dev local).
//
// Sampling alvo (prod): parentbased_traceidratio com ARG=0.1 (10% head-based).
const otlpEndpoint = process.env['OTEL_EXPORTER_OTLP_ENDPOINT'];
if (otlpEndpoint) {
// TODO(otel): plugar @opentelemetry/sdk-node + auto-instrumentations
// quando dependência entrar no catálogo. Stub atual mantém posição correta
// do import sem instalar dependência pesada em solo-founder mode.
console.warn(
'[tracing] OTEL_EXPORTER_OTLP_ENDPOINT definido mas SDK não plugado ainda — placeholder ativo.',
);
}

View File

@@ -6,7 +6,7 @@
"types": ["node"], "types": ["node"],
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"target": "es2021", "target": "ES2023",
"moduleResolution": "node" "moduleResolution": "node"
}, },
"include": ["src/**/*.ts"], "include": ["src/**/*.ts"],

View File

@@ -250,6 +250,46 @@
4. Implementar multi-tenant BD-por-workspace via Prisma factory + cls 4. Implementar multi-tenant BD-por-workspace via Prisma factory + cls
5. Primeira tela viva: login + painel Rafael (vazio) 5. Primeira tela viva: login + painel Rafael (vazio)
### 2026-05-27 — Foundation API (Frente A) CONCLUÍDA ✅
- **10 tarefas executadas (A1-A10):** tsconfig hardening · tracing stub · Zod env · Pino+redact LGPD · main.ts hardening · RFC 9457 filter · health endpoints · CLS workspace · /api/v1/ping · build+lint+smoke
- **Estrutura `apps/api/src/`:**
- `tracing.ts` — primeiro import (PGD-OBS-001), OTel SDK ativável por env
- `main.ts` — helmet · CORS por env · compression · versionamento URI `/api/v1` · graceful shutdown · Pino logger global
- `app/config/` — EnvSchema Zod 4 com `superRefine` (fail-fast prod, defaults dev) + EnvModule global
- `app/logger/` — nestjs-pino com redact `*.cpf|*.cardNumber|*.password|authorization|cookie`, ignora `/health/*`, pretty em dev
- `app/filters/problem-details.filter.ts` — RFC 9457 `application/problem+json`, Zod → 422 com array `errors`, type URIs em `https://docs.sar.jcs.com.br/errors/*`
- `app/health/``/health/live` e `/health/ready` (skeleton, K=3 LRU pool placeholder documentado)
- `app/workspace/` — ClsModule.forRootAsync com `setup` populando requestId+workspaceId; idGenerator alinha com pino-http (mesmo UUID header+body)
- `app/ping/``GET /api/v1/ping` retornando status+service+version+workspaceId+requestId+uptime+now
- `app.module.ts` — APP_PIPE: ZodValidationPipe (nestjs-zod) · APP_FILTER: ProblemDetailsFilter
- **Dependências instaladas (root):** @nestjs/config 4.0 · @nestjs/terminus 11.1 · nestjs-pino 4.6 · pino 9.14 · pino-http 10.5 · pino-pretty 13.1 · nestjs-zod 4.3 · nestjs-cls 5.4 · helmet 8.2 · compression 1.8 · zod (catalog) · @types/express · @types/compression
- **Smoke test verde:** `GET /api/v1/ping` → 200 com workspaceId+requestId · `/health/live` + `/health/ready` → 200 (heap OK) · `/api/v1/nope` → 404 application/problem+json · CORS preflight: localhost:4200 permitido, evil.com bloqueado · helmet headers todos presentes (HSTS, X-CTO, X-Frame-Options, etc.) · `x-request-id` propagado em todas as responses
- **Hello-world boilerplate removido** (app.controller/service/specs)
- **Pendente próxima sessão:**
1. **Frente C — Zod contracts compartilhados** (`libs/shared/api-interface`): primeiro DTO real (createZodDto) consumido por API + Web
2. **Frente D — ESLint boundaries** (3 tags Nx canônicas) + Husky+gitleaks
3. **Web → API integração:** `apps/web` chamar `/api/v1/ping` via TanStack Query (validar fundação ponta-a-ponta no browser)
4. **OpenTelemetry SDK** plugar quando entrar em catálogo (stub atual mantém posição correta)
5. **Master-login + WorkspacePrismaPool** (próxima frente arquitetural pesada)
6. **Docker compose dev**: subir e validar healthcheck (`pnpm dev:up`)
### 2026-05-27 — Foundation Web (Frente B) CONCLUÍDA ✅
- **Commit:** `3a42723 feat(web): foundation com brand JCS + AntD theme + Rafael painel placeholder`
- **Tokens CSS** em `apps/web/src/styles/tokens.css` espelhando brand.md (paleta, tipografia, layout, motion, spacing, type scale)
- **Plus Jakarta Sans Variable** self-host via `@fontsource-variable/plus-jakarta-sans` (LGPD + performance)
- **AntD ConfigProvider tema JCS** em `apps/web/src/lib/theme.ts` — colorPrimary #004a99, radius 12/20, sombra canon, motion sutil
- **TanStack Query + Router** setup com defaults conservadores (no refetchOnFocus, retry 5xx, no mutation retry — Idempotency-Key cobre)
- **Layout shell:** Topbar 80px + Sidebar 260px com 9 itens cockpit Rafael (FA outline icons)
- **RafaelPainel placeholder** com copy canônica + mock data:
- "Bom dia, Rafael" + agenda do dia
- Meta de maio (R$ 47.600 / R$ 60.000 = 79%) com Progress JCS Blue
- "Pedidos no mês" (28, +18% vs abril) · "Comissão" (R$ 2.540, FLEX R$ 380)
- "Clientes esfriando" — OPENFRIOS 47 dias, etc. — vocabulário canon
- "Próxima visita" OPENFRIOS 14:30
- **Build OK:** 878KB JS (~250KB gzip) — vai code-splitar quando cockpits virarem rotas separadas
- **Dev server:** http://localhost:4200/ servindo com title, theme-color, lang pt-BR corretos
- **Pendentes próxima sessão:** Frente A (API foundation), C (Zod contracts), D (ESLint+boundaries), Docker permissions, **abrir browser e validar visualmente**
--- ---
## About This Folder ## About This Folder

View File

@@ -50,6 +50,8 @@
"@swc/helpers": "~0.5.18", "@swc/helpers": "~0.5.18",
"@testing-library/dom": "10.4.0", "@testing-library/dom": "10.4.0",
"@testing-library/react": "16.3.0", "@testing-library/react": "16.3.0",
"@types/compression": "^1.8.1",
"@types/express": "^5.0.6",
"@types/jest": "~30.0.0", "@types/jest": "~30.0.0",
"@types/node": "catalog:", "@types/node": "catalog:",
"@types/react": "^19.0.0", "@types/react": "^19.0.0",
@@ -82,13 +84,24 @@
}, },
"dependencies": { "dependencies": {
"@nestjs/common": "^11.0.0", "@nestjs/common": "^11.0.0",
"@nestjs/config": "^4.0.4",
"@nestjs/core": "^11.0.0", "@nestjs/core": "^11.0.0",
"@nestjs/platform-express": "^11.0.0", "@nestjs/platform-express": "^11.0.0",
"@nestjs/terminus": "^11.1.1",
"axios": "^1.6.0", "axios": "^1.6.0",
"compression": "^1.8.1",
"helmet": "^8.2.0",
"nestjs-cls": "^5.4.3",
"nestjs-pino": "^4.6.1",
"nestjs-zod": "^4.3.1",
"pino": "^9.14.0",
"pino-http": "^10.5.0",
"pino-pretty": "^13.1.3",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "^7.8.0", "rxjs": "^7.8.0",
"tslib": "^2.3.0" "tslib": "^2.3.0",
"zod": "catalog:"
} }
} }

448
pnpm-lock.yaml generated
View File

@@ -23,15 +23,45 @@ importers:
'@nestjs/common': '@nestjs/common':
specifier: ^11.0.0 specifier: ^11.0.0
version: 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1) version: 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/config':
specifier: ^4.0.4
version: 4.0.4(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(rxjs@7.8.1)
'@nestjs/core': '@nestjs/core':
specifier: ^11.0.0 specifier: ^11.0.0
version: 11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1) version: 11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/platform-express': '@nestjs/platform-express':
specifier: ^11.0.0 specifier: ^11.0.0
version: 11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24) version: 11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24)
'@nestjs/terminus':
specifier: ^11.1.1
version: 11.1.1(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1)
axios: axios:
specifier: ^1.6.0 specifier: ^1.6.0
version: 1.16.0 version: 1.16.0
compression:
specifier: ^1.8.1
version: 1.8.1
helmet:
specifier: ^8.2.0
version: 8.2.0
nestjs-cls:
specifier: ^5.4.3
version: 5.4.3(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1)
nestjs-pino:
specifier: ^4.6.1
version: 4.6.1(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(pino-http@10.5.0)(pino@9.14.0)(rxjs@7.8.1)
nestjs-zod:
specifier: ^4.3.1
version: 4.3.1(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24)(zod@4.4.3)
pino:
specifier: ^9.14.0
version: 9.14.0
pino-http:
specifier: ^10.5.0
version: 10.5.0
pino-pretty:
specifier: ^13.1.3
version: 13.1.3
react: react:
specifier: ^19.0.0 specifier: ^19.0.0
version: 19.2.6 version: 19.2.6
@@ -47,6 +77,9 @@ importers:
tslib: tslib:
specifier: ^2.3.0 specifier: ^2.3.0
version: 2.8.1 version: 2.8.1
zod:
specifier: 'catalog:'
version: 4.4.3
devDependencies: devDependencies:
'@eslint/js': '@eslint/js':
specifier: ^9.8.0 specifier: ^9.8.0
@@ -120,6 +153,12 @@ importers:
'@testing-library/react': '@testing-library/react':
specifier: 16.3.0 specifier: 16.3.0
version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.2.3(@types/react@19.2.15))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.2.3(@types/react@19.2.15))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@types/compression':
specifier: ^1.8.1
version: 1.8.1
'@types/express':
specifier: ^5.0.6
version: 5.0.6
'@types/jest': '@types/jest':
specifier: ~30.0.0 specifier: ~30.0.0
version: 30.0.0 version: 30.0.0
@@ -1656,6 +1695,21 @@ packages:
'@emnapi/core': ^1.7.1 '@emnapi/core': ^1.7.1
'@emnapi/runtime': ^1.7.1 '@emnapi/runtime': ^1.7.1
'@nest-zod/z@2.0.0':
resolution: {integrity: sha512-OqmJUZlpcx9ECzPYSIjaR/q/xLKrm9FkV+0FIWLEb9MVc9YeP21GmnQJBxE1dPRlLJ1kybNFBlt4D/PB8YAPkA==}
peerDependencies:
'@nestjs/common': ^10.0.0 || ^11.0.0
'@nestjs/core': ^10.0.0 || ^11.0.0
'@nestjs/swagger': ^7.4.2 || ^8.0.0 || ^11.0.0
zod: '>= 3.14.3'
peerDependenciesMeta:
'@nestjs/common':
optional: true
'@nestjs/core':
optional: true
'@nestjs/swagger':
optional: true
'@nestjs/common@11.1.24': '@nestjs/common@11.1.24':
resolution: {integrity: sha512-9zHxaDDM+oXW9As6UsP5yYB+UqczBmpeSCIFWdPEtEukMnZhxODG1BBjaUcdBB8Sc1uzojSJSJlp3yFp853t1g==} resolution: {integrity: sha512-9zHxaDDM+oXW9As6UsP5yYB+UqczBmpeSCIFWdPEtEukMnZhxODG1BBjaUcdBB8Sc1uzojSJSJlp3yFp853t1g==}
peerDependencies: peerDependencies:
@@ -1669,6 +1723,12 @@ packages:
class-validator: class-validator:
optional: true optional: true
'@nestjs/config@4.0.4':
resolution: {integrity: sha512-CJPjNitr0bAufSEnRe2N+JbnVmMmDoo6hvKCPzXgZoGwJSmp/dZPk9f/RMbuD/+Q1ZJPjwsRpq0vxna++Knwow==}
peerDependencies:
'@nestjs/common': ^10.0.0 || ^11.0.0
rxjs: ^7.1.0
'@nestjs/core@11.1.24': '@nestjs/core@11.1.24':
resolution: {integrity: sha512-K4bzT+lEdd0Hhcsw3jtk56QAW6s6skK3ViN7hIROSN0kUf4ROwWEAKopJID6yhPQxB45kDtP2wEcjzE8171J3g==} resolution: {integrity: sha512-K4bzT+lEdd0Hhcsw3jtk56QAW6s6skK3ViN7hIROSN0kUf4ROwWEAKopJID6yhPQxB45kDtP2wEcjzE8171J3g==}
engines: {node: '>= 20'} engines: {node: '>= 20'}
@@ -1702,6 +1762,54 @@ packages:
prettier: prettier:
optional: true optional: true
'@nestjs/terminus@11.1.1':
resolution: {integrity: sha512-Ssql79H+EQY/Wg108eJqN4NiNsO/tLrj+qbzOWSQUf2JE4vJQ2RG3WTqUOrYjfjWmVHD3+Ys0+azed7LSMKScw==}
peerDependencies:
'@grpc/grpc-js': '*'
'@grpc/proto-loader': '*'
'@mikro-orm/core': '*'
'@mikro-orm/nestjs': '*'
'@nestjs/axios': ^2.0.0 || ^3.0.0 || ^4.0.0
'@nestjs/common': ^10.0.0 || ^11.0.0
'@nestjs/core': ^10.0.0 || ^11.0.0
'@nestjs/microservices': ^10.0.0 || ^11.0.0
'@nestjs/mongoose': ^11.0.0
'@nestjs/sequelize': ^10.0.0 || ^11.0.0
'@nestjs/typeorm': ^10.0.0 || ^11.0.0
'@prisma/client': '*'
mongoose: '*'
reflect-metadata: 0.1.x || 0.2.x
rxjs: 7.x
sequelize: '*'
typeorm: '*'
peerDependenciesMeta:
'@grpc/grpc-js':
optional: true
'@grpc/proto-loader':
optional: true
'@mikro-orm/core':
optional: true
'@mikro-orm/nestjs':
optional: true
'@nestjs/axios':
optional: true
'@nestjs/microservices':
optional: true
'@nestjs/mongoose':
optional: true
'@nestjs/sequelize':
optional: true
'@nestjs/typeorm':
optional: true
'@prisma/client':
optional: true
mongoose:
optional: true
sequelize:
optional: true
typeorm:
optional: true
'@nestjs/testing@11.1.24': '@nestjs/testing@11.1.24':
resolution: {integrity: sha512-+4M4UAnhtprBQN0J2uI6IP0wDqhy9aH8XCMu5SO8oCi0oB04YXA4a4PAEkxmsPn7gHW4dj1u4GFteNQOWgvTJw==} resolution: {integrity: sha512-+4M4UAnhtprBQN0J2uI6IP0wDqhy9aH8XCMu5SO8oCi0oB04YXA4a4PAEkxmsPn7gHW4dj1u4GFteNQOWgvTJw==}
peerDependencies: peerDependencies:
@@ -2131,6 +2239,9 @@ packages:
peerDependencies: peerDependencies:
typescript: '>3.0.0' typescript: '>3.0.0'
'@pinojs/redact@0.4.0':
resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
'@pkgjs/parseargs@0.11.0': '@pkgjs/parseargs@0.11.0':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'} engines: {node: '>=14'}
@@ -3137,6 +3248,9 @@ packages:
'@types/chai@5.2.3': '@types/chai@5.2.3':
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
'@types/compression@1.8.1':
resolution: {integrity: sha512-kCFuWS0ebDbmxs0AXYn6e2r2nrGAb5KwQhknjSPSPgJcGd8+HVSILlUyFhGqML2gk39HcG7D1ydW9/qpYkN00Q==}
'@types/connect-history-api-fallback@1.5.4': '@types/connect-history-api-fallback@1.5.4':
resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==}
@@ -3158,9 +3272,15 @@ packages:
'@types/express-serve-static-core@4.19.8': '@types/express-serve-static-core@4.19.8':
resolution: {integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==} resolution: {integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==}
'@types/express-serve-static-core@5.1.1':
resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==}
'@types/express@4.17.25': '@types/express@4.17.25':
resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==}
'@types/express@5.0.6':
resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==}
'@types/http-cache-semantics@4.2.0': '@types/http-cache-semantics@4.2.0':
resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==}
@@ -3232,6 +3352,9 @@ packages:
'@types/serve-static@1.15.10': '@types/serve-static@1.15.10':
resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==}
'@types/serve-static@2.2.0':
resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==}
'@types/sockjs@0.3.36': '@types/sockjs@0.3.36':
resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==}
@@ -3687,6 +3810,9 @@ packages:
ajv@8.20.0: ajv@8.20.0:
resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==}
ansi-align@3.0.1:
resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==}
ansi-colors@4.1.3: ansi-colors@4.1.3:
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -3811,6 +3937,10 @@ packages:
asynckit@0.4.0: asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
atomic-sleep@1.0.0:
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
engines: {node: '>=8.0.0'}
autoprefixer@10.5.0: autoprefixer@10.5.0:
resolution: {integrity: sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==} resolution: {integrity: sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==}
engines: {node: ^10 || ^12 || >=14} engines: {node: ^10 || ^12 || >=14}
@@ -3989,6 +4119,10 @@ packages:
boolbase@1.0.0: boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
boxen@5.1.2:
resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==}
engines: {node: '>=10'}
brace-expansion@1.1.15: brace-expansion@1.1.15:
resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==} resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==}
@@ -4098,6 +4232,10 @@ packages:
resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==} resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==}
engines: {pnpm: '>=8'} engines: {pnpm: '>=8'}
check-disk-space@3.4.0:
resolution: {integrity: sha512-drVkSqfwA+TvuEhFipiR1OC9boEGZL5RrWvVsOthdcvQNXyCCuKkEiTOTXZ7qxSf/GLwq4GvzfrQD/Wz325hgw==}
engines: {node: '>=16'}
chokidar@3.6.0: chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'} engines: {node: '>= 8.10.0'}
@@ -4121,6 +4259,10 @@ packages:
cjs-module-lexer@2.2.0: cjs-module-lexer@2.2.0:
resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==}
cli-boxes@2.2.1:
resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==}
engines: {node: '>=6'}
cli-cursor@3.1.0: cli-cursor@3.1.0:
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -4450,6 +4592,9 @@ packages:
resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
dateformat@4.6.3:
resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==}
dayjs@1.11.21: dayjs@1.11.21:
resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==}
@@ -4616,6 +4761,10 @@ packages:
resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
dotenv@17.4.1:
resolution: {integrity: sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==}
engines: {node: '>=12'}
dunder-proto@1.0.1: dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@@ -4943,6 +5092,9 @@ packages:
resolution: {integrity: sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==} resolution: {integrity: sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==}
engines: {node: '>=4'} engines: {node: '>=4'}
fast-copy@4.0.3:
resolution: {integrity: sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw==}
fast-deep-equal@3.1.3: fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@@ -5305,6 +5457,13 @@ packages:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
hasBin: true hasBin: true
helmet@8.2.0:
resolution: {integrity: sha512-DRgTIUgnWcJ62KyarxxziuqYxKGnR6Rgg19BlbucN/dpmJbl1XOit6qvoOX0ZT+HhWe5OUVhU/a1zpGyc1xA0Q==}
engines: {node: '>=18.0.0'}
help-me@5.0.0:
resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==}
homedir-polyfill@1.0.3: homedir-polyfill@1.0.3:
resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -5976,6 +6135,10 @@ packages:
resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
hasBin: true hasBin: true
joycon@3.1.1:
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
engines: {node: '>=10'}
js-tokens@10.0.0: js-tokens@10.0.0:
resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==}
@@ -6234,6 +6397,9 @@ packages:
lodash.uniq@4.5.0: lodash.uniq@4.5.0:
resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==}
lodash@4.18.1:
resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
log-symbols@4.1.0: log-symbols@4.1.0:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -6467,6 +6633,39 @@ packages:
neo-async@2.6.2: neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
nestjs-cls@5.4.3:
resolution: {integrity: sha512-yHEHyVoe6rsvj3XRPFonBKPXPjDREyHfKZ9PTStSLJTZAV3wey1Q89TquSj6QciqXB5387GiHv9DG+ja6iAUHw==}
engines: {node: '>=18'}
peerDependencies:
'@nestjs/common': '>= 10 < 12'
'@nestjs/core': '>= 10 < 12'
reflect-metadata: '*'
rxjs: '>= 7'
nestjs-pino@4.6.1:
resolution: {integrity: sha512-nuARXa0xpdJ1lY2+fgycIQr6H3g0VgqAWNK3xMYjOFcj2DoPETNXj0lV3Y86nRuI7BUfQp5PGiVoZvT4dTWbpQ==}
engines: {node: '>= 14'}
peerDependencies:
'@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
pino: ^7.5.0 || ^8.0.0 || ^9.0.0 || ^10.0.0
pino-http: ^6.4.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
rxjs: ^7.1.0
nestjs-zod@4.3.1:
resolution: {integrity: sha512-gl10NOf/AhWt4HLcnMI1J0WUlBCKyteJBftD6SwNyX71/vzAorr5MJQWiDJoPPkou9QL2CRHHBtyjr55o7++Xw==}
peerDependencies:
'@nestjs/common': ^10.0.0 || ^11.0.0
'@nestjs/core': ^10.0.0 || ^11.0.0
'@nestjs/swagger': ^7.4.2 || ^8.0.0 || ^11.0.0
zod: '>= 3.14.3'
peerDependenciesMeta:
'@nestjs/common':
optional: true
'@nestjs/core':
optional: true
'@nestjs/swagger':
optional: true
no-case@3.0.4: no-case@3.0.4:
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
@@ -6576,6 +6775,10 @@ packages:
obug@2.1.1: obug@2.1.1:
resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
on-exit-leak-free@2.1.2:
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
engines: {node: '>=14.0.0'}
on-finished@2.4.1: on-finished@2.4.1:
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
@@ -6765,6 +6968,26 @@ packages:
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
engines: {node: '>=6'} engines: {node: '>=6'}
pino-abstract-transport@2.0.0:
resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==}
pino-abstract-transport@3.0.0:
resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==}
pino-http@10.5.0:
resolution: {integrity: sha512-hD91XjgaKkSsdn8P7LaebrNzhGTdB086W3pyPihX0EzGPjq5uBJBXo4N5guqNaK6mUjg9aubMF7wDViYek9dRA==}
pino-pretty@13.1.3:
resolution: {integrity: sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==}
hasBin: true
pino-std-serializers@7.1.0:
resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==}
pino@9.14.0:
resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==}
hasBin: true
pirates@4.0.7: pirates@4.0.7:
resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@@ -7055,6 +7278,9 @@ packages:
process-nextick-args@2.0.1: process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
process-warning@5.0.0:
resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
prop-types@15.8.1: prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
@@ -7072,6 +7298,9 @@ packages:
psl@1.15.0: psl@1.15.0:
resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
pump@3.0.4:
resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==}
punycode@2.3.1: punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -7093,6 +7322,9 @@ packages:
querystringify@2.2.0: querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
quick-format-unescaped@4.0.4:
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
quick-lru@5.1.1: quick-lru@5.1.1:
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -7164,6 +7396,10 @@ packages:
resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
engines: {node: '>= 20.19.0'} engines: {node: '>= 20.19.0'}
real-require@0.2.0:
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
engines: {node: '>= 12.13.0'}
rechoir@0.8.0: rechoir@0.8.0:
resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==}
engines: {node: '>= 10.13.0'} engines: {node: '>= 10.13.0'}
@@ -7308,6 +7544,10 @@ packages:
resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
safe-stable-stringify@2.5.0:
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
engines: {node: '>=10'}
safer-buffer@2.1.2: safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
@@ -7483,6 +7723,9 @@ packages:
secure-compare@3.0.1: secure-compare@3.0.1:
resolution: {integrity: sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==} resolution: {integrity: sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==}
secure-json-parse@4.1.0:
resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==}
seek-bzip@2.0.0: seek-bzip@2.0.0:
resolution: {integrity: sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==} resolution: {integrity: sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==}
hasBin: true hasBin: true
@@ -7637,6 +7880,9 @@ packages:
sockjs@0.3.24: sockjs@0.3.24:
resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==}
sonic-boom@4.2.1:
resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==}
sort-keys-length@1.0.1: sort-keys-length@1.0.1:
resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==} resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -7682,6 +7928,10 @@ packages:
resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
split2@4.2.0:
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
engines: {node: '>= 10.x'}
sprintf-js@1.0.3: sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
@@ -7796,6 +8046,10 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'} engines: {node: '>=8'}
strip-json-comments@5.0.3:
resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==}
engines: {node: '>=14.16'}
strtok3@10.3.5: strtok3@10.3.5:
resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==}
engines: {node: '>=18'} engines: {node: '>=18'}
@@ -7942,6 +8196,9 @@ packages:
peerDependencies: peerDependencies:
tslib: ^2 tslib: ^2
thread-stream@3.1.0:
resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==}
throttle-debounce@5.0.2: throttle-debounce@5.0.2:
resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==}
engines: {node: '>=12.22'} engines: {node: '>=12.22'}
@@ -8504,6 +8761,10 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
hasBin: true hasBin: true
widest-line@3.1.0:
resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==}
engines: {node: '>=8'}
wildcard@2.0.1: wildcard@2.0.1:
resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==}
@@ -10434,6 +10695,13 @@ snapshots:
'@tybys/wasm-util': 0.10.2 '@tybys/wasm-util': 0.10.2
optional: true optional: true
'@nest-zod/z@2.0.0(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24)(zod@4.4.3)':
dependencies:
zod: 4.4.3
optionalDependencies:
'@nestjs/common': 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/core': 11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1)': '@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1)':
dependencies: dependencies:
file-type: 21.3.4 file-type: 21.3.4
@@ -10446,6 +10714,14 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@nestjs/config@4.0.4(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(rxjs@7.8.1)':
dependencies:
'@nestjs/common': 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1)
dotenv: 17.4.1
dotenv-expand: 12.0.3
lodash: 4.18.1
rxjs: 7.8.1
'@nestjs/core@11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1)': '@nestjs/core@11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1)':
dependencies: dependencies:
'@nestjs/common': 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1) '@nestjs/common': 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1)
@@ -10485,6 +10761,15 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- chokidar - chokidar
'@nestjs/terminus@11.1.1(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1)':
dependencies:
'@nestjs/common': 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/core': 11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1)
boxen: 5.1.2
check-disk-space: 3.4.0
reflect-metadata: 0.1.14
rxjs: 7.8.1
'@nestjs/testing@11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24)(@nestjs/platform-express@11.1.24)': '@nestjs/testing@11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24)(@nestjs/platform-express@11.1.24)':
dependencies: dependencies:
'@nestjs/common': 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1) '@nestjs/common': 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1)
@@ -11250,6 +11535,8 @@ snapshots:
esquery: 1.7.0 esquery: 1.7.0
typescript: 5.9.3 typescript: 5.9.3
'@pinojs/redact@0.4.0': {}
'@pkgjs/parseargs@0.11.0': '@pkgjs/parseargs@0.11.0':
optional: true optional: true
@@ -12191,6 +12478,11 @@ snapshots:
'@types/deep-eql': 4.0.2 '@types/deep-eql': 4.0.2
assertion-error: 2.0.1 assertion-error: 2.0.1
'@types/compression@1.8.1':
dependencies:
'@types/express': 4.17.25
'@types/node': 24.12.4
'@types/connect-history-api-fallback@1.5.4': '@types/connect-history-api-fallback@1.5.4':
dependencies: dependencies:
'@types/express-serve-static-core': 4.19.8 '@types/express-serve-static-core': 4.19.8
@@ -12217,6 +12509,13 @@ snapshots:
'@types/range-parser': 1.2.7 '@types/range-parser': 1.2.7
'@types/send': 1.2.1 '@types/send': 1.2.1
'@types/express-serve-static-core@5.1.1':
dependencies:
'@types/node': 24.12.4
'@types/qs': 6.15.1
'@types/range-parser': 1.2.7
'@types/send': 1.2.1
'@types/express@4.17.25': '@types/express@4.17.25':
dependencies: dependencies:
'@types/body-parser': 1.19.6 '@types/body-parser': 1.19.6
@@ -12224,6 +12523,12 @@ snapshots:
'@types/qs': 6.15.1 '@types/qs': 6.15.1
'@types/serve-static': 1.15.10 '@types/serve-static': 1.15.10
'@types/express@5.0.6':
dependencies:
'@types/body-parser': 1.19.6
'@types/express-serve-static-core': 5.1.1
'@types/serve-static': 2.2.0
'@types/http-cache-semantics@4.2.0': {} '@types/http-cache-semantics@4.2.0': {}
'@types/http-errors@2.0.5': {} '@types/http-errors@2.0.5': {}
@@ -12296,6 +12601,11 @@ snapshots:
'@types/node': 24.12.4 '@types/node': 24.12.4
'@types/send': 0.17.6 '@types/send': 0.17.6
'@types/serve-static@2.2.0':
dependencies:
'@types/http-errors': 2.0.5
'@types/node': 24.12.4
'@types/sockjs@0.3.36': '@types/sockjs@0.3.36':
dependencies: dependencies:
'@types/node': 24.12.4 '@types/node': 24.12.4
@@ -12815,6 +13125,10 @@ snapshots:
json-schema-traverse: 1.0.0 json-schema-traverse: 1.0.0
require-from-string: 2.0.2 require-from-string: 2.0.2
ansi-align@3.0.1:
dependencies:
string-width: 4.2.3
ansi-colors@4.1.3: {} ansi-colors@4.1.3: {}
ansi-escapes@4.3.2: ansi-escapes@4.3.2:
@@ -13005,6 +13319,8 @@ snapshots:
asynckit@0.4.0: {} asynckit@0.4.0: {}
atomic-sleep@1.0.0: {}
autoprefixer@10.5.0(postcss@8.5.15): autoprefixer@10.5.0(postcss@8.5.15):
dependencies: dependencies:
browserslist: 4.28.2 browserslist: 4.28.2
@@ -13243,6 +13559,17 @@ snapshots:
boolbase@1.0.0: {} boolbase@1.0.0: {}
boxen@5.1.2:
dependencies:
ansi-align: 3.0.1
camelcase: 6.3.0
chalk: 4.1.2
cli-boxes: 2.2.1
string-width: 4.2.3
type-fest: 0.20.2
widest-line: 3.1.0
wrap-ansi: 7.0.0
brace-expansion@1.1.15: brace-expansion@1.1.15:
dependencies: dependencies:
balanced-match: 1.0.2 balanced-match: 1.0.2
@@ -13356,6 +13683,8 @@ snapshots:
dependencies: dependencies:
'@kurkle/color': 0.3.4 '@kurkle/color': 0.3.4
check-disk-space@3.4.0: {}
chokidar@3.6.0: chokidar@3.6.0:
dependencies: dependencies:
anymatch: 3.1.3 anymatch: 3.1.3
@@ -13382,6 +13711,8 @@ snapshots:
cjs-module-lexer@2.2.0: {} cjs-module-lexer@2.2.0: {}
cli-boxes@2.2.1: {}
cli-cursor@3.1.0: cli-cursor@3.1.0:
dependencies: dependencies:
restore-cursor: 3.1.0 restore-cursor: 3.1.0
@@ -13708,6 +14039,8 @@ snapshots:
es-errors: 1.3.0 es-errors: 1.3.0
is-data-view: 1.0.2 is-data-view: 1.0.2
dateformat@4.6.3: {}
dayjs@1.11.21: {} dayjs@1.11.21: {}
debug@2.6.9: debug@2.6.9:
@@ -13832,6 +14165,8 @@ snapshots:
dotenv@16.4.7: {} dotenv@16.4.7: {}
dotenv@17.4.1: {}
dunder-proto@1.0.1: dunder-proto@1.0.1:
dependencies: dependencies:
call-bind-apply-helpers: 1.0.2 call-bind-apply-helpers: 1.0.2
@@ -14351,6 +14686,8 @@ snapshots:
ext-list: 2.2.2 ext-list: 2.2.2
sort-keys-length: 1.0.1 sort-keys-length: 1.0.1
fast-copy@4.0.3: {}
fast-deep-equal@3.1.3: {} fast-deep-equal@3.1.3: {}
fast-fifo@1.3.2: {} fast-fifo@1.3.2: {}
@@ -14736,6 +15073,10 @@ snapshots:
he@1.2.0: {} he@1.2.0: {}
helmet@8.2.0: {}
help-me@5.0.0: {}
homedir-polyfill@1.0.3: homedir-polyfill@1.0.3:
dependencies: dependencies:
parse-passwd: 1.0.0 parse-passwd: 1.0.0
@@ -15759,6 +16100,8 @@ snapshots:
jiti@2.7.0: {} jiti@2.7.0: {}
joycon@3.1.1: {}
js-tokens@10.0.0: {} js-tokens@10.0.0: {}
js-tokens@4.0.0: {} js-tokens@4.0.0: {}
@@ -15997,6 +16340,8 @@ snapshots:
lodash.uniq@4.5.0: {} lodash.uniq@4.5.0: {}
lodash@4.18.1: {}
log-symbols@4.1.0: log-symbols@4.1.0:
dependencies: dependencies:
chalk: 4.1.2 chalk: 4.1.2
@@ -16199,6 +16544,29 @@ snapshots:
neo-async@2.6.2: {} neo-async@2.6.2: {}
nestjs-cls@5.4.3(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1):
dependencies:
'@nestjs/common': 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/core': 11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1)
reflect-metadata: 0.1.14
rxjs: 7.8.1
nestjs-pino@4.6.1(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(pino-http@10.5.0)(pino@9.14.0)(rxjs@7.8.1):
dependencies:
'@nestjs/common': 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1)
pino: 9.14.0
pino-http: 10.5.0
rxjs: 7.8.1
nestjs-zod@4.3.1(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24)(zod@4.4.3):
dependencies:
'@nest-zod/z': 2.0.0(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@11.1.24)(zod@4.4.3)
deepmerge: 4.3.1
zod: 4.4.3
optionalDependencies:
'@nestjs/common': 11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/core': 11.1.24(@nestjs/common@11.1.24(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@11.1.24)(reflect-metadata@0.1.14)(rxjs@7.8.1)
no-case@3.0.4: no-case@3.0.4:
dependencies: dependencies:
lower-case: 2.0.2 lower-case: 2.0.2
@@ -16429,6 +16797,8 @@ snapshots:
obug@2.1.1: {} obug@2.1.1: {}
on-exit-leak-free@2.1.2: {}
on-finished@2.4.1: on-finished@2.4.1:
dependencies: dependencies:
ee-first: 1.1.1 ee-first: 1.1.1
@@ -16631,6 +17001,53 @@ snapshots:
pify@4.0.1: pify@4.0.1:
optional: true optional: true
pino-abstract-transport@2.0.0:
dependencies:
split2: 4.2.0
pino-abstract-transport@3.0.0:
dependencies:
split2: 4.2.0
pino-http@10.5.0:
dependencies:
get-caller-file: 2.0.5
pino: 9.14.0
pino-std-serializers: 7.1.0
process-warning: 5.0.0
pino-pretty@13.1.3:
dependencies:
colorette: 2.0.20
dateformat: 4.6.3
fast-copy: 4.0.3
fast-safe-stringify: 2.1.1
help-me: 5.0.0
joycon: 3.1.1
minimist: 1.2.8
on-exit-leak-free: 2.1.2
pino-abstract-transport: 3.0.0
pump: 3.0.4
secure-json-parse: 4.1.0
sonic-boom: 4.2.1
strip-json-comments: 5.0.3
pino-std-serializers@7.1.0: {}
pino@9.14.0:
dependencies:
'@pinojs/redact': 0.4.0
atomic-sleep: 1.0.0
on-exit-leak-free: 2.1.2
pino-abstract-transport: 2.0.0
pino-std-serializers: 7.1.0
process-warning: 5.0.0
quick-format-unescaped: 4.0.4
real-require: 0.2.0
safe-stable-stringify: 2.5.0
sonic-boom: 4.2.1
thread-stream: 3.1.0
pirates@4.0.7: {} pirates@4.0.7: {}
piscina@4.9.2: piscina@4.9.2:
@@ -16918,6 +17335,8 @@ snapshots:
process-nextick-args@2.0.1: {} process-nextick-args@2.0.1: {}
process-warning@5.0.0: {}
prop-types@15.8.1: prop-types@15.8.1:
dependencies: dependencies:
loose-envify: 1.4.0 loose-envify: 1.4.0
@@ -16938,6 +17357,11 @@ snapshots:
dependencies: dependencies:
punycode: 2.3.1 punycode: 2.3.1
pump@3.0.4:
dependencies:
end-of-stream: 1.4.5
once: 1.4.0
punycode@2.3.1: {} punycode@2.3.1: {}
pure-rand@7.0.1: {} pure-rand@7.0.1: {}
@@ -16954,6 +17378,8 @@ snapshots:
querystringify@2.2.0: {} querystringify@2.2.0: {}
quick-format-unescaped@4.0.4: {}
quick-lru@5.1.1: {} quick-lru@5.1.1: {}
range-parser@1.2.1: {} range-parser@1.2.1: {}
@@ -17024,6 +17450,8 @@ snapshots:
readdirp@5.0.0: {} readdirp@5.0.0: {}
real-require@0.2.0: {}
rechoir@0.8.0: rechoir@0.8.0:
dependencies: dependencies:
resolve: 1.22.12 resolve: 1.22.12
@@ -17232,6 +17660,8 @@ snapshots:
es-errors: 1.3.0 es-errors: 1.3.0
is-regex: 1.2.1 is-regex: 1.2.1
safe-stable-stringify@2.5.0: {}
safer-buffer@2.1.2: {} safer-buffer@2.1.2: {}
sass-embedded-all-unknown@1.100.0: sass-embedded-all-unknown@1.100.0:
@@ -17372,6 +17802,8 @@ snapshots:
secure-compare@3.0.1: {} secure-compare@3.0.1: {}
secure-json-parse@4.1.0: {}
seek-bzip@2.0.0: seek-bzip@2.0.0:
dependencies: dependencies:
commander: 6.2.1 commander: 6.2.1
@@ -17565,6 +17997,10 @@ snapshots:
uuid: 8.3.2 uuid: 8.3.2
websocket-driver: 0.7.4 websocket-driver: 0.7.4
sonic-boom@4.2.1:
dependencies:
atomic-sleep: 1.0.0
sort-keys-length@1.0.1: sort-keys-length@1.0.1:
dependencies: dependencies:
sort-keys: 1.1.2 sort-keys: 1.1.2
@@ -17623,6 +18059,8 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
split2@4.2.0: {}
sprintf-js@1.0.3: {} sprintf-js@1.0.3: {}
stack-utils@2.0.6: stack-utils@2.0.6:
@@ -17757,6 +18195,8 @@ snapshots:
strip-json-comments@3.1.1: {} strip-json-comments@3.1.1: {}
strip-json-comments@5.0.3: {}
strtok3@10.3.5: strtok3@10.3.5:
dependencies: dependencies:
'@tokenizer/token': 0.3.0 '@tokenizer/token': 0.3.0
@@ -17887,6 +18327,10 @@ snapshots:
dependencies: dependencies:
tslib: 2.8.1 tslib: 2.8.1
thread-stream@3.1.0:
dependencies:
real-require: 0.2.0
throttle-debounce@5.0.2: {} throttle-debounce@5.0.2: {}
through@2.3.8: {} through@2.3.8: {}
@@ -18494,6 +18938,10 @@ snapshots:
siginfo: 2.0.0 siginfo: 2.0.0
stackback: 0.0.2 stackback: 0.0.2
widest-line@3.1.0:
dependencies:
string-width: 4.2.3
wildcard@2.0.1: {} wildcard@2.0.1: {}
word-wrap@1.2.5: {} word-wrap@1.2.5: {}