feat(05-03): calendar backend — model, crypto, source CRUD module

- Add CalendarSource Prisma model with encrypted credentials (AES-256-GCM)
- Create CalendarCryptoService with encrypt/decrypt using CALENDAR_ENCRYPTION_KEY
- Create CalendarController with source CRUD endpoints (GET/POST/PATCH/DELETE)
- Create CalendarService with ownership checks and SSRF URL validation
- Add DTOs with https-only URL validation and class-validator decorators
- Register CalendarModule in AppModule
- Install tsdav, node-ical, ews-javascript-api, @microsoft/microsoft-graph-client
- Stub provider files for Task 2 compilation
This commit is contained in:
2026-06-24 15:09:03 +02:00
parent 7616365cbe
commit 9ec6313f4d
14 changed files with 1114 additions and 6 deletions
+5 -1
View File
@@ -9,6 +9,7 @@
"type-check": "tsc --noEmit" "type-check": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"@microsoft/microsoft-graph-client": "3.0.7",
"@nestjs-modules/mailer": "^2.3.7", "@nestjs-modules/mailer": "^2.3.7",
"@nestjs/common": "^11.0.0", "@nestjs/common": "^11.0.0",
"@nestjs/config": "^4.0.0", "@nestjs/config": "^4.0.0",
@@ -24,13 +25,16 @@
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.15.1", "class-validator": "^0.15.1",
"cookie-parser": "^1.4.7", "cookie-parser": "^1.4.7",
"ews-javascript-api": "0.15.3",
"ldapts": "^8.1.8", "ldapts": "^8.1.8",
"node-ical": "0.26.1",
"nodemailer": "^9.0.1", "nodemailer": "^9.0.1",
"passport": "^0.7.0", "passport": "^0.7.0",
"passport-jwt": "^4.0.1", "passport-jwt": "^4.0.1",
"passport-local": "^1.0.0", "passport-local": "^1.0.0",
"reflect-metadata": "^0.2.0", "reflect-metadata": "^0.2.0",
"rxjs": "^7.0.0" "rxjs": "^7.0.0",
"tsdav": "2.2.2"
}, },
"devDependencies": { "devDependencies": {
"@nestjs/cli": "^11.0.0", "@nestjs/cli": "^11.0.0",
+22
View File
@@ -146,3 +146,25 @@ model SearchProvider {
@@index([userId]) @@index([userId])
} }
model CalendarSource {
id String @id @default(uuid())
userId String
tenantId String
name String
type String // 'caldav' | 'ics' | 'exchange'
exchangeMode String? // 'ews' | 'graph' — only for exchange type
url String
username String?
encryptedPassword String? // AES-256-GCM ciphertext (iv:authTag:ciphertext hex)
color String? @default("#3B82F6")
isVisible Boolean @default(true)
syncIntervalMin Int @default(15)
lastSyncAt DateTime?
lastSyncError String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId])
@@index([tenantId])
}
+2
View File
@@ -8,6 +8,7 @@ import { ForcePasswordChangeInterceptor } from './auth/interceptors/force-passwo
import { HealthModule } from './health/health.module'; import { HealthModule } from './health/health.module';
import { LdapModule } from './ldap/ldap.module'; import { LdapModule } from './ldap/ldap.module';
import { MailModule } from './mail/mail.module'; import { MailModule } from './mail/mail.module';
import { CalendarModule } from './calendar/calendar.module';
import { DashboardModule } from './dashboard/dashboard.module'; import { DashboardModule } from './dashboard/dashboard.module';
import { DomaincheckModule } from './domaincheck/domaincheck.module'; import { DomaincheckModule } from './domaincheck/domaincheck.module';
import { ModuleRegistryModule } from './module-registry/module-registry.module'; import { ModuleRegistryModule } from './module-registry/module-registry.module';
@@ -29,6 +30,7 @@ import { UserModule } from './user/user.module';
ModuleRegistryModule, ModuleRegistryModule,
DomaincheckModule, DomaincheckModule,
DashboardModule, DashboardModule,
CalendarModule,
], ],
providers: [ providers: [
// Global JWT guard: all routes require auth unless @Public() // Global JWT guard: all routes require auth unless @Public()
@@ -0,0 +1,131 @@
import {
Body,
Controller,
Delete,
ForbiddenException,
Get,
Param,
Patch,
Post,
Query,
Req,
} from '@nestjs/common';
import { Request } from 'express';
import { CalendarService } from './calendar.service';
import { CreateCalendarSourceDto } from './dto/create-calendar-source.dto';
import { UpdateCalendarSourceDto } from './dto/update-calendar-source.dto';
import { CalendarEventsQueryDto } from './dto/calendar-events-query.dto';
/**
* REST controller for calendar source management and event aggregation.
*
* All endpoints require JWT auth (global JwtAuthGuard).
* Every handler extracts userId and tenantId from the request
* and scopes all operations to the calling user (T-05-12).
*
* Routes:
* - GET /calendar/sources — list user's calendar sources (no passwords)
* - POST /calendar/sources — add a new calendar source
* - PATCH /calendar/sources/:id — update a calendar source
* - DELETE /calendar/sources/:id — remove a calendar source
* - POST /calendar/sources/:id/test — test connection to a source
* - GET /calendar/events — aggregated events from visible sources
*/
@Controller('calendar')
export class CalendarController {
constructor(private readonly calendarService: CalendarService) {}
private extractContext(req: Request) {
const userId = (req as any).user?.id;
const tenantId =
(req as any).tenantId ?? (req as any).user?.tenantId;
if (!tenantId) {
throw new ForbiddenException('No tenant context');
}
if (!userId) {
throw new ForbiddenException('No user context');
}
return { userId, tenantId };
}
/**
* GET /calendar/sources
* Returns all calendar sources for the user WITHOUT encryptedPassword.
* T-05-09: Uses Prisma select to exclude credentials; returns hasCredentials boolean.
*/
@Get('sources')
async getSources(@Req() req: Request) {
const { userId } = this.extractContext(req);
return this.calendarService.getSources(userId);
}
/**
* POST /calendar/sources
* Creates a new calendar source. Password is encrypted before storage.
* T-05-11: URL validated as https-only + SSRF private IP check.
*/
@Post('sources')
async addSource(
@Req() req: Request,
@Body() dto: CreateCalendarSourceDto,
) {
const { userId, tenantId } = this.extractContext(req);
return this.calendarService.addSource(userId, tenantId, dto);
}
/**
* PATCH /calendar/sources/:id
* Updates an existing calendar source. Ownership verified.
* CAL-02: isVisible toggle is part of this DTO.
*/
@Patch('sources/:id')
async updateSource(
@Param('id') id: string,
@Req() req: Request,
@Body() dto: UpdateCalendarSourceDto,
) {
const { userId } = this.extractContext(req);
return this.calendarService.updateSource(id, userId, dto);
}
/**
* DELETE /calendar/sources/:id
* Removes a calendar source. Ownership verified (T-05-12).
*/
@Delete('sources/:id')
async deleteSource(
@Param('id') id: string,
@Req() req: Request,
) {
const { userId } = this.extractContext(req);
return this.calendarService.deleteSource(id, userId);
}
/**
* POST /calendar/sources/:id/test
* Tests connection to a calendar source. Implemented in Task 3.
*/
@Post('sources/:id/test')
async testSource(
@Param('id') id: string,
@Req() req: Request,
) {
const { userId } = this.extractContext(req);
return this.calendarService.testConnection(id, userId);
}
/**
* GET /calendar/events
* Returns aggregated events from all visible sources. Implemented in Task 3.
*/
@Get('events')
async getEvents(
@Req() req: Request,
@Query() query: CalendarEventsQueryDto,
) {
const { userId } = this.extractContext(req);
return this.calendarService.aggregateEvents(userId, query.from, query.to);
}
}
+33
View File
@@ -0,0 +1,33 @@
import { Module } from '@nestjs/common';
import { CalendarController } from './calendar.controller';
import { CalendarService } from './calendar.service';
import { CalendarCryptoService } from './crypto.service';
import { CalDAVProvider } from './providers/caldav.provider';
import { ICSProvider } from './providers/ics.provider';
import { ExchangeProvider } from './providers/exchange.provider';
/**
* NestJS module for calendar source management and event aggregation.
*
* Provides:
* - CalendarCryptoService: AES-256-GCM encryption for calendar credentials
* - CalendarService: Source CRUD + event aggregation across providers
* - CalDAVProvider: CalDAV protocol integration via tsdav
* - ICSProvider: ICS file fetch + parse via node-ical
* - ExchangeProvider: Exchange Online (Graph) + Exchange Server (EWS) integration
* - CalendarController: REST API for sources and events
*
* Exports CalendarService for potential use by other modules.
*/
@Module({
controllers: [CalendarController],
providers: [
CalendarService,
CalendarCryptoService,
CalDAVProvider,
ICSProvider,
ExchangeProvider,
],
exports: [CalendarService],
})
export class CalendarModule {}
+281
View File
@@ -0,0 +1,281 @@
import {
ForbiddenException,
Injectable,
Logger,
NotFoundException,
} from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { CalendarCryptoService } from './crypto.service';
import { CreateCalendarSourceDto } from './dto/create-calendar-source.dto';
import { UpdateCalendarSourceDto } from './dto/update-calendar-source.dto';
/**
* Common interface for normalized calendar events across all provider types.
*/
export interface CalendarEvent {
id: string;
sourceId: string;
title: string;
start: Date;
end: Date;
allDay: boolean;
location?: string;
description?: string;
color?: string;
}
/**
* Provider interface for calendar source integrations.
* Each provider (ICS, CalDAV, Exchange) implements this contract.
*/
export interface CalendarProvider {
fetchEvents(
source: { url: string; username?: string; password?: string; exchangeMode?: string | null; id: string; color?: string | null },
from: Date,
to: Date,
): Promise<CalendarEvent[]>;
testConnection(
source: { url: string; username?: string; password?: string; exchangeMode?: string | null; id: string },
): Promise<boolean>;
}
/**
* Prisma `select` for safe source responses — NEVER includes encryptedPassword.
* T-05-09: Return hasCredentials boolean instead.
*/
const SOURCE_SAFE_SELECT = {
id: true,
userId: true,
tenantId: true,
name: true,
type: true,
exchangeMode: true,
url: true,
username: true,
// encryptedPassword: NEVER included — T-05-09
color: true,
isVisible: true,
syncIntervalMin: true,
lastSyncAt: true,
lastSyncError: true,
createdAt: true,
updatedAt: true,
} as const;
/**
* Private IP ranges for SSRF protection (T-05-11).
*/
const PRIVATE_IP_PATTERNS = [
/^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,
/^192\.168\.\d{1,3}\.\d{1,3}$/,
/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,
/^169\.254\.\d{1,3}\.\d{1,3}$/,
/^172\.(1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}$/,
/^0\.0\.0\.0$/,
/^\[::1\]$/,
/^\[fc00:/,
/^\[fd00:/,
/^\[fe80:/,
];
/**
* Service for calendar source CRUD and event aggregation.
*
* Source config is per-user (D-09), not per-tenant.
* Credentials encrypted at rest via CalendarCryptoService (T-05-10).
*/
@Injectable()
export class CalendarService {
private readonly logger = new Logger(CalendarService.name);
constructor(
private readonly prisma: PrismaService,
private readonly crypto: CalendarCryptoService,
) {}
/**
* Returns all calendar sources for a user WITHOUT encryptedPassword.
* Adds a `hasCredentials` boolean so the UI knows if credentials are set.
*/
async getSources(userId: string) {
const sources = await this.prisma.calendarSource.findMany({
where: { userId },
select: {
...SOURCE_SAFE_SELECT,
encryptedPassword: true, // Need it only to derive hasCredentials
},
orderBy: { createdAt: 'asc' },
});
return sources.map(({ encryptedPassword, ...source }) => ({
...source,
hasCredentials: !!encryptedPassword,
}));
}
/**
* Creates a new calendar source. Encrypts password before storage.
* T-05-11: Validates URL against private IP ranges (SSRF).
*/
async addSource(userId: string, tenantId: string, dto: CreateCalendarSourceDto) {
await this.validateUrlNotPrivate(dto.url);
const data: Record<string, unknown> = {
userId,
tenantId,
name: dto.name,
type: dto.type,
url: dto.url,
username: dto.username ?? null,
exchangeMode: dto.exchangeMode ?? null,
color: dto.color ?? '#3B82F6',
};
if (dto.password) {
data.encryptedPassword = this.crypto.encrypt(dto.password);
}
const created = await this.prisma.calendarSource.create({
data: data as any,
select: SOURCE_SAFE_SELECT,
});
return { ...created, hasCredentials: !!dto.password };
}
/**
* Updates a calendar source. Ownership check ensures user can only modify their own sources.
* Re-encrypts password if provided; T-05-12 ownership enforcement.
*/
async updateSource(id: string, userId: string, dto: UpdateCalendarSourceDto) {
const existing = await this.prisma.calendarSource.findUnique({
where: { id },
select: { userId: true },
});
if (!existing) {
throw new NotFoundException('Calendar source not found');
}
if (existing.userId !== userId) {
throw new ForbiddenException('Not your calendar source');
}
if (dto.url) {
await this.validateUrlNotPrivate(dto.url);
}
const data: Record<string, unknown> = {};
if (dto.name !== undefined) data.name = dto.name;
if (dto.type !== undefined) data.type = dto.type;
if (dto.url !== undefined) data.url = dto.url;
if (dto.username !== undefined) data.username = dto.username;
if (dto.exchangeMode !== undefined) data.exchangeMode = dto.exchangeMode;
if (dto.color !== undefined) data.color = dto.color;
if (dto.isVisible !== undefined) data.isVisible = dto.isVisible;
if (dto.password !== undefined) {
data.encryptedPassword = dto.password
? this.crypto.encrypt(dto.password)
: null;
}
const updated = await this.prisma.calendarSource.update({
where: { id },
data: data as any,
select: {
...SOURCE_SAFE_SELECT,
encryptedPassword: true,
},
});
const { encryptedPassword, ...safe } = updated;
return { ...safe, hasCredentials: !!encryptedPassword };
}
/**
* Deletes a calendar source. Ownership check enforced (T-05-12).
*/
async deleteSource(id: string, userId: string) {
const existing = await this.prisma.calendarSource.findUnique({
where: { id },
select: { userId: true },
});
if (!existing) {
throw new NotFoundException('Calendar source not found');
}
if (existing.userId !== userId) {
throw new ForbiddenException('Not your calendar source');
}
await this.prisma.calendarSource.delete({ where: { id } });
return { deleted: true };
}
/**
* Test connection to a calendar source via its provider.
* Stub — full implementation in Task 3.
*/
async testConnection(id: string, userId: string): Promise<{ success: boolean; error?: string }> {
const source = await this.prisma.calendarSource.findUnique({ where: { id } });
if (!source) throw new NotFoundException('Calendar source not found');
if (source.userId !== userId) throw new ForbiddenException('Not your calendar source');
return { success: false, error: 'Not yet implemented' };
}
/**
* Aggregate events from all visible sources for a user.
* Stub — full implementation in Task 3.
*/
async aggregateEvents(
userId: string,
from?: string,
to?: string,
): Promise<CalendarEvent[]> {
return [];
}
/**
* Decrypts stored credentials for a source (used internally by providers).
* NEVER expose this in API responses.
*/
decryptSourcePassword(encryptedPassword: string): string {
return this.crypto.decrypt(encryptedPassword);
}
/**
* SSRF protection: reject URLs that resolve to private IP ranges.
* T-05-11: Combined with https-only DTO validation.
*/
private async validateUrlNotPrivate(url: string): Promise<void> {
try {
const parsed = new URL(url);
const hostname = parsed.hostname;
// Check against private IP patterns
for (const pattern of PRIVATE_IP_PATTERNS) {
if (pattern.test(hostname)) {
throw new ForbiddenException(
'Calendar source URL must not point to private/internal networks',
);
}
}
// Also block localhost variants
if (
hostname === 'localhost' ||
hostname === 'ip6-localhost' ||
hostname.endsWith('.local') ||
hostname.endsWith('.internal')
) {
throw new ForbiddenException(
'Calendar source URL must not point to localhost or local networks',
);
}
} catch (error) {
if (error instanceof ForbiddenException) throw error;
throw new ForbiddenException('Invalid calendar source URL');
}
}
}
+75
View File
@@ -0,0 +1,75 @@
import { Injectable, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
/**
* Encryption service for calendar source credentials.
*
* Uses AES-256-GCM with a 32-byte hex key from CALENDAR_ENCRYPTION_KEY env var.
* Encrypted values are stored as `iv:authTag:ciphertext` (hex-joined).
*
* Security: T-05-10 — credentials encrypted at rest, never returned in GET responses.
*/
@Injectable()
export class CalendarCryptoService implements OnModuleInit {
private key!: Buffer;
constructor(private readonly configService: ConfigService) {}
onModuleInit() {
const hexKey = this.configService.get<string>('CALENDAR_ENCRYPTION_KEY');
if (!hexKey) {
throw new Error(
'CALENDAR_ENCRYPTION_KEY is not set. Generate one with: openssl rand -hex 32',
);
}
if (hexKey.length !== 64) {
throw new Error(
`CALENDAR_ENCRYPTION_KEY must be a 64-character hex string (32 bytes). Got ${hexKey.length} characters.`,
);
}
this.key = Buffer.from(hexKey, 'hex');
}
/**
* Encrypts plaintext using AES-256-GCM.
* @returns `iv:authTag:ciphertext` (all hex-encoded, colon-separated)
*/
encrypt(plaintext: string): string {
const iv = randomBytes(12); // 96-bit IV for GCM
const cipher = createCipheriv('aes-256-gcm', this.key, iv);
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag().toString('hex');
return `${iv.toString('hex')}:${authTag}:${encrypted}`;
}
/**
* Decrypts a stored `iv:authTag:ciphertext` value.
* @returns The original plaintext
*/
decrypt(stored: string): string {
const parts = stored.split(':');
if (parts.length !== 3) {
throw new Error('Invalid encrypted value format. Expected iv:authTag:ciphertext');
}
const [ivHex, authTagHex, ciphertext] = parts;
const iv = Buffer.from(ivHex, 'hex');
const authTag = Buffer.from(authTagHex, 'hex');
const decipher = createDecipheriv('aes-256-gcm', this.key, iv);
decipher.setAuthTag(authTag);
let decrypted = decipher.update(ciphertext, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}
@@ -0,0 +1,16 @@
import { IsDateString, IsOptional } from 'class-validator';
/**
* DTO for querying aggregated calendar events.
*
* Default window: now to now + 30 days (applied in CalendarService).
*/
export class CalendarEventsQueryDto {
@IsOptional()
@IsDateString()
from?: string;
@IsOptional()
@IsDateString()
to?: string;
}
@@ -0,0 +1,47 @@
import {
IsBoolean,
IsHexColor,
IsIn,
IsNotEmpty,
IsOptional,
IsString,
IsUrl,
} from 'class-validator';
/**
* DTO for creating a new calendar source.
*
* Security:
* - T-05-11: URL restricted to https only (SSRF mitigation)
* - T-05-10: password is plaintext in transit (over TLS), encrypted at rest by CryptoService
*/
export class CreateCalendarSourceDto {
@IsString()
@IsNotEmpty()
name!: string;
@IsIn(['caldav', 'ics', 'exchange'])
type!: string;
@IsUrl(
{ protocols: ['https'], require_protocol: true },
{ message: 'URL must use HTTPS protocol' },
)
url!: string;
@IsOptional()
@IsString()
username?: string;
@IsOptional()
@IsString()
password?: string;
@IsOptional()
@IsIn(['ews', 'graph'])
exchangeMode?: string;
@IsOptional()
@IsHexColor()
color?: string;
}
@@ -0,0 +1,55 @@
import {
IsBoolean,
IsHexColor,
IsIn,
IsNotEmpty,
IsOptional,
IsString,
IsUrl,
} from 'class-validator';
/**
* DTO for updating an existing calendar source.
* All fields are optional — only provided fields are updated.
*
* Security:
* - T-05-11: URL restricted to https only if provided
* - CAL-02: isVisible toggle for widget source visibility
*/
export class UpdateCalendarSourceDto {
@IsOptional()
@IsString()
@IsNotEmpty()
name?: string;
@IsOptional()
@IsIn(['caldav', 'ics', 'exchange'])
type?: string;
@IsOptional()
@IsUrl(
{ protocols: ['https'], require_protocol: true },
{ message: 'URL must use HTTPS protocol' },
)
url?: string;
@IsOptional()
@IsString()
username?: string;
@IsOptional()
@IsString()
password?: string;
@IsOptional()
@IsIn(['ews', 'graph'])
exchangeMode?: string;
@IsOptional()
@IsHexColor()
color?: string;
@IsOptional()
@IsBoolean()
isVisible?: boolean;
}
@@ -0,0 +1,27 @@
import { Injectable, Logger } from '@nestjs/common';
import { CalendarEvent, CalendarProvider } from '../calendar.service';
/**
* CalDAV calendar provider — uses tsdav for protocol handling.
* Full implementation in Task 2.
*/
@Injectable()
export class CalDAVProvider implements CalendarProvider {
private readonly logger = new Logger(CalDAVProvider.name);
async fetchEvents(
source: { url: string; username?: string; password?: string; id: string; color?: string | null },
from: Date,
to: Date,
): Promise<CalendarEvent[]> {
// Stub — implemented in Task 2
return [];
}
async testConnection(
source: { url: string; username?: string; password?: string; id: string },
): Promise<boolean> {
// Stub — implemented in Task 2
return false;
}
}
@@ -0,0 +1,28 @@
import { Injectable, Logger } from '@nestjs/common';
import { CalendarEvent, CalendarProvider } from '../calendar.service';
/**
* Exchange calendar provider — dispatches on exchangeMode ('graph' vs 'ews').
* Uses @microsoft/microsoft-graph-client for Graph and ews-javascript-api for EWS.
* Full implementation in Task 2.
*/
@Injectable()
export class ExchangeProvider implements CalendarProvider {
private readonly logger = new Logger(ExchangeProvider.name);
async fetchEvents(
source: { url: string; username?: string; password?: string; exchangeMode?: string | null; id: string; color?: string | null },
from: Date,
to: Date,
): Promise<CalendarEvent[]> {
// Stub — implemented in Task 2
return [];
}
async testConnection(
source: { url: string; username?: string; password?: string; exchangeMode?: string | null; id: string },
): Promise<boolean> {
// Stub — implemented in Task 2
return false;
}
}
@@ -0,0 +1,27 @@
import { Injectable, Logger } from '@nestjs/common';
import { CalendarEvent, CalendarProvider } from '../calendar.service';
/**
* ICS calendar provider — fetches and parses .ics files via HTTPS.
* Uses node-ical for parsing. Full implementation in Task 2.
*/
@Injectable()
export class ICSProvider implements CalendarProvider {
private readonly logger = new Logger(ICSProvider.name);
async fetchEvents(
source: { url: string; id: string; color?: string | null },
from: Date,
to: Date,
): Promise<CalendarEvent[]> {
// Stub — implemented in Task 2
return [];
}
async testConnection(
source: { url: string; id: string },
): Promise<boolean> {
// Stub — implemented in Task 2
return false;
}
}
+365 -5
View File
@@ -20,6 +20,9 @@ importers:
apps/api: apps/api:
dependencies: dependencies:
'@microsoft/microsoft-graph-client':
specifier: 3.0.7
version: 3.0.7
'@nestjs-modules/mailer': '@nestjs-modules/mailer':
specifier: ^2.3.7 specifier: ^2.3.7
version: 2.3.7(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.27)(chokidar@4.0.3)(nodemailer@9.0.1)(svgo@4.0.1)(terser@5.48.0)(typescript@5.9.3) version: 2.3.7(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.27)(chokidar@4.0.3)(nodemailer@9.0.1)(svgo@4.0.1)(terser@5.48.0)(typescript@5.9.3)
@@ -65,9 +68,15 @@ importers:
cookie-parser: cookie-parser:
specifier: ^1.4.7 specifier: ^1.4.7
version: 1.4.7 version: 1.4.7
ews-javascript-api:
specifier: 0.15.3
version: 0.15.3
ldapts: ldapts:
specifier: ^8.1.8 specifier: ^8.1.8
version: 8.1.8 version: 8.1.8
node-ical:
specifier: 0.26.1
version: 0.26.1
nodemailer: nodemailer:
specifier: ^9.0.1 specifier: ^9.0.1
version: 9.0.1 version: 9.0.1
@@ -86,6 +95,9 @@ importers:
rxjs: rxjs:
specifier: ^7.0.0 specifier: ^7.0.0
version: 7.8.2 version: 7.8.2
tsdav:
specifier: 2.2.2
version: 2.2.2
devDependencies: devDependencies:
'@nestjs/cli': '@nestjs/cli':
specifier: ^11.0.0 specifier: ^11.0.0
@@ -261,6 +273,14 @@ packages:
'@asamuzakjp/nwsapi@2.3.9': '@asamuzakjp/nwsapi@2.3.9':
resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==}
'@azure/msal-common@14.16.1':
resolution: {integrity: sha512-nyxsA6NA4SVKh5YyRpbSXiMr7oQbwark7JU9LMeg6tJYTSPyAGkdx61wPT4gyxZfxlSxMMEyAsWaubBlNyIa1w==}
engines: {node: '>=0.8.0'}
'@azure/msal-node@2.16.3':
resolution: {integrity: sha512-CO+SE4weOsfJf+C5LM8argzvotrXw252/ZU6SM2Tz63fEblhH1uuVaaO4ISYFuN4Q6BhTo7I3qIdi8ydUQCqhw==}
engines: {node: '>=16'}
'@babel/code-frame@7.29.7': '@babel/code-frame@7.29.7':
resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
@@ -474,6 +494,13 @@ packages:
'@epic-web/invariant@1.0.0': '@epic-web/invariant@1.0.0':
resolution: {integrity: sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==} resolution: {integrity: sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==}
'@ewsjs/ntlm-client@3.0.1':
resolution: {integrity: sha512-eJEyxiR0Eb1kRU0N96ISubBgyhZJ8PXhw+gj5m5My+M5CqDEn8Ae2xPHiSyo0fUWiSj1A2tQ+kk3PZmursR5kQ==}
engines: {node: '>=4.0.0'}
'@ewsjs/xhr@3.1.3':
resolution: {integrity: sha512-vUMv1XwUvoGmlhLl0b/zXDB7qIUz4WCQqy70vsdl71RhnWXxnlUA/hIL0VkOBJSLBPEBkhsmERkbhBpnGvpkng==}
'@exodus/bytes@1.15.1': '@exodus/bytes@1.15.1':
resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==} resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==}
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
@@ -802,10 +829,32 @@ packages:
'@jridgewell/trace-mapping@0.3.31': '@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
'@js-temporal/polyfill@0.5.1':
resolution: {integrity: sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ==}
engines: {node: '>=12'}
'@lukeed/csprng@1.1.0': '@lukeed/csprng@1.1.0':
resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==}
engines: {node: '>=8'} engines: {node: '>=8'}
'@microsoft/microsoft-graph-client@3.0.7':
resolution: {integrity: sha512-/AazAV/F+HK4LIywF9C+NYHcJo038zEnWkteilcxC1FM/uK/4NVGDKGrxx7nNq1ybspAroRKT4I1FHfxQzxkUw==}
engines: {node: '>=12.0.0'}
peerDependencies:
'@azure/identity': '*'
'@azure/msal-browser': '*'
buffer: '*'
stream-browserify: '*'
peerDependenciesMeta:
'@azure/identity':
optional: true
'@azure/msal-browser':
optional: true
buffer:
optional: true
stream-browserify:
optional: true
'@napi-rs/wasm-runtime@1.1.5': '@napi-rs/wasm-runtime@1.1.5':
resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==}
peerDependencies: peerDependencies:
@@ -1687,6 +1736,10 @@ packages:
'@webassemblyjs/wast-printer@1.14.1': '@webassemblyjs/wast-printer@1.14.1':
resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==}
'@xmldom/xmldom@0.8.13':
resolution: {integrity: sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==}
engines: {node: '>=10.0.0'}
'@xtuc/ieee754@1.2.0': '@xtuc/ieee754@1.2.0':
resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==}
@@ -1723,6 +1776,14 @@ packages:
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
hasBin: true hasBin: true
agent-base@6.0.2:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'}
agent-base@7.1.4:
resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
engines: {node: '>= 14'}
ajv-formats@2.1.1: ajv-formats@2.1.1:
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
peerDependencies: peerDependencies:
@@ -1820,6 +1881,12 @@ packages:
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
engines: {node: '>=12'} engines: {node: '>=12'}
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
axios@1.18.1:
resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==}
babel-walk@3.0.0-canary-5: babel-walk@3.0.0-canary-5:
resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==} resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==}
engines: {node: '>= 10.0.0'} engines: {node: '>= 10.0.0'}
@@ -1834,6 +1901,9 @@ packages:
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
engines: {node: 18 || 20 || >=22} engines: {node: 18 || 20 || >=22}
base-64@1.0.0:
resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==}
base64-js@1.5.1: base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
@@ -2018,6 +2088,10 @@ packages:
color-name@1.1.4: color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
comma-separated-tokens@2.0.3: comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
@@ -2237,6 +2311,10 @@ packages:
defu@6.1.7: defu@6.1.7:
resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==}
delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
depd@2.0.0: depd@2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
@@ -2245,6 +2323,9 @@ packages:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'} engines: {node: '>=6'}
des.js@1.1.0:
resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==}
destr@2.0.5: destr@2.0.5:
resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
@@ -2421,6 +2502,10 @@ packages:
resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
es-set-tostringtag@2.1.0:
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
engines: {node: '>= 0.4'}
escalade@3.2.0: escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -2484,6 +2569,9 @@ packages:
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
engines: {node: '>=0.8.x'} engines: {node: '>=0.8.x'}
ews-javascript-api@0.15.3:
resolution: {integrity: sha512-7re0Q/FSHyM9MgcPxjcNZlQuyzHmU7wHOdODRmQYMgxlGU8HB73cZdysyia4rE+CQCFyqhZqV8vMddYJXDwA9Q==}
execa@5.1.1: execa@5.1.1:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -2545,6 +2633,15 @@ packages:
resolution: {integrity: sha512-5SM1+H2CcuJ3gGEwTiVo/+nd/hYpNj9Ch3iMDOQ58ndY+VGQ2QdvaUTkd3otjZvYnd/8LF/HkJ5cx7PBq0orCQ==} resolution: {integrity: sha512-5SM1+H2CcuJ3gGEwTiVo/+nd/hYpNj9Ch3iMDOQ58ndY+VGQ2QdvaUTkd3otjZvYnd/8LF/HkJ5cx7PBq0orCQ==}
hasBin: true hasBin: true
follow-redirects@1.16.0:
resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
foreground-child@3.3.1: foreground-child@3.3.1:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'} engines: {node: '>=14'}
@@ -2556,6 +2653,10 @@ packages:
typescript: '>3.6.0' typescript: '>3.6.0'
webpack: ^5.11.0 webpack: ^5.11.0
form-data@4.0.6:
resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==}
engines: {node: '>= 6'}
forwarded@0.2.0: forwarded@0.2.0:
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
@@ -2754,10 +2855,27 @@ packages:
htmlparser2@9.1.0: htmlparser2@9.1.0:
resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==}
http-cookie-agent@5.0.4:
resolution: {integrity: sha512-OtvikW69RvfyP6Lsequ0fN5R49S+8QcS9zwd58k6VSr6r57T8G29BkPdyrBcSwLq6ExLs9V+rBlfxu7gDstJag==}
engines: {node: '>=14.18.0 <15.0.0 || >=16.0.0'}
peerDependencies:
deasync: ^0.1.26
tough-cookie: ^4.0.0
undici: ^5.11.0
peerDependenciesMeta:
deasync:
optional: true
undici:
optional: true
http-errors@2.0.1: http-errors@2.0.1:
resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
https-proxy-agent@5.0.1:
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
engines: {node: '>= 6'}
human-signals@2.1.0: human-signals@2.1.0:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
engines: {node: '>=10.17.0'} engines: {node: '>=10.17.0'}
@@ -2908,6 +3026,9 @@ packages:
js-cookie@3.0.8: js-cookie@3.0.8:
resolution: {integrity: sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==} resolution: {integrity: sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==}
js-md4@0.3.2:
resolution: {integrity: sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==}
js-stringify@1.0.2: js-stringify@1.0.2:
resolution: {integrity: sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==} resolution: {integrity: sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==}
@@ -2918,6 +3039,9 @@ packages:
resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==}
hasBin: true hasBin: true
jsbi@4.3.2:
resolution: {integrity: sha512-9fqMSQbhJykSeii05nxKl4m6Eqn2P6rOlYiS+C5Dr/HPIU/7yZxu5qzbs40tgaFORiw2Amd0mirjxatXYMkIew==}
jsdom@29.1.1: jsdom@29.1.1:
resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==}
engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0}
@@ -3335,6 +3459,9 @@ packages:
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
engines: {node: '>=4'} engines: {node: '>=4'}
minimalistic-assert@1.0.1:
resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==}
minimatch@10.2.5: minimatch@10.2.5:
resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==}
engines: {node: 18 || 20 || >=22} engines: {node: 18 || 20 || >=22}
@@ -3448,6 +3575,12 @@ packages:
resolution: {integrity: sha512-cOrV1zC8SekUpZ2YGT174iWADRnuttYMtrAypQ1UvYXOUCOUc1DvwB8Dx8DH9+51+WyA0fNVOmUDx1Bc8qztqQ==} resolution: {integrity: sha512-cOrV1zC8SekUpZ2YGT174iWADRnuttYMtrAypQ1UvYXOUCOUc1DvwB8Dx8DH9+51+WyA0fNVOmUDx1Bc8qztqQ==}
hasBin: true hasBin: true
moment-timezone@0.5.48:
resolution: {integrity: sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==}
moment@2.30.1:
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
ms@2.1.3: ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -3531,6 +3664,10 @@ packages:
resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==}
hasBin: true hasBin: true
node-ical@0.26.1:
resolution: {integrity: sha512-KoYLpsz7Ga9lPDpt9vy0iKcgcb/9Ix7ICRZd0csLXMl2lZOSONGj7HrcktJFR7Jid1l44Zu1H4k/1nB04rWPgQ==}
engines: {node: '>=20'}
node-releases@2.0.48: node-releases@2.0.48:
resolution: {integrity: sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==} resolution: {integrity: sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==}
engines: {node: '>=18'} engines: {node: '>=18'}
@@ -3949,6 +4086,13 @@ packages:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
proxy-from-env@2.1.0:
resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==}
engines: {node: '>=10'}
psl@1.15.0:
resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
pug-attrs@3.0.0: pug-attrs@3.0.0:
resolution: {integrity: sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==} resolution: {integrity: sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==}
@@ -4000,6 +4144,9 @@ packages:
resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==}
engines: {node: '>=0.6'} engines: {node: '>=0.6'}
querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
range-parser@1.2.1: range-parser@1.2.1:
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
@@ -4138,6 +4285,9 @@ packages:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
resize-observer-polyfill@1.5.1: resize-observer-polyfill@1.5.1:
resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
@@ -4163,6 +4313,9 @@ packages:
resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==}
engines: {node: '>= 18'} engines: {node: '>= 18'}
rrule-temporal@1.5.3:
resolution: {integrity: sha512-qALnXyu4MKNUeykkkO0r6Xxl5or3rM8Cf6ibKIe/29sgmq3tGm1oNq4G1Ddp8Ku3mnKmvC3+3yFAJ3OgOu6OJw==}
run-applescript@5.0.0: run-applescript@5.0.0:
resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -4391,6 +4544,12 @@ packages:
resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==}
engines: {node: '>=6'} engines: {node: '>=6'}
temporal-polyfill@0.3.2:
resolution: {integrity: sha512-TzHthD/heRK947GNiSu3Y5gSPpeUDH34+LESnfsq8bqpFhsB79HFBX8+Z834IVX68P3EUyRPZK5bL/1fh437Eg==}
temporal-spec@0.3.1:
resolution: {integrity: sha512-B4TUhezh9knfSIMwt7RVggApDRJZo73uZdj8AacL2mZ8RP5KtLianh2MXxL06GN9ESYiIsiuoLQhgVfwe55Yhw==}
terser-webpack-plugin@5.6.1: terser-webpack-plugin@5.6.1:
resolution: {integrity: sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==} resolution: {integrity: sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==}
engines: {node: '>= 10.13.0'} engines: {node: '>= 10.13.0'}
@@ -4476,6 +4635,10 @@ packages:
resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==}
engines: {node: '>=14.16'} engines: {node: '>=14.16'}
tough-cookie@4.1.4:
resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==}
engines: {node: '>=6'}
tough-cookie@6.0.1: tough-cookie@6.0.1:
resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==}
engines: {node: '>=16'} engines: {node: '>=16'}
@@ -4498,6 +4661,10 @@ packages:
resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==}
engines: {node: '>=6'} engines: {node: '>=6'}
tsdav@2.2.2:
resolution: {integrity: sha512-/uC/RItcdYVxUj8b2gT4CorAkUmDFUuzhgS4XVT+OVzGRE80hH5ldubcWH13dHa2T9rNaXu6UIEWHlQ1UL7H1Q==}
engines: {node: '>=18'}
tslib@2.8.1: tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@@ -4572,6 +4739,10 @@ packages:
unist-util-visit@5.1.0: unist-util-visit@5.1.0:
resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==}
universalify@0.2.0:
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
engines: {node: '>= 4.0.0'}
universalify@2.0.1: universalify@2.0.1:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'} engines: {node: '>= 10.0.0'}
@@ -4589,6 +4760,9 @@ packages:
uri-js@4.4.1: uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
url-parse@1.5.10:
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
use-intl@4.13.0: use-intl@4.13.0:
resolution: {integrity: sha512-fAFDrWaASxlhXOipcOyb5VDD+YONqj6+8O8EcG/J7RBoOUF3A8YahRWLN+mBxYMrlMQB8N6Voqk5X+YC+HSL0A==} resolution: {integrity: sha512-fAFDrWaASxlhXOipcOyb5VDD+YONqj6+8O8EcG/J7RBoOUF3A8YahRWLN+mBxYMrlMQB8N6Voqk5X+YC+HSL0A==}
peerDependencies: peerDependencies:
@@ -4601,6 +4775,11 @@ packages:
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
engines: {node: '>= 0.4.0'} engines: {node: '>= 0.4.0'}
uuid@8.3.2:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
hasBin: true
uuid@9.0.1: uuid@9.0.1:
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
@@ -4804,6 +4983,10 @@ packages:
wrappy@1.0.2: wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
xml-js@1.6.11:
resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
hasBin: true
xml-name-validator@5.0.0: xml-name-validator@5.0.0:
resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@@ -4931,6 +5114,14 @@ snapshots:
'@asamuzakjp/nwsapi@2.3.9': {} '@asamuzakjp/nwsapi@2.3.9': {}
'@azure/msal-common@14.16.1': {}
'@azure/msal-node@2.16.3':
dependencies:
'@azure/msal-common': 14.16.1
jsonwebtoken: 9.0.3
uuid: 8.3.2
'@babel/code-frame@7.29.7': '@babel/code-frame@7.29.7':
dependencies: dependencies:
'@babel/helper-validator-identifier': 7.29.7 '@babel/helper-validator-identifier': 7.29.7
@@ -5096,6 +5287,25 @@ snapshots:
'@epic-web/invariant@1.0.0': {} '@epic-web/invariant@1.0.0': {}
'@ewsjs/ntlm-client@3.0.1':
dependencies:
des.js: 1.1.0
js-md4: 0.3.2
optionalDependencies:
extend: 3.0.2
'@ewsjs/xhr@3.1.3':
dependencies:
'@ewsjs/ntlm-client': 3.0.1
axios: 1.18.1
http-cookie-agent: 5.0.4(tough-cookie@4.1.4)
tough-cookie: 4.1.4
transitivePeerDependencies:
- deasync
- debug
- supports-color
- undici
'@exodus/bytes@1.15.1': {} '@exodus/bytes@1.15.1': {}
'@formatjs/fast-memoize@3.1.6': {} '@formatjs/fast-memoize@3.1.6': {}
@@ -5384,8 +5594,17 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2 '@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/sourcemap-codec': 1.5.5
'@js-temporal/polyfill@0.5.1':
dependencies:
jsbi: 4.3.2
'@lukeed/csprng@1.1.0': {} '@lukeed/csprng@1.1.0': {}
'@microsoft/microsoft-graph-client@3.0.7':
dependencies:
'@babel/runtime': 7.29.7
tslib: 2.8.1
'@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
dependencies: dependencies:
'@emnapi/core': 1.10.0 '@emnapi/core': 1.10.0
@@ -6252,6 +6471,8 @@ snapshots:
'@webassemblyjs/ast': 1.14.1 '@webassemblyjs/ast': 1.14.1
'@xtuc/long': 4.2.2 '@xtuc/long': 4.2.2
'@xmldom/xmldom@0.8.13': {}
'@xtuc/ieee754@1.2.0': {} '@xtuc/ieee754@1.2.0': {}
'@xtuc/long@4.2.2': {} '@xtuc/long@4.2.2': {}
@@ -6283,6 +6504,14 @@ snapshots:
acorn@8.17.0: {} acorn@8.17.0: {}
agent-base@6.0.2:
dependencies:
debug: 4.4.3
transitivePeerDependencies:
- supports-color
agent-base@7.1.4: {}
ajv-formats@2.1.1(ajv@8.20.0): ajv-formats@2.1.1(ajv@8.20.0):
optionalDependencies: optionalDependencies:
ajv: 8.20.0 ajv: 8.20.0
@@ -6372,6 +6601,18 @@ snapshots:
assertion-error@2.0.1: {} assertion-error@2.0.1: {}
asynckit@0.4.0: {}
axios@1.18.1:
dependencies:
follow-redirects: 1.16.0
form-data: 4.0.6
https-proxy-agent: 5.0.1
proxy-from-env: 2.1.0
transitivePeerDependencies:
- debug
- supports-color
babel-walk@3.0.0-canary-5: babel-walk@3.0.0-canary-5:
dependencies: dependencies:
'@babel/types': 7.29.7 '@babel/types': 7.29.7
@@ -6383,6 +6624,8 @@ snapshots:
balanced-match@4.0.4: {} balanced-match@4.0.4: {}
base-64@1.0.0: {}
base64-js@1.5.1: {} base64-js@1.5.1: {}
baseline-browser-mapping@2.10.38: {} baseline-browser-mapping@2.10.38: {}
@@ -6600,6 +6843,10 @@ snapshots:
color-name@1.1.4: {} color-name@1.1.4: {}
combined-stream@1.0.8:
dependencies:
delayed-stream: 1.0.0
comma-separated-tokens@2.0.3: {} comma-separated-tokens@2.0.3: {}
commander@10.0.1: commander@10.0.1:
@@ -6838,10 +7085,17 @@ snapshots:
defu@6.1.7: {} defu@6.1.7: {}
delayed-stream@1.0.0: {}
depd@2.0.0: {} depd@2.0.0: {}
dequal@2.0.3: {} dequal@2.0.3: {}
des.js@1.1.0:
dependencies:
inherits: 2.0.4
minimalistic-assert: 1.0.1
destr@2.0.5: {} destr@2.0.5: {}
detect-indent@6.1.0: detect-indent@6.1.0:
@@ -7017,6 +7271,13 @@ snapshots:
dependencies: dependencies:
es-errors: 1.3.0 es-errors: 1.3.0
es-set-tostringtag@2.1.0:
dependencies:
es-errors: 1.3.0
get-intrinsic: 1.3.0
has-tostringtag: 1.0.2
hasown: 2.0.4
escalade@3.2.0: {} escalade@3.2.0: {}
escape-goat@3.0.0: escape-goat@3.0.0:
@@ -7060,6 +7321,21 @@ snapshots:
events@3.3.0: {} events@3.3.0: {}
ews-javascript-api@0.15.3:
dependencies:
'@azure/msal-node': 2.16.3
'@ewsjs/xhr': 3.1.3
'@xmldom/xmldom': 0.8.13
base64-js: 1.5.1
moment: 2.30.1
moment-timezone: 0.5.48
uuid: 9.0.1
transitivePeerDependencies:
- deasync
- debug
- supports-color
- undici
execa@5.1.1: execa@5.1.1:
dependencies: dependencies:
cross-spawn: 7.0.6 cross-spawn: 7.0.6
@@ -7163,6 +7439,8 @@ snapshots:
rc: 1.2.8 rc: 1.2.8
optional: true optional: true
follow-redirects@1.16.0: {}
foreground-child@3.3.1: foreground-child@3.3.1:
dependencies: dependencies:
cross-spawn: 7.0.6 cross-spawn: 7.0.6
@@ -7186,6 +7464,14 @@ snapshots:
typescript: 5.9.3 typescript: 5.9.3
webpack: 5.106.2(@swc/core@1.15.41)(cssnano@7.1.9(postcss@8.5.15))(postcss@8.5.15) webpack: 5.106.2(@swc/core@1.15.41)(cssnano@7.1.9(postcss@8.5.15))(postcss@8.5.15)
form-data@4.0.6:
dependencies:
asynckit: 0.4.0
combined-stream: 1.0.8
es-set-tostringtag: 2.1.0
hasown: 2.0.4
mime-types: 2.1.35
forwarded@0.2.0: {} forwarded@0.2.0: {}
fresh@2.0.0: {} fresh@2.0.0: {}
@@ -7290,7 +7576,6 @@ snapshots:
has-tostringtag@1.0.2: has-tostringtag@1.0.2:
dependencies: dependencies:
has-symbols: 1.1.0 has-symbols: 1.1.0
optional: true
hasown@2.0.4: hasown@2.0.4:
dependencies: dependencies:
@@ -7493,6 +7778,11 @@ snapshots:
entities: 4.5.0 entities: 4.5.0
optional: true optional: true
http-cookie-agent@5.0.4(tough-cookie@4.1.4):
dependencies:
agent-base: 7.1.4
tough-cookie: 4.1.4
http-errors@2.0.1: http-errors@2.0.1:
dependencies: dependencies:
depd: 2.0.0 depd: 2.0.0
@@ -7501,6 +7791,13 @@ snapshots:
statuses: 2.0.2 statuses: 2.0.2
toidentifier: 1.0.1 toidentifier: 1.0.1
https-proxy-agent@5.0.1:
dependencies:
agent-base: 6.0.2
debug: 4.4.3
transitivePeerDependencies:
- supports-color
human-signals@2.1.0: human-signals@2.1.0:
optional: true optional: true
@@ -7645,6 +7942,8 @@ snapshots:
js-cookie@3.0.8: js-cookie@3.0.8:
optional: true optional: true
js-md4@0.3.2: {}
js-stringify@1.0.2: js-stringify@1.0.2:
optional: true optional: true
@@ -7654,6 +7953,8 @@ snapshots:
dependencies: dependencies:
argparse: 2.0.1 argparse: 2.0.1
jsbi@4.3.2: {}
jsdom@29.1.1: jsdom@29.1.1:
dependencies: dependencies:
'@asamuzakjp/css-color': 5.1.11 '@asamuzakjp/css-color': 5.1.11
@@ -8278,6 +8579,8 @@ snapshots:
min-indent@1.0.1: {} min-indent@1.0.1: {}
minimalistic-assert@1.0.1: {}
minimatch@10.2.5: minimatch@10.2.5:
dependencies: dependencies:
brace-expansion: 5.0.6 brace-expansion: 5.0.6
@@ -8785,6 +9088,12 @@ snapshots:
- uncss - uncss
optional: true optional: true
moment-timezone@0.5.48:
dependencies:
moment: 2.30.1
moment@2.30.1: {}
ms@2.1.3: {} ms@2.1.3: {}
multer@2.1.1: multer@2.1.1:
@@ -8863,6 +9172,11 @@ snapshots:
node-gyp-build@4.8.4: {} node-gyp-build@4.8.4: {}
node-ical@0.26.1:
dependencies:
rrule-temporal: 1.5.3
temporal-polyfill: 0.3.2
node-releases@2.0.48: {} node-releases@2.0.48: {}
nodemailer@8.0.11: nodemailer@8.0.11:
@@ -9337,6 +9651,12 @@ snapshots:
forwarded: 0.2.0 forwarded: 0.2.0
ipaddr.js: 1.9.1 ipaddr.js: 1.9.1
proxy-from-env@2.1.0: {}
psl@1.15.0:
dependencies:
punycode: 2.3.1
pug-attrs@3.0.0: pug-attrs@3.0.0:
dependencies: dependencies:
constantinople: 4.0.1 constantinople: 4.0.1
@@ -9427,6 +9747,8 @@ snapshots:
dependencies: dependencies:
side-channel: 1.1.1 side-channel: 1.1.1
querystringify@2.2.0: {}
range-parser@1.2.1: {} range-parser@1.2.1: {}
raw-body@3.0.2: raw-body@3.0.2:
@@ -9648,6 +9970,8 @@ snapshots:
require-from-string@2.0.2: {} require-from-string@2.0.2: {}
requires-port@1.0.0: {}
resize-observer-polyfill@1.5.1: {} resize-observer-polyfill@1.5.1: {}
resolve-from@4.0.0: {} resolve-from@4.0.0: {}
@@ -9696,6 +10020,10 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
rrule-temporal@1.5.3:
dependencies:
'@js-temporal/polyfill': 0.5.1
run-applescript@5.0.0: run-applescript@5.0.0:
dependencies: dependencies:
execa: 5.1.1 execa: 5.1.1
@@ -9713,8 +10041,7 @@ snapshots:
safer-buffer@2.1.2: {} safer-buffer@2.1.2: {}
sax@1.6.0: sax@1.6.0: {}
optional: true
saxes@6.0.0: saxes@6.0.0:
dependencies: dependencies:
@@ -9964,6 +10291,12 @@ snapshots:
tapable@2.3.3: {} tapable@2.3.3: {}
temporal-polyfill@0.3.2:
dependencies:
temporal-spec: 0.3.1
temporal-spec@0.3.1: {}
terser-webpack-plugin@5.6.1(@swc/core@1.15.41)(cssnano@7.1.9(postcss@8.5.15))(postcss@8.5.15)(webpack@5.106.2(@swc/core@1.15.41)(cssnano@7.1.9(postcss@8.5.15))(postcss@8.5.15)): terser-webpack-plugin@5.6.1(@swc/core@1.15.41)(cssnano@7.1.9(postcss@8.5.15))(postcss@8.5.15)(webpack@5.106.2(@swc/core@1.15.41)(cssnano@7.1.9(postcss@8.5.15))(postcss@8.5.15)):
dependencies: dependencies:
'@jridgewell/trace-mapping': 0.3.31 '@jridgewell/trace-mapping': 0.3.31
@@ -10014,6 +10347,13 @@ snapshots:
'@tokenizer/token': 0.3.0 '@tokenizer/token': 0.3.0
ieee754: 1.2.1 ieee754: 1.2.1
tough-cookie@4.1.4:
dependencies:
psl: 1.15.0
punycode: 2.3.1
universalify: 0.2.0
url-parse: 1.5.10
tough-cookie@6.0.1: tough-cookie@6.0.1:
dependencies: dependencies:
tldts: 7.4.3 tldts: 7.4.3
@@ -10039,6 +10379,14 @@ snapshots:
minimist: 1.2.8 minimist: 1.2.8
strip-bom: 3.0.0 strip-bom: 3.0.0
tsdav@2.2.2:
dependencies:
base-64: 1.0.0
debug: 4.4.3
xml-js: 1.6.11
transitivePeerDependencies:
- supports-color
tslib@2.8.1: {} tslib@2.8.1: {}
turbo@2.9.18: turbo@2.9.18:
@@ -10129,6 +10477,8 @@ snapshots:
unist-util-is: 6.0.1 unist-util-is: 6.0.1
unist-util-visit-parents: 6.0.2 unist-util-visit-parents: 6.0.2
universalify@0.2.0: {}
universalify@2.0.1: {} universalify@2.0.1: {}
unpipe@1.0.0: {} unpipe@1.0.0: {}
@@ -10143,6 +10493,11 @@ snapshots:
dependencies: dependencies:
punycode: 2.3.1 punycode: 2.3.1
url-parse@1.5.10:
dependencies:
querystringify: 2.2.0
requires-port: 1.0.0
use-intl@4.13.0(react@19.2.7): use-intl@4.13.0(react@19.2.7):
dependencies: dependencies:
'@formatjs/fast-memoize': 3.1.6 '@formatjs/fast-memoize': 3.1.6
@@ -10155,8 +10510,9 @@ snapshots:
utils-merge@1.0.1: {} utils-merge@1.0.1: {}
uuid@9.0.1: uuid@8.3.2: {}
optional: true
uuid@9.0.1: {}
valid-data-url@3.0.1: valid-data-url@3.0.1:
optional: true optional: true
@@ -10353,6 +10709,10 @@ snapshots:
wrappy@1.0.2: {} wrappy@1.0.2: {}
xml-js@1.6.11:
dependencies:
sax: 1.6.0
xml-name-validator@5.0.0: {} xml-name-validator@5.0.0: {}
xmlchars@2.2.0: {} xmlchars@2.2.0: {}