diff --git a/.gitignore b/.gitignore index 520cd64..611e681 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,5 @@ temp/ data local +.atl +openspec \ No newline at end of file diff --git a/package.json b/package.json index f92f554..2324d23 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "build": "pnpm --filter @floci/frontend build", "lint": "pnpm --filter @floci/frontend lint", "type-check": "pnpm --filter @floci/api type-check && pnpm --filter @floci/frontend type-check", - "test": "pnpm --filter @floci/api test", + "test": "pnpm --filter @floci/api test && pnpm --filter @floci/frontend test", "dev:api": "sh -c 'PORT=${PORT:-4501} pnpm --filter @floci/api dev'", "start:api": "sh -c 'PORT=${PORT:-4501} pnpm --filter @floci/api start'" } diff --git a/packages/api/package.json b/packages/api/package.json index df9c5c8..5f4dc4c 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -10,6 +10,7 @@ "test": "bun test" }, "dependencies": { + "@aws-sdk/client-dynamodb": "^3.1066.0", "@aws-sdk/client-ec2": "^3.1063.0", "@aws-sdk/client-eks": "^3.1063.0", "@aws-sdk/client-lambda": "^3.1063.0", diff --git a/packages/api/src/adapter-aws/AwsDynamoDbAdapter.test.ts b/packages/api/src/adapter-aws/AwsDynamoDbAdapter.test.ts new file mode 100644 index 0000000..19ab160 --- /dev/null +++ b/packages/api/src/adapter-aws/AwsDynamoDbAdapter.test.ts @@ -0,0 +1,108 @@ +import {describe, expect, test} from 'bun:test' +import {AwsDynamoDbAdapter} from './AwsDynamoDbAdapter' +import type {DynamoDbTable} from '../services/dynamodb' + +const baseTable: DynamoDbTable = { + tableName: 'users', + arn: 'arn:aws:dynamodb:us-east-1:123456789012:table/users', + status: 'ACTIVE', + billingMode: 'PAY_PER_REQUEST', + itemCount: 12, + sizeBytes: 256, + keySchema: [{attributeName: 'pk', keyType: 'HASH'}], + region: 'us-east-1', + createdAt: '2025-01-01T00:00:00.000Z', +} + +function fakeService(overrides: Partial<{ + listTables: () => Promise + describeTable: (tableName: string) => Promise +}> = {}) { + return { + listTables: async () => [baseTable], + describeTable: async (_tableName: string) => baseTable, + ...overrides, + } +} + +describe('AwsDynamoDbAdapter', () => { + test('list returns mapped CloudResource array', async () => { + const adapter = new AwsDynamoDbAdapter(fakeService()) + const result = await adapter.list() + + expect(result).toHaveLength(1) + expect(result[0]).toMatchObject({ + id: 'users', + name: 'users', + cloud: 'aws', + service: 'dynamodb', + type: 'dynamodb-table', + status: 'ACTIVE', + region: 'us-east-1', + }) + expect(result[0].metadata).toEqual({ + arn: 'arn:aws:dynamodb:us-east-1:123456789012:table/users', + billingMode: 'PAY_PER_REQUEST', + itemCount: 12, + sizeBytes: 256, + keySchema: [{attributeName: 'pk', keyType: 'HASH'}], + }) + }) + + test('list filters results by search term', async () => { + const adapter = new AwsDynamoDbAdapter(fakeService({ + listTables: async () => [ + baseTable, + {...baseTable, tableName: 'orders'}, + ], + })) + + const result = await adapter.list({search: 'user'}) + + expect(result).toHaveLength(1) + expect(result[0].name).toBe('users') + }) + + test('list returns an empty array when no tables exist', async () => { + const adapter = new AwsDynamoDbAdapter(fakeService({ + listTables: async () => [], + })) + + await expect(adapter.list()).resolves.toEqual([]) + }) + + test('get returns null when the table is not found', async () => { + const notFound = Object.assign(new Error('Requested resource not found'), { + name: 'ResourceNotFoundException', + $metadata: {httpStatusCode: 404}, + }) + const adapter = new AwsDynamoDbAdapter(fakeService({ + describeTable: async () => { + throw notFound + }, + })) + + await expect(adapter.get('missing')).resolves.toBeNull() + }) + + test('get rethrows non-404 errors', async () => { + const adapter = new AwsDynamoDbAdapter(fakeService({ + describeTable: async () => { + throw new Error('boom') + }, + })) + + await expect(adapter.get('users')).rejects.toThrow('boom') + }) + + test('schema returns the aws dynamodb schema', () => { + const adapter = new AwsDynamoDbAdapter(fakeService()) + const schema = adapter.schema() + + expect(schema.cloud).toBe('aws') + expect(schema.service).toBe('dynamodb') + expect(schema.displayName).toBe('DynamoDB') + expect(schema.actions).toContain('list') + expect(schema.actions).toContain('inspect') + }) +}) diff --git a/packages/api/src/adapter-aws/AwsDynamoDbAdapter.ts b/packages/api/src/adapter-aws/AwsDynamoDbAdapter.ts new file mode 100644 index 0000000..9bd3675 --- /dev/null +++ b/packages/api/src/adapter-aws/AwsDynamoDbAdapter.ts @@ -0,0 +1,80 @@ +import {awsDynamoDbSchema} from '../cloud-spi/dynamodbSchema' +import type { + CloudResource, + CloudServiceAdapter, + CreateResourceInput, + ResourceQuery, + ServiceSchema, +} from '../cloud-spi/types' +import {dynamoDbService, type DynamoDbTable} from '../services/dynamodb' + +type DynamoDbServiceShape = { + listTables(): Promise + describeTable(tableName: string): Promise +} + +export class AwsDynamoDbAdapter implements CloudServiceAdapter { + readonly cloud = 'aws' as const + readonly service = 'dynamodb' as const + + constructor(private readonly service_: DynamoDbServiceShape = dynamoDbService) {} + + schema(): ServiceSchema { + return awsDynamoDbSchema() + } + + async list(query: ResourceQuery = {}): Promise { + const resources = (await this.service_.listTables()).map(tableToResource) + return filterBySearch(resources, query.search) + } + + async get(id: string): Promise { + try { + return tableToResource(await this.service_.describeTable(id)) + } catch (error) { + if (hasNotFoundStatus(error)) return null + throw error + } + } + + async create(_input: CreateResourceInput): Promise { + throw new Error('DynamoDB table creation is not supported from the dynamic Cloud Explorer.') + } + + async delete(_id: string): Promise { + throw new Error('DynamoDB table deletion is not supported from the dynamic Cloud Explorer.') + } +} + +function tableToResource(table: DynamoDbTable): CloudResource { + return { + id: table.tableName, + name: table.tableName, + cloud: 'aws', + service: 'dynamodb', + type: 'dynamodb-table', + region: table.region, + createdAt: table.createdAt ?? null, + status: table.status ?? null, + metadata: { + arn: table.arn, + billingMode: table.billingMode, + itemCount: table.itemCount, + sizeBytes: table.sizeBytes, + keySchema: table.keySchema, + }, + } +} + +function filterBySearch(resources: CloudResource[], search?: string): CloudResource[] { + const normalized = search?.trim().toLowerCase() + if (!normalized) return resources + return resources.filter((resource) => resource.name.toLowerCase().includes(normalized)) +} + +function hasNotFoundStatus(error: unknown): boolean { + if (typeof error !== 'object' || error === null) return false + const metadata = (error as {$metadata?: {httpStatusCode?: number}}).$metadata + const name = 'name' in error ? error.name : undefined + return metadata?.httpStatusCode === 404 || name === 'ResourceNotFoundException' +} diff --git a/packages/api/src/aws.test.ts b/packages/api/src/aws.test.ts new file mode 100644 index 0000000..87aa9aa --- /dev/null +++ b/packages/api/src/aws.test.ts @@ -0,0 +1,12 @@ +import {describe, expect, test} from 'bun:test' +import {awsClients, awsRegion} from './aws' + +describe('aws client registry', () => { + test('exposes a dynamodb client', () => { + expect(typeof awsClients.dynamodb.send).toBe('function') + }) + + test('exports the resolved aws region', () => { + expect(awsRegion).toBe(process.env.AWS_REGION ?? 'us-east-1') + }) +}) diff --git a/packages/api/src/aws.ts b/packages/api/src/aws.ts index e9ae0c9..d8339b5 100644 --- a/packages/api/src/aws.ts +++ b/packages/api/src/aws.ts @@ -4,9 +4,10 @@ import { EKSClient } from "@aws-sdk/client-eks"; import { EC2Client } from "@aws-sdk/client-ec2"; import { RDSClient } from "@aws-sdk/client-rds"; import { SecretsManagerClient } from "@aws-sdk/client-secrets-manager"; +import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; const endpoint = process.env.FLOCI_ENDPOINT; -const region = process.env.AWS_REGION || "us-east-1"; +export const awsRegion = process.env.AWS_REGION || "us-east-1"; // Floci derives the AWS account from AWS_ACCESS_KEY_ID: a value that is exactly // 12 digits is used verbatim as the account id, and resources are isolated per @@ -39,6 +40,7 @@ export type AwsClients = { ec2: EC2Client; rds: RDSClient; secretsManager: SecretsManagerClient; + dynamodb: DynamoDBClient; }; export type AwsClientName = keyof AwsClients; @@ -47,7 +49,7 @@ const clientCache = new Map(); function buildClients(accountId: string): AwsClients { const base = { - region, + region: awsRegion, credentials: { accessKeyId: accountId, secretAccessKey: SECRET_ACCESS_KEY }, ...(endpoint ? { endpoint, forcePathStyle: true } : {}), }; @@ -58,6 +60,7 @@ function buildClients(accountId: string): AwsClients { ec2: new EC2Client(base), rds: new RDSClient(base), secretsManager: new SecretsManagerClient(base), + dynamodb: new DynamoDBClient(base), }; } @@ -89,3 +92,4 @@ export const eks = awsClients.eks; export const ec2 = awsClients.ec2; export const rds = awsClients.rds; export const secretsManager = awsClients.secretsManager; +export const dynamodb = awsClients.dynamodb; diff --git a/packages/api/src/cloud-spi/dynamodbSchema.test.ts b/packages/api/src/cloud-spi/dynamodbSchema.test.ts new file mode 100644 index 0000000..e66d343 --- /dev/null +++ b/packages/api/src/cloud-spi/dynamodbSchema.test.ts @@ -0,0 +1,26 @@ +import {describe, expect, test} from 'bun:test' +import {awsDynamoDbSchema, dynamodbSchemaFor} from './dynamodbSchema' + +describe('dynamodb schema', () => { + test('returns the aws dynamodb schema', () => { + const schema = awsDynamoDbSchema() + + expect(schema.cloud).toBe('aws') + expect(schema.service).toBe('dynamodb') + expect(schema.displayName).toBe('DynamoDB') + expect(schema.actions).toEqual(['list', 'inspect']) + expect(schema.columns.map((column) => column.name)).toEqual([ + 'name', + 'status', + 'billingMode', + 'itemCount', + 'sizeBytes', + ]) + }) + + test('returns a provider fallback only for aws', () => { + expect(dynamodbSchemaFor('aws')?.displayName).toBe('DynamoDB') + expect(dynamodbSchemaFor('azure')).toBeNull() + expect(dynamodbSchemaFor('gcp')).toBeNull() + }) +}) diff --git a/packages/api/src/cloud-spi/dynamodbSchema.ts b/packages/api/src/cloud-spi/dynamodbSchema.ts new file mode 100644 index 0000000..306adbb --- /dev/null +++ b/packages/api/src/cloud-spi/dynamodbSchema.ts @@ -0,0 +1,30 @@ +import type {CloudProvider, FieldSchema, ServiceSchema, TableColumnSchema} from './types' + +const dynamodbColumns: TableColumnSchema[] = [ + {name: 'name', label: 'Name'}, + {name: 'status', label: 'Status'}, + {name: 'billingMode', label: 'Billing Mode'}, + {name: 'itemCount', label: 'Item Count'}, + {name: 'sizeBytes', label: 'Size (Bytes)'}, +] + +const dynamodbFilters: FieldSchema[] = [ + {name: 'search', label: 'Search', type: 'text', required: false}, +] + +export function awsDynamoDbSchema(): ServiceSchema { + return { + cloud: 'aws', + service: 'dynamodb', + displayName: 'DynamoDB', + fields: [], + actions: ['list', 'inspect'], + filters: dynamodbFilters, + columns: dynamodbColumns, + } +} + +export function dynamodbSchemaFor(cloud: CloudProvider): ServiceSchema | null { + if (cloud === 'aws') return awsDynamoDbSchema() + return null +} diff --git a/packages/api/src/cloud-spi/types.ts b/packages/api/src/cloud-spi/types.ts index be2a569..d72f2f6 100644 --- a/packages/api/src/cloud-spi/types.ts +++ b/packages/api/src/cloud-spi/types.ts @@ -1,6 +1,6 @@ export type CloudProvider = 'aws' | 'azure' | 'gcp' -export type CloudServiceType = 'storage' | 'k8s' | 'database' | 'serverless' | 'compute' | 'networking' +export type CloudServiceType = 'storage' | 'k8s' | 'database' | 'dynamodb' | 'serverless' | 'compute' | 'networking' export type CloudAvailability = 'available' | 'coming_soon' @@ -83,7 +83,7 @@ export interface CloudResource { name: string cloud: CloudProvider service: CloudServiceType - type: 'bucket' | 'container' | 'cluster' | 'db-instance' | 'cosmos-database' | 'instance' | 'image' | 'vpc' | 'lambda' | 'azure-function' + type: 'bucket' | 'container' | 'cluster' | 'db-instance' | 'cosmos-database' | 'dynamodb-table' | 'instance' | 'image' | 'vpc' | 'lambda' | 'azure-function' region: string | null createdAt: string | null status?: string | null diff --git a/packages/api/src/cloudProxy.ts b/packages/api/src/cloudProxy.ts index e7ace97..65fcf77 100644 --- a/packages/api/src/cloudProxy.ts +++ b/packages/api/src/cloudProxy.ts @@ -2,6 +2,7 @@ import {CloudAdapterRegistry} from './registry/CloudAdapterRegistry' import {AwsComputeAdapter} from './adapter-aws/AwsComputeAdapter' import {AwsNetworkingAdapter} from './adapter-aws/AwsNetworkingAdapter' import {AwsDatabaseAdapter} from './adapter-aws/AwsDatabaseAdapter' +import {AwsDynamoDbAdapter} from './adapter-aws/AwsDynamoDbAdapter' import {AwsEksAdapter} from './adapter-aws/AwsEksAdapter' import {AwsStorageAdapter} from './adapter-aws/AwsStorageAdapter' import {AzureDatabaseAdapter} from './adapter-azure/AzureDatabaseAdapter' @@ -12,6 +13,7 @@ import {AzureServerlessAdapter} from './adapter-azure/AzureServerlessAdapter' import {AwsServerlessAdapter} from './adapter-aws/AwsServerlessAdapter' import {awsClientsForAccount, resolveAccountId} from './aws' import {createEc2Service} from './services/ec2' +import {createDynamoDbService} from './services/dynamodb' import {createEksService} from './services/eks' import {createRdsService} from './services/rds' @@ -24,11 +26,13 @@ import {createRdsService} from './services/rds' export function createCloudProxyService(accountId?: string | null): CloudProxyService { const clients = awsClientsForAccount(accountId) const ec2Service = createEc2Service(clients.ec2) + const dynamoDbService = createDynamoDbService(clients.dynamodb) const registry = new CloudAdapterRegistry([ new AwsStorageAdapter(clients.s3), new AwsEksAdapter(createEksService(clients.eks)), new AwsDatabaseAdapter(createRdsService(clients.rds), clients.rds), + new AwsDynamoDbAdapter(dynamoDbService), new AwsComputeAdapter(ec2Service), new AwsNetworkingAdapter(ec2Service), new AwsServerlessAdapter(clients.lambda), diff --git a/packages/api/src/routes/clouds.account.test.ts b/packages/api/src/routes/clouds.account.test.ts new file mode 100644 index 0000000..421627c --- /dev/null +++ b/packages/api/src/routes/clouds.account.test.ts @@ -0,0 +1,56 @@ +import {describe, expect, mock, test} from 'bun:test' + +const requestedAccountIds: Array = [] + +mock.module('../cloudProxy', () => ({ + serviceForAccount(accountId?: string | null) { + requestedAccountIds.push(accountId) + + const resolvedAccountId = accountId ?? '000000000000' + + return { + clouds: () => [], + services: () => [], + status: async () => ({cloud: 'aws', adapterRegistered: true, runtime: 'reachable', endpoint: 'http://localhost:4566', checkedAt: new Date().toISOString(), error: null}), + schema: () => null, + listResources: async () => [{ + id: `table-${resolvedAccountId}`, + name: `table-${resolvedAccountId}`, + cloud: 'aws', + service: 'dynamodb', + type: 'dynamodb-table', + region: 'us-east-1', + createdAt: null, + status: 'ACTIVE', + metadata: {accountId: resolvedAccountId}, + }], + } + }, +})) + +const {createCloudRoutes, ACCOUNT_HEADER} = await import('./clouds') + +describe('cloud account routing', () => { + test('scopes dynamodb resources by x-floci-account-id', async () => { + const app = createCloudRoutes() + + const firstResponse = await app.request('/aws/services/dynamodb/resources', { + headers: {[ACCOUNT_HEADER]: '111111111111'}, + }) + const secondResponse = await app.request('/aws/services/dynamodb/resources', { + headers: {[ACCOUNT_HEADER]: '222222222222'}, + }) + + expect(firstResponse.status).toBe(200) + expect(secondResponse.status).toBe(200) + expect(await firstResponse.json()).toEqual([expect.objectContaining({ + id: 'table-111111111111', + metadata: {accountId: '111111111111'}, + })]) + expect(await secondResponse.json()).toEqual([expect.objectContaining({ + id: 'table-222222222222', + metadata: {accountId: '222222222222'}, + })]) + expect(requestedAccountIds).toEqual(['111111111111', '222222222222']) + }) +}) diff --git a/packages/api/src/routes/clouds.test.ts b/packages/api/src/routes/clouds.test.ts index 49296be..8bbe7cb 100644 --- a/packages/api/src/routes/clouds.test.ts +++ b/packages/api/src/routes/clouds.test.ts @@ -1,6 +1,7 @@ import {describe, expect, test} from 'bun:test' import {Hono} from 'hono' import {azureDatabaseSchema} from '../cloud-spi/databaseSchema' +import {awsDynamoDbSchema} from '../cloud-spi/dynamodbSchema' import {awsStorageSchema, azureStorageSchema} from '../cloud-spi/storageSchema' import type {CloudResource, CloudServiceAdapter, CosmosContainer, CosmosItem, CosmosQueryResult, CreateResourceInput} from '../cloud-spi/types' import {CloudAdapterRegistry} from '../registry/CloudAdapterRegistry' @@ -116,6 +117,20 @@ describe('cloud schema routes', () => { expect(gcpBody.displayName).toBe('Cloud SQL') }) + test('returns AWS dynamodb schema when the adapter is registered', async () => { + const app = appWithRoutes([mockAdapter('aws', { + service: 'dynamodb', + schema: awsDynamoDbSchema, + })]) + const res = await app.request('/api/clouds/aws/services/dynamodb/schema') + const body = await res.json() + + expect(res.status).toBe(200) + expect(body.cloud).toBe('aws') + expect(body.service).toBe('dynamodb') + expect(body.displayName).toBe('DynamoDB') + }) + test('returns AWS cloud status', async () => { const res = await appWithRoutes().request('/api/clouds/aws/status') const body = await res.json() @@ -146,6 +161,55 @@ describe('cloud schema routes', () => { expect(body.objects[0].name).toBe('object.txt') }) + test('lists dynamodb resources through the cloud adapter', async () => { + const app = appWithRoutes([mockAdapter('aws', { + service: 'dynamodb', + schema: awsDynamoDbSchema, + list: async (): Promise => [{ + id: 'users', + name: 'users', + cloud: 'aws', + service: 'dynamodb', + type: 'dynamodb-table', + region: 'us-east-1', + createdAt: null, + status: 'ACTIVE', + metadata: {}, + }], + })]) + + const res = await app.request('/api/clouds/aws/services/dynamodb/resources') + const body = await res.json() + + expect(res.status).toBe(200) + expect(body).toHaveLength(1) + expect(body[0].service).toBe('dynamodb') + expect(body[0].type).toBe('dynamodb-table') + }) + + test('does not expose a duplicate dynamodb alias route', async () => { + const res = await appWithRoutes().request('/api/clouds/aws/dynamodb/resources') + + expect(res.status).toBe(404) + }) + + test('includes dynamodb in the aws service listing when registered', async () => { + const app = appWithRoutes([ + mockAdapter('aws'), + mockAdapter('aws', { + service: 'dynamodb', + schema: awsDynamoDbSchema, + list: async () => [], + }), + ]) + + const res = await app.request('/api/clouds/aws/services') + const body = await res.json() + + expect(res.status).toBe(200) + expect(body.some((entry: {service: string}) => entry.service === 'dynamodb')).toBe(true) + }) + test('lists Cosmos containers through the cloud database adapter', async () => { const app = appWithRoutes([mockAdapter('azure', { service: 'database', diff --git a/packages/api/src/routes/clouds.ts b/packages/api/src/routes/clouds.ts index bd11b1e..d14206c 100644 --- a/packages/api/src/routes/clouds.ts +++ b/packages/api/src/routes/clouds.ts @@ -242,7 +242,7 @@ function isCloudProvider(value: string): value is CloudProvider { } function isServiceType(value: string): value is CloudServiceType { - return value === 'storage' || value === 'k8s' || value === 'database' || value === 'serverless' || value === 'compute' || value === 'networking' + return value === 'storage' || value === 'k8s' || value === 'database' || value === 'dynamodb' || value === 'serverless' || value === 'compute' || value === 'networking' } async function withRuntime(c: Context, handler: () => Promise): Promise { diff --git a/packages/api/src/service/CloudProxyService.ts b/packages/api/src/service/CloudProxyService.ts index 0c7803d..c4d2ddd 100644 --- a/packages/api/src/service/CloudProxyService.ts +++ b/packages/api/src/service/CloudProxyService.ts @@ -19,6 +19,7 @@ import {CloudAdapterRegistry} from '../registry/CloudAdapterRegistry' import {serverlessSchemaFor} from '../cloud-spi/serverlessSchema' import {k8sSchemaFor} from '../cloud-spi/eksSchema' import {databaseSchemaFor} from '../cloud-spi/databaseSchema' +import {dynamodbSchemaFor} from '../cloud-spi/dynamodbSchema' import {azureEndpoint} from '../azure' import {checkGcpRuntime, gcpEndpoint} from '../gcp' @@ -54,6 +55,12 @@ export class CloudProxyService { displayName: 'Database', availability: this.registry.get(cloud, 'database') ? 'available' : 'coming_soon', }) + services.push({ + cloud, + service: 'dynamodb', + displayName: 'DynamoDB', + availability: this.registry.get(cloud, 'dynamodb') ? 'available' : 'coming_soon', + }) services.push({ cloud, service: 'serverless', @@ -81,6 +88,7 @@ export class CloudProxyService { if (service === 'storage') return storageSchemaFor(cloud) if (service === 'k8s') return k8sSchemaFor(cloud) if (service === 'database') return databaseSchemaFor(cloud) + if (service === 'dynamodb') return dynamodbSchemaFor(cloud) if (service === 'serverless') return serverlessSchemaFor(cloud) return null } diff --git a/packages/api/src/services/dynamodb.test.ts b/packages/api/src/services/dynamodb.test.ts new file mode 100644 index 0000000..b14bafa --- /dev/null +++ b/packages/api/src/services/dynamodb.test.ts @@ -0,0 +1,132 @@ +import {describe, expect, test} from 'bun:test' +import {DescribeTableCommand, ListTablesCommand, type DynamoDBClient} from '@aws-sdk/client-dynamodb' +import {createDynamoDbService} from './dynamodb' + +type SentCommand = { + name: string + input: unknown +} + +function fakeClient(handler: (command: DescribeTableCommand | ListTablesCommand) => Promise): Pick { + return { + send: handler as DynamoDBClient['send'], + } +} + +describe('dynamodb service', () => { + test('listTables paginates list calls and normalizes described tables', async () => { + const sent: SentCommand[] = [] + const service = createDynamoDbService(fakeClient(async (command) => { + sent.push({name: command.constructor.name, input: command.input}) + + if (command instanceof ListTablesCommand && !command.input.ExclusiveStartTableName) { + return { + TableNames: ['users'], + LastEvaluatedTableName: 'users', + } + } + + if (command instanceof ListTablesCommand) { + return { + TableNames: ['orders'], + } + } + + if (command.input.TableName === 'users') { + return { + Table: { + TableName: 'users', + TableArn: 'arn:aws:dynamodb:us-east-1:123456789012:table/users', + TableStatus: 'ACTIVE', + BillingModeSummary: {BillingMode: 'PAY_PER_REQUEST'}, + ItemCount: 12, + TableSizeBytes: 256, + KeySchema: [{AttributeName: 'pk', KeyType: 'HASH'}], + CreationDateTime: new Date('2025-01-01T00:00:00.000Z'), + }, + } + } + + return { + Table: { + TableName: 'orders', + TableArn: 'arn:aws:dynamodb:us-east-1:123456789012:table/orders', + TableStatus: 'CREATING', + BillingModeSummary: {BillingMode: 'PROVISIONED'}, + ItemCount: 3, + TableSizeBytes: 128, + KeySchema: [{AttributeName: 'orderId', KeyType: 'HASH'}], + CreationDateTime: new Date('2025-01-02T00:00:00.000Z'), + }, + } + }), 'us-east-1') + + const tables = await service.listTables() + + expect(tables).toHaveLength(2) + expect(tables[0]).toMatchObject({ + tableName: 'users', + status: 'ACTIVE', + billingMode: 'PAY_PER_REQUEST', + itemCount: 12, + sizeBytes: 256, + region: 'us-east-1', + }) + expect(tables[1]).toMatchObject({ + tableName: 'orders', + status: 'CREATING', + billingMode: 'PROVISIONED', + itemCount: 3, + }) + expect(sent).toEqual([ + {name: 'ListTablesCommand', input: {}}, + {name: 'ListTablesCommand', input: {ExclusiveStartTableName: 'users'}}, + {name: 'DescribeTableCommand', input: {TableName: 'users'}}, + {name: 'DescribeTableCommand', input: {TableName: 'orders'}}, + ]) + }) + + test('returns an empty list when aws reports no tables', async () => { + const service = createDynamoDbService(fakeClient(async (command) => { + if (command instanceof ListTablesCommand) return {TableNames: []} + throw new Error('DescribeTable should not be called when there are no tables') + }), 'us-east-1') + + await expect(service.listTables()).resolves.toEqual([]) + }) + + test('describeTable normalizes a single table result', async () => { + const service = createDynamoDbService(fakeClient(async (command) => { + if (command instanceof DescribeTableCommand) { + return { + Table: { + TableName: 'users', + TableArn: 'arn:aws:dynamodb:us-east-1:123456789012:table/users', + TableStatus: 'ACTIVE', + BillingModeSummary: {BillingMode: 'PAY_PER_REQUEST'}, + ItemCount: 12, + TableSizeBytes: 256, + KeySchema: [{AttributeName: 'pk', KeyType: 'HASH'}], + CreationDateTime: new Date('2025-01-01T00:00:00.000Z'), + }, + } + } + + throw new Error('ListTables should not be called during describeTable') + }), 'us-east-1') + + const table = await service.describeTable('users') + + expect(table).toEqual({ + tableName: 'users', + arn: 'arn:aws:dynamodb:us-east-1:123456789012:table/users', + status: 'ACTIVE', + billingMode: 'PAY_PER_REQUEST', + itemCount: 12, + sizeBytes: 256, + keySchema: [{attributeName: 'pk', keyType: 'HASH'}], + region: 'us-east-1', + createdAt: '2025-01-01T00:00:00.000Z', + }) + }) +}) diff --git a/packages/api/src/services/dynamodb.ts b/packages/api/src/services/dynamodb.ts new file mode 100644 index 0000000..23cda88 --- /dev/null +++ b/packages/api/src/services/dynamodb.ts @@ -0,0 +1,75 @@ +import { + DescribeTableCommand, + ListTablesCommand, + type DynamoDBClient, + type KeySchemaElement, + type TableDescription, +} from '@aws-sdk/client-dynamodb' +import {awsClients, awsRegion} from '../aws' + +export type DynamoDbKeySchema = { + attributeName?: string + keyType?: string +} + +export type DynamoDbTable = { + tableName: string + arn?: string + status?: string + billingMode?: string + itemCount?: number + sizeBytes?: number + keySchema: DynamoDbKeySchema[] + region: string + createdAt?: string +} + +type DynamoDbClientShape = Pick + +export function createDynamoDbService(client: DynamoDbClientShape = awsClients.dynamodb, region: string = awsRegion) { + return { + async listTables(): Promise { + const tableNames: string[] = [] + let lastEvaluatedTableName: string | undefined + + do { + const response = await client.send(new ListTablesCommand({ + ...(lastEvaluatedTableName ? {ExclusiveStartTableName: lastEvaluatedTableName} : {}), + })) + tableNames.push(...(response.TableNames ?? [])) + lastEvaluatedTableName = response.LastEvaluatedTableName + } while (lastEvaluatedTableName) + + // ListTables only returns table names, so describe each table to populate the CloudResource metadata used by the explorer. + return Promise.all(tableNames.map((tableName) => this.describeTable(tableName))) + }, + + async describeTable(tableName: string): Promise { + const response = await client.send(new DescribeTableCommand({TableName: tableName})) + return toDynamoDbTable(response.Table ?? {}, region) + }, + } +} + +function toDynamoDbTable(table: TableDescription, region: string): DynamoDbTable { + return { + tableName: table.TableName ?? '', + arn: table.TableArn, + status: table.TableStatus, + billingMode: table.BillingModeSummary?.BillingMode, + itemCount: table.ItemCount, + sizeBytes: table.TableSizeBytes, + keySchema: (table.KeySchema ?? []).map(toKeySchema), + region, + createdAt: table.CreationDateTime?.toISOString(), + } +} + +function toKeySchema(key: KeySchemaElement): DynamoDbKeySchema { + return { + attributeName: key.AttributeName, + keyType: key.KeyType, + } +} + +export const dynamoDbService = createDynamoDbService() diff --git a/packages/frontend/package.json b/packages/frontend/package.json index ffb0c9b..67fd115 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -8,7 +8,8 @@ "dev": "vite", "build": "tsc && vite build", "preview": "vite preview", - "lint": "eslint src --report-unused-disable-directives --max-warnings 0", + "test": "vitest run", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "type-check": "tsc --noEmit" }, "dependencies": { @@ -25,6 +26,9 @@ "zustand": "^5.0.13" }, "devDependencies": { + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", + "@testing-library/user-event": "^14.6.1", "@types/node": "^25.8.0", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.0", @@ -35,10 +39,12 @@ "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-react-refresh": "^0.5.2", "globals": "^16.0.0", + "jsdom": "^29.1.1", "postcss": "^8.5.15", "tailwindcss": "^3.4.3", "typescript": "^5.4.5", "typescript-eslint": "^8.60.1", - "vite": "^8.0.13" + "vite": "^8.0.13", + "vitest": "^1.6.1" } } diff --git a/packages/frontend/src/components/Layout.test.tsx b/packages/frontend/src/components/Layout.test.tsx new file mode 100644 index 0000000..be37068 --- /dev/null +++ b/packages/frontend/src/components/Layout.test.tsx @@ -0,0 +1,69 @@ +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import userEvent from "@testing-library/user-event"; +import { render, screen, waitFor } from "@testing-library/react"; +import { MemoryRouter, Route, Routes } from "react-router-dom"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { Layout } from "@/components/Layout"; + +const getCloudStatus = vi.fn(); + +vi.mock("@/api/cloudProxyClient", () => ({ + getCloudStatus: (...args: unknown[]) => getCloudStatus(...args), +})); + +describe("Layout cloud navigation", () => { + beforeEach(() => { + getCloudStatus.mockResolvedValue({ + cloud: "aws", + adapterRegistered: true, + runtime: "reachable", + endpoint: "http://localhost:4566", + checkedAt: "2026-06-10T00:00:00.000Z", + error: null, + }); + }); + + it("shows the grouped database navigation with DynamoDB active on the dedicated route", async () => { + renderLayout("/cloud-explorer/aws/dynamodb"); + + const trigger = await screen.findByRole("button", { name: "Database" }); + expect(trigger).toHaveAttribute("aria-expanded", "true"); + expect(screen.getByRole("link", { name: "DynamoDB" })).toHaveAttribute("aria-current", "page"); + expect(screen.getByRole("link", { name: "Database" })).toHaveAttribute("href", "/cloud-explorer/aws/database"); + }); + + it("opens the database group with keyboard input and moves focus to the first child route", async () => { + const user = userEvent.setup(); + renderLayout("/cloud-explorer/aws/storage"); + + const trigger = await screen.findByRole("button", { name: "Database" }); + trigger.focus(); + await user.keyboard("{ArrowDown}"); + + await waitFor(() => { + expect(trigger).toHaveAttribute("aria-expanded", "true"); + }); + expect(screen.getByRole("link", { name: "Database" })).toHaveFocus(); + expect(screen.getByRole("link", { name: "DynamoDB" })).toBeInTheDocument(); + }); +}); + +function renderLayout(initialEntry: string) { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, + }, + }); + + return render( + + + + }> + Child page} /> + + + + , + ); +} diff --git a/packages/frontend/src/components/Layout.tsx b/packages/frontend/src/components/Layout.tsx index 46f24d9..fa520a7 100644 --- a/packages/frontend/src/components/Layout.tsx +++ b/packages/frontend/src/components/Layout.tsx @@ -1,8 +1,10 @@ +import {type ElementType, type KeyboardEvent, useEffect, useId, useRef, useState} from 'react' import {NavLink, Outlet, useLocation} from 'react-router-dom' import { Database, Boxes, KeyRound, + ChevronDown, LayoutDashboard, MessageSquare, Moon, @@ -20,10 +22,10 @@ import {useQuery} from '@tanstack/react-query' import {getCloudStatus} from '@/api/cloudProxyClient' import {AccountSwitcher} from '@/components/AccountSwitcher' -function NavItem({to, icon, label}: { to: string; icon: React.ElementType; label: string }) { +function NavItem({to, icon, label, className}: { to: string; icon: ElementType; label: string; className?: string }) { const Icon = icon return ( - + navLinkClassName(className, isActive)} to={to}> {label} @@ -40,14 +42,13 @@ const CLOUD_SERVICE_ICONS = { compute: Server, networking: Network, serverless: Zap, -} satisfies Record +} satisfies Record type CloudSidebarService = keyof typeof CLOUD_SERVICE_ICONS const CLOUD_SERVICE_ITEMS: Array<{name: CloudSidebarService; label: string; route?: string}> = [ {name: 'storage', label: 'Storage', route: 'storage'}, {name: 'k8s', label: 'k8s Engine', route: 'k8s'}, - {name: 'database', label: 'Database', route: 'database'}, {name: 'compute', label: 'Compute', route: 'compute'}, {name: 'networking', label: 'Networking', route: 'networking'}, {name: 'secretsmanager', label: 'Secrets Manager', route: '/secretsmanager'}, @@ -60,6 +61,8 @@ function CloudServiceNav() { const location = useLocation() const cloud = activeCloudFromPath(location.pathname) const cloudLabel = cloud.toUpperCase() + const showDatabaseGroup = cloud === 'aws' + const showDatabaseLink = cloud === 'azure' return (
@@ -83,6 +86,77 @@ function CloudServiceNav() {
) })} + {showDatabaseGroup + ? + : showDatabaseLink + ? + : ( +
+ + Database + Soon +
+ )} + + ) +} + +function DatabaseGroupNav({cloud}: {cloud: 'aws'}) { + const location = useLocation() + const groupId = useId() + const databaseLinkRef = useRef(null) + const isActive = location.pathname === `/cloud-explorer/${cloud}/database` + || location.pathname === `/cloud-explorer/${cloud}/dynamodb` + const [isOpen, setIsOpen] = useState(isActive) + const [focusFirstChild, setFocusFirstChild] = useState(false) + + useEffect(() => { + if (isActive) { + setIsOpen(true) + } + }, [isActive]) + + useEffect(() => { + if (isOpen && focusFirstChild) { + databaseLinkRef.current?.focus() + setFocusFirstChild(false) + } + }, [focusFirstChild, isOpen]) + + const openAndFocusFirstChild = () => { + setIsOpen(true) + setFocusFirstChild(true) + } + + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown') { + event.preventDefault() + openAndFocusFirstChild() + } + } + + return ( +
+ +
+ navLinkClassName('nav-sublink', linkActive)} ref={databaseLinkRef} to={`/cloud-explorer/${cloud}/database`}> + Database + + navLinkClassName('nav-sublink', linkActive)} to={`/cloud-explorer/${cloud}/dynamodb`}> + DynamoDB + +
) } @@ -149,3 +223,11 @@ function activeCloudFromPath(pathname: string): 'aws' | 'azure' | 'gcp' { const match = pathname.match(/^\/(?:cloud-explorer|console)\/(aws|azure|gcp)(?:\/|$)/) return (match?.[1] ?? 'aws') as 'aws' | 'azure' | 'gcp' } + +function navLinkClassName(className: string | undefined, isActive: boolean): string { + return [className ?? 'nav-link', isActive ? 'active' : ''].filter(Boolean).join(' ') +} + +function navGroupTriggerClassName(isActive: boolean): string { + return ['nav-link', 'nav-group-trigger', isActive ? 'active' : ''].filter(Boolean).join(' ') +} diff --git a/packages/frontend/src/features/cloud-console/cloudConsoleHome.utils.ts b/packages/frontend/src/features/cloud-console/cloudConsoleHome.utils.ts index 688d09c..58d1089 100644 --- a/packages/frontend/src/features/cloud-console/cloudConsoleHome.utils.ts +++ b/packages/frontend/src/features/cloud-console/cloudConsoleHome.utils.ts @@ -25,7 +25,7 @@ export function runtimeDetailFor(cloud: CloudProvider, status?: CloudStatus): st } export function activeServicesDetailFor(cloud: CloudProvider): string { - if (cloud === 'aws') return 'Storage, k8s Engine, Database, and Secrets Manager are wired' + if (cloud === 'aws') return 'Storage, k8s Engine, Database, Secrets Manager and DynamoDB are wired' if (cloud === 'gcp') return 'Storage is wired through Floci-GCP' return 'Storage only for this multi-cloud pass' } @@ -42,7 +42,7 @@ export function resourceDetailFor( if (status?.runtime === 'coming_soon') return 'No adapter registered yet' if (resourcesLoading) return 'Loading normalized resources' if (resourcesError) return 'Resource load failed' - if (cloud === 'aws') return 'Storage, k8s Engine, Database, and Secrets Manager resources' + if (cloud === 'aws') return 'Storage, k8s Engine, Database, Secrets Manager and DynamoDB resources' if (cloud === 'gcp') return 'Cloud Storage resources' return 'Normalized storage resources' } diff --git a/packages/frontend/src/features/cloud-console/useCloudConsoleHomeData.test.tsx b/packages/frontend/src/features/cloud-console/useCloudConsoleHomeData.test.tsx new file mode 100644 index 0000000..9cbafc2 --- /dev/null +++ b/packages/frontend/src/features/cloud-console/useCloudConsoleHomeData.test.tsx @@ -0,0 +1,82 @@ +import { renderHook } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { useCloudConsoleHomeData } from "@/features/cloud-console/useCloudConsoleHomeData"; + +const useCloudsQuery = vi.fn(); +const useCloudServicesQuery = vi.fn(); +const useCloudStatusQuery = vi.fn(); +const useCloudConsoleResourcesQuery = vi.fn(); +const useSecretsQuery = vi.fn(); + +vi.mock("@/features/cloud-console/cloudConsoleHome.queries", () => ({ + useCloudsQuery: () => useCloudsQuery(), + useCloudServicesQuery: (...args: unknown[]) => useCloudServicesQuery(...args), + useCloudStatusQuery: (...args: unknown[]) => useCloudStatusQuery(...args), + useCloudConsoleResourcesQuery: (...args: unknown[]) => useCloudConsoleResourcesQuery(...args), +})); + +vi.mock("@/api/aws/secretsmanager.queries", () => ({ + useSecretsQuery: (...args: unknown[]) => useSecretsQuery(...args), +})); + +describe("useCloudConsoleHomeData", () => { + beforeEach(() => { + useCloudsQuery.mockReturnValue({ data: [] }); + useCloudServicesQuery.mockReturnValue({ + data: [ + { cloud: "aws", service: "storage", displayName: "Storage", availability: "available" }, + { cloud: "aws", service: "k8s", displayName: "k8s Engine", availability: "available" }, + { cloud: "aws", service: "database", displayName: "Database", availability: "available" }, + { cloud: "aws", service: "dynamodb", displayName: "DynamoDB", availability: "available" }, + ], + }); + useCloudStatusQuery.mockReturnValue({ + data: { + cloud: "aws", + adapterRegistered: true, + runtime: "reachable", + endpoint: "http://localhost:4566", + checkedAt: "2026-06-10T00:00:00.000Z", + error: null, + }, + isLoading: false, + }); + useSecretsQuery.mockReturnValue({ data: [{ name: "secret-1" }], isLoading: false, isError: false }); + useCloudConsoleResourcesQuery.mockImplementation(({ service }: { service: string }) => { + if (service === "storage") return { data: [{ id: "bucket-1" }], isLoading: false, isError: false }; + if (service === "k8s") return { data: [{ id: "cluster-1" }], isLoading: false, isError: false }; + if (service === "database") return { data: [{ id: "db-1" }], isLoading: false, isError: false }; + return { data: [{ id: "table-1" }, { id: "table-2" }], isLoading: false, isError: false }; + }); + }); + + it("adds DynamoDB and Secrets Manager cards and counts both resource families", () => { + const { result } = renderHook(() => useCloudConsoleHomeData("aws")); + + expect(result.current.serviceCards.map((service) => service.id)).toContain("dynamodb"); + expect(result.current.serviceCards.map((service) => service.id)).toContain("secretsmanager"); + expect(result.current.serviceCards.find((service) => service.id === "dynamodb")).toMatchObject({ + label: "DynamoDB", + count: 2, + route: "/cloud-explorer/aws/dynamodb", + }); + expect(result.current.resourceCount).toBe(6); + expect(result.current.activeServicesDetail).toContain("DynamoDB"); + expect(result.current.activeServicesDetail).toContain("Secrets Manager"); + }); + + it("keeps the DynamoDB card discoverable when the runtime reports zero tables", () => { + useCloudConsoleResourcesQuery.mockImplementation(({ service }: { service: string }) => { + if (service === "storage") return { data: [{ id: "bucket-1" }], isLoading: false, isError: false }; + if (service === "k8s") return { data: [{ id: "cluster-1" }], isLoading: false, isError: false }; + if (service === "database") return { data: [{ id: "db-1" }], isLoading: false, isError: false }; + return { data: [], isLoading: false, isError: false }; + }); + + const { result } = renderHook(() => useCloudConsoleHomeData("aws")); + + expect(result.current.serviceCards.map((service) => service.id)).toContain("dynamodb"); + expect(result.current.serviceCards.find((service) => service.id === "dynamodb")).toMatchObject({ count: 0 }); + expect(result.current.resourceCount).toBe(4); + }); +}); diff --git a/packages/frontend/src/features/cloud-console/useCloudConsoleHomeData.ts b/packages/frontend/src/features/cloud-console/useCloudConsoleHomeData.ts index 9efe11d..b9b037a 100644 --- a/packages/frontend/src/features/cloud-console/useCloudConsoleHomeData.ts +++ b/packages/frontend/src/features/cloud-console/useCloudConsoleHomeData.ts @@ -1,4 +1,3 @@ -import {useMemo} from 'react' import {Cpu, Database, KeyRound, MessageSquare, Table2, Zap} from 'lucide-react' import { useCloudConsoleResourcesQuery, @@ -38,78 +37,79 @@ export function useCloudConsoleHomeData(cloud: CloudProvider) { const k8sResourcesQuery = useCloudConsoleResourcesQuery({...queryContext, service: 'k8s'}) const databaseResourcesQuery = useCloudConsoleResourcesQuery({...queryContext, service: 'database'}) const secretsQuery = useSecretsQuery(cloud === 'aws' && status?.runtime === 'reachable') - const serviceCards = useMemo(() => { - const storage = servicesQuery.data?.find((service) => service.service === 'storage') - const k8s = servicesQuery.data?.find((service) => service.service === 'k8s') - const database = servicesQuery.data?.find((service) => service.service === 'database') - - return [ - { - id: 'storage', - label: storage?.displayName ?? 'Storage', - status: storage?.availability ?? (cloud === 'gcp' ? 'coming_soon' : 'available'), - count: storageResourcesQuery.data?.length, - icon: Database, - route: `/cloud-explorer/${cloud}/storage`, - meta: serviceMetaLabel(status, storageResourcesQuery.isLoading, 'resources'), - }, - { - id: 'k8s', - label: k8s?.displayName ?? 'k8s Engine', - status: k8s?.availability ?? 'coming_soon', - count: k8sResourcesQuery.data?.length, - icon: Cpu, - route: `/cloud-explorer/${cloud}/k8s`, - meta: serviceMetaLabel(status, k8sResourcesQuery.isLoading, 'clusters'), - }, - { - id: 'database', - label: database?.displayName ?? 'Database', - status: database?.availability ?? 'coming_soon', - count: databaseResourcesQuery.data?.length, + const dynamodbResourcesQuery = useCloudConsoleResourcesQuery({...queryContext, service: 'dynamodb'}) + const storage = servicesQuery.data?.find((service) => service.service === 'storage') + const k8s = servicesQuery.data?.find((service) => service.service === 'k8s') + const database = servicesQuery.data?.find((service) => service.service === 'database') + const dynamodb = servicesQuery.data?.find((service) => service.service === 'dynamodb') + const dynamodbCount = dynamodbResourcesQuery.data?.length + const serviceCards: ConsoleServiceCard[] = [ + { + id: 'storage', + label: storage?.displayName ?? 'Storage', + status: storage?.availability ?? (cloud === 'gcp' ? 'coming_soon' : 'available'), + count: storageResourcesQuery.data?.length, + icon: Database, + route: `/cloud-explorer/${cloud}/storage`, + meta: serviceMetaLabel(status, storageResourcesQuery.isLoading, 'resources'), + }, + { + id: 'k8s', + label: k8s?.displayName ?? 'k8s Engine', + status: k8s?.availability ?? 'coming_soon', + count: k8sResourcesQuery.data?.length, + icon: Cpu, + route: `/cloud-explorer/${cloud}/k8s`, + meta: serviceMetaLabel(status, k8sResourcesQuery.isLoading, 'clusters'), + }, + { + id: 'database', + label: database?.displayName ?? 'Database', + status: database?.availability ?? 'coming_soon', + count: databaseResourcesQuery.data?.length, + icon: Table2, + route: `/cloud-explorer/${cloud}/database`, + meta: serviceMetaLabel(status, databaseResourcesQuery.isLoading, 'instances'), + }, + ...(cloud === 'aws' + ? [{ + id: 'dynamodb', + label: dynamodb?.displayName ?? 'DynamoDB', + status: dynamodb?.availability ?? 'coming_soon', + count: dynamodbCount, icon: Table2, - route: `/cloud-explorer/${cloud}/database`, - meta: serviceMetaLabel(status, databaseResourcesQuery.isLoading, 'instances'), - }, - ...(cloud === 'aws' ? [{ + route: `/cloud-explorer/${cloud}/dynamodb`, + meta: serviceMetaLabel(status, dynamodbResourcesQuery.isLoading, 'tables'), + } satisfies ConsoleServiceCard, { id: 'secretsmanager', label: 'Secrets Manager', - status: 'available' as const, + status: 'available', count: secretsQuery.data?.length, icon: KeyRound, route: '/secretsmanager', meta: serviceMetaLabel(status, secretsQuery.isLoading, 'secrets'), - }] : []), - ...SERVICE_PLACEHOLDERS.map((service) => ({ - ...service, - status: 'coming_soon' as const, - count: undefined, - route: undefined, - meta: 'not wired yet', - })), - ] - }, [ - databaseResourcesQuery.data, - databaseResourcesQuery.isLoading, - cloud, - k8sResourcesQuery.data, - k8sResourcesQuery.isLoading, - secretsQuery.data, - secretsQuery.isLoading, - servicesQuery.data, - status, - storageResourcesQuery.data, - storageResourcesQuery.isLoading, - ]) + } satisfies ConsoleServiceCard] + : []), + ...SERVICE_PLACEHOLDERS.map((service) => ({ + ...service, + status: 'coming_soon' as const, + count: undefined, + route: undefined, + meta: 'not wired yet', + })), + ] const resourcesLoading = storageResourcesQuery.isLoading || k8sResourcesQuery.isLoading || databaseResourcesQuery.isLoading || (cloud === 'aws' && secretsQuery.isLoading) + || dynamodbResourcesQuery.isLoading const resourcesError = storageResourcesQuery.isError || k8sResourcesQuery.isError || databaseResourcesQuery.isError + || dynamodbResourcesQuery.isError || (cloud === 'aws' && secretsQuery.isError) + const availableServices = serviceCards.filter((service) => service.status === 'available').length return { cloudsQuery, @@ -118,11 +118,12 @@ export function useCloudConsoleHomeData(cloud: CloudProvider) { runtimeState: runtimeLabelFor(status, statusQuery.isLoading), runtimeClass: runtimeClassFor(status, statusQuery.isLoading), runtimeDetail: status?.error ?? runtimeDetailFor(cloud, status), - activeServices: serviceCards.filter((service) => service.status === 'available').length, + activeServices: availableServices, activeServicesDetail: activeServicesDetailFor(cloud), resourceCount: (storageResourcesQuery.data?.length ?? 0) + (k8sResourcesQuery.data?.length ?? 0) + (databaseResourcesQuery.data?.length ?? 0) + + (dynamodbCount ?? 0) + (cloud === 'aws' ? (secretsQuery.data?.length ?? 0) : 0), resourceDetail: resourceDetailFor(cloud, status, statusQuery.isLoading, resourcesLoading, resourcesError), serviceCards, diff --git a/packages/frontend/src/index.css b/packages/frontend/src/index.css index c23bbe0..b6ca554 100644 --- a/packages/frontend/src/index.css +++ b/packages/frontend/src/index.css @@ -248,6 +248,57 @@ pre, box-shadow: inset 2px 0 var(--accent); } +.nav-group { + display: grid; +} + +.nav-group-trigger { + width: 100%; + border: 0; + background: transparent; + text-align: left; +} + +.nav-group-chevron { + margin-left: auto; + transition: transform 120ms ease; +} + +.nav-group-chevron.open { + transform: rotate(180deg); +} + +.nav-group-children { + display: none; + padding: 4px 0 6px; +} + +.nav-group-children.open { + display: grid; +} + +.nav-sublink { + display: flex; + align-items: center; + gap: 10px; + padding: 7px 16px 7px 39px; + color: var(--text-nav); + text-decoration: none; + font-size: 13px; + transition: background 120ms, color 120ms; +} + +.nav-sublink:hover { + background: var(--hover); + color: var(--text); +} + +.nav-sublink.active { + color: var(--text-bright); + background: var(--active-nav-bg); + box-shadow: inset 2px 0 var(--accent); +} + .nav-soon { margin-left: auto; border: 1px solid var(--border); @@ -2459,7 +2510,7 @@ pre, .console-service-grid { display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; } diff --git a/packages/frontend/src/pages/CloudExplorerPage.test.tsx b/packages/frontend/src/pages/CloudExplorerPage.test.tsx new file mode 100644 index 0000000..ba57dad --- /dev/null +++ b/packages/frontend/src/pages/CloudExplorerPage.test.tsx @@ -0,0 +1,89 @@ +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { render, screen, waitFor } from "@testing-library/react"; +import { MemoryRouter, Route, Routes } from "react-router-dom"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { CloudExplorerPage } from "@/pages/CloudExplorerPage"; + +const listClouds = vi.fn(); +const listCloudServices = vi.fn(); +const getCloudStatus = vi.fn(); +const getServiceSchema = vi.fn(); + +vi.mock("@/api/cloudProxyClient", () => ({ + listClouds: (...args: unknown[]) => listClouds(...args), + listCloudServices: (...args: unknown[]) => listCloudServices(...args), + getCloudStatus: (...args: unknown[]) => getCloudStatus(...args), + getServiceSchema: (...args: unknown[]) => getServiceSchema(...args), +})); + +vi.mock("@/components/DynamicResourceView", () => ({ + DynamicResourceView: ({ cloud, service }: { cloud: string; service: string }) => ( +
{`${cloud}:${service}`}
+ ), +})); + +describe("CloudExplorerPage", () => { + beforeEach(() => { + listClouds.mockResolvedValue([ + { id: "aws", displayName: "AWS", availability: "available" }, + ]); + listCloudServices.mockResolvedValue([ + { cloud: "aws", service: "storage", displayName: "Storage", availability: "available" }, + { cloud: "aws", service: "database", displayName: "Database", availability: "available" }, + { cloud: "aws", service: "dynamodb", displayName: "DynamoDB", availability: "available" }, + ]); + getCloudStatus.mockResolvedValue({ + cloud: "aws", + adapterRegistered: true, + runtime: "reachable", + endpoint: "http://localhost:4566", + checkedAt: "2026-06-10T00:00:00.000Z", + error: null, + }); + getServiceSchema.mockResolvedValue({ + cloud: "aws", + service: "dynamodb", + displayName: "DynamoDB", + fields: [], + actions: ["list", "inspect"], + filters: [], + columns: [], + }); + }); + + it("routes the dedicated DynamoDB explorer path to the shared resource view", async () => { + renderPage("/cloud-explorer/aws/dynamodb"); + + await waitFor(() => { + expect(screen.getByTestId("dynamic-resource-view")).toHaveTextContent("aws:dynamodb"); + }); + + expect(screen.getByText("/api/clouds/aws/services/dynamodb")).toBeInTheDocument(); + }); + + it("keeps the existing database route mapped to the database service", async () => { + renderPage("/cloud-explorer/aws/database"); + + await waitFor(() => { + expect(screen.getByTestId("dynamic-resource-view")).toHaveTextContent("aws:database"); + }); + }); +}); + +function renderPage(initialEntry: string) { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, + }, + }); + + return render( + + + + } /> + + + , + ); +} diff --git a/packages/frontend/src/pages/CloudExplorerPage.tsx b/packages/frontend/src/pages/CloudExplorerPage.tsx index b72ceff..97ee3df 100644 --- a/packages/frontend/src/pages/CloudExplorerPage.tsx +++ b/packages/frontend/src/pages/CloudExplorerPage.tsx @@ -1,4 +1,4 @@ -import {type ElementType, useMemo, useState} from 'react' +import {type ElementType, useState} from 'react' import {Cloud, DatabaseZap, Info, Radio, Route, ShieldCheck, X} from 'lucide-react' import {Navigate, useNavigate, useParams} from 'react-router-dom' import {useQuery} from '@tanstack/react-query' @@ -6,8 +6,8 @@ import {getCloudStatus, getServiceSchema, listClouds, listCloudServices} from '@ import {CloudSelector} from '@/components/CloudSelector' import {DynamicResourceView} from '@/components/DynamicResourceView' import {normalizeCapabilities} from '@/lib/capabilities' -import type {CloudProvider, CloudServiceDescriptor, CloudServiceType, CloudStatus} from '@/types/cloud' import type {ServiceSchema} from '@/types/schema' +import {CLOUD_PROVIDER, CLOUD_SERVICE, type CloudProvider, type CloudServiceDescriptor, type CloudServiceType, type CloudStatus} from '@/types/cloud' export function CloudExplorerPage() { const navigate = useNavigate() @@ -38,10 +38,7 @@ export function CloudExplorerPage() { queryFn: ({signal}) => getServiceSchema(cloud, service, signal), }) - const selectedService = useMemo( - () => servicesQuery.data?.find((item) => item.service === service), - [service, servicesQuery.data], - ) + const selectedService = servicesQuery.data?.find((item) => item.service === service) if (!routeCloud || !routeService) { return @@ -109,11 +106,19 @@ export function CloudExplorerPage() { } function normalizeCloud(value?: string): CloudProvider | null { - return value === 'aws' || value === 'azure' || value === 'gcp' ? value : null + return value === CLOUD_PROVIDER.AWS || value === CLOUD_PROVIDER.AZURE || value === CLOUD_PROVIDER.GCP ? value : null } function normalizeService(value?: string): CloudServiceType | null { - return value === 'storage' || value === 'k8s' || value === 'database' || value === 'compute' || value === 'networking' || value === 'serverless' ? value : null + return value === CLOUD_SERVICE.STORAGE + || value === CLOUD_SERVICE.K8S + || value === CLOUD_SERVICE.DATABASE + || value === CLOUD_SERVICE.DYNAMODB + || value === CLOUD_SERVICE.COMPUTE + || value === CLOUD_SERVICE.NETWORKING + || value === CLOUD_SERVICE.SERVERLESS + ? value + : null } function RuntimeCard({ diff --git a/packages/frontend/src/test/dynamoDbSourceHygiene.test.ts b/packages/frontend/src/test/dynamoDbSourceHygiene.test.ts new file mode 100644 index 0000000..f663c2d --- /dev/null +++ b/packages/frontend/src/test/dynamoDbSourceHygiene.test.ts @@ -0,0 +1,33 @@ +import { readFileSync } from "node:fs"; +import path from "node:path"; +import { describe, expect, it } from "vitest"; + +const repoRoot = path.resolve(import.meta.dirname, "../../../.."); +const dynamoDbServicePath = path.join(repoRoot, "packages/api/src/services/dynamodb.ts"); +const dynamoDbAdapterPath = path.join(repoRoot, "packages/api/src/adapter-aws/AwsDynamoDbAdapter.ts"); + +const FORBIDDEN_MARKERS = ["console.log", "console.debug", "debugger", "TODO", "FIXME"] as const; + +describe("DynamoDB source hygiene", () => { + it("keeps the DynamoDB service free of debug markers and explains why table details are fetched", () => { + const source = readSource(dynamoDbServicePath); + + expect(findForbiddenMarkers(source)).toEqual([]); + expect(source).toContain("ListTables only returns table names, so describe each table to populate the CloudResource metadata used by the explorer."); + }); + + it("keeps the DynamoDB adapter free of debug markers and temporary comments", () => { + const source = readSource(dynamoDbAdapterPath); + + expect(findForbiddenMarkers(source)).toEqual([]); + expect(source).not.toContain("temporary"); + }); +}); + +function readSource(filePath: string): string { + return readFileSync(filePath, "utf8"); +} + +function findForbiddenMarkers(source: string): string[] { + return FORBIDDEN_MARKERS.filter((marker) => source.includes(marker)); +} diff --git a/packages/frontend/src/test/setup.ts b/packages/frontend/src/test/setup.ts new file mode 100644 index 0000000..f149f27 --- /dev/null +++ b/packages/frontend/src/test/setup.ts @@ -0,0 +1 @@ +import "@testing-library/jest-dom/vitest"; diff --git a/packages/frontend/src/types/cloud.ts b/packages/frontend/src/types/cloud.ts index 668a147..4961995 100644 --- a/packages/frontend/src/types/cloud.ts +++ b/packages/frontend/src/types/cloud.ts @@ -1,6 +1,29 @@ -export type CloudProvider = 'aws' | 'azure' | 'gcp' -export type CloudAvailability = 'available' | 'coming_soon' -export type CloudServiceType = 'storage' | 'k8s' | 'database' | 'compute' | 'networking' | 'serverless' +export const CLOUD_PROVIDER = { + AWS: 'aws', + AZURE: 'azure', + GCP: 'gcp', +} as const + +export type CloudProvider = (typeof CLOUD_PROVIDER)[keyof typeof CLOUD_PROVIDER] + +export const CLOUD_AVAILABILITY = { + AVAILABLE: 'available', + COMING_SOON: 'coming_soon', +} as const + +export type CloudAvailability = (typeof CLOUD_AVAILABILITY)[keyof typeof CLOUD_AVAILABILITY] + +export const CLOUD_SERVICE = { + STORAGE: 'storage', + K8S: 'k8s', + DATABASE: 'database', + DYNAMODB: 'dynamodb', + COMPUTE: 'compute', + NETWORKING: 'networking', + SERVERLESS: 'serverless', +} as const + +export type CloudServiceType = (typeof CLOUD_SERVICE)[keyof typeof CLOUD_SERVICE] export interface CloudDescriptor { id: CloudProvider diff --git a/packages/frontend/src/types/cloudResourceTypes.test.ts b/packages/frontend/src/types/cloudResourceTypes.test.ts new file mode 100644 index 0000000..14aebeb --- /dev/null +++ b/packages/frontend/src/types/cloudResourceTypes.test.ts @@ -0,0 +1,15 @@ +import { describe, expect, it } from "vitest"; +import { CLOUD_SERVICE } from "@/types/cloud"; +import { CLOUD_RESOURCE_TYPE } from "@/types/resource"; + +describe("cloud and resource type constants", () => { + it("includes DynamoDB as a supported cloud service", () => { + expect(CLOUD_SERVICE.DYNAMODB).toBe("dynamodb"); + expect(Object.values(CLOUD_SERVICE)).toContain("dynamodb"); + }); + + it("includes DynamoDB tables as a normalized resource type", () => { + expect(CLOUD_RESOURCE_TYPE.DYNAMODB_TABLE).toBe("dynamodb-table"); + expect(Object.values(CLOUD_RESOURCE_TYPE)).toContain("dynamodb-table"); + }); +}); diff --git a/packages/frontend/src/types/resource.ts b/packages/frontend/src/types/resource.ts index e382084..b183ff9 100644 --- a/packages/frontend/src/types/resource.ts +++ b/packages/frontend/src/types/resource.ts @@ -1,11 +1,27 @@ import type {CloudProvider, CloudServiceType} from './cloud' +export const CLOUD_RESOURCE_TYPE = { + BUCKET: 'bucket', + CONTAINER: 'container', + CLUSTER: 'cluster', + DB_INSTANCE: 'db-instance', + COSMOS_DATABASE: 'cosmos-database', + DYNAMODB_TABLE: 'dynamodb-table', + INSTANCE: 'instance', + IMAGE: 'image', + VPC: 'vpc', + LAMBDA: 'lambda', + AZURE_FUNCTION: 'azure-function', +} as const + +export type CloudResourceType = (typeof CLOUD_RESOURCE_TYPE)[keyof typeof CLOUD_RESOURCE_TYPE] + export interface CloudResource { id: string name: string cloud: CloudProvider service: CloudServiceType - type: 'bucket' | 'container' | 'cluster' | 'db-instance' | 'cosmos-database' | 'instance' | 'image' | 'vpc' | 'lambda' + type: CloudResourceType region: string | null createdAt: string | null status?: string | null diff --git a/packages/frontend/tsconfig.json b/packages/frontend/tsconfig.json index 21385a1..065f9af 100644 --- a/packages/frontend/tsconfig.json +++ b/packages/frontend/tsconfig.json @@ -3,7 +3,7 @@ "target": "ES2020", "useDefineForClassFields": true, "lib": ["ES2020", "DOM", "DOM.Iterable"], - "types": ["vite/client", "node"], + "types": ["vite/client", "vitest/globals", "node"], "module": "ESNext", "skipLibCheck": true, "moduleResolution": "bundler", diff --git a/packages/frontend/vite.config.ts b/packages/frontend/vite.config.ts index 486a0b9..87bc9e9 100644 --- a/packages/frontend/vite.config.ts +++ b/packages/frontend/vite.config.ts @@ -6,6 +6,13 @@ const usePolling = process.env.VITE_USE_POLLING === "true"; export default defineConfig({ plugins: [react()], + test: { + environment: "jsdom", + globals: true, + setupFiles: "./src/test/setup.ts", + css: true, + allowOnly: !process.env.CI, + }, resolve: { alias: { "@": path.resolve(__dirname, "./src") }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b34dca..0570e91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,37 +10,40 @@ importers: packages/api: dependencies: + '@aws-sdk/client-dynamodb': + specifier: ^3.1066.0 + version: 3.1066.0 '@aws-sdk/client-ec2': specifier: ^3.1063.0 - version: 3.1068.0 + version: 3.1075.0 '@aws-sdk/client-eks': specifier: ^3.1063.0 - version: 3.1068.0 + version: 3.1075.0 '@aws-sdk/client-lambda': specifier: ^3.1063.0 - version: 3.1068.0 + version: 3.1075.0 '@aws-sdk/client-rds': specifier: ^3.1063.0 - version: 3.1068.0 + version: 3.1075.0 '@aws-sdk/client-s3': specifier: ^3.1063.0 - version: 3.1068.0 + version: 3.1075.0 '@aws-sdk/client-secrets-manager': specifier: ^3.1063.0 - version: 3.1068.0 + version: 3.1075.0 dotenv: specifier: ^17.4.2 version: 17.4.2 hono: specifier: ^4.12.25 - version: 4.12.25 + version: 4.12.27 devDependencies: '@types/bun': specifier: ^1.3.2 version: 1.3.14 '@types/node': specifier: ^25.8.0 - version: 25.9.3 + version: 25.9.4 typescript: specifier: ^5.4.5 version: 5.9.3 @@ -49,10 +52,10 @@ importers: dependencies: '@tanstack/react-query': specifier: ^5.101.0 - version: 5.101.0(react@19.2.7) + version: 5.101.1(react@19.2.7) '@tanstack/react-query-devtools': specifier: ^5.101.0 - version: 5.101.0(@tanstack/react-query@5.101.0(react@19.2.7))(react@19.2.7) + version: 5.101.1(@tanstack/react-query@5.101.1(react@19.2.7))(react@19.2.7) class-variance-authority: specifier: ^0.7.0 version: 0.7.1 @@ -64,7 +67,7 @@ importers: version: 4.4.0 lucide-react: specifier: ^1.16.0 - version: 1.18.0(react@19.2.7) + version: 1.21.0(react@19.2.7) react: specifier: ^19.2.6 version: 19.2.7 @@ -73,7 +76,7 @@ importers: version: 19.2.7(react@19.2.7) react-router-dom: specifier: ^7.15.1 - version: 7.17.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) tailwind-merge: specifier: ^2.3.0 version: 2.6.1 @@ -84,9 +87,18 @@ importers: '@eslint/js': specifier: ^10.0.1 version: 10.0.1(eslint@10.5.0(jiti@1.21.7)) + '@testing-library/jest-dom': + specifier: ^6.9.1 + version: 6.9.1 + '@testing-library/react': + specifier: ^16.3.2 + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@testing-library/user-event': + specifier: ^14.6.1 + version: 14.6.1(@testing-library/dom@10.4.1) '@types/node': specifier: ^25.8.0 - version: 25.9.3 + version: 25.9.4 '@types/react': specifier: ^19.2.14 version: 19.2.17 @@ -95,7 +107,7 @@ importers: version: 19.2.3(@types/react@19.2.17) '@vitejs/plugin-react': specifier: ^5.0.0 - version: 5.2.0(vite@8.0.16(@types/node@25.9.3)(jiti@1.21.7)) + version: 5.2.0(vite@8.1.0(@types/node@25.9.4)(jiti@1.21.7)) autoprefixer: specifier: ^10.4.19 version: 10.5.0(postcss@8.5.15) @@ -111,6 +123,9 @@ importers: globals: specifier: ^16.0.0 version: 16.5.0 + jsdom: + specifier: ^29.1.1 + version: 29.1.1 postcss: specifier: ^8.5.15 version: 8.5.15 @@ -122,17 +137,38 @@ importers: version: 5.9.3 typescript-eslint: specifier: ^8.60.1 - version: 8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) + version: 8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) vite: specifier: ^8.0.13 - version: 8.0.16(@types/node@25.9.3)(jiti@1.21.7) + version: 8.1.0(@types/node@25.9.4)(jiti@1.21.7) + vitest: + specifier: ^1.6.1 + version: 1.6.1(@types/node@25.9.4)(jsdom@29.1.1)(lightningcss@1.32.0) packages: + '@adobe/css-tools@4.5.0': + resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==} + '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} + '@asamuzakjp/css-color@5.1.11': + resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/dom-selector@7.1.1': + resolution: {integrity: sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/generational-cache@1.0.1': + resolution: {integrity: sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@aws-crypto/crc32@5.2.0': resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} engines: {node: '>=16.0.0'} @@ -156,102 +192,174 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/checksums@3.1000.5': - resolution: {integrity: sha512-zOXUUnilC6lgCsQtp77p/QNPmRlTES9Xi6tlDwbR6kfC/kz5PCzZckgHWm5z+8DskdwuMAbFDq61x3zr10GEEQ==} + '@aws-sdk/checksums@3.1000.8': + resolution: {integrity: sha512-v0U9S7gBIme3OTgt1LdbAF4RpvavCc+4GK1+1xqAcqtbrHsEhjQo6R45LKcjhs/+WrRJij1Y0Gztw7QPAIeUfA==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-ec2@3.1068.0': - resolution: {integrity: sha512-5wQACr4zx16ajWl0/iHn8eyWT/PEONKp5MuyRHdff9EY6t6PDaxDKOInWY0ET12RLJQiL3riRFDDrGDhikP9FA==} + '@aws-sdk/client-dynamodb@3.1066.0': + resolution: {integrity: sha512-b1EtaQ4YtJh9PZ3NQSk8EkGpsrAZ2bDNeJp8VQ/TNeQdODbscT99qhq7bbq27ZkBva/jl8ma9ouwGWxwtsqeXQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-eks@3.1068.0': - resolution: {integrity: sha512-3+6Wpqav1AOJ5Lw8DfqkFfrbgeNSm1Kv0YfvGSALbe0ZvEI9deg7rWKlLQimx72PDxuH8sn+lSSOSfK7/YDsAg==} + '@aws-sdk/client-ec2@3.1075.0': + resolution: {integrity: sha512-mrj3G83NkalaYNK6T2vDnoQAfHBY7drzoaDfuTmQeXAfSs9+ucddfJLLV95HT3fdYMfJEKf4Xul2dgyb2t3UuA==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-lambda@3.1068.0': - resolution: {integrity: sha512-GitXCytcrvezkAQbyT+cYMrGPCM9zdh9sU8FrQr1vyniVijXk2X4ZBf2WZwDQcenNPMJyN5YdtUAbmUJCrfZDg==} + '@aws-sdk/client-eks@3.1075.0': + resolution: {integrity: sha512-TA+EvfMpEA2PjBIJ4kDcHPKvrpyLEX5ewi8/1qe4cBxLQNJ2gxn4JnYiQ1k1ASVJricNkiM6DVtnVVZv8q4kZA==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-rds@3.1068.0': - resolution: {integrity: sha512-bmX3pZQK333SNVnAH/QyEedETbMPH7KByfgbDGa5tpDAKCl95oUUiOP6mOocNVMApnTSQHHKeO5mzajxLR4TKg==} + '@aws-sdk/client-lambda@3.1075.0': + resolution: {integrity: sha512-S+sy0L7WEouGGys0kJZJ+br0sQGxgWC+0nR/4ySsym/CSg/k+VHXBdD697WJLli+X5a76tFBshx5bjgVKgLg4Q==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-s3@3.1068.0': - resolution: {integrity: sha512-lFgaIpxZvloNbJvQ337YPdMXhzI2zJdDw13nATVGnkAGNoNPx4ksD84AQAcuW75hsaaMaIuNmXU9sSx6+FTirA==} + '@aws-sdk/client-rds@3.1075.0': + resolution: {integrity: sha512-Ed8NlyH9aakJpQhSutVDd0pZX1lTdLuXj08tEMu+OapTGQxF2pNTsfLdN9n9p1PobImlqwhOcBYOHkNKvdIfzw==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-secrets-manager@3.1068.0': - resolution: {integrity: sha512-5FPwDBwKnUsCwjFX8nnuI++1Aez+cuHHWviwLhBME2p1qdfqYknHzfnvV+LHKeJWJk/chqARAHgfYVxcLj8nvA==} + '@aws-sdk/client-s3@3.1075.0': + resolution: {integrity: sha512-h1A6nIl1YX6Y45enGsTK7ef3ZrOnBiQJ1qF5R2K/nMWfsu6A9mc2Y5T66nxerABzyjjyyvign3MrzafnFoQKmA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-secrets-manager@3.1075.0': + resolution: {integrity: sha512-5cLjSmrgzohO2q4gMrb7oHq58W+gR/qul7yHSRZ1fZv7aYtONvq23dKr+E7i0KBid4zkjGpjw8VJ7fNdQi9YUQ==} engines: {node: '>=20.0.0'} '@aws-sdk/core@3.974.20': resolution: {integrity: sha512-7sDi2B2N3mc3nf1nz6FyEx/FCrJ1N1QnBmraHHQNabFaeAh2IaOOLml48/rHOD1bICHgTRkbBgNTvUzEr5Z35g==} engines: {node: '>=20.0.0'} + '@aws-sdk/core@3.974.23': + resolution: {integrity: sha512-MiWR/uWjxjFXGzrE0Ghc5lWxUxzHsUWFhV+OX7M4cR9SrmrnZs6TXavnCWnzzdwJeFri34xQo81rvGNzK3c4BQ==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-env@3.972.46': resolution: {integrity: sha512-+GPXVS2srMOlH74S+SmC1gVuP2TvUZ0siuC0onKO93q+udP+M72dmY8wJfVQ5CX9z/9X5A1HHwz5yRIGBtskvQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-env@3.972.49': + resolution: {integrity: sha512-liB3yQNHCM9k/gu/w36XHMKPluT7HTlnGUhRbBGSISDQkcr/Sy1zsZabiuvQj8WG5yW573u9RehrBvvnIQ9OEQ==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-http@3.972.48': resolution: {integrity: sha512-fA5loSdlocacRxyUXtpoHSMuk5rsIKRDzQYVMnMxjcmFeZshaJlJ8lymy/hYKji6sne/UmNGj5pxuEs6kq/Qcg==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-http@3.972.51': + resolution: {integrity: sha512-XET0H2oofciJ5lMRWNIvRjAP7Q3wv2XT+JtJJEdhPWUMwe3TvQ9qcxonpu7vXmNngncvFpi4E2It+Tamas/naA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-ini@3.972.53': resolution: {integrity: sha512-ZfdhIOR41q8TcWEnUac+gCOb+O2LBWdHLmjedXpXz4IEFW2ppNuFcm6p0sMTavpM+zD5TYfpH5Gp7guRyqSgsQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-ini@3.972.56': + resolution: {integrity: sha512-IAmc61hbgQiHht9U3x0tnRwz0lzdwOwD/i9voRgdJrKamF+JtmrBOsW9GwB7mfFonNWOWL4qARWYrF8veEMe3w==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-login@3.972.52': resolution: {integrity: sha512-9hu2oR0qH7Fst5Tzdx+UWxm+w5zCXtErTLtOOW5hwwQc170CLwOeniRxyFY6s9mHfGEfC5zFukNBdKBwJR8mhQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-login@3.972.55': + resolution: {integrity: sha512-hBBkANo3cDn+h2qxxzER4a+J8JCO9o9Z/YYmU7iky6AcaarX5RRdRcHNC6SLdwY0vAXQygn6soUbDqPn3GghaA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-node@3.972.55': resolution: {integrity: sha512-zMGLa/dhESVqmCD7mmIFFKSwSFrJGScvCXcjvBZEVOOMauFS5JRQvLTMukFpMEFWiV6dTAlsen2ATDBulLPtbg==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-node@3.972.58': + resolution: {integrity: sha512-OyCLVmSI7pZO8hxwNVX6pXhTVlJqRBTp+ijdEfJSUj0RyjHnF602OfAarOzGq6wkGodeFkYBt8MmJ6A6ycRgWw==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-process@3.972.46': resolution: {integrity: sha512-VUoNFBIjWrUN8NbFiQiuxQEgFjvziAlBRPK+ddh27aj65gk0BYu6bLZnrdrNZwpW6vAihtSUtEMQ1PUJ32QRPA==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-process@3.972.49': + resolution: {integrity: sha512-C8h36lBuC/RnBSsjlO+dn6xZm3KbAl5vpJaVPAfQnMmz2/OISmKOc8XZcqMQgO2ADwBYNRMM6Kf3vz9G/TulMQ==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-sso@3.972.52': resolution: {integrity: sha512-nb2/n4o/HQf+FVpVbZe9vCTFngmuDoIsltMgLAtjixaKzvzhB4J8WSDFyWgnErgLHk55ctWH+I4PU+LIHhyffg==} engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-sso@3.972.55': + resolution: {integrity: sha512-1FkOz74Ea5QGS9jtIoXp55T/IkSS3spv+nLTT07fRY/+T5xmEOqaYBVIaEmX4zTNvbV6g2lrtlaVKWEoNyJt3w==} + engines: {node: '>=20.0.0'} + '@aws-sdk/credential-provider-web-identity@3.972.52': resolution: {integrity: sha512-lKj6aRSGbqLmpYmM24bY7a1Xmfcq2vkE3hv8CSPYfc1yCu0BPu/XEJ1L4Fm61MsU6ULLNSG8UGsffNoFUBjESA==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.974.30': - resolution: {integrity: sha512-OaIhub+3yTgfFWPzKO8OzOZFIMUoJaiS5v67y3spQg7SoULGoMx4jKVBbE+uhnzkiZXQ+rEDS0RqrK4/aD1yJw==} + '@aws-sdk/credential-provider-web-identity@3.972.55': + resolution: {integrity: sha512-g2BoECD1q01kTPByi56+VLVvdWDzMkKIcr77qixpqH0okw2t0U5CoPv+6S8v/D1Y2Wa6QKKtn6XAtDzP+Kfpvg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/dynamodb-codec@3.973.20': + resolution: {integrity: sha512-SFfxiqVgWeIe+RsJJNAMD//2IfehT4bLpGyNJRB0MgHmOIJtdcfMnR1k7KYyaHokSoQVdncVa9O9DIGa4eqcwg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/endpoint-cache@3.972.7': + resolution: {integrity: sha512-LkwS3ZOUNL5kHzmz3dDx8lE3HOhZmf2VGjbJ/tMUZJYWWl3J0RJTZM7RFz1MLt06WDVvlShcAjY/RzhYlqLL7g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-endpoint-discovery@3.972.18': + resolution: {integrity: sha512-1vKJt/6MBB/MBMRM3qzCMdW70syJY8u2DH+dq7yCnPn7wVJmyeAzAa/sK1lIbbYh8BVLbM5FspsT4zbe885gOw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-flexible-checksums@3.974.33': + resolution: {integrity: sha512-qMgQSPemQq2/eW/e/0+SpY4kYR5L7dUgBiVdEc5bd+ztHNv07ZMYiI+sTiir3TgKndFfglSw/VFi7oZJ6bZ63g==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-ec2@3.972.34': - resolution: {integrity: sha512-xOxVjHBm04meFPYBBNN3X1eMP1epESN5E1t+JCWCbkQMTkijOnrbR3/ZOdWxRCPoCba5NG6mXaZ9Kg5oy5CywQ==} + '@aws-sdk/middleware-sdk-ec2@3.972.37': + resolution: {integrity: sha512-Z8ogjHT2C7YnMb83PhsAKmuySs+UMC6SBKXbtJT5y0mV5vvqm9UmMAiAEP+06hBFt7ta/nYHJvFBP3wjO3+YBQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-rds@3.972.34': - resolution: {integrity: sha512-+UFkYLaGqN/VvWPKV0N2QKq4UZZlWzrMcuyZFPCYqanaPnonnHNg3n7vFkGNvU0DXe4oynaW0+MLZW/HMjCshA==} + '@aws-sdk/middleware-sdk-rds@3.972.37': + resolution: {integrity: sha512-VuUIRnbkchafWIKb0nqvX+RlKYc8cq0a6tE/mtdF1J4cf44/R/wsKZgq5BHsHeLSuLjCoj5BHtSbLe+CF5OhOg==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-s3@3.972.51': - resolution: {integrity: sha512-keQgcIUTcHL0Qn7guhsuLaxQU36r9norCrxgaPH4DNCwon4TPtXdI/UdYuycl9vj3Dlwc3YR1dfL3U+6iIwJ6w==} + '@aws-sdk/middleware-sdk-s3@3.972.54': + resolution: {integrity: sha512-GDfDQ0gwLFRKN9gWIKcmVrHJ3e7XagnY7N1LLzMVNgnOnuY7f/ALgmy3CuBjosWD95T/Z6e+gs1IeWmLPkyLKQ==} engines: {node: '>=20.0.0'} '@aws-sdk/nested-clients@3.997.20': resolution: {integrity: sha512-IYJuLpXp2DEILVQpQOy0PMpkftv0AHEOCn52o0atyOaumA0CdWQ3klPyXdViGYLbNpESsVFMVybvHUeZAuiGxA==} engines: {node: '>=20.0.0'} + '@aws-sdk/nested-clients@3.997.23': + resolution: {integrity: sha512-gO93ZPsI2bxeFZD42f1/qjDw6FAZkNZcKRO94LIiT03fzOmcJ9e/tunxjVjA1Rl69ClmVJzz8H3G9CdKef10PA==} + engines: {node: '>=20.0.0'} + '@aws-sdk/signature-v4-multi-region@3.996.34': resolution: {integrity: sha512-mx1L5qlumSOt/nKM3BFaHE2HVkWwz0i4Bw0pyYO42FfX/FeLlo8YI6csC0gSPprEk6fTIqI+CZN9RwUwKd5krQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/signature-v4-multi-region@3.996.35': + resolution: {integrity: sha512-6L/VWs+Wch2stHemCGTmUNqKLMzURxQDK5boNG3Jn3kAOp71meDUuS5sbObpEvFxHDq0uWeSLFDNSYsjNt+Dlg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/token-providers@3.1066.0': resolution: {integrity: sha512-UqEUJq7dqa44hneLDUcX7UJy95cg8YqEWyakRpvIPnrNS3Mq+UlQHgCDGu5pvwAPtlIW4qcYbvW6reG6++FyvA==} engines: {node: '>=20.0.0'} + '@aws-sdk/token-providers@3.1074.0': + resolution: {integrity: sha512-pv80IzgGW4RnXWtft692chZOM9i6PhebVsLCcnaM4dBEPZva2fE6FXAHs76G7Rc7s3yGyX/68G0nZMrUy+Vmpg==} + engines: {node: '>=20.0.0'} + '@aws-sdk/types@3.973.12': resolution: {integrity: sha512-43ajd1NF0RMgX5k0hxCNUyEdrtFUsb2aHT2QvpktSC/2Eyb2Jr/JPVqdp0XIoaHWikZJq5tNWSLO6kB5q2eMCA==} engines: {node: '>=20.0.0'} + '@aws-sdk/types@3.973.13': + resolution: {integrity: sha512-pEHZqRkAlHfnfAU9tK+WpKv/gBNjGJrHMgA3A0iYRGyswBS2t0pfez+lWlwktb3Bqa0ovh7w/QJTFwp3fDxLNg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.973.8': + resolution: {integrity: sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==} + engines: {node: '>=20.0.0'} + '@aws-sdk/util-locate-window@3.965.5': resolution: {integrity: sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==} engines: {node: '>=20.0.0'} @@ -260,6 +368,10 @@ packages: resolution: {integrity: sha512-fk0niuGFxfi8yIJuMVM4mhwObkiQSuwZFj3tAPrLVx64Pk3BkrEIpqjzHKY4hKoEBUD6Jg/S74Zj9jy+5F3DnQ==} engines: {node: '>=20.0.0'} + '@aws-sdk/xml-builder@3.972.31': + resolution: {integrity: sha512-SzE4Pgyl+hDF+BuyuzxUSpwnuUu9lJuO1YGgteG89/4Qv0+2IQiVQqdbPV32IozLvXWQChPQcdkk/sKvb1QHiQ==} + engines: {node: '>=20.0.0'} + '@aws/lambda-invoke-store@0.2.4': resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==} engines: {node: '>=18.0.0'} @@ -335,6 +447,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + '@babel/template@7.28.6': resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} @@ -347,14 +463,192 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@emnapi/core@1.10.0': - resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + '@bramus/specificity@2.4.2': + resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} + hasBin: true + + '@csstools/color-helpers@6.0.2': + resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==} + engines: {node: '>=20.19.0'} + + '@csstools/css-calc@3.2.1': + resolution: {integrity: sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-color-parser@4.1.3': + resolution: {integrity: sha512-DOgvIPkikIOixQRlD4YF31VN6fLLUTdrzhfRbis8vm0kMTgIbEPX0Ip/YX9fOeV9iywAS4sUUbTclpan7yYP8Q==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-parser-algorithms@4.0.0': + resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.5': + resolution: {integrity: sha512-oNjBvzLq2GPZtJphCjLqXow/cHySHSgtxvKZb7OqSZ/xHgw6NWNhfad+6AB9cLeVm6eA9d/qMll3JdEHjy6M+A==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + + '@csstools/css-tokenizer@4.0.0': + resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + engines: {node: '>=20.19.0'} + + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] - '@emnapi/runtime@1.10.0': - resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] - '@emnapi/wasi-threads@1.2.1': - resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} @@ -395,6 +689,15 @@ packages: resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@exodus/bytes@1.15.1': + resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true + '@humanfs/core@0.19.2': resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} engines: {node: '>=18.18.0'} @@ -415,6 +718,10 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -431,8 +738,8 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@napi-rs/wasm-runtime@1.1.5': - resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} peerDependencies: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 @@ -452,94 +759,94 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@oxc-project/types@0.133.0': - resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + '@oxc-project/types@0.137.0': + resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==} - '@rolldown/binding-android-arm64@1.0.3': - resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} + '@rolldown/binding-android-arm64@1.1.3': + resolution: {integrity: sha512-DT6Z3PhvioeHMvxo+xHc3KtqggrI7CCTXCmC2h/5zUlp5jVitv7XEy+9q5/7v8IolhlioawpMo8Kg0EEBy7J0g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.3': - resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==} + '@rolldown/binding-darwin-arm64@1.1.3': + resolution: {integrity: sha512-0NwgwsjM7LrsuVnXMK3koTpagBNOhloc/BNjKqZjv4V5zI5r13qx69uVhRx+o5Z0yy4Hzq+lpy7TAgUG/ocvrw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.3': - resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==} + '@rolldown/binding-darwin-x64@1.1.3': + resolution: {integrity: sha512-YtiBp4disu6V560loT6PjMdiRaWmVvDNrUunAalbiFx2ggeJwxdAsgZMcoGP17uyAsTwAj5V1niksxlHnVQ1Sw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.3': - resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==} + '@rolldown/binding-freebsd-x64@1.1.3': + resolution: {integrity: sha512-yD3EkEdXk2LypPxnf/kSZHirarsI8gcPzc62SukhR9VJTyvV+F9Q/GxWNuCojc7sXyuVC4DxRGhdDK4X8VSsbw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.3': - resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==} + '@rolldown/binding-linux-arm-gnueabihf@1.1.3': + resolution: {integrity: sha512-c+8vieQbsD7HNAHKIA34w0GJ9FedFFuJGD+7E6vz7Q3uqAIugL5p45fhlsj4UaAsHpcmlqugBWMhA0/j7o0sIg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.3': - resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==} + '@rolldown/binding-linux-arm64-gnu@1.1.3': + resolution: {integrity: sha512-50jD0uUwLvur7Zz9LHz17kaAdTPjn5wN93hEgjvmYFRZwiR7ZJYovTd5ipyWJDAnXKvZ+wgc+/Ika6dwSF5OcA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@rolldown/binding-linux-arm64-musl@1.0.3': - resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} + '@rolldown/binding-linux-arm64-musl@1.1.3': + resolution: {integrity: sha512-BO9+oPL8K9poZJBfYPsXNtYjPE5uM3qeehT3aFcW4LITOl+iSqhp0abzjR2nWBUNjIZeKXjAEWBZ64WjNoHd6w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@rolldown/binding-linux-ppc64-gnu@1.0.3': - resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} + '@rolldown/binding-linux-ppc64-gnu@1.1.3': + resolution: {integrity: sha512-f3VpLB1vQ0Eo6ecr/6cekLnvYMFF4YBFoVGkfkvPLq1bAkbAwHYQPZKoAmG6OJyTcxxoC+AvezGx/S1obNC0Mw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - '@rolldown/binding-linux-s390x-gnu@1.0.3': - resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} + '@rolldown/binding-linux-s390x-gnu@1.1.3': + resolution: {integrity: sha512-AmurZ26Pqx/RI9N1gzEOCklkKXl927yjfXWUUS0O7Puh8ARM/Ob8qfrD3qnWksScdw6cSrW5PSHE9DyLu7+PtA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - '@rolldown/binding-linux-x64-gnu@1.0.3': - resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} + '@rolldown/binding-linux-x64-gnu@1.1.3': + resolution: {integrity: sha512-JJpqs8bRGITDOdbkNKnlojzBabbOHrqjSvDr0IVsZObE1lBcPjxItUEY9eWIDbxaJ3cGrXPWGfGkIxFijg/URg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@rolldown/binding-linux-x64-musl@1.0.3': - resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} + '@rolldown/binding-linux-x64-musl@1.1.3': + resolution: {integrity: sha512-rSJcdjPxzA/by/6/rYs+v+bXU7UjvnbUWz8MJb6kh6+knqB1dCrtHg0uu7C/4haqJvqdkYHQ5IGn+tCH9GLW/g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@rolldown/binding-openharmony-arm64@1.0.3': - resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} + '@rolldown/binding-openharmony-arm64@1.1.3': + resolution: {integrity: sha512-hQ3/PYkDJICgevvyNcVrihVeqq7k1Pp3VZ9lY+dauAYUJKO+auqApvANhvR1An9BhmqYKvW2Mu1F9u4DXSMLxQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.3': - resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==} + '@rolldown/binding-wasm32-wasi@1.1.3': + resolution: {integrity: sha512-Elcv/BtML9lXrV6JuKITc/grN2kYV9gjsQpW8Jfw4ioK0TOkjBjye0nnyqQNy9STNaI20lXNaQBRrD5gSgR0Yg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.3': - resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==} + '@rolldown/binding-win32-arm64-msvc@1.1.3': + resolution: {integrity: sha512-2DrEfhluH9yhiaFApmsjsjwrSYbNcY1oFTzYSP1a535jDbV98zCFanA/96TBUd0iDFcxGmw9QRExwGCXz3U+/g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.3': - resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==} + '@rolldown/binding-win32-x64-msvc@1.1.3': + resolution: {integrity: sha512-OL4OMk7UPXOeVGGd3qo5zJyPIljf4AFgk5QAkPPS+OoLuOOozhuaQGC18MxVTnw/06q93gShAJzlwnSCY9YtqA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -550,32 +857,160 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@smithy/core@3.24.7': - resolution: {integrity: sha512-KoUi4M1f3BG6kzN1FnCwL7oyFptTbyBJKjR6yhSib+JHRdUmM1o+VwsFtJ66NZCkCzVfJMWRHJNo0R0jznp0Pg==} + '@rollup/rollup-android-arm-eabi@4.60.4': + resolution: {integrity: sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.60.4': + resolution: {integrity: sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.60.4': + resolution: {integrity: sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.60.4': + resolution: {integrity: sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.60.4': + resolution: {integrity: sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.60.4': + resolution: {integrity: sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.60.4': + resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.60.4': + resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.60.4': + resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.60.4': + resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.60.4': + resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.60.4': + resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.60.4': + resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.60.4': + resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.60.4': + resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.60.4': + resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.60.4': + resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.60.4': + resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.60.4': + resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.60.4': + resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.60.4': + resolution: {integrity: sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.60.4': + resolution: {integrity: sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.60.4': + resolution: {integrity: sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.60.4': + resolution: {integrity: sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.60.4': + resolution: {integrity: sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==} + cpu: [x64] + os: [win32] + + '@sinclair/typebox@0.27.10': + resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} + + '@smithy/core@3.24.6': + resolution: {integrity: sha512-wBXDRup6UU97VKyaiRo8AssnfStPtG0oAAfpq/bC0a1YYau8pM86YB4kM6ccoVi1mS8l/UHbn9oDM+7uozr/ug==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.3.9': - resolution: {integrity: sha512-ZlfJ/4Fa3jYb+3eaohPfG9utX9HmdhFNcFtpoGAhUhdynAOmGXtmigbi7eEiONKM+ykHw8RwKuDEb85Lx7t7fA==} + '@smithy/credential-provider-imds@4.3.8': + resolution: {integrity: sha512-5cAM+KZC02sTqDt6NaLXyu50M/GNMd1eTzDVR8Lb0BBsVtu7RWHo47VPPEEv1vt3Yub6uzr+M5FHC+GtoT0USg==} engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.4.7': - resolution: {integrity: sha512-NslaM2ir0N2hisDmzXLstPaVINZheh8SokyOC++kzFPloZucL2R7Y7bS57mSzx/1Fc/fqmn7twjkeezTTrV0EA==} + '@smithy/fetch-http-handler@5.4.6': + resolution: {integrity: sha512-FEwEYJ1jlBKdhe9TPzfghEi1bP55ZeEImlDkEa62bBBYzUcnB6RUCyuiS2mqKt6ZVjUbBgcNhzfIctH+Hevx9g==} engines: {node: '>=18.0.0'} '@smithy/is-array-buffer@2.2.0': resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} engines: {node: '>=14.0.0'} - '@smithy/node-http-handler@4.7.8': - resolution: {integrity: sha512-f+DbsWUwSbtMu1a/j8Y93KiU1SRg9nyzfjereqn1BJ33QOTUXxdlYvVXMhAYl1vuR1Kmna5aIJe09KSIfyFNYw==} + '@smithy/node-http-handler@4.7.7': + resolution: {integrity: sha512-ZAFvHXrEk6K180EVhmZVg8GU5pUH5BSFqRs27JW3j1qEFx9YyYwWFx17x/MHcjALYimGAji7qEOlF1++be+G5A==} engines: {node: '>=18.0.0'} - '@smithy/signature-v4@5.4.7': - resolution: {integrity: sha512-LwQZazFayImv+IOm0S0enoLeUJwmAlhGC5O6YCcLWezyu08dF46GOxPOq35OpBIHkgd7OvNvBStIFwVNyrvoBw==} + '@smithy/signature-v4@5.4.6': + resolution: {integrity: sha512-Ojg4B6oIDlIr1R86xCDJt1zJWnYa0VINmqdjfe9qxWjdRivHalZ3iSlQgVqYbW0MdpFOC5XfHEWsnbmdnpIILQ==} engines: {node: '>=18.0.0'} - '@smithy/types@4.14.4': - resolution: {integrity: sha512-B2S9+UGm1+/pHkcx3ZoLVX1a+pmSk8rqxRR+ZsNqZaJ5q9FWX9AFGQVM4qG5+OBeQUZVy99HY8HqW8gK/wgXzQ==} + '@smithy/types@4.14.3': + resolution: {integrity: sha512-YupL0ZWmFtJexUN2cHzkvvF/b9pKrtAIfT1o7/oY/Ppu8IYeZ+lDPM5vZdQJaSeA132dJCqojjGC9NhXeF71VQ==} engines: {node: '>=18.0.0'} '@smithy/util-buffer-from@2.2.0': @@ -586,25 +1021,57 @@ packages: resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} engines: {node: '>=14.0.0'} - '@tanstack/query-core@5.101.0': - resolution: {integrity: sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow==} + '@tanstack/query-core@5.101.1': + resolution: {integrity: sha512-Y6Y92dkXtNqx67m2pMSxUsA3zOCwv862JexZRP8/EPwvKXMPu9m8rv43spiXWzOUIggQ3SQApttALStzhA8B4g==} - '@tanstack/query-devtools@5.101.0': - resolution: {integrity: sha512-MVqw17k08RQtGGLEL654+dX/btbX9p/8WjkznO//zusLTMaObxi3Q+MoFwGVkC9K3tqjn8qrrNhJevXx4fJTeQ==} + '@tanstack/query-devtools@5.101.1': + resolution: {integrity: sha512-37RQ9U2PxlXQiv1era2t+uHgVhmiyvxqTMu30+KoVf0rufiucu6rpGRKFJk61Wh5OAZFKqCQd6lxTzFWfLZiuQ==} - '@tanstack/react-query-devtools@5.101.0': - resolution: {integrity: sha512-cpZA0+WqKXwrwMfiWZEGGF6QrIWVQFbhBtxqDF5sQsAfrFf47HIE6fiPbQU3wyAUEN2+7UNqLCQe7oG6m3f93w==} + '@tanstack/react-query-devtools@5.101.1': + resolution: {integrity: sha512-OXFR9XKdEslraq3cpl3kCUeNvTIq/xGWEZiFZdn2bLB/q4WxSALMEDKYZ5yYjMQytsfnQxwQYqV4qtVEf0nuog==} peerDependencies: - '@tanstack/react-query': ^5.101.0 + '@tanstack/react-query': ^5.101.1 react: ^18 || ^19 - '@tanstack/react-query@5.101.0': - resolution: {integrity: sha512-rLlJXSpkqfizLWgkR5+eLeIk0MvTx/meEIR7LRjxic+qxiQP8zVjq7BqQkiCMNLQBlLfuOLqqr6KO5GtrDlmSg==} + '@tanstack/react-query@5.101.1': + resolution: {integrity: sha512-ZnONUuQKJe1bJMStXUL1s5uKN9FcfC28j5cK+iDZcdSHtUv1wtin1cGc/Oewhf2Oc4eKY7lggtpvT/AbMmhHew==} peerDependencies: react: ^18 || ^19 - '@tybys/wasm-util@0.10.2': - resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/react@16.3.2': + resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@testing-library/user-event@14.6.1': + resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -630,8 +1097,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@25.9.3': - resolution: {integrity: sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==} + '@types/node@25.9.4': + resolution: {integrity: sha512-dszCsrKb5U7ZsVZBWiHFklTloVl0mSEnWH/iZXfZUlI4rzCUnsvGmgqfuVRHL54ugE7/wRuxEIXRa2iMZ+BG6g==} '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} @@ -641,63 +1108,63 @@ packages: '@types/react@19.2.17': resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} - '@typescript-eslint/eslint-plugin@8.61.0': - resolution: {integrity: sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==} + '@typescript-eslint/eslint-plugin@8.62.0': + resolution: {integrity: sha512-o+mpz7EYiMzXoySXiKmzlabIvTVqUuK5yLrAedRPRDA0IpPFMUV1IXt6OqljIxX/kumN6EjUYp41Hqelh6p/Dw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.61.0 + '@typescript-eslint/parser': ^8.62.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.61.0': - resolution: {integrity: sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==} + '@typescript-eslint/parser@8.62.0': + resolution: {integrity: sha512-dzHeT2gySzZtLDsuqxU9AkYgIsQoHAHtRBpOqM+Ofzx1Bwrd2RcCjQJ+6iQbsHOIR6NS33bF2W1k3blN1zLDrA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.61.0': - resolution: {integrity: sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==} + '@typescript-eslint/project-service@8.62.0': + resolution: {integrity: sha512-wexnCqiTg7BOGtbLDftYpRWlmLq4xfoMd7BKFR6Y75sZS3QmRKLdN3yWLhmIYgqMmP/OXWpj3H8odkb5nGURCQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.61.0': - resolution: {integrity: sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==} + '@typescript-eslint/scope-manager@8.62.0': + resolution: {integrity: sha512-1lX38kNxXIRb8mEc3lbq5mdHq1Pf2+U0nFU65KfT18mtPxxl0fvjuEE92mHuXPuCtElJhOrddOpyMlM3Z0umEA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.61.0': - resolution: {integrity: sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==} + '@typescript-eslint/tsconfig-utils@8.62.0': + resolution: {integrity: sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.61.0': - resolution: {integrity: sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==} + '@typescript-eslint/type-utils@8.62.0': + resolution: {integrity: sha512-+g5O3j0w2ldzC86Pv6fvbO/xhAonbJFIdf/MKQ1d30gndlsVzUOE83ldfSE15Qrl9fhFjK6AovHs5Wpp6vx86w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.61.0': - resolution: {integrity: sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==} + '@typescript-eslint/types@8.62.0': + resolution: {integrity: sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.61.0': - resolution: {integrity: sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==} + '@typescript-eslint/typescript-estree@8.62.0': + resolution: {integrity: sha512-+hVbNxtW64pIcZWDPGbyaKF7vp2IBTVY5ma1blwwksrjdsbdqqEKvJWMGbBofei4F6Dovx1M0RJgoFeNu2279A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.61.0': - resolution: {integrity: sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==} + '@typescript-eslint/utils@8.62.0': + resolution: {integrity: sha512-82r66fi9zYwZ+mTq3vKgwjbZ1PVk/DJzrXFLpG6RnBbdvH8TEGVHIs9H4d2drhkOzf0syZuD/OZvvlu6GDbP4g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.61.0': - resolution: {integrity: sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==} + '@typescript-eslint/visitor-keys@8.62.0': + resolution: {integrity: sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vitejs/plugin-react@5.2.0': @@ -706,11 +1173,30 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + '@vitest/expect@1.6.1': + resolution: {integrity: sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==} + + '@vitest/runner@1.6.1': + resolution: {integrity: sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==} + + '@vitest/snapshot@1.6.1': + resolution: {integrity: sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==} + + '@vitest/spy@1.6.1': + resolution: {integrity: sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==} + + '@vitest/utils@1.6.1': + resolution: {integrity: sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} + engines: {node: '>=0.4.0'} + acorn@8.16.0: resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} engines: {node: '>=0.4.0'} @@ -719,6 +1205,14 @@ packages: ajv@6.15.0: resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -729,6 +1223,16 @@ packages: arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + autoprefixer@10.5.0: resolution: {integrity: sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==} engines: {node: ^10 || ^12 || >=14} @@ -745,6 +1249,9 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -768,6 +1275,10 @@ packages: bun-types@1.3.14: resolution: {integrity: sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ==} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} @@ -775,6 +1286,13 @@ packages: caniuse-lite@1.0.30001792: resolution: {integrity: sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==} + chai@4.5.0: + resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} + engines: {node: '>=4'} + + check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -790,6 +1308,9 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -801,6 +1322,13 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -809,6 +1337,10 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + data-urls@7.0.0: + resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + date-fns@4.4.0: resolution: {integrity: sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w==} @@ -821,9 +1353,20 @@ packages: supports-color: optional: true + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + + deep-eql@4.1.4: + resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} + engines: {node: '>=6'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -831,9 +1374,19 @@ packages: didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + dotenv@17.4.2: resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==} engines: {node: '>=12'} @@ -841,10 +1394,19 @@ packages: electron-to-chromium@1.5.356: resolution: {integrity: sha512-9NgFd7m5t5MCJ5rUSjJITUXAH9mEGlrlofnMf4YEr+pz6JlP7cWmTAH+JFmbPnaSW8koVTkuW7pacORWAnA5Yw==} + entities@8.0.0: + resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + engines: {node: '>=20.19.0'} + es-errors@1.3.0: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -902,10 +1464,17 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -972,6 +1541,13 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -994,10 +1570,18 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hono@4.12.25: - resolution: {integrity: sha512-2NFaIyNVgJmBs/ecmtGzlmluTFs5cHEWGTdu0t1HBwYzoGXOL5nUQBRMXsXWla5i4KkG//QMzVP88m1+I3fdAQ==} + hono@4.12.27: + resolution: {integrity: sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==} engines: {node: '>=16.9.0'} + html-encoding-sniffer@6.0.0: + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1010,6 +1594,10 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -1030,6 +1618,13 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -1040,6 +1635,18 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + jsdom@29.1.1: + resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -1143,17 +1750,41 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + local-pkg@0.5.1: + resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} + engines: {node: '>=14'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + + lru-cache@11.5.1: + resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - lucide-react@1.18.0: - resolution: {integrity: sha512-LZDb7H/0YfM+RJncD0hDQRCAu+vSGODqpe35TuVI8EuXaRjkczbsx7p8dY4J87F/MUSj6bpYqeI8nw8qXaAdmA==} - peerDependencies: - react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + lucide-react@1.21.0: + resolution: {integrity: sha512-reEZMXq8Qdd5jg5XYkQ5TR1fB/GiQ7ih4vcrthYDtgjSDwh0i6/YLiGjsWsIwgN49gpAnd4J2elSNzncMEEUUQ==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -1163,10 +1794,24 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + minimatch@10.2.5: resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} engines: {node: 18 || 20 || >=22} + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} + + mnemonist@0.38.3: + resolution: {integrity: sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1188,6 +1833,10 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -1196,6 +1845,13 @@ packages: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} + obliterator@1.6.1: + resolution: {integrity: sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -1204,10 +1860,17 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -1220,9 +1883,22 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1242,6 +1918,9 @@ packages: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + postcss-import@15.1.0: resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} @@ -1293,6 +1972,14 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -1305,19 +1992,25 @@ packages: peerDependencies: react: ^19.2.7 + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + react-refresh@0.18.0: resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} engines: {node: '>=0.10.0'} - react-router-dom@7.17.0: - resolution: {integrity: sha512-fyU2yjGups/hE6Xz0I5ZYbVL8Gx29eCjgpHaRaTaVU+OOAdfRX05KsvyRm0GO8YQwOkhpU3MurW1jyMUJn+zSw==} + react-router-dom@7.18.0: + resolution: {integrity: sha512-Fi0yY6kgtKae/Th2xibdWK0KSdYZ4B53Gyf6wRtomOKWgpNm7H7+DyfDhncdz9FKbpS+1jmDhg3F4WoGJ+yFOA==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' react-dom: '>=18' - react-router@7.17.0: - resolution: {integrity: sha512-FDELK7rTMlCHO5+reyXsPlmfr7N1F91lPHsWYfMEGQm/KQ+F4JFM8jGoeQDmDvdTs93Fw9aSilH+uKRb4/jXvQ==} + react-router@7.18.0: + resolution: {integrity: sha512-pTTGt8J+ji1NOmYnjzT+bAJy/1zD+Jp4ziO6cL7T3ZLvXKtusO7BpFqlRXitqpcPVqllsIXFHRMt+2/k3Xn6HQ==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' @@ -1337,6 +2030,14 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + resolve@1.22.12: resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} engines: {node: '>= 0.4'} @@ -1346,14 +2047,23 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rolldown@1.0.3: - resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==} + rolldown@1.1.3: + resolution: {integrity: sha512-1F1eEtUBtFvcGm1HQ9TiUIUHPQG7mSAODrhIzjxoUEFuo8OcbrGLiVLkevNgj84TE4lnHvnumwFjhJO5Eu135g==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rollup@4.60.4: + resolution: {integrity: sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -1377,10 +2087,34 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-literal@2.1.1: + resolution: {integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==} + strnum@2.3.0: resolution: {integrity: sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==} @@ -1393,6 +2127,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tailwind-merge@2.6.1: resolution: {integrity: sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==} @@ -1408,6 +2145,9 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinyglobby@0.2.16: resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} @@ -1416,10 +2156,33 @@ packages: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} + tinypool@0.8.4: + resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} + engines: {node: '>=14.0.0'} + + tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + engines: {node: '>=14.0.0'} + + tldts-core@7.4.2: + resolution: {integrity: sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==} + + tldts@7.4.2: + resolution: {integrity: sha512-kCwffuaH8ntKtygnWe1b4BJKWiCUH30n5KfoTr6IchcXOwR7chAOFJxFrH3vjANafUYrIA4a7SDL+nn7SiR4Sw==} + hasBin: true + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tough-cookie@6.0.1: + resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} + engines: {node: '>=16'} + + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + ts-api-utils@2.5.0: resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} @@ -1436,8 +2199,12 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript-eslint@8.61.0: - resolution: {integrity: sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==} + type-detect@4.1.0: + resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} + engines: {node: '>=4'} + + typescript-eslint@8.62.0: + resolution: {integrity: sha512-8QxXi+ZACKX0kaqO4gY8kn0RSD9gFfaHDWwjqtEN48aWCBkX4MJaufWN+c3BzlrXLOxfywDL8CaoqUwcRq4j4Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -1448,9 +2215,16 @@ packages: engines: {node: '>=14.17'} hasBin: true + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + undici-types@7.24.6: resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + undici@7.27.2: + resolution: {integrity: sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==} + engines: {node: '>=20.18.1'} + update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true @@ -1468,13 +2242,49 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - vite@8.0.16: - resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==} + vite-node@1.6.1: + resolution: {integrity: sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vite@8.1.0: + resolution: {integrity: sha512-BuJcQK/56NQTWDGn4ABea3q4SSBdNPWwNZKTkkUpcMPnLoquSYH8llRtSUIgoL1KSCpHt5eghLShn50mH36y7Q==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.1.18 + '@vitejs/devtools': ^0.3.0 esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 @@ -1511,19 +2321,72 @@ packages: yaml: optional: true + vitest@1.6.1: + resolution: {integrity: sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 1.6.1 + '@vitest/ui': 1.6.1 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} + + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} + + whatwg-url@16.0.1: + resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + xml-naming@0.1.0: resolution: {integrity: sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==} engines: {node: '>=16.0.0'} + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -1531,6 +2394,10 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yocto-queue@1.2.2: + resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} + engines: {node: '>=12.20'} + zod-validation-error@4.0.2: resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} engines: {node: '>=18.0.0'} @@ -1560,8 +2427,30 @@ packages: snapshots: + '@adobe/css-tools@4.5.0': {} + '@alloc/quick-lru@5.2.0': {} + '@asamuzakjp/css-color@5.1.11': + dependencies: + '@asamuzakjp/generational-cache': 1.0.1 + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.1.3(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@asamuzakjp/dom-selector@7.1.1': + dependencies: + '@asamuzakjp/generational-cache': 1.0.1 + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + + '@asamuzakjp/generational-cache@1.0.1': {} + + '@asamuzakjp/nwsapi@2.3.9': {} + '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 @@ -1571,14 +2460,14 @@ snapshots: '@aws-crypto/crc32c@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.12 + '@aws-sdk/types': 3.973.13 tslib: 2.8.1 '@aws-crypto/sha1-browser@5.2.0': dependencies: '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.12 + '@aws-sdk/types': 3.973.13 '@aws-sdk/util-locate-window': 3.965.5 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -1588,7 +2477,7 @@ snapshots: '@aws-crypto/sha256-js': 5.2.0 '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.12 + '@aws-sdk/types': 3.973.8 '@aws-sdk/util-locate-window': 3.965.5 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -1596,7 +2485,7 @@ snapshots: '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.12 + '@aws-sdk/types': 3.973.8 tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': @@ -1609,99 +2498,114 @@ snapshots: '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/checksums@3.1000.5': + '@aws-sdk/checksums@3.1000.8': dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.974.20 - '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@aws-sdk/client-ec2@3.1068.0': + '@aws-sdk/client-dynamodb@3.1066.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 '@aws-sdk/core': 3.974.20 '@aws-sdk/credential-provider-node': 3.972.55 - '@aws-sdk/middleware-sdk-ec2': 3.972.34 + '@aws-sdk/dynamodb-codec': 3.973.20 + '@aws-sdk/middleware-endpoint-discovery': 3.972.18 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/fetch-http-handler': 5.4.7 - '@smithy/node-http-handler': 4.7.8 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/fetch-http-handler': 5.4.6 + '@smithy/node-http-handler': 4.7.7 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@aws-sdk/client-eks@3.1068.0': + '@aws-sdk/client-ec2@3.1075.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.20 - '@aws-sdk/credential-provider-node': 3.972.55 - '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/fetch-http-handler': 5.4.7 - '@smithy/node-http-handler': 4.7.8 - '@smithy/types': 4.14.4 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-node': 3.972.58 + '@aws-sdk/middleware-sdk-ec2': 3.972.37 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/fetch-http-handler': 5.4.6 + '@smithy/node-http-handler': 4.7.7 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@aws-sdk/client-lambda@3.1068.0': + '@aws-sdk/client-eks@3.1075.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.20 - '@aws-sdk/credential-provider-node': 3.972.55 - '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/fetch-http-handler': 5.4.7 - '@smithy/node-http-handler': 4.7.8 - '@smithy/types': 4.14.4 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-node': 3.972.58 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/fetch-http-handler': 5.4.6 + '@smithy/node-http-handler': 4.7.7 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@aws-sdk/client-rds@3.1068.0': + '@aws-sdk/client-lambda@3.1075.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.20 - '@aws-sdk/credential-provider-node': 3.972.55 - '@aws-sdk/middleware-sdk-rds': 3.972.34 - '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/fetch-http-handler': 5.4.7 - '@smithy/node-http-handler': 4.7.8 - '@smithy/types': 4.14.4 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-node': 3.972.58 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/fetch-http-handler': 5.4.6 + '@smithy/node-http-handler': 4.7.7 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/client-rds@3.1075.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-node': 3.972.58 + '@aws-sdk/middleware-sdk-rds': 3.972.37 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/fetch-http-handler': 5.4.6 + '@smithy/node-http-handler': 4.7.7 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@aws-sdk/client-s3@3.1068.0': + '@aws-sdk/client-s3@3.1075.0': dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.20 - '@aws-sdk/credential-provider-node': 3.972.55 - '@aws-sdk/middleware-flexible-checksums': 3.974.30 - '@aws-sdk/middleware-sdk-s3': 3.972.51 - '@aws-sdk/signature-v4-multi-region': 3.996.34 - '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/fetch-http-handler': 5.4.7 - '@smithy/node-http-handler': 4.7.8 - '@smithy/types': 4.14.4 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-node': 3.972.58 + '@aws-sdk/middleware-flexible-checksums': 3.974.33 + '@aws-sdk/middleware-sdk-s3': 3.972.54 + '@aws-sdk/signature-v4-multi-region': 3.996.35 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/fetch-http-handler': 5.4.6 + '@smithy/node-http-handler': 4.7.7 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@aws-sdk/client-secrets-manager@3.1068.0': + '@aws-sdk/client-secrets-manager@3.1075.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.20 - '@aws-sdk/credential-provider-node': 3.972.55 - '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/fetch-http-handler': 5.4.7 - '@smithy/node-http-handler': 4.7.8 - '@smithy/types': 4.14.4 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-node': 3.972.58 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/fetch-http-handler': 5.4.6 + '@smithy/node-http-handler': 4.7.7 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/core@3.974.20': @@ -1709,9 +2613,20 @@ snapshots: '@aws-sdk/types': 3.973.12 '@aws-sdk/xml-builder': 3.972.29 '@aws/lambda-invoke-store': 0.2.4 - '@smithy/core': 3.24.7 - '@smithy/signature-v4': 5.4.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/signature-v4': 5.4.6 + '@smithy/types': 4.14.3 + bowser: 2.14.1 + tslib: 2.8.1 + + '@aws-sdk/core@3.974.23': + dependencies: + '@aws-sdk/types': 3.973.13 + '@aws-sdk/xml-builder': 3.972.31 + '@aws/lambda-invoke-store': 0.2.4 + '@smithy/core': 3.24.6 + '@smithy/signature-v4': 5.4.6 + '@smithy/types': 4.14.3 bowser: 2.14.1 tslib: 2.8.1 @@ -1719,18 +2634,36 @@ snapshots: dependencies: '@aws-sdk/core': 3.974.20 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.972.49': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/credential-provider-http@3.972.48': dependencies: '@aws-sdk/core': 3.974.20 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/fetch-http-handler': 5.4.7 - '@smithy/node-http-handler': 4.7.8 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/fetch-http-handler': 5.4.6 + '@smithy/node-http-handler': 4.7.7 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.51': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/fetch-http-handler': 5.4.6 + '@smithy/node-http-handler': 4.7.7 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/credential-provider-ini@3.972.53': @@ -1744,9 +2677,25 @@ snapshots: '@aws-sdk/credential-provider-web-identity': 3.972.52 '@aws-sdk/nested-clients': 3.997.20 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/credential-provider-imds': 4.3.9 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/credential-provider-imds': 4.3.8 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.972.56': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-env': 3.972.49 + '@aws-sdk/credential-provider-http': 3.972.51 + '@aws-sdk/credential-provider-login': 3.972.55 + '@aws-sdk/credential-provider-process': 3.972.49 + '@aws-sdk/credential-provider-sso': 3.972.55 + '@aws-sdk/credential-provider-web-identity': 3.972.55 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/credential-provider-imds': 4.3.8 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/credential-provider-login@3.972.52': @@ -1754,8 +2703,17 @@ snapshots: '@aws-sdk/core': 3.974.20 '@aws-sdk/nested-clients': 3.997.20 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-login@3.972.55': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/credential-provider-node@3.972.55': @@ -1767,17 +2725,39 @@ snapshots: '@aws-sdk/credential-provider-sso': 3.972.52 '@aws-sdk/credential-provider-web-identity': 3.972.52 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/credential-provider-imds': 4.3.9 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/credential-provider-imds': 4.3.8 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-node@3.972.58': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.49 + '@aws-sdk/credential-provider-http': 3.972.51 + '@aws-sdk/credential-provider-ini': 3.972.56 + '@aws-sdk/credential-provider-process': 3.972.49 + '@aws-sdk/credential-provider-sso': 3.972.55 + '@aws-sdk/credential-provider-web-identity': 3.972.55 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/credential-provider-imds': 4.3.8 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/credential-provider-process@3.972.46': dependencies: '@aws-sdk/core': 3.974.20 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-process@3.972.49': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/credential-provider-sso@3.972.52': @@ -1786,8 +2766,18 @@ snapshots: '@aws-sdk/nested-clients': 3.997.20 '@aws-sdk/token-providers': 3.1066.0 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.972.55': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/token-providers': 3.1074.0 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/credential-provider-web-identity@3.972.52': @@ -1795,40 +2785,69 @@ snapshots: '@aws-sdk/core': 3.974.20 '@aws-sdk/nested-clients': 3.997.20 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@aws-sdk/middleware-flexible-checksums@3.974.30': + '@aws-sdk/credential-provider-web-identity@3.972.55': dependencies: - '@aws-sdk/checksums': 3.1000.5 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-ec2@3.972.34': + '@aws-sdk/dynamodb-codec@3.973.20': dependencies: '@aws-sdk/core': 3.974.20 - '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/signature-v4': 5.4.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-rds@3.972.34': + '@aws-sdk/endpoint-cache@3.972.7': dependencies: - '@aws-sdk/core': 3.974.20 - '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/signature-v4': 5.4.7 - '@smithy/types': 4.14.4 + mnemonist: 0.38.3 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.972.51': + '@aws-sdk/middleware-endpoint-discovery@3.972.18': dependencies: - '@aws-sdk/core': 3.974.20 - '@aws-sdk/signature-v4-multi-region': 3.996.34 + '@aws-sdk/endpoint-cache': 3.972.7 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/middleware-flexible-checksums@3.974.33': + dependencies: + '@aws-sdk/checksums': 3.1000.8 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-ec2@3.972.37': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/signature-v4': 5.4.6 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-rds@3.972.37': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/signature-v4': 5.4.6 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-s3@3.972.54': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/signature-v4-multi-region': 3.996.35 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/nested-clients@3.997.20': @@ -1838,17 +2857,37 @@ snapshots: '@aws-sdk/core': 3.974.20 '@aws-sdk/signature-v4-multi-region': 3.996.34 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/fetch-http-handler': 5.4.7 - '@smithy/node-http-handler': 4.7.8 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/fetch-http-handler': 5.4.6 + '@smithy/node-http-handler': 4.7.7 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.997.23': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/signature-v4-multi-region': 3.996.35 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/fetch-http-handler': 5.4.6 + '@smithy/node-http-handler': 4.7.7 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/signature-v4-multi-region@3.996.34': dependencies: '@aws-sdk/types': 3.973.12 - '@smithy/signature-v4': 5.4.7 - '@smithy/types': 4.14.4 + '@smithy/signature-v4': 5.4.6 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.996.35': + dependencies: + '@aws-sdk/types': 3.973.13 + '@smithy/signature-v4': 5.4.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/token-providers@3.1066.0': @@ -1856,13 +2895,32 @@ snapshots: '@aws-sdk/core': 3.974.20 '@aws-sdk/nested-clients': 3.997.20 '@aws-sdk/types': 3.973.12 - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1074.0': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/types@3.973.12': dependencies: - '@smithy/types': 4.14.4 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/types@3.973.13': + dependencies: + '@smithy/types': 4.14.3 + tslib: 2.8.1 + + '@aws-sdk/types@3.973.8': + dependencies: + '@smithy/types': 4.14.3 tslib: 2.8.1 '@aws-sdk/util-locate-window@3.965.5': @@ -1871,10 +2929,15 @@ snapshots: '@aws-sdk/xml-builder@3.972.29': dependencies: - '@smithy/types': 4.14.4 + '@smithy/types': 4.14.3 fast-xml-parser: 5.7.3 tslib: 2.8.1 + '@aws-sdk/xml-builder@3.972.31': + dependencies: + '@smithy/types': 4.14.3 + tslib: 2.8.1 + '@aws/lambda-invoke-store@0.2.4': {} '@babel/code-frame@7.29.0': @@ -1966,6 +3029,8 @@ snapshots: '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 + '@babel/runtime@7.29.7': {} + '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 @@ -1984,25 +3049,122 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/types@7.29.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@bramus/specificity@2.4.2': + dependencies: + css-tree: 3.2.1 + + '@csstools/color-helpers@6.0.2': {} + + '@csstools/css-calc@3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-color-parser@4.1.3(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/color-helpers': 6.0.2 + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.5(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@4.0.0': {} + + '@emnapi/core@1.11.1': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.11.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true - '@emnapi/core@1.10.0': - dependencies: - '@emnapi/wasi-threads': 1.2.1 - tslib: 2.8.1 + '@esbuild/linux-x64@0.21.5': optional: true - '@emnapi/runtime@1.10.0': - dependencies: - tslib: 2.8.1 + '@esbuild/netbsd-x64@0.21.5': optional: true - '@emnapi/wasi-threads@1.2.1': - dependencies: - tslib: 2.8.1 + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': optional: true '@eslint-community/eslint-utils@4.9.1(eslint@10.5.0(jiti@1.21.7))': @@ -2039,6 +3201,8 @@ snapshots: '@eslint/core': 1.2.1 levn: 0.4.1 + '@exodus/bytes@1.15.1': {} + '@humanfs/core@0.19.2': dependencies: '@humanfs/types': 0.15.0 @@ -2055,6 +3219,10 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.10 + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -2074,11 +3242,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@tybys/wasm-util': 0.10.2 + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 optional: true '@nodable/entities@2.1.0': {} @@ -2095,96 +3263,173 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@oxc-project/types@0.133.0': {} + '@oxc-project/types@0.137.0': {} - '@rolldown/binding-android-arm64@1.0.3': + '@rolldown/binding-android-arm64@1.1.3': optional: true - '@rolldown/binding-darwin-arm64@1.0.3': + '@rolldown/binding-darwin-arm64@1.1.3': optional: true - '@rolldown/binding-darwin-x64@1.0.3': + '@rolldown/binding-darwin-x64@1.1.3': optional: true - '@rolldown/binding-freebsd-x64@1.0.3': + '@rolldown/binding-freebsd-x64@1.1.3': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + '@rolldown/binding-linux-arm-gnueabihf@1.1.3': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.3': + '@rolldown/binding-linux-arm64-gnu@1.1.3': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.3': + '@rolldown/binding-linux-arm64-musl@1.1.3': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.3': + '@rolldown/binding-linux-ppc64-gnu@1.1.3': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.3': + '@rolldown/binding-linux-s390x-gnu@1.1.3': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.3': + '@rolldown/binding-linux-x64-gnu@1.1.3': optional: true - '@rolldown/binding-linux-x64-musl@1.0.3': + '@rolldown/binding-linux-x64-musl@1.1.3': optional: true - '@rolldown/binding-openharmony-arm64@1.0.3': + '@rolldown/binding-openharmony-arm64@1.1.3': optional: true - '@rolldown/binding-wasm32-wasi@1.0.3': + '@rolldown/binding-wasm32-wasi@1.1.3': dependencies: - '@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) + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.3': + '@rolldown/binding-win32-arm64-msvc@1.1.3': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.3': + '@rolldown/binding-win32-x64-msvc@1.1.3': optional: true '@rolldown/pluginutils@1.0.0-rc.3': {} '@rolldown/pluginutils@1.0.1': {} - '@smithy/core@3.24.7': + '@rollup/rollup-android-arm-eabi@4.60.4': + optional: true + + '@rollup/rollup-android-arm64@4.60.4': + optional: true + + '@rollup/rollup-darwin-arm64@4.60.4': + optional: true + + '@rollup/rollup-darwin-x64@4.60.4': + optional: true + + '@rollup/rollup-freebsd-arm64@4.60.4': + optional: true + + '@rollup/rollup-freebsd-x64@4.60.4': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.60.4': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.60.4': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.60.4': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.60.4': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.60.4': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.60.4': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-x64-musl@4.60.4': + optional: true + + '@rollup/rollup-openbsd-x64@4.60.4': + optional: true + + '@rollup/rollup-openharmony-arm64@4.60.4': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.60.4': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.60.4': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.60.4': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.60.4': + optional: true + + '@sinclair/typebox@0.27.10': {} + + '@smithy/core@3.24.6': dependencies: '@aws-crypto/crc32': 5.2.0 - '@smithy/types': 4.14.4 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@smithy/credential-provider-imds@4.3.9': + '@smithy/credential-provider-imds@4.3.8': dependencies: - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@smithy/fetch-http-handler@5.4.7': + '@smithy/fetch-http-handler@5.4.6': dependencies: - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': dependencies: tslib: 2.8.1 - '@smithy/node-http-handler@4.7.8': + '@smithy/node-http-handler@4.7.7': dependencies: - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@smithy/signature-v4@5.4.7': + '@smithy/signature-v4@5.4.6': dependencies: - '@smithy/core': 3.24.7 - '@smithy/types': 4.14.4 + '@smithy/core': 3.24.6 + '@smithy/types': 4.14.3 tslib: 2.8.1 - '@smithy/types@4.14.4': + '@smithy/types@4.14.3': dependencies: tslib: 2.8.1 @@ -2198,26 +3443,62 @@ snapshots: '@smithy/util-buffer-from': 2.2.0 tslib: 2.8.1 - '@tanstack/query-core@5.101.0': {} + '@tanstack/query-core@5.101.1': {} - '@tanstack/query-devtools@5.101.0': {} + '@tanstack/query-devtools@5.101.1': {} + + '@tanstack/react-query-devtools@5.101.1(@tanstack/react-query@5.101.1(react@19.2.7))(react@19.2.7)': + dependencies: + '@tanstack/query-devtools': 5.101.1 + '@tanstack/react-query': 5.101.1(react@19.2.7) + react: 19.2.7 - '@tanstack/react-query-devtools@5.101.0(@tanstack/react-query@5.101.0(react@19.2.7))(react@19.2.7)': + '@tanstack/react-query@5.101.1(react@19.2.7)': dependencies: - '@tanstack/query-devtools': 5.101.0 - '@tanstack/react-query': 5.101.0(react@19.2.7) + '@tanstack/query-core': 5.101.1 react: 19.2.7 - '@tanstack/react-query@5.101.0(react@19.2.7)': + '@testing-library/dom@10.4.1': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/runtime': 7.29.7 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.9.1': + dependencies: + '@adobe/css-tools': 4.5.0 + aria-query: 5.3.2 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + picocolors: 1.1.1 + redent: 3.0.0 + + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@tanstack/query-core': 5.101.0 + '@babel/runtime': 7.29.7 + '@testing-library/dom': 10.4.1 react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)': + dependencies: + '@testing-library/dom': 10.4.1 - '@tybys/wasm-util@0.10.2': + '@tybys/wasm-util@0.10.3': dependencies: tslib: 2.8.1 optional: true + '@types/aria-query@5.0.4': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.29.3 @@ -2249,7 +3530,7 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@25.9.3': + '@types/node@25.9.4': dependencies: undici-types: 7.24.6 @@ -2261,14 +3542,14 @@ snapshots: dependencies: csstype: 3.2.3 - '@typescript-eslint/eslint-plugin@8.61.0(@typescript-eslint/parser@8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3))(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3))(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.61.0 - '@typescript-eslint/type-utils': 8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/utils': 8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.61.0 + '@typescript-eslint/parser': 8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.62.0 + '@typescript-eslint/type-utils': 8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/utils': 8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.62.0 eslint: 10.5.0(jiti@1.21.7) ignore: 7.0.5 natural-compare: 1.4.0 @@ -2277,41 +3558,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/parser@8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.61.0 - '@typescript-eslint/types': 8.61.0 - '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.61.0 + '@typescript-eslint/scope-manager': 8.62.0 + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/typescript-estree': 8.62.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.62.0 debug: 4.4.3 eslint: 10.5.0(jiti@1.21.7) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.61.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.62.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.61.0(typescript@5.9.3) - '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@5.9.3) + '@typescript-eslint/types': 8.62.0 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.61.0': + '@typescript-eslint/scope-manager@8.62.0': dependencies: - '@typescript-eslint/types': 8.61.0 - '@typescript-eslint/visitor-keys': 8.61.0 + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/visitor-keys': 8.62.0 - '@typescript-eslint/tsconfig-utils@8.61.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.62.0(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.61.0 - '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/typescript-estree': 8.62.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) debug: 4.4.3 eslint: 10.5.0(jiti@1.21.7) ts-api-utils: 2.5.0(typescript@5.9.3) @@ -2319,40 +3600,40 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.61.0': {} + '@typescript-eslint/types@8.62.0': {} - '@typescript-eslint/typescript-estree@8.61.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.62.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.61.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.61.0(typescript@5.9.3) - '@typescript-eslint/types': 8.61.0 - '@typescript-eslint/visitor-keys': 8.61.0 + '@typescript-eslint/project-service': 8.62.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@5.9.3) + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/visitor-keys': 8.62.0 debug: 4.4.3 minimatch: 10.2.5 semver: 7.8.0 - tinyglobby: 0.2.17 + tinyglobby: 0.2.16 ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/utils@8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.5.0(jiti@1.21.7)) - '@typescript-eslint/scope-manager': 8.61.0 - '@typescript-eslint/types': 8.61.0 - '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.62.0 + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/typescript-estree': 8.62.0(typescript@5.9.3) eslint: 10.5.0(jiti@1.21.7) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.61.0': + '@typescript-eslint/visitor-keys@8.62.0': dependencies: - '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/types': 8.62.0 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react@5.2.0(vite@8.0.16(@types/node@25.9.3)(jiti@1.21.7))': + '@vitejs/plugin-react@5.2.0(vite@8.1.0(@types/node@25.9.4)(jiti@1.21.7))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) @@ -2360,14 +3641,47 @@ snapshots: '@rolldown/pluginutils': 1.0.0-rc.3 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 8.0.16(@types/node@25.9.3)(jiti@1.21.7) + vite: 8.1.0(@types/node@25.9.4)(jiti@1.21.7) transitivePeerDependencies: - supports-color + '@vitest/expect@1.6.1': + dependencies: + '@vitest/spy': 1.6.1 + '@vitest/utils': 1.6.1 + chai: 4.5.0 + + '@vitest/runner@1.6.1': + dependencies: + '@vitest/utils': 1.6.1 + p-limit: 5.0.0 + pathe: 1.1.2 + + '@vitest/snapshot@1.6.1': + dependencies: + magic-string: 0.30.21 + pathe: 1.1.2 + pretty-format: 29.7.0 + + '@vitest/spy@1.6.1': + dependencies: + tinyspy: 2.2.1 + + '@vitest/utils@1.6.1': + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + acorn-jsx@5.3.2(acorn@8.16.0): dependencies: acorn: 8.16.0 + acorn-walk@8.3.5: + dependencies: + acorn: 8.16.0 + acorn@8.16.0: {} ajv@6.15.0: @@ -2377,6 +3691,10 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ansi-regex@5.0.1: {} + + ansi-styles@5.2.0: {} + any-promise@1.3.0: {} anymatch@3.1.3: @@ -2386,6 +3704,14 @@ snapshots: arg@5.0.2: {} + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + + assertion-error@1.1.0: {} + autoprefixer@10.5.0(postcss@8.5.15): dependencies: browserslist: 4.28.2 @@ -2399,6 +3725,10 @@ snapshots: baseline-browser-mapping@2.10.29: {} + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + binary-extensions@2.3.0: {} bowser@2.14.1: {} @@ -2421,12 +3751,28 @@ snapshots: bun-types@1.3.14: dependencies: - '@types/node': 25.9.3 + '@types/node': 25.9.4 + + cac@6.7.14: {} camelcase-css@2.0.1: {} caniuse-lite@1.0.30001792: {} + chai@4.5.0: + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.4 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.1.0 + + check-error@1.0.3: + dependencies: + get-func-name: 2.0.2 + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -2447,6 +3793,8 @@ snapshots: commander@4.1.1: {} + confbox@0.1.8: {} + convert-source-map@2.0.0: {} cookie@1.1.1: {} @@ -2457,30 +3805,86 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + + css.escape@1.5.1: {} + cssesc@3.0.0: {} csstype@3.2.3: {} + data-urls@7.0.0: + dependencies: + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + transitivePeerDependencies: + - '@noble/hashes' + date-fns@4.4.0: {} debug@4.4.3: dependencies: ms: 2.1.3 + decimal.js@10.6.0: {} + + deep-eql@4.1.4: + dependencies: + type-detect: 4.1.0 + deep-is@0.1.4: {} + dequal@2.0.3: {} + detect-libc@2.1.2: {} didyoumean@1.2.2: {} + diff-sequences@29.6.3: {} + dlv@1.1.3: {} + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + dotenv@17.4.2: {} electron-to-chromium@1.5.356: {} + entities@8.0.0: {} + es-errors@1.3.0: {} + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + escalade@3.2.0: {} escape-string-regexp@4.0.0: {} @@ -2564,8 +3968,24 @@ snapshots: estraverse@5.3.0: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + esutils@2.0.3: {} + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + fast-deep-equal@3.1.3: {} fast-glob@3.3.3: @@ -2629,6 +4049,10 @@ snapshots: gensync@1.0.0-beta.2: {} + get-func-name@2.0.2: {} + + get-stream@8.0.1: {} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -2649,7 +4073,15 @@ snapshots: dependencies: hermes-estree: 0.25.1 - hono@4.12.25: {} + hono@4.12.27: {} + + html-encoding-sniffer@6.0.0: + dependencies: + '@exodus/bytes': 1.15.1 + transitivePeerDependencies: + - '@noble/hashes' + + human-signals@5.0.0: {} ignore@5.3.2: {} @@ -2657,6 +4089,8 @@ snapshots: imurmurhash@0.1.4: {} + indent-string@4.0.0: {} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -2673,12 +4107,44 @@ snapshots: is-number@7.0.0: {} + is-potential-custom-element-name@1.0.1: {} + + is-stream@3.0.0: {} + isexe@2.0.0: {} jiti@1.21.7: {} js-tokens@4.0.0: {} + js-tokens@9.0.1: {} + + jsdom@29.1.1: + dependencies: + '@asamuzakjp/css-color': 5.1.11 + '@asamuzakjp/dom-selector': 7.1.1 + '@bramus/specificity': 2.4.2 + '@csstools/css-syntax-patches-for-csstree': 1.1.5(css-tree@3.2.1) + '@exodus/bytes': 1.15.1 + css-tree: 3.2.1 + data-urls: 7.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.1 + parse5: 8.0.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.1 + undici: 7.27.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@noble/hashes' + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -2751,18 +4217,39 @@ snapshots: lines-and-columns@1.2.4: {} + local-pkg@0.5.1: + dependencies: + mlly: 1.8.2 + pkg-types: 1.3.1 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 + loupe@2.3.7: + dependencies: + get-func-name: 2.0.2 + + lru-cache@11.5.1: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 - lucide-react@1.18.0(react@19.2.7): + lucide-react@1.21.0(react@19.2.7): dependencies: react: 19.2.7 + lz-string@1.5.0: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + mdn-data@2.27.1: {} + + merge-stream@2.0.0: {} + merge2@1.4.1: {} micromatch@4.0.8: @@ -2770,10 +4257,25 @@ snapshots: braces: 3.0.3 picomatch: 2.3.2 + mimic-fn@4.0.0: {} + + min-indent@1.0.1: {} + minimatch@10.2.5: dependencies: brace-expansion: 5.0.6 + mlly@1.8.2: + dependencies: + acorn: 8.16.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.4 + + mnemonist@0.38.3: + dependencies: + obliterator: 1.6.1 + ms@2.1.3: {} mz@2.7.0: @@ -2790,10 +4292,20 @@ snapshots: normalize-path@3.0.0: {} + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + object-assign@4.1.1: {} object-hash@3.0.0: {} + obliterator@1.6.1: {} + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -2807,18 +4319,34 @@ snapshots: dependencies: yocto-queue: 0.1.0 + p-limit@5.0.0: + dependencies: + yocto-queue: 1.2.2 + p-locate@5.0.0: dependencies: p-limit: 3.1.0 + parse5@8.0.1: + dependencies: + entities: 8.0.0 + path-exists@4.0.0: {} path-expression-matcher@1.5.0: {} path-key@3.1.1: {} + path-key@4.0.0: {} + path-parse@1.0.7: {} + pathe@1.1.2: {} + + pathe@2.0.3: {} + + pathval@1.1.1: {} + picocolors@1.1.1: {} picomatch@2.3.2: {} @@ -2829,6 +4357,12 @@ snapshots: pirates@4.0.7: {} + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.2 + pathe: 2.0.3 + postcss-import@15.1.0(postcss@8.5.15): dependencies: postcss: 8.5.15 @@ -2868,6 +4402,18 @@ snapshots: prelude-ls@1.2.1: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + punycode@2.3.1: {} queue-microtask@1.2.3: {} @@ -2877,15 +4423,19 @@ snapshots: react: 19.2.7 scheduler: 0.27.0 + react-is@17.0.2: {} + + react-is@18.3.1: {} + react-refresh@0.18.0: {} - react-router-dom@7.17.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + react-router-dom@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - react-router: 7.17.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react-router: 7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - react-router@7.17.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: cookie: 1.1.1 react: 19.2.7 @@ -2903,6 +4453,13 @@ snapshots: dependencies: picomatch: 2.3.2 + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + require-from-string@2.0.2: {} + resolve@1.22.12: dependencies: es-errors: 1.3.0 @@ -2912,31 +4469,66 @@ snapshots: reusify@1.1.0: {} - rolldown@1.0.3: + rolldown@1.1.3: dependencies: - '@oxc-project/types': 0.133.0 + '@oxc-project/types': 0.137.0 '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.3 - '@rolldown/binding-darwin-arm64': 1.0.3 - '@rolldown/binding-darwin-x64': 1.0.3 - '@rolldown/binding-freebsd-x64': 1.0.3 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.3 - '@rolldown/binding-linux-arm64-gnu': 1.0.3 - '@rolldown/binding-linux-arm64-musl': 1.0.3 - '@rolldown/binding-linux-ppc64-gnu': 1.0.3 - '@rolldown/binding-linux-s390x-gnu': 1.0.3 - '@rolldown/binding-linux-x64-gnu': 1.0.3 - '@rolldown/binding-linux-x64-musl': 1.0.3 - '@rolldown/binding-openharmony-arm64': 1.0.3 - '@rolldown/binding-wasm32-wasi': 1.0.3 - '@rolldown/binding-win32-arm64-msvc': 1.0.3 - '@rolldown/binding-win32-x64-msvc': 1.0.3 + '@rolldown/binding-android-arm64': 1.1.3 + '@rolldown/binding-darwin-arm64': 1.1.3 + '@rolldown/binding-darwin-x64': 1.1.3 + '@rolldown/binding-freebsd-x64': 1.1.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.3 + '@rolldown/binding-linux-arm64-gnu': 1.1.3 + '@rolldown/binding-linux-arm64-musl': 1.1.3 + '@rolldown/binding-linux-ppc64-gnu': 1.1.3 + '@rolldown/binding-linux-s390x-gnu': 1.1.3 + '@rolldown/binding-linux-x64-gnu': 1.1.3 + '@rolldown/binding-linux-x64-musl': 1.1.3 + '@rolldown/binding-openharmony-arm64': 1.1.3 + '@rolldown/binding-wasm32-wasi': 1.1.3 + '@rolldown/binding-win32-arm64-msvc': 1.1.3 + '@rolldown/binding-win32-x64-msvc': 1.1.3 + + rollup@4.60.4: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.60.4 + '@rollup/rollup-android-arm64': 4.60.4 + '@rollup/rollup-darwin-arm64': 4.60.4 + '@rollup/rollup-darwin-x64': 4.60.4 + '@rollup/rollup-freebsd-arm64': 4.60.4 + '@rollup/rollup-freebsd-x64': 4.60.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.4 + '@rollup/rollup-linux-arm-musleabihf': 4.60.4 + '@rollup/rollup-linux-arm64-gnu': 4.60.4 + '@rollup/rollup-linux-arm64-musl': 4.60.4 + '@rollup/rollup-linux-loong64-gnu': 4.60.4 + '@rollup/rollup-linux-loong64-musl': 4.60.4 + '@rollup/rollup-linux-ppc64-gnu': 4.60.4 + '@rollup/rollup-linux-ppc64-musl': 4.60.4 + '@rollup/rollup-linux-riscv64-gnu': 4.60.4 + '@rollup/rollup-linux-riscv64-musl': 4.60.4 + '@rollup/rollup-linux-s390x-gnu': 4.60.4 + '@rollup/rollup-linux-x64-gnu': 4.60.4 + '@rollup/rollup-linux-x64-musl': 4.60.4 + '@rollup/rollup-openbsd-x64': 4.60.4 + '@rollup/rollup-openharmony-arm64': 4.60.4 + '@rollup/rollup-win32-arm64-msvc': 4.60.4 + '@rollup/rollup-win32-ia32-msvc': 4.60.4 + '@rollup/rollup-win32-x64-gnu': 4.60.4 + '@rollup/rollup-win32-x64-msvc': 4.60.4 + fsevents: 2.3.3 run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.27.0: {} semver@6.3.1: {} @@ -2951,8 +4543,26 @@ snapshots: shebang-regex@3.0.0: {} + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + source-map-js@1.2.1: {} + stackback@0.0.2: {} + + std-env@3.10.0: {} + + strip-final-newline@3.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-literal@2.1.1: + dependencies: + js-tokens: 9.0.1 + strnum@2.3.0: {} sucrase@3.35.1: @@ -2967,6 +4577,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + symbol-tree@3.2.4: {} + tailwind-merge@2.6.1: {} tailwindcss@3.4.19: @@ -3005,6 +4617,8 @@ snapshots: dependencies: any-promise: 1.3.0 + tinybench@2.9.0: {} + tinyglobby@0.2.16: dependencies: fdir: 6.5.0(picomatch@4.0.4) @@ -3015,10 +4629,28 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 + tinypool@0.8.4: {} + + tinyspy@2.2.1: {} + + tldts-core@7.4.2: {} + + tldts@7.4.2: + dependencies: + tldts-core: 7.4.2 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 + tough-cookie@6.0.1: + dependencies: + tldts: 7.4.2 + + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + ts-api-utils@2.5.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -3031,12 +4663,14 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3): + type-detect@4.1.0: {} + + typescript-eslint@8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.61.0(@typescript-eslint/parser@8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3))(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/parser': 8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.61.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3))(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/parser': 8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.62.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.62.0(eslint@10.5.0(jiti@1.21.7))(typescript@5.9.3) eslint: 10.5.0(jiti@1.21.7) typescript: 5.9.3 transitivePeerDependencies: @@ -3044,8 +4678,12 @@ snapshots: typescript@5.9.3: {} + ufo@1.6.4: {} + undici-types@7.24.6: {} + undici@7.27.2: {} + update-browserslist-db@1.2.3(browserslist@4.28.2): dependencies: browserslist: 4.28.2 @@ -3063,30 +4701,120 @@ snapshots: util-deprecate@1.0.2: {} - vite@8.0.16(@types/node@25.9.3)(jiti@1.21.7): + vite-node@1.6.1(@types/node@25.9.4)(lightningcss@1.32.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + pathe: 1.1.2 + picocolors: 1.1.1 + vite: 5.4.21(@types/node@25.9.4)(lightningcss@1.32.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vite@5.4.21(@types/node@25.9.4)(lightningcss@1.32.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.15 + rollup: 4.60.4 + optionalDependencies: + '@types/node': 25.9.4 + fsevents: 2.3.3 + lightningcss: 1.32.0 + + vite@8.1.0(@types/node@25.9.4)(jiti@1.21.7): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 postcss: 8.5.15 - rolldown: 1.0.3 + rolldown: 1.1.3 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 25.9.3 + '@types/node': 25.9.4 fsevents: 2.3.3 jiti: 1.21.7 + vitest@1.6.1(@types/node@25.9.4)(jsdom@29.1.1)(lightningcss@1.32.0): + dependencies: + '@vitest/expect': 1.6.1 + '@vitest/runner': 1.6.1 + '@vitest/snapshot': 1.6.1 + '@vitest/spy': 1.6.1 + '@vitest/utils': 1.6.1 + acorn-walk: 8.3.5 + chai: 4.5.0 + debug: 4.4.3 + execa: 8.0.1 + local-pkg: 0.5.1 + magic-string: 0.30.21 + pathe: 1.1.2 + picocolors: 1.1.1 + std-env: 3.10.0 + strip-literal: 2.1.1 + tinybench: 2.9.0 + tinypool: 0.8.4 + vite: 5.4.21(@types/node@25.9.4)(lightningcss@1.32.0) + vite-node: 1.6.1(@types/node@25.9.4)(lightningcss@1.32.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.9.4 + jsdom: 29.1.1 + transitivePeerDependencies: + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + webidl-conversions@8.0.1: {} + + whatwg-mimetype@5.0.0: {} + + whatwg-url@16.0.1: + dependencies: + '@exodus/bytes': 1.15.1 + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + which@2.0.2: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + word-wrap@1.2.5: {} + xml-name-validator@5.0.0: {} + xml-naming@0.1.0: {} + xmlchars@2.2.0: {} + yallist@3.1.1: {} yocto-queue@0.1.0: {} + yocto-queue@1.2.2: {} + zod-validation-error@4.0.2(zod@4.4.3): dependencies: zod: 4.4.3