From febc0514e6e3eb30a9c13bf3912227b966b51a6a Mon Sep 17 00:00:00 2001 From: Xavier Abad <77491413+xabg2@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:39:59 +0100 Subject: [PATCH 1/4] feat: local storage, config and sdk services --- .env.example | 5 + .github/workflows/ci.yml | 32 + package.json | 13 +- src/services/config/config.errors.ts | 7 + src/services/config/config.service.test.ts | 48 ++ src/services/config/index.ts | 33 + src/services/local-storage/index.ts | 74 +++ .../local-storage.service.test.ts | 101 +++ src/services/sdk/index.ts | 77 +++ src/services/sdk/payments.service.test.ts | 101 +++ src/services/sdk/payments.service.ts | 17 + src/services/sdk/sdk.service.test.ts | 215 ++++++ vitest.config.ts | 14 + yarn.lock | 617 +++++++++++++++++- 14 files changed, 1347 insertions(+), 7 deletions(-) create mode 100644 .env.example create mode 100644 .github/workflows/ci.yml create mode 100644 src/services/config/config.errors.ts create mode 100644 src/services/config/config.service.test.ts create mode 100644 src/services/config/index.ts create mode 100644 src/services/local-storage/index.ts create mode 100644 src/services/local-storage/local-storage.service.test.ts create mode 100644 src/services/sdk/index.ts create mode 100644 src/services/sdk/payments.service.test.ts create mode 100644 src/services/sdk/payments.service.ts create mode 100644 src/services/sdk/sdk.service.test.ts create mode 100644 vitest.config.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..e0fdd24 --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +VITE_PAYMENTS_API_URL= +VITE_DRIVE_API_URL= +VITE_MAGIC_IV= +VITE_MAGIC_SALT= +VITE_CRYPTO_SECRET= \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c2033b9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: Mail Web CI + +on: + pull_request: + branches: [master] + +jobs: + ci: + runs-on: ubuntu-22.04 + + strategy: + matrix: + node-version: [20.x] + + env: + VITE_PAYMENTS_API_URL: ${{ secrets.PAYMENTS_API_URL }} + VITE_DRIVE_API_URL: ${{ secrets.DRIVE_API_URL }} + VITE_MAGIC_IV: ${{ secrets.MAGIC_IV }} + VITE_MAGIC_SALT: ${{ secrets.MAGIC_SALT }} + VITE_CRYPTO_SECRET: ${{ secrets.CRYPTO_SECRET }} + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "yarn" + + - run: yarn install --frozen-lockfile + - run: yarn test + - run: yarn build diff --git a/package.json b/package.json index 28d1e11..010b98c 100644 --- a/package.json +++ b/package.json @@ -3,14 +3,21 @@ "private": true, "version": "0.0.0", "type": "module", + "engines": { + "node": ">=24" + }, "scripts": { "dev": "vite", "build": "tsc -b && vite build", "lint": "eslint .", - "preview": "vite preview" + "preview": "vite preview", + "test": "vitest run", + "test:ui": "vitest --ui", + "test:coverage": "vitest run --coverage" }, "dependencies": { "@internxt/css-config": "^1.1.0", + "@internxt/sdk": "^1.15.1", "@internxt/ui": "^0.1.9", "@phosphor-icons/react": "^2.1.10", "@tailwindcss/vite": "^4.2.1", @@ -41,9 +48,11 @@ "eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-refresh": "^0.4.24", "globals": "^16.5.0", + "jsdom": "^28.1.0", "typescript": "~5.9.3", "typescript-eslint": "^8.48.0", "vite": "^7.3.1", - "vite-plugin-node-polyfills": "^0.25.0" + "vite-plugin-node-polyfills": "^0.25.0", + "vitest": "^4.0.18" } } diff --git a/src/services/config/config.errors.ts b/src/services/config/config.errors.ts new file mode 100644 index 0000000..1aee6b2 --- /dev/null +++ b/src/services/config/config.errors.ts @@ -0,0 +1,7 @@ +export class VariableNotFoundError extends Error { + constructor(variableName: string) { + super(`Variable not found: ${variableName}`) + + Object.setPrototypeOf(this, VariableNotFoundError.prototype) + } +} diff --git a/src/services/config/config.service.test.ts b/src/services/config/config.service.test.ts new file mode 100644 index 0000000..3dba814 --- /dev/null +++ b/src/services/config/config.service.test.ts @@ -0,0 +1,48 @@ +import { describe, expect, vi, beforeEach, test, afterEach } from 'vitest' +import { VariableNotFoundError } from './config.errors' + +import { ConfigService } from '.' +describe('Config Service', () => { + beforeEach(() => { + vi.stubEnv('VITE_DRIVE_API_URL', 'https://api-drive.internxt.com') + vi.stubEnv('VITE_MAIL_API_URL', 'https://api-mail.internxt.com') + vi.stubEnv('VITE_PAYMENTS_API_URL', 'https://api-payments.internxt.com') + vi.stubEnv('VITE_CRYPTO_SECRET', 'test-secret') + vi.stubEnv('VITE_MAGIC_IV', 'test-iv') + vi.stubEnv('VITE_MAGIC_SALT', 'test-salt') + vi.stubEnv('PROD', false) + }) + + afterEach(() => { + vi.unstubAllEnvs() + }) + + const configService = ConfigService.instance + + describe('Get Variable', () => { + test('When getting an existing variable, then it should be returned successfully', () => { + const result = configService.getVariable('DRIVE_API_URL') + expect(result).toBe('https://api-drive.internxt.com') + }) + + test('When the variable does not exist, then an error indicating so is thrown', () => { + vi.stubEnv('VITE_DRIVE_API_URL', undefined) + + expect(() => configService.getVariable('DRIVE_API_URL')).toThrow( + VariableNotFoundError, + ) + }) + }) + + describe('Checking if the environment is production', () => { + test('When the environment is not production, then should indicate so', () => { + expect(configService.isProduction()).toBe(false) + }) + + test('When the environment is production, then should indicate so', () => { + vi.stubEnv('PROD', true) + + expect(configService.isProduction()).toBe(true) + }) + }) +}) diff --git a/src/services/config/index.ts b/src/services/config/index.ts new file mode 100644 index 0000000..f00ff3b --- /dev/null +++ b/src/services/config/index.ts @@ -0,0 +1,33 @@ +import { VariableNotFoundError } from './config.errors' + +interface ConfigKeys { + DRIVE_API_URL: string + MAIL_API_URL: string + PAYMENTS_API_URL: string + CRYPTO_SECRET: string + MAGIC_IV: string + MAGIC_SALT: string +} + +const configKeys: Record = { + DRIVE_API_URL: 'VITE_DRIVE_API_URL', + MAIL_API_URL: 'VITE_MAIL_API_URL', + PAYMENTS_API_URL: 'VITE_PAYMENTS_API_URL', + CRYPTO_SECRET: 'VITE_CRYPTO_SECRET', + MAGIC_IV: 'VITE_MAGIC_IV', + MAGIC_SALT: 'VITE_MAGIC_SALT', +} + +export class ConfigService { + public static readonly instance: ConfigService = new ConfigService() + + public getVariable = (key: keyof ConfigKeys): string => { + const value = import.meta.env[configKeys[key]] + if (!value) throw new VariableNotFoundError(key) + return value + } + + public isProduction = (): boolean => { + return import.meta.env.PROD + } +} diff --git a/src/services/local-storage/index.ts b/src/services/local-storage/index.ts new file mode 100644 index 0000000..0763d36 --- /dev/null +++ b/src/services/local-storage/index.ts @@ -0,0 +1,74 @@ +import type { UserSubscription } from '@internxt/sdk/dist/drive/payments/types/types' +import type { UserSettings } from '@internxt/sdk/dist/shared/types/userSettings' + +const LocalStorageKeys = { + xUser: 'xUser', + xNewToken: 'xNewToken', +} + +export class LocalStorageService { + public static readonly instance = new LocalStorageService() + + set(key: string, value: string) { + localStorage.setItem(key, value) + } + + get(key: string): string | null { + return localStorage.getItem(key) + } + + remove(key: string) { + localStorage.removeItem(key) + } + + clear() { + localStorage.clear() + } + + setUser(user: UserSettings) { + localStorage.setItem(LocalStorageKeys.xUser, JSON.stringify(user)) + } + + getUser(): UserSettings | null { + const user = localStorage.getItem(LocalStorageKeys.xUser) + return user ? JSON.parse(user) : null + } + + setToken(token: string) { + localStorage.setItem(LocalStorageKeys.xNewToken, token) + } + + getToken(): string | null { + return localStorage.getItem(LocalStorageKeys.xNewToken) + } + + setMnemonic(mnemonic: string) { + localStorage.setItem('xMnemonic', mnemonic) + } + + getMnemonic(): string | null { + return localStorage.getItem('xMnemonic') + } + + setSubscription(subscription: UserSubscription) { + localStorage.setItem('xSubscription', JSON.stringify(subscription)) + } + + getSubscription(): UserSubscription | null { + const subscription = localStorage.getItem('xSubscription') + return subscription ? JSON.parse(subscription) : null + } + + saveCredentials(user: UserSettings, mnemonic: string, token: string) { + this.setUser(user) + this.setMnemonic(mnemonic) + this.setToken(token) + } + + clearCredentials() { + localStorage.removeItem('xUser') + localStorage.removeItem('xNewToken') + localStorage.removeItem('xSubscription') + localStorage.removeItem('xMnemonic') + } +} diff --git a/src/services/local-storage/local-storage.service.test.ts b/src/services/local-storage/local-storage.service.test.ts new file mode 100644 index 0000000..0f7f3fa --- /dev/null +++ b/src/services/local-storage/local-storage.service.test.ts @@ -0,0 +1,101 @@ +import { afterEach, beforeEach, describe, expect, test } from 'vitest' +import { LocalStorageService } from '.' +import type { UserSettings } from '@internxt/sdk/dist/shared/types/userSettings' +import type { UserSubscription } from '@internxt/sdk/dist/drive/payments/types/types' + +const localStorageService = LocalStorageService.instance + +describe('Local Storage Service', () => { + beforeEach(() => { + localStorage.clear() + }) + + afterEach(() => { + localStorage.clear() + }) + + describe('User persistence', () => { + test('When storing user data, then it should persist across service calls', () => { + const user = { name: 'John Doe' } + localStorageService.setUser(user as UserSettings) + const savedUser = localStorageService.getUser() + expect(savedUser).toStrictEqual(user) + }) + + test('When no user is stored, then should return null', () => { + expect(localStorageService.getUser()).toBeNull() + }) + }) + + describe('Token management', () => { + test('When storing a token, then it should be retrievable', () => { + const token = 'token' + localStorageService.setToken(token) + const savedToken = localStorageService.getToken() + expect(savedToken).toBe(token) + }) + + test('When no token is stored, then should return null', () => { + expect(localStorageService.getToken()).toBeNull() + }) + }) + + describe('Mnemonic storage', () => { + test('When storing a mnemonic phrase, then it should be retrievable', () => { + const mnemonic = 'mnemonic' + localStorageService.setMnemonic(mnemonic) + const savedMnemonic = localStorageService.getMnemonic() + expect(savedMnemonic).toBe(mnemonic) + }) + + test('When no mnemonic is stored, then should return null', () => { + expect(localStorageService.getMnemonic()).toBeNull() + }) + }) + + describe('Subscription data', () => { + test('When storing subscription info, then it should persist the data', () => { + const subscription = { plan: 'plan', status: 'status' } + localStorageService.setSubscription( + subscription as unknown as UserSubscription, + ) + const savedSubscription = localStorageService.getSubscription() + expect(savedSubscription).toStrictEqual(subscription) + }) + + test('When no subscription is stored, then should return null', () => { + expect(localStorageService.getSubscription()).toBeNull() + }) + }) + + describe('Batch credential operations', () => { + test('When saving all credentials at once, then all should be stored correctly', () => { + const user = { name: 'John Doe' } + const mnemonic = 'mnemonic' + const token = 'token' + localStorageService.saveCredentials(user as UserSettings, mnemonic, token) + const savedUser = localStorageService.getUser() + const savedMnemonic = localStorageService.getMnemonic() + const savedToken = localStorageService.getToken() + expect(savedUser).toStrictEqual(user) + expect(savedMnemonic).toBe(mnemonic) + expect(savedToken).toBe(token) + }) + }) + + describe('Credential cleanup', () => { + test('When clearing credentials, then all sensitive data should be removed', () => { + const user = { name: 'John Doe' } + const mnemonic = 'mnemonic' + const token = 'token' + localStorageService.saveCredentials(user as UserSettings, mnemonic, token) + localStorageService.clearCredentials() + const savedUser = localStorageService.getUser() + const savedMnemonic = localStorageService.getMnemonic() + const savedToken = localStorageService.getToken() + expect(savedUser).toBeNull() + expect(savedMnemonic).toBeNull() + expect(savedToken).toBeNull() + }) + }) +}) diff --git a/src/services/sdk/index.ts b/src/services/sdk/index.ts new file mode 100644 index 0000000..a61f69e --- /dev/null +++ b/src/services/sdk/index.ts @@ -0,0 +1,77 @@ +import { Auth, Drive } from '@internxt/sdk' +import type { ApiSecurity, AppDetails } from '@internxt/sdk/dist/shared' +import packageJson from '../../../package.json' +import { ConfigService } from '../config' +import { LocalStorageService } from '../local-storage' + +export type SdkManagerApiSecurity = ApiSecurity & { newToken: string } + +export class SdkManager { + public static readonly instance: SdkManager = new SdkManager() + private static apiSecurity?: SdkManagerApiSecurity + private readonly localStorage = LocalStorageService + + public static readonly init = (apiSecurity: SdkManagerApiSecurity) => { + SdkManager.apiSecurity = apiSecurity + } + + public static readonly clean = () => { + SdkManager.apiSecurity = undefined + } + + public static readonly getApiSecurity = ( + config = { throwErrorOnMissingCredentials: true }, + ): SdkManagerApiSecurity | undefined => { + if (!SdkManager.apiSecurity && config.throwErrorOnMissingCredentials) + throw new Error('Api security properties not found in SdkManager') + + return SdkManager.apiSecurity + } + + private getNewTokenApiSecurity(): ApiSecurity { + return { + token: this.localStorage.instance?.getToken() ?? '', + unauthorizedCallback: () => { + if (this.localStorage.instance) { + this.localStorage.instance.clearCredentials() + } + }, + } + } + + public static readonly getAppDetails = (): AppDetails => { + return { + clientName: packageJson.name, + clientVersion: packageJson.version, + } + } + + getNewAuth() { + const driveApi = ConfigService.instance.getVariable('DRIVE_API_URL') + + const apiSecurity = SdkManager.getApiSecurity({ + throwErrorOnMissingCredentials: false, + }) + const appDetails = SdkManager.getAppDetails() + + return Auth.client(driveApi, appDetails, apiSecurity) + } + + getUsers() { + const driveApi = ConfigService.instance.getVariable('DRIVE_API_URL') + + const apiSecurity = this.getNewTokenApiSecurity() + const appDetails = SdkManager.getAppDetails() + + return Drive.Users.client(driveApi, appDetails, apiSecurity) + } + + getPayments() { + const paymentsApi = ConfigService.instance.getVariable('PAYMENTS_API_URL') + + const apiSecurity = this.getNewTokenApiSecurity() + const appDetails = SdkManager.getAppDetails() + + return Drive.Payments.client(paymentsApi, appDetails, apiSecurity) + } +} diff --git a/src/services/sdk/payments.service.test.ts b/src/services/sdk/payments.service.test.ts new file mode 100644 index 0000000..2683bb0 --- /dev/null +++ b/src/services/sdk/payments.service.test.ts @@ -0,0 +1,101 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { describe, expect, test, vi, beforeEach, afterEach } from 'vitest' +import { SdkManager } from '.' +import { PaymentsService } from './payments.service' + +describe('Payments Service', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + afterEach(() => { + vi.restoreAllMocks() + }) + + describe('User tier retrieval', () => { + test('When fetching user tier, then tier data should be returned', async () => { + const mockedTier = { + id: 'free', + billingType: 'subscription', + label: 'Test', + productId: 'product-id', + featuresPerService: { + 'service-1': { + features: ['feature-1', 'feature-2'], + }, + 'service-2': { + features: ['feature-3', 'feature-4'], + }, + }, + } + + const mockPaymentsClient = { + getUserTier: vi.fn().mockResolvedValue(mockedTier), + } as any + + vi.spyOn(SdkManager.instance, 'getPayments').mockReturnValue( + mockPaymentsClient, + ) + + const result = await PaymentsService.instance.getUserTier() + + expect(result).toStrictEqual(mockedTier) + expect(mockPaymentsClient.getUserTier).toHaveBeenCalledTimes(1) + }) + + test('When tier retrieval fails, then error should be thrown', async () => { + const unexpectedError = new Error('Unexpected error') + + const mockPaymentsClient = { + getUserTier: vi.fn().mockRejectedValue(unexpectedError), + } as any + + vi.spyOn(SdkManager.instance, 'getPayments').mockReturnValue( + mockPaymentsClient, + ) + + await expect(PaymentsService.instance.getUserTier()).rejects.toThrow( + unexpectedError, + ) + }) + }) + + describe('User subscription retrieval', () => { + test('When fetching user subscription, then subscription data should be returned', async () => { + const mockedSubscription = { + id: 'subscription-id', + status: 'active', + } + + const mockPaymentsClient = { + getUserSubscription: vi.fn().mockResolvedValue(mockedSubscription), + } as any + + vi.spyOn(SdkManager.instance, 'getPayments').mockReturnValue( + mockPaymentsClient, + ) + + const result = await PaymentsService.instance.getUserSubscription() + + expect(result).toStrictEqual(mockedSubscription) + expect(mockPaymentsClient.getUserSubscription).toHaveBeenCalledTimes(1) + }) + + test('When subscription retrieval fails, then error should be thrown', async () => { + const unexpectedError = new Error('Unexpected error') + + const mockPaymentsClient = { + getUserSubscription: vi.fn().mockRejectedValue(unexpectedError), + } as any + + vi.spyOn(SdkManager.instance, 'getPayments').mockReturnValue( + mockPaymentsClient, + ) + + await expect( + PaymentsService.instance.getUserSubscription(), + ).rejects.toThrow(unexpectedError) + }) + }) +}) diff --git a/src/services/sdk/payments.service.ts b/src/services/sdk/payments.service.ts new file mode 100644 index 0000000..c0bf956 --- /dev/null +++ b/src/services/sdk/payments.service.ts @@ -0,0 +1,17 @@ +import { type Tier } from '@internxt/sdk/dist/drive/payments/types/tiers' +import { type UserSubscription } from '@internxt/sdk/dist/drive/payments/types/types' +import { SdkManager } from '.' + +export class PaymentsService { + public static readonly instance: PaymentsService = new PaymentsService() + + public getUserTier = async (): Promise => { + const paymentsClient = SdkManager.instance.getPayments() + return paymentsClient.getUserTier() + } + + public getUserSubscription = async (): Promise => { + const paymentsClient = SdkManager.instance.getPayments() + return paymentsClient.getUserSubscription() + } +} diff --git a/src/services/sdk/sdk.service.test.ts b/src/services/sdk/sdk.service.test.ts new file mode 100644 index 0000000..3a0c327 --- /dev/null +++ b/src/services/sdk/sdk.service.test.ts @@ -0,0 +1,215 @@ +import { Auth, Drive } from '@internxt/sdk' +import { beforeEach, describe, expect, test, vi, afterEach } from 'vitest' +import { SdkManager } from '.' +import { ConfigService } from '../config' +import { LocalStorageService } from '../local-storage' + +vi.mock('@internxt/sdk', () => ({ + Auth: { + client: vi.fn().mockImplementation((baseUrl, appDetails, security) => ({ + baseUrl, + appDetails, + security, + unauthorizedCallback: vi.fn(), + })), + }, + Drive: { + Users: { + client: vi.fn().mockImplementation((baseUrl, appDetails, security) => ({ + baseUrl, + appDetails, + security, + unauthorizedCallback: vi.fn(), + })), + }, + Payments: { + client: vi.fn().mockImplementation((baseUrl, appDetails, security) => ({ + baseUrl, + appDetails, + security, + unauthorizedCallback: vi.fn(), + })), + }, + }, +})) + +describe('SDK Manager', () => { + beforeEach(() => { + SdkManager.clean() + localStorage.clear() + vi.clearAllMocks() + + vi.spyOn(ConfigService.instance, 'getVariable').mockImplementation( + (key: string) => { + const config: Record = { + DRIVE_API_URL: 'https://api-drive.internxt.com', + PAYMENTS_API_URL: 'https://api-payments.internxt.com', + } + return config[key] || '' + }, + ) + + vi.spyOn(LocalStorageService.instance, 'getToken').mockReturnValue( + 'mock-token', + ) + vi.spyOn(LocalStorageService.instance, 'clearCredentials').mockReturnValue() + }) + + afterEach(() => { + vi.restoreAllMocks() + }) + + describe('Security initialization', () => { + test('When initializing with API security, then credentials should be stored', () => { + const mockApiSecurity = { + token: 'test-token', + newToken: 'new-test-token', + userId: 'test-user-id', + } + + SdkManager.init(mockApiSecurity) + const storedSecurity = SdkManager.getApiSecurity({ + throwErrorOnMissingCredentials: false, + }) + + expect(storedSecurity).toEqual(mockApiSecurity) + }) + + test('When cleaning the manager, then security credentials should be removed', () => { + const mockApiSecurity = { + token: 'test-token', + newToken: 'new-test-token', + userId: 'test-user-id', + } + + SdkManager.init(mockApiSecurity) + SdkManager.clean() + + const storedSecurity = SdkManager.getApiSecurity({ + throwErrorOnMissingCredentials: false, + }) + expect(storedSecurity).toBeUndefined() + }) + + test('When requesting credentials without initialization and throwError is true, then should throw error', () => { + expect(() => SdkManager.getApiSecurity()).toThrow( + 'Api security properties not found in SdkManager', + ) + }) + + test('When requesting credentials without initialization and throwError is false, then should return undefined', () => { + const result = SdkManager.getApiSecurity({ + throwErrorOnMissingCredentials: false, + }) + expect(result).toBeUndefined() + }) + }) + + describe('App metadata', () => { + test('When getting app details, then package information should be returned', () => { + const appDetails = SdkManager.getAppDetails() + + expect(appDetails).toEqual({ + clientName: 'mail-web', + clientVersion: expect.any(String), + }) + expect(appDetails.clientVersion).toMatch(/^\d+\.\d+\.\d+$/) + }) + }) + + describe('Auth client creation', () => { + test('When creating Auth client with initialized security, then client should use provided credentials', () => { + const mockApiSecurity = { + token: 'test-token', + newToken: 'new-test-token', + userId: 'test-user-id', + } + SdkManager.init(mockApiSecurity) + + const authClient = SdkManager.instance.getNewAuth() + + expect(authClient).toBeDefined() + expect(Auth.client).toHaveBeenCalledWith( + 'https://api-drive.internxt.com', + expect.objectContaining({ + clientName: 'mail-web', + clientVersion: expect.any(String), + }), + mockApiSecurity, + ) + }) + + test('When creating Auth client without initialized security, then client should use undefined credentials', () => { + const authClient = SdkManager.instance.getNewAuth() + + expect(authClient).toBeDefined() + expect(Auth.client).toHaveBeenCalledWith( + 'https://api-drive.internxt.com', + expect.objectContaining({ + clientName: 'mail-web', + }), + undefined, + ) + }) + }) + + describe('Users client creation', () => { + test('When creating Users client, then it should use token from localStorage', () => { + const usersClient = SdkManager.instance.getUsers() + + expect(usersClient).toBeDefined() + expect(LocalStorageService.instance.getToken).toHaveBeenCalled() + expect(Drive.Users.client).toHaveBeenCalledWith( + 'https://api-drive.internxt.com', + expect.objectContaining({ + clientName: 'mail-web', + clientVersion: expect.any(String), + }), + expect.objectContaining({ + token: 'mock-token', + unauthorizedCallback: expect.any(Function), + }), + ) + }) + + test('When Users client receives unauthorized response, then credentials should be cleared', () => { + SdkManager.instance.getUsers() + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const securityArg = (Drive.Users.client as any).mock.calls[0][2] + securityArg.unauthorizedCallback() + + expect(LocalStorageService.instance.clearCredentials).toHaveBeenCalled() + }) + }) + + describe('Payments client creation', () => { + test('When creating Payments client, then it should use correct API URL and token', () => { + const paymentsClient = SdkManager.instance.getPayments() + + expect(paymentsClient).toBeDefined() + expect(LocalStorageService.instance.getToken).toHaveBeenCalled() + expect(Drive.Payments.client).toHaveBeenCalledWith( + 'https://api-payments.internxt.com', + expect.objectContaining({ + clientName: 'mail-web', + clientVersion: expect.any(String), + }), + expect.objectContaining({ + token: 'mock-token', + unauthorizedCallback: expect.any(Function), + }), + ) + }) + + test('When Payments client receives unauthorized response, then credentials should be cleared', () => { + SdkManager.instance.getPayments() + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const securityArg = (Drive.Payments.client as any).mock.calls[0][2] + securityArg.unauthorizedCallback() + + expect(LocalStorageService.instance.clearCredentials).toHaveBeenCalled() + }) + }) +}) diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..4e44efe --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from 'vitest/config' +import path from 'node:path' + +export default defineConfig({ + test: { + globals: true, + environment: 'jsdom', + }, + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, +}) diff --git a/yarn.lock b/yarn.lock index 229a126..5463bc2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,38 @@ # yarn lockfile v1 +"@acemir/cssom@^0.9.31": + version "0.9.31" + resolved "https://registry.yarnpkg.com/@acemir/cssom/-/cssom-0.9.31.tgz#bd5337d290fb8be2ac18391f37386bc53778b0bc" + integrity sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA== + +"@asamuzakjp/css-color@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@asamuzakjp/css-color/-/css-color-5.0.1.tgz#3b9462a9b52f3c6680a0945a3d0851881017550f" + integrity sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw== + dependencies: + "@csstools/css-calc" "^3.1.1" + "@csstools/css-color-parser" "^4.0.2" + "@csstools/css-parser-algorithms" "^4.0.0" + "@csstools/css-tokenizer" "^4.0.0" + lru-cache "^11.2.6" + +"@asamuzakjp/dom-selector@^6.8.1": + version "6.8.1" + resolved "https://registry.yarnpkg.com/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz#39b20993672b106f7cd9a3a9a465212e87e0bfd1" + integrity sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ== + dependencies: + "@asamuzakjp/nwsapi" "^2.3.9" + bidi-js "^1.0.3" + css-tree "^3.1.0" + is-potential-custom-element-name "^1.0.1" + lru-cache "^11.2.6" + +"@asamuzakjp/nwsapi@^2.3.9": + version "2.3.9" + resolved "https://registry.yarnpkg.com/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz#ad5549322dfe9d153d4b4dd6f7ff2ae234b06e24" + integrity sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q== + "@babel/code-frame@^7.28.6", "@babel/code-frame@^7.29.0": version "7.29.0" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.0.tgz#7cd7a59f15b3cc0dcd803038f7792712a7d0b15c" @@ -165,6 +197,46 @@ "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.28.5" +"@bramus/specificity@^2.4.2": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@bramus/specificity/-/specificity-2.4.2.tgz#aa8db8eb173fdee7324f82284833106adeecc648" + integrity sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw== + dependencies: + css-tree "^3.0.0" + +"@csstools/color-helpers@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@csstools/color-helpers/-/color-helpers-6.0.2.tgz#82c59fd30649cf0b4d3c82160489748666e6550b" + integrity sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q== + +"@csstools/css-calc@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@csstools/css-calc/-/css-calc-3.1.1.tgz#78b494996dac41a02797dcca18ac3b46d25b3fd7" + integrity sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ== + +"@csstools/css-color-parser@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-4.0.2.tgz#c27e03a3770d0352db92d668d6dde427a37859e5" + integrity sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw== + dependencies: + "@csstools/color-helpers" "^6.0.2" + "@csstools/css-calc" "^3.1.1" + +"@csstools/css-parser-algorithms@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz#e1c65dc09378b42f26a111fca7f7075fc2c26164" + integrity sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w== + +"@csstools/css-syntax-patches-for-csstree@^1.0.28": + version "1.0.29" + resolved "https://registry.yarnpkg.com/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.29.tgz#b1bffea9c70e5d0c4d339f0e1df270b435cb418a" + integrity sha512-jx9GjkkP5YHuTmko2eWAvpPnb0mB4mGRr2U7XwVNwevm8nlpobZEVk+GNmiYMk2VuA75v+plfXWyroWKmICZXg== + +"@csstools/css-tokenizer@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz#798a33950d11226a0ebb6acafa60f5594424967f" + integrity sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA== + "@emnapi/core@^1.7.1", "@emnapi/core@^1.8.1": version "1.8.1" resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.8.1.tgz#fd9efe721a616288345ffee17a1f26ac5dd01349" @@ -385,6 +457,11 @@ "@eslint/core" "^0.17.0" levn "^0.4.1" +"@exodus/bytes@^1.11.0", "@exodus/bytes@^1.6.0": + version "1.15.0" + resolved "https://registry.yarnpkg.com/@exodus/bytes/-/bytes-1.15.0.tgz#54479e0f406cbad024d6fe1c3190ecca4468df3b" + integrity sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ== + "@floating-ui/core@^1.7.4": version "1.7.4" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.4.tgz#4a006a6e01565c0f87ba222c317b056a2cffd2f4" @@ -442,6 +519,14 @@ dependencies: tailwindcss "^4.1.17" +"@internxt/sdk@^1.15.1": + version "1.15.1" + resolved "https://registry.yarnpkg.com/@internxt/sdk/-/sdk-1.15.1.tgz#69ad13a3c8cacbd929f025f24adc6fd2d1faf8ef" + integrity sha512-CEH/fNjDWenmFAl8NHaykb85AY4uEZDO5pA2ap8/GD4SXmxC3rcWsKnMsYO9jc8R2vpOPxmE3oBlNqOVcI/llQ== + dependencies: + axios "1.13.5" + internxt-crypto "0.0.13" + "@internxt/ui@^0.1.9": version "0.1.9" resolved "https://registry.yarnpkg.com/@internxt/ui/-/ui-0.1.9.tgz#7059d388916ecf4518680774c7b9abc2b0459c3e" @@ -495,6 +580,26 @@ "@emnapi/runtime" "^1.7.1" "@tybys/wasm-util" "^0.10.1" +"@noble/curves@~2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-2.0.1.tgz#64ba8bd5e8564a02942655602515646df1cdb3ad" + integrity sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw== + dependencies: + "@noble/hashes" "2.0.1" + +"@noble/hashes@2.0.1", "@noble/hashes@^2.0.1", "@noble/hashes@~2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-2.0.1.tgz#fc1a928061d1232b0a52bb754393c37a5216c89e" + integrity sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw== + +"@noble/post-quantum@^0.5.2": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@noble/post-quantum/-/post-quantum-0.5.4.tgz#bd1095647c61e4c8fd317fa8a3977db8cd28a4b9" + integrity sha512-leww0zzIirrvwaYMPI9fj6aRIlA/c6Y0/lifQQ1YOOyHEr0MNH3yYpjXeiVG+tWdPps4XxGclFWX2INPO3Yo5w== + dependencies: + "@noble/curves" "~2.0.0" + "@noble/hashes" "~2.0.0" + "@phosphor-icons/react@^2.1.10": version "2.1.10" resolved "https://registry.yarnpkg.com/@phosphor-icons/react/-/react-2.1.10.tgz#3a97ec5b7a4b8d53afeb29125bc17e74ed2daf92" @@ -1333,6 +1438,24 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz#4584a8a87b29188a4c1fe987a9fcf701e256d86c" integrity sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA== +"@scure/base@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-2.0.0.tgz#ba6371fddf92c2727e88ad6ab485db6e624f9a98" + integrity sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w== + +"@scure/bip39@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-2.0.1.tgz#47a6dc15e04faf200041239d46ae3bb7c3c96add" + integrity sha512-PsxdFj/d2AcJcZDX1FXN3dDgitDDTmwf78rKZq1a6c1P1Nan1X/Sxc7667zU3U+AN60g7SxxP0YCVw2H/hBycg== + dependencies: + "@noble/hashes" "2.0.1" + "@scure/base" "2.0.0" + +"@standard-schema/spec@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.1.0.tgz#a79b55dbaf8604812f52d140b2c9ab41bc150bb8" + integrity sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w== + "@tailwindcss/node@4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.2.1.tgz#e963ac242a885353a4660e7e3e9c695cde7d3fc9" @@ -1700,6 +1823,19 @@ dependencies: "@babel/types" "^7.28.2" +"@types/chai@^5.2.2": + version "5.2.3" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.3.tgz#8e9cd9e1c3581fa6b341a5aed5588eb285be0b4a" + integrity sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA== + dependencies: + "@types/deep-eql" "*" + assertion-error "^2.0.1" + +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== + "@types/estree@1.0.8", "@types/estree@^1.0.0", "@types/estree@^1.0.6": version "1.0.8" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" @@ -1860,6 +1996,64 @@ "@types/babel__core" "^7.20.5" react-refresh "^0.18.0" +"@vitest/expect@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.18.tgz#361510d99fbf20eb814222e4afcb8539d79dc94d" + integrity sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ== + dependencies: + "@standard-schema/spec" "^1.0.0" + "@types/chai" "^5.2.2" + "@vitest/spy" "4.0.18" + "@vitest/utils" "4.0.18" + chai "^6.2.1" + tinyrainbow "^3.0.3" + +"@vitest/mocker@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.18.tgz#b9735da114ef65ea95652c5bdf13159c6fab4865" + integrity sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ== + dependencies: + "@vitest/spy" "4.0.18" + estree-walker "^3.0.3" + magic-string "^0.30.21" + +"@vitest/pretty-format@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.18.tgz#fbccd4d910774072ec15463553edb8ca5ce53218" + integrity sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw== + dependencies: + tinyrainbow "^3.0.3" + +"@vitest/runner@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.18.tgz#c2c0a3ed226ec85e9312f9cc8c43c5b3a893a8b1" + integrity sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw== + dependencies: + "@vitest/utils" "4.0.18" + pathe "^2.0.3" + +"@vitest/snapshot@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.18.tgz#bcb40fd6d742679c2ac927ba295b66af1c6c34c5" + integrity sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA== + dependencies: + "@vitest/pretty-format" "4.0.18" + magic-string "^0.30.21" + pathe "^2.0.3" + +"@vitest/spy@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.18.tgz#ba0f20503fb6d08baf3309d690b3efabdfa88762" + integrity sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw== + +"@vitest/utils@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.18.tgz#9636b16d86a4152ec68a8d6859cff702896433d4" + integrity sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA== + dependencies: + "@vitest/pretty-format" "4.0.18" + tinyrainbow "^3.0.3" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -1870,6 +2064,11 @@ acorn@^8.15.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a" integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== +agent-base@^7.1.0, agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== + ajv@^6.12.4, ajv@^6.14.0: version "6.14.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.14.0.tgz#fd067713e228210636ebb08c60bd3765d6dbe73a" @@ -1919,6 +2118,16 @@ assert@^2.0.0: object.assign "^4.1.4" util "^0.12.5" +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" @@ -1926,6 +2135,15 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" +axios@1.13.5: + version "1.13.5" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.13.5.tgz#5e464688fa127e11a660a2c49441c009f6567a43" + integrity sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q== + dependencies: + follow-redirects "^1.15.11" + form-data "^4.0.5" + proxy-from-env "^1.1.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -1946,6 +2164,13 @@ baseline-browser-mapping@^2.9.0: resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz#5b09935025bf8a80e29130251e337c6a7fc8cbb9" integrity sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA== +bidi-js@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/bidi-js/-/bidi-js-1.0.3.tgz#6f8bcf3c877c4d9220ddf49b9bb6930c88f877d2" + integrity sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw== + dependencies: + require-from-string "^2.0.2" + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.3" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.3.tgz#2cc2c679188eb35b006f2d0d4710bed8437a769e" @@ -2110,6 +2335,11 @@ caniuse-lite@^1.0.30001759: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001774.tgz#0e576b6f374063abcd499d202b9ba1301be29b70" integrity sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA== +chai@^6.2.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/chai/-/chai-6.2.2.tgz#ae41b52c9aca87734505362717f3255facda360e" + integrity sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg== + chalk@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -2144,6 +2374,13 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2242,23 +2479,54 @@ crypto-browserify@^3.12.1: randombytes "^2.1.0" randomfill "^1.0.4" +css-tree@^3.0.0, css-tree@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-3.1.0.tgz#7aabc035f4e66b5c86f54570d55e05b1346eb0fd" + integrity sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w== + dependencies: + mdn-data "2.12.2" + source-map-js "^1.0.1" + +cssstyle@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-6.2.0.tgz#c41b59955c19c7a1223352d67ca462750204ad0f" + integrity sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig== + dependencies: + "@asamuzakjp/css-color" "^5.0.1" + "@csstools/css-syntax-patches-for-csstree" "^1.0.28" + css-tree "^3.1.0" + lru-cache "^11.2.6" + csstype@^3.2.2: version "3.2.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.2.3.tgz#ec48c0f3e993e50648c86da559e2610995cf989a" integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ== +data-urls@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-7.0.0.tgz#6dce8b63226a1ecfdd907ce18a8ccfb1eee506d3" + integrity sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA== + dependencies: + whatwg-mimetype "^5.0.0" + whatwg-url "^16.0.0" + dayjs@^1.11.19: version "1.11.19" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.19.tgz#15dc98e854bb43917f12021806af897c58ae2938" integrity sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw== -debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.4.3: +debug@4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.3: version "4.4.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== dependencies: ms "^2.1.3" +decimal.js@^10.6.0: + version "10.6.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a" + integrity sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg== + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -2282,6 +2550,11 @@ define-properties@^1.1.3, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + des.js@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" @@ -2354,6 +2627,11 @@ entities@^4.4.0: resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== +entities@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694" + integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== + es-define-property@^1.0.0, es-define-property@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" @@ -2364,6 +2642,11 @@ es-errors@^1.3.0: resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== +es-module-lexer@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" + integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== + es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" @@ -2371,6 +2654,16 @@ es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: dependencies: es-errors "^1.3.0" +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + esbuild@^0.27.0: version "0.27.3" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.27.3.tgz#5859ca8e70a3af956b26895ce4954d7e73bd27a8" @@ -2525,6 +2818,13 @@ estree-walker@^2.0.2: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -2543,6 +2843,11 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +expect-type@^1.2.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.3.0.tgz#0d58ed361877a31bbc4dd6cf71bbfef7faf6bd68" + integrity sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -2596,6 +2901,16 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== +flexsearch@^0.8.205: + version "0.8.212" + resolved "https://registry.yarnpkg.com/flexsearch/-/flexsearch-0.8.212.tgz#b9509af778a991b938292e36fe0809a4ece4b940" + integrity sha512-wSyJr1GUWoOOIISRu+X2IXiOcVfg9qqBRyCPRUdLMIGJqPzMo+jMRlvE83t14v1j0dRMEaBbER/adQjp6Du2pw== + +follow-redirects@^1.15.11: + version "1.15.11" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340" + integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== + for-each@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" @@ -2603,6 +2918,17 @@ for-each@^0.3.5: dependencies: is-callable "^1.2.7" +form-data@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053" + integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" + mime-types "^2.1.12" + fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" @@ -2623,7 +2949,7 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== @@ -2721,6 +3047,11 @@ hash-base@~3.0.4: inherits "^2.0.4" safe-buffer "^5.2.1" +hash-wasm@^4.12.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/hash-wasm/-/hash-wasm-4.12.0.tgz#f9f1a9f9121e027a9acbf6db5d59452ace1ef9bb" + integrity sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ== + hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -2757,6 +3088,13 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +html-encoding-sniffer@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz#f8d9390b3b348b50d4f61c16dd2ef5c05980a882" + integrity sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg== + dependencies: + "@exodus/bytes" "^1.6.0" + html-parse-stringify@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" @@ -2764,11 +3102,32 @@ html-parse-stringify@^3.0.1: dependencies: void-elements "3.1.0" +http-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== +https-proxy-agent@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== + dependencies: + agent-base "^7.1.2" + debug "4" + +husky@^9.1.7: + version "9.1.7" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" + integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== + i18next@^25.8.13: version "25.8.13" resolved "https://registry.yarnpkg.com/i18next/-/i18next-25.8.13.tgz#1f9df59329f1706f02b2b58b5d1f75196ddb6e4a" @@ -2776,6 +3135,11 @@ i18next@^25.8.13: dependencies: "@babel/runtime" "^7.28.4" +idb@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/idb/-/idb-8.0.3.tgz#c91e558f15a8d53f1d7f53a094d226fc3ad71fd9" + integrity sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg== + ieee754@^1.1.13: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -2809,6 +3173,20 @@ inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2. resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +internxt-crypto@0.0.13: + version "0.0.13" + resolved "https://registry.yarnpkg.com/internxt-crypto/-/internxt-crypto-0.0.13.tgz#90c83828a34667ecf6938ad7c22d94c9f0d9808b" + integrity sha512-V8Epf4oFZQZwMyIt8mcw7w36M+tryQ9VcfaiKtcruNW/129bawZnPXEeoOfLvAV+9OYlY2ZAwIYP0EtOD2ec6g== + dependencies: + "@noble/hashes" "^2.0.1" + "@noble/post-quantum" "^0.5.2" + "@scure/bip39" "^2.0.1" + flexsearch "^0.8.205" + hash-wasm "^4.12.0" + husky "^9.1.7" + idb "^8.0.3" + uuid "^13.0.0" + is-arguments@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b" @@ -2860,6 +3238,11 @@ is-nan@^1.3.2: call-bind "^1.0.0" define-properties "^1.1.3" +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + is-regex@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" @@ -2914,6 +3297,33 @@ js-yaml@^4.1.1: dependencies: argparse "^2.0.1" +jsdom@^28.1.0: + version "28.1.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-28.1.0.tgz#ac4203e58fd24d7b0f34359ab00d6d9caebd4b62" + integrity sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug== + dependencies: + "@acemir/cssom" "^0.9.31" + "@asamuzakjp/dom-selector" "^6.8.1" + "@bramus/specificity" "^2.4.2" + "@exodus/bytes" "^1.11.0" + cssstyle "^6.0.1" + data-urls "^7.0.0" + decimal.js "^10.6.0" + html-encoding-sniffer "^6.0.0" + http-proxy-agent "^7.0.2" + https-proxy-agent "^7.0.6" + is-potential-custom-element-name "^1.0.1" + parse5 "^8.0.0" + saxes "^6.0.0" + symbol-tree "^3.2.4" + tough-cookie "^6.0.0" + undici "^7.21.0" + w3c-xmlserializer "^5.0.0" + webidl-conversions "^8.0.1" + whatwg-mimetype "^5.0.0" + whatwg-url "^16.0.0" + xml-name-validator "^5.0.0" + jsesc@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" @@ -3052,6 +3462,11 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lru-cache@^11.2.6: + version "11.2.6" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.2.6.tgz#356bf8a29e88a7a2945507b31f6429a65a192c58" + integrity sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -3092,6 +3507,11 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" +mdn-data@2.12.2: + version "2.12.2" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.12.2.tgz#9ae6c41a9e65adf61318b32bff7b64fbfb13f8cf" + integrity sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA== + mdurl@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" @@ -3105,6 +3525,18 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -3212,6 +3644,11 @@ object.assign@^4.1.4: has-symbols "^1.1.0" object-keys "^1.1.1" +obug@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/obug/-/obug-2.1.1.tgz#2cba74ff241beb77d63055ddf4cd1e9f90b538be" + integrity sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ== + optionator@^0.9.3: version "0.9.4" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" @@ -3271,6 +3708,13 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.9: pbkdf2 "^3.1.5" safe-buffer "^5.2.1" +parse5@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-8.0.0.tgz#aceb267f6b15f9b6e6ba9e35bfdd481fc2167b12" + integrity sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA== + dependencies: + entities "^6.0.0" + path-browserify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" @@ -3291,6 +3735,11 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + pbkdf2@^3.1.2, pbkdf2@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.5.tgz#444a59d7a259a95536c56e80c89de31cc01ed366" @@ -3503,6 +3952,11 @@ prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.27.0, pros prosemirror-state "^1.0.0" prosemirror-transform "^1.1.0" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + public-encrypt@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" @@ -3525,7 +3979,7 @@ punycode@^1.4.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -3708,6 +4162,11 @@ readable-stream@^3.5.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -3788,6 +4247,13 @@ safe-regex-test@^1.1.0: es-errors "^1.3.0" is-regex "^1.2.1" +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== + dependencies: + xmlchars "^2.2.0" + scheduler@^0.27.0: version "0.27.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.27.0.tgz#0c4ef82d67d1e5c1e359e8fc76d3a87f045fe5bd" @@ -3886,11 +4352,26 @@ side-channel@^1.1.0: side-channel-map "^1.0.1" side-channel-weakmap "^1.0.2" -source-map-js@^1.2.1: +siginfo@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" + integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== + +source-map-js@^1.0.1, source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== +stackback@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" + integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== + +std-env@^3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b" + integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg== + stream-browserify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" @@ -3940,6 +4421,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + tailwindcss@4.2.1, tailwindcss@^4.1.17, tailwindcss@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.2.1.tgz#018c4720b58baf98a6bf56b0a12aa797c6cfef1d" @@ -3957,6 +4443,16 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +tinybench@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" + integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== + +tinyexec@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.0.2.tgz#bdd2737fe2ba40bd6f918ae26642f264b99ca251" + integrity sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg== + tinyglobby@^0.2.15: version "0.2.15" resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2" @@ -3965,6 +4461,23 @@ tinyglobby@^0.2.15: fdir "^6.5.0" picomatch "^4.0.3" +tinyrainbow@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.0.3.tgz#984a5b1c1b25854a9b6bccbe77964d0593d1ea42" + integrity sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q== + +tldts-core@^7.0.24: + version "7.0.24" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-7.0.24.tgz#ffc93642720e4dd708fc7b68dfd7d630fec43403" + integrity sha512-pj7yygNMoMRqG7ML2SDQ0xNIOfN3IBDUcPVM2Sg6hP96oFNN2nqnzHreT3z9xLq85IWJyNTvD38O002DdOrPMw== + +tldts@^7.0.5: + version "7.0.24" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-7.0.24.tgz#11785c58333ef50afdf1ed42f571efc8808ebb1f" + integrity sha512-1r6vQTTt1rUiJkI5vX7KG8PR342Ru/5Oh13kEQP2SMbRSZpOey9SrBe27IDxkoWulx8ShWu4K6C0BkctP8Z1bQ== + dependencies: + tldts-core "^7.0.24" + to-buffer@^1.2.0, to-buffer@^1.2.1, to-buffer@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.2.2.tgz#ffe59ef7522ada0a2d1cb5dfe03bb8abc3cdc133" @@ -3974,6 +4487,20 @@ to-buffer@^1.2.0, to-buffer@^1.2.1, to-buffer@^1.2.2: safe-buffer "^5.2.1" typed-array-buffer "^1.0.3" +tough-cookie@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-6.0.0.tgz#11e418b7864a2c0d874702bc8ce0f011261940e5" + integrity sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w== + dependencies: + tldts "^7.0.5" + +tr46@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-6.0.0.tgz#f5a1ae546a0adb32a277a2278d0d17fa2f9093e6" + integrity sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw== + dependencies: + punycode "^2.3.1" + ts-api-utils@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.4.0.tgz#2690579f96d2790253bdcf1ca35d569ad78f9ad8" @@ -4030,6 +4557,11 @@ undici-types@~7.16.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== +undici@^7.21.0: + version "7.22.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-7.22.0.tgz#7a82590a5908e504a47d85c60b0f89ca14240e60" + integrity sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg== + update-browserslist-db@^1.2.0: version "1.2.3" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" @@ -4089,6 +4621,11 @@ util@^0.12.4, util@^0.12.5: is-typed-array "^1.1.3" which-typed-array "^1.1.2" +uuid@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-13.0.0.tgz#263dc341b19b4d755eb8fe36b78d95a6b65707e8" + integrity sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w== + vite-plugin-node-polyfills@^0.25.0: version "0.25.0" resolved "https://registry.yarnpkg.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.25.0.tgz#dccbb76b3c81a4981a89403feabc1b74d2dc60d4" @@ -4097,7 +4634,7 @@ vite-plugin-node-polyfills@^0.25.0: "@rollup/plugin-inject" "^5.0.5" node-stdlib-browser "^1.3.1" -vite@^7.3.1: +"vite@^6.0.0 || ^7.0.0", vite@^7.3.1: version "7.3.1" resolved "https://registry.yarnpkg.com/vite/-/vite-7.3.1.tgz#7f6cfe8fb9074138605e822a75d9d30b814d6507" integrity sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA== @@ -4111,6 +4648,32 @@ vite@^7.3.1: optionalDependencies: fsevents "~2.3.3" +vitest@^4.0.18: + version "4.0.18" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.18.tgz#56f966353eca0b50f4df7540cd4350ca6d454a05" + integrity sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ== + dependencies: + "@vitest/expect" "4.0.18" + "@vitest/mocker" "4.0.18" + "@vitest/pretty-format" "4.0.18" + "@vitest/runner" "4.0.18" + "@vitest/snapshot" "4.0.18" + "@vitest/spy" "4.0.18" + "@vitest/utils" "4.0.18" + es-module-lexer "^1.7.0" + expect-type "^1.2.2" + magic-string "^0.30.21" + obug "^2.1.1" + pathe "^2.0.3" + picomatch "^4.0.3" + std-env "^3.10.0" + tinybench "^2.9.0" + tinyexec "^1.0.2" + tinyglobby "^0.2.15" + tinyrainbow "^3.0.3" + vite "^6.0.0 || ^7.0.0" + why-is-node-running "^2.3.0" + vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" @@ -4126,6 +4689,32 @@ w3c-keyname@^2.2.0: resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5" integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ== +w3c-xmlserializer@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" + integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA== + dependencies: + xml-name-validator "^5.0.0" + +webidl-conversions@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-8.0.1.tgz#0657e571fe6f06fcb15ca50ed1fdbcb495cd1686" + integrity sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ== + +whatwg-mimetype@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz#d8232895dbd527ceaee74efd4162008fb8a8cf48" + integrity sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw== + +whatwg-url@^16.0.0: + version "16.0.1" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-16.0.1.tgz#047f7f4bd36ef76b7198c172d1b1cebc66f764dd" + integrity sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw== + dependencies: + "@exodus/bytes" "^1.11.0" + tr46 "^6.0.0" + webidl-conversions "^8.0.1" + which-typed-array@^1.1.16, which-typed-array@^1.1.2: version "1.1.20" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.20.tgz#3fdb7adfafe0ea69157b1509f3a1cd892bd1d122" @@ -4146,11 +4735,29 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +why-is-node-running@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" + integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== + dependencies: + siginfo "^2.0.0" + stackback "0.0.2" + word-wrap@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== +xml-name-validator@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" + integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + xtend@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" From f5c6cb9b6c8ad8f09f39f32c51e6c03e367adb6d Mon Sep 17 00:00:00 2001 From: Xavier Abad <77491413+xabg2@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:46:04 +0100 Subject: [PATCH 2/4] ci: upgrade node version --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2033b9..3359f36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: - node-version: [20.x] + node-version: [24.x] env: VITE_PAYMENTS_API_URL: ${{ secrets.PAYMENTS_API_URL }} From 4d02aa2f4d7ce78ba05218a4c5d5d9b19881738f Mon Sep 17 00:00:00 2001 From: Xavier Abad <77491413+xabg2@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:53:59 +0100 Subject: [PATCH 3/4] fix: some imports in components --- src/components/chips/RecipientChip.tsx | 2 +- .../components/RecipientInput.tsx | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/components/chips/RecipientChip.tsx b/src/components/chips/RecipientChip.tsx index 8893f54..c666c39 100644 --- a/src/components/chips/RecipientChip.tsx +++ b/src/components/chips/RecipientChip.tsx @@ -1,5 +1,5 @@ import { XIcon } from '@phosphor-icons/react' -import type { Recipient } from '../composeMessageDialog/types' +import type { Recipient } from '../mail/composeMessageDialog/types' interface RecipientChipProps { recipient: Recipient diff --git a/src/components/mail/composeMessageDialog/components/RecipientInput.tsx b/src/components/mail/composeMessageDialog/components/RecipientInput.tsx index f0e3fcb..b1c35ea 100644 --- a/src/components/mail/composeMessageDialog/components/RecipientInput.tsx +++ b/src/components/mail/composeMessageDialog/components/RecipientInput.tsx @@ -1,6 +1,6 @@ import { useState, type KeyboardEvent } from 'react' import type { Recipient } from '../types' -import { RecipientChip } from '../../chips/RecipientChip' +import { RecipientChip } from '@/components/chips/RecipientChip' interface RecipientInputProps { label: string @@ -46,7 +46,7 @@ export const RecipientInput = ({ inputValue === '' && recipients.length > 0 ) { - onRemoveRecipient(recipients[recipients.length - 1].id) + onRemoveRecipient(recipients.at(-1)!.id) } } @@ -60,9 +60,7 @@ export const RecipientInput = ({ return (
-

- {label} -

+

{label}

{recipients.map((recipient) => ( {showCcBcc && (showCcButton || showBccButton) && (
@@ -87,7 +85,7 @@ export const RecipientInput = ({ type="button" onClick={onCcClick} disabled={disabled} - className={`px-1.5 py-0.5 text-sm font-medium text-primary hover:bg-gray-5 rounded bg-primary/20 hover:bg-primary/30 ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`} + className={`px-1.5 py-0.5 text-sm font-medium text-primary rounded bg-primary/20 hover:bg-primary/30 ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`} > {ccButtonText} @@ -97,7 +95,7 @@ export const RecipientInput = ({ type="button" onClick={onBccClick} disabled={disabled} - className={`px-1.5 py-0.5 text-sm font-medium text-primary hover:bg-gray-5 rounded bg-primary/20 hover:bg-primary/30 ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`} + className={`px-1.5 py-0.5 text-sm font-medium text-primary rounded bg-primary/20 hover:bg-primary/30 ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`} > {bccButtonText} From 03151f4769492aaf115c4bdcd1ad843b02a80af7 Mon Sep 17 00:00:00 2001 From: Xavier Abad <77491413+xabg2@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:05:47 +0100 Subject: [PATCH 4/4] ci: execute build before tests --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3359f36..3e289ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,5 +28,5 @@ jobs: cache: "yarn" - run: yarn install --frozen-lockfile - - run: yarn test - run: yarn build + - run: yarn test