diff --git a/apps/edr-passenger-api/src/modules/bookings/bookings.controller.ts b/apps/edr-passenger-api/src/modules/bookings/bookings.controller.ts index 2a8e237e6..bb9b8ffae 100644 --- a/apps/edr-passenger-api/src/modules/bookings/bookings.controller.ts +++ b/apps/edr-passenger-api/src/modules/bookings/bookings.controller.ts @@ -1,5 +1,6 @@ import { Body, Controller, Delete, Get, Param, Post, Patch, UseGuards, Query, Req, BadRequestException } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiResponse, ApiQuery, ApiBody } from '@nestjs/swagger'; +import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.decorator'; import { BookingsService } from './bookings.service'; import { GuestBookingService } from './guest-booking.service'; import { CreateBookingDto, ModifyBookingDto, CancelBookingDto } from './bookings.dto'; @@ -44,7 +45,8 @@ export class BookingsController { } @Get('by-device') - @ApiOperation({ + @IsPublic() + @ApiOperation({ summary: 'Get bookings by device ID', description: 'Returns all bookings associated with a device ID (for guest users). Includes saved passenger details and booking history.' }) @@ -98,7 +100,8 @@ export class BookingsController { } @Post('guest') - @ApiOperation({ + @IsPublic() + @ApiOperation({ summary: 'Create guest booking — ONE_WAY | ROUND_TRIP | TRANSIT | ROUND_TRIP_TRANSIT (no login required)', description: `Creates a booking without requiring login. Supports all four booking types. diff --git a/apps/edr-passenger-api/src/modules/payments/payments.controller.ts b/apps/edr-passenger-api/src/modules/payments/payments.controller.ts index 4cb79a89f..0bf09e41d 100644 --- a/apps/edr-passenger-api/src/modules/payments/payments.controller.ts +++ b/apps/edr-passenger-api/src/modules/payments/payments.controller.ts @@ -17,6 +17,7 @@ import { ApiOkResponse, ApiProduces, } from "@nestjs/swagger"; +import { IsPublic } from "@tria-plc/api-common/modules/auth/decorators/public.decorator"; import { Response } from "express"; import { PaymentsService } from "./payments.service"; import { @@ -62,6 +63,7 @@ export class PaymentsController { } @Post("initiate") + @IsPublic() @ApiOperation({ summary: "Initiate payment with nationality-based payment methods", description: `Initiates payment for a booking with support for multiple payment providers:\n\n**Ethiopian Payment Methods:**\n- TELEBIRR - Ethiopia's leading mobile money\n- CBE_BIRR - Commercial Bank of Ethiopia\n- EBIRR - Electronic payment gateway\n\n**Djiboutian Payment Methods:**\n- WAAFI - Djibouti's mobile money service\n\n**International Payment Methods:**\n- CARD - Visa, Mastercard\n- WALLET - Internal wallet balance\n\n**Multi-Currency:**\n- All transactions processed in ETB\n- Display amounts in ETB, DJF, or USD\n- Real-time exchange rate conversion`, @@ -71,12 +73,14 @@ export class PaymentsController { } @Get("intents/:bookingId") + @IsPublic() @ApiOperation({ summary: "Get payment intent status for a booking" }) getIntent(@Param("bookingId") bookingId: string) { return this.service.getIntentByBookingId(bookingId); } @Get("waafi/return") + @IsPublic() @ApiOperation({ summary: "DEMO ONLY — confirm a Waafi payment from the browser-return params and return JSON for the " + @@ -117,6 +121,7 @@ export class PaymentsController { } @Get("methods") + @IsPublic() @ApiOperation({ summary: "List payment systems supported by the platform", description: @@ -129,6 +134,7 @@ export class PaymentsController { } @Get("checkout") + @IsPublic() @ApiOperation({ summary: "Browser checkout redirect", description: diff --git a/apps/edr-passenger-api/src/modules/schedules/schedules.controller.ts b/apps/edr-passenger-api/src/modules/schedules/schedules.controller.ts index 378bc8fa7..ac55bc14b 100644 --- a/apps/edr-passenger-api/src/modules/schedules/schedules.controller.ts +++ b/apps/edr-passenger-api/src/modules/schedules/schedules.controller.ts @@ -1,5 +1,6 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Query, ParseIntPipe, UseGuards } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiQuery, ApiResponse } from '@nestjs/swagger'; +import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.decorator'; import { SchedulesService } from './schedules.service'; import { CreateScheduleDto, UpdateScheduleDto, CreateFareRuleDto, UpdateScheduleStatusDto, UpdateStopTimeDto, ListSchedulesDto, BulkCreateSchedulesDto, BulkSchedulesResponseDto } from './schedules.dto'; import { JwtGuard } from '../../common/jwt.guard'; @@ -23,6 +24,7 @@ export class SchedulesController { createSchedule(@Body() dto: CreateScheduleDto) { return this.service.createSchedule(dto); } @Get() + @IsPublic() @ApiOperation({ summary: 'List schedules with optional filters' }) @ApiQuery({ name: 'date', required: false }) @ApiQuery({ name: 'routeId', required: false }) @@ -67,6 +69,7 @@ export class SchedulesController { createSegmentFareRule(@Body() dto: any) { return this.service.createSegmentFareRule(dto); } @Get('routes/:routeId/segment-fares') + @IsPublic() @ApiOperation({ summary: 'List all segment fare rules for a route' }) @ApiParam({ name: 'routeId', description: 'Route UUID' }) getSegmentFares(@Param('routeId') routeId: string) { return this.service.getSegmentFares(routeId); } @@ -86,6 +89,7 @@ export class SchedulesController { // ===== PARAMETRIZED ROUTES (generic :id routes come AFTER specific routes) ===== @Get(':id') + @IsPublic() @ApiOperation({ summary: 'Get schedule detail' }) @ApiParam({ name: 'id', description: 'TrainSchedule UUID' }) getSchedule(@Param('id') id: string) { return this.service.getSchedule(id); } @@ -113,6 +117,7 @@ export class SchedulesController { deleteSchedule(@Param('id') id: string) { return this.service.deleteSchedule(id); } @Get(':id/stops') + @IsPublic() @ApiOperation({ summary: 'List all stops for a schedule' }) @ApiParam({ name: 'id', description: 'TrainSchedule UUID' }) getStops(@Param('id') id: string) { return this.service.getStops(id); } diff --git a/apps/edr-passenger-api/src/modules/search/search.controller.ts b/apps/edr-passenger-api/src/modules/search/search.controller.ts index b32f2f291..6bb9d1960 100644 --- a/apps/edr-passenger-api/src/modules/search/search.controller.ts +++ b/apps/edr-passenger-api/src/modules/search/search.controller.ts @@ -1,10 +1,12 @@ import { Body, Controller, Post } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; +import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.decorator'; import { SearchService } from './search.service'; import { SearchTripsDto, FareQuoteDto } from './search.dto'; @ApiTags('Search') @Controller('search') +@IsPublic() export class SearchController { constructor(private service: SearchService) {} diff --git a/apps/edr-passenger-api/src/modules/seat-classes/seat-classes.controller.ts b/apps/edr-passenger-api/src/modules/seat-classes/seat-classes.controller.ts index 0ac25272d..86eb287a4 100644 --- a/apps/edr-passenger-api/src/modules/seat-classes/seat-classes.controller.ts +++ b/apps/edr-passenger-api/src/modules/seat-classes/seat-classes.controller.ts @@ -1,5 +1,6 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, UseGuards } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiResponse, ApiBody } from '@nestjs/swagger'; +import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.decorator'; import { SeatClassesService } from './seat-classes.service'; import { CreateSeatClassDto, UpdateSeatClassDto } from './seat-classes.dto'; import { JwtGuard } from '../../common/jwt.guard'; @@ -10,11 +11,13 @@ export class SeatClassesController { constructor(private service: SeatClassesService) {} @Get() + @IsPublic() @ApiOperation({ summary: 'List all seat classes' }) @ApiResponse({ status: 200, description: 'Returns all seat classes with their coaches' }) listSeatClasses() { return this.service.listSeatClasses(); } @Get(':id') + @IsPublic() @ApiOperation({ summary: 'Get a seat class by ID' }) @ApiParam({ name: 'id', description: 'Seat class UUID' }) @ApiResponse({ status: 200, description: 'Returns seat class with its coaches' }) diff --git a/apps/edr-passenger-api/src/modules/seats/seats.controller.ts b/apps/edr-passenger-api/src/modules/seats/seats.controller.ts index 4d0784f23..513017ad6 100644 --- a/apps/edr-passenger-api/src/modules/seats/seats.controller.ts +++ b/apps/edr-passenger-api/src/modules/seats/seats.controller.ts @@ -1,36 +1,64 @@ -import { Body, Controller, Delete, Get, Param, Post, Patch, Query, UseGuards } from '@nestjs/common'; -import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiQuery, ApiResponse } from '@nestjs/swagger'; -import { SeatsService } from './seats.service'; -import { HoldSeatsDto } from './seats.dto'; -import { JwtGuard } from '../../common/jwt.guard'; -import { IamGuard } from '../../common/iam-adapter'; +import { + Body, + Controller, + Delete, + Get, + Param, + Post, + Patch, + Query, + UseGuards, +} from "@nestjs/common"; +import { + ApiTags, + ApiOperation, + ApiBearerAuth, + ApiParam, + ApiQuery, + ApiResponse, +} from "@nestjs/swagger"; +import { IsPublic } from "@tria-plc/api-common/modules/auth/decorators/public.decorator"; +import { SeatsService } from "./seats.service"; +import { HoldSeatsDto } from "./seats.dto"; +import { JwtGuard } from "../../common/jwt.guard"; +import { IamGuard } from "../../common/iam-adapter"; -@ApiTags('Seats') -@Controller('seats') +@ApiTags("Seats") +@Controller("seats") export class SeatsController { constructor(private service: SeatsService) {} // ── Seat Map ────────────────────────────────────────────────────────────── - @Get('seatmap/:scheduleId') + @Get("seatmap/:scheduleId") @ApiOperation({ - summary: 'Get seat map filtered by coach type', - description: `Returns all coaches of the given coachTypeId assigned to the schedule, each with their full seat list and real-time availability. Origin and destination are derived from the schedule. Omit coachTypeId to get all coaches.` + summary: "Get seat map filtered by coach type", + description: `Returns all coaches of the given coachTypeId assigned to the schedule, each with their full seat list and real-time availability. Origin and destination are derived from the schedule. Omit coachTypeId to get all coaches.`, + }) + @ApiParam({ name: "scheduleId", description: "TrainSchedule UUID" }) + @ApiQuery({ + name: "coachTypeId", + required: false, + description: + "Filter by CoachType UUID — returns all coaches of that type (e.g. all Economy coaches)", + }) + @ApiResponse({ + status: 200, + description: + "List of coaches of the given type with their seats and availability", }) - @ApiParam({ name: 'scheduleId', description: 'TrainSchedule UUID' }) - @ApiQuery({ name: 'coachTypeId', required: false, description: 'Filter by CoachType UUID — returns all coaches of that type (e.g. all Economy coaches)' }) - @ApiResponse({ status: 200, description: 'List of coaches of the given type with their seats and availability' }) getSeatMap( - @Param('scheduleId') scheduleId: string, - @Query('coachTypeId') coachTypeId?: string, + @Param("scheduleId") scheduleId: string, + @Query("coachTypeId") coachTypeId?: string, ) { return this.service.getSeatMap(scheduleId, coachTypeId); } // ── Hold / Release ──────────────────────────────────────────────────────── - @Get('holds') - @UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth') + @Get("holds") + @UseGuards(JwtGuard) + @ApiBearerAuth("JWT-auth") @ApiOperation({ - summary: 'List active seat holds with full leg context', + summary: "List active seat holds with full leg context", description: `Returns all non-expired holds enriched with: - **schedule**: train number, departure/arrival, full route origin→destination - **leg**: the specific origin→destination this hold covers (station name, code, stop sequence) @@ -39,25 +67,45 @@ export class SeatsController { This makes it clear which segment of the route each seat is held for, enabling segment-based reuse of the same seat on non-overlapping legs.`, }) - @ApiQuery({ name: 'scheduleId', required: false, description: 'Filter by TrainSchedule UUID' }) - @ApiQuery({ name: 'passengerId', required: false, description: 'Filter by Passenger UUID' }) - @ApiResponse({ status: 200, description: 'Active holds with schedule, leg, and seat details' }) + @ApiQuery({ + name: "scheduleId", + required: false, + description: "Filter by TrainSchedule UUID", + }) + @ApiQuery({ + name: "passengerId", + required: false, + description: "Filter by Passenger UUID", + }) + @ApiResponse({ + status: 200, + description: "Active holds with schedule, leg, and seat details", + }) getHolds( - @Query('scheduleId') scheduleId?: string, - @Query('passengerId') passengerId?: string, - ) { return this.service.getHolds(scheduleId, passengerId); } + @Query("scheduleId") scheduleId?: string, + @Query("passengerId") passengerId?: string, + ) { + return this.service.getHolds(scheduleId, passengerId); + } - @Get('holds/:holdId') - @UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth') - @ApiOperation({ summary: 'Get a single hold with full leg context' }) - @ApiParam({ name: 'holdId', description: 'SeatHold UUID' }) - @ApiResponse({ status: 200, description: 'Hold with schedule, leg, and seat details' }) - @ApiResponse({ status: 404, description: 'Hold not found' }) - getHold(@Param('holdId') holdId: string) { return this.service.getHold(holdId); } + @Get("holds/:holdId") + @UseGuards(JwtGuard) + @ApiBearerAuth("JWT-auth") + @ApiOperation({ summary: "Get a single hold with full leg context" }) + @ApiParam({ name: "holdId", description: "SeatHold UUID" }) + @ApiResponse({ + status: 200, + description: "Hold with schedule, leg, and seat details", + }) + @ApiResponse({ status: 404, description: "Hold not found" }) + getHold(@Param("holdId") holdId: string) { + return this.service.getHold(holdId); + } - @Post('hold') - @ApiOperation({ - summary: 'Hold seats for 15 minutes before booking (Public - Guest booking supported)', + @Post("hold") + @ApiOperation({ + summary: + "Hold seats for 15 minutes before booking (Public - Guest booking supported)", description: `Temporarily reserves seats for a passenger to complete booking. **Features:** @@ -65,74 +113,107 @@ This makes it clear which segment of the route each seat is held for, enabling s - Auto-release after expiry - Prevents double booking - Required before creating booking -- **Public endpoint** - No authentication required (supports guest booking)` +- **Public endpoint** - No authentication required (supports guest booking)`, }) - @ApiResponse({ status: 201, description: 'Seats held successfully with holdId' }) - @ApiResponse({ status: 409, description: 'One or more seats unavailable' }) - holdSeats(@Body() dto: HoldSeatsDto) { return this.service.holdSeats(dto); } + @ApiResponse({ + status: 201, + description: "Seats held successfully with holdId", + }) + @ApiResponse({ status: 409, description: "One or more seats unavailable" }) + holdSeats(@Body() dto: HoldSeatsDto) { + return this.service.holdSeats(dto); + } - @Delete('hold/:holdId') - @UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth') - @ApiOperation({ summary: 'Release a seat hold' }) - @ApiParam({ name: 'holdId', description: 'Hold UUID' }) - @ApiResponse({ status: 200, description: 'Hold released' }) - @ApiResponse({ status: 404, description: 'Hold not found' }) - releaseHold(@Param('holdId') holdId: string) { return this.service.releaseHold(holdId); } + @Delete("hold/:holdId") + @UseGuards(JwtGuard) + @ApiBearerAuth("JWT-auth") + @ApiOperation({ summary: "Release a seat hold" }) + @ApiParam({ name: "holdId", description: "Hold UUID" }) + @ApiResponse({ status: 200, description: "Hold released" }) + @ApiResponse({ status: 404, description: "Hold not found" }) + releaseHold(@Param("holdId") holdId: string) { + return this.service.releaseHold(holdId); + } // ── Seat Block / Unblock ─────────────────────────────────────────────────── - @Post(':seatId/block') - @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') - @ApiOperation({ summary: 'Block a seat (e.g., maintenance, damage)' }) - @ApiParam({ name: 'seatId', description: 'Seat UUID' }) - @ApiResponse({ status: 200, description: 'Seat blocked' }) - blockSeat(@Param('seatId') seatId: string, @Body() body: { reason: string }) { + @Post(":seatId/block") + @UseGuards(IamGuard) + @ApiBearerAuth("IAM-auth") + @ApiOperation({ summary: "Block a seat (e.g., maintenance, damage)" }) + @ApiParam({ name: "seatId", description: "Seat UUID" }) + @ApiResponse({ status: 200, description: "Seat blocked" }) + blockSeat(@Param("seatId") seatId: string, @Body() body: { reason: string }) { return this.service.blockSeat(seatId, body.reason); } - @Delete(':seatId/block') - @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') - @ApiOperation({ summary: 'Unblock a seat' }) - @ApiParam({ name: 'seatId', description: 'Seat UUID' }) - @ApiResponse({ status: 200, description: 'Seat unblocked' }) - unblockSeat(@Param('seatId') seatId: string) { + @Delete(":seatId/block") + @UseGuards(IamGuard) + @ApiBearerAuth("IAM-auth") + @ApiOperation({ summary: "Unblock a seat" }) + @ApiParam({ name: "seatId", description: "Seat UUID" }) + @ApiResponse({ status: 200, description: "Seat unblocked" }) + unblockSeat(@Param("seatId") seatId: string) { return this.service.unblockSeat(seatId); } // ── Remove Seat ──────────────────────────────────────────────────────────── - @Patch(':seatId/remove') - @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') - @ApiOperation({ summary: 'Remove a seat by marking with negative seatNumber' }) - @ApiParam({ name: 'seatId', description: 'Seat UUID' }) - @ApiResponse({ status: 200, description: 'Seat removed (seatNumber negated), shows as empty space' }) - @ApiResponse({ status: 404, description: 'Seat not found' }) - removeSeat(@Param('seatId') seatId: string) { + @Patch(":seatId/remove") + @UseGuards(IamGuard) + @ApiBearerAuth("IAM-auth") + @ApiOperation({ + summary: "Remove a seat by marking with negative seatNumber", + }) + @ApiParam({ name: "seatId", description: "Seat UUID" }) + @ApiResponse({ + status: 200, + description: "Seat removed (seatNumber negated), shows as empty space", + }) + @ApiResponse({ status: 404, description: "Seat not found" }) + removeSeat(@Param("seatId") seatId: string) { return this.service.removeSeat(seatId); } - @Patch(':seatId/undo-remove') - @UseGuards(IamGuard) @ApiBearerAuth('IAM-auth') - @ApiOperation({ summary: 'Undo seat removal by restoring original seatNumber' }) - @ApiParam({ name: 'seatId', description: 'Seat UUID' }) - @ApiResponse({ status: 200, description: 'Seat restored (negative seatNumber removed)' }) - @ApiResponse({ status: 404, description: 'Seat not found' }) - @ApiResponse({ status: 400, description: 'Seat is not removed' }) - undoRemoveSeat(@Param('seatId') seatId: string) { + @Patch(":seatId/undo-remove") + @UseGuards(IamGuard) + @ApiBearerAuth("IAM-auth") + @ApiOperation({ + summary: "Undo seat removal by restoring original seatNumber", + }) + @ApiParam({ name: "seatId", description: "Seat UUID" }) + @ApiResponse({ + status: 200, + description: "Seat restored (negative seatNumber removed)", + }) + @ApiResponse({ status: 404, description: "Seat not found" }) + @ApiResponse({ status: 400, description: "Seat is not removed" }) + undoRemoveSeat(@Param("seatId") seatId: string) { return this.service.undoRemoveSeat(seatId); } - @Get('export/csv/:scheduleId') @UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth') @ApiOperation({ summary: 'Export seats as CSV' }) - async exportCSV(@Param('scheduleId') scheduleId: string) { + @Get("export/csv/:scheduleId") + @UseGuards(JwtGuard) + @ApiBearerAuth("JWT-auth") + @ApiOperation({ summary: "Export seats as CSV" }) + async exportCSV(@Param("scheduleId") scheduleId: string) { const csv = await this.service.exportSeatsCSV(scheduleId); return { csv, filename: `seats-${scheduleId}.csv` }; } - @Post('import/preview') @UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth') @ApiOperation({ summary: 'Preview CSV import' }) + @Post("import/preview") + @UseGuards(JwtGuard) + @ApiBearerAuth("JWT-auth") + @ApiOperation({ summary: "Preview CSV import" }) previewCSV(@Body() body: { csv: string }) { return this.service.previewSeatsCSV(body.csv); } - @Post('import/commit') @UseGuards(JwtGuard) @ApiBearerAuth('JWT-auth') @ApiOperation({ summary: 'Commit CSV import' }) - importCSV(@Body() body: { scheduleId: string; csv: string; commit: boolean }) { + @Post("import/commit") + @UseGuards(JwtGuard) + @ApiBearerAuth("JWT-auth") + @ApiOperation({ summary: "Commit CSV import" }) + importCSV( + @Body() body: { scheduleId: string; csv: string; commit: boolean }, + ) { return this.service.importSeatsCSV(body.scheduleId, body.csv, body.commit); } } diff --git a/apps/edr-passenger-api/src/modules/stations/stations.controller.ts b/apps/edr-passenger-api/src/modules/stations/stations.controller.ts index 9c864c307..a89ecd87d 100644 --- a/apps/edr-passenger-api/src/modules/stations/stations.controller.ts +++ b/apps/edr-passenger-api/src/modules/stations/stations.controller.ts @@ -1,5 +1,6 @@ import { Body, Controller, Get, Param, Post, Patch, Delete, UseGuards, Query } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiQuery, ApiResponse } from '@nestjs/swagger'; +import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.decorator'; import { StationsService } from './stations.service'; import { CreateStationDto } from './stations.dto'; import { JwtGuard } from '../../common/jwt.guard'; @@ -10,7 +11,8 @@ export class StationsController { constructor(private service: StationsService) {} @Get() - @ApiOperation({ + @IsPublic() + @ApiOperation({ summary: 'List all stations with country information', description: 'Returns all stations on the Ethio-Djibouti Railway with country codes (ET for Ethiopia, DJ for Djibouti)' }) @@ -48,7 +50,8 @@ export class StationsController { } @Get(':id') - @ApiOperation({ + @IsPublic() + @ApiOperation({ summary: 'Get station details by ID', description: 'Returns station information including name, code, country, coordinates, and facilities' }) diff --git a/apps/edr-passenger-web/portal/src/app/booking/payment/dmoney/success/page.tsx b/apps/edr-passenger-web/portal/src/app/booking/payment/dmoney/success/page.tsx new file mode 100644 index 000000000..e75f9b36a --- /dev/null +++ b/apps/edr-passenger-web/portal/src/app/booking/payment/dmoney/success/page.tsx @@ -0,0 +1,85 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { useRouter, useSearchParams } from 'next/navigation'; +import { useBookingStore } from '@/lib/booking-store'; +import { usePaymentStore } from '@/lib/payment-store'; +import { apiClient } from '@/lib/api-client'; +import { CheckCircle, Loader2 } from 'lucide-react'; +import { Suspense } from 'react'; + +function DmoneySuccessContent() { + const router = useRouter(); + const searchParams = useSearchParams(); + const { bookingId } = useBookingStore(); + const { updateStatus } = usePaymentStore(); + const [status, setStatus] = useState<'processing' | 'done' | 'error'>('processing'); + + // D-Money callback query params (mirrors Telebirr) + const orderid = searchParams.get('orderid') || ''; + const trxRef = searchParams.get('trxRef') || searchParams.get('outTradeNo') || ''; + const bookingIdQp = searchParams.get('bookingId') || bookingId || ''; + + useEffect(() => { + const confirm = async () => { + try { + if (bookingIdQp) { + await apiClient.patch(`/bookings/${bookingIdQp}/confirm`, { + paymentReference: orderid || trxRef, + paymentMethod: 'DMONEY', + }); + } + + updateStatus('SUCCEEDED'); + setStatus('done'); + setTimeout(() => router.push('/booking/confirmation'), 1500); + } catch (err: any) { + updateStatus('SUCCEEDED'); + setStatus('done'); + setTimeout(() => router.push('/booking/confirmation'), 1500); + } + }; + + confirm(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( +
+
+ {status === 'processing' && ( + <> + +

Confirming payment…

+

Please wait while we confirm your D-Money payment.

+ + )} + {status === 'done' && ( + <> + +

Payment Successful!

+

Your D-Money payment was received.

+ {orderid &&

Order ID: {orderid}

} + {trxRef &&

Transaction Ref: {trxRef}

} +

Redirecting to your booking confirmation…

+ + )} + {status === 'error' && ( + <> +
+ ⚠️ +
+

Something went wrong

+

Unable to confirm payment

+ + + )} +
+
+ ); +} + +export default function DmoneySuccessPage() { + return }>; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a11640abb..828700ca4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -454,10 +454,7 @@ importers: version: 2.1.1(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24) "@nestjs/microservices": specifier: ^11.1.24 - version: 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@0.10.9))(amqplib@0.10.9)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/passport': - specifier: ^10.0.3 - version: 10.0.3(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(passport@0.7.0) + version: 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@2.0.1))(amqplib@2.0.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/platform-express': specifier: ^11.1.19 version: 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24) @@ -2679,18 +2676,8 @@ packages: peerDependencies: react: ^18.x || ^19.x - "@mapbox/node-pre-gyp@1.0.11": - resolution: - { - integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==, - } - hasBin: true - - "@microsoft/tsdoc@0.15.1": - resolution: - { - integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==, - } + '@microsoft/tsdoc@0.15.1': + resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==} "@microsoft/tsdoc@0.16.0": resolution: @@ -5469,25 +5456,21 @@ packages: rxjs: ^7.8.0 typeorm: ^0.3.0 - "@tria-plc/iamapi-common@file:local-packages/tria-plc-iamapi-common-0.7.3.tgz": - resolution: - { - integrity: sha512-poMG3sm+HmnfNbWNqMDZJMf3pXdc3HHA+o/ay6CA4E6ehLKkO7Np77C6xrCYuGxyDgqqKdmWiFLqKKddkv5rig==, - tarball: file:local-packages/tria-plc-iamapi-common-0.7.3.tgz, - } + '@tria-plc/iamapi-common@file:local-packages/tria-plc-iamapi-common-0.7.3.tgz': + resolution: {integrity: sha512-poMG3sm+HmnfNbWNqMDZJMf3pXdc3HHA+o/ay6CA4E6ehLKkO7Np77C6xrCYuGxyDgqqKdmWiFLqKKddkv5rig==, tarball: file:local-packages/tria-plc-iamapi-common-0.7.3.tgz} version: 0.7.3 - engines: { node: ">=20" } + engines: {node: '>=20'} peerDependencies: - "@nestjs/axios": ^4.0.0 - "@nestjs/common": ^11.0.0 - "@nestjs/core": ^11.0.0 - "@nestjs/jwt": ^11.0.0 - "@nestjs/microservices": ^11.0.0 - "@nestjs/passport": ^11.0.0 - "@nestjs/swagger": ^11.0.0 - "@nestjs/throttler": ^6.0.0 - "@nestjs/typeorm": ^11.0.0 - "@tria-plc/api-common": "*" + '@nestjs/axios': ^4.0.0 + '@nestjs/common': ^11.0.0 + '@nestjs/core': ^11.0.0 + '@nestjs/jwt': ^11.0.0 + '@nestjs/microservices': ^11.0.0 + '@nestjs/passport': ^11.0.0 + '@nestjs/swagger': ^11.0.0 + '@nestjs/throttler': ^6.0.0 + '@nestjs/typeorm': ^11.0.0 + '@tria-plc/api-common': '*' axios: ^1.9.0 class-transformer: ^0.5.1 class-validator: ^0.14.1 @@ -5495,12 +5478,8 @@ packages: rxjs: ^7.8.0 typeorm: ^0.3.0 - "@tria-plc/iamui@file:local-packages/tria-plc-iamui-0.0.3.tgz": - resolution: - { - integrity: sha512-aZhIeNq2Uui7TUkG88G9QTBqdhaVB5kvqfd47HLgVE7qKkVyfjlm4nwlSWnHh5MO+CjgP9vRi6ILwMJx1ULO8g==, - tarball: file:local-packages/tria-plc-iamui-0.0.3.tgz, - } + '@tria-plc/iamui@file:local-packages/tria-plc-iamui-0.0.3.tgz': + resolution: {integrity: sha512-aZhIeNq2Uui7TUkG88G9QTBqdhaVB5kvqfd47HLgVE7qKkVyfjlm4nwlSWnHh5MO+CjgP9vRi6ILwMJx1ULO8g==, tarball: file:local-packages/tria-plc-iamui-0.0.3.tgz} version: 0.0.3 engines: { node: ">=18" } peerDependencies: @@ -7448,13 +7427,6 @@ packages: } engines: { node: ">=10.0.0" } - bcrypt@5.1.1: - resolution: - { - integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==, - } - engines: { node: ">= 10.0.0" } - bidi-js@1.0.3: resolution: { @@ -8167,12 +8139,6 @@ packages: } engines: { node: ^14.18.0 || >=16.10.0 } - console-control-strings@1.1.0: - resolution: - { - integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==, - } - content-disposition@0.5.4: resolution: { @@ -8810,12 +8776,6 @@ packages: } engines: { node: ">=0.4.0" } - delegates@1.0.0: - resolution: - { - integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==, - } - depd@2.0.0: resolution: { @@ -11979,10 +11939,6 @@ packages: integrity: sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==, } - jsprim@1.4.2: - resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} - engines: {node: '>=0.6.0'} - jsx-ast-utils@3.3.5: resolution: { @@ -13212,18 +13168,6 @@ packages: integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==, } - node-fetch@2.7.0: - resolution: - { - integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==, - } - engines: { node: 4.x || >=6.0.0 } - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - node-fetch@3.3.2: resolution: { @@ -13257,14 +13201,6 @@ packages: } engines: { node: ">=18" } - nopt@5.0.0: - resolution: - { - integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==, - } - engines: { node: ">=6" } - hasBin: true - normalize-path@3.0.0: resolution: { @@ -16428,12 +16364,6 @@ packages: } engines: { node: ">=16" } - tr46@0.0.3: - resolution: - { - integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==, - } - tr46@5.1.1: resolution: { @@ -17251,12 +17181,6 @@ packages: integrity: sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==, } - webidl-conversions@3.0.1: - resolution: - { - integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==, - } - webidl-conversions@7.0.0: resolution: { @@ -17313,12 +17237,6 @@ packages: } engines: { node: ">=18" } - whatwg-url@5.0.0: - resolution: - { - integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==, - } - which-boxed-primitive@1.1.1: resolution: { @@ -17377,12 +17295,6 @@ packages: engines: { node: ">=8" } hasBin: true - wide-align@1.1.5: - resolution: - { - integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==, - } - winston-daily-rotate-file@1.7.2: resolution: { @@ -19044,22 +18956,7 @@ snapshots: dependencies: react: 19.2.6 - "@mapbox/node-pre-gyp@1.0.11": - dependencies: - detect-libc: 2.1.2 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.8.2 - tar: 6.2.1 - transitivePeerDependencies: - - encoding - - supports-color - - "@microsoft/tsdoc@0.15.1": {} + '@microsoft/tsdoc@0.15.1': {} "@microsoft/tsdoc@0.16.0": {} @@ -19359,7 +19256,7 @@ snapshots: tslib: 2.8.1 uid: 2.0.2 optionalDependencies: - '@nestjs/microservices': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@0.10.9))(amqplib@0.10.9)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/microservices': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@2.0.1))(amqplib@2.0.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/platform-express': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24) "@nestjs/event-emitter@2.1.1(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)": @@ -19390,18 +19287,6 @@ snapshots: class-transformer: 0.5.1 class-validator: 0.14.4 - '@nestjs/microservices@11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@0.10.9))(amqplib@0.10.9)(reflect-metadata@0.2.2)(rxjs@7.8.2)': - dependencies: - '@nestjs/common': 11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/microservices@11.1.24)(@nestjs/platform-express@11.1.24)(reflect-metadata@0.2.2)(rxjs@7.8.2) - iterare: 1.2.1 - reflect-metadata: 0.2.2 - rxjs: 7.8.2 - tslib: 2.8.1 - optionalDependencies: - amqp-connection-manager: 5.0.0(amqplib@0.10.9) - amqplib: 0.10.9 - '@nestjs/microservices@11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@2.0.1))(amqplib@2.0.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: "@nestjs/common": 11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -19486,7 +19371,7 @@ snapshots: "@nestjs/core": 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/microservices@11.1.24)(@nestjs/platform-express@11.1.24)(reflect-metadata@0.2.2)(rxjs@7.8.2) tslib: 2.8.1 optionalDependencies: - '@nestjs/microservices': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@0.10.9))(amqplib@0.10.9)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/microservices': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@2.0.1))(amqplib@2.0.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/platform-express': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24) "@nestjs/throttler@6.5.0(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(reflect-metadata@0.2.2)": @@ -21806,18 +21691,62 @@ snapshots: - debug - supports-color - "@tria-plc/iamapi-common@file:local-packages/tria-plc-iamapi-common-0.7.3.tgz(578386f46cf99fd4720e3e99f196f69e)": + '@tria-plc/api-common@file:local-packages/tria-plc-api-common-1.4.3.tgz(d81a2b6a79840fd7ce8c5d0cfc968145)': dependencies: - "@nestjs/axios": 4.0.1(@nestjs/common@11.1.24(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": 11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) - "@nestjs/core": 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/microservices@11.1.24)(@nestjs/platform-express@11.1.24)(reflect-metadata@0.2.2)(rxjs@7.8.2) - "@nestjs/jwt": 10.2.0(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)) - "@nestjs/microservices": 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@2.0.1))(amqplib@2.0.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - "@nestjs/passport": 10.0.3(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(passport@0.7.0) - "@nestjs/swagger": 11.4.4(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2) - "@nestjs/throttler": 6.5.0(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(reflect-metadata@0.2.2) - "@nestjs/typeorm": 11.0.1(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(reflect-metadata@0.2.2)(rxjs@7.8.2)(typeorm@0.3.30(babel-plugin-macros@3.1.0)(pg@8.21.0)(ts-node@10.9.2(@types/node@20.19.42)(typescript@5.9.3))) - "@tria-plc/api-common": file:local-packages/tria-plc-api-common-1.4.3.tgz(28ab85b15f2c569b3d04dfa1367528a6) + '@nestjs/axios': 4.0.1(@nestjs/common@11.1.24(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': 11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/microservices@11.1.24)(@nestjs/platform-express@11.1.24)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/jwt': 10.2.0(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)) + '@nestjs/microservices': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@2.0.1))(amqplib@2.0.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/passport': 10.0.3(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(passport@0.7.0) + '@nestjs/swagger': 7.4.2(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2) + '@nestjs/throttler': 6.5.0(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(reflect-metadata@0.2.2) + '@nestjs/typeorm': 11.0.1(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(reflect-metadata@0.2.2)(rxjs@7.8.2)(typeorm@0.3.30(babel-plugin-macros@3.1.0)(pg@8.21.0)(ts-node@10.9.2(@types/node@20.19.42)(typescript@5.9.3))) + '@tria-plc/iamapi-common': file:local-packages/tria-plc-iamapi-common-0.7.3.tgz(c97ba831ddde82920910406ab5262991) + argon2: 0.43.1 + axios: 1.17.0 + change-case: 5.4.4 + class-transformer: 0.5.1 + class-validator: 0.14.4 + dotenv: 16.6.1 + ethiopian-calendar-date-converter: 2.1.6 + ethiopian-date: 0.0.6 + exceljs: 4.4.0 + file-type: 21.3.4 + handlebars: 4.7.9 + handlebars-helpers: 0.10.0 + jmespath: 0.16.0 + jose: 5.10.0 + jsonwebtoken: 9.0.3 + libphonenumber-js: 1.13.6 + libreoffice-convert: 1.8.1 + nestjs-minio-client: 2.2.0(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24) + passport-jwt: 4.0.1 + qrcode: 1.5.4 + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + style-object-to-css-string: 1.1.3 + typeorm: 0.3.30(babel-plugin-macros@3.1.0)(pg@8.21.0)(ts-node@10.9.2(@types/node@20.19.42)(typescript@5.9.3)) + typeorm-extension: 3.9.0(@faker-js/faker@10.4.0)(typeorm@0.3.30(babel-plugin-macros@3.1.0)(pg@8.21.0)(ts-node@10.9.2(@types/node@20.19.42)(typescript@5.9.3))) + uuid: 11.1.1 + xlsx: 0.18.5 + transitivePeerDependencies: + - '@faker-js/faker' + - debug + - supports-color + + '@tria-plc/iamapi-common@file:local-packages/tria-plc-iamapi-common-0.7.3.tgz(578386f46cf99fd4720e3e99f196f69e)': + dependencies: + '@nestjs/axios': 4.0.1(@nestjs/common@11.1.24(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': 11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/microservices@11.1.24)(@nestjs/platform-express@11.1.24)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/jwt': 10.2.0(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)) + '@nestjs/microservices': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@2.0.1))(amqplib@2.0.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/passport': 10.0.3(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(passport@0.7.0) + '@nestjs/swagger': 11.4.4(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2) + '@nestjs/throttler': 6.5.0(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(reflect-metadata@0.2.2) + '@nestjs/typeorm': 11.0.1(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(reflect-metadata@0.2.2)(rxjs@7.8.2)(typeorm@0.3.30(babel-plugin-macros@3.1.0)(pg@8.21.0)(ts-node@10.9.2(@types/node@20.19.42)(typescript@5.9.3))) + '@tria-plc/api-common': file:local-packages/tria-plc-api-common-1.4.3.tgz(28ab85b15f2c569b3d04dfa1367528a6) api-common: 1.2.2 argon2: 0.43.1 axios: 1.17.0 @@ -21841,52 +21770,87 @@ snapshots: - "@faker-js/faker" - supports-color - "@tria-plc/iamui@file:local-packages/tria-plc-iamui-0.0.3.tgz(0ce39b7e349029277dcd938d06eeb0f7)": + '@tria-plc/iamapi-common@file:local-packages/tria-plc-iamapi-common-0.7.3.tgz(c97ba831ddde82920910406ab5262991)': dependencies: - "@emotion/react": 11.14.0(@types/react@18.3.31)(react@19.2.6) - "@emotion/styled": 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) - "@hookform/resolvers": 5.4.0(react-hook-form@7.77.0(react@19.2.6)) - "@lottiefiles/react-lottie-player": 3.6.0(react@19.2.6) - "@mantine/charts": 7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@7.17.8(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(recharts@3.8.1(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6)(redux@5.0.1)) - "@mantine/core": 7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@mantine/dates": 7.17.8(@mantine/core@9.3.0(@mantine/hooks@9.3.0(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@9.3.0(react@19.2.6))(dayjs@1.11.21)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@mantine/hooks": 7.17.8(react@19.2.6) - "@mantine/notifications": 7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@7.17.8(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-accordion": 1.2.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-alert-dialog": 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-avatar": 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-checkbox": 1.3.4(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-collapsible": 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-context-menu": 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-dialog": 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-dropdown-menu": 2.1.17(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-hover-card": 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-label": 2.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-navigation-menu": 1.2.15(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-popover": 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-progress": 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-radio-group": 1.4.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-scroll-area": 1.2.11(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-select": 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-separator": 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-slot": 1.2.5(@types/react@18.3.31)(react@19.2.6) - "@radix-ui/react-switch": 1.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-tabs": 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-toast": 1.2.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@radix-ui/react-tooltip": 1.2.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@react-pdf-viewer/core": 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@react-pdf-viewer/default-layout": 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@react-pdf/renderer": 4.5.1(react@19.2.6) - "@reduxjs/toolkit": 2.12.0(react-redux@9.3.0(@types/react@18.3.31)(react@19.2.6)(redux@5.0.1))(react@19.2.6) - "@tabler/icons-react": 3.44.0(react@19.2.6) - "@tailwindcss/vite": 4.3.0(vite@5.4.21(@types/node@24.13.1)(lightningcss@1.32.0)(terser@5.48.0)) - "@tanstack/react-query": 5.101.0(react@19.2.6) - "@tanstack/react-query-devtools": 5.101.0(@tanstack/react-query@5.101.0(react@19.2.6))(react@19.2.6) - "@tanstack/react-table": 8.21.3(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - "@tinymce/tinymce-react": 6.3.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(tinymce@7.9.3) - "@types/dompurify": 3.2.0 - "@types/node": 24.13.1 - "@types/tinymce": 4.6.9 + '@nestjs/axios': 4.0.1(@nestjs/common@11.1.24(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': 11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/microservices@11.1.24)(@nestjs/platform-express@11.1.24)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/jwt': 10.2.0(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)) + '@nestjs/microservices': 11.1.24(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(amqp-connection-manager@5.0.0(amqplib@2.0.1))(amqplib@2.0.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/passport': 10.0.3(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(passport@0.7.0) + '@nestjs/swagger': 7.4.2(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2) + '@nestjs/throttler': 6.5.0(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(reflect-metadata@0.2.2) + '@nestjs/typeorm': 11.0.1(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24)(reflect-metadata@0.2.2)(rxjs@7.8.2)(typeorm@0.3.30(babel-plugin-macros@3.1.0)(pg@8.21.0)(ts-node@10.9.2(@types/node@20.19.42)(typescript@5.9.3))) + '@tria-plc/api-common': file:local-packages/tria-plc-api-common-1.4.3.tgz(d81a2b6a79840fd7ce8c5d0cfc968145) + api-common: 1.2.2 + argon2: 0.43.1 + axios: 1.17.0 + class-transformer: 0.5.1 + class-validator: 0.14.4 + dotenv: 17.4.2 + ethiopian-date: 0.0.6 + file-type: 21.3.4 + jose: 5.10.0 + jsonwebtoken: 9.0.3 + libphonenumber-js: 1.13.6 + nestjs-minio-client: 2.2.0(@nestjs/common@11.1.24(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.24) + passport-jwt: 4.0.1 + qrcode: 1.5.4 + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + typeorm: 0.3.30(babel-plugin-macros@3.1.0)(pg@8.21.0)(ts-node@10.9.2(@types/node@20.19.42)(typescript@5.9.3)) + typeorm-extension: 3.9.0(@faker-js/faker@10.4.0)(typeorm@0.3.30(babel-plugin-macros@3.1.0)(pg@8.21.0)(ts-node@10.9.2(@types/node@20.19.42)(typescript@5.9.3))) + uuid: 11.1.1 + transitivePeerDependencies: + - '@faker-js/faker' + - supports-color + + '@tria-plc/iamui@file:local-packages/tria-plc-iamui-0.0.3.tgz(0ce39b7e349029277dcd938d06eeb0f7)': + dependencies: + '@emotion/react': 11.14.0(@types/react@18.3.31)(react@19.2.6) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) + '@hookform/resolvers': 5.4.0(react-hook-form@7.77.0(react@19.2.6)) + '@lottiefiles/react-lottie-player': 3.6.0(react@19.2.6) + '@mantine/charts': 7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@7.17.8(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(recharts@3.8.1(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6)(redux@5.0.1)) + '@mantine/core': 7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@mantine/dates': 7.17.8(@mantine/core@9.3.0(@mantine/hooks@9.3.0(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@9.3.0(react@19.2.6))(dayjs@1.11.21)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@mantine/hooks': 7.17.8(react@19.2.6) + '@mantine/notifications': 7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@7.17.8(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-accordion': 1.2.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-alert-dialog': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-avatar': 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-checkbox': 1.3.4(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-collapsible': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-context-menu': 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-dialog': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-dropdown-menu': 2.1.17(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-hover-card': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-label': 2.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-navigation-menu': 1.2.15(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-popover': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-progress': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-radio-group': 1.4.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-scroll-area': 1.2.11(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-select': 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-separator': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-slot': 1.2.5(@types/react@18.3.31)(react@19.2.6) + '@radix-ui/react-switch': 1.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-tabs': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-toast': 1.2.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-tooltip': 1.2.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@react-pdf-viewer/default-layout': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@react-pdf/renderer': 4.5.1(react@19.2.6) + '@reduxjs/toolkit': 2.12.0(react-redux@9.3.0(@types/react@18.3.31)(react@19.2.6)(redux@5.0.1))(react@19.2.6) + '@tabler/icons-react': 3.44.0(react@19.2.6) + '@tailwindcss/vite': 4.3.0(vite@5.4.21(@types/node@24.13.1)(lightningcss@1.32.0)(terser@5.48.0)) + '@tanstack/react-query': 5.101.0(react@19.2.6) + '@tanstack/react-query-devtools': 5.101.0(@tanstack/react-query@5.101.0(react@19.2.6))(react@19.2.6) + '@tanstack/react-table': 8.21.3(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@tinymce/tinymce-react': 6.3.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(tinymce@7.9.3) + '@types/dompurify': 3.2.0 + '@types/node': 24.13.1 + '@types/tinymce': 4.6.9 axios: 1.17.0 class-variance-authority: 0.7.1 clsx: 2.1.1 @@ -22668,12 +22632,6 @@ snapshots: amqplib: 0.10.9 promise-breaker: 6.0.0 - amqp-connection-manager@5.0.0(amqplib@0.10.9): - dependencies: - amqplib: 0.10.9 - promise-breaker: 6.0.0 - optional: true - amqp-connection-manager@5.0.0(amqplib@2.0.1): dependencies: amqplib: 2.0.1 @@ -23206,14 +23164,6 @@ snapshots: basic-ftp@5.3.1: {} - bcrypt@5.1.1: - dependencies: - "@mapbox/node-pre-gyp": 1.0.11 - node-addon-api: 5.1.0 - transitivePeerDependencies: - - encoding - - supports-color - bidi-js@1.0.3: dependencies: require-from-string: 2.0.2 @@ -23659,8 +23609,6 @@ snapshots: consola@3.4.2: {} - console-control-strings@1.1.0: {} - content-disposition@0.5.4: dependencies: safe-buffer: 5.2.1 @@ -24000,8 +23948,6 @@ snapshots: delayed-stream@1.0.0: {} - delegates@1.0.0: {} - depd@2.0.0: {} dequal@2.0.3: {} @@ -26305,17 +26251,6 @@ snapshots: dompurify: 3.4.8 html2canvas: 1.4.1 - jsprim@1.4.2: - dependencies: - '@babel/runtime': 7.29.7 - fast-png: 6.4.0 - fflate: 0.8.3 - optionalDependencies: - canvg: 3.0.11 - core-js: 3.49.0 - dompurify: 3.4.8 - html2canvas: 1.4.1 - jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.9 @@ -26998,10 +26933,6 @@ snapshots: node-fetch-native@1.6.7: {} - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - node-fetch@3.3.2: dependencies: data-uri-to-buffer: 4.0.1 @@ -27019,10 +26950,6 @@ snapshots: node-releases@2.0.47: {} - nopt@5.0.0: - dependencies: - abbrev: 1.1.1 - normalize-path@3.0.0: {} normalize-svg-path@1.1.0: @@ -29225,8 +29152,6 @@ snapshots: dependencies: tldts: 7.4.2 - tr46@0.0.3: {} - tr46@5.1.1: dependencies: punycode: 2.3.1 @@ -29852,8 +29777,6 @@ snapshots: webdriver-bidi-protocol@0.4.1: {} - webidl-conversions@3.0.1: {} - webidl-conversions@7.0.0: {} webpack-node-externals@3.0.0: {} @@ -29912,11 +29835,6 @@ snapshots: tr46: 5.1.1 webidl-conversions: 7.0.0 - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -29973,10 +29891,6 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 - wide-align@1.1.5: - dependencies: - string-width: 4.2.3 - winston-daily-rotate-file@1.7.2(winston@2.4.7): dependencies: mkdirp: 0.5.1