diff --git a/apps/edr-freight-api/src/app.module.ts b/apps/edr-freight-api/src/app.module.ts index 08c9e20bb..75826364c 100644 --- a/apps/edr-freight-api/src/app.module.ts +++ b/apps/edr-freight-api/src/app.module.ts @@ -38,6 +38,7 @@ import { import { EdrOrgSeeder } from "./seed/edr-org.seeder"; import { DemoUsersSeeder } from "./seed/demo-users.seeder"; import { FreightStaffUsersSeeder } from "./seed/freight-staff-users.seeder"; +import { PaymentModule } from "./modules/payment/payment.module"; import { DemoBookingsSeeder } from "./seed/demo-bookings.seeder"; import { PricingDataSeeder } from "./seed/pricing-data.seeder"; import { FileUploadSettingsSeeder } from "./seed/file-upload-settings.seeder"; @@ -92,6 +93,7 @@ import { CargoesModule } from './modules/cargoes/cargoes.module'; BackofficeModule, DemoPermissionsModule, FreightAuthModule, + PaymentModule, //New Modules TrainsModule, WagonsModule, diff --git a/apps/edr-freight-api/src/common/freight-permission.util.ts b/apps/edr-freight-api/src/common/freight-permission.util.ts index d6e258654..69596c21d 100644 --- a/apps/edr-freight-api/src/common/freight-permission.util.ts +++ b/apps/edr-freight-api/src/common/freight-permission.util.ts @@ -4,6 +4,7 @@ import type { TCurrentUser } from '@tria-plc/api-common/modules/auth/types/curre import { FREIGHT_PERMS } from '../seed/freight-permissions.registry'; const SUPER_ADMIN_ROLE = 'super_admin'; +const ORGANIZATION_ADMIN_ROLE = 'organization_admin'; type PermissionLike = { key?: string }; type MeLikeUser = { @@ -25,6 +26,15 @@ export function isSuperAdmin(user: MeLikeUser | null | undefined): boolean { return user.roles.some((r) => r.key === SUPER_ADMIN_ROLE); } +export function isOrganizationAdmin(user: MeLikeUser | null | undefined): boolean { + if (!user?.roles?.length) return false; + return user.roles.some((r) => r.key === ORGANIZATION_ADMIN_ROLE); +} + +export function isFreightApprovalAdmin(user: MeLikeUser | null | undefined): boolean { + return isSuperAdmin(user) || isOrganizationAdmin(user); +} + /** Flat permission keys from JWT / session user (roles + position permissions). */ export function collectPermissionKeys(user: MeLikeUser | null | undefined): string[] { if (!user) return []; @@ -90,7 +100,7 @@ export function assertCanApproveBookingStep( user: TCurrentUser | MeLikeUser | null | undefined, requiredRole: string, ): void { - if (isSuperAdmin(user)) return; + if (isFreightApprovalAdmin(user)) return; const perm = APPROVE_ROLE_PERMISSION[requiredRole]; if (!perm) { throw new ForbiddenException(`Unknown approval role: ${requiredRole}`); diff --git a/apps/edr-freight-api/src/migrations/1749800000000-AddShippingLinesCodeUniqueIndex.ts b/apps/edr-freight-api/src/migrations/1749800000000-AddShippingLinesCodeUniqueIndex.ts new file mode 100644 index 000000000..374fea724 --- /dev/null +++ b/apps/edr-freight-api/src/migrations/1749800000000-AddShippingLinesCodeUniqueIndex.ts @@ -0,0 +1,28 @@ +import { MigrationInterface, QueryRunner, TableIndex } from 'typeorm'; + +/** + * shipping_lines was created without a unique index on code; seeder upserts require it. + */ +export class AddShippingLinesCodeUniqueIndex1749800000000 implements MigrationInterface { + name = 'AddShippingLinesCodeUniqueIndex1749800000000'; + + public async up(queryRunner: QueryRunner): Promise { + const existing = await queryRunner.query( + `SELECT 1 FROM pg_indexes WHERE schemaname = 'freight' AND tablename = 'shipping_lines' AND indexdef ILIKE '%UNIQUE%code%' LIMIT 1`, + ); + if (existing.length === 0) { + await queryRunner.createIndex( + 'freight.shipping_lines', + new TableIndex({ + name: 'UQ_shipping_lines_code', + columnNames: ['code'], + isUnique: true, + }), + ); + } + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropIndex('freight.shipping_lines', 'UQ_shipping_lines_code'); + } +} diff --git a/apps/edr-freight-api/src/migrations/1749900000000-CreateFileUploadSettingsTables.ts b/apps/edr-freight-api/src/migrations/1749900000000-CreateFileUploadSettingsTables.ts new file mode 100644 index 000000000..cbbf914d4 --- /dev/null +++ b/apps/edr-freight-api/src/migrations/1749900000000-CreateFileUploadSettingsTables.ts @@ -0,0 +1,63 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +/** + * file_upload_settings / file_upload_fields entities had no migration; seeder requires both tables. + */ +export class CreateFileUploadSettingsTables1749900000000 implements MigrationInterface { + name = 'CreateFileUploadSettingsTables1749900000000'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + CREATE TABLE IF NOT EXISTS freight.file_upload_settings ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + code VARCHAR(128) NOT NULL, + label VARCHAR(256) NOT NULL, + description TEXT, + entity VARCHAR(32) NOT NULL DEFAULT 'other', + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), + deleted_at TIMESTAMPTZ + ); + `); + + await queryRunner.query(` + CREATE UNIQUE INDEX IF NOT EXISTS "UQ_file_upload_settings_code" + ON freight.file_upload_settings (code); + `); + + await queryRunner.query(` + CREATE TABLE IF NOT EXISTS freight.file_upload_fields ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + setting_id UUID NOT NULL, + file_key VARCHAR(128) NOT NULL, + file_label VARCHAR(256) NOT NULL, + help_text TEXT, + is_required BOOLEAN NOT NULL DEFAULT false, + is_multiple BOOLEAN NOT NULL DEFAULT false, + max_files INTEGER NOT NULL DEFAULT 1, + allowed_extensions TEXT[] NOT NULL DEFAULT '{}'::text[], + max_size_mb INTEGER NOT NULL DEFAULT 10, + display_order INTEGER NOT NULL DEFAULT 0, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), + deleted_at TIMESTAMPTZ, + CONSTRAINT "CHK_file_upload_fields_max_files" CHECK (max_files > 0), + CONSTRAINT "CHK_file_upload_fields_max_size_mb" CHECK (max_size_mb > 0), + CONSTRAINT "FK_file_upload_fields_setting" + FOREIGN KEY (setting_id) + REFERENCES freight.file_upload_settings(id) + ON DELETE CASCADE + ); + `); + + await queryRunner.query(` + CREATE UNIQUE INDEX IF NOT EXISTS "UQ_file_upload_fields_setting_file_key" + ON freight.file_upload_fields (setting_id, file_key); + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS freight.file_upload_fields CASCADE`); + await queryRunner.query(`DROP TABLE IF EXISTS freight.file_upload_settings CASCADE`); + } +} diff --git a/apps/edr-freight-api/src/migrations/1750000000000-AddTrainExtendedColumns.ts b/apps/edr-freight-api/src/migrations/1750000000000-AddTrainExtendedColumns.ts new file mode 100644 index 000000000..b249bd198 --- /dev/null +++ b/apps/edr-freight-api/src/migrations/1750000000000-AddTrainExtendedColumns.ts @@ -0,0 +1,45 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +/** + * Train entity gained extended fields; baseline trains table only had code/capacity/status/notes. + */ +export class AddTrainExtendedColumns1750000000000 implements MigrationInterface { + name = 'AddTrainExtendedColumns1750000000000'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE freight.trains + ADD COLUMN IF NOT EXISTS train_number VARCHAR(20), + ADD COLUMN IF NOT EXISTS train_name VARCHAR(100), + ADD COLUMN IF NOT EXISTS route_id UUID, + ADD COLUMN IF NOT EXISTS origin_station_id UUID, + ADD COLUMN IF NOT EXISTS destination_station_id UUID, + ADD COLUMN IF NOT EXISTS departure_time TIMESTAMPTZ, + ADD COLUMN IF NOT EXISTS arrival_time TIMESTAMPTZ, + ADD COLUMN IF NOT EXISTS locomotive_number VARCHAR(50), + ADD COLUMN IF NOT EXISTS remarks TEXT; + `); + + await queryRunner.query(` + CREATE UNIQUE INDEX IF NOT EXISTS "UQ_trains_train_number" + ON freight.trains (train_number) + WHERE train_number IS NOT NULL; + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX IF EXISTS freight."UQ_trains_train_number"`); + await queryRunner.query(` + ALTER TABLE freight.trains + DROP COLUMN IF EXISTS remarks, + DROP COLUMN IF EXISTS locomotive_number, + DROP COLUMN IF EXISTS arrival_time, + DROP COLUMN IF EXISTS departure_time, + DROP COLUMN IF EXISTS destination_station_id, + DROP COLUMN IF EXISTS origin_station_id, + DROP COLUMN IF EXISTS route_id, + DROP COLUMN IF EXISTS train_name, + DROP COLUMN IF EXISTS train_number; + `); + } +} diff --git a/apps/edr-freight-api/src/migrations/1780639311366-CreatePaymentTable.ts b/apps/edr-freight-api/src/migrations/1780639311366-CreatePaymentTable.ts new file mode 100644 index 000000000..cbb60d5d4 --- /dev/null +++ b/apps/edr-freight-api/src/migrations/1780639311366-CreatePaymentTable.ts @@ -0,0 +1,96 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class CreatePaymentTable1780639311366 implements MigrationInterface { + name = "CreatePaymentTable1780639311366"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + CREATE TYPE freight.payments_type_enum AS ENUM ('booking'); + `); + + await queryRunner.query(` + CREATE TYPE freight.payments_method_enum AS ENUM ('telebirr', 'cbe-birr', 'ebirr'); + `); + + await queryRunner.query(` + CREATE TYPE freight.payments_currency_enum AS ENUM ('ETB', 'USD'); + `); + + await queryRunner.query(` + CREATE TYPE freight.payments_status_enum AS ENUM ( + 'action-required', + 'processing', + 'success', + 'failed', + 'canceled', + 'refunded' + ); + `); + + await queryRunner.query(` + CREATE TABLE freight.payments ( + id uuid NOT NULL DEFAULT uuid_generate_v4(), + + ref_id varchar(255) NOT NULL, + + type freight.payments_type_enum NOT NULL, + + method freight.payments_method_enum NOT NULL, + + currency freight.payments_currency_enum NOT NULL, + + amount numeric NOT NULL, + + raw_initiation jsonb NOT NULL DEFAULT '{}'::jsonb, + + client_action json, + + merchant_order_id varchar(255) NOT NULL, + + transaction_id varchar(255), + + status freight.payments_status_enum NOT NULL DEFAULT 'action-required', + + paid_at date, + + refunded_at date, + + expires_at date, + + failer_code varchar(30), + + failer_message varchar(255), + + created_at TIMESTAMP NOT NULL DEFAULT now(), + + CONSTRAINT PK_payments PRIMARY KEY (id), + + CONSTRAINT UQ_payments_merchant_order_id UNIQUE (merchant_order_id), + + CONSTRAINT UQ_payments_transaction_id UNIQUE (transaction_id) + ); + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + DROP TABLE IF EXISTS freight.payments; + `); + + await queryRunner.query(` + DROP TYPE IF EXISTS freight.payments_status_enum; + `); + + await queryRunner.query(` + DROP TYPE IF EXISTS freight.payments_currency_enum; + `); + + await queryRunner.query(` + DROP TYPE IF EXISTS freight.payments_method_enum; + `); + + await queryRunner.query(` + DROP TYPE IF EXISTS freight.payments_type_enum; + `); + } +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/migrations/1780639978834-AlterClientActionToJsonb.ts b/apps/edr-freight-api/src/migrations/1780639978834-AlterClientActionToJsonb.ts new file mode 100644 index 000000000..723331ab3 --- /dev/null +++ b/apps/edr-freight-api/src/migrations/1780639978834-AlterClientActionToJsonb.ts @@ -0,0 +1,28 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AlterClientActionToJsonb1780639978834 implements MigrationInterface { + name = "AlterClientActionToJsonb1780639978834"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE freight.payments + ALTER COLUMN client_action TYPE jsonb + USING client_action::jsonb; + `); + + await queryRunner.query(` + ALTER TABLE freight.payments + ALTER COLUMN client_action DROP DEFAULT; + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE freight.payments + ALTER COLUMN client_action TYPE json + USING client_action::json; + `); + } + + +} diff --git a/apps/edr-freight-api/src/migrations/1780644945086-UpdatePaymentTimestamp.ts b/apps/edr-freight-api/src/migrations/1780644945086-UpdatePaymentTimestamp.ts new file mode 100644 index 000000000..6cfc7fc8f --- /dev/null +++ b/apps/edr-freight-api/src/migrations/1780644945086-UpdatePaymentTimestamp.ts @@ -0,0 +1,33 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdatePaymentTimestamp1780644945086 implements MigrationInterface { + name = "UpdatePaymentTimestamp1780644945086"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE freight.payments + ALTER COLUMN refunded_at TYPE timestamp + USING refunded_at::timestamp; + `); + + await queryRunner.query(` + ALTER TABLE freight.payments + ALTER COLUMN expires_at TYPE timestamp + USING expires_at::timestamp; + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE freight.payments + ALTER COLUMN refunded_at TYPE timestamptz + USING refunded_at::timestamptz; + `); + + await queryRunner.query(` + ALTER TABLE freight.payments + ALTER COLUMN expires_at TYPE timestamptz + USING expires_at::timestamptz; + `); + } +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/dto/update-payment-status.dto.ts b/apps/edr-freight-api/src/modules/payment/dto/update-payment-status.dto.ts new file mode 100644 index 000000000..de72c8ba7 --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/dto/update-payment-status.dto.ts @@ -0,0 +1,23 @@ +import { IsEnum, IsOptional, IsString } from "class-validator"; + +export enum PaymentStatus { + REQUIRES_ACTION, + PROCESSING, + SUCCEEDED, + FAILED, + CANCELLED, + REFUNDED, + +} +export class UpdatePaymentStatusDto { + @IsString() + orderId!: string; + + + @IsEnum(PaymentStatus) + status!: PaymentStatus + + @IsOptional() + @IsString() + failureMessage?: string +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/entities/payment.entity.ts b/apps/edr-freight-api/src/modules/payment/entities/payment.entity.ts new file mode 100644 index 000000000..f4b784a62 --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/entities/payment.entity.ts @@ -0,0 +1,62 @@ +import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from "typeorm"; + + +type PaymentType = "booking" +type PaymentMethod = "telebirr" | "cbe-birr" | "ebirr" +type Currency = "ETB" | "USD" +type PaymentStatus = "action-required" | "processing" | "success" | "failed" | "canceled" | "refunded" + +@Entity({ schema: 'freight', name: 'payments' }) +export class PaymentEntity extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id!: string + + @Column({ type: 'varchar', length: 255, name: "ref_id" }) + refId!: string + + @Column({ type: "enum", enum: ["booking"] }) + type!: PaymentType; + + @Column({ type: "enum", enum: ["telebirr", "cbe-birr", "ebirr"] }) + method!: PaymentMethod + + @Column({ type: "enum", enum: ["ETB", "USD"] }) + currency!: Currency + + @Column({ type: "numeric" }) + amount!: number + + @Column({ type: "jsonb", default: {}, name: "raw_initiation" }) + rawInitiation?: Record + + @Column({ type: "jsonb", name: "client_action" }) + clientAction?: Record; + + @Column({ type: "varchar", length: 255, unique: true, name: "merchant_order_id", }) + merchantOrderId!: string + + @Column({ type: "varchar", length: 255, unique: true, name: "transaction_id", }) + transactionId?: string + + @Column({ type: "enum", enum: ["action-required", "processing", "success", "failed", "canceled", "refunded"], default: "action-required" }) + status!: PaymentStatus + + @Column({ type: "date", nullable: true, name: "paid_at" }) + paidAt?: Date + + @Column({ type: "timestamp", nullable: true, name: "refunded_at" }) + refundedAt?: Date + + @Column({ type: "timestamp", nullable: true, name: "expires_at" }) + expiresAt?: Date + + @Column({ type: "varchar", length: 30, nullable: true, name: "failer_code" }) + failerCode?: string + + @Column({ type: "varchar", length: 255, nullable: true, name: "failer_message" }) + failureMessage?: string + + @CreateDateColumn({ name: "created_at" }) + createdAt!: Date + +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/payment.controller.ts b/apps/edr-freight-api/src/modules/payment/payment.controller.ts new file mode 100644 index 000000000..8e9944c28 --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/payment.controller.ts @@ -0,0 +1,53 @@ +import { Controller, Get, NotFoundException, Param, ParseUUIDPipe, Post, Res } from "@nestjs/common"; +import { PaymentService } from "./payment.service"; +import { Public } from "@edr/api-common"; +import { randomUUID } from "crypto"; +import { Response } from "express" +@Public() +@Controller("payments") +export class PaymentController { + constructor(private readonly paymentService: PaymentService) { } + + @Post("/initiate") + async initiatePayment() { + + //Only for testing.. + const data = await this.paymentService.pay(20, "ETB", "telebirr", (_) => { + return new Promise((resp, _) => { + resp({ + id: randomUUID(), + type: "booking" + }) + }); + }) + + return data + } + + + @Get("/telebirr/:refId") + async pay(@Param("refId", ParseUUIDPipe) refId: string, @Res() res: Response) { + const payment = await this.paymentService.getActivePaymentByRefIdAndMethod(refId, "telebirr") + if (!payment) { + throw new NotFoundException('payment not found') + } + return res.send(` + + + + Redirecting... + + +

Redirecting...

+ + + + + `); + } + + + +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/payment.module.ts b/apps/edr-freight-api/src/modules/payment/payment.module.ts new file mode 100644 index 000000000..e9f99bd06 --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/payment.module.ts @@ -0,0 +1,16 @@ +import { Module } from "@nestjs/common"; +import { PaymentTelebirrStrategy } from "./strategies/payment.telebirr.strategy"; +import { PaymentService } from "./payment.service"; +import { HttpModule } from "@nestjs/axios"; +import { PaymentController } from "./payment.controller"; +import { ConfigModule } from "@nestjs/config"; +import { PaymentRepository } from "./payment.repository"; +import { WebhookController } from "./webhooks/webhook.controller"; +import { TelebirrWebhookService } from "./webhooks/providers/telebirr.service"; + +@Module({ + imports: [HttpModule, ConfigModule], + providers: [PaymentRepository, PaymentTelebirrStrategy, PaymentService, TelebirrWebhookService], + controllers: [PaymentController, WebhookController] +}) +export class PaymentModule { } \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/payment.repository.ts b/apps/edr-freight-api/src/modules/payment/payment.repository.ts new file mode 100644 index 000000000..3f93fd77d --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/payment.repository.ts @@ -0,0 +1,39 @@ +import { Injectable } from "@nestjs/common"; +import { DataSource, FindOptionsWhere, QueryDeepPartialEntity, QueryRunner, Repository } from "typeorm"; +import { PaymentEntity } from "./entities/payment.entity"; + +@Injectable() +export class PaymentRepository { + private readonly paymentRepo: Repository; + constructor(private readonly dataSource: DataSource) { + this.paymentRepo = this.dataSource.getRepository(PaymentEntity) + } + + async createTr(qr: QueryRunner, data: Pick): Promise { + const payment = qr.manager.create(PaymentEntity, data) + return qr.manager.save(payment) + } + + findOneBy(options: FindOptionsWhere | FindOptionsWhere[]): Promise { + return this.paymentRepo.findOneBy(options); + } + + update(where: FindOptionsWhere, data: QueryDeepPartialEntity) { + return this.paymentRepo.update(where, data) + } + + getActivePaymentByRefIdAndMethod(refId: string, method: PaymentEntity["method"]) { + return this.paymentRepo + .createQueryBuilder('payment') + .where('payment.method = :method', { method }) + .andWhere('payment.refId = :refId', { refId }) + .andWhere('payment.status IN (:...statuses)', { + statuses: ['action-required'], + }) + .andWhere('payment.expiresAt > :now', { now: new Date() }) + .getOne(); + } + + + +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/payment.service.ts b/apps/edr-freight-api/src/modules/payment/payment.service.ts new file mode 100644 index 000000000..cee35bf79 --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/payment.service.ts @@ -0,0 +1,113 @@ +import { Injectable, NotFoundException } from "@nestjs/common"; +import { DataSource, QueryRunner } from "typeorm"; +import { PaymentEntity } from "./entities/payment.entity"; +import { PaymentStrategy } from "./strategies/payment.strategy"; +import { PaymentTelebirrStrategy } from "./strategies/payment.telebirr.strategy"; +import { PaymentRepository } from "./payment.repository"; +import { ClientAction, PaymentPlatform } from "./strategies/payments.types"; +import * as crypto from 'crypto'; +import { PaymentStatus, UpdatePaymentStatusDto } from "./dto/update-payment-status.dto"; + +type PaymentMethod = PaymentEntity["method"] +type CurrencyType = PaymentEntity["currency"] + +@Injectable() +export class PaymentService { + private strategies: Map; + + constructor( + private readonly datasource: DataSource, + private readonly paymentRepo: PaymentRepository, + private readonly telebirrPaymentStategy: PaymentTelebirrStrategy) { + this.strategies = new Map([ + ["telebirr", this.telebirrPaymentStategy as PaymentStrategy] + ]) + } + + async pay(amount: number, currency: CurrencyType, method: PaymentMethod, cb: (qr: QueryRunner) => Promise<{ id: string, type: PaymentEntity["type"] }>, payform: PaymentPlatform = "web"): Promise<{ + refId: string, + clientAction: ClientAction, + status: PaymentEntity["status"], + paidAt?: string, + failureCode?: string, + failureMessage?: string, + }> { + + const strategy = this.strategies.get(method) + if (!strategy) { + throw new NotFoundException("strategy not found") + } + + const orderId = `freigh${Date.now()}${crypto.randomBytes(4).toString('hex')}` //todo: make it dynamic + const paymentResp = await strategy.pay({ + amountMinor: amount, + currency: currency, + merchantOrderId: orderId, + platform: payform, + }); + + const queryRunner = this.datasource.createQueryRunner() + await queryRunner.connect() + await queryRunner.startTransaction() + + console.log(paymentResp.expiresAt) + try { + const resp = await cb(queryRunner) + const payment = await this.paymentRepo.createTr(queryRunner, { + amount, + currency, + method, + refId: resp.id, + type: resp.type, + merchantOrderId: orderId, + rawInitiation: paymentResp.rawInitiation, + clientAction: paymentResp.clientAction, + expiresAt: paymentResp.expiresAt + + }) + await queryRunner.commitTransaction() + return { + refId: payment.refId, + clientAction: paymentResp.clientAction, + status: payment.status, + paidAt: payment.paidAt?.toISOString(), + failureCode: payment.failerCode ?? undefined, + failureMessage: payment.failureMessage ?? undefined, + } + } catch (err) { + await queryRunner.rollbackTransaction() + throw new Error("payment failed") + } finally { + await queryRunner.release() + } + + } + + + async getActivePaymentByRefIdAndMethod(refId: string, method: PaymentEntity["method"]): Promise { + return this.paymentRepo.getActivePaymentByRefIdAndMethod(refId, method) + } + + + async handleTelebirrPaymentCb(dto: UpdatePaymentStatusDto): Promise { + switch (dto.status) { + case PaymentStatus.SUCCEEDED: + await this.paymentRepo.update({ merchantOrderId: dto.orderId }, { status: "success" }) + break; + case PaymentStatus.FAILED: + await this.paymentRepo.update({ merchantOrderId: dto.orderId }, { status: "failed", failureMessage: dto.failureMessage }) + break; + case PaymentStatus.CANCELLED: + await this.paymentRepo.update({ merchantOrderId: dto.orderId }, { status: "canceled" }) + break; + case PaymentStatus.PROCESSING: + await this.paymentRepo.update({ merchantOrderId: dto.orderId }, { status: "canceled" }) + break; + case PaymentStatus.REFUNDED: + await this.paymentRepo.update({ merchantOrderId: dto.orderId }, { status: "canceled" }) + break; + + } + } + +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/strategies/payment.strategy.ts b/apps/edr-freight-api/src/modules/payment/strategies/payment.strategy.ts new file mode 100644 index 000000000..b1daa2770 --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/strategies/payment.strategy.ts @@ -0,0 +1,8 @@ +import { Injectable } from "@nestjs/common"; +import { ProviderInitiationInput, ProviderInitiationResult } from "./payments.types"; + + +@Injectable() +export abstract class PaymentStrategy { + abstract pay(data: ProviderInitiationInput): Promise +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/strategies/payment.telebirr.strategy.ts b/apps/edr-freight-api/src/modules/payment/strategies/payment.telebirr.strategy.ts new file mode 100644 index 000000000..3fa5fdc75 --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/strategies/payment.telebirr.strategy.ts @@ -0,0 +1,303 @@ +import { Injectable, Logger } from "@nestjs/common"; +import { PaymentStrategy } from "./payment.strategy"; +import { ConfigService } from '@nestjs/config'; +import { HttpService } from '@nestjs/axios'; +import { AxiosError, AxiosRequestConfig } from 'axios'; +import { firstValueFrom } from 'rxjs'; +import * as https from 'node:https'; +import { PaymentEntity } from "../entities/payment.entity"; +import { ProviderInitiationInput, ProviderInitiationResult, ProviderStatus } from "./payments.types"; +import { CreateOrderRequest, CreateOrderResponse, FabricTokenResponse, QueryOrderResponse } from "./telebirr/telebirr.types"; +import { createNonceStr, createTimestamp, signRequestObject, verifyRequestObject } from "./telebirr/telebirr.crypto"; + + + +// type PaymentCurrency = PaymentEntity["currency"] +type PaymentIntentStatus = PaymentEntity["status"] + +const TELEBIRR_HTTP_TIMEOUT_MS = 10_000; + +@Injectable() +export class PaymentTelebirrStrategy implements PaymentStrategy { + async pay(data: ProviderInitiationInput): Promise { + // const refId = randomUUID() + // const orderId = createMerchantOrderId() + const resp = await this.initiate(data) + return resp; + } + + // readonly method = PaymentMethodType.TELEBIRR; + private readonly logger = new Logger(PaymentTelebirrStrategy.name); + private readonly httpsAgent: https.Agent; + + constructor( + private readonly config: ConfigService, + private readonly http: HttpService, + ) { + const insecure = this.config.get('telebirr.insecureTls'); + if (insecure) { + this.logger.warn('TELEBIRR_INSECURE_TLS=true — TLS verification disabled for Telebirr calls. DEV ONLY.'); + } + this.httpsAgent = new https.Agent({ + rejectUnauthorized: !insecure, + secureProtocol: 'TLSv1_2_method', + }); + } + + async initiate(input: ProviderInitiationInput): Promise { + const fabricToken = await this.applyFabricToken(); + const requestBody = this.buildCreateOrderRequest(input); + const response = await this.requestCreateOrder(fabricToken, requestBody); + + const prepayId = response.biz_content?.prepay_id; + if (!prepayId) { + throw new Error( + `Telebirr createOrder returned no prepay_id: ${JSON.stringify(response)}`, + ); + } + + const expiresAt = this.computeExpiresAt(requestBody.biz_content.timeout_express); + const platform = input.platform ?? 'web'; + const clientAction = + platform === 'mobile' + ? { + type: 'LAUNCH_APP' as const, + prepayId, + receiveCode: response.biz_content?.receiveCode, + shortCode: this.merchantCode, + } + : { type: 'REDIRECT' as const, url: this.buildCheckoutUrl(prepayId) }; + + return { + providerOrderId: prepayId, + clientAction, + expiresAt, + rawInitiation: { + request: this.sanitize(requestBody), + response, + }, + }; + } + + async queryStatus(merchantOrderId: string): Promise { + const fabricToken = await this.applyFabricToken(); + const requestBody = this.buildQueryOrderRequest(merchantOrderId); + const response = await this.postJson( + `${this.baseUrl}/payment/v1/merchant/queryOrder`, + requestBody, + { + 'Content-Type': 'application/json', + 'X-APP-Key': this.fabricAppId, + Authorization: fabricToken, + }, + ); + + const tradeStatus = response.biz_content?.trade_status; + const providerTxnId = + response.biz_content?.trans_id ?? response.biz_content?.payment_order_id; + const mapped = this.mapTradeStatus(tradeStatus); + + return { + status: mapped, + providerTxnId, + failureCode: + mapped === "failed" && tradeStatus ? tradeStatus : undefined, + rawResponse: response as Record, + }; + } + + mapTradeStatus(tradeStatus: string | undefined): PaymentIntentStatus { + switch (tradeStatus) { + case 'PAY_SUCCESS': + return "success"; + case 'PAY_FAILED': + case 'ORDER_CLOSED': + return "failed"; + case 'WAIT_PAY': + return "action-required"; + case 'PAYING': + return "processing"; + default: + return "processing"; + } + } + + mapWebhookTradeStatus(tradeStatus: string | undefined): PaymentIntentStatus { + switch (tradeStatus) { + case 'Completed': + return "success"; + case 'Failure': + case 'Expired': + return "failed"; + case 'Paying': + case 'Pending': + return "processing"; + default: + return "processing"; + } + } + + verifyWebhookSignature(payload: Record): boolean { + if (!this.publicKey) { + this.logger.error('TELEBIRR_PUBLIC_KEY not configured; rejecting all webhooks'); + return false; + } + return verifyRequestObject(payload, this.publicKey); + } + + private async applyFabricToken(): Promise { + console.log(this.baseUrl, "base url") + const response = await this.postJson( + `${this.baseUrl}/payment/v1/token`, + { appSecret: this.appSecret }, + { + 'Content-Type': 'application/json', + 'X-APP-Key': this.fabricAppId, + }, + ); + if (!response?.token) { + throw new Error(`Telebirr token request failed: ${JSON.stringify(response)}`); + } + return response.token; + } + + private async requestCreateOrder( + fabricToken: string, + body: CreateOrderRequest, + ): Promise { + return this.postJson( + `${this.baseUrl}/payment/v1/inapp/createOrder`, + body, + { + 'Content-Type': 'application/json', + 'X-APP-Key': this.fabricAppId, + Authorization: fabricToken, + }, + ); + } + + private buildCreateOrderRequest(input: ProviderInitiationInput): CreateOrderRequest { + const totalAmount = String(input.amountMinor / 100); + const req = { + timestamp: createTimestamp(), + nonce_str: createNonceStr(), + method: 'payment.preorder' as const, + version: '1.0' as const, + biz_content: { + notify_url: this.notifyUrl, + appid: this.merchantAppId, + merch_code: this.merchantCode, + merch_order_id: input.merchantOrderId, + trade_type: 'Checkout' as const, + title: `EDR Booking`, + total_amount: totalAmount, + trans_currency: input.currency, + timeout_express: this.timeoutExpress, + }, + }; + const sign = signRequestObject(req as unknown as Record, this.privateKey); + return { ...req, sign, sign_type: 'SHA256WithRSA' }; + } + + private buildQueryOrderRequest(merchantOrderId: string): Record { + const req = { + timestamp: createTimestamp(), + nonce_str: createNonceStr(), + method: 'payment.queryorder', + version: '1.0', + biz_content: { + appid: this.merchantAppId, + merch_code: this.merchantCode, + merch_order_id: merchantOrderId, + }, + }; + const sign = signRequestObject(req as Record, this.privateKey); + return { ...req, sign, sign_type: 'SHA256WithRSA' }; + } + + private buildCheckoutUrl(prepayId: string): string { + const map: Record = { + appid: this.merchantAppId, + merch_code: this.merchantCode, + nonce_str: createNonceStr(), + prepay_id: prepayId, + timestamp: createTimestamp(), + }; + const sign = signRequestObject(map, this.privateKey); + const rawRequest = [ + `appid=${map.appid}`, + `merch_code=${map.merch_code}`, + `nonce_str=${map.nonce_str}`, + `prepay_id=${map.prepay_id}`, + `timestamp=${map.timestamp}`, + 'sign_type=SHA256WithRSA', + `sign=${sign}`, + 'version=1.0', + 'trade_type=Checkout', + ].join('&'); + return `${this.webBaseUrl}${rawRequest}`; + } + + private computeExpiresAt(timeoutExpress: string): Date { + const match = /^(\d+)([smhd])$/.exec(timeoutExpress); + const minutes = match ? this.toMinutes(parseInt(match[1], 10), match[2]) : 15; + return new Date(Date.now() + minutes * 60_000); + } + + private toMinutes(n: number, unit: string): number { + switch (unit) { + case 's': return Math.max(1, Math.round(n / 60)); + case 'm': return n; + case 'h': return n * 60; + case 'd': return n * 60 * 24; + default: return 15; + } + } + + private async postJson( + url: string, + body: unknown, + headers: Record, + ): Promise { + const config: AxiosRequestConfig = { + headers, + timeout: TELEBIRR_HTTP_TIMEOUT_MS, + httpsAgent: this.httpsAgent, + }; + const started = Date.now(); + try { + const res = await firstValueFrom(this.http.post(url, body, config)); + this.logger.debug(`Telebirr POST ${url} status=${res.status} latency=${Date.now() - started}ms`); + return res.data; + } catch (err) { + if (err instanceof AxiosError) { + this.logger.error( + `Telebirr POST ${url} failed: status=${err.response?.status} body=${JSON.stringify(err.response?.data)} code=${err.code} message=${err.message}`, + ); + } else { + this.logger.error(`Telebirr POST ${url} threw: ${err instanceof Error ? err.message : err}`); + } + throw err; + } + } + + private sanitize(body: CreateOrderRequest): Record { + const { sign: _sign, ...rest } = body; + return rest; + } + + private get baseUrl(): string { return this.config.get('telebirr.baseUrl') ?? ''; } + private get webBaseUrl(): string { return this.config.get('telebirr.webBaseUrl') ?? ''; } + private get fabricAppId(): string { return this.config.get('telebirr.fabricAppId') ?? ''; } + private get appSecret(): string { return this.config.get('telebirr.appSecret') ?? ''; } + private get merchantAppId(): string { return this.config.get('telebirr.merchantAppId') ?? ''; } + private get merchantCode(): string { return this.config.get('telebirr.merchantCode') ?? ''; } + private get notifyUrl(): string { return this.config.get('telebirr.notifyUrl') ?? ''; } + private get timeoutExpress(): string { return this.config.get('telebirr.timeoutExpress') ?? '15m'; } + private get privateKey(): string { return this.config.get('telebirr.privateKey') ?? ''; } + private get publicKey(): string { + return this.config.get('telebirr.publicKey') ?? ''; + } + + +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/strategies/payments.types.ts b/apps/edr-freight-api/src/modules/payment/strategies/payments.types.ts new file mode 100644 index 000000000..dae192db9 --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/strategies/payments.types.ts @@ -0,0 +1,39 @@ +import { PaymentEntity } from "../entities/payment.entity"; + +type PaymentIntentStatus = PaymentEntity["status"] +type PaymentMethodType = PaymentEntity["method"] + +export type PaymentPlatform = 'web' | 'mobile'; + +export type ClientAction = + | { type: 'REDIRECT'; url: string } + | { type: 'LAUNCH_APP'; prepayId: string; receiveCode?: string; shortCode: string }; + +export interface ProviderInitiationInput { + merchantOrderId: string; + // bookingRef: string; + amountMinor: number; + currency: string; + platform?: PaymentPlatform; +} + +export interface ProviderInitiationResult { + providerOrderId: string; + clientAction: ClientAction; + expiresAt: Date; + rawInitiation: Record; +} + +export interface ProviderStatus { + status: PaymentIntentStatus; + providerTxnId?: string; + failureCode?: string; + failureMessage?: string; + rawResponse: Record; +} + +export interface PaymentProvider { + readonly method: PaymentMethodType; + initiate(input: ProviderInitiationInput): Promise; + queryStatus(merchantOrderId: string): Promise; +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/strategies/telebirr/telebirr.crypto.ts b/apps/edr-freight-api/src/modules/payment/strategies/telebirr/telebirr.crypto.ts new file mode 100644 index 000000000..20319818d --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/strategies/telebirr/telebirr.crypto.ts @@ -0,0 +1,98 @@ +import * as crypto from 'crypto'; + +const EXCLUDE_FIELDS = new Set([ + 'sign', + 'sign_type', + 'header', + 'refund_info', + 'openType', + 'raw_request', + 'biz_content', +]); + +const NONCE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + +export function buildCanonicalString(requestObject: Record): string { + const fieldMap: Record = {}; + + for (const key of Object.keys(requestObject)) { + if (EXCLUDE_FIELDS.has(key)) continue; + fieldMap[key] = requestObject[key]; + } + + const biz = requestObject['biz_content']; + if (biz && typeof biz === 'object') { + for (const key of Object.keys(biz as Record)) { + if (EXCLUDE_FIELDS.has(key)) continue; + fieldMap[key] = (biz as Record)[key]; + } + } + + return Object.keys(fieldMap) + .sort() + .map((k) => `${k}=${fieldMap[k]}`) + .join('&'); +} + +export function signRequestObject( + requestObject: Record, + privateKey: string, +): string { + return signString(buildCanonicalString(requestObject), privateKey); +} + +export function verifyRequestObject( + requestObject: Record, + publicKey: string, +): boolean { + const signature = requestObject['sign']; + if (typeof signature !== 'string' || signature.length === 0) return false; + return verifySignature(buildCanonicalString(requestObject), signature, publicKey); +} + +export function signString(text: string, privateKey: string): string { + const signature = crypto.sign('sha256', Buffer.from(text), { + key: privateKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST, + }); + return signature.toString('base64'); +} + +export function verifySignature( + text: string, + signatureBase64: string, + publicKey: string, +): boolean { + try { + return crypto.verify( + 'sha256', + Buffer.from(text), + { + key: publicKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST, + }, + Buffer.from(signatureBase64, 'base64'), + ); + } catch { + return false; + } +} + +export function createTimestamp(): string { + return Math.round(Date.now() / 1000).toString(); +} + +export function createNonceStr(length = 32): string { + const bytes = crypto.randomBytes(length); + let out = ''; + for (let i = 0; i < length; i++) { + out += NONCE_CHARS[bytes[i] % NONCE_CHARS.length]; + } + return out; +} + +export function createMerchantOrderId(): string { + return `${Date.now()}${crypto.randomBytes(4).toString('hex')}`; +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/strategies/telebirr/telebirr.types.ts b/apps/edr-freight-api/src/modules/payment/strategies/telebirr/telebirr.types.ts new file mode 100644 index 000000000..6cc29e9f4 --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/strategies/telebirr/telebirr.types.ts @@ -0,0 +1,69 @@ +export interface FabricTokenResponse { + token: string; + expires_in?: number | string; +} + +export interface CreateOrderBizContent { + notify_url: string; + appid: string; + merch_code: string; + merch_order_id: string; + trade_type: 'Checkout' | 'InApp' | 'MiniApp'; + title: string; + total_amount: string; + trans_currency: string; + timeout_express: string; +} + +export interface CreateOrderRequest { + timestamp: string; + nonce_str: string; + method: 'payment.preorder'; + version: '1.0'; + biz_content: CreateOrderBizContent; + sign: string; + sign_type: 'SHA256WithRSA'; +} + +export interface CreateOrderResponse { + code?: string; + msg?: string; + biz_content?: { + prepay_id?: string; + receiveCode?: string; + [key: string]: unknown; + }; + [key: string]: unknown; +} + +export type TelebirrTradeStatus = + | 'PAY_SUCCESS' + | 'PAY_FAILED' + | 'WAIT_PAY' + | 'ORDER_CLOSED' + | 'PAYING' + | 'ACCEPTED' + | 'REFUNDING' + | 'REFUND_SUCCESS' + | 'REFUND_FAILED'; + +export interface QueryOrderResponse { + result?: 'SUCCESS' | 'FAIL'; + code?: string; + msg?: string; + nonce_str?: string; + sign?: string; + sign_type?: string; + biz_content?: { + merch_order_id?: string; + order_status?: string; + trade_status?: TelebirrTradeStatus | string; + payment_order_id?: string; + trans_id?: string; + trans_time?: string; + trans_currency?: string; + total_amount?: string; + [key: string]: unknown; + }; + [key: string]: unknown; +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/webhooks/dto/telebirr.dto.ts b/apps/edr-freight-api/src/modules/payment/webhooks/dto/telebirr.dto.ts new file mode 100644 index 000000000..ef6bf4b3a --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/webhooks/dto/telebirr.dto.ts @@ -0,0 +1,13 @@ +export class TelebirrDto { + merch_order_id!: string; + payment_order_id!: string; + trade_status!: string; + trans_id?: string; + total_amount?: string; + trans_currency?: string; + notify_time?: string; + trans_end_time?: string; + sign!: string; + sign_type?: string; + [key: string]: unknown; +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/webhooks/providers/telebirr.service.ts b/apps/edr-freight-api/src/modules/payment/webhooks/providers/telebirr.service.ts new file mode 100644 index 000000000..96b4c1f0d --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/webhooks/providers/telebirr.service.ts @@ -0,0 +1,49 @@ +import { Injectable, } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import * as crypto from "crypto" +import { TelebirrDto } from '../dto/telebirr.dto'; +@Injectable() +export class TelebirrWebhookService { + // private readonly logger = new Logger(TelebirrWebhookService.name); + + constructor( + private readonly config: ConfigService + ) { } + + verifyTelebirrNotification(payload: TelebirrDto) { + // 1. Extract the signature provided by Telebirr + const { sign, ...bizContent } = payload; + + if (!sign) { + throw new Error("Missing 'sign' field from Telebirr payload"); + } + + // 2. Sort the remaining keys alphabetically to rebuild the raw string + const sortedKeys = Object.keys(bizContent).sort(); + const signString = sortedKeys + .map(key => `${key}=${typeof bizContent[key] === 'object' ? JSON.stringify(bizContent[key]) : bizContent[key]}`) + .join('&'); + + // 3. Convert Telebirr's public key into an object specifying RSA-PSS padding + const publicKey = { + key: this.config.get("telebirr.publicKey") ?? "", + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: 32 // Telebirr standard salt length + }; + + // 4. Verify the signature against the sorted string + const isVerified = crypto.verify( + "sha256", + Buffer.from(signString), + publicKey, + Buffer.from(sign, 'base64') + ); + + return isVerified; + } + + async handle(payload: TelebirrDto): Promise { + console.log(payload) + } + +} \ No newline at end of file diff --git a/apps/edr-freight-api/src/modules/payment/webhooks/webhook.controller.ts b/apps/edr-freight-api/src/modules/payment/webhooks/webhook.controller.ts new file mode 100644 index 000000000..378853728 --- /dev/null +++ b/apps/edr-freight-api/src/modules/payment/webhooks/webhook.controller.ts @@ -0,0 +1,41 @@ +import { All, Body, Controller, HttpCode, HttpStatus, Logger, } from '@nestjs/common'; +import { TelebirrWebhookService } from './providers/telebirr.service'; +import { ApiOperation } from '@nestjs/swagger'; +import { TelebirrDto } from './dto/telebirr.dto'; + +@Controller("payments/webhooks") +export class WebhookController { + constructor(private readonly telebirr: TelebirrWebhookService) { } + private readonly logger = new Logger(WebhookController.name); + + @All('telebirr') + @HttpCode(HttpStatus.OK) + @ApiOperation({ + summary: 'Telebirr payment notification callback (Ethiopia)', + description: 'Webhook endpoint for Telebirr payment status updates. Used by Ethiopian passengers.' + }) + async receiveTelebirr(@Body() payload: TelebirrDto) { + this.logger.log( + `Telebirr webhook Called`, + ); + + try { + const verified = this.telebirr.verifyTelebirrNotification(payload) + if (!verified) { + throw new Error("not valid") + } + const merchantOrderId = payload.merch_order_id; + if (merchantOrderId.startsWith("freight")) { + await this.telebirr.handle(payload); + } else if (merchantOrderId.startsWith("passagner")) { + //todo: handle else where + } + + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + this.logger.error(`Telebirr webhook handler threw: ${message}`); + } + return { code: '0', message: 'OK' }; + } + +} diff --git a/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts b/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts index 68fae00ea..34c4a7843 100644 --- a/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts +++ b/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts @@ -82,17 +82,6 @@ export class TrainSchedulingService { async getEligibleContainerBookings(query: GetEligibleContainerBookingsDto) { const bookingRepository = this.dataSource.getRepository(Booking); const queryBuilder = bookingRepository -<<<<<<< HEAD - .createQueryBuilder('booking') - .leftJoinAndSelect('booking.company', 'company') - .leftJoinAndSelect('booking.originYard', 'originYard') - .leftJoinAndSelect('booking.destinationYard', 'destinationYard') - .leftJoinAndSelect('booking.bookingContainers', 'bookingContainer') - .leftJoinAndSelect('bookingContainer.containerType', 'containerType') - .leftJoin(TrainScheduleBooking, 'scheduleBooking', 'scheduleBooking.booking_id = booking.id') - .where('booking.freightType = :freightType', { freightType: 'CONTAINER' }) - .andWhere('scheduleBooking.id IS NULL'); -======= .createQueryBuilder("booking") .leftJoinAndSelect("booking.customer", "customer") .leftJoinAndSelect("booking.originYard", "originYard") @@ -106,7 +95,6 @@ export class TrainSchedulingService { ) .where("booking.freightType = :freightType", { freightType: "CONTAINER" }) .andWhere("scheduleBooking.id IS NULL"); ->>>>>>> bd6ad54eea229305a214d06081e0ffd27fe163b8 if (query.originStationId) { queryBuilder.andWhere("booking.originYardId = :originStationId", { @@ -144,13 +132,6 @@ export class TrainSchedulingService { const items: EligibleBookingItem[] = bookings.map((booking) => ({ id: booking.id, reference: booking.reference, -<<<<<<< HEAD - customer: booking.company?.name ?? booking.company?.email ?? 'Unknown customer', - containerType: booking.bookingContainers - ?.map((container) => container.containerType?.label ?? container.containerType?.code ?? 'Container') - .join(', ') ?? 'Container', - quantity: booking.bookingContainers?.reduce((sum, container) => sum + Number(container.quantity ?? 0), 0) ?? 0, -======= customer: booking.company?.name ?? booking.company?.email ?? "Unknown customer", containerType: @@ -167,7 +148,6 @@ export class TrainSchedulingService { (sum, container) => sum + Number(container.quantity ?? 0), 0, ) ?? 0, ->>>>>>> bd6ad54eea229305a214d06081e0ffd27fe163b8 weightTons: this.roundTons(booking.cargoTotalWeightVgm), origin: booking.originYard?.label ?? @@ -674,17 +654,6 @@ export class TrainSchedulingService { } async getContainerTrainScheduleById(id: string) { -<<<<<<< HEAD - const schedule = await this.dataSource.getRepository(TrainSchedule).findOne({ - where: { id }, - relations: { - trainSet: { locomotive: true, wagons: { wagonType: true, allocations: { booking: true } } }, - originStation: true, - destinationStation: true, - scheduleBookings: { booking: { company: true, originYard: true, destinationYard: true } }, - }, - }); -======= const schedule = await this.dataSource .getRepository(TrainSchedule) .findOne({ @@ -701,7 +670,6 @@ export class TrainSchedulingService { }, }, }); ->>>>>>> bd6ad54eea229305a214d06081e0ffd27fe163b8 if (!schedule) { throw new NotFoundException(`Train schedule ${id} not found`); diff --git a/apps/edr-freight-web/backoffice/src/App.tsx b/apps/edr-freight-web/backoffice/src/App.tsx index 89e516108..ea824762e 100644 --- a/apps/edr-freight-web/backoffice/src/App.tsx +++ b/apps/edr-freight-web/backoffice/src/App.tsx @@ -1,449 +1,297 @@ -import type { ReactNode } from "react"; -import { Navigate, Outlet, Route, Routes, useLocation, useNavigate } from "react-router-dom"; -import { - Boxes, - FileText, - LayoutDashboard, - Network, - Paperclip, - Settings, - SlidersHorizontal, - Train, - Truck, - Container, - Package, - //TrainTrack, -} from "lucide-react"; - -import { FreightDashboardLayout, type SidebarItem, type SidebarSection } from "@/components/layout"; -import LoadingScreen from "./components/LoadingScreen"; -import { useAuth } from "./auth/useAuth"; -import { - canAccessBookings, - canAccessRuleEngineResource, - hasPermission, -} from "@/lib/permissions"; -import LoginPage from "./pages/auth/LoginPage"; -import BookingContractPage from "./pages/bookings/BookingContractPage"; -import BookingRequestDetailPage from "./pages/bookings/BookingRequestDetailPage"; -import BookingRequestsPage from "./pages/bookings/BookingRequestsPage"; -import DemoUser1Page from "./pages/dashboard/demo/DemoUser1Page"; -import DemoUser2Page from "./pages/dashboard/demo/DemoUser2Page"; -import OverviewPage from "./pages/dashboard/OverviewPage"; -import PermissionsPage from "./pages/dashboard/user-management/PermissionsPage"; -import PositionTypesPage from "./pages/dashboard/user-management/PositionTypesPage"; -import RolesPage from "./pages/dashboard/user-management/RolesPage"; -import UserManagementPage from "./pages/dashboard/user-management/UserManagementPage"; -import UsersPage from "./pages/dashboard/user-management/UsersPage"; -import DropdownSettingsPage from "./pages/dropdown_settings/DropdownSettingsPage"; -import FileUploadSettingsPage from "./pages/documents/FileUploadSettingsPage"; -import RuleEngineLegacyRedirect from "./pages/ruleEngine/RuleEngineLegacyRedirect"; -import RuleEngineResourcePage from "./pages/ruleEngine/RuleEngineResourcePage"; -<<<<<<< HEAD -import { - getCategorySidebarChildren, - RULE_ENGINE_RESOURCES, - type RuleEngineNavCategory, -} from "./pages/ruleEngine/config/resources"; -import type { RuleEngineResourceSlug } from "./types/rule-engine"; - -const filterRuleEngineChildren = ( -======= -import TrainsPage from "./pages/trains/TrainsPage"; -import { getCategorySidebarChildren } from "./pages/ruleEngine/config/resources"; -//import TrainsPage from "./pages/trains/TrainsPage"; -import TrainDetailPage from "./pages/trains/TrainDetailPage"; -import WagonsPage from "./pages/wagons/WagonsPage"; -import ContainersPage from "./pages/containers_management/ContainersPage"; -import CargoesPage from "./pages/cargoes/CargoesPage"; - -const buildSidebarSections = (demoItems: SidebarItem[]): SidebarSection[] => [ - { - title: "Main menu", - mutedTitle: true, - items: [ - { - label: "Overview", - href: "/dashboard/overview", - icon: , - }, - { - label: "Booking requests", - href: "/dashboard/booking-requests", - icon: , - }, - { - label: "Train scheduling", - href: "/dashboard/operations/train-scheduling", - icon: , - }, - ...demoItems, - ], - }, - { - title: "Fleet Management", - items: [ - { - label: "Trains", - href: "/dashboard/trains", - icon: , - }, - { - label: "Wagons", - href: "/dashboard/wagons", - icon: , - }, - { - label: "Containers", - href: "/dashboard/containers", - icon: , - }, - { - label: "Cargoes", - href: "/dashboard/cargoes", - icon: , - }, - ], - }, - { - title: "Administration", - items: [ - { - label: "User management", - href: "/dashboard/user-management", - icon: , - children: [ - { - label: "Users", - href: "/dashboard/user-management/users", - }, - { - label: "Employees", - href: "/dashboard/user-management/employees", - }, - { - label: "Position Types", - href: "/dashboard/user-management/position-types", - }, - { - label: "Permissions", - href: "/dashboard/user-management/permissions", - }, - { - label: "Roles", - href: "/dashboard/user-management/roles", - }, - ], - }, - { - label: "File settings", - href: "/dashboard/file-settings", - icon: , - }, - { - label: "Dropdown settings", - href: "/dashboard/dropdown-settings", - icon: , - }, - ], - }, - { - title: "Freight configuration", - mutedTitle: true, - items: [ - { - label: "Configuration", - href: "/dashboard/configuration", - icon: , - children: getCategorySidebarChildren("configuration"), - }, - { - label: "Rules", - href: "/dashboard/rules", - icon: , - children: getCategorySidebarChildren("rules"), - }, - ], - }, -]; - -const hasPermission = ( ->>>>>>> bd6ad54eea229305a214d06081e0ffd27fe163b8 - user: ReturnType["user"], - category: RuleEngineNavCategory, -): SidebarItem[] => - getCategorySidebarChildren(category).filter((item) => { - const slug = item.href.split("/").pop() as RuleEngineResourceSlug; - return canAccessRuleEngineResource(user, slug, "view"); - }); - -const buildSidebarSections = ( - user: ReturnType["user"], - demoItems: SidebarItem[], -): SidebarSection[] => { - const configurationChildren = filterRuleEngineChildren(user, "configuration"); - const rulesChildren = filterRuleEngineChildren(user, "rules"); - - const mainItems: SidebarItem[] = [ - { - label: "Overview", - href: "/dashboard/overview", - icon: , - }, - ...(canAccessBookings(user) - ? [ - { - label: "Booking requests", - href: "/dashboard/booking-requests", - icon: , - }, - ] - : []), - ...demoItems, - ]; - - const freightConfigItems: SidebarItem[] = []; - if (configurationChildren.length) { - freightConfigItems.push({ - label: "Configuration", - href: "/dashboard/configuration", - icon: , - children: configurationChildren, - }); - } - if (rulesChildren.length) { - freightConfigItems.push({ - label: "Rules", - href: "/dashboard/rules", - icon: , - children: rulesChildren, - }); - } - - const sections: SidebarSection[] = [ - { title: "Main menu", mutedTitle: true, items: mainItems }, - { - title: "Administration", - items: [ - { - label: "User management", - href: "/dashboard/user-management", - icon: , - children: [ - { label: "Users", href: "/dashboard/user-management/users" }, - { label: "Position Types", href: "/dashboard/user-management/position-types" }, - { label: "Permissions", href: "/dashboard/user-management/permissions" }, - { label: "Roles", href: "/dashboard/user-management/roles" }, - ], - }, - { - label: "File settings", - href: "/dashboard/file-settings", - icon: , - }, - { - label: "Dropdown settings", - href: "/dashboard/dropdown-settings", - icon: , - }, - ], - }, - ]; - - if (freightConfigItems.length) { - sections.push({ - title: "Freight configuration", - mutedTitle: true, - items: freightConfigItems, - }); - } - - return sections; -}; - -const PermissionRoute = ({ - allow, - children, -}: { - allow: boolean; - children: ReactNode; -}) => (allow ? children : ); - -const DashboardShell = () => { - const navigate = useNavigate(); - const location = useLocation(); - const { user, logout } = useAuth(); - - const demoItems: SidebarItem[] = [ - ...(hasPermission(user, "can:demo:user1") - ? [{ label: "User1", href: "/dashboard/user1", icon: }] - : []), - ...(hasPermission(user, "can:demo:user2") - ? [{ label: "User2", href: "/dashboard/user2", icon: }] - : []), - ]; - - const sidebarSections = buildSidebarSections(user, demoItems); - const displayName = user?.name?.en || user?.username || user?.email || "User"; - - return ( - - - - ); -}; - -const ruleEngineSlugs = RULE_ENGINE_RESOURCES.map((r) => r.slug); - -const App = () => { - const { user, loading } = useAuth(); - - if (loading) { - return ; - } - - if (!user) { - return ( - - } /> - } /> - - ); - } - - const canBookings = canAccessBookings(user); - - return ( - - } /> - } /> - - }> - } /> - -<<<<<<< HEAD - - - - } - /> - - - - } - /> - - - - } - /> -======= - } /> - } /> - } - /> - } /> ->>>>>>> bd6ad54eea229305a214d06081e0ffd27fe163b8 - -<<<<<<< HEAD - } /> - } /> - } /> - } /> - } /> -======= - } /> - } /> - } /> - } /> - } /> - - } /> - } /> - } /> - {/* } /> */} - } /> - } /> ->>>>>>> ec3f83c9fb517bc0302e315bd3e35db501483751 - - } /> - } /> - - } - /> - - canAccessRuleEngineResource(user, slug, "view"), - )} - > - - - } - /> - - } - /> - - canAccessRuleEngineResource(user, slug, "view"), - )} - > - - - } - /> - - } - /> - } /> - - } /> - } /> - - } - /> - } - /> - - - } /> - - ); -}; - -export default App; +import { Navigate, Outlet, Route, Routes, useLocation, useNavigate } from "react-router-dom"; +import { + Boxes, + FileText, + LayoutDashboard, + Network, + Paperclip, + Settings, + SlidersHorizontal, + Train, + Truck, + Container, + Package, + //TrainTrack, +} from "lucide-react"; + +import { FreightDashboardLayout, type SidebarItem, type SidebarSection } from "@/components/layout"; +import LoadingScreen from "./components/LoadingScreen"; +import { useAuth } from "./auth/useAuth"; +import LoginPage from "./pages/auth/LoginPage"; +import BookingContractPage from "./pages/bookings/BookingContractPage"; +import BookingRequestDetailPage from "./pages/bookings/BookingRequestDetailPage"; +import BookingRequestsPage from "./pages/bookings/BookingRequestsPage"; +import DemoUser1Page from "./pages/dashboard/demo/DemoUser1Page"; +import DemoUser2Page from "./pages/dashboard/demo/DemoUser2Page"; +import OverviewPage from "./pages/dashboard/OverviewPage"; +import EmployeesPage from "./pages/dashboard/user-management/EmployeesPage"; +import PermissionsPage from "./pages/dashboard/user-management/PermissionsPage"; +import PositionTypesPage from "./pages/dashboard/user-management/PositionTypesPage"; +import RolesPage from "./pages/dashboard/user-management/RolesPage"; +import UserManagementPage from "./pages/dashboard/user-management/UserManagementPage"; +import UsersPage from "./pages/dashboard/user-management/UsersPage"; +import DropdownSettingsPage from "./pages/dropdown_settings/DropdownSettingsPage"; +import FileUploadSettingsPage from "./pages/documents/FileUploadSettingsPage"; +import RuleEngineLegacyRedirect from "./pages/ruleEngine/RuleEngineLegacyRedirect"; +import RuleEngineResourcePage from "./pages/ruleEngine/RuleEngineResourcePage"; +// import TrainsPage from "./pages/trains/TrainsPage"; +import { getCategorySidebarChildren } from "./pages/ruleEngine/config/resources"; +//import TrainsPage from "./pages/trains/TrainsPage"; +import TrainDetailPage from "./pages/trains/TrainDetailPage"; +import WagonsPage from "./pages/wagons/WagonsPage"; +import ContainersPage from "./pages/containers_management/ContainersPage"; +import CargoesPage from "./pages/cargoes/CargoesPage"; + +const buildSidebarSections = (demoItems: SidebarItem[]): SidebarSection[] => [ + { + title: "Main menu", + mutedTitle: true, + items: [ + { + label: "Overview", + href: "/dashboard/overview", + icon: , + }, + { + label: "Booking requests", + href: "/dashboard/booking-requests", + icon: , + }, + { + label: "Train scheduling", + href: "/dashboard/operations/train-scheduling", + icon: , + }, + ...demoItems, + ], + }, + { + title: "Fleet Management", + items: [ + { + label: "Trains", + href: "/dashboard/trains", + icon: , + }, + { + label: "Wagons", + href: "/dashboard/wagons", + icon: , + }, + { + label: "Containers", + href: "/dashboard/containers", + icon: , + }, + { + label: "Cargoes", + href: "/dashboard/cargoes", + icon: , + }, + ], + }, + { + title: "Administration", + items: [ + { + label: "User management", + href: "/dashboard/user-management", + icon: , + children: [ + { + label: "Users", + href: "/dashboard/user-management/users", + }, + { + label: "Employees", + href: "/dashboard/user-management/employees", + }, + { + label: "Position Types", + href: "/dashboard/user-management/position-types", + }, + { + label: "Permissions", + href: "/dashboard/user-management/permissions", + }, + { + label: "Roles", + href: "/dashboard/user-management/roles", + }, + ], + }, + { + label: "File settings", + href: "/dashboard/file-settings", + icon: , + }, + { + label: "Dropdown settings", + href: "/dashboard/dropdown-settings", + icon: , + }, + ], + }, + { + title: "Freight configuration", + mutedTitle: true, + items: [ + { + label: "Configuration", + href: "/dashboard/configuration", + icon: , + children: getCategorySidebarChildren("configuration"), + }, + { + label: "Rules", + href: "/dashboard/rules", + icon: , + children: getCategorySidebarChildren("rules"), + }, + ], + }, +]; + +const hasPermission = ( + user: ReturnType["user"], + key: string, +) => { + if (!user) return false; + if (user.permissions?.some((p) => p.key === key)) return true; + + return (user.employee ?? []).some((emp) => + (emp.positions ?? []).some((pos) => + (pos.permissions ?? []).some((p) => p.key === key), + ), + ); +}; + +const DashboardShell = () => { + const navigate = useNavigate(); + const location = useLocation(); + const { user, logout } = useAuth(); + + const demoItems: SidebarItem[] = [ + ...(hasPermission(user, "can:demo:user1") + ? [ + { + label: "User1", + href: "/dashboard/user1", + icon: , + }, + ] + : []), + ...(hasPermission(user, "can:demo:user2") + ? [ + { + label: "User2", + href: "/dashboard/user2", + icon: , + }, + ] + : []), + ]; + + const sidebarSections = buildSidebarSections(demoItems); + const displayName = user?.name?.en || user?.username || user?.email || "User"; + + return ( + + + + ); +}; + +const App = () => { + const { user, loading } = useAuth(); + + if (loading) { + return ; + } + + if (!user) { + return ( + + } /> + } /> + + ); + } + + return ( + + } /> + } /> + + }> + } /> + + } /> + } /> + } + /> + {/* } /> + + } /> */} + } /> + } /> + } /> + } /> + + } /> + } /> + } /> + {/* } /> */} + } /> + } /> + + } /> + } /> + + } + /> + } /> + + } + /> + } /> + + } + /> + } /> + + } /> + } /> + + } + /> + } + /> + + + } /> + + ); +}; + +export default App; diff --git a/apps/edr-freight-web/backoffice/src/components/bookings/ApprovalStepsCard.tsx b/apps/edr-freight-web/backoffice/src/components/bookings/ApprovalStepsCard.tsx index fcffe97d5..293c17e2a 100644 --- a/apps/edr-freight-web/backoffice/src/components/bookings/ApprovalStepsCard.tsx +++ b/apps/edr-freight-web/backoffice/src/components/bookings/ApprovalStepsCard.tsx @@ -1,19 +1,35 @@ -import { useMemo } from "react"; -import { ShieldCheck } from "lucide-react"; +import { useMemo, useState } from "react"; +import { Check, ShieldCheck } from "lucide-react"; -import type { BookingApprovalStep, BookingDetail } from "@/types/booking"; +import { BookingConfirmDialog } from "./BookingConfirmDialog"; +import { useAuth } from "@/auth/useAuth"; import { formatApprovalProgress } from "@/features/bookings/approval-progress"; -import { getNextPendingApprovalStep } from "@/features/bookings/booking-actions.config"; +import { + buildApproveActionForStep, + canActOnApprovalStep, + getNextPendingApprovalStep, +} from "@/features/bookings/booking-actions.config"; +import type { useBookingMutations } from "@/hooks/bookings/useBookings"; +import type { BookingApprovalStep, BookingDetail } from "@/types/booking"; import { bookingGlass, bookingSurface } from "./booking-ui.styles"; -import { Badge } from "@edr/ui-common"; +import { Badge, Button } from "@edr/ui-common"; import { cn } from "@/lib/utils"; +type Mutations = ReturnType; + interface ApprovalStepsCardProps { booking: BookingDetail; + mutations: Mutations; } -/** Read-only approval chain visualization; actions live in BookingActionsToolbar. */ -export function ApprovalStepsCard({ booking }: ApprovalStepsCardProps) { +/** Approval chain with inline approve on the current pending step. */ +export function ApprovalStepsCard({ booking, mutations }: ApprovalStepsCardProps) { + const { user } = useAuth(); + const [confirmOpen, setConfirmOpen] = useState(false); + const [pendingStep, setPendingStep] = useState( + null, + ); + const steps = useMemo( () => [...(booking.approvalSteps ?? [])].sort( @@ -24,57 +40,110 @@ export function ApprovalStepsCard({ booking }: ApprovalStepsCardProps) { const nextPending = getNextPendingApprovalStep(steps); const summary = formatApprovalProgress(booking.status, steps); + const pendingAction = pendingStep + ? buildApproveActionForStep(pendingStep) + : null; + + const openApprove = (step: BookingApprovalStep) => { + setPendingStep(step); + setConfirmOpen(true); + }; + + const closeApprove = () => { + setConfirmOpen(false); + setPendingStep(null); + }; + + const runApprove = () => { + if (!pendingStep) return; + mutations.approveStep.mutate( + { stepId: pendingStep.id, requiredRole: pendingStep.requiredRole }, + { onSuccess: () => closeApprove() }, + ); + }; return ( -
-
-
- + <> +
+
+
+ +
+
+

+ Approval chain +

+

+ {summary.detail || + (nextPending + ? `Next: ${nextPending.requiredRole} · step ${nextPending.stepOrder}` + : steps.length + ? "All steps complete" + : "Accept submission to begin")} +

+
-
-

- Approval chain -

-

- {summary.detail || - (nextPending - ? `Next: ${nextPending.requiredRole} · step ${nextPending.stepOrder}` - : steps.length - ? "All steps complete" - : "Accept submission to begin")} -

+ +
+ {steps.length === 0 ? ( +

+ Use{" "} + + Accept for approval + {" "} + in staff actions to instantiate steps. +

+ ) : ( +
    + {steps.map((step) => ( + + ))} +
+ )}
-
- {steps.length === 0 ? ( -

- Use Accept for approval{" "} - in staff actions to instantiate steps. -

- ) : ( -
    - {steps.map((step) => ( - - ))} -
- )} -
-
+ { + if (!open) closeApprove(); + else setConfirmOpen(true); + }} + action={pendingAction} + reference={booking.reference} + inputValue="" + onInputChange={() => {}} + onConfirm={runApprove} + isPending={mutations.approveStep.isPending} + /> + ); } function StepRow({ step, + steps, + user, isNext, + isPending, + onApprove, }: { step: BookingApprovalStep; + steps: BookingApprovalStep[]; + user: ReturnType["user"]; isNext: boolean; + isPending: boolean; + onApprove: (step: BookingApprovalStep) => void; }) { + const canApprove = canActOnApprovalStep(user, step, steps); const statusStyles = step.status === "APPROVED" ? "border-emerald-500/25 bg-emerald-500/10 text-black" @@ -88,9 +157,7 @@ function StepRow({
  • @@ -115,12 +182,26 @@ function StepRow({ )}
  • - - {step.status} - +
    + {canApprove && ( + + )} + + {step.status} + +
    ); } diff --git a/apps/edr-freight-web/backoffice/src/components/wagons/AssignWagonDialog.tsx b/apps/edr-freight-web/backoffice/src/components/wagons/AssignWagonDialog.tsx index 1f14ecb13..25877ac4e 100644 --- a/apps/edr-freight-web/backoffice/src/components/wagons/AssignWagonDialog.tsx +++ b/apps/edr-freight-web/backoffice/src/components/wagons/AssignWagonDialog.tsx @@ -1,12 +1,13 @@ import { useState } from 'react'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +// import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { useWagons, useAssignWagonToTrain } from '@/hooks/useWagons'; import { useToast } from '@/hooks/use-toast'; import { Plus } from 'lucide-react'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@edr/ui-common'; export function AssignWagonDialog({ trainId }: { trainId: string }) { const [open, setOpen] = useState(false); @@ -16,7 +17,7 @@ export function AssignWagonDialog({ trainId }: { trainId: string }) { const assign = useAssignWagonToTrain(); const { toast } = useToast(); - const available = wagons?.filter(w => w.status === 'AVAILABLE' || !w.trainId); + const available = wagons?.filter((w:any) => w.status === 'AVAILABLE' || !w.trainId); const handleAssign = async () => { if (!wagonId) return; @@ -36,7 +37,7 @@ export function AssignWagonDialog({ trainId }: { trainId: string }) {
    diff --git a/apps/edr-freight-web/backoffice/src/components/wagons/WagonsTable.tsx b/apps/edr-freight-web/backoffice/src/components/wagons/WagonsTable.tsx index 5b372030f..145f643c4 100644 --- a/apps/edr-freight-web/backoffice/src/components/wagons/WagonsTable.tsx +++ b/apps/edr-freight-web/backoffice/src/components/wagons/WagonsTable.tsx @@ -2,7 +2,7 @@ import { useWagonsByTrain, useUnassignWagon, useReorderWagons } from '@/hooks/us import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Button } from '@/components/ui/button'; import { Trash2, GripVertical } from 'lucide-react'; -import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd'; +// import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd'; export function WagonsTable({ trainId }: { trainId: string }) { const { data: wagons, refetch } = useWagonsByTrain(trainId); @@ -14,50 +14,51 @@ export function WagonsTable({ trainId }: { trainId: string }) { const items = Array.from(wagons || []); const [removed] = items.splice(result.source.index, 1); items.splice(result.destination.index, 0, removed); - reorder.mutate({ trainId, wagonIds: items.map(w => w.id) }); + reorder.mutate({ trainId, wagonIds: items.map((w:any) => w.id) }); }; if (!wagons?.length) return
    No wagons assigned.
    ; return ( - - - {(provided) => ( - - - - - Number - Type - Sequence - Status - Actions - - - - {wagons.map((wagon, idx) => ( - - {(provided) => ( - - - {wagon.wagonNumber} - {wagon.wagonTypeId} - {wagon.sequenceNumber} - {wagon.status} - - - - - )} - - ))} - {provided.placeholder} - -
    - )} -
    -
    +
    + // + // + // {(provided) => ( + // + // + // + // + // Number + // Type + // Sequence + // Status + // Actions + // + // + // + // {wagons.map((wagon, idx) => ( + // + // {(provided) => ( + // + // + // {wagon.wagonNumber} + // {wagon.wagonTypeId} + // {wagon.sequenceNumber} + // {wagon.status} + // + // + // + // + // )} + // + // ))} + // {provided.placeholder} + // + //
    + // )} + //
    + //
    ); } \ No newline at end of file diff --git a/apps/edr-freight-web/backoffice/src/features/bookings/booking-actions.config.ts b/apps/edr-freight-web/backoffice/src/features/bookings/booking-actions.config.ts index 01a0efb20..652988a39 100644 --- a/apps/edr-freight-web/backoffice/src/features/bookings/booking-actions.config.ts +++ b/apps/edr-freight-web/backoffice/src/features/bookings/booking-actions.config.ts @@ -13,7 +13,11 @@ import { } from "lucide-react"; import type { AuthUser } from "@/auth/types"; -import { FREIGHT_PERMS, hasPermission } from "@/lib/permissions"; +import { + FREIGHT_PERMS, + hasPermission, + isFreightApprovalAdmin, +} from "@/lib/permissions"; import type { BookingApprovalStep, BookingDetail, @@ -71,18 +75,7 @@ function approvalActions( const next = getNextPendingApprovalStep(steps); if (!next) return []; return [ - { - id: "approve", - label: `Approve (${next.requiredRole})`, - shortLabel: "Approve", - description: `Complete step ${next.stepOrder} as ${next.requiredRole}`, - confirmTitle: `Approve as ${next.requiredRole}?`, - confirmDescription: - "This records your approval and advances the booking to the next step in the chain.", - variant: "default", - icon: Check, - primary: true, - }, + buildApproveActionForStep(next), { id: "rejectApproval", label: "Reject approval", @@ -219,6 +212,37 @@ const approvePermissionForRole = (role: string): string | undefined => { return undefined; }; +/** True when this step is the current pending step and the user may approve it. */ +export function canActOnApprovalStep( + user: AuthUser | null | undefined, + step: BookingApprovalStep, + steps?: BookingApprovalStep[] | null, +): boolean { + if (step.status !== "PENDING") return false; + const next = getNextPendingApprovalStep(steps); + if (!next || next.id !== step.id) return false; + if (isFreightApprovalAdmin(user)) return true; + const perm = approvePermissionForRole(step.requiredRole); + return perm ? hasPermission(user, perm) : false; +} + +export function buildApproveActionForStep( + step: BookingApprovalStep, +): BookingActionDef { + return { + id: "approve", + label: `Approve (${step.requiredRole})`, + shortLabel: "Approve", + description: `Complete step ${step.stepOrder} as ${step.requiredRole}`, + confirmTitle: `Approve as ${step.requiredRole}?`, + confirmDescription: + "This records your approval and advances the booking to the next step in the chain.", + variant: "default", + icon: Check, + primary: true, + }; +} + function filterActionsByUser( actions: BookingActionDef[], user: AuthUser | null | undefined, @@ -228,8 +252,7 @@ function filterActionsByUser( const next = getNextPendingApprovalStep(approvalSteps); return actions.filter((action) => { if (action.id === "approve" && next) { - const perm = approvePermissionForRole(next.requiredRole); - return perm ? hasPermission(user, perm) : false; + return canActOnApprovalStep(user, next, approvalSteps); } const perm = ACTION_PERMISSION[action.id]; return perm ? hasPermission(user, perm) : true; diff --git a/apps/edr-freight-web/backoffice/src/lib/permissions.ts b/apps/edr-freight-web/backoffice/src/lib/permissions.ts index c5c25a6aa..cadaaea03 100644 --- a/apps/edr-freight-web/backoffice/src/lib/permissions.ts +++ b/apps/edr-freight-web/backoffice/src/lib/permissions.ts @@ -44,6 +44,19 @@ export function isSuperAdmin(user: AuthUser | null | undefined): boolean { return Boolean(user?.roles?.some((r) => r.key === "super_admin")); } +/** Org-level admins may act on any approval step in the chain. */ +export function isOrganizationAdmin( + user: AuthUser | null | undefined, +): boolean { + return Boolean(user?.roles?.some((r) => r.key === "organization_admin")); +} + +export function isFreightApprovalAdmin( + user: AuthUser | null | undefined, +): boolean { + return isSuperAdmin(user) || isOrganizationAdmin(user); +} + export function hasPermission( user: AuthUser | null | undefined, key: string, diff --git a/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestDetailPage.tsx b/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestDetailPage.tsx index 2893e2259..a57edc5ea 100644 --- a/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestDetailPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestDetailPage.tsx @@ -258,7 +258,7 @@ export default function BookingRequestDetailPage() { )} {(booking.status === "PENDING_APPROVAL" || booking.status === "APPROVED_PENDING_SIGNATURE") && ( - + )}
    diff --git a/apps/edr-freight-web/backoffice/src/pages/cargoes/CargoesPage.tsx b/apps/edr-freight-web/backoffice/src/pages/cargoes/CargoesPage.tsx index 4733d23cf..bb4555771 100644 --- a/apps/edr-freight-web/backoffice/src/pages/cargoes/CargoesPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/cargoes/CargoesPage.tsx @@ -1,8 +1,9 @@ import { useCargoes } from '@/hooks/useCargoes'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +// import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Badge } from '@/components/ui/badge'; import { LoadCargoDialog } from '@/components/cargoes/LoadCargoDialog'; +import { Card, CardContent, CardHeader, CardTitle } from '@edr/ui-common'; export default function CargoesPage() { const { data: cargoes, refetch, isLoading } = useCargoes(); @@ -14,7 +15,7 @@ export default function CargoesPage() { ReferenceDescriptionQuantityWeightStatusActions - {cargoes?.map(c => ( + {cargoes?.map((c:any) => ( {c.cargoReference} {c.description || '-'} diff --git a/apps/edr-freight-web/backoffice/src/pages/containers_management/ContainersPage.tsx b/apps/edr-freight-web/backoffice/src/pages/containers_management/ContainersPage.tsx index 5c531a434..6aea46a4a 100644 --- a/apps/edr-freight-web/backoffice/src/pages/containers_management/ContainersPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/containers_management/ContainersPage.tsx @@ -1,7 +1,8 @@ import { useContainers } from '@/hooks/useContainers'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +// import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Badge } from '@/components/ui/badge'; +import { Card, CardContent, CardHeader, CardTitle } from '@edr/ui-common'; export default function ContainersPage() { const { data: containers, isLoading } = useContainers(); @@ -13,7 +14,7 @@ export default function ContainersPage() {
    NumberTypeWagonStatus - {containers?.map(c => ( + {containers?.map((c:any) => ( {c.containerNumber} {c.containerTypeId} diff --git a/apps/edr-freight-web/backoffice/src/pages/trains/TrainDetailPage.tsx b/apps/edr-freight-web/backoffice/src/pages/trains/TrainDetailPage.tsx index 500fc3c91..75cf8c047 100644 --- a/apps/edr-freight-web/backoffice/src/pages/trains/TrainDetailPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/trains/TrainDetailPage.tsx @@ -1,9 +1,12 @@ import { useParams } from 'react-router-dom'; import { useTrain } from '@/hooks/useTrains'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { Skeleton } from '@/components/ui/skeleton'; -import { AssignWagonDialog } from '@/components/AssignWagonDialog'; -import { WagonsTable } from '@/components/WagonsTable'; +// import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +// import { Skeleton } from '@/components/ui/skeleton'; +// import { AssignWagonDialog } from '@/components/AssignWagonDialog'; +// import { WagonsTable } from '@/components/WagonsTable'; +import { Card, CardContent, CardHeader, CardTitle, Skeleton } from '@edr/ui-common'; +import { AssignWagonDialog } from '@/components/wagons/AssignWagonDialog'; +import { WagonsTable } from '@/components/wagons/WagonsTable'; export default function TrainDetailPage() { const { id } = useParams<{ id: string }>(); diff --git a/apps/edr-freight-web/backoffice/src/pages/trains/TrainsPage.tsx b/apps/edr-freight-web/backoffice/src/pages/trains/TrainsPage.tsx index ef6dba506..51de6226a 100644 --- a/apps/edr-freight-web/backoffice/src/pages/trains/TrainsPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/trains/TrainsPage.tsx @@ -1,42 +1,3 @@ -<<<<<<< HEAD -import { useState } from 'react'; -import { useTrains, useDeleteTrain, useCreateTrain } from '@/hooks/useTrains'; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; -import { Badge } from '@/components/ui/badge'; -import { Button } from '@/components/ui/button'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; -import { Input } from '@/components/ui/input'; -import { Label } from '@/components/ui/label'; -import { useToast } from '@/hooks/use-toast'; -import { Plus, Eye, Trash2 } from 'lucide-react'; -import { Link } from 'react-router-dom'; - -const CreateTrainForm = ({ onSuccess }: { onSuccess: () => void }) => { - const [form, setForm] = useState({ code: '', capacityTons: 0, trainNumber: '', trainName: '' }); - const createTrain = useCreateTrain(); - const { toast } = useToast(); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - try { - await createTrain.mutateAsync(form); - toast({ title: 'Train created', description: `${form.code} added.` }); - onSuccess(); - } catch { - toast({ title: 'Error', description: 'Failed to create train.', variant: 'destructive' }); - } - }; - - return ( -
    -
    setForm({...form, code: e.target.value})} />
    -
    setForm({...form, capacityTons: parseFloat(e.target.value)})} />
    -
    setForm({...form, trainNumber: e.target.value})} />
    -
    setForm({...form, trainName: e.target.value})} />
    - - -======= import { useMemo, useState } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { isAxiosError } from 'axios'; @@ -794,45 +755,44 @@ const TrainsPage = () => { ->>>>>>> 523d7e58422f1bde8024c2dd237092a7cf6aa190 ); }; -export default function TrainsPage() { - const { data: trains, isLoading } = useTrains(); - const deleteTrain = useDeleteTrain(); - const [open, setOpen] = useState(false); +// export default function TrainsPage() { +// const { data: trains, isLoading } = useTrains(); +// const deleteTrain = useDeleteTrain(); +// const [open, setOpen] = useState(false); - if (isLoading) return
    Loading trains...
    ; +// if (isLoading) return
    Loading trains...
    ; - return ( - - - Trains - - - Create Train setOpen(false)} /> - - - -
    - NumberNameStatusCapacityActions - - {trains?.map(train => ( - - {train.trainNumber || train.code} - {train.trainName || '-'} - {train.status} - {train.capacityTons} t - - - - - - ))} - -
    - - - ); -} \ No newline at end of file +// return ( +// +// +// Trains +// +// +// Create Train setOpen(false)} /> +// +// +// +// +// NumberNameStatusCapacityActions +// +// {trains?.map(train => ( +// +// {train.trainNumber || train.code} +// {train.trainName || '-'} +// {train.status} +// {train.capacityTons} t +// +// +// +// +// +// ))} +// +//
    +//
    +//
    +// ); +// } \ No newline at end of file diff --git a/apps/edr-freight-web/backoffice/src/pages/wagons/WagonsPage.tsx b/apps/edr-freight-web/backoffice/src/pages/wagons/WagonsPage.tsx index b5407f022..6d9c3fcd3 100644 --- a/apps/edr-freight-web/backoffice/src/pages/wagons/WagonsPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/wagons/WagonsPage.tsx @@ -1,7 +1,9 @@ import { useWagons } from '@/hooks/useWagons'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Badge } from '@/components/ui/badge'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +// import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Card, CardContent, CardHeader, CardTitle } from '@edr/ui-common'; + export default function WagonsPage() { const { data: wagons, isLoading } = useWagons(); @@ -13,7 +15,7 @@ export default function WagonsPage() { NumberTypeTrainStatus - {wagons?.map(w => ( + {wagons?.map((w:any) => ( {w.wagonNumber} {w.wagonTypeId} diff --git a/apps/edr-freight-web/backoffice/src/services/cargoService.ts b/apps/edr-freight-web/backoffice/src/services/cargoService.ts index 79facab6e..432f7073e 100644 --- a/apps/edr-freight-web/backoffice/src/services/cargoService.ts +++ b/apps/edr-freight-web/backoffice/src/services/cargoService.ts @@ -1,4 +1,6 @@ -import { apiClient } from '@/lib/axios'; +// import { apiClient } from '@/lib/axios'; +import { api as apiClient } from "../auth/http"; + export interface Cargo { id: string; diff --git a/apps/edr-freight-web/backoffice/src/services/containerService.ts b/apps/edr-freight-web/backoffice/src/services/containerService.ts index 3d0e84bb8..791da39f8 100644 --- a/apps/edr-freight-web/backoffice/src/services/containerService.ts +++ b/apps/edr-freight-web/backoffice/src/services/containerService.ts @@ -1,4 +1,6 @@ -import { apiClient } from '@/lib/axios'; +// import { apiClient } from '@/lib/axios'; +import { api as apiClient } from "../auth/http"; + export interface Container { id: string; diff --git a/apps/edr-freight-web/backoffice/src/services/trains.service.ts b/apps/edr-freight-web/backoffice/src/services/trains.service.ts index 57f0c5630..c45d84887 100644 --- a/apps/edr-freight-web/backoffice/src/services/trains.service.ts +++ b/apps/edr-freight-web/backoffice/src/services/trains.service.ts @@ -1,4 +1,6 @@ -import { apiClient } from '@/lib/axios'; +// import { apiClient } from '@/lib/axios'; + import { api as apiClient } from "../auth/http"; + export interface Train { id: string; diff --git a/apps/edr-freight-web/backoffice/src/services/wagon.service.ts b/apps/edr-freight-web/backoffice/src/services/wagon.service.ts index 27ee99bbd..29125ced1 100644 --- a/apps/edr-freight-web/backoffice/src/services/wagon.service.ts +++ b/apps/edr-freight-web/backoffice/src/services/wagon.service.ts @@ -1,4 +1,4 @@ -import { apiClient } from '@/lib/axios'; +import { api as apiClient } from "../auth/http"; export interface Wagon { id: string; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d01697188..dbb202c1e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,7 +17,7 @@ importers: devDependencies: '@commitlint/cli': specifier: ^19.5.0 - version: 19.8.1(@types/node@20.19.41)(typescript@5.9.3) + version: 19.8.1(@types/node@24.13.0)(typescript@5.9.3) '@commitlint/config-conventional': specifier: ^19.5.0 version: 19.8.1 @@ -159,7 +159,7 @@ importers: version: 7.2.2 ts-jest: specifier: ^29.2.5 - version: 29.4.11(@babel/core@7.29.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.29.0))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.11(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.4.1(@babel/core@7.29.0))(jest-util@30.4.1)(jest@29.7.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)))(typescript@5.9.3) ts-loader: specifier: ^9.5.1 version: 9.5.7(typescript@5.9.3)(webpack@5.106.0) @@ -241,7 +241,7 @@ importers: version: link:../../../packages/config/tsconfig '@tailwindcss/vite': specifier: ^4.3.0 - version: 4.3.0(vite@5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0)) + version: 4.3.0(vite@5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0)) '@types/react': specifier: ^18.3.11 version: 18.3.29 @@ -250,7 +250,7 @@ importers: version: 18.3.7(@types/react@18.3.29) '@vitejs/plugin-react': specifier: ^4.3.2 - version: 4.7.0(vite@5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0)) + version: 4.7.0(vite@5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0)) autoprefixer: specifier: ^10.4.20 version: 10.5.0(postcss@8.5.15) @@ -268,10 +268,10 @@ importers: version: 5.9.3 vite: specifier: ^5.4.8 - version: 5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0) + version: 5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0) vitest: specifier: ^2.1.2 - version: 2.1.9(@types/node@20.19.41)(jsdom@25.0.1(canvas@2.11.2))(lightningcss@1.32.0)(msw@2.14.6(@types/node@20.19.41)(typescript@5.9.3))(terser@5.48.0) + version: 2.1.9(@types/node@24.13.0)(jsdom@25.0.1(canvas@2.11.2))(lightningcss@1.32.0)(msw@2.14.6(@types/node@24.13.0)(typescript@5.9.3))(terser@5.48.0) apps/edr-freight-web/portal: dependencies: @@ -341,7 +341,7 @@ importers: version: link:../../../packages/config/tsconfig '@tailwindcss/vite': specifier: ^4.3.0 - version: 4.3.0(vite@5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0)) + version: 4.3.0(vite@5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0)) '@types/react': specifier: ^18.3.11 version: 18.3.29 @@ -350,7 +350,7 @@ importers: version: 18.3.7(@types/react@18.3.29) '@vitejs/plugin-react': specifier: ^4.3.2 - version: 4.7.0(vite@5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0)) + version: 4.7.0(vite@5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0)) autoprefixer: specifier: ^10.4.20 version: 10.5.0(postcss@8.5.15) @@ -368,10 +368,10 @@ importers: version: 5.9.3 vite: specifier: ^5.4.8 - version: 5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0) + version: 5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0) vitest: specifier: ^2.1.2 - version: 2.1.9(@types/node@20.19.41)(jsdom@25.0.1(canvas@2.11.2))(lightningcss@1.32.0)(msw@2.14.6(@types/node@20.19.41)(typescript@5.9.3))(terser@5.48.0) + version: 2.1.9(@types/node@24.13.0)(jsdom@25.0.1(canvas@2.11.2))(lightningcss@1.32.0)(msw@2.14.6(@types/node@24.13.0)(typescript@5.9.3))(terser@5.48.0) apps/edr-passenger-api: dependencies: @@ -456,7 +456,7 @@ importers: version: 7.2.2 ts-jest: specifier: ^29.2.5 - version: 29.4.11(@babel/core@7.29.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.29.0))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.11(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.4.1(@babel/core@7.29.0))(jest-util@30.4.1)(jest@29.7.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)))(typescript@5.9.3) ts-loader: specifier: ^9.5.1 version: 9.5.7(typescript@5.9.3)(webpack@5.106.0) @@ -514,7 +514,7 @@ importers: version: 18.3.7(@types/react@18.3.29) '@vitejs/plugin-react': specifier: ^4.3.2 - version: 4.7.0(vite@5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0)) + version: 4.7.0(vite@5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0)) autoprefixer: specifier: ^10.4.20 version: 10.5.0(postcss@8.5.15) @@ -532,10 +532,10 @@ importers: version: 5.9.3 vite: specifier: ^5.4.8 - version: 5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0) + version: 5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0) vitest: specifier: ^2.1.2 - version: 2.1.9(@types/node@20.19.41)(jsdom@25.0.1(canvas@2.11.2))(lightningcss@1.32.0)(msw@2.14.6(@types/node@20.19.41)(typescript@5.9.3))(terser@5.48.0) + version: 2.1.9(@types/node@24.13.0)(jsdom@25.0.1(canvas@2.11.2))(lightningcss@1.32.0)(msw@2.14.6(@types/node@24.13.0)(typescript@5.9.3))(terser@5.48.0) apps/edr-passenger-web/portal: dependencies: @@ -581,7 +581,7 @@ importers: version: 18.3.7(@types/react@18.3.29) '@vitejs/plugin-react': specifier: ^4.3.2 - version: 4.7.0(vite@5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0)) + version: 4.7.0(vite@5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0)) autoprefixer: specifier: ^10.4.20 version: 10.5.0(postcss@8.5.15) @@ -599,10 +599,110 @@ importers: version: 5.9.3 vite: specifier: ^5.4.8 - version: 5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0) + version: 5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0) vitest: specifier: ^2.1.2 - version: 2.1.9(@types/node@20.19.41)(jsdom@25.0.1(canvas@2.11.2))(lightningcss@1.32.0)(msw@2.14.6(@types/node@20.19.41)(typescript@5.9.3))(terser@5.48.0) + version: 2.1.9(@types/node@24.13.0)(jsdom@25.0.1(canvas@2.11.2))(lightningcss@1.32.0)(msw@2.14.6(@types/node@24.13.0)(typescript@5.9.3))(terser@5.48.0) + + apps/edr-payment-webhook: + dependencies: + '@nestjs/axios': + specifier: ^4.0.1 + version: 4.0.1(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.17.0)(rxjs@7.8.2) + '@nestjs/common': + specifier: ^11.0.1 + version: 11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/config': + specifier: ^4.0.0 + version: 4.0.4(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(rxjs@7.8.2) + '@nestjs/core': + specifier: ^11.0.1 + version: 11.1.23(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/microservices@11.1.23)(@nestjs/platform-express@11.1.23)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/platform-express': + specifier: ^11.0.1 + version: 11.1.23(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.23) + '@nestjs/swagger': + specifier: ^11.4.2 + version: 11.4.4(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.23)(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2) + axios: + specifier: ^1.17.0 + version: 1.17.0 + reflect-metadata: + specifier: ^0.2.2 + version: 0.2.2 + rxjs: + specifier: ^7.8.1 + version: 7.8.2 + devDependencies: + '@eslint/eslintrc': + specifier: ^3.2.0 + version: 3.3.5 + '@eslint/js': + specifier: ^9.18.0 + version: 9.39.4 + '@nestjs/cli': + specifier: ^11.0.0 + version: 11.0.21(@types/node@24.13.0)(prettier@3.8.3) + '@nestjs/schematics': + specifier: ^11.0.0 + version: 11.1.0(chokidar@4.0.3)(prettier@3.8.3)(typescript@5.9.3) + '@nestjs/testing': + specifier: ^11.0.1 + version: 11.1.23(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.23)(@nestjs/microservices@11.1.23)(@nestjs/platform-express@11.1.23) + '@types/express': + specifier: ^5.0.0 + version: 5.0.6 + '@types/jest': + specifier: ^30.0.0 + version: 30.0.0 + '@types/node': + specifier: ^24.0.0 + version: 24.13.0 + '@types/supertest': + specifier: ^7.0.0 + version: 7.2.0 + eslint: + specifier: ^9.18.0 + version: 9.39.4(jiti@2.7.0) + eslint-config-prettier: + specifier: ^10.0.1 + version: 10.1.8(eslint@9.39.4(jiti@2.7.0)) + eslint-plugin-prettier: + specifier: ^5.2.2 + version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0))(prettier@3.8.3) + globals: + specifier: ^17.0.0 + version: 17.6.0 + jest: + specifier: ^30.0.0 + version: 30.4.2(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)) + prettier: + specifier: ^3.4.2 + version: 3.8.3 + source-map-support: + specifier: ^0.5.21 + version: 0.5.21 + supertest: + specifier: ^7.0.0 + version: 7.2.2 + ts-jest: + specifier: ^29.2.5 + version: 29.4.11(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.4.1(@babel/core@7.29.0))(jest-util@30.4.1)(jest@30.4.2(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)))(typescript@5.9.3) + ts-loader: + specifier: ^9.5.2 + version: 9.5.7(typescript@5.9.3)(webpack@5.106.0) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@24.13.0)(typescript@5.9.3) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.7.3 + version: 5.9.3 + typescript-eslint: + specifier: ^8.20.0 + version: 8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) packages/api-common: dependencies: @@ -703,7 +803,7 @@ importers: version: 1.4.3(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) shadcn: specifier: ^4.7.0 - version: 4.8.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(typescript@5.9.3) + version: 4.8.0(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(typescript@5.9.3) tailwind-merge: specifier: ^3.6.0 version: 3.6.0 @@ -1130,6 +1230,15 @@ packages: peerDependencies: '@noble/ciphers': ^1.0.0 + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@emotion/babel-plugin@11.13.5': resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} @@ -1332,14 +1441,42 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint/config-array@0.21.2': + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@2.1.4': resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/eslintrc@3.3.5': + resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@8.57.1': resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/js@9.39.4': + resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@faker-js/faker@10.4.0': resolution: {integrity: sha512-sDBWI3yLy8EcDzgobvJTWq1MJYzAkQdpjXuPukga9wXonhpMRvd1Izuo2Qgwey2OiEoRIBr35RMU9HJRoOHzpw==} engines: {node: ^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0, npm: '>=10'} @@ -1388,6 +1525,18 @@ packages: peerDependencies: react-hook-form: ^7.55.0 + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + '@humanwhocodes/config-array@0.13.0': resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} @@ -1401,6 +1550,10 @@ packages: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + '@inquirer/ansi@1.0.2': resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} engines: {node: '>=18'} @@ -1601,6 +1754,10 @@ packages: resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/console@30.4.1': + resolution: {integrity: sha512-v3bhyxUh9Hgmo5p6hAOXe14/R3ZxZDOsvHleh4B07z3m/x4/ngPUXEm9XwK4sF4u+f+P2ORb0Ge+MgpaqRMVDA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/core@29.7.0': resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1610,26 +1767,67 @@ packages: node-notifier: optional: true + '@jest/core@30.4.2': + resolution: {integrity: sha512-TZJA6cPJUFxoWhxaLo8t0VX/MZX2wPWr0uIDvLSHIvN4gu9h02vSzqI2kBADG1ExqQlC+cY09xKMSreivvrChQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/diff-sequences@30.4.0': + resolution: {integrity: sha512-zOpzlfUs45l6u7jm39qr87JCHUDsaeCtvL+kQe/Vn9jSnRB4/5IPXISm0h9I1vZW/o00Kn4UTJ2MOlhnUGwv3g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/environment@29.7.0': resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/environment@30.4.1': + resolution: {integrity: sha512-AK9yNRqgKxiabqMoe4oW+3/TSSeV8vkdC7BGaxZdU0AFXfOpofTLqdru2GXKZghP3sdgwE9XXpnVwfZ8JnFV4w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/expect-utils@29.7.0': resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/expect-utils@30.4.1': + resolution: {integrity: sha512-ZBn5CglH8fBsQsvs4VWNzD4aWfUYks+IdOOQU3MEK71ol/BcVm+P+rtb1KpiFBpSWSCE27uOahyyf1vfqOVbcQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/expect@29.7.0': resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/expect@30.4.1': + resolution: {integrity: sha512-ginrj6TMgh2GshLUGCjO94Ptx9HhdZA/I6A9iUfyeLKFtdAjnKzHDgzgP9HYQgbxM1lbXScQ2eUBz2lGeVDPWA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/fake-timers@29.7.0': resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/fake-timers@30.4.1': + resolution: {integrity: sha512-iW5umdmfPeWzehrVhugFQZqCchSCud5S1l2YT0O9ZhjRR0ExclANDZkiSBwzqtnlOn0J1JXvO+HZ6rkuyOVOgQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/get-type@30.1.0': + resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/globals@29.7.0': resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/globals@30.4.1': + resolution: {integrity: sha512-ZbuY4cmXC8DkxYjfvT2DbcHWL2T6vmsMhXCDcmTB2T0y0gaezBI77ufq5ZAIdcRkYZ7NEQEDg1xFeKbxUJ5v5Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/pattern@30.4.0': + resolution: {integrity: sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/reporters@29.7.0': resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1639,30 +1837,67 @@ packages: node-notifier: optional: true + '@jest/reporters@30.4.1': + resolution: {integrity: sha512-/SnkPCzEQpUaBH81kjdEdDdo2WZl5hxw+BmLDGWjRkm8o7XlhjwsU36cqwe5PGBE5WYpBvDzRSdXx9rbGuJtNA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + '@jest/schemas@29.6.3': resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/schemas@30.4.1': + resolution: {integrity: sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/snapshot-utils@30.4.1': + resolution: {integrity: sha512-ObY4ljvQ95mt6iwKtVLetR/4yXiAgl3H4nJxhztr0MTjrN97TwDYrnCp/kF60Ec9HdhkWTHSu+Hg05aXfngpOA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/source-map@29.6.3': resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/source-map@30.0.1': + resolution: {integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/test-result@29.7.0': resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/test-result@30.4.1': + resolution: {integrity: sha512-/ZG7pgEiOmmWkN9TplKbOu4id2N5lh7FHwRwlkgBVAzGdRH+OkkQ8wX/kIxg4zmd3ZQvAL1RwL2yWsvNYYECTw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/test-sequencer@29.7.0': resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/test-sequencer@30.4.1': + resolution: {integrity: sha512-PeYE+4td5rKjoRPxztObrXU+H8hsjZfxKMXOcmrr34JerSyB/ROOxbbicz8B7A5j9R9VayDnVPvBmedqCsFCdw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/transform@29.7.0': resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/transform@30.4.1': + resolution: {integrity: sha512-Wz0LyktlTvRefoymh+n64hQ84KNXsRGcwdoZ8CSa0Ea+fgYcHZlnk+hDP7v2MS7il2bQ5uTEIxf4/NNfhMN4KQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/types@29.6.3': resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/types@30.4.1': + resolution: {integrity: sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -1883,6 +2118,12 @@ packages: moment-jalaali: optional: true + '@napi-rs/wasm-runtime@1.1.4': + resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + '@nestjs/axios@4.0.1': resolution: {integrity: sha512-68pFJgu+/AZbWkGu65Z3r55bTsCPlgyKaV4BSG8yUAD72q1PPuyVRgUwFv6BxdnibTUHlyxm06FmYWNC+bjN7A==} peerDependencies: @@ -2208,6 +2449,10 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@pkgr/core@0.3.6': + resolution: {integrity: sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==} + engines: {node: ^14.18.0 || >=16.0.0} + '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} @@ -3296,6 +3541,9 @@ packages: '@sinclair/typebox@0.27.10': resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} + '@sinclair/typebox@0.34.49': + resolution: {integrity: sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==} + '@sindresorhus/merge-streams@4.0.0': resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} @@ -3306,6 +3554,9 @@ packages: '@sinonjs/fake-timers@10.3.0': resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@sinonjs/fake-timers@15.4.0': + resolution: {integrity: sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==} + '@socket.io/component-emitter@3.1.2': resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} @@ -3738,6 +3989,9 @@ packages: cpu: [arm64] os: [win32] + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + '@types/amqplib@0.10.8': resolution: {integrity: sha512-vtDp8Pk1wsE/AuQ8/Rgtm6KUZYqcnTgNvEHwzCkX8rL7AGsC6zqAfKAAJhUZXFhM/Pp++tbnUHiam/8vVpPztA==} @@ -3833,6 +4087,9 @@ packages: '@types/jest@29.5.14': resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + '@types/jest@30.0.0': + resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -3857,6 +4114,9 @@ packages: '@types/node@20.19.41': resolution: {integrity: sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ==} + '@types/node@24.13.0': + resolution: {integrity: sha512-5vtOqGQr4NJKeEzV441FcOi2MeG9UTWq9LqVLGneDdu4vlX17H8kQ2PA2UmNwCUGPVDj4oBjNhS7ReVEIWJJrg==} + '@types/pako@2.0.4': resolution: {integrity: sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==} @@ -3912,6 +4172,9 @@ packages: '@types/supertest@6.0.3': resolution: {integrity: sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==} + '@types/supertest@7.2.0': + resolution: {integrity: sha512-uh2Lv57xvggst6lCqNdFAmDSvoMG7M/HDtX4iUCquxQ5EGPtaPM5PL5Hmi7LCvOG8db7YaCPNJEeoI8s/WzIQw==} + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -3941,6 +4204,14 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/eslint-plugin@8.60.1': + resolution: {integrity: sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.60.1 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/parser@8.59.4': resolution: {integrity: sha512-zORHqO/tuhxY1zWuTvMUqddRxpiFJ72xVfcNoWpqdLjs6lfPbuQBJuW4pk+49/uBMy7Ssr4bzgjiKmmDB1UbZQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3948,22 +4219,45 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/parser@8.60.1': + resolution: {integrity: sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/project-service@8.59.4': resolution: {integrity: sha512-Ly00Vu4oAacfDeHp2Zg85ioNG6l8HG+tN1D7J+xTHSxu9y0awYKJ2zH1rFBn8ZSfuGK+7FxK3Cgl3uAz0aZZLg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/project-service@8.60.1': + resolution: {integrity: sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/scope-manager@8.59.4': resolution: {integrity: sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.60.1': + resolution: {integrity: sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.59.4': resolution: {integrity: sha512-DLCpnKgD4alVxTBSKulK+gU1KCqOgUXfDRDXh2mZgzokQKa/70ax93I2uVO3m/LLvIAtWZIFoiifudmIqAxpMA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/tsconfig-utils@8.60.1': + resolution: {integrity: sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/type-utils@8.59.4': resolution: {integrity: sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3971,16 +4265,33 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/type-utils@8.60.1': + resolution: {integrity: sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/types@8.59.4': resolution: {integrity: sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.60.1': + resolution: {integrity: sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.59.4': resolution: {integrity: sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/typescript-estree@8.60.1': + resolution: {integrity: sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@8.59.4': resolution: {integrity: sha512-cYXeNAUsG4lJo5dbc1FcKm+JwIWrj1/UpTORsC6tGMjEZ81DYcvIr9/ueikhMa/Y/gDQYGp+YX9/xQrXje5BJw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3988,13 +4299,134 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@8.60.1': + resolution: {integrity: sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/visitor-keys@8.59.4': resolution: {integrity: sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.60.1': + resolution: {integrity: sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.1': resolution: {integrity: sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==} + '@unrs/resolver-binding-android-arm-eabi@1.12.2': + resolution: {integrity: sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.12.2': + resolution: {integrity: sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.12.2': + resolution: {integrity: sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.12.2': + resolution: {integrity: sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.12.2': + resolution: {integrity: sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': + resolution: {integrity: sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': + resolution: {integrity: sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': + resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-musl@1.12.2': + resolution: {integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': + resolution: {integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==} + cpu: [loong64] + os: [linux] + + '@unrs/resolver-binding-linux-loong64-musl@1.12.2': + resolution: {integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==} + cpu: [loong64] + os: [linux] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': + resolution: {integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==} + cpu: [ppc64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': + resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': + resolution: {integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': + resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==} + cpu: [s390x] + os: [linux] + + '@unrs/resolver-binding-linux-x64-gnu@1.12.2': + resolution: {integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-linux-x64-musl@1.12.2': + resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-openharmony-arm64@1.12.2': + resolution: {integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==} + cpu: [arm64] + os: [openharmony] + + '@unrs/resolver-binding-wasm32-wasi@1.12.2': + resolution: {integrity: sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': + resolution: {integrity: sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': + resolution: {integrity: sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.12.2': + resolution: {integrity: sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==} + cpu: [x64] + os: [win32] + '@vitejs/plugin-react@4.7.0': resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} engines: {node: ^14.18.0 || >=16.0.0} @@ -4746,14 +5178,28 @@ packages: peerDependencies: '@babel/core': ^7.8.0 + babel-jest@30.4.1: + resolution: {integrity: sha512-fATAbM8piYxkiXQp3RBXmZHxZVNJZAVXXfyeyCN2Tida3+qJ8ea9UxhiJ2y4fLO90ZImKt6k9FlcH2+rLkJGhw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 || ^8.0.0-0 + babel-plugin-istanbul@6.1.1: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} + babel-plugin-istanbul@7.0.1: + resolution: {integrity: sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==} + engines: {node: '>=12'} + babel-plugin-jest-hoist@29.6.3: resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + babel-plugin-jest-hoist@30.4.0: + resolution: {integrity: sha512-9EdtWM/sSfXLOGLwSn+GS6pIXyBnL07/8gyJlwFXjWy4DxMOyItqyUT29d4lQiS380EZwYlX7/At4PgBS+m2aA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} @@ -4769,6 +5215,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0 + babel-preset-jest@30.4.0: + resolution: {integrity: sha512-lBY4jxsNmCnSiu7kquw8ZC9F4+XLMOKypT3RnNHPvU2Kpd4W0xaPuLr5ZkRyOsvLYAY4yaW1ZwTW4xB7NIiZzg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 || ^8.0.0-beta.1 + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -5053,9 +5505,16 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + cjs-module-lexer@1.4.3: resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + cjs-module-lexer@2.2.0: + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} + class-transformer@0.5.1: resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==} @@ -5823,6 +6282,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + eslint-config-prettier@10.1.8: + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' escodegen@2.1.0: resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} engines: {node: '>=6.0'} @@ -5868,6 +6332,20 @@ packages: '@typescript-eslint/parser': optional: true + eslint-plugin-prettier@5.5.6: + resolution: {integrity: sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + eslint-plugin-react-hooks@4.6.2: resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} engines: {node: '>=10'} @@ -5893,10 +6371,18 @@ packages: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@5.0.1: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} @@ -5907,6 +6393,20 @@ packages: deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true + eslint@9.39.4: + resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5991,6 +6491,10 @@ packages: resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} engines: {node: ^18.19.0 || >=20.5.0} + exit-x@0.2.2: + resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} + engines: {node: '>= 0.8.0'} + exit@0.1.2: resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} engines: {node: '>= 0.8.0'} @@ -6007,6 +6511,10 @@ packages: resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + expect@30.4.1: + resolution: {integrity: sha512-PMARsyh/JtqC20HoGqlFcIlQAyqUtW4PlI1rup1uhYJtKuwAjbvWi3GQMAn+STdHum/dk8xrKfUM1+5SAwpolA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + express-rate-limit@8.5.2: resolution: {integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==} engines: {node: '>= 16'} @@ -6045,6 +6553,9 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + fast-equals@5.4.0: resolution: {integrity: sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==} engines: {node: '>=6.0.0'} @@ -6117,6 +6628,10 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + file-selector@2.1.2: resolution: {integrity: sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==} engines: {node: '>= 12'} @@ -6164,6 +6679,10 @@ packages: resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} engines: {node: ^10.12.0 || >=12.0.0} + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + flat@5.0.2: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true @@ -6410,6 +6929,14 @@ packages: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@17.6.0: + resolution: {integrity: sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==} + engines: {node: '>=18'} + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -7009,6 +7536,10 @@ packages: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} engines: {node: '>=10'} + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + istanbul-reports@3.2.0: resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} @@ -7031,10 +7562,18 @@ packages: resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-changed-files@30.4.1: + resolution: {integrity: sha512-IuctmYrxi21iOSOaIXpJWalHyPAsVv0GeBHKDn8C1CA4W5htHn7INL+wdnL4Bo0+olEndvAFkmb++tIQJG+vvg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-circus@29.7.0: resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-circus@30.4.2: + resolution: {integrity: sha512-rvHH7VlY6LgbJXJTQ87GW62g1FntOtbhh0zT+v04kC+pgL6aBKyYINXxWukCpj3dcIBMw5/XUbtDS9dU9JTXeQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-cli@29.7.0: resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7045,6 +7584,16 @@ packages: node-notifier: optional: true + jest-cli@30.4.2: + resolution: {integrity: sha512-jfA2ocvVHMXS2QijrJ0d31ektP+d/W0T5RpcTX2Pq+3sVqHlsXVCM2+FmwpL+bdY8OfHpIg9xMxLF17Zg0U49Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + jest-config@29.7.0: resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7057,22 +7606,53 @@ packages: ts-node: optional: true + jest-config@30.4.2: + resolution: {integrity: sha512-rNHAShJQqQwFNoL0hbf3BphSBOWnpOUAKvidLS/AjNVLPfoj5mSf4jQMfW3cYOs6hXeZC7nF7mDHaBnbxELOzg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@types/node': '*' + esbuild-register: '>=3.4.0' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + esbuild-register: + optional: true + ts-node: + optional: true + jest-diff@29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-diff@30.4.1: + resolution: {integrity: sha512-CRpFK0RtLriVDGcPPAnR6HMVI8bSR2jnUIgralhauzYQZIb4RH9AtEInTuQr65LmmGggGcRT6HIASxwqsVsmlA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-docblock@29.7.0: resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-docblock@30.4.0: + resolution: {integrity: sha512-ZPMabUZCx5MpbZ2eBYSvZ0J8fvo3dR9oM+eeUpb3aKNQFuS2tu3Duw1TNlMoP8k3WQgKGJuhcMFvwcVuq6T7oA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-each@29.7.0: resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-each@30.4.1: + resolution: {integrity: sha512-/8MJbH6fuj48TstjrMf+u/pd06Qezz5xOXvZA6442heNOWr8bdeoGZX2d9fCn028CoMgYmroH9//zky5GfyYmA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-environment-node@29.7.0: resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-environment-node@30.4.1: + resolution: {integrity: sha512-4FZYVOk85hz2AyT6BbarKy9u37g6DbrDyCdFhsnDdXqyrueYQvB+0zO4f/kqLCRD0BsPRXPMNJeQwihKZV8naw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-get-type@29.6.3: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7081,22 +7661,42 @@ packages: resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-haste-map@30.4.1: + resolution: {integrity: sha512-rFrcONd8jeFsyw+Z9CrScJgglRf2+NFmNam8dKu7n+SoHqNYT47mn0DdEcVUZJpvh7Iz6/si7f7yUH7GJHVgnw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-leak-detector@29.7.0: resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-leak-detector@30.4.1: + resolution: {integrity: sha512-IpmyiioeHxiWDhesHnUFmOxcTzwCwKpgACgWajtAP+nYQXiY7DakTxB6Bx9JFiRMljr0AX1PvnQdaU1KFoz6NQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-matcher-utils@29.7.0: resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-matcher-utils@30.4.1: + resolution: {integrity: sha512-zvYfX5CaeEkFrrLS9suWe9rvJrm9J1Iv3ua8kIBv9GEPzcnsfBf0bob37la7s67fs0nlBC3EuvkOLnXQKxtx4A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-message-util@29.7.0: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-message-util@30.4.1: + resolution: {integrity: sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-mock@29.7.0: resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-mock@30.4.1: + resolution: {integrity: sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-pnp-resolver@1.2.3: resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} engines: {node: '>=6'} @@ -7110,38 +7710,74 @@ packages: resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-regex-util@30.4.0: + resolution: {integrity: sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-resolve-dependencies@29.7.0: resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-resolve-dependencies@30.4.2: + resolution: {integrity: sha512-gDiVh1I+GxYzz9oXlyw+1wv6VOYX1WYxMOfjsA3iGKePV2oxmbHhwxfkALxNxYy1ciw6APWwkW2zZONwP97aEQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-resolve@29.7.0: resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-resolve@30.4.1: + resolution: {integrity: sha512-Zry8Yq/yJcNAZ7dJ5F2heic8AheXvbFZ7XI5V+h28nrYZ7Qoyy4dItq8OodjnYD270mvX+ZudmrNV9cysqhW5Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-runner@29.7.0: resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-runner@30.4.2: + resolution: {integrity: sha512-2dw0PslVYXxffXGpLo+Ejad+KcI1Qkjn7f4X4619gf21oCUmL+SPfjqIa/losUem3yEOvfNZe/F1HWUcNpODcg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-runtime@29.7.0: resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-runtime@30.4.2: + resolution: {integrity: sha512-3/5e8iPz2k/VLqlr8DgTftYyLUv8Su3FkCAO2/Od81UsUTpSxOrS6O5x5KkoQwyUjmpYyDJKeyAvg2T2nvpNkQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-snapshot@29.7.0: resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-snapshot@30.4.1: + resolution: {integrity: sha512-tEOkkfOMppUyeiHwjZswOQ3lcnoTnws/q5FnGIaeIh/jmoU0ZlgMYRR8sTlTj+nNGCoJ0RDq6SfxGxCsyMTPmw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-util@29.7.0: resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-util@30.4.1: + resolution: {integrity: sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-validate@29.7.0: resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-validate@30.4.1: + resolution: {integrity: sha512-PDWi4SOwLnwqNDfHZjOcsEFyZ4fc/2W2gVL3DEoyqnB6jCQMLRtfBong8s6omIw3lI0HWOus12xfnFmQtjW3fw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-watcher@29.7.0: resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-watcher@30.4.1: + resolution: {integrity: sha512-/l9UonmvCwjHH7d2h3iAwIloLc1H0S8mJZ/LNK3i86hqwPAz8otUJjP9MfYtz9Tt77Su5FD2xGjZn8d31IZHlw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-worker@27.5.1: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} @@ -7150,6 +7786,10 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-worker@30.4.1: + resolution: {integrity: sha512-SHynN/q/QD++iNyvMdy+WMmbCGk8jIsNcRxycXbWubSOhvo6T+j2afcfUSl+3hYsiBebOTo0cT7c2H7CXugu1g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest@29.7.0: resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7160,6 +7800,16 @@ packages: node-notifier: optional: true + jest@30.4.2: + resolution: {integrity: sha512-Yi1jqNC/Oq0N4hBgNH/YvBpP1P57QqundgytzYqy3yqAa7NZPNjSoi4SGbRAXDMdBzNE6xBCi5U7RgfrvMEUVQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + jiti@1.21.7: resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true @@ -7852,6 +8502,11 @@ packages: resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} engines: {node: '>=0.10.0'} + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -8392,6 +9047,10 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + prettier-linter-helpers@1.0.1: + resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==} + engines: {node: '>=6.0.0'} + prettier@3.8.3: resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==} engines: {node: '>=14'} @@ -8401,6 +9060,10 @@ packages: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + pretty-format@30.4.1: + resolution: {integrity: sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + pretty-ms@9.3.0: resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} engines: {node: '>=18'} @@ -8505,6 +9168,9 @@ packages: pure-rand@6.1.0: resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + pure-rand@7.0.1: + resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} + qrcode@1.5.4: resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} engines: {node: '>=10.13.0'} @@ -9442,6 +10108,10 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + synckit@0.11.13: + resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} + engines: {node: ^14.18.0 || >=16.0.0} + tabbable@6.4.0: resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} @@ -9904,6 +10574,13 @@ packages: typeorm-aurora-data-api-driver: optional: true + typescript-eslint@8.60.1: + resolution: {integrity: sha512-6m5hkkRAp8lKvhVpcprAIn5KkehQEh+47oHH2VGnExEh7dhNxXlg6GPAOIu6TxbVQxhebrJDvjl3020ooiWCMA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -9929,6 +10606,9 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + unicode-properties@1.4.1: resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==} @@ -9958,6 +10638,9 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} + unrs-resolver@1.12.2: + resolution: {integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==} + unset-value@1.0.0: resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} engines: {node: '>=0.10.0'} @@ -10312,6 +10995,10 @@ packages: resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + ws@8.20.1: resolution: {integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==} engines: {node: '>=10.0.0'} @@ -10502,6 +11189,18 @@ snapshots: - '@types/node' - chokidar + '@angular-devkit/schematics-cli@19.2.24(@types/node@24.13.0)(chokidar@4.0.3)': + dependencies: + '@angular-devkit/core': 19.2.24(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.24(chokidar@4.0.3) + '@inquirer/prompts': 7.3.2(@types/node@24.13.0) + ansi-colors: 4.1.3 + symbol-observable: 4.0.0 + yargs-parser: 21.1.1 + transitivePeerDependencies: + - '@types/node' + - chokidar + '@angular-devkit/schematics@19.2.24(chokidar@4.0.3)': dependencies: '@angular-devkit/core': 19.2.24(chokidar@4.0.3) @@ -10885,11 +11584,11 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@commitlint/cli@19.8.1(@types/node@20.19.41)(typescript@5.9.3)': + '@commitlint/cli@19.8.1(@types/node@24.13.0)(typescript@5.9.3)': dependencies: '@commitlint/format': 19.8.1 '@commitlint/lint': 19.8.1 - '@commitlint/load': 19.8.1(@types/node@20.19.41)(typescript@5.9.3) + '@commitlint/load': 19.8.1(@types/node@24.13.0)(typescript@5.9.3) '@commitlint/read': 19.8.1 '@commitlint/types': 19.8.1 tinyexec: 1.1.2 @@ -10936,7 +11635,7 @@ snapshots: '@commitlint/rules': 19.8.1 '@commitlint/types': 19.8.1 - '@commitlint/load@19.8.1(@types/node@20.19.41)(typescript@5.9.3)': + '@commitlint/load@19.8.1(@types/node@24.13.0)(typescript@5.9.3)': dependencies: '@commitlint/config-validator': 19.8.1 '@commitlint/execute-rule': 19.8.1 @@ -10944,7 +11643,7 @@ snapshots: '@commitlint/types': 19.8.1 chalk: 5.6.2 cosmiconfig: 9.0.1(typescript@5.9.3) - cosmiconfig-typescript-loader: 6.3.0(@types/node@20.19.41)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3) + cosmiconfig-typescript-loader: 6.3.0(@types/node@24.13.0)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -11039,6 +11738,22 @@ snapshots: dependencies: '@noble/ciphers': 1.3.0 + '@emnapi/core@1.10.0': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + '@emotion/babel-plugin@11.13.5': dependencies: '@babel/helper-module-imports': 7.28.6 @@ -11196,8 +11911,29 @@ snapshots: eslint: 8.57.1 eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.7.0))': + dependencies: + eslint: 9.39.4(jiti@2.7.0) + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.12.2': {} + '@eslint/config-array@0.21.2': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.15.0 @@ -11212,8 +11948,31 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/eslintrc@3.3.5': + dependencies: + ajv: 6.15.0 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + '@eslint/js@8.57.1': {} + '@eslint/js@9.39.4': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + '@faker-js/faker@10.4.0': {} '@fast-csv/format@4.3.5': @@ -11273,6 +12032,18 @@ snapshots: '@standard-schema/utils': 0.3.0 react-hook-form: 7.76.0(react@19.2.6) + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} + '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 @@ -11285,6 +12056,8 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@humanwhocodes/retry@0.4.3': {} + '@inquirer/ansi@1.0.2': {} '@inquirer/ansi@2.0.5': {} @@ -11299,6 +12072,16 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/checkbox@4.3.2(@types/node@24.13.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.2(@types/node@24.13.0) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@24.13.0) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/confirm@5.1.21(@types/node@20.19.41)': dependencies: '@inquirer/core': 10.3.2(@types/node@20.19.41) @@ -11306,12 +12089,19 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 - '@inquirer/confirm@6.0.13(@types/node@20.19.41)': + '@inquirer/confirm@5.1.21(@types/node@24.13.0)': dependencies: - '@inquirer/core': 11.1.10(@types/node@20.19.41) - '@inquirer/type': 4.0.5(@types/node@20.19.41) + '@inquirer/core': 10.3.2(@types/node@24.13.0) + '@inquirer/type': 3.0.10(@types/node@24.13.0) optionalDependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 + + '@inquirer/confirm@6.0.13(@types/node@24.13.0)': + dependencies: + '@inquirer/core': 11.1.10(@types/node@24.13.0) + '@inquirer/type': 4.0.5(@types/node@24.13.0) + optionalDependencies: + '@types/node': 24.13.0 '@inquirer/core@10.3.2(@types/node@20.19.41)': dependencies: @@ -11326,17 +12116,30 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 - '@inquirer/core@11.1.10(@types/node@20.19.41)': + '@inquirer/core@10.3.2(@types/node@24.13.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@24.13.0) + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 24.13.0 + + '@inquirer/core@11.1.10(@types/node@24.13.0)': dependencies: '@inquirer/ansi': 2.0.5 '@inquirer/figures': 2.0.5 - '@inquirer/type': 4.0.5(@types/node@20.19.41) + '@inquirer/type': 4.0.5(@types/node@24.13.0) cli-width: 4.1.0 fast-wrap-ansi: 0.2.2 mute-stream: 3.0.0 signal-exit: 4.1.0 optionalDependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 '@inquirer/editor@4.2.23(@types/node@20.19.41)': dependencies: @@ -11346,6 +12149,14 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/editor@4.2.23(@types/node@24.13.0)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@24.13.0) + '@inquirer/external-editor': 1.0.3(@types/node@24.13.0) + '@inquirer/type': 3.0.10(@types/node@24.13.0) + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/expand@4.0.23(@types/node@20.19.41)': dependencies: '@inquirer/core': 10.3.2(@types/node@20.19.41) @@ -11354,6 +12165,14 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/expand@4.0.23(@types/node@24.13.0)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@24.13.0) + '@inquirer/type': 3.0.10(@types/node@24.13.0) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/external-editor@1.0.3(@types/node@20.19.41)': dependencies: chardet: 2.1.1 @@ -11361,6 +12180,13 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/external-editor@1.0.3(@types/node@24.13.0)': + dependencies: + chardet: 2.1.1 + iconv-lite: 0.7.2 + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/figures@1.0.15': {} '@inquirer/figures@2.0.5': {} @@ -11372,6 +12198,13 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/input@4.3.1(@types/node@24.13.0)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@24.13.0) + '@inquirer/type': 3.0.10(@types/node@24.13.0) + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/number@3.0.23(@types/node@20.19.41)': dependencies: '@inquirer/core': 10.3.2(@types/node@20.19.41) @@ -11379,6 +12212,13 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/number@3.0.23(@types/node@24.13.0)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@24.13.0) + '@inquirer/type': 3.0.10(@types/node@24.13.0) + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/password@4.0.23(@types/node@20.19.41)': dependencies: '@inquirer/ansi': 1.0.2 @@ -11387,6 +12227,14 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/password@4.0.23(@types/node@24.13.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.2(@types/node@24.13.0) + '@inquirer/type': 3.0.10(@types/node@24.13.0) + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/prompts@7.10.1(@types/node@20.19.41)': dependencies: '@inquirer/checkbox': 4.3.2(@types/node@20.19.41) @@ -11402,6 +12250,21 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/prompts@7.10.1(@types/node@24.13.0)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@24.13.0) + '@inquirer/confirm': 5.1.21(@types/node@24.13.0) + '@inquirer/editor': 4.2.23(@types/node@24.13.0) + '@inquirer/expand': 4.0.23(@types/node@24.13.0) + '@inquirer/input': 4.3.1(@types/node@24.13.0) + '@inquirer/number': 3.0.23(@types/node@24.13.0) + '@inquirer/password': 4.0.23(@types/node@24.13.0) + '@inquirer/rawlist': 4.1.11(@types/node@24.13.0) + '@inquirer/search': 3.2.2(@types/node@24.13.0) + '@inquirer/select': 4.4.2(@types/node@24.13.0) + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/prompts@7.3.2(@types/node@20.19.41)': dependencies: '@inquirer/checkbox': 4.3.2(@types/node@20.19.41) @@ -11417,6 +12280,21 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/prompts@7.3.2(@types/node@24.13.0)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@24.13.0) + '@inquirer/confirm': 5.1.21(@types/node@24.13.0) + '@inquirer/editor': 4.2.23(@types/node@24.13.0) + '@inquirer/expand': 4.0.23(@types/node@24.13.0) + '@inquirer/input': 4.3.1(@types/node@24.13.0) + '@inquirer/number': 3.0.23(@types/node@24.13.0) + '@inquirer/password': 4.0.23(@types/node@24.13.0) + '@inquirer/rawlist': 4.1.11(@types/node@24.13.0) + '@inquirer/search': 3.2.2(@types/node@24.13.0) + '@inquirer/select': 4.4.2(@types/node@24.13.0) + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/rawlist@4.1.11(@types/node@20.19.41)': dependencies: '@inquirer/core': 10.3.2(@types/node@20.19.41) @@ -11425,6 +12303,14 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/rawlist@4.1.11(@types/node@24.13.0)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@24.13.0) + '@inquirer/type': 3.0.10(@types/node@24.13.0) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/search@3.2.2(@types/node@20.19.41)': dependencies: '@inquirer/core': 10.3.2(@types/node@20.19.41) @@ -11434,6 +12320,15 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/search@3.2.2(@types/node@24.13.0)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@24.13.0) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@24.13.0) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/select@4.4.2(@types/node@20.19.41)': dependencies: '@inquirer/ansi': 1.0.2 @@ -11444,13 +12339,27 @@ snapshots: optionalDependencies: '@types/node': 20.19.41 + '@inquirer/select@4.4.2(@types/node@24.13.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.2(@types/node@24.13.0) + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@24.13.0) + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 24.13.0 + '@inquirer/type@3.0.10(@types/node@20.19.41)': optionalDependencies: '@types/node': 20.19.41 - '@inquirer/type@4.0.5(@types/node@20.19.41)': + '@inquirer/type@3.0.10(@types/node@24.13.0)': optionalDependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 + + '@inquirer/type@4.0.5(@types/node@24.13.0)': + optionalDependencies: + '@types/node': 24.13.0 '@internationalized/date@3.12.0': dependencies: @@ -11482,12 +12391,21 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.19.41 + '@types/node': 24.13.0 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 + '@jest/console@30.4.1': + dependencies: + '@jest/types': 30.4.1 + '@types/node': 24.13.0 + chalk: 4.1.2 + jest-message-util: 30.4.1 + jest-util: 30.4.1 + slash: 3.0.0 + '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3))': dependencies: '@jest/console': 29.7.0 @@ -11495,14 +12413,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.19.41 + '@types/node': 24.13.0 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)) + jest-config: 29.7.0(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -11523,17 +12441,66 @@ snapshots: - supports-color - ts-node + '@jest/core@30.4.2(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3))': + dependencies: + '@jest/console': 30.4.1 + '@jest/pattern': 30.4.0 + '@jest/reporters': 30.4.1 + '@jest/test-result': 30.4.1 + '@jest/transform': 30.4.1 + '@jest/types': 30.4.1 + '@types/node': 24.13.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 4.4.0 + exit-x: 0.2.2 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-changed-files: 30.4.1 + jest-config: 30.4.2(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)) + jest-haste-map: 30.4.1 + jest-message-util: 30.4.1 + jest-regex-util: 30.4.0 + jest-resolve: 30.4.1 + jest-resolve-dependencies: 30.4.2 + jest-runner: 30.4.2 + jest-runtime: 30.4.2 + jest-snapshot: 30.4.1 + jest-util: 30.4.1 + jest-validate: 30.4.1 + jest-watcher: 30.4.1 + pretty-format: 30.4.1 + slash: 3.0.0 + transitivePeerDependencies: + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + '@jest/diff-sequences@30.4.0': {} + '@jest/environment@29.7.0': dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.19.41 + '@types/node': 24.13.0 jest-mock: 29.7.0 + '@jest/environment@30.4.1': + dependencies: + '@jest/fake-timers': 30.4.1 + '@jest/types': 30.4.1 + '@types/node': 24.13.0 + jest-mock: 30.4.1 + '@jest/expect-utils@29.7.0': dependencies: jest-get-type: 29.6.3 + '@jest/expect-utils@30.4.1': + dependencies: + '@jest/get-type': 30.1.0 + '@jest/expect@29.7.0': dependencies: expect: 29.7.0 @@ -11541,15 +12508,33 @@ snapshots: transitivePeerDependencies: - supports-color + '@jest/expect@30.4.1': + dependencies: + expect: 30.4.1 + jest-snapshot: 30.4.1 + transitivePeerDependencies: + - supports-color + '@jest/fake-timers@29.7.0': dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.19.41 + '@types/node': 24.13.0 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 + '@jest/fake-timers@30.4.1': + dependencies: + '@jest/types': 30.4.1 + '@sinonjs/fake-timers': 15.4.0 + '@types/node': 24.13.0 + jest-message-util: 30.4.1 + jest-mock: 30.4.1 + jest-util: 30.4.1 + + '@jest/get-type@30.1.0': {} + '@jest/globals@29.7.0': dependencies: '@jest/environment': 29.7.0 @@ -11559,6 +12544,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@jest/globals@30.4.1': + dependencies: + '@jest/environment': 30.4.1 + '@jest/expect': 30.4.1 + '@jest/types': 30.4.1 + jest-mock: 30.4.1 + transitivePeerDependencies: + - supports-color + + '@jest/pattern@30.4.0': + dependencies: + '@types/node': 24.13.0 + jest-regex-util: 30.4.0 + '@jest/reporters@29.7.0': dependencies: '@bcoe/v8-coverage': 0.2.3 @@ -11567,7 +12566,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.31 - '@types/node': 20.19.41 + '@types/node': 24.13.0 chalk: 4.1.2 collect-v8-coverage: 1.0.3 exit: 0.1.2 @@ -11588,16 +12587,61 @@ snapshots: transitivePeerDependencies: - supports-color + '@jest/reporters@30.4.1': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 30.4.1 + '@jest/test-result': 30.4.1 + '@jest/transform': 30.4.1 + '@jest/types': 30.4.1 + '@jridgewell/trace-mapping': 0.3.31 + '@types/node': 24.13.0 + chalk: 4.1.2 + collect-v8-coverage: 1.0.3 + exit-x: 0.2.2 + glob: 10.5.0 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + jest-message-util: 30.4.1 + jest-util: 30.4.1 + jest-worker: 30.4.1 + slash: 3.0.0 + string-length: 4.0.2 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + '@jest/schemas@29.6.3': dependencies: '@sinclair/typebox': 0.27.10 + '@jest/schemas@30.4.1': + dependencies: + '@sinclair/typebox': 0.34.49 + + '@jest/snapshot-utils@30.4.1': + dependencies: + '@jest/types': 30.4.1 + chalk: 4.1.2 + graceful-fs: 4.2.11 + natural-compare: 1.4.0 + '@jest/source-map@29.6.3': dependencies: '@jridgewell/trace-mapping': 0.3.31 callsites: 3.1.0 graceful-fs: 4.2.11 + '@jest/source-map@30.0.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + callsites: 3.1.0 + graceful-fs: 4.2.11 + '@jest/test-result@29.7.0': dependencies: '@jest/console': 29.7.0 @@ -11605,6 +12649,13 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 collect-v8-coverage: 1.0.3 + '@jest/test-result@30.4.1': + dependencies: + '@jest/console': 30.4.1 + '@jest/types': 30.4.1 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.3 + '@jest/test-sequencer@29.7.0': dependencies: '@jest/test-result': 29.7.0 @@ -11612,6 +12663,13 @@ snapshots: jest-haste-map: 29.7.0 slash: 3.0.0 + '@jest/test-sequencer@30.4.1': + dependencies: + '@jest/test-result': 30.4.1 + graceful-fs: 4.2.11 + jest-haste-map: 30.4.1 + slash: 3.0.0 + '@jest/transform@29.7.0': dependencies: '@babel/core': 7.29.0 @@ -11632,12 +12690,41 @@ snapshots: transitivePeerDependencies: - supports-color + '@jest/transform@30.4.1': + dependencies: + '@babel/core': 7.29.0 + '@jest/types': 30.4.1 + '@jridgewell/trace-mapping': 0.3.31 + babel-plugin-istanbul: 7.0.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 30.4.1 + jest-regex-util: 30.4.0 + jest-util: 30.4.1 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color + '@jest/types@29.6.3': dependencies: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.19.41 + '@types/node': 24.13.0 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + + '@jest/types@30.4.1': + dependencies: + '@jest/pattern': 30.4.0 + '@jest/schemas': 30.4.1 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 24.13.0 '@types/yargs': 17.0.35 chalk: 4.1.2 @@ -11885,12 +12972,25 @@ snapshots: transitivePeerDependencies: - '@types/react' + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.2 + optional: true + '@nestjs/axios@4.0.1(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.16.1)(rxjs@7.8.2)': dependencies: '@nestjs/common': 11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) axios: 1.16.1 rxjs: 7.8.2 + '@nestjs/axios@4.0.1(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.17.0)(rxjs@7.8.2)': + dependencies: + '@nestjs/common': 11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) + axios: 1.17.0 + rxjs: 7.8.2 + '@nestjs/cli@11.0.21(@types/node@20.19.41)(prettier@3.8.3)': dependencies: '@angular-devkit/core': 19.2.24(chokidar@4.0.3) @@ -11927,6 +13027,42 @@ snapshots: - uglify-js - webpack-cli + '@nestjs/cli@11.0.21(@types/node@24.13.0)(prettier@3.8.3)': + dependencies: + '@angular-devkit/core': 19.2.24(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.24(chokidar@4.0.3) + '@angular-devkit/schematics-cli': 19.2.24(@types/node@24.13.0)(chokidar@4.0.3) + '@inquirer/prompts': 7.10.1(@types/node@24.13.0) + '@nestjs/schematics': 11.1.0(chokidar@4.0.3)(prettier@3.8.3)(typescript@5.9.3) + ansis: 4.2.0 + chokidar: 4.0.3 + cli-table3: 0.6.5 + commander: 4.1.1 + fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.106.0) + glob: 13.0.6 + node-emoji: 1.11.0 + ora: 5.4.1 + tsconfig-paths: 4.2.0 + tsconfig-paths-webpack-plugin: 4.2.0 + typescript: 5.9.3 + webpack: 5.106.0 + webpack-node-externals: 3.0.0 + transitivePeerDependencies: + - '@minify-html/node' + - '@swc/css' + - '@swc/html' + - '@types/node' + - clean-css + - cssnano + - csso + - esbuild + - html-minifier-terser + - lightningcss + - postcss + - prettier + - uglify-js + - webpack-cli + '@nestjs/common@11.1.23(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 @@ -12174,6 +13310,8 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true + '@pkgr/core@0.3.6': {} + '@popperjs/core@2.11.8': {} '@puppeteer/browsers@2.13.2': @@ -13362,6 +14500,8 @@ snapshots: '@sinclair/typebox@0.27.10': {} + '@sinclair/typebox@0.34.49': {} + '@sindresorhus/merge-streams@4.0.0': {} '@sinonjs/commons@3.0.1': @@ -13372,6 +14512,10 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 + '@sinonjs/fake-timers@15.4.0': + dependencies: + '@sinonjs/commons': 3.0.1 + '@socket.io/component-emitter@3.1.2': {} '@sqltools/formatter@1.2.5': {} @@ -13464,12 +14608,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.3.0 '@tailwindcss/oxide-win32-x64-msvc': 4.3.0 - '@tailwindcss/vite@4.3.0(vite@5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0))': + '@tailwindcss/vite@4.3.0(vite@5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0))': dependencies: '@tailwindcss/node': 4.3.0 '@tailwindcss/oxide': 4.3.0 tailwindcss: 4.3.0 - vite: 5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0) + vite: 5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0) '@tanstack/query-core@5.100.11': {} @@ -13941,6 +15085,11 @@ snapshots: '@turbo/windows-arm64@2.9.14': optional: true + '@tybys/wasm-util@0.10.2': + dependencies: + tslib: 2.8.1 + optional: true + '@types/amqplib@0.10.8': dependencies: '@types/node': 20.19.41 @@ -13969,15 +15118,15 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.19.41 + '@types/node': 24.13.0 '@types/connect@3.4.38': dependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 '@types/conventional-commits-parser@5.0.2': dependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 '@types/cookiejar@2.1.5': {} @@ -14021,7 +15170,7 @@ snapshots: '@types/express-serve-static-core@5.1.1': dependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 '@types/qs': 6.15.1 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 @@ -14034,7 +15183,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 '@types/hoist-non-react-statics@3.3.7(@types/react@18.3.29)': dependencies: @@ -14058,6 +15207,11 @@ snapshots: expect: 29.7.0 pretty-format: 29.7.0 + '@types/jest@30.0.0': + dependencies: + expect: 30.4.1 + pretty-format: 30.4.1 + '@types/json-schema@7.0.15': {} '@types/json5@0.0.29': {} @@ -14065,7 +15219,7 @@ snapshots: '@types/jsonwebtoken@9.0.10': dependencies: '@types/ms': 2.1.0 - '@types/node': 20.19.41 + '@types/node': 24.13.0 '@types/methods@1.1.4': {} @@ -14081,6 +15235,10 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/node@24.13.0': + dependencies: + undici-types: 7.18.2 + '@types/pako@2.0.4': {} '@types/parse-json@4.0.2': {} @@ -14109,16 +15267,16 @@ snapshots: '@types/send@1.2.1': dependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 '@types/serve-static@2.2.0': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 20.19.41 + '@types/node': 24.13.0 '@types/set-cookie-parser@2.4.10': dependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 '@types/signature_pad@2.3.6': {} @@ -14130,7 +15288,7 @@ snapshots: dependencies: '@types/cookiejar': 2.1.5 '@types/methods': 1.1.4 - '@types/node': 20.19.41 + '@types/node': 24.13.0 form-data: 4.0.5 '@types/supertest@6.0.3': @@ -14138,6 +15296,11 @@ snapshots: '@types/methods': 1.1.4 '@types/superagent': 8.1.10 + '@types/supertest@7.2.0': + dependencies: + '@types/methods': 1.1.4 + '@types/superagent': 8.1.10 + '@types/trusted-types@2.0.7': optional: true @@ -14174,6 +15337,22 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/eslint-plugin@8.60.1(@typescript-eslint/parser@8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.60.1 + '@typescript-eslint/type-utils': 8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/utils': 8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.60.1 + eslint: 9.39.4(jiti@2.7.0) + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@8.59.4(eslint@8.57.1)(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.59.4 @@ -14186,6 +15365,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.60.1 + '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/typescript-estree': 8.60.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.60.1 + debug: 4.4.3 + eslint: 9.39.4(jiti@2.7.0) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/project-service@8.59.4(typescript@5.9.3)': dependencies: '@typescript-eslint/tsconfig-utils': 8.59.4(typescript@5.9.3) @@ -14195,15 +15386,33 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.60.1(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.60.1(typescript@5.9.3) + '@typescript-eslint/types': 8.60.1 + debug: 4.4.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@8.59.4': dependencies: '@typescript-eslint/types': 8.59.4 '@typescript-eslint/visitor-keys': 8.59.4 + '@typescript-eslint/scope-manager@8.60.1': + dependencies: + '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/visitor-keys': 8.60.1 + '@typescript-eslint/tsconfig-utils@8.59.4(typescript@5.9.3)': dependencies: typescript: 5.9.3 + '@typescript-eslint/tsconfig-utils@8.60.1(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + '@typescript-eslint/type-utils@8.59.4(eslint@8.57.1)(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.59.4 @@ -14216,8 +15425,22 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/typescript-estree': 8.60.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.39.4(jiti@2.7.0) + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/types@8.59.4': {} + '@typescript-eslint/types@8.60.1': {} + '@typescript-eslint/typescript-estree@8.59.4(typescript@5.9.3)': dependencies: '@typescript-eslint/project-service': 8.59.4(typescript@5.9.3) @@ -14233,6 +15456,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.60.1(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.60.1(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.60.1(typescript@5.9.3) + '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/visitor-keys': 8.60.1 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.8.1 + tinyglobby: 0.2.16 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.59.4(eslint@8.57.1)(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) @@ -14244,14 +15482,100 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.60.1 + '@typescript-eslint/types': 8.60.1 + '@typescript-eslint/typescript-estree': 8.60.1(typescript@5.9.3) + eslint: 9.39.4(jiti@2.7.0) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@8.59.4': dependencies: '@typescript-eslint/types': 8.59.4 eslint-visitor-keys: 5.0.1 + '@typescript-eslint/visitor-keys@8.60.1': + dependencies: + '@typescript-eslint/types': 8.60.1 + eslint-visitor-keys: 5.0.1 + '@ungap/structured-clone@1.3.1': {} - '@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0))': + '@unrs/resolver-binding-android-arm-eabi@1.12.2': + optional: true + + '@unrs/resolver-binding-android-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.12.2': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-loong64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-openharmony-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.12.2': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.12.2': + optional: true + + '@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) @@ -14259,7 +15583,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0) + vite: 5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0) transitivePeerDependencies: - supports-color @@ -14270,14 +15594,14 @@ snapshots: chai: 5.3.3 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.9(msw@2.14.6(@types/node@20.19.41)(typescript@5.9.3))(vite@5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0))': + '@vitest/mocker@2.1.9(msw@2.14.6(@types/node@24.13.0)(typescript@5.9.3))(vite@5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0))': dependencies: '@vitest/spy': 2.1.9 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - msw: 2.14.6(@types/node@20.19.41)(typescript@5.9.3) - vite: 5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0) + msw: 2.14.6(@types/node@24.13.0)(typescript@5.9.3) + vite: 5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0) '@vitest/pretty-format@2.1.9': dependencies: @@ -15420,6 +16744,15 @@ snapshots: - debug - supports-color + axios@1.17.0: + dependencies: + follow-redirects: 1.16.0 + form-data: 4.0.5 + https-proxy-agent: 5.0.1 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + - supports-color b4a@1.8.1: {} babel-jest@29.7.0(@babel/core@7.29.0): @@ -15435,6 +16768,19 @@ snapshots: transitivePeerDependencies: - supports-color + babel-jest@30.4.1(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@jest/transform': 30.4.1 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 7.0.1 + babel-preset-jest: 30.4.0(@babel/core@7.29.0) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + babel-plugin-istanbul@6.1.1: dependencies: '@babel/helper-plugin-utils': 7.28.6 @@ -15445,6 +16791,16 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-istanbul@7.0.1: + dependencies: + '@babel/helper-plugin-utils': 7.28.6 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-instrument: 6.0.3 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + babel-plugin-jest-hoist@29.6.3: dependencies: '@babel/template': 7.28.6 @@ -15452,6 +16808,10 @@ snapshots: '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.28.0 + babel-plugin-jest-hoist@30.4.0: + dependencies: + '@types/babel__core': 7.20.5 + babel-plugin-macros@3.1.0: dependencies: '@babel/runtime': 7.29.2 @@ -15483,6 +16843,12 @@ snapshots: babel-plugin-jest-hoist: 29.6.3 babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) + babel-preset-jest@30.4.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + babel-plugin-jest-hoist: 30.4.0 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) + balanced-match@1.0.2: {} balanced-match@4.0.4: {} @@ -15794,8 +17160,12 @@ snapshots: ci-info@3.9.0: {} + ci-info@4.4.0: {} + cjs-module-lexer@1.4.3: {} + cjs-module-lexer@2.2.0: {} + class-transformer@0.5.1: {} class-utils@0.3.6: @@ -16000,9 +17370,9 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 - cosmiconfig-typescript-loader@6.3.0(@types/node@20.19.41)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3): + cosmiconfig-typescript-loader@6.3.0(@types/node@24.13.0)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3): dependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 cosmiconfig: 9.0.1(typescript@5.9.3) jiti: 2.6.1 typescript: 5.9.3 @@ -16593,6 +17963,9 @@ snapshots: escape-string-regexp@4.0.0: {} + eslint-config-prettier@10.1.8(eslint@9.39.4(jiti@2.7.0)): + dependencies: + eslint: 9.39.4(jiti@2.7.0) escodegen@2.1.0: dependencies: esprima: 4.0.1 @@ -16652,6 +18025,16 @@ snapshots: - eslint-import-resolver-webpack - supports-color + eslint-plugin-prettier@5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0))(prettier@3.8.3): + dependencies: + eslint: 9.39.4(jiti@2.7.0) + prettier: 3.8.3 + prettier-linter-helpers: 1.0.1 + synckit: 0.11.13 + optionalDependencies: + '@types/eslint': 9.6.1 + eslint-config-prettier: 10.1.8(eslint@9.39.4(jiti@2.7.0)) + eslint-plugin-react-hooks@4.6.2(eslint@8.57.1): dependencies: eslint: 8.57.1 @@ -16692,8 +18075,15 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + eslint-visitor-keys@3.4.3: {} + eslint-visitor-keys@4.2.1: {} + eslint-visitor-keys@5.0.1: {} eslint@8.57.1: @@ -16739,6 +18129,53 @@ snapshots: transitivePeerDependencies: - supports-color + eslint@9.39.4(jiti@2.7.0): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.2 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.5 + '@eslint/js': 9.39.4 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 + ajv: 6.15.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.7.0 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 4.2.1 + espree@9.6.1: dependencies: acorn: 8.16.0 @@ -16842,6 +18279,8 @@ snapshots: strip-final-newline: 4.0.0 yoctocolors: 2.1.2 + exit-x@0.2.2: {} + exit@0.1.2: {} expand-brackets@2.1.4: @@ -16866,6 +18305,15 @@ snapshots: jest-message-util: 29.7.0 jest-util: 29.7.0 + expect@30.4.1: + dependencies: + '@jest/expect-utils': 30.4.1 + '@jest/get-type': 30.1.0 + jest-matcher-utils: 30.4.1 + jest-message-util: 30.4.1 + jest-mock: 30.4.1 + jest-util: 30.4.1 + express-rate-limit@8.5.2(express@5.2.1): dependencies: express: 5.2.1 @@ -16947,6 +18395,8 @@ snapshots: fast-deep-equal@3.1.3: {} + fast-diff@1.3.0: {} + fast-equals@5.4.0: {} fast-fifo@1.3.2: {} @@ -17018,6 +18468,10 @@ snapshots: dependencies: flat-cache: 3.2.0 + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + file-selector@2.1.2: dependencies: tslib: 2.8.1 @@ -17085,6 +18539,11 @@ snapshots: keyv: 4.5.4 rimraf: 3.0.2 + flat-cache@4.0.1: + dependencies: + flatted: 3.4.2 + keyv: 4.5.4 + flat@5.0.2: {} flatted@3.4.2: {} @@ -17352,6 +18811,10 @@ snapshots: dependencies: type-fest: 0.20.2 + globals@14.0.0: {} + + globals@17.6.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -17934,6 +19397,14 @@ snapshots: transitivePeerDependencies: - supports-color + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + istanbul-reports@3.2.0: dependencies: html-escaper: 2.0.2 @@ -17966,13 +19437,19 @@ snapshots: jest-util: 29.7.0 p-limit: 3.1.0 + jest-changed-files@30.4.1: + dependencies: + execa: 5.1.1 + jest-util: 30.4.1 + p-limit: 3.1.0 + jest-circus@29.7.0(babel-plugin-macros@3.1.0): dependencies: '@jest/environment': 29.7.0 '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.19.41 + '@types/node': 24.13.0 chalk: 4.1.2 co: 4.6.0 dedent: 1.7.2(babel-plugin-macros@3.1.0) @@ -17992,6 +19469,32 @@ snapshots: - babel-plugin-macros - supports-color + jest-circus@30.4.2(babel-plugin-macros@3.1.0): + dependencies: + '@jest/environment': 30.4.1 + '@jest/expect': 30.4.1 + '@jest/test-result': 30.4.1 + '@jest/types': 30.4.1 + '@types/node': 24.13.0 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.7.2(babel-plugin-macros@3.1.0) + is-generator-fn: 2.1.0 + jest-each: 30.4.1 + jest-matcher-utils: 30.4.1 + jest-message-util: 30.4.1 + jest-runtime: 30.4.2 + jest-snapshot: 30.4.1 + jest-util: 30.4.1 + p-limit: 3.1.0 + pretty-format: 30.4.1 + pure-rand: 7.0.1 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + jest-cli@29.7.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)): dependencies: '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)) @@ -18011,6 +19514,25 @@ snapshots: - supports-color - ts-node + jest-cli@30.4.2(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)): + dependencies: + '@jest/core': 30.4.2(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)) + '@jest/test-result': 30.4.1 + '@jest/types': 30.4.1 + chalk: 4.1.2 + exit-x: 0.2.2 + import-local: 3.2.0 + jest-config: 30.4.2(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)) + jest-util: 30.4.1 + jest-validate: 30.4.1 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + jest-config@29.7.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)): dependencies: '@babel/core': 7.29.0 @@ -18042,6 +19564,69 @@ snapshots: - babel-plugin-macros - supports-color + jest-config@29.7.0(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)): + dependencies: + '@babel/core': 7.29.0 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.29.0) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0(babel-plugin-macros@3.1.0) + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 24.13.0 + ts-node: 10.9.2(@types/node@20.19.41)(typescript@5.9.3) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-config@30.4.2(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)): + dependencies: + '@babel/core': 7.29.0 + '@jest/get-type': 30.1.0 + '@jest/pattern': 30.4.0 + '@jest/test-sequencer': 30.4.1 + '@jest/types': 30.4.1 + babel-jest: 30.4.1(@babel/core@7.29.0) + chalk: 4.1.2 + ci-info: 4.4.0 + deepmerge: 4.3.1 + glob: 10.5.0 + graceful-fs: 4.2.11 + jest-circus: 30.4.2(babel-plugin-macros@3.1.0) + jest-docblock: 30.4.0 + jest-environment-node: 30.4.1 + jest-regex-util: 30.4.0 + jest-resolve: 30.4.1 + jest-runner: 30.4.2 + jest-util: 30.4.1 + jest-validate: 30.4.1 + parse-json: 5.2.0 + pretty-format: 30.4.1 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 24.13.0 + ts-node: 10.9.2(@types/node@24.13.0)(typescript@5.9.3) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + jest-diff@29.7.0: dependencies: chalk: 4.1.2 @@ -18049,10 +19634,21 @@ snapshots: jest-get-type: 29.6.3 pretty-format: 29.7.0 + jest-diff@30.4.1: + dependencies: + '@jest/diff-sequences': 30.4.0 + '@jest/get-type': 30.1.0 + chalk: 4.1.2 + pretty-format: 30.4.1 + jest-docblock@29.7.0: dependencies: detect-newline: 3.1.0 + jest-docblock@30.4.0: + dependencies: + detect-newline: 3.1.0 + jest-each@29.7.0: dependencies: '@jest/types': 29.6.3 @@ -18061,22 +19657,40 @@ snapshots: jest-util: 29.7.0 pretty-format: 29.7.0 + jest-each@30.4.1: + dependencies: + '@jest/get-type': 30.1.0 + '@jest/types': 30.4.1 + chalk: 4.1.2 + jest-util: 30.4.1 + pretty-format: 30.4.1 + jest-environment-node@29.7.0: dependencies: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.19.41 + '@types/node': 24.13.0 jest-mock: 29.7.0 jest-util: 29.7.0 + jest-environment-node@30.4.1: + dependencies: + '@jest/environment': 30.4.1 + '@jest/fake-timers': 30.4.1 + '@jest/types': 30.4.1 + '@types/node': 24.13.0 + jest-mock: 30.4.1 + jest-util: 30.4.1 + jest-validate: 30.4.1 + jest-get-type@29.6.3: {} jest-haste-map@29.7.0: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.19.41 + '@types/node': 24.13.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -18088,11 +19702,31 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + jest-haste-map@30.4.1: + dependencies: + '@jest/types': 30.4.1 + '@types/node': 24.13.0 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 30.4.0 + jest-util: 30.4.1 + jest-worker: 30.4.1 + picomatch: 4.0.4 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + jest-leak-detector@29.7.0: dependencies: jest-get-type: 29.6.3 pretty-format: 29.7.0 + jest-leak-detector@30.4.1: + dependencies: + '@jest/get-type': 30.1.0 + pretty-format: 30.4.1 + jest-matcher-utils@29.7.0: dependencies: chalk: 4.1.2 @@ -18100,6 +19734,13 @@ snapshots: jest-get-type: 29.6.3 pretty-format: 29.7.0 + jest-matcher-utils@30.4.1: + dependencies: + '@jest/get-type': 30.1.0 + chalk: 4.1.2 + jest-diff: 30.4.1 + pretty-format: 30.4.1 + jest-message-util@29.7.0: dependencies: '@babel/code-frame': 7.29.0 @@ -18112,18 +19753,43 @@ snapshots: slash: 3.0.0 stack-utils: 2.0.6 + jest-message-util@30.4.1: + dependencies: + '@babel/code-frame': 7.29.0 + '@jest/types': 30.4.1 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-util: 30.4.1 + picomatch: 4.0.4 + pretty-format: 30.4.1 + slash: 3.0.0 + stack-utils: 2.0.6 + jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.19.41 + '@types/node': 24.13.0 jest-util: 29.7.0 + jest-mock@30.4.1: + dependencies: + '@jest/types': 30.4.1 + '@types/node': 24.13.0 + jest-util: 30.4.1 + jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): optionalDependencies: jest-resolve: 29.7.0 + jest-pnp-resolver@1.2.3(jest-resolve@30.4.1): + optionalDependencies: + jest-resolve: 30.4.1 + jest-regex-util@29.6.3: {} + jest-regex-util@30.4.0: {} + jest-resolve-dependencies@29.7.0: dependencies: jest-regex-util: 29.6.3 @@ -18131,6 +19797,13 @@ snapshots: transitivePeerDependencies: - supports-color + jest-resolve-dependencies@30.4.2: + dependencies: + jest-regex-util: 30.4.0 + jest-snapshot: 30.4.1 + transitivePeerDependencies: + - supports-color + jest-resolve@29.7.0: dependencies: chalk: 4.1.2 @@ -18143,6 +19816,17 @@ snapshots: resolve.exports: 2.0.3 slash: 3.0.0 + jest-resolve@30.4.1: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 30.4.1 + jest-pnp-resolver: 1.2.3(jest-resolve@30.4.1) + jest-util: 30.4.1 + jest-validate: 30.4.1 + slash: 3.0.0 + unrs-resolver: 1.12.2 + jest-runner@29.7.0: dependencies: '@jest/console': 29.7.0 @@ -18150,7 +19834,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.19.41 + '@types/node': 24.13.0 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -18169,6 +19853,33 @@ snapshots: transitivePeerDependencies: - supports-color + jest-runner@30.4.2: + dependencies: + '@jest/console': 30.4.1 + '@jest/environment': 30.4.1 + '@jest/test-result': 30.4.1 + '@jest/transform': 30.4.1 + '@jest/types': 30.4.1 + '@types/node': 24.13.0 + chalk: 4.1.2 + emittery: 0.13.1 + exit-x: 0.2.2 + graceful-fs: 4.2.11 + jest-docblock: 30.4.0 + jest-environment-node: 30.4.1 + jest-haste-map: 30.4.1 + jest-leak-detector: 30.4.1 + jest-message-util: 30.4.1 + jest-resolve: 30.4.1 + jest-runtime: 30.4.2 + jest-util: 30.4.1 + jest-watcher: 30.4.1 + jest-worker: 30.4.1 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + jest-runtime@29.7.0: dependencies: '@jest/environment': 29.7.0 @@ -18178,7 +19889,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.19.41 + '@types/node': 24.13.0 chalk: 4.1.2 cjs-module-lexer: 1.4.3 collect-v8-coverage: 1.0.3 @@ -18196,6 +19907,33 @@ snapshots: transitivePeerDependencies: - supports-color + jest-runtime@30.4.2: + dependencies: + '@jest/environment': 30.4.1 + '@jest/fake-timers': 30.4.1 + '@jest/globals': 30.4.1 + '@jest/source-map': 30.0.1 + '@jest/test-result': 30.4.1 + '@jest/transform': 30.4.1 + '@jest/types': 30.4.1 + '@types/node': 24.13.0 + chalk: 4.1.2 + cjs-module-lexer: 2.2.0 + collect-v8-coverage: 1.0.3 + glob: 10.5.0 + graceful-fs: 4.2.11 + jest-haste-map: 30.4.1 + jest-message-util: 30.4.1 + jest-mock: 30.4.1 + jest-regex-util: 30.4.0 + jest-resolve: 30.4.1 + jest-snapshot: 30.4.1 + jest-util: 30.4.1 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + jest-snapshot@29.7.0: dependencies: '@babel/core': 7.29.0 @@ -18221,15 +19959,50 @@ snapshots: transitivePeerDependencies: - supports-color + jest-snapshot@30.4.1: + dependencies: + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/types': 7.29.0 + '@jest/expect-utils': 30.4.1 + '@jest/get-type': 30.1.0 + '@jest/snapshot-utils': 30.4.1 + '@jest/transform': 30.4.1 + '@jest/types': 30.4.1 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) + chalk: 4.1.2 + expect: 30.4.1 + graceful-fs: 4.2.11 + jest-diff: 30.4.1 + jest-matcher-utils: 30.4.1 + jest-message-util: 30.4.1 + jest-util: 30.4.1 + pretty-format: 30.4.1 + semver: 7.8.1 + synckit: 0.11.13 + transitivePeerDependencies: + - supports-color + jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.19.41 + '@types/node': 24.13.0 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 picomatch: 2.3.2 + jest-util@30.4.1: + dependencies: + '@jest/types': 30.4.1 + '@types/node': 24.13.0 + chalk: 4.1.2 + ci-info: 4.4.0 + graceful-fs: 4.2.11 + picomatch: 4.0.4 + jest-validate@29.7.0: dependencies: '@jest/types': 29.6.3 @@ -18239,30 +20012,58 @@ snapshots: leven: 3.1.0 pretty-format: 29.7.0 + jest-validate@30.4.1: + dependencies: + '@jest/get-type': 30.1.0 + '@jest/types': 30.4.1 + camelcase: 6.3.0 + chalk: 4.1.2 + leven: 3.1.0 + pretty-format: 30.4.1 + jest-watcher@29.7.0: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.19.41 + '@types/node': 24.13.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 jest-util: 29.7.0 string-length: 4.0.2 + jest-watcher@30.4.1: + dependencies: + '@jest/test-result': 30.4.1 + '@jest/types': 30.4.1 + '@types/node': 24.13.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 30.4.1 + string-length: 4.0.2 + jest-worker@27.5.1: dependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 + jest-worker@30.4.1: + dependencies: + '@types/node': 24.13.0 + '@ungap/structured-clone': 1.3.1 + jest-util: 30.4.1 + merge-stream: 2.0.0 + supports-color: 8.1.1 + jest@29.7.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)): dependencies: '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)) @@ -18275,6 +20076,19 @@ snapshots: - supports-color - ts-node + jest@30.4.2(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)): + dependencies: + '@jest/core': 30.4.2(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)) + '@jest/types': 30.4.1 + import-local: 3.2.0 + jest-cli: 30.4.2(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + jiti@1.21.7: {} jiti@2.6.1: {} @@ -18891,9 +20705,9 @@ snapshots: ms@2.1.3: {} - msw@2.14.6(@types/node@20.19.41)(typescript@5.9.3): + msw@2.14.6(@types/node@24.13.0)(typescript@5.9.3): dependencies: - '@inquirer/confirm': 6.0.13(@types/node@20.19.41) + '@inquirer/confirm': 6.0.13(@types/node@24.13.0) '@mswjs/interceptors': 0.41.9 '@open-draft/deferred-promise': 3.0.0 '@types/statuses': 2.0.6 @@ -18965,6 +20779,8 @@ snapshots: transitivePeerDependencies: - supports-color + napi-postinstall@0.3.4: {} + natural-compare@1.4.0: {} negotiator@1.0.0: {} @@ -19476,6 +21292,10 @@ snapshots: prelude-ls@1.2.1: {} + prettier-linter-helpers@1.0.1: + dependencies: + fast-diff: 1.3.0 + prettier@3.8.3: {} pretty-format@29.7.0: @@ -19484,6 +21304,13 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 + pretty-format@30.4.1: + dependencies: + '@jest/schemas': 30.4.1 + ansi-styles: 5.2.0 + react-is-18: react-is@18.3.1 + react-is-19: react-is@19.2.6 + pretty-ms@9.3.0: dependencies: parse-ms: 4.0.0 @@ -19649,6 +21476,8 @@ snapshots: pure-rand@6.1.0: {} + pure-rand@7.0.1: {} + qrcode@1.5.4: dependencies: dijkstrajs: 1.0.3 @@ -20371,7 +22200,7 @@ snapshots: safe-buffer: 5.2.1 to-buffer: 1.2.2 - shadcn@4.8.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(typescript@5.9.3): + shadcn@4.8.0(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(typescript@5.9.3): dependencies: '@babel/core': 7.29.0 '@babel/parser': 7.29.3 @@ -20392,7 +22221,7 @@ snapshots: fuzzysort: 3.1.0 https-proxy-agent: 7.0.6 kleur: 4.1.5 - msw: 2.14.6(@types/node@20.19.41)(typescript@5.9.3) + msw: 2.14.6(@types/node@24.13.0)(typescript@5.9.3) node-fetch: 3.3.2 open: 11.0.0 ora: 8.2.0 @@ -20806,6 +22635,10 @@ snapshots: symbol-tree@3.2.4: {} + synckit@0.11.13: + dependencies: + '@pkgr/core': 0.3.6 + tabbable@6.4.0: {} tagged-tag@1.0.0: {} @@ -21086,7 +22919,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.4.11(@babel/core@7.29.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.29.0))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)))(typescript@5.9.3): + ts-jest@29.4.11(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.4.1(@babel/core@7.29.0))(jest-util@30.4.1)(jest@29.7.0(@types/node@20.19.41)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)))(typescript@5.9.3): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -21101,10 +22934,30 @@ snapshots: yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 7.29.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.29.0) - jest-util: 29.7.0 + '@jest/transform': 30.4.1 + '@jest/types': 30.4.1 + babel-jest: 30.4.1(@babel/core@7.29.0) + jest-util: 30.4.1 + + ts-jest@29.4.11(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.4.1(@babel/core@7.29.0))(jest-util@30.4.1)(jest@30.4.2(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)))(typescript@5.9.3): + dependencies: + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + handlebars: 4.7.9 + jest: 30.4.2(@types/node@24.13.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3)) + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.8.1 + type-fest: 4.41.0 + typescript: 5.9.3 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.29.0 + '@jest/transform': 30.4.1 + '@jest/types': 30.4.1 + babel-jest: 30.4.1(@babel/core@7.29.0) + jest-util: 30.4.1 ts-loader@9.5.7(typescript@5.9.3)(webpack@5.106.0): dependencies: @@ -21139,6 +22992,24 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 + ts-node@10.9.2(@types/node@24.13.0)(typescript@5.9.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.12 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 24.13.0 + acorn: 8.16.0 + acorn-walk: 8.3.5 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.4 + make-error: 1.3.6 + typescript: 5.9.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + tsconfig-paths-webpack-plugin@4.2.0: dependencies: chalk: 4.1.2 @@ -21277,6 +23148,17 @@ snapshots: - babel-plugin-macros - supports-color + typescript-eslint@8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.60.1(@typescript-eslint/parser@8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/parser': 8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.60.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.60.1(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + eslint: 9.39.4(jiti@2.7.0) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + typescript@5.9.3: {} uglify-js@3.19.3: @@ -21297,6 +23179,8 @@ snapshots: undici-types@6.21.0: {} + undici-types@7.18.2: {} + unicode-properties@1.4.1: dependencies: base64-js: 1.5.1 @@ -21326,6 +23210,33 @@ snapshots: unpipe@1.0.0: {} + unrs-resolver@1.12.2: + dependencies: + napi-postinstall: 0.3.4 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.12.2 + '@unrs/resolver-binding-android-arm64': 1.12.2 + '@unrs/resolver-binding-darwin-arm64': 1.12.2 + '@unrs/resolver-binding-darwin-x64': 1.12.2 + '@unrs/resolver-binding-freebsd-x64': 1.12.2 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.12.2 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.12.2 + '@unrs/resolver-binding-linux-arm64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-arm64-musl': 1.12.2 + '@unrs/resolver-binding-linux-loong64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-loong64-musl': 1.12.2 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-riscv64-musl': 1.12.2 + '@unrs/resolver-binding-linux-s390x-gnu': 1.12.2 + '@unrs/resolver-binding-linux-x64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-x64-musl': 1.12.2 + '@unrs/resolver-binding-openharmony-arm64': 1.12.2 + '@unrs/resolver-binding-wasm32-wasi': 1.12.2 + '@unrs/resolver-binding-win32-arm64-msvc': 1.12.2 + '@unrs/resolver-binding-win32-ia32-msvc': 1.12.2 + '@unrs/resolver-binding-win32-x64-msvc': 1.12.2 + unset-value@1.0.0: dependencies: has-value: 0.3.1 @@ -21466,13 +23377,13 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 - vite-node@2.1.9(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0): + vite-node@2.1.9(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 1.1.2 - vite: 5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0) + vite: 5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0) transitivePeerDependencies: - '@types/node' - less @@ -21484,21 +23395,21 @@ snapshots: - supports-color - terser - vite@5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0): + vite@5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0): dependencies: esbuild: 0.21.5 postcss: 8.5.15 rollup: 4.60.4 optionalDependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 fsevents: 2.3.3 lightningcss: 1.32.0 terser: 5.48.0 - vitest@2.1.9(@types/node@20.19.41)(jsdom@25.0.1(canvas@2.11.2))(lightningcss@1.32.0)(msw@2.14.6(@types/node@20.19.41)(typescript@5.9.3))(terser@5.48.0): + vitest@2.1.9(@types/node@24.13.0)(jsdom@25.0.1(canvas@2.11.2))(lightningcss@1.32.0)(msw@2.14.6(@types/node@24.13.0)(typescript@5.9.3))(terser@5.48.0): dependencies: '@vitest/expect': 2.1.9 - '@vitest/mocker': 2.1.9(msw@2.14.6(@types/node@20.19.41)(typescript@5.9.3))(vite@5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0)) + '@vitest/mocker': 2.1.9(msw@2.14.6(@types/node@24.13.0)(typescript@5.9.3))(vite@5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0)) '@vitest/pretty-format': 2.1.9 '@vitest/runner': 2.1.9 '@vitest/snapshot': 2.1.9 @@ -21514,11 +23425,11 @@ snapshots: tinyexec: 0.3.2 tinypool: 1.1.1 tinyrainbow: 1.2.0 - vite: 5.4.21(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0) - vite-node: 2.1.9(@types/node@20.19.41)(lightningcss@1.32.0)(terser@5.48.0) + vite: 5.4.21(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0) + vite-node: 2.1.9(@types/node@24.13.0)(lightningcss@1.32.0)(terser@5.48.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 20.19.41 + '@types/node': 24.13.0 jsdom: 25.0.1(canvas@2.11.2) transitivePeerDependencies: - less @@ -21735,6 +23646,11 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 3.0.7 + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + ws@8.20.1: {} wsl-utils@0.3.1: