diff --git a/components.json b/components.json index 6998bdf..771aa24 100644 --- a/components.json +++ b/components.json @@ -11,11 +11,11 @@ "prefix": "" }, "aliases": { - "components": "@/components", - "utils": "@/lib/utils", - "ui": "@/components/ui", - "lib": "@/lib", - "hooks": "@/hooks" + "components": "#src/webapp/components", + "utils": "#src/webapp/utils", + "ui": "#src/webapp/components/ui", + "lib": "#src/webapp/lib", + "hooks": "#src/webapp/hooks" }, "iconLibrary": "lucide" } \ No newline at end of file diff --git a/docs/PLAN-DB-PERSONS.md b/docs/PLAN-DB-PERSONS.md new file mode 100644 index 0000000..cff9c24 --- /dev/null +++ b/docs/PLAN-DB-PERSONS.md @@ -0,0 +1,1647 @@ +# Plan: DB Persons Feature with Multi-Entity Architecture + +## Overview + +This document outlines the implementation plan for a "DB Persons" feature similar to the existing "DB Todo" but with a more complex multi-entity data model. The feature will manage persons with related entities like addresses and banking data using DynamoDB single-table design **powered by ElectroDB**. + +This is a **simple multi-entity example** focused on basic CRUD operations with TanStack DB and ElectroDB. Search functionality is postponed to a future branch. + +**Key Design Decision:** ElectroDB schemas are **derived from Zod schemas** to ensure a single source of truth. When Zod schemas are updated, ElectroDB entities automatically reflect those changes. + +--- + +## Status Update + +- Completed: Collections + server functions for persons and related entities +- Completed: React hooks `useDbPersons.ts` with CRUD mutations and live queries +- Completed: UI CRUD for persons, addresses, contacts, bank accounts, employment via modals +- Added: Person detail panel, edit modal, and create person modal +- Notes: Adjusted code to comply with strict oxlint rules (no ternary, id-length, max-statements); replaced Tailwind shrink classes per linter + +Remaining minor tasks: +- Refine statement counts in route components if flagged by linter +- Document search/indexing phase (postponed) + +## 1. Data Model Design + +### 1.1 Entity Types + +| Entity | Description | Relationship | +|--------|-------------|--------------| +| **Person** | Core entity with personal information | Root entity | +| **Address** | Physical/mailing addresses | 1:N with Person | +| **BankAccount** | Banking information | 1:N with Person | +| **ContactInfo** | Email, phone, social media | 1:N with Person | +| **Employment** | Job history and current employment | 1:N with Person | + +### 1.2 Entity Schemas (TypeScript/Zod) + +```typescript +// Person +{ + id: string; // UUID + firstName: string; + lastName: string; + dateOfBirth: string; // ISO date + gender: 'male' | 'female' | 'other' | 'prefer_not_to_say'; + createdAt: string; + updatedAt: string; +} + +// Address +{ + id: string; // UUID + personId: string; // FK to Person + type: 'home' | 'work' | 'billing' | 'shipping'; + street: string; + city: string; + state: string; + postalCode: string; + country: string; + isPrimary: boolean; +} + +// BankAccount +{ + id: string; // UUID + personId: string; // FK to Person + bankName: string; + accountType: 'checking' | 'savings' | 'investment'; + accountNumberLast4: string; // Only store last 4 digits + iban: string; // International Bank Account Number + bic: string; // Bank Identifier Code + isPrimary: boolean; +} + +// ContactInfo +{ + id: string; // UUID + personId: string; // FK to Person + type: 'email' | 'phone' | 'mobile' | 'linkedin' | 'twitter'; + value: string; + isPrimary: boolean; + isVerified: boolean; +} + +// Employment +{ + id: string; // UUID + personId: string; // FK to Person + companyName: string; + position: string; + department: string; + startDate: string; + endDate: string | null; + isCurrent: boolean; + salary: number; + currency: string; +} +``` + +--- + +## 2. DynamoDB Single-Table Design + +### 2.1 Key Structure + +| Entity | PK | SK | Purpose | +|--------|----|----|---------| +| Person | `PERSON#` | `PROFILE` | Person profile data | +| Address | `PERSON#` | `ADDRESS#` | Person's addresses | +| BankAccount | `PERSON#` | `BANK#` | Person's bank accounts | +| ContactInfo | `PERSON#` | `CONTACT#` | Person's contact info | +| Employment | `PERSON#` | `EMPLOYMENT#` | Person's employment history | + +### 2.2 Access Patterns + +| Access Pattern | Key Condition | Description | +|----------------|---------------|-------------| +| Get all persons | GSI1: `gsi1pk = PERSONS` | List all persons | +| Get person by ID | `pk = PERSON#, sk = PROFILE` | Single person lookup | +| Get person with all data | `pk = PERSON#` | Get person + all related entities (collection query) | +| Get person's addresses | `pk = PERSON#, sk begins_with ADDRESS#` | All addresses for a person | +| Get person's bank accounts | `pk = PERSON#, sk begins_with BANK#` | All bank accounts for a person | + +### 2.3 Global Secondary Indexes + +**GSI1: List All Persons** is used for querying all persons. + +**Note on GSI2:** A Global Secondary Index (GSI2) for efficiently fetching all entities for search functionality is **postponed**. It will be implemented when search capability is added in a future phase. This includes: +- Partition Key: `gsi2pk = "ALL_DATA"` +- Sort Key: `gsi2sk = "PERSON###"` + +When implementing search, GSI2 will provide efficient bulk data fetching compared to multiple table scans. + +--- + +## 3. Implementation Tasks + +### Phase 1: Types & Fake Data Generation + +#### 3.1 Create Type Definitions +- [ ] Create `/src/webapp/types/person.ts` with all entity schemas (Zod) + - PersonSchema + - AddressSchema + - BankAccountSchema + - ContactInfoSchema + - EmploymentSchema + - Combined request/response schemas + +#### 3.2 Create Fake Data Generator +- [ ] Create `/src/webapp/data/fake-persons.ts` + - Use `@faker-js/faker` with seeded random for reproducible data + - Generate **10,000 fake persons** with related data + - Each person should have: + - 1-3 addresses + - 1-2 bank accounts + - 2-4 contact infos + - 1-3 employment records + - Export both individual entity arrays and combined data structure + - Use batching for efficient generation + +### Phase 2: CDK Infrastructure Updates + +#### 3.3 Update Database Construct +- [x] Modify `/lib/constructs/DatabasePersons.ts` + - Add GSI1 for listing all persons (`gsi1pk`, `gsi1sk`) + - GSI2 for listing all entities is **postponed** until search implementation + - Keep existing pk/sk structure + +#### 3.4 Update Webapp Construct +- [ ] Modify `/lib/constructs/Webapp.ts` + - Add `grantReadWriteData` for databasePersons + +### Phase 3: ElectroDB Entities (Derived from Zod) + +#### 3.5 Create Zod-to-ElectroDB Schema Converter +- [ ] Create `/src/webapp/integrations/electrodb/zod-to-electrodb.ts` + - Utility to convert Zod schemas to ElectroDB attribute definitions + - Maps Zod types to ElectroDB types: + - `z.string()` → `{ type: 'string' }` + - `z.number()` → `{ type: 'number' }` + - `z.boolean()` → `{ type: 'boolean' }` + - `z.enum([...])` → `{ type: [...] as const }` + - `z.optional()` → no `required: true` + - Ensures single source of truth: Zod changes → ElectroDB changes + +#### 3.6 Create ElectroDB Entities +- [ ] Create `/src/webapp/integrations/electrodb/entities.ts` + - `PersonEntity` - Person profile entity + - `AddressEntity` - Address entity with personId composite key + - `BankAccountEntity` - Bank account entity + - `ContactInfoEntity` - Contact info entity + - `EmploymentEntity` - Employment entity + - All entities share the same table (single-table design) + +#### 3.7 Create ElectroDB Service +- [ ] Create `/src/webapp/integrations/electrodb/personsService.ts` + - Combine all entities into a Service for collection queries + - Collection: `personData` - Query person with all related entities + - CRUD operations use ElectroDB's fluent API: + - `PersonEntity.query.byPerson({ personId }).go()` - Get person + - `PersonEntity.put(person).go()` - Create/update person + - `PersonEntity.delete({ personId }).go()` - Delete person + - `PersonsService.collections.personData({ personId }).go()` - Get all data + +### Phase 4: Orama Search + TanStack Pacer + +#### 3.6 Create Search Index +### Phase 4: TanStack DB Collections with Server Functions + +#### 4.1 Create Server Functions & Collections + - [x] Create `/src/webapp/db-collections/persons.ts` + - Define server functions for DynamoDB operations (co-located with collections) + - personsCollection - Base collection using server functions + - addressesCollection - Addresses collection + - bankAccountsCollection - Bank accounts collection + - contactInfosCollection - Contact info collection + - employmentsCollection - Employment history collection + +#### 4.2 Create Live Query Collections for Related Data +- [ ] Create derived collections using `createLiveQueryCollection` for: + - Filtering addresses by personId + - Filtering bank accounts by personId + - Combining person with related entities via joins + +#### 4.3 Query Operators Reference +Available operators for filtering (from TanStack DB docs): + +```typescript +import { eq, gt, gte, lt, lte, like, ilike, inArray, and, or, not } from '@tanstack/db' + +// Examples +eq(user.id, '123') // Equality +gt(user.age, 18) // Greater than +gte(user.age, 18) // Greater than or equal +lt(user.age, 65) // Less than +lte(user.age, 65) // Less than or equal +like(user.name, 'John%') // Case-sensitive pattern matching +ilike(user.name, 'john%') // Case-insensitive pattern matching +inArray(user.id, ['1', '2']) // Array membership + +// Logical operators +and(condition1, condition2) +or(condition1, condition2) +not(condition) +``` + +**Why GSI2 instead of multiple scans?** +- ✅ **1 query** vs 5 separate scans +- ✅ **Sorted by personId** for easy grouping +- ✅ **Efficient pagination** with ElectroDB's `pages: 'all'` +- ✅ **Lower cost** - fewer read operations + +#### 3.8 Payload Size Limits & Data Loading Strategy + +**⚠️ Critical Issue:** Lambda/API Gateway have payload limits that affect 50k items (~25 MB): + +| Service | Limit | Our Data (~50k items) | +|---------|-------|----------------------| +| Lambda (sync response) | 6 MB | ❌ ~25 MB exceeds | +| Lambda Function URL | 6 MB | ❌ ~25 MB exceeds | +| API Gateway REST/HTTP | 10 MB | ❌ ~25 MB exceeds | +| Lambda Streaming | Unlimited | ✅ Works | + +**✅ DECIDED: Pagination + Compression (Recommended)** + +Fetch data in paginated chunks with gzip compression: + +```typescript +// Server function: Fetch paginated + compressed data +const fetchAllDataPaginated = createServerFn({ method: 'GET' }) + .validator(z.object({ cursor: z.string().optional() })) + .handler(async ({ data }) => { + const PAGE_SIZE = 1000 // ~500 KB uncompressed per page + + const result = await PersonsService.collections + .allData({}) + .go({ + cursor: data.cursor, + limit: PAGE_SIZE, + }) + + return { + data: result.data, + cursor: result.cursor, // null when done + hasMore: !!result.cursor, + } + }) + +// Client: Progressive loading with progress indicator +async function loadAllDataForOrama(onProgress: (percent: number) => void) { + const allData = { person: [], address: [], contactInfo: [], employment: [], bankAccount: [] } + let cursor: string | undefined + let loaded = 0 + const estimated = 50000 // Estimated total items + + do { + const { data, cursor: nextCursor, hasMore } = await fetchAllDataPaginated({ + data: { cursor } + }) + + // Merge results + Object.keys(data).forEach(key => { + allData[key].push(...(data[key] || [])) + loaded += data[key]?.length || 0 + }) + + onProgress(Math.min(95, (loaded / estimated) * 100)) + cursor = nextCursor + } while (cursor) + + onProgress(100) + return allData +} +``` + +**UI Progress Indicator:** +```tsx +function SearchIndexLoader() { + const [progress, setProgress] = useState(0) + const [isLoading, setIsLoading] = useState(true) + + useEffect(() => { + loadAllDataForOrama(setProgress) + .then(buildOramaIndex) + .finally(() => setIsLoading(false)) + }, []) + + if (!isLoading) return null + + return ( +
+ + + Building search index... {Math.round(progress)}% + +
+ ) +} +``` + +**Benefits of Pagination + Compression:** +- ✅ Each request stays under 6 MB limit (with gzip: ~100 KB per 1000 items) +- ✅ Progressive loading with user-visible progress +- ✅ Works with existing Lambda + TanStack Start setup +- ✅ Resilient to network issues (can resume from cursor) + +--- + +### Future Options (For Production Consideration) + +#### Option A: Lambda Response Streaming + +For true streaming without pagination overhead: + +```typescript +// Requires Lambda function URL with streaming enabled +const fetchAllDataStreaming = createServerFn({ method: 'GET' }) + .handler(async () => { + const stream = new ReadableStream({ + async start(controller) { + let cursor: string | undefined + + do { + const { data, cursor: nextCursor } = await PersonsService.collections + .allData({}) + .go({ cursor, limit: 500 }) + + controller.enqueue(new TextEncoder().encode(JSON.stringify(data) + '\n')) + cursor = nextCursor + } while (cursor) + + controller.close() + } + }) + + return new Response(stream, { + headers: { 'Content-Type': 'application/x-ndjson' } + }) + }) +``` + +**Pros:** No payload limit, single request, real streaming +**Cons:** Requires Lambda streaming setup, more complex client parsing + +#### Option B: Server-Side Orama Index + +Move search entirely to server: + +```typescript +// Cache Orama index in Lambda memory (reused across warm invocations) +let cachedIndex: Orama | null = null +let lastBuildTime = 0 + +const searchPersonsServer = createServerFn({ method: 'POST' }) + .validator(z.object({ term: z.string(), limit: z.number().default(50) })) + .handler(async ({ data }) => { + const CACHE_TTL = 5 * 60 * 1000 // 5 minutes + + // Rebuild if cache expired or missing + if (!cachedIndex || Date.now() - lastBuildTime > CACHE_TTL) { + const allData = await fetchAllEntitiesFromDDB() + cachedIndex = await buildOramaIndex(allData) + lastBuildTime = Date.now() + } + + const results = await search(cachedIndex, { + term: data.term, + limit: data.limit, + tolerance: 1, + }) + + // Return only IDs, client fetches full data on click + return results.hits.map(h => ({ id: h.document.id, score: h.score })) + }) +``` + +**Pros:** Fast initial page load, no client-side index building +**Cons:** Search latency (~100-200ms vs <10ms), Lambda memory usage, cache invalidation complexity + +#### Option C: Pre-built Search Index in S3 + +Build index offline and serve from S3/CloudFront: + +```typescript +// Scheduled Lambda: Build and upload index to S3 +async function rebuildSearchIndex() { + const allData = await fetchAllEntitiesFromDDB() + const index = await buildOramaIndex(allData) + const serialized = await persist(index) + + await s3.putObject({ + Bucket: 'my-bucket', + Key: 'search-index.json', + Body: JSON.stringify(serialized), + ContentType: 'application/json', + ContentEncoding: 'gzip', + }) +} + +// Client: Download pre-built index +async function loadPrebuiltIndex() { + const response = await fetch('https://cdn.example.com/search-index.json') + const serialized = await response.json() + return restore(serialized) // Orama's restore function +} +``` + +**Pros:** Fastest client load, CDN cached, consistent across users +**Cons:** Stale data (rebuild frequency), additional infrastructure + +--- + +#### 3.9 Search Architecture + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ CLIENT (Browser) │ +├─────────────────────────────────────────────────────────────────┤ +│ ┌──────────────────┐ ┌──────────────────────────────────┐ │ +│ │ Search Input │───>│ Orama In-Memory Index │ │ +│ │ (debounced) │ │ - 10k persons indexed │ │ +│ └──────────────────┘ │ - Fuzzy search, typo tolerance │ │ +│ │ - < 10ms response time │ │ +│ └──────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────────────────┐ │ +│ │ TanStack DB Collections │ │ +│ │ - Full person data on demand │ │ +│ │ - Paginated loading │ │ +│ └──────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ SERVER (Lambda) │ +├─────────────────────────────────────────────────────────────────┤ +│ Server Functions ←→ DynamoDB (Single-Table) │ +└─────────────────────────────────────────────────────────────────┘ +``` + +**Search Flow:** +1. On page load: Fetch all persons (paginated) → Build Orama index (~2-3s) +2. User types in search → Orama fuzzy search (< 10ms) +3. Results shown instantly with person IDs +4. Click result → Load full person data from TanStack DB collection + +### Phase 5: TanStack DB Collections with Server Functions + +#### 3.8 Create Server Functions & Collections +- [ ] Create `/src/webapp/db-collections/persons.ts` + - Define server functions for DynamoDB operations (co-located with collections) + - personsCollection - Base collection using server functions + - addressesCollection - Addresses collection + - bankAccountsCollection - Bank accounts collection + - contactInfosCollection - Contact info collection + - employmentsCollection - Employment history collection + +**Server Functions Pattern (replaces API routes):** + +```typescript +import { createServerFn } from '@tanstack/react-start' +import { createCollection } from '@tanstack/react-db' +import { queryCollectionOptions } from '@tanstack/query-db-collection' +import { createPersonsDdbClient } from '@/webapp/integrations/ddb-client/personsClient' + +// Server functions - no HTTP routes needed! +const fetchPersons = createServerFn({ method: 'GET' }) + .handler(async () => { + const client = createPersonsDdbClient() + return client.getPersons() + }) + +const createPerson = createServerFn({ method: 'POST' }) + .validator((data: Person) => personSchema.parse(data)) + .handler(async ({ data }) => { + const client = createPersonsDdbClient() + return client.putPerson(data) + }) + +const updatePersons = createServerFn({ method: 'POST' }) + .validator((data: PersonUpdate[]) => personUpdateSchema.array().parse(data)) + .handler(async ({ data }) => { + const client = createPersonsDdbClient() + return client.updatePersons(data) + }) + +const deletePersons = createServerFn({ method: 'POST' }) + .validator((data: string[]) => z.array(z.string()).parse(data)) + .handler(async ({ data }) => { + const client = createPersonsDdbClient() + return client.deletePersons(data) + }) + +// Collection uses server functions directly +export const personsCollection = createCollection( + queryCollectionOptions({ + id: 'persons', + queryKey: ['persons'], + queryFn: () => fetchPersons(), + queryClient: getContext().queryClient, + getKey: (item) => item.id, + + onInsert: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((m) => createPerson({ data: m.modified })) + ) + }, + + onUpdate: async ({ transaction }) => { + const updates = transaction.mutations.map((m) => ({ + id: m.key, + changes: m.changes, + })) + await updatePersons({ data: updates }) + }, + + onDelete: async ({ transaction }) => { + const ids = transaction.mutations.map((m) => m.key) + await deletePersons({ data: ids }) + }, + }) +) + +// Similar pattern for addresses, bankAccounts, contacts, employments... +``` + +**Benefits of Server Functions over API Routes:** +- ✅ No HTTP route files needed +- ✅ Type-safe end-to-end (input validation with Zod) +- ✅ Co-located with collections (better DX) +- ✅ Automatic serialization/deserialization +- ✅ Works with TanStack Start's SSR + +#### 3.7 Create Live Query Collections for Related Data +- [ ] Create derived collections using `createLiveQueryCollection` for: + - Filtering addresses by personId + - Filtering bank accounts by personId + - Combining person with related entities via joins + +**Live Query Collection Pattern (from docs):** + +```typescript +import { createLiveQueryCollection, eq } from '@tanstack/db' + +// Filter addresses for a specific person +const createPersonAddresses = (personId: string) => + createLiveQueryCollection((q) => + q + .from({ address: addressesCollection }) + .where(({ address }) => eq(address.personId, personId)) + .select(({ address }) => address) + ) + +// Join person with addresses (left join) +const personWithAddresses = createLiveQueryCollection((q) => + q + .from({ person: personsCollection }) + .join({ address: addressesCollection }, ({ person, address }) => + eq(person.id, address.personId) + ) + .select(({ person, address }) => ({ + ...person, + address, // Optional because it's a left join + })) +) +``` + +#### 3.10 Query Operators Reference +Available operators for filtering (from TanStack DB docs): + +```typescript +import { eq, gt, gte, lt, lte, like, ilike, inArray, and, or, not } from '@tanstack/db' + +// Examples +eq(user.id, '123') // Equality +gt(user.age, 18) // Greater than +gte(user.age, 18) // Greater than or equal +lt(user.age, 65) // Less than +lte(user.age, 65) // Less than or equal +like(user.name, 'John%') // Case-sensitive pattern matching +ilike(user.name, 'john%') // Case-insensitive pattern matching +inArray(user.id, ['1', '2']) // Array membership + +// Logical operators +and(condition1, condition2) +or(condition1, condition2) +not(condition) +``` + +### Phase 6: Hooks + +#### 3.11 Create React Hooks + - [x] Create `/src/webapp/hooks/useDbPersons.ts` + - `usePersons()` - List all persons using `useLiveQuery` + - `usePerson(personId)` - Single person with all related data + - `usePersonMutations()` - CRUD operations using collection methods + - `usePersonAddresses(personId)` - Addresses for a specific person + - `usePersonBankAccounts(personId)` - Bank accounts for a specific person + - Similar hooks for ContactInfo and Employment + +**useLiveQuery Pattern (from docs):** + +```typescript +import { useLiveQuery } from '@tanstack/react-db' +import { eq } from '@tanstack/db' + +// List all persons +export function usePersons() { + const { data: persons } = useLiveQuery((q) => + q + .from({ person: personsCollection }) + .select(({ person }) => person) + ) + return persons +} + +// Get person with addresses via join +export function usePersonWithAddresses(personId: string) { + const { data } = useLiveQuery((q) => + q + .from({ person: personsCollection }) + .join( + { address: addressesCollection }, + ({ person, address }) => eq(person.id, address.personId), + 'left' + ) + .where(({ person }) => eq(person.id, personId)) + .select(({ person, address }) => ({ + ...person, + address, + })) + ) + return data +} + +// Mutations use collection methods directly (optimistic by default) +export function usePersonMutations() { + const addPerson = (person: Omit) => { + personsCollection.insert({ + id: crypto.randomUUID(), + ...person, + }) + } + + const updatePerson = (id: string, changes: Partial) => { + personsCollection.update(id, (draft) => { + Object.assign(draft, changes) + }) + } + + const deletePerson = (id: string) => { + personsCollection.delete(id) + } + + return { addPerson, updatePerson, deletePerson } +} +``` + +**Non-Optimistic Mutations (when needed):** + +```typescript +// For operations requiring server confirmation +const handleDeleteAccount = () => { + personCollection.delete(personId, { optimistic: false }) +} + +// Server-generated data (IDs, timestamps, etc.) +const handleCreateWithServerData = () => { + personCollection.insert(personData, { optimistic: false }) +} +``` + +### Phase 7: UI Components (shadcn/ui) + +#### 3.12 Create UI Components (shadcn/ui) +- [ ] Create `/src/webapp/components/persons/PersonCard.tsx` + - Display person summary with inline edit capability +- [ ] Create `/src/webapp/components/persons/PersonForm.tsx` + - Form for creating/editing person profile +- [ ] Create `/src/webapp/components/persons/PersonSearchInput.tsx` + - Search input with debouncing for Orama search +- [ ] Create `/src/webapp/components/persons/AddressCard.tsx` + - Display address with inline editing +- [ ] Create `/src/webapp/components/persons/AddressForm.tsx` + - Form for adding/editing addresses +- [ ] Create `/src/webapp/components/persons/BankAccountCard.tsx` + - Display bank account (masked data) with inline editing +- [ ] Create `/src/webapp/components/persons/ContactInfoCard.tsx` + - Display contact info with inline editing +- [ ] Create `/src/webapp/components/persons/EmploymentCard.tsx` + - Display employment history with inline editing + +**Search Component Pattern (using TanStack Pacer):** + +```tsx +import { useState } from 'react' +import { useDebouncedValue } from '@tanstack/react-pacer' +import { searchPersons, usePersonSearch } from '@/webapp/integrations/orama/personSearch' + +// PersonSearchInput with TanStack Pacer debouncing +function PersonSearchInput({ + onResults +}: { + onResults: (results: SearchResult[]) => void +}) { + const [term, setTerm] = useState('') + const { searchIndex, isLoading } = usePersonSearch() + + // TanStack Pacer - debounce the search term + const [debouncedTerm, debouncer] = useDebouncedValue(term, { + wait: 200, // 200ms debounce + }, (state) => ({ isPending: state.isPending })) + + // Effect runs when debounced term changes + useEffect(() => { + async function performSearch() { + if (debouncedTerm.length >= 2 && searchIndex) { + const results = await searchPersons(searchIndex, debouncedTerm, { + limit: 20, + tolerance: 1, // Allow 1 typo + }) + onResults(results.hits) + } else { + onResults([]) + } + } + performSearch() + }, [debouncedTerm, searchIndex]) + + return ( +
+ setTerm(e.target.value)} + /> + {debouncer.state.isPending && ( + + Searching... + + )} +
+ ) +} +``` + +**Component Integration Pattern:** + +```tsx +// PersonCard with optimistic updates +function PersonCard({ person }: { person: Person }) { + const [isEditing, setIsEditing] = useState(false) + + const handleSave = (changes: Partial) => { + // Optimistic update - UI updates immediately + personsCollection.update(person.id, (draft) => { + Object.assign(draft, changes) + }) + setIsEditing(false) + } + + const handleDelete = () => { + personsCollection.delete(person.id) + } + + return ( + + {isEditing ? ( + + ) : ( + setIsEditing(true)} /> + )} + + ) +} +``` + +### Phase 8: Pages/Routes + +#### 3.13 Create Pages +- [ ] Create `/src/webapp/routes/demo/db-persons.tsx` + - **Search-first UI** with Orama fuzzy search + - Paginated list view (10k persons - must paginate!) + - Create new person button + +- [ ] Create `/src/webapp/routes/demo/db-persons.$personId.tsx` + - Detail view using shadcn/ui Tabs component + - Tabs: Profile | Addresses | Banking | Contacts | Employment + - Each tab uses `useLiveQuery` with joins for related data + - Inline edit/delete functionality for all entities + +**List Page with Orama Search Pattern:** + +```tsx +import { useState, useEffect } from 'react' +import { useNavigate } from '@tanstack/react-router' +import { searchPersons, usePersonSearch } from '@/webapp/integrations/orama/personSearch' + +function PersonsListPage() { + const navigate = useNavigate() + const [searchTerm, setSearchTerm] = useState('') + const [searchResults, setSearchResults] = useState([]) + const { searchIndex, isLoading } = usePersonSearch() + + // Debounced Orama search + useEffect(() => { + const timer = setTimeout(async () => { + if (searchTerm.length >= 2 && searchIndex) { + const results = await searchPersons(searchIndex, searchTerm, { + limit: 50, + tolerance: 1, // Typo tolerance + }) + setSearchResults(results.hits) + } else { + setSearchResults([]) + } + }, 200) + return () => clearTimeout(timer) + }, [searchTerm, searchIndex]) + + return ( +
+ setSearchTerm(e.target.value)} + /> + + {isLoading &&

Building search index...

} + + {searchResults.map((hit) => ( + navigate({ to: `/demo/db-persons/${hit.document.id}` })} + /> + ))} +
+ ) +} +``` + +**Detail Page with Live Query & Tabs Pattern:** + +```tsx +import { useLiveQuery } from '@tanstack/react-db' +import { eq } from '@tanstack/db' +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' + +function PersonDetailPage({ personId }: { personId: string }) { + // Live query with joins - automatically updates when data changes + const { data: personData } = useLiveQuery((q) => + q + .from({ person: personsCollection }) + .where(({ person }) => eq(person.id, personId)) + .select(({ person }) => person) + ) + + const { data: addresses } = useLiveQuery((q) => + q + .from({ address: addressesCollection }) + .where(({ address }) => eq(address.personId, personId)) + .select(({ address }) => address) + ) + + const person = personData?.[0] + if (!person) return + + return ( + + + Profile + Addresses ({addresses?.length}) + Banking + Contacts + Employment + + + + + + + + {addresses?.map((addr) => ( + + ))} + + + + {/* ... other tabs */} + + ) +} +``` + +### Phase 9: Data Seeding + +#### 3.14 Create Seed Script +- [ ] Create `/scripts/seed-persons.ts` + - Generate 10,000 persons with `@faker-js/faker` + - Batch write to DynamoDB (25 items per batch, handles retries) + - Progress reporting + - Idempotent (clear existing data option) + +- [ ] Add npm script in `package.json` + - `"seed:persons": "tsx scripts/seed-persons.ts"` + - `"seed:persons:clear": "tsx scripts/seed-persons.ts --clear"` + +**Seeding Script Pattern:** + +```typescript +// scripts/seed-persons.ts +import { faker } from '@faker-js/faker' +import { createPersonsDdbClient } from '../src/webapp/integrations/ddb-client/personsClient' + +const TOTAL_PERSONS = 10_000 +const BATCH_SIZE = 25 // DynamoDB limit + +async function seedPersons() { + const client = createPersonsDdbClient() + + console.log(`Seeding ${TOTAL_PERSONS} persons...`) + + for (let i = 0; i < TOTAL_PERSONS; i += BATCH_SIZE) { + const batch = Array.from({ length: Math.min(BATCH_SIZE, TOTAL_PERSONS - i) }, () => + generateFakePerson() + ) + + await client.batchWritePersons(batch) + + if ((i + BATCH_SIZE) % 1000 === 0) { + console.log(`Progress: ${Math.min(i + BATCH_SIZE, TOTAL_PERSONS)}/${TOTAL_PERSONS}`) + } + } + + console.log('Done!') +} + +seedPersons() +``` + +--- + +## 4. File Structure (New Files) + +``` +src/webapp/ +├── types/ +│ └── person.ts # All entity type definitions (Zod - SOURCE OF TRUTH) +├── data/ +│ └── fake-persons.ts # Fake data generator (@faker-js/faker) +├── db-collections/ +│ └── persons.ts # Server functions + TanStack DB collections +├── integrations/ +│ └── electrodb/ +│ ├── zod-to-electrodb.ts # Zod → ElectroDB schema converter +│ ├── entities.ts # ElectroDB entities (derived from Zod) +│ └── personsService.ts # ElectroDB Service for collection queries +├── hooks/ +│ └── useDbPersons.ts # React hooks for CRUD +├── components/ +│ └── persons/ +│ ├── PersonCard.tsx +│ ├── PersonForm.tsx +│ ├── AddressCard.tsx +│ ├── AddressForm.tsx +│ ├── BankAccountCard.tsx +│ ├── ContactInfoCard.tsx +│ └── EmploymentCard.tsx +└── routes/ + └── demo/ + ├── db-persons.tsx # Persons list page + └── db-persons.$personId.tsx # Person detail page + +scripts/ +└── seed-persons.ts # Data seeding script + +lib/constructs/ +└── DatabasePersons.ts # (Modified) Infrastructure updates +``` + +**Note:** No API route files needed - Server functions are co-located in `db-collections/persons.ts` + +--- + +## 5. Modified Files + +| File | Changes | +|------|---------| +| `/lib/constructs/DatabasePersons.ts` | Infrastructure setup (no GSI required for basic example) | +| `/lib/constructs/Webapp.ts` | Add `grantReadWriteData` for persons table | +| `/package.json` | Add seed script, add `@faker-js/faker` and `electrodb` dependencies | + +--- + +## 6. Implementation Order (Recommended) + +1. **Types & Schemas (Zod)** - Single source of truth for all types +2. **Fake Data Generator** - Needed for local dev and seeding +3. **CDK Updates** - Infrastructure changes (deploy after) +4. **Zod-to-ElectroDB Converter** - Utility to derive ElectroDB schemas from Zod +5. **ElectroDB Entities & Service** - Type-safe DynamoDB operations +6. **Collections + Server Functions** - TanStack DB integration (using ElectroDB) +7. **Hooks** - React integration +8. **UI Components** - Reusable components +9. **Pages** - Final UI assembly (simple list + detail views) +10. **Seed Script** - Populate DynamoDB with 10k persons (using ElectroDB batch) + +--- + +## 7. Questions / Decisions Needed + +All decisions have been made: + +1. **Fake Data Library**: ✅ **DECIDED** - Use `@faker-js/faker` library + +2. **UI Framework**: ✅ **DECIDED** - Use shadcn/ui components + +3. **Person Detail Layout**: ✅ **DECIDED** - Use tabs (Profile | Addresses | Banking | Contacts | Employment) + +4. **Inline Editing**: ✅ **DECIDED** - Enable inline editing for all entities + +5. **Optimistic Updates**: ✅ **DECIDED** - Yes, TanStack DB is optimistic by default + +6. **Person Profile Photo**: ✅ **DECIDED** - No profile photos needed + +7. **Data Volume**: ✅ **DECIDED** - 10,000 persons with batch seeding + +8. **Search**: ✅ **DECIDED** - Search functionality postponed to future branch + +--- + +## 8. Tech Stack Summary + +| Layer | Technology | +|-------|------------| +| Database | AWS DynamoDB (Single-Table Design) | +| **DynamoDB Client** | **ElectroDB (schemas derived from Zod)** | +| Backend | TanStack Start Server Functions | +| Data Fetching | TanStack Query + queryCollectionOptions | +| Local State | TanStack DB Collections with Live Queries | +| Optimistic Updates | TanStack DB (built-in via onInsert/onUpdate/onDelete handlers) | +| UI Framework | React + TailwindCSS + shadcn/ui | +| Type Safety | Zod + TypeScript | +| Infrastructure | AWS CDK | +| Fake Data | @faker-js/faker | + +--- + +## 9. Multi-User Data Synchronization + +### Sync Strategy: Polling + Refetch on Focus + +For the basic multi-entity example, use polling for simplicity: + +```typescript +// In persons collection definition +export const personsCollection = createCollection({ + ...queryCollectionOptions({ + queryKey: ['persons'], + queryFn: getAllPersons, + getId: (person) => person.id, + // TanStack Query options for sync + staleTime: 30_000, // Consider data fresh for 30s + refetchInterval: 60_000, // Poll every 60s for updates + refetchOnWindowFocus: true, // Refetch when user returns to tab + }), + onInsert: async (person) => { /* ... */ }, + onUpdate: async (person) => { /* ... */ }, + onDelete: async (id) => { /* ... */ }, +}) +``` + +**Benefits:** +- Simple to implement +- No additional AWS infrastructure needed +- Acceptable latency for person directory use case + +--- + +## 10. Future Enhancements (Search & Real-Time) + +### Search Implementation (Postponed) + +Full-text search across multi-entity data is planned for a future branch: + +- **Orama Search**: Client-side fuzzy search with typo tolerance +- **Cross-Entity Search**: Search across Person, Address, Contact, Employment, and BankAccount fields +- **Search Index Building**: Efficient data fetching via collection queries +- **TanStack Pacer**: Debouncing search input for optimized performance + +See future search branch for implementation details. + +### Real-Time Synchronization (Future) + +Alternative sync strategies for higher update frequency: + +- **WebSocket (API Gateway)**: For real-time updates via WebSocket +- **AppSync Subscriptions**: GraphQL subscriptions for real-time data +- **DynamoDB Streams**: Process changes via Lambda + DynamoDB Streams + +These are deferred to a specialized real-time branch. + +--- + +## 11. Estimated Timeline + +| Phase | Estimated Time | +|-------|---------------| +| Types & Fake Data | 2-3 hours | +| CDK Updates | 1 hour | +| ElectroDB Integration | 3-4 hours | +| Collections + Server Functions | 2-3 hours | +| Hooks | 1-2 hours | +| UI Components | 4-6 hours | +| Pages | 2-3 hours | +| Seed Script (10k) | 1-2 hours | +| Testing & Polish | 2-3 hours | +| **Total** | **18-26 hours** | + +### Why ElectroDB? +- **Type-safe DynamoDB operations** with fluent API +- **Single-table design** made easy with entities and services +- **Collection queries** to fetch related entities in one call +- **Automatic key generation** based on composite attributes +- **Built-in validation** that complements Zod + +### Zod-to-ElectroDB Schema Derivation + +The key insight: **Zod is the single source of truth**. ElectroDB schemas are derived from Zod schemas programmatically. + +```typescript +// /src/webapp/integrations/electrodb/zod-to-electrodb.ts +import { z } from 'zod' +import type { Attribute } from 'electrodb' + +type ElectroDBAttribute = { + type: 'string' | 'number' | 'boolean' | 'list' | 'map' | 'set' | readonly string[] + required?: boolean + default?: unknown +} + +/** + * Convert a Zod schema to ElectroDB attributes + * This ensures Zod is the single source of truth + */ +export function zodToElectroDBAttributes( + schema: z.ZodObject +): Record { + const shape = schema.shape + const attributes: Record = {} + + for (const [key, zodType] of Object.entries(shape)) { + attributes[key] = convertZodType(zodType as z.ZodTypeAny) + } + + return attributes as Record +} + +function convertZodType(zodType: z.ZodTypeAny): ElectroDBAttribute { + // Handle optional wrapper + if (zodType instanceof z.ZodOptional) { + const inner = convertZodType(zodType.unwrap()) + return { ...inner, required: false } + } + + // Handle nullable + if (zodType instanceof z.ZodNullable) { + const inner = convertZodType(zodType.unwrap()) + return { ...inner, required: false } + } + + // Handle default + if (zodType instanceof z.ZodDefault) { + const inner = convertZodType(zodType.removeDefault()) + return { ...inner, default: zodType._def.defaultValue() } + } + + // Handle primitives + if (zodType instanceof z.ZodString) { + return { type: 'string', required: true } + } + if (zodType instanceof z.ZodNumber) { + return { type: 'number', required: true } + } + if (zodType instanceof z.ZodBoolean) { + return { type: 'boolean', required: true } + } + + // Handle enums + if (zodType instanceof z.ZodEnum) { + return { type: zodType.options as readonly string[], required: true } + } + + // Handle arrays + if (zodType instanceof z.ZodArray) { + return { type: 'list', required: true } + } + + // Handle objects (nested) + if (zodType instanceof z.ZodObject) { + return { type: 'map', required: true } + } + + // Default to string + return { type: 'string', required: true } +} +``` + +### Using Derived Schemas in Entities + +```typescript +// /src/webapp/integrations/electrodb/entities.ts +import { Entity } from 'electrodb' +import { DynamoDBClient } from '@aws-sdk/client-dynamodb' +import { zodToElectroDBAttributes } from './zod-to-electrodb' +import { + PersonSchema, + AddressSchema, + // ... other schemas +} from '@/webapp/types/person' + +const client = new DynamoDBClient({}) +const table = process.env.DDB_PERSONS_TABLE_NAME! + +// Derive ElectroDB attributes from Zod schemas +const personAttributes = zodToElectroDBAttributes(PersonSchema.omit({ id: true })) +const addressAttributes = zodToElectroDBAttributes(AddressSchema.omit({ id: true, personId: true })) + +// Person Entity +export const PersonEntity = new Entity( + { + model: { + entity: 'person', + version: '1', + service: 'persons', + }, + attributes: { + personId: { type: 'string' }, + ...personAttributes, + }, + indexes: { + // Primary index - get person by ID + byPerson: { + pk: { field: 'pk', composite: ['personId'], template: 'PERSON#${personId}' }, + sk: { field: 'sk', composite: [], template: 'PROFILE' }, + }, + // GSI1 - list all persons + allPersons: { + index: 'GSI1', + pk: { field: 'gsi1pk', composite: [], template: 'PERSONS' }, + sk: { field: 'gsi1sk', composite: ['personId'], template: 'PERSON#${personId}' }, + }, + // GSI2 - list ALL entities for Orama search index (collection query) + allData: { + collection: 'allData', // Shared collection across all entities + index: 'GSI2', + pk: { field: 'gsi2pk', composite: [], template: 'ALL_DATA' }, + sk: { field: 'gsi2sk', composite: ['personId'], template: 'PERSON#${personId}#PROFILE' }, + }, + }, + }, + { client, table } +) + +// Address Entity +export const AddressEntity = new Entity( + { + model: { + entity: 'address', + version: '1', + service: 'persons', + }, + attributes: { + personId: { type: 'string' }, + addressId: { type: 'string' }, + ...addressAttributes, + }, + indexes: { + // Primary index - get addresses by person + byPerson: { + collection: 'personData', // Collection for querying single person's data + pk: { field: 'pk', composite: ['personId'], template: 'PERSON#${personId}' }, + sk: { field: 'sk', composite: ['addressId'], template: 'ADDRESS#${addressId}' }, + }, + // GSI2 - list ALL entities for Orama + allData: { + collection: 'allData', + index: 'GSI2', + pk: { field: 'gsi2pk', composite: [], template: 'ALL_DATA' }, + sk: { field: 'gsi2sk', composite: ['personId', 'addressId'], template: 'PERSON#${personId}#ADDRESS#${addressId}' }, + }, + }, + }, + { client, table } +) + +// BankAccountEntity, ContactInfoEntity, EmploymentEntity follow the same pattern: +// - Primary index with 'personData' collection for single person queries +// - GSI2 index with 'allData' collection for Orama bulk fetch +``` + +### ElectroDB Service for Collection Queries + +```typescript +// /src/webapp/integrations/electrodb/personsService.ts +import { Service } from 'electrodb' +import { PersonEntity, AddressEntity, BankAccountEntity, ContactInfoEntity, EmploymentEntity } from './entities' + +export const PersonsService = new Service({ + person: PersonEntity, + address: AddressEntity, + bankAccount: BankAccountEntity, + contactInfo: ContactInfoEntity, + employment: EmploymentEntity, +}) + +// Usage examples: + +// Get all persons (using GSI1) +const allPersons = await PersonEntity.query.allPersons({}).go() + +// Get person with all related data (collection query via primary index) +const personData = await PersonsService.collections.personData({ personId }).go() +// Returns: { person: [...], address: [...], bankAccount: [...], contactInfo: [...], employment: [...] } + +// 🔥 Get ALL entities for Orama search index (collection query via GSI2) +const allData = await PersonsService.collections.allData({}).go({ pages: 'all' }) +// Returns ALL entities across ALL persons in one query! +// { person: [10k items], address: [~20k items], contactInfo: [~30k items], ... } + +// Create a person +await PersonEntity.put({ personId, firstName, lastName, ... }).go() + +// Update a person +await PersonEntity.patch({ personId }).set({ firstName: 'New Name' }).go() + +// Delete a person and all related entities +await PersonEntity.delete({ personId }).go() +// Note: Related entities need separate deletion or use transactions + +// Batch operations +await PersonEntity.put([person1, person2, person3]).go() +``` + +### Benefits of Zod → ElectroDB Derivation + +1. **Single Source of Truth**: Update Zod schema once, ElectroDB follows +2. **Consistent Validation**: Zod validates at runtime, ElectroDB at persistence +3. **Type Safety**: TypeScript types flow from Zod to ElectroDB to client +4. **Less Boilerplate**: No need to maintain two separate schema definitions +5. **Reduced Errors**: Schema drift between Zod and DB is impossible + +--- + +## 11. TanStack DB Key Concepts + +### Collections +- **queryCollectionOptions**: For data synced with a backend API +- **localOnlyCollectionOptions**: For client-only data +- **liveQueryCollectionOptions**: For derived/filtered views of other collections + +### Mutations +- All mutations are **optimistic by default** - UI updates immediately +- Use `{ optimistic: false }` for server-confirmed operations +- Mutation handlers (`onInsert`, `onUpdate`, `onDelete`) sync to backend +- Failed mutations **automatically rollback** + +### Live Queries +- Use `useLiveQuery` hook in React components +- Queries are **reactive** - automatically update when underlying data changes +- Support **joins** for combining related collections +- Support **filtering** with operators (`eq`, `gt`, `lt`, `and`, `or`, etc.) + +### Best Practices +1. Create base collections with `queryCollectionOptions` for each entity type +2. Use `createLiveQueryCollection` for filtered/joined views +3. Keep mutation logic in collection handlers, not components +4. Use `useLiveQuery` for all data access in components + +--- + +## 11. Multi-User Data Synchronization + +### The Problem +When User B modifies data on the server (via their own browser), User A's: +1. **TanStack DB collection** still has stale data +2. **Orama search index** is out of sync + +### Sync Strategy Options + +| Strategy | Latency | Complexity | AWS Cost | +|----------|---------|------------|----------| +| **Polling** (recommended) | 5-30s | Low | Low | +| Refetch on Focus | User-dependent | Very Low | Very Low | +| WebSocket (API Gateway) | Real-time | High | Medium | +| AppSync Subscriptions | Real-time | Medium | Medium | +| DynamoDB Streams + SSE | Near real-time | High | Medium | + +### Recommended: Polling + Refetch on Focus + +For 10k persons with moderate update frequency, polling is the pragmatic choice: + +```typescript +// In persons collection definition +export const personsCollection = createCollection({ + ...queryCollectionOptions({ + queryKey: ['persons'], + queryFn: getAllPersons, + getId: (person) => person.id, + // TanStack Query options for sync + staleTime: 30_000, // Consider data fresh for 30s + refetchInterval: 60_000, // Poll every 60s for updates + refetchOnWindowFocus: true, // Refetch when user returns to tab + }), + onInsert: async (person) => { /* ... */ }, + onUpdate: async (person) => { /* ... */ }, + onDelete: async (id) => { /* ... */ }, +}) +``` + +### Syncing Orama Search Index with Collection + +The search index must stay in sync with the TanStack DB collection: + +```typescript +// usePersonSearch.ts - Sync Orama with collection state +import { useEffect, useRef, useState } from 'react' +import { useLiveQuery } from '@tanstack/db' +import { create, insertMultiple, removeMultiple } from '@orama/orama' +import { personsCollection } from '@/webapp/db-collections/persons' + +export function usePersonSearch() { + const [searchIndex, setSearchIndex] = useState(null) + const [isBuilding, setIsBuilding] = useState(true) + const lastSyncRef = useRef('') + + // Live query to watch collection changes + const persons = useLiveQuery(personsCollection, { + query: { + $select: ['id', 'firstName', 'lastName', 'email'], + }, + }) + + // Rebuild index when persons change + useEffect(() => { + async function syncIndex() { + if (!persons.data) return + + // Create hash of current data to detect changes + const dataHash = JSON.stringify(persons.data.map(p => p.id).sort()) + if (dataHash === lastSyncRef.current) return // No change + + setIsBuilding(true) + + // Full rebuild (simple, reliable for moderate update frequency) + const index = await create({ + schema: { + id: 'string', + firstName: 'string', + lastName: 'string', + fullName: 'string', + email: 'string', + }, + }) + + const docs = persons.data.map(p => ({ + id: p.id, + firstName: p.firstName, + lastName: p.lastName, + fullName: `${p.firstName} ${p.lastName}`, + email: p.email ?? '', + })) + + await insertMultiple(index, docs) + + setSearchIndex(index) + lastSyncRef.current = dataHash + setIsBuilding(false) + } + + syncIndex() + }, [persons.data]) + + return { + searchIndex, + isBuilding, + isLoading: persons.isLoading, + lastUpdated: persons.dataUpdatedAt, + } +} +``` + +### Alternative: Incremental Index Updates + +For higher update frequency, use Orama's incremental operations: + +```typescript +// Track and apply incremental changes +useEffect(() => { + if (!searchIndex || !persons.data) return + + const currentIds = new Set(persons.data.map(p => p.id)) + const indexedIds = new Set(/* track indexed IDs */) + + // Find additions and removals + const added = persons.data.filter(p => !indexedIds.has(p.id)) + const removed = [...indexedIds].filter(id => !currentIds.has(id)) + + if (added.length > 0) { + insertMultiple(searchIndex, added.map(toSearchDoc)) + } + if (removed.length > 0) { + removeMultiple(searchIndex, removed) + } +}, [persons.data, searchIndex]) +``` + +### Real-Time Option: AppSync Subscriptions (Future Enhancement) + +For true real-time sync, AWS AppSync with GraphQL subscriptions: + +```typescript +// Future: Real-time subscription +import { useSubscription } from '@/webapp/integrations/appsync' + +function useRealtimePersonSync() { + useSubscription({ + query: onPersonChanged, + onData: (event) => { + switch (event.type) { + case 'INSERT': + personsCollection.insert(event.person, { optimistic: false }) + break + case 'UPDATE': + personsCollection.update(event.person.id, () => event.person, { optimistic: false }) + break + case 'DELETE': + personsCollection.delete(event.person.id, { optimistic: false }) + break + } + }, + }) +} +``` + +### UI: Show Sync Status + +```tsx +function PersonsPage() { + const { lastUpdated, isLoading } = usePersonSearch() + + return ( +
+
+ Last synced: {formatRelative(lastUpdated)} + {isLoading && } + +
+ {/* ... */} +
+ ) +} +``` + +### Decision: Sync Strategy + +**✅ DECIDED: Polling + Refetch on Focus** +- `refetchInterval: 60_000` (poll every 60 seconds) +- `refetchOnWindowFocus: true` (immediate sync when user returns) +- Manual refresh button for user-triggered sync +- Orama index rebuilds when collection data changes (via `useLiveQuery`) + +**Rationale:** +- Simple to implement +- No additional AWS infrastructure needed +- Acceptable latency for person directory use case +- Full index rebuild is fast enough for 10k records (~2-3s) + +--- + +## 12. Estimated Timeline + +| Phase | Estimated Time | +|-------|---------------| +| Types & Fake Data | 2-3 hours | +| CDK Updates | 1 hour | +| DDB Client | 3-4 hours | +| Orama Search Integration | 1-2 hours | +| Collections + Server Functions | 2-3 hours | +| Hooks (incl. search) | 1-2 hours | +| UI Components | 4-6 hours | +| Pages | 2-3 hours | +| Seed Script (10k) | 1-2 hours | +| Testing & Polish | 2-3 hours | +| **Total** | **19-28 hours** | + +--- + +*Document created: December 23, 2025* +*Updated with TanStack DB documentation patterns* +*Updated with Orama search and 10,000 persons seeding* diff --git a/knip.json b/knip.json new file mode 100644 index 0000000..6829985 --- /dev/null +++ b/knip.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://unpkg.com/knip@5/schema.json", + "entry": [ + "src/webapp/router.tsx", + "src/webapp/routes/**/*.{ts,tsx}", + "bin/app.ts", + "lib/**/*.ts", + "scripts/**/*.ts" + ], + "project": [ + "src/webapp/**/*.{ts,tsx}", + "bin/**/*.ts", + "lib/**/*.ts", + "scripts/**/*.ts" + ], + "paths": { + "#src/*": ["./src/*"] + }, + "ignore": [ + "src/webapp/routeTree.gen.ts" + ], + "vite": { + "config": ["vite.config.ts"] + }, + "vitest": true, + "typescript": { + "config": ["tsconfig.json"] + } +} diff --git a/lib/constructs/DatabasePersons.ts b/lib/constructs/DatabasePersons.ts new file mode 100644 index 0000000..6dc335a --- /dev/null +++ b/lib/constructs/DatabasePersons.ts @@ -0,0 +1,33 @@ +import { AttributeType, BillingMode, ProjectionType, Table } from 'aws-cdk-lib/aws-dynamodb'; +import { Construct } from 'constructs'; + +export class DatabasePersons extends Construct { + public readonly dbPersons: Table; + constructor(scope: Construct, id: string) { + super(scope, id); + + this.dbPersons = new Table(this, 'Persons', { + partitionKey: { name: 'pk', type: AttributeType.STRING }, + sortKey: { name: 'sk', type: AttributeType.STRING }, + billingMode: BillingMode.PAY_PER_REQUEST, + }); + + // GSI1: For listing all persons + // Example gsi1pk = "PERSONS", gsi1sk = "PERSON#" + this.dbPersons.addGlobalSecondaryIndex({ + indexName: 'GSI1', + partitionKey: { name: 'gsi1pk', type: AttributeType.STRING }, + sortKey: { name: 'gsi1sk', type: AttributeType.STRING }, + projectionType: ProjectionType.ALL, + }); + + // GSI2: For fetching all entities (postponed until search implementation) + // Uncomment when search functionality is implemented + // THIS.dbPersons.addGlobalSecondaryIndex({ + // IndexName: 'GSI2', + // PartitionKey: { name: 'gsi2pk', type: AttributeType.STRING }, + // SortKey: { name: 'gsi2sk', type: AttributeType.STRING }, + // ProjectionType: ProjectionType.ALL, + // }); + } +} diff --git a/lib/constructs/Webapp.ts b/lib/constructs/Webapp.ts index 7dc9365..15b6ab9 100644 --- a/lib/constructs/Webapp.ts +++ b/lib/constructs/Webapp.ts @@ -1,4 +1,5 @@ import { Construct } from 'constructs'; +import { DatabasePersons } from './DatabasePersons.ts'; import { DatabaseTodos } from './DatabaseTodos.ts'; import { WebappApi } from './WebappApi.ts'; import { WebappAssetsBucket } from './WebappAssetsBucket.ts'; @@ -12,12 +13,15 @@ export class Webapp extends Construct { super(scope, id); const databaseTodos = new DatabaseTodos(this, 'DatabaseTodos'); + const databasePersons = new DatabasePersons(this, 'DatabasePersons'); const webappServer = new WebappServer(this, 'WebappServer', { - tableName: databaseTodos.dbTodos.tableName, + tableNameTodos: databaseTodos.dbTodos.tableName, + tableNamePersons: databasePersons.dbPersons.tableName, }); databaseTodos.dbTodos.grantReadWriteData(webappServer.webappServer); + databasePersons.dbPersons.grantReadWriteData(webappServer.webappServer); const webappServerFunctionUrl = new WebappFunctionUrl(this, 'WebappServerFunctionUrl', { webappServer: webappServer.webappServer, diff --git a/lib/constructs/WebappServer.ts b/lib/constructs/WebappServer.ts index bca7ff1..858c0e3 100644 --- a/lib/constructs/WebappServer.ts +++ b/lib/constructs/WebappServer.ts @@ -5,7 +5,8 @@ import { Construct } from 'constructs'; import path from 'node:path'; type WebappServerProps = { - tableName: string; + tableNameTodos: string; + tableNamePersons: string; }; export class WebappServer extends Construct { readonly webappServer: Function; @@ -13,7 +14,7 @@ export class WebappServer extends Construct { constructor(scope: Construct, id: string, props: WebappServerProps) { super(scope, id); - const { tableName } = props; + const { tableNameTodos, tableNamePersons } = props; this.webappServer = new Function(this, 'WebappServer', { code: Code.fromAsset( @@ -26,7 +27,8 @@ export class WebappServer extends Construct { // oxlint-disable-next-line no-magic-numbers timeout: Duration.seconds(60), environment: { - DDB_TODOS_TABLE_NAME: tableName, + DDB_TODOS_TABLE_NAME: tableNameTodos, + DDB_PERSONS_TABLE_NAME: tableNamePersons, }, }); Tags.of(this.webappServer).add('IsWebAppServer', 'true'); diff --git a/package.json b/package.json index 46b2e76..8e55511 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,9 @@ "name": "tanstack-aws", "private": true, "type": "module", + "imports": { + "#src/*": "./src/*" + }, "scripts": { "webapp:dev": "vite dev --port 3000", "webapp:build": "vite build", @@ -11,35 +14,40 @@ "lint:fix": "pnpm lint --fix", "format": "oxfmt . -c .oxfmtrc.json", "format:check": "pnpm format --check", - "cdk": "cdk" + "knip": "knip", + "knip:fix": "knip --fix", + "cdk": "cdk", + "seed:persons": "node scripts/seed-persons.ts", + "compile": "tsc" }, "dependencies": { - "@ai-sdk/amazon-bedrock": "3.0.70", - "@ai-sdk/anthropic": "^2.0.56", - "@ai-sdk/mcp": "^0.0.12", - "@ai-sdk/react": "^2.0.117", - "@aws-sdk/client-dynamodb": "^3.879.0", - "@aws-sdk/lib-dynamodb": "^3.879.0", - "@modelcontextprotocol/sdk": "^1.25.1", + "@ai-sdk/amazon-bedrock": "3.0.72", + "@ai-sdk/react": "^3.0.3", + "@aws-sdk/client-dynamodb": "^3.958.0", + "@aws-sdk/lib-dynamodb": "^3.958.0", + "@faker-js/faker": "^10.1.0", + "@radix-ui/react-slot": "^1.2.4", "@tailwindcss/vite": "^4.1.18", - "@tanstack/query-db-collection": "^1.0.8", - "@tanstack/react-db": "0.1.56", - "@tanstack/react-devtools": "^0.8.4", + "@tanstack/query-db-collection": "^1.0.12", + "@tanstack/react-db": "0.1.60", + "@tanstack/react-devtools": "^0.8.6", + "@tanstack/react-form": "^1.11.0", "@tanstack/react-query": "^5.90.12", "@tanstack/react-query-devtools": "^5.84.2", - "@tanstack/react-router": "^1.141.6", - "@tanstack/react-router-devtools": "^1.141.6", - "@tanstack/react-router-ssr-query": "^1.141.6", - "@tanstack/react-start": "^1.141.7", + "@tanstack/react-router": "^1.143.4", + "@tanstack/react-router-devtools": "^1.143.4", + "@tanstack/react-router-ssr-query": "^1.143.4", + "@tanstack/react-start": "^1.143.4", "@tanstack/react-store": "^0.8.0", - "@tanstack/router-plugin": "^1.141.7", + "@tanstack/react-table": "^8.21.3", "@tanstack/store": "^0.8.0", - "@trpc/client": "^11.8.0", - "@trpc/server": "^11.8.0", - "@trpc/tanstack-react-query": "^11.8.0", - "ai": "^5.0.115", + "@trpc/client": "^11.8.1", + "@trpc/server": "^11.8.1", + "@trpc/tanstack-react-query": "^11.8.1", + "ai": "^6.0.3", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "electrodb": "^3.5.0", "highlight.js": "^11.11.1", "lucide-react": "^0.562.0", "nitro": "3.0.1-alpha.1", @@ -49,31 +57,28 @@ "superjson": "^2.2.2", "tailwind-merge": "^3.0.2", "tailwindcss": "^4.1.18", - "tw-animate-css": "^1.3.6", + "tw-animate-css": "^1.4.0", "vite-tsconfig-paths": "^6.0.3", "zod": "^4.2.1" }, "devDependencies": { "@tanstack/devtools-event-client": "^0.4.0", "@tanstack/devtools-vite": "^0.3.12", - "@testing-library/dom": "^10.4.0", - "@testing-library/react": "^16.3.1", "@types/node": "^25.0.3", "@types/react": "^19.2.0", "@types/react-dom": "^19.2.0", "@vitejs/plugin-react": "^5.1.2", "aws-cdk": "^2.1100.1", - "aws-cdk-lib": "2.232.2", - "cdk-nag": "^2.37.55", + "aws-cdk-lib": "2.233.0", + "babel-plugin-react-compiler": "^1.0.0", "constructs": "^10.4.4", - "eslint-cdk-plugin": "^3.4.7", "jsdom": "^27.3.0", - "oxfmt": "0.18.0", - "oxlint": "1.33.0", - "oxlint-tsgolint": "^0.9.1", + "knip": "5.77.1", + "oxfmt": "0.20.0", + "oxlint": "1.35.0", + "oxlint-tsgolint": "^0.10.0", "typescript": "5.9.3", - "vite": "8.0.0-beta.0", - "vitest": "^4.0.16", - "web-vitals": "^5.1.0" + "vite": "8.0.0-beta.4", + "vitest": "^4.0.16" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 24edff8..74d9959 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,38 +9,38 @@ importers: .: dependencies: '@ai-sdk/amazon-bedrock': - specifier: 3.0.70 - version: 3.0.70(zod@4.2.1) - '@ai-sdk/anthropic': - specifier: ^2.0.56 - version: 2.0.56(zod@4.2.1) - '@ai-sdk/mcp': - specifier: ^0.0.12 - version: 0.0.12(zod@4.2.1) + specifier: 3.0.72 + version: 3.0.72(zod@4.2.1) '@ai-sdk/react': - specifier: ^2.0.117 - version: 2.0.117(react@19.2.3)(zod@4.2.1) + specifier: ^3.0.3 + version: 3.0.3(react@19.2.3)(zod@4.2.1) '@aws-sdk/client-dynamodb': - specifier: ^3.879.0 - version: 3.954.0 + specifier: ^3.958.0 + version: 3.958.0 '@aws-sdk/lib-dynamodb': - specifier: ^3.879.0 - version: 3.954.0(@aws-sdk/client-dynamodb@3.954.0) - '@modelcontextprotocol/sdk': - specifier: ^1.25.1 - version: 1.25.1(hono@4.11.1)(zod@4.2.1) + specifier: ^3.958.0 + version: 3.958.0(@aws-sdk/client-dynamodb@3.958.0) + '@faker-js/faker': + specifier: ^10.1.0 + version: 10.1.0 + '@radix-ui/react-slot': + specifier: ^1.2.4 + version: 1.2.4(@types/react@19.2.7)(react@19.2.3) '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + version: 4.1.18(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) '@tanstack/query-db-collection': - specifier: ^1.0.8 - version: 1.0.8(@tanstack/query-core@5.90.12)(typescript@5.9.3) + specifier: ^1.0.12 + version: 1.0.12(@tanstack/query-core@5.90.12)(typescript@5.9.3) '@tanstack/react-db': - specifier: 0.1.56 - version: 0.1.56(react@19.2.3)(typescript@5.9.3) + specifier: 0.1.60 + version: 0.1.60(react@19.2.3)(typescript@5.9.3) '@tanstack/react-devtools': - specifier: ^0.8.4 - version: 0.8.4(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10) + specifier: ^0.8.6 + version: 0.8.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10) + '@tanstack/react-form': + specifier: ^1.11.0 + version: 1.27.6(@tanstack/react-start@1.143.4(crossws@0.4.1(srvx@0.9.7))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-query': specifier: ^5.90.12 version: 5.90.12(react@19.2.3) @@ -48,44 +48,47 @@ importers: specifier: ^5.84.2 version: 5.91.1(@tanstack/react-query@5.90.12(react@19.2.3))(react@19.2.3) '@tanstack/react-router': - specifier: ^1.141.6 - version: 1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + specifier: ^1.143.4 + version: 1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-router-devtools': - specifier: ^1.141.6 - version: 1.141.6(@tanstack/react-router@1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.141.6)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10) + specifier: ^1.143.4 + version: 1.143.4(@tanstack/react-router@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.143.4)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10) '@tanstack/react-router-ssr-query': - specifier: ^1.141.6 - version: 1.141.6(@tanstack/query-core@5.90.12)(@tanstack/react-query@5.90.12(react@19.2.3))(@tanstack/react-router@1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.141.6)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + specifier: ^1.143.4 + version: 1.143.4(@tanstack/query-core@5.90.12)(@tanstack/react-query@5.90.12(react@19.2.3))(@tanstack/react-router@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.143.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-start': - specifier: ^1.141.7 - version: 1.141.7(crossws@0.4.1(srvx@0.9.7))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + specifier: ^1.143.4 + version: 1.143.4(crossws@0.4.1(srvx@0.9.7))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) '@tanstack/react-store': specifier: ^0.8.0 version: 0.8.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/router-plugin': - specifier: ^1.141.7 - version: 1.141.7(@tanstack/react-router@1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + '@tanstack/react-table': + specifier: ^8.21.3 + version: 8.21.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/store': specifier: ^0.8.0 version: 0.8.0 '@trpc/client': - specifier: ^11.8.0 - version: 11.8.0(@trpc/server@11.8.0(typescript@5.9.3))(typescript@5.9.3) + specifier: ^11.8.1 + version: 11.8.1(@trpc/server@11.8.1(typescript@5.9.3))(typescript@5.9.3) '@trpc/server': - specifier: ^11.8.0 - version: 11.8.0(typescript@5.9.3) + specifier: ^11.8.1 + version: 11.8.1(typescript@5.9.3) '@trpc/tanstack-react-query': - specifier: ^11.8.0 - version: 11.8.0(@tanstack/react-query@5.90.12(react@19.2.3))(@trpc/client@11.8.0(@trpc/server@11.8.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.8.0(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + specifier: ^11.8.1 + version: 11.8.1(@tanstack/react-query@5.90.12(react@19.2.3))(@trpc/client@11.8.1(@trpc/server@11.8.1(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.8.1(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3) ai: - specifier: ^5.0.115 - version: 5.0.115(zod@4.2.1) + specifier: ^6.0.3 + version: 6.0.3(zod@4.2.1) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 clsx: specifier: ^2.1.1 version: 2.1.1 + electrodb: + specifier: ^3.5.0 + version: 3.5.0(@aws-sdk/client-dynamodb@3.958.0) highlight.js: specifier: ^11.11.1 version: 11.11.1 @@ -94,7 +97,7 @@ importers: version: 0.562.0(react@19.2.3) nitro: specifier: 3.0.1-alpha.1 - version: 3.0.1-alpha.1(aws4fetch@1.0.20)(lru-cache@11.2.4)(rollup@4.53.5)(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + version: 3.0.1-alpha.1(aws4fetch@1.0.20)(lru-cache@11.2.4)(rollup@4.53.5)(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) react: specifier: ^19.2.3 version: 19.2.3 @@ -114,11 +117,11 @@ importers: specifier: ^4.1.18 version: 4.1.18 tw-animate-css: - specifier: ^1.3.6 + specifier: ^1.4.0 version: 1.4.0 vite-tsconfig-paths: specifier: ^6.0.3 - version: 6.0.3(typescript@5.9.3)(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + version: 6.0.3(typescript@5.9.3)(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) zod: specifier: ^4.2.1 version: 4.2.1 @@ -128,13 +131,7 @@ importers: version: 0.4.0 '@tanstack/devtools-vite': specifier: ^0.3.12 - version: 0.3.12(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) - '@testing-library/dom': - specifier: ^10.4.0 - version: 10.4.1 - '@testing-library/react': - specifier: ^16.3.1 - version: 16.3.1(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + version: 0.3.12(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) '@types/node': specifier: ^25.0.3 version: 25.0.3 @@ -146,54 +143,51 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^5.1.2 - version: 5.1.2(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + version: 5.1.2(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) aws-cdk: specifier: ^2.1100.1 version: 2.1100.1 aws-cdk-lib: - specifier: 2.232.2 - version: 2.232.2(constructs@10.4.4) - cdk-nag: - specifier: ^2.37.55 - version: 2.37.55(aws-cdk-lib@2.232.2(constructs@10.4.4))(constructs@10.4.4) + specifier: 2.233.0 + version: 2.233.0(constructs@10.4.4) + babel-plugin-react-compiler: + specifier: ^1.0.0 + version: 1.0.0 constructs: specifier: ^10.4.4 version: 10.4.4 - eslint-cdk-plugin: - specifier: ^3.4.7 - version: 3.4.7(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) jsdom: specifier: ^27.3.0 version: 27.3.0 + knip: + specifier: 5.77.1 + version: 5.77.1(@types/node@25.0.3)(typescript@5.9.3) oxfmt: - specifier: 0.18.0 - version: 0.18.0 + specifier: 0.20.0 + version: 0.20.0 oxlint: - specifier: 1.33.0 - version: 1.33.0(oxlint-tsgolint@0.9.1) + specifier: 1.35.0 + version: 1.35.0(oxlint-tsgolint@0.10.0) oxlint-tsgolint: - specifier: ^0.9.1 - version: 0.9.1 + specifier: ^0.10.0 + version: 0.10.0 typescript: specifier: 5.9.3 version: 5.9.3 vite: - specifier: 8.0.0-beta.0 - version: 8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) + specifier: 8.0.0-beta.4 + version: 8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) vitest: specifier: ^4.0.16 version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@25.0.3)(jiti@2.6.1)(jsdom@27.3.0)(lightningcss@1.30.2)(tsx@4.21.0) - web-vitals: - specifier: ^5.1.0 - version: 5.1.0 packages: '@acemir/cssom@0.9.29': resolution: {integrity: sha512-G90x0VW+9nW4dFajtjCoT+NM0scAfH9Mb08IcjgFHYbfiL/lU04dTF9JuVOi3/OH+DJCQdcIseSXkdCB9Ky6JA==} - '@ai-sdk/amazon-bedrock@3.0.70': - resolution: {integrity: sha512-4NIBlwuS/iLKq2ynOqqyJ9imk/oyHuOzhBx88Bfm5I0ihQPKJ0dMMD1IKKuyDZvLRYKmlOEpa//P+/ZBp10drw==} + '@ai-sdk/amazon-bedrock@3.0.72': + resolution: {integrity: sha512-NUDgTtSbaQ1le8U1F7g79hmDlk0wwH+BKnzKpWF9ShO8SaYib7I2XUAik5STRAmDmbjfUNTtLQx+fizHUzCkBQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -204,20 +198,20 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/gateway@2.0.22': - resolution: {integrity: sha512-6fHjDfCbjfj4vyMExuLei7ir2///E5sNwNZaobdJsJIxJjDSsjzSLGO/aUI7p9eOnB8XctDrDSF5ilwDGpi6eg==} + '@ai-sdk/gateway@3.0.2': + resolution: {integrity: sha512-giJEg9ob45htbu3iautK+2kvplY2JnTj7ir4wZzYSQWvqGatWfBBfDuNCU5wSJt9BCGjymM5ZS9ziD42JGCZBw==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/mcp@0.0.12': - resolution: {integrity: sha512-hyf31U2CmgGexqOLgLfno525pjbqidJLu9pU+XcEwW/PkMcfTFuRq1iD3wbqtAmURRW0qJITiKV+in1B4I23gA==} + '@ai-sdk/provider-utils@3.0.19': + resolution: {integrity: sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider-utils@3.0.19': - resolution: {integrity: sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA==} + '@ai-sdk/provider-utils@4.0.1': + resolution: {integrity: sha512-de2v8gH9zj47tRI38oSxhQIewmNc+OZjYIOOaMoVWKL65ERSav2PYYZHPSPCrfOeLMkv+Dyh8Y0QGwkO29wMWQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -226,15 +220,15 @@ packages: resolution: {integrity: sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==} engines: {node: '>=18'} - '@ai-sdk/react@2.0.117': - resolution: {integrity: sha512-qfwz4p1ev+i/M9rsOUEe53UgzxMUz7e4wrImWdkuFrpD78MBIj53eE/LtyCeAYSCFVSz3JfIDvtdk5MjTrNcbA==} + '@ai-sdk/provider@3.0.0': + resolution: {integrity: sha512-m9ka3ptkPQbaHHZHqDXDF9C9B5/Mav0KTdky1k2HZ3/nrW2t1AgObxIVPyGDWQNS9FXT/FS6PIoSjpcP/No8rQ==} + engines: {node: '>=18'} + + '@ai-sdk/react@3.0.3': + resolution: {integrity: sha512-mLIgQuBdIX9gxCYQN3Pv/J8ARoFreIKYr/TVQtI+FwEzejuGFimTyhDln7UIBfrnm3Mpn1xENIWZfDfCRF7wkw==} engines: {node: '>=18'} peerDependencies: react: ^18 || ~19.0.1 || ~19.1.2 || ^19.2.1 - zod: ^3.25.76 || ^4.1.8 - peerDependenciesMeta: - zod: - optional: true '@antfu/install-pkg@1.1.0': resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} @@ -278,104 +272,100 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-dynamodb@3.954.0': - resolution: {integrity: sha512-QhdiE3W9jC8wAmkjQhiwDBdpaK3/y/kc9aXfTyj8TaPP+B39zt56zA0VT4GtmXauyiYb81qcvKIjIDTvr95Y4A==} + '@aws-sdk/client-dynamodb@3.958.0': + resolution: {integrity: sha512-R3G5cxf3fsL0CEcTbY1VkSwU1FJtImrhA5I9Eepd8nEO6isZ6C99qVKZtDG9eG7qVNK6zTzUigXac/GFrn6hYA==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-sso@3.954.0': - resolution: {integrity: sha512-FVyMAvlFhLK68DHWB1lSkCRTm25xl38bIZDd+jKt5+yDolCrG5+n9aIN8AA8jNO1HNGhZuMjSIQm9r5rGmJH8g==} + '@aws-sdk/client-sso@3.958.0': + resolution: {integrity: sha512-6qNCIeaMzKzfqasy2nNRuYnMuaMebCcCPP4J2CVGkA8QYMbIVKPlkn9bpB20Vxe6H/r3jtCCLQaOJjVTx/6dXg==} engines: {node: '>=18.0.0'} - '@aws-sdk/core@3.954.0': - resolution: {integrity: sha512-5oYO5RP+mvCNXNj8XnF9jZo0EP0LTseYOJVNQYcii1D9DJqzHL3HJWurYh7cXxz7G7eDyvVYA01O9Xpt34TdoA==} + '@aws-sdk/core@3.957.0': + resolution: {integrity: sha512-DrZgDnF1lQZv75a52nFWs6MExihJF2GZB6ETZRqr6jMwhrk2kbJPUtvgbifwcL7AYmVqHQDJBrR/MqkwwFCpiw==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-env@3.954.0': - resolution: {integrity: sha512-2HNkqBjfsvyoRuPAiFh86JBFMFyaCNhL4VyH6XqwTGKZffjG7hdBmzXPy7AT7G3oFh1k/1Zc27v0qxaKoK7mBA==} + '@aws-sdk/credential-provider-env@3.957.0': + resolution: {integrity: sha512-475mkhGaWCr+Z52fOOVb/q2VHuNvqEDixlYIkeaO6xJ6t9qR0wpLt4hOQaR6zR1wfZV0SlE7d8RErdYq/PByog==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-http@3.954.0': - resolution: {integrity: sha512-CrWD5300+NE1OYRnSVDxoG7G0b5cLIZb7yp+rNQ5Jq/kqnTmyJXpVAsivq+bQIDaGzPXhadzpAMIoo7K/aHaag==} + '@aws-sdk/credential-provider-http@3.957.0': + resolution: {integrity: sha512-8dS55QHRxXgJlHkEYaCGZIhieCs9NU1HU1BcqQ4RfUdSsfRdxxktqUKgCnBnOOn0oD3PPA8cQOCAVgIyRb3Rfw==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-ini@3.954.0': - resolution: {integrity: sha512-WAFD8pVwRSoBsuXcoD+s/hrdsP9Z0PNUedSgkOGExuJVAabpM2cIIMzYNsdHio9XFZUSqHkv8mF5mQXuIZvuzg==} + '@aws-sdk/credential-provider-ini@3.958.0': + resolution: {integrity: sha512-u7twvZa1/6GWmPBZs6DbjlegCoNzNjBsMS/6fvh5quByYrcJr/uLd8YEr7S3UIq4kR/gSnHqcae7y2nL2bqZdg==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-login@3.954.0': - resolution: {integrity: sha512-EYqaBWwdVbVK7prmsmgTWLPptoWREplPkFMFscOpVmseDvf/0IjYNbNLLtfuhy/6L7ZBGI9wat2k4u0MRivvxA==} + '@aws-sdk/credential-provider-login@3.958.0': + resolution: {integrity: sha512-sDwtDnBSszUIbzbOORGh5gmXGl9aK25+BHb4gb1aVlqB+nNL2+IUEJA62+CE55lXSH8qXF90paivjK8tOHTwPA==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-node@3.954.0': - resolution: {integrity: sha512-UPBjw7Lnly5i+/rES8Z5U+nPaumzEUYOE/wrHkxyH6JjwFWn8w7R07fE5Z5cgYlIq1U1lQ7sxYwB3wHPpQ65Aw==} + '@aws-sdk/credential-provider-node@3.958.0': + resolution: {integrity: sha512-vdoZbNG2dt66I7EpN3fKCzi6fp9xjIiwEA/vVVgqO4wXCGw8rKPIdDUus4e13VvTr330uQs2W0UNg/7AgtquEQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-process@3.954.0': - resolution: {integrity: sha512-Y1/0O2LgbKM8iIgcVj/GNEQW6p90LVTCOzF2CI1pouoKqxmZ/1F7F66WHoa6XUOfKaCRj/R6nuMR3om9ThaM5A==} + '@aws-sdk/credential-provider-process@3.957.0': + resolution: {integrity: sha512-/KIz9kadwbeLy6SKvT79W81Y+hb/8LMDyeloA2zhouE28hmne+hLn0wNCQXAAupFFlYOAtZR2NTBs7HBAReJlg==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-sso@3.954.0': - resolution: {integrity: sha512-UXxGfkp/plFRdyidMLvNul5zoLKmHhVQOCrD2OgR/lg9jNqNmJ7abF+Qu8abo902iDkhU21Qj4M398cx6l8Kng==} + '@aws-sdk/credential-provider-sso@3.958.0': + resolution: {integrity: sha512-CBYHJ5ufp8HC4q+o7IJejCUctJXWaksgpmoFpXerbjAso7/Fg7LLUu9inXVOxlHKLlvYekDXjIUBXDJS2WYdgg==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-web-identity@3.954.0': - resolution: {integrity: sha512-XEyf1T08q1tG4zkTS4Dnf1cAQyrJUo/xlvi6XNpqGhY3bOmKUYE2h/K6eITIdytDL9VuCpWYQ6YRcIVtL29E0w==} + '@aws-sdk/credential-provider-web-identity@3.958.0': + resolution: {integrity: sha512-dgnvwjMq5Y66WozzUzxNkCFap+umHUtqMMKlr8z/vl9NYMLem/WUbWNpFFOVFWquXikc+ewtpBMR4KEDXfZ+KA==} engines: {node: '>=18.0.0'} - '@aws-sdk/dynamodb-codec@3.954.0': - resolution: {integrity: sha512-fNY0L1l9e36pLJef4NY5k7Q1SJnm5rgLSxSRPT8xL+bhQBtEn2E2t4JdBiTqlxgeyuOrafWOawbg8yS3pRPcLw==} + '@aws-sdk/dynamodb-codec@3.957.0': + resolution: {integrity: sha512-xds1mkwEGzXrNy/gT6/ehaJ+cbYn/QM7AkdwNrO1NBlwJVLo3imO6hOnOQ/0KWG2ck1dbKv9H9f2hka67bAzEA==} engines: {node: '>=18.0.0'} peerDependencies: - '@aws-sdk/client-dynamodb': ^3.954.0 + '@aws-sdk/client-dynamodb': ^3.957.0 - '@aws-sdk/endpoint-cache@3.953.0': - resolution: {integrity: sha512-pz67DoHk5WNmvMuyNDiomUS2xo0mq6Z3TdfLJZlWVbSKi3h8hYxVQchJ2kzgTr6wu6zt3UBbtKV9yY1IBhKMVA==} + '@aws-sdk/endpoint-cache@3.957.0': + resolution: {integrity: sha512-QxvFejXYYBZp/GBfT7B15gvmvuq+0f2U8RPHqArf5IqBi51ZyBqUD805tQ8TlsVrlLoi+Z4fEFw4HEM5pGvPUg==} engines: {node: '>=18.0.0'} - '@aws-sdk/lib-dynamodb@3.954.0': - resolution: {integrity: sha512-DBEzAW7WfvNy6bQ32TfpvuFSVewj5eE8O1sTQWfvylNSZu81u6sPwb+eHPEclbvC84zAANl72JnkETOIkL4r8g==} + '@aws-sdk/lib-dynamodb@3.958.0': + resolution: {integrity: sha512-ojqEe4ojhk/MINaaEzqFLcZ9abBGP+zwUxTJh9x2mM2Y7Y4Gvqmwvs5aT790pI8yiPKPDkeF/E+DNEmSCUPtlA==} engines: {node: '>=18.0.0'} peerDependencies: - '@aws-sdk/client-dynamodb': ^3.954.0 - - '@aws-sdk/middleware-endpoint-discovery@3.953.0': - resolution: {integrity: sha512-/YKB1/OiWr7TwOfmkqzv8x1xgOpU71yciQTfsq6erB3dTQhdukPADt/CMJOhWFKC6Q1D5cDN8381nsGmnNuBVg==} - engines: {node: '>=18.0.0'} + '@aws-sdk/client-dynamodb': ^3.958.0 - '@aws-sdk/middleware-host-header@3.953.0': - resolution: {integrity: sha512-jTGhfkONav+r4E6HLOrl5SzBqDmPByUYCkyB/c/3TVb8jX3wAZx8/q9bphKpCh+G5ARi3IdbSisgkZrJYqQ19Q==} + '@aws-sdk/middleware-endpoint-discovery@3.957.0': + resolution: {integrity: sha512-MJjlw4mVJNTyR5dW6wpzKLRzFPIYAMA8qUWqgG4hGscmm4GFHvWVJ9mhhdpDu7Ie4Uaikmzfy0C4xzZ+lkf1+w==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-logger@3.953.0': - resolution: {integrity: sha512-PlWdVYgcuptkIC0ZKqVUhWNtSHXJSx7U9V8J7dJjRmsXC40X7zpEycvrkzDMJjeTDGcCceYbyYAg/4X1lkcIMw==} + '@aws-sdk/middleware-host-header@3.957.0': + resolution: {integrity: sha512-BBgKawVyfQZglEkNTuBBdC3azlyqNXsvvN4jPkWAiNYcY0x1BasaJFl+7u/HisfULstryweJq/dAvIZIxzlZaA==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-recursion-detection@3.953.0': - resolution: {integrity: sha512-cmIJx0gWeesUKK4YwgE+VQL3mpACr3/J24fbwnc1Z5tntC86b+HQFzU5vsBDw6lLwyD46dBgWdsXFh1jL+ZaFw==} + '@aws-sdk/middleware-logger@3.957.0': + resolution: {integrity: sha512-w1qfKrSKHf9b5a8O76yQ1t69u6NWuBjr5kBX+jRWFx/5mu6RLpqERXRpVJxfosbep7k3B+DSB5tZMZ82GKcJtQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-user-agent@3.954.0': - resolution: {integrity: sha512-5PX8JDe3dB2+MqXeGIhmgFnm2rbVsSxhz+Xyuu1oxLtbOn+a9UDA+sNBufEBjt3UxWy5qwEEY1fxdbXXayjlGg==} + '@aws-sdk/middleware-recursion-detection@3.957.0': + resolution: {integrity: sha512-D2H/WoxhAZNYX+IjkKTdOhOkWQaK0jjJrDBj56hKjU5c9ltQiaX/1PqJ4dfjHntEshJfu0w+E6XJ+/6A6ILBBA==} engines: {node: '>=18.0.0'} - '@aws-sdk/nested-clients@3.954.0': - resolution: {integrity: sha512-JLUhf35fTQIDPLk6G5KPggL9tV//Hjhy6+N2zZeis76LuBRNhKDq8z1CFyKhjf00vXi/tDYdn9D7y9emI+5Y/g==} + '@aws-sdk/middleware-user-agent@3.957.0': + resolution: {integrity: sha512-50vcHu96XakQnIvlKJ1UoltrFODjsq2KvtTgHiPFteUS884lQnK5VC/8xd1Msz/1ONpLMzdCVproCQqhDTtMPQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/region-config-resolver@3.953.0': - resolution: {integrity: sha512-5MJgnsc+HLO+le0EK1cy92yrC7kyhGZSpaq8PcQvKs9qtXCXT5Tb6tMdkr5Y07JxYsYOV1omWBynvL6PWh08tQ==} + '@aws-sdk/nested-clients@3.958.0': + resolution: {integrity: sha512-/KuCcS8b5TpQXkYOrPLYytrgxBhv81+5pChkOlhegbeHttjM69pyUpQVJqyfDM/A7wPLnDrzCAnk4zaAOkY0Nw==} engines: {node: '>=18.0.0'} - '@aws-sdk/token-providers@3.954.0': - resolution: {integrity: sha512-rDyN3oQQKMOJgyQ9/LNbh4fAGAj8ePMGOAQzSP/kyzizmViI6STpBW1o/VRqiTgMNi1bvA9ZasDtfrJqcVt0iA==} + '@aws-sdk/region-config-resolver@3.957.0': + resolution: {integrity: sha512-V8iY3blh8l2iaOqXWW88HbkY5jDoWjH56jonprG/cpyqqCnprvpMUZWPWYJoI8rHRf2bqzZeql1slxG6EnKI7A==} engines: {node: '>=18.0.0'} - '@aws-sdk/types@3.936.0': - resolution: {integrity: sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==} + '@aws-sdk/token-providers@3.958.0': + resolution: {integrity: sha512-UCj7lQXODduD1myNJQkV+LYcGYJ9iiMggR8ow8Hva1g3A/Na5imNXzz6O67k7DAee0TYpy+gkNw+SizC6min8Q==} engines: {node: '>=18.0.0'} - '@aws-sdk/types@3.953.0': - resolution: {integrity: sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==} + '@aws-sdk/types@3.957.0': + resolution: {integrity: sha512-wzWC2Nrt859ABk6UCAVY/WYEbAd7FjkdrQL6m24+tfmWYDNRByTJ9uOgU/kw9zqLCAwb//CPvrJdhqjTznWXAg==} engines: {node: '>=18.0.0'} '@aws-sdk/util-dynamodb@3.954.0': @@ -384,19 +374,25 @@ packages: peerDependencies: '@aws-sdk/client-dynamodb': ^3.954.0 - '@aws-sdk/util-endpoints@3.953.0': - resolution: {integrity: sha512-rjaS6jrFksopXvNg6YeN+D1lYwhcByORNlFuYesFvaQNtPOufbE5tJL4GJ3TMXyaY0uFR28N5BHHITPyWWfH/g==} + '@aws-sdk/util-dynamodb@3.958.0': + resolution: {integrity: sha512-wNGCmCBaj+Om4e93+zkiWv7L+sPGlJuDKHWpndCLdHp3EyHt46KxQpAC5QOMTzbRS0obxl2LqXilX8fbQZxU6A==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@aws-sdk/client-dynamodb': ^3.958.0 + + '@aws-sdk/util-endpoints@3.957.0': + resolution: {integrity: sha512-xwF9K24mZSxcxKS3UKQFeX/dPYkEps9wF1b+MGON7EvnbcucrJGyQyK1v1xFPn1aqXkBTFi+SZaMRx5E5YCVFw==} engines: {node: '>=18.0.0'} - '@aws-sdk/util-locate-window@3.953.0': - resolution: {integrity: sha512-mPxK+I1LcrgC/RSa3G5AMAn8eN2Ay0VOgw8lSRmV1jCtO+iYvNeCqOdxoJUjOW6I5BA4niIRWqVORuRP07776Q==} + '@aws-sdk/util-locate-window@3.957.0': + resolution: {integrity: sha512-nhmgKHnNV9K+i9daumaIz8JTLsIIML9PE/HUks5liyrjUzenjW/aHoc7WJ9/Td/gPZtayxFnXQSJRb/fDlBuJw==} engines: {node: '>=18.0.0'} - '@aws-sdk/util-user-agent-browser@3.953.0': - resolution: {integrity: sha512-UF5NeqYesWuFao+u7LJvpV1SJCaLml5BtFZKUdTnNNMeN6jvV+dW/eQoFGpXF94RCqguX0XESmRuRRPQp+/rzQ==} + '@aws-sdk/util-user-agent-browser@3.957.0': + resolution: {integrity: sha512-exueuwxef0lUJRnGaVkNSC674eAiWU07ORhxBnevFFZEKisln+09Qrtw823iyv5I1N8T+wKfh95xvtWQrNKNQw==} - '@aws-sdk/util-user-agent-node@3.954.0': - resolution: {integrity: sha512-fB5S5VOu7OFkeNzcblQlez4AjO5hgDFaa7phYt7716YWisY3RjAaQPlxgv+G3GltHHDJIfzEC5aRxdf62B9zMg==} + '@aws-sdk/util-user-agent-node@3.957.0': + resolution: {integrity: sha512-ycbYCwqXk4gJGp0Oxkzf2KBeeGBdTxz559D41NJP8FlzSej1Gh7Rk40Zo6AyTfsNWkrl/kVi1t937OIzC5t+9Q==} engines: {node: '>=18.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -404,8 +400,8 @@ packages: aws-crt: optional: true - '@aws-sdk/xml-builder@3.953.0': - resolution: {integrity: sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==} + '@aws-sdk/xml-builder@3.957.0': + resolution: {integrity: sha512-Ai5iiQqS8kJ5PjzMhWcLKN0G2yasAkvpnPlq2EnqlIMdB48HsizElt62qcktdxp4neRMyGkFq4NzgmDbXnhRiA==} engines: {node: '>=18.0.0'} '@aws/lambda-invoke-store@0.2.2': @@ -545,10 +541,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.28.4': - resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} - engines: {node: '>=6.9.0'} - '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} @@ -932,65 +924,9 @@ packages: cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.9.0': - resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.12.2': - resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/config-array@0.21.1': - resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/config-helpers@0.4.2': - resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.17.0': - resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/eslintrc@3.3.3': - resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.39.1': - resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/object-schema@2.1.7': - resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/plugin-kit@0.4.1': - resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@hono/node-server@1.19.7': - resolution: {integrity: sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw==} - engines: {node: '>=18.14.1'} - peerDependencies: - hono: ^4 - - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.7': - resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} - engines: {node: '>=18.18.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/retry@0.4.3': - resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} - engines: {node: '>=18.18'} + '@faker-js/faker@10.1.0': + resolution: {integrity: sha512-C3mrr3b5dRVlKPJdfrAXS8+dq+rq8Qm5SNRazca0JKgw1HQERFmrVb0towvMmw5uu8hHKNiQasMaR/tydf3Zsg==} + engines: {node: ^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0, npm: '>=10'} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} @@ -1017,22 +953,21 @@ packages: '@mermaid-js/parser@0.6.3': resolution: {integrity: sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==} - '@modelcontextprotocol/sdk@1.25.1': - resolution: {integrity: sha512-yO28oVFFC7EBoiKdAn+VqRm+plcfv4v0xp6osG/VsCB0NlPZWi87ajbCZZ8f/RvOFLEu7//rSRmuZZ7lMoe3gQ==} - engines: {node: '>=18'} - peerDependencies: - '@cfworker/json-schema': ^4.1.1 - zod: ^3.25 || ^4.0 - peerDependenciesMeta: - '@cfworker/json-schema': - optional: true - - '@napi-rs/wasm-runtime@1.0.7': - resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} - '@napi-rs/wasm-runtime@1.1.0': resolution: {integrity: sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==} + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + '@oozcitak/dom@2.0.2': resolution: {integrity: sha512-GjpKhkSYC3Mj4+lfwEyI1dqnsKTgwGy48ytZEhm4A/xnH/8z9M3ZVXKr/YGQi3uCLs1AEBS+x5T2JPiueEDW8w==} engines: {node: '>=20.0'} @@ -1148,12 +1083,120 @@ packages: cpu: [x64] os: [win32] - '@oxc-project/runtime@0.101.0': - resolution: {integrity: sha512-t3qpfVZIqSiLQ5Kqt/MC4Ge/WCOGrrcagAdzTcDaggupjiGxUx4nJF2v6wUCXWSzWHn5Ns7XLv13fCJEwCOERQ==} + '@oxc-project/runtime@0.103.0': + resolution: {integrity: sha512-sQKZo5lLS1/yzbsVlZ+zaQorOkLe3OkQjyyMN29tMvCax5e5Sa9uUYKChDDMR4D41n6ApEazMN2UcIwFdHgS7g==} engines: {node: ^20.19.0 || >=22.12.0} - '@oxc-project/types@0.101.0': - resolution: {integrity: sha512-nuFhqlUzJX+gVIPPfuE6xurd4lST3mdcWOhyK/rZO0B9XWMKm79SuszIQEnSMmmDhq1DC8WWVYGVd+6F93o1gQ==} + '@oxc-project/types@0.103.0': + resolution: {integrity: sha512-bkiYX5kaXWwUessFRSoXFkGIQTmc6dLGdxuRTrC+h8PSnIdZyuXHHlLAeTmOue5Br/a0/a7dHH0Gca6eXn9MKg==} + + '@oxc-resolver/binding-android-arm-eabi@11.16.1': + resolution: {integrity: sha512-EkOmYEFccQfSdsYjqBVeA6/m1eM3agQQp29RvI8x6Z++Ng5++76rXqgSHl/4G3I3FvO273vb33tmwsjMLyKPaQ==} + cpu: [arm] + os: [android] + + '@oxc-resolver/binding-android-arm64@11.16.1': + resolution: {integrity: sha512-Sj+URM2+3jWEoe8uyozhRRI2azgRs54wldvEEbndVhk2XrB2xTUFV+YB/pPLCqr0eSlfamtmpjmakJFpN6oBCw==} + cpu: [arm64] + os: [android] + + '@oxc-resolver/binding-darwin-arm64@11.16.1': + resolution: {integrity: sha512-80vNc2c+Da274yxJaenJi79iENOoQ/r6YG/lnNMyFN4aEkpYFUJu/zji8u4gxHWm121VdA2rdVzody1dgFq/Kg==} + cpu: [arm64] + os: [darwin] + + '@oxc-resolver/binding-darwin-x64@11.16.1': + resolution: {integrity: sha512-pYmRpiB7BrJVoaYsfhxybp3kqgzqjm8BE8RPGdYoPMItmBh4bVItpx1i0djCJXyx3dcZfG4kD9ZfDK2JUMPvcw==} + cpu: [x64] + os: [darwin] + + '@oxc-resolver/binding-freebsd-x64@11.16.1': + resolution: {integrity: sha512-XxGkO8CywZKirr2lnhQH1UGVNJY6GMtQZs7C05Rwj2d0p72VDliAL2w1PkWov/WrrqbXGAPqeQxc0XJ8ycEFIw==} + cpu: [x64] + os: [freebsd] + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.16.1': + resolution: {integrity: sha512-PaCQgtsNG9JQrRFLVfW3NJlWQ6OR8EuntvgnbmkMQ4SDAP4xZLFXR/4J3JyavUlvGcAcCrbOvGoVXpZAptSyLQ==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm-musleabihf@11.16.1': + resolution: {integrity: sha512-5ZOgCH2PMvk92y5RFX7ReDhUVAZnv/1UntURDE6EaAbKVSwHzzD2o9NaW1WFHY3noqJpEN0VdDVG2+ih/uoWqg==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm64-gnu@11.16.1': + resolution: {integrity: sha512-Y5pnJDKm85atZgN7LAKy+5ta/+qUzm+P+8RDKCQSstFwIrseS163B5XK93BxlHSKS31GGjVBoxRXUxiYotpLyQ==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-arm64-musl@11.16.1': + resolution: {integrity: sha512-ZYQgkl7dzjCbI2q05uZwSDWCBJRZy5fyhiO0KEuG6Ni+imJUoRFgaLHQ5YJWjYGP+pgswCFV09gURTZqA3mpUQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-resolver/binding-linux-ppc64-gnu@11.16.1': + resolution: {integrity: sha512-IO+L910FaHv/6cJ09GLXlg6kTeo7nQEhGNCgXM2mypMOX2mZIbG7wIDaCiZyBBYykfu/s0N+6zmQjM4RanTc8Q==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-riscv64-gnu@11.16.1': + resolution: {integrity: sha512-JfS9ap5rn2xKBMCtT2KoTdkVP4d56Xk7ydpBhIo50zWVCbV4M42ScmJhOj4Rt9BCEFKARAj5Y3dpGZ4WG2Vkag==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-riscv64-musl@11.16.1': + resolution: {integrity: sha512-FtAXP2LDnSn2Q334KdGUMK+/XhSVD+CxlLthAKUUv+hK+6PsFCTnL99iHKMBr0jVLuar4pYZnULri032BpdYrA==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-resolver/binding-linux-s390x-gnu@11.16.1': + resolution: {integrity: sha512-obYGj/cR8yk1IZVYeWRJlWtJkYap9d9x1y/tewatVkRca+5QgC8o8+fGz2HZIpKEXLkuMyFBoC9xnC2455MYoQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-x64-gnu@11.16.1': + resolution: {integrity: sha512-vLUCPrgQ7KN2XTtn3ZGCsEFi1HVwjkRfUxYa5jd0dgwiI9xRP8m5mMolMZO5aGgwq62JbYXTdmlLhll46lc5Aw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-x64-musl@11.16.1': + resolution: {integrity: sha512-Habu7Q/FrnIMuPfAslFPry42yUE8FVG4No1SWeJ21SW+vrMU7nZh6jQSfGT4t+jcgWUsuTYXfnewlIxMpmEHNw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-resolver/binding-openharmony-arm64@11.16.1': + resolution: {integrity: sha512-4zPHQ0g/3C6QKxfxe130+mJlp1Hr1Ias1VgaN3ulktO50v3V1MWgSnNZ6rnEHY2FGOyY1QpzJarZsN5OYG/PLw==} + cpu: [arm64] + os: [openharmony] + + '@oxc-resolver/binding-wasm32-wasi@11.16.1': + resolution: {integrity: sha512-uCF71JE6Z6bLzaZORasf81Zp6t7r6r3DV6o+EZPoNAYH4FMUUTFr1MHpkZLrwi+ifI+DtuSGJDCcSeQW31rx5w==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@oxc-resolver/binding-win32-arm64-msvc@11.16.1': + resolution: {integrity: sha512-GIm51df6OR6EVdusezBsRrI496AnV7U6elDXlwzJnKmgX+WuUXTUUDcepMSIX8dV4B9+nDxAHa/0X0THWyzA0A==} + cpu: [arm64] + os: [win32] + + '@oxc-resolver/binding-win32-ia32-msvc@11.16.1': + resolution: {integrity: sha512-lvMx7XWLJED1JGMyOUKSXFlebdCUMGzBu6fnOjt7iLDtJpwyR/HUs+kMhoUyiMDEsN8DRGLoy+C7V/VUIwxRqg==} + cpu: [ia32] + os: [win32] + + '@oxc-resolver/binding-win32-x64-msvc@11.16.1': + resolution: {integrity: sha512-PhzhSbDJP8q1T47DzUKMgWecRcfZjYKJdCkmMpW8eSsh86xpnBgrz37UGyBes2g9CAiPp2RmnZAoAA/ufuf3YQ==} + cpu: [x64] + os: [win32] '@oxc-transform/binding-android-arm64@0.96.0': resolution: {integrity: sha512-wOm+ZsqFvyZ7B9RefUMsj0zcXw77Z2pXA51nbSQyPXqr+g0/pDGxriZWP8Sdpz/e4AEaKPA9DvrwyOZxu7GRDQ==} @@ -1250,201 +1293,219 @@ packages: cpu: [x64] os: [win32] - '@oxfmt/darwin-arm64@0.18.0': - resolution: {integrity: sha512-Dp3mOFUtLtG/0eDclI3rx2be5FEnUxh2T6zlq7Zx5Q1c+DS9LJF8H97nQx+O/OU+o0e0J90kN8Msf9v3j7Hhsg==} + '@oxfmt/darwin-arm64@0.20.0': + resolution: {integrity: sha512-bjR5dqvrd9gxKYfYR0ljUu3/T3+TuDVWcwA7d+tsfmx9lqidlw3zhgBTblnjF1mrd1zkPMoc5zzq86GeSEt1cA==} cpu: [arm64] os: [darwin] - '@oxfmt/darwin-x64@0.18.0': - resolution: {integrity: sha512-Oe3KS4tdfLq+f1Ebje7D9BF7/0xmBYSMN6dWatSko1xfvu8oCZzKcNCcbwz0a8rBnoH/BnIiGFUEbgJDnA/JLQ==} + '@oxfmt/darwin-x64@0.20.0': + resolution: {integrity: sha512-esUDes8FlJX3IY4TVjFLgZrnZlIIyPDlhkCaHgGR3+z2eHFZOvQu68kTSpZLCEJmGXdSpU5rlveycQ6n8tk9ew==} cpu: [x64] os: [darwin] - '@oxfmt/linux-arm64-gnu@0.18.0': - resolution: {integrity: sha512-zW9z8LrAgL9bswgsaFOnQmoImCbq9YQST8B15FAoTeZYr9sb/VfdD6/PQEBLCptYlFmoTvmDNHjppi9g61NwHQ==} + '@oxfmt/linux-arm64-gnu@0.20.0': + resolution: {integrity: sha512-irE0RO9B0R6ziQE6kUVZtZ6IuTdRyuumn1cPWhDfpa0XUa5sE0ly8pjVsvJbj/J9qerVtidU05txeXBB5CirQg==} cpu: [arm64] os: [linux] libc: [glibc] - '@oxfmt/linux-arm64-musl@0.18.0': - resolution: {integrity: sha512-mFnpcasZZv1s/+6YDPradhIgR2G7GWr+mnzgJMIKQOJAtX3b0vzG+FE4f7hDIZPEUhC0hvZSd8f31FjAtrX0aQ==} + '@oxfmt/linux-arm64-musl@0.20.0': + resolution: {integrity: sha512-eXPBLwYJm26DCmwMwhelEwQMRwuGNaYhYZOhd+CYYsmVoF+h6L6dtjwj0Ovuu0Gqh18EL8vfsaoUvb+jr3vEBg==} cpu: [arm64] os: [linux] libc: [musl] - '@oxfmt/linux-x64-gnu@0.18.0': - resolution: {integrity: sha512-G1AXQNHVkPgVgRrAvDYdNi0x3gkvVyEmpL6WLMwoSjMnwYWQLt5/jrndHbS2Db8/CcmMo6VPP8lUQGvM4TRVaQ==} + '@oxfmt/linux-x64-gnu@0.20.0': + resolution: {integrity: sha512-dTPW38Hjgb7LoD2mNgyQGBaJ1hu5YgPrxImhl5Eb04eiws+ETCM0wrb2TWGduA+Nv3rHKn3vZEkMTEjklZXgRw==} cpu: [x64] os: [linux] libc: [glibc] - '@oxfmt/linux-x64-musl@0.18.0': - resolution: {integrity: sha512-M/KEIMHDr5lcK9gDxgIGr9xVwX7Pfl3PZs+6e8SySuckMgoJMkee6uWxhMdxws3dfU94saAkVmNQzM2+l3hvtA==} + '@oxfmt/linux-x64-musl@0.20.0': + resolution: {integrity: sha512-b4duw9JGDK/kZoqrPNU9tBOOZQdUW8KJPZ7gW7z54X1eGSqCJ1PT0XLNmZ7SOA1BzQwQ0a3qmQWfFVOsH3a5bw==} cpu: [x64] os: [linux] libc: [musl] - '@oxfmt/win32-arm64@0.18.0': - resolution: {integrity: sha512-LunuNBTLOgfkYFjiHOeNHD/Ii5paO/GVyNPSEYBwEPULbdeMGnjHqxzQHLGU8QIQjwu55mp4uuBP0DAXTli2TQ==} + '@oxfmt/win32-arm64@0.20.0': + resolution: {integrity: sha512-XAzvBhw4K+Fe16dBaFgYAdob9WaM8RYEXl0ibbm5NlNaQEq+5bH9xwc0oaYlHFnLfcgXWmn9ceTAYqNlONQRNA==} cpu: [arm64] os: [win32] - '@oxfmt/win32-x64@0.18.0': - resolution: {integrity: sha512-0kJJwn4FPeGJ4uV6ofOCiY+oBKWg+RWpRjYc9bywTjDbxWR6JAqtuXkiARCJej8UD/rJeXnHYTF78sFALkwZyA==} + '@oxfmt/win32-x64@0.20.0': + resolution: {integrity: sha512-fkJqHbJaoOMRmrjHSljyb4/7BgXO3xPLBsJSFGtm3mpfW0HHFbAKvd4/6njhqJz9KY+b3RWP1WssjFshcqQQ4w==} cpu: [x64] os: [win32] - '@oxlint-tsgolint/darwin-arm64@0.9.1': - resolution: {integrity: sha512-vk+8kChWqN+F+QUOvp4/6jDTlDCzXPgYGkxdi6EOUSOmCP1ix0uYOlIi/ytH2imXmC8YfPgLR/1BhqbsuDKuew==} + '@oxlint-tsgolint/darwin-arm64@0.10.0': + resolution: {integrity: sha512-mhBF/pjey0UdLL1ocU46Fqta+uJuRfqrLfDpcViRg17BtDiUNd8JY9iN2FOoS2HGSCAgCUjZ0AZkwkHwFs/VTw==} cpu: [arm64] os: [darwin] - '@oxlint-tsgolint/darwin-x64@0.9.1': - resolution: {integrity: sha512-yXmqr7El17+Oo56fWkPdUluU8d0jWxwRwAe1QZ0Xprxul9FHJeR/O2oYuBUngvCi02dbt0VZlwgJXcljQEdHlQ==} + '@oxlint-tsgolint/darwin-x64@0.10.0': + resolution: {integrity: sha512-roLi34mw/i1z+NS7luboix55SXyhVv38dNUTcRDkk+0lNPzI9ngrM+1y1N2oBSUmz5o9OZGnfJJ7BSGCw/fFEQ==} cpu: [x64] os: [darwin] - '@oxlint-tsgolint/linux-arm64@0.9.1': - resolution: {integrity: sha512-ukLb35BHSsxXaVEe8eIvYXMTxOdv8K4CySmtkWyc0pJT0q8zh85by1bsREWAP2hZc0wN0ClHjZHPdKY3958Jwg==} + '@oxlint-tsgolint/linux-arm64@0.10.0': + resolution: {integrity: sha512-HL9NThPH1V2F6l9XhwNmhQZUknN4m4yQYEvQFFGfZTYN6cvEEBIiqfF4KvBUg8c0xadMbQlW+Ug7/ybA9Nn+CA==} cpu: [arm64] os: [linux] - '@oxlint-tsgolint/linux-x64@0.9.1': - resolution: {integrity: sha512-kkxSS/meANLun4dHep2wnfvo8OHJKgdxzuY3RoooSWorVqw3/K5Qttmo0OQFt7UNq/oisn0YTaNhV28S0nAWyQ==} + '@oxlint-tsgolint/linux-x64@0.10.0': + resolution: {integrity: sha512-Tw8QNq8ab+4+qE5krvJyMA66v6XE3GoiISRD5WmJ7YOxUnu//jSw/bBm7OYf/TNEZyeV0BTR7zXzhT5R+VFWlQ==} cpu: [x64] os: [linux] - '@oxlint-tsgolint/win32-arm64@0.9.1': - resolution: {integrity: sha512-F9tiZZRn3x+kjXJC8GAE5C5xkvD8b8unoFeh7mS5W4USAH8+AzYydzLev5rAW2uXdOqtkO30EJl0ygl68Zlb8w==} + '@oxlint-tsgolint/win32-arm64@0.10.0': + resolution: {integrity: sha512-LTogmTRwpwQqVaH1Ama8Wd5/VVZWBSF8v5qTbeT628+1F5Kt1V5eHBvyFh4oN18UCZlgqrh7DqkDhsieXUaC8Q==} cpu: [arm64] os: [win32] - '@oxlint-tsgolint/win32-x64@0.9.1': - resolution: {integrity: sha512-DKTBgKUbycKNYgpWpglEHzkgiNVSG1rZmfiqw7w31keAq8q7avNGhz2WNmsRvXh8IGNw1PMb7vgxwUK8eyXIeg==} + '@oxlint-tsgolint/win32-x64@0.10.0': + resolution: {integrity: sha512-ygqxx8EmNWy9/wCQS5uXq9k/o2EyYNwNxY1ZHNzlmZC/kV06Aemx5OBDafefawBNqH7xTZPfccUrjdiy+QlTrw==} cpu: [x64] os: [win32] - '@oxlint/darwin-arm64@1.33.0': - resolution: {integrity: sha512-PmEQDLHAxiAdyttQ1ZWXd+5VpHLbHf3FTMJL9bg5TZamDnhNiW/v0Pamv3MTAdymnoDI3H8IVLAN/SAseV/adw==} + '@oxlint/darwin-arm64@1.35.0': + resolution: {integrity: sha512-ieiYVHkNZPo77Hgrxav595wGS4rRNKuDNrljf+4xhwpJsddrxMpM64IQUf2IvR3MhK4FxdGzhhB6OVmGVHY5/w==} cpu: [arm64] os: [darwin] - '@oxlint/darwin-x64@1.33.0': - resolution: {integrity: sha512-2R9aH3kR0X2M30z5agGikv3tfNTi8/uLhU5/tYktu33VGUXpbf0OLZSlD25UEuwOKAlf3RVtzV5oDyjoq93JuQ==} + '@oxlint/darwin-x64@1.35.0': + resolution: {integrity: sha512-1jNHu3j66X5jKySvgtE+jGtjx4ye+xioAucVTi2IuROZO6keK2YG74pnD+9FT+DpWZAtWRZGoW0r0x6aN9sEEg==} cpu: [x64] os: [darwin] - '@oxlint/linux-arm64-gnu@1.33.0': - resolution: {integrity: sha512-yb/k8GaMDgnX2LyO6km33kKItZ/n573SlbiHBBFU2HmeU7tzEHL5jHkHQXXcysUkapmqHd7UsDhOZDqPmXaQRg==} + '@oxlint/linux-arm64-gnu@1.35.0': + resolution: {integrity: sha512-T1lc0UaYbTxZyqVpLfC7eipbauNG8pBpkaZEW4JGz8Y68rxTH7d9s+CF0zxUxNr5RCtcmT669RLVjQT7VrKVLg==} cpu: [arm64] os: [linux] libc: [glibc] - '@oxlint/linux-arm64-musl@1.33.0': - resolution: {integrity: sha512-03pt9IO1C4ZfVOW6SQiOK26mzklAhLM3Kc79OXpX1kgZRlxk+rvFoMhlgCOzn7tEdrEgbePkBoxNnwDnJDFqJQ==} + '@oxlint/linux-arm64-musl@1.35.0': + resolution: {integrity: sha512-7Wv5Pke9kwWKFycUziSHsmi3EM0389TLzraB0KE/MArrKxx30ycwfJ5PYoMj9ERoW+Ybs0txdaOF/xJy/XyYkg==} cpu: [arm64] os: [linux] libc: [musl] - '@oxlint/linux-x64-gnu@1.33.0': - resolution: {integrity: sha512-Z7ImLWM50FoVXzYvyxUQ+QwBkBfRyK4YdLEGonyAGMp7iT3DksonDaTK9ODnJ1qHyAyAZCvuqXD7AEDsDvzDbA==} + '@oxlint/linux-x64-gnu@1.35.0': + resolution: {integrity: sha512-HDMPOzyVVy+rQl3H7UOq8oGHt7m1yaiWCanlhAu4jciK8dvXeO9OG/OQd74lD/h05IcJh93pCLEJ3wWOG8hTiQ==} cpu: [x64] os: [linux] libc: [glibc] - '@oxlint/linux-x64-musl@1.33.0': - resolution: {integrity: sha512-idb55Uzu5kkqqpMiVUfI9nP7zOqPZinQKsIRQAIU40wILcf/ijvhNZKIu3ucDMmye0n6IWOaSnxIRL5W2fNoUQ==} + '@oxlint/linux-x64-musl@1.35.0': + resolution: {integrity: sha512-kAPBBsUOM3HQQ6n3nnZauvFR9EoXqCSoj4O3OSXXarzsRTiItNrHabVUwxeswZEc+xMzQNR0FHEWg/d4QAAWLw==} cpu: [x64] os: [linux] libc: [musl] - '@oxlint/win32-arm64@1.33.0': - resolution: {integrity: sha512-wKKFt7cubfrLelNzdmDsNSmtBrlSUe1fWus587+uSxDZdpFbQ7liU0gsUlCbcHvym0H1Tc2O3K3cnLrgQORLPQ==} + '@oxlint/win32-arm64@1.35.0': + resolution: {integrity: sha512-qrpBkkOASS0WT8ra9xmBRXOEliN6D/MV9JhI/68lFHrtLhfFuRwg4AjzjxrCWrQCnQ0WkvAVpJzu73F4ICLYZw==} cpu: [arm64] os: [win32] - '@oxlint/win32-x64@1.33.0': - resolution: {integrity: sha512-ReyR8rNHjKNnO7dxGny9RCPELRAdhm3y780FNBcA07E1wvxSCkB+Mn5db0Pa5bRmxrsU/MTZ/aaBFa+ERXDdXw==} + '@oxlint/win32-x64@1.35.0': + resolution: {integrity: sha512-yPFcj6umrhusnG/kMS5wh96vblsqZ0kArQJS+7kEOSJDrH+DsFWaDCsSRF8U6gmSmZJ26KVMU3C3TMpqDN4M1g==} cpu: [x64] os: [win32] - '@rolldown/binding-android-arm64@1.0.0-beta.53': - resolution: {integrity: sha512-Ok9V8o7o6YfSdTTYA/uHH30r3YtOxLD6G3wih/U9DO0ucBBFq8WPt/DslU53OgfteLRHITZny9N/qCUxMf9kjQ==} + '@radix-ui/react-compose-refs@1.1.2': + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-slot@1.2.4': + resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@rolldown/binding-android-arm64@1.0.0-beta.56': + resolution: {integrity: sha512-GFsly+vPnl1Sa61sC2LwK4Hrz48W+YBqBmLSxBEj9IJW6nHNsWof1wwh1gwnxMIm/yN5F9M0B/cRAwn6rTINyg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-beta.53': - resolution: {integrity: sha512-yIsKqMz0CtRnVa6x3Pa+mzTihr4Ty+Z6HfPbZ7RVbk1Uxnco4+CUn7Qbm/5SBol1JD/7nvY8rphAgyAi7Lj6Vg==} + '@rolldown/binding-darwin-arm64@1.0.0-beta.56': + resolution: {integrity: sha512-8fSkk5g5MVZpddrH8hOyc9O5t5Dqv2Vi3Qe628xe+2zJedJxucUc5DX/KY1OVBRp8XY09LJO+J1V56LsxeBVPA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-beta.53': - resolution: {integrity: sha512-GTXe+mxsCGUnJOFMhfGWmefP7Q9TpYUseHvhAhr21nCTgdS8jPsvirb0tJwM3lN0/u/cg7bpFNa16fQrjKrCjQ==} + '@rolldown/binding-darwin-x64@1.0.0-beta.56': + resolution: {integrity: sha512-R+Q5zd763MKvgYSkBfr2gr/3nZQENaK88qEqfRUUYrpq/W0okOpbOJaxn5FDIIS+yq3cjyktYm115I5RiI6G5A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0-beta.53': - resolution: {integrity: sha512-9Tmp7bBvKqyDkMcL4e089pH3RsjD3SUungjmqWtyhNOxoQMh0fSmINTyYV8KXtE+JkxYMPWvnEt+/mfpVCkk8w==} + '@rolldown/binding-freebsd-x64@1.0.0-beta.56': + resolution: {integrity: sha512-YEsv0rfJoHHRNaVx6AfW/o4bmwTY7BJnSQ45rRCyU6DWEgvFZMojh6qzMQmW5ZVdcikE3cU1ZnrQQ2yem9H9Yg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53': - resolution: {integrity: sha512-a1y5fiB0iovuzdbjUxa7+Zcvgv+mTmlGGC4XydVIsyl48eoxgaYkA3l9079hyTyhECsPq+mbr0gVQsFU11OJAQ==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.56': + resolution: {integrity: sha512-mpaV+NCKcHUOkcAThvz1KiXcNshLQRSBLNNKqum2dG7oLZKk+z+02Fxa8BSuFFqq/rmmO6Fq2TPAdZUgOrwiqw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53': - resolution: {integrity: sha512-bpIGX+ov9PhJYV+wHNXl9rzq4F0QvILiURn0y0oepbQx+7stmQsKA0DhPGwmhfvF856wq+gbM8L92SAa/CBcLg==} + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.56': + resolution: {integrity: sha512-wj1uQRN4GEhYw5cs0dobGzZg3oKMLuQ3hY3fW7cLzvlwi9XRdzW7NmU58e6YUp6boOQLarSxdmAaqCMgaMZfcQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53': - resolution: {integrity: sha512-bGe5EBB8FVjHBR1mOLOPEFg1Lp3//7geqWkU5NIhxe+yH0W8FVrQ6WRYOap4SUTKdklD/dC4qPLREkMMQ855FA==} + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.56': + resolution: {integrity: sha512-Z2PWbAHjW2EUflb1/tPvouMqppwWF5Va1Y9b4GQpO6QlpGK0Wqmn90GO2VKiheDh/gSZlsxZ7uOZoXh2y8R7Kg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53': - resolution: {integrity: sha512-qL+63WKVQs1CMvFedlPt0U9PiEKJOAL/bsHMKUDS6Vp2Q+YAv/QLPu8rcvkfIMvQ0FPU2WL0aX4eWwF6e/GAnA==} + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.56': + resolution: {integrity: sha512-Z/uv04/Tsf7oqhwjPUiDiSildhWmCpsklA0e5PEB+0eGGmm07B+M2SmqRe9Fd0ypfU2TPGhq+Hn7RVUGIfSMxg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.0-beta.53': - resolution: {integrity: sha512-VGl9JIGjoJh3H8Mb+7xnVqODajBmrdOOb9lxWXdcmxyI+zjB2sux69br0hZJDTyLJfvBoYm439zPACYbCjGRmw==} + '@rolldown/binding-linux-x64-musl@1.0.0-beta.56': + resolution: {integrity: sha512-u+yP0Pt9ar3PkLGGiyGmQKVj9j20X0E831DY0OVmbKYHAAbTyLKYx+UIIorCm+SQnhGKfkD+0pmwfTc2t2Vt/g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.0-beta.53': - resolution: {integrity: sha512-B4iIserJXuSnNzA5xBLFUIjTfhNy7d9sq4FUMQY3GhQWGVhS2RWWzzDnkSU6MUt7/aHUrep0CdQfXUJI9D3W7A==} + '@rolldown/binding-openharmony-arm64@1.0.0-beta.56': + resolution: {integrity: sha512-Kuc6r5Uya+KxdJ7MUSok3K8zta/1bcsaSNxTvYujm2mWYuffadqgkkR3d0UCRbbCH5klZ+7VG6DR3VtPRlCntw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-beta.53': - resolution: {integrity: sha512-BUjAEgpABEJXilGq/BPh7jeU3WAJ5o15c1ZEgHaDWSz3LB881LQZnbNJHmUiM4d1JQWMYYyR1Y490IBHi2FPJg==} + '@rolldown/binding-wasm32-wasi@1.0.0-beta.56': + resolution: {integrity: sha512-pejT5oLj8xlfn8tjC3bJKeuAsk/un6GKwjbsBQG0AchefdaHf2+S4QRn8XfEMB1l1ZTbe5yEiiV92mr7Jdjaeg==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53': - resolution: {integrity: sha512-s27uU7tpCWSjHBnxyVXHt3rMrQdJq5MHNv3BzsewCIroIw3DJFjMH1dzCPPMUFxnh1r52Nf9IJ/eWp6LDoyGcw==} + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.56': + resolution: {integrity: sha512-1NKkRLQR2ghmHMd+14nm1noOhoLei62pkdGlf1g4F+9lfFws66+9LBnP6Z+E+KK8Do9hzQ6FFRwtkC3EADAeyA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': - resolution: {integrity: sha512-cjWL/USPJ1g0en2htb4ssMjIycc36RvdQAx1WlXnS6DpULswiUTVXPDesTifSKYSyvx24E0YqQkEm0K/M2Z/AA==} + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.56': + resolution: {integrity: sha512-BC3mObCr7/O+1jMJ/Hm3INikBk5D25RTxCha10Rq8b1gHlBfb9eA460+7xQfc8FxUsMCUgHtvrK3Vs5izgwBOQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -1455,6 +1516,9 @@ packages: '@rolldown/pluginutils@1.0.0-beta.53': resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} + '@rolldown/pluginutils@1.0.0-beta.56': + resolution: {integrity: sha512-cw9jwAgCs024Nic4OB8PeFDLBHLD1Athcv3bRvyYATIVD9B/gL5X5cJkezT94Y7m7Dk9HXaUMcvb7ypvSX46sA==} + '@rollup/rollup-android-arm-eabi@4.53.5': resolution: {integrity: sha512-iDGS/h7D8t7tvZ1t6+WPK04KD0MwzLZrG0se1hzBjSi5fyxlsiggoJHwh18PCFNn7tG43OWb6pdZ6Y+rMlmyNQ==} cpu: [arm] @@ -1597,36 +1661,36 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - '@smithy/abort-controller@4.2.6': - resolution: {integrity: sha512-P7JD4J+wxHMpGxqIg6SHno2tPkZbBUBLbPpR5/T1DEUvw/mEaINBMaPFZNM7lA+ToSCZ36j6nMHa+5kej+fhGg==} + '@smithy/abort-controller@4.2.7': + resolution: {integrity: sha512-rzMY6CaKx2qxrbYbqjXWS0plqEy7LOdKHS0bg4ixJ6aoGDPNUcLWk/FRNuCILh7GKLG9TFUXYYeQQldMBBwuyw==} engines: {node: '>=18.0.0'} - '@smithy/config-resolver@4.4.4': - resolution: {integrity: sha512-s3U5ChS21DwU54kMmZ0UJumoS5cg0+rGVZvN6f5Lp6EbAVi0ZyP+qDSHdewfmXKUgNK1j3z45JyzulkDukrjAA==} + '@smithy/config-resolver@4.4.5': + resolution: {integrity: sha512-HAGoUAFYsUkoSckuKbCPayECeMim8pOu+yLy1zOxt1sifzEbrsRpYa+mKcMdiHKMeiqOibyPG0sFJnmaV/OGEg==} engines: {node: '>=18.0.0'} - '@smithy/core@3.19.0': - resolution: {integrity: sha512-Y9oHXpBcXQgYHOcAEmxjkDilUbSTkgKjoHYed3WaYUH8jngq8lPWDBSpjHblJ9uOgBdy5mh3pzebrScDdYr29w==} + '@smithy/core@3.20.0': + resolution: {integrity: sha512-WsSHCPq/neD5G/MkK4csLI5Y5Pkd9c1NMfpYEKeghSGaD4Ja1qLIohRQf2D5c1Uy5aXp76DeKHkzWZ9KAlHroQ==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.2.6': - resolution: {integrity: sha512-xBmawExyTzOjbhzkZwg+vVm/khg28kG+rj2sbGlULjFd1jI70sv/cbpaR0Ev4Yfd6CpDUDRMe64cTqR//wAOyA==} + '@smithy/credential-provider-imds@4.2.7': + resolution: {integrity: sha512-CmduWdCiILCRNbQWFR0OcZlUPVtyE49Sr8yYL0rZQ4D/wKxiNzBNS/YHemvnbkIWj623fplgkexUd/c9CAKdoA==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-codec@4.2.6': - resolution: {integrity: sha512-OZfsI+YRG26XZik/jKMMg37acnBSbUiK/8nETW3uM3mLj+0tMmFXdHQw1e5WEd/IHN8BGOh3te91SNDe2o4RHg==} + '@smithy/eventstream-codec@4.2.7': + resolution: {integrity: sha512-DrpkEoM3j9cBBWhufqBwnbbn+3nf1N9FP6xuVJ+e220jbactKuQgaZwjwP5CP1t+O94brm2JgVMD2atMGX3xIQ==} engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.3.7': - resolution: {integrity: sha512-fcVap4QwqmzQwQK9QU3keeEpCzTjnP9NJ171vI7GnD7nbkAIcP9biZhDUx88uRH9BabSsQDS0unUps88uZvFIQ==} + '@smithy/fetch-http-handler@5.3.8': + resolution: {integrity: sha512-h/Fi+o7mti4n8wx1SR6UHWLaakwHRx29sizvp8OOm7iqwKGFneT06GCSFhml6Bha5BT6ot5pj3CYZnCHhGC2Rg==} engines: {node: '>=18.0.0'} - '@smithy/hash-node@4.2.6': - resolution: {integrity: sha512-k3Dy9VNR37wfMh2/1RHkFf/e0rMyN0pjY0FdyY6ItJRjENYyVPRMwad6ZR1S9HFm6tTuIOd9pqKBmtJ4VHxvxg==} + '@smithy/hash-node@4.2.7': + resolution: {integrity: sha512-PU/JWLTBCV1c8FtB8tEFnY4eV1tSfBc7bDBADHfn1K+uRbPgSJ9jnJp0hyjiFN2PMdPzxsf1Fdu0eo9fJ760Xw==} engines: {node: '>=18.0.0'} - '@smithy/invalid-dependency@4.2.6': - resolution: {integrity: sha512-E4t/V/q2T46RY21fpfznd1iSLTvCXKNKo4zJ1QuEFN4SE9gKfu2vb6bgq35LpufkQ+SETWIC7ZAf2GGvTlBaMQ==} + '@smithy/invalid-dependency@4.2.7': + resolution: {integrity: sha512-ncvgCr9a15nPlkhIUx3CU4d7E7WEuVJOV7fS7nnK2hLtPK9tYRBkMHQbhXU1VvvKeBm/O0x26OEoBq+ngFpOEQ==} engines: {node: '>=18.0.0'} '@smithy/is-array-buffer@2.2.0': @@ -1637,76 +1701,72 @@ packages: resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==} engines: {node: '>=18.0.0'} - '@smithy/middleware-content-length@4.2.6': - resolution: {integrity: sha512-0cjqjyfj+Gls30ntq45SsBtqF3dfJQCeqQPyGz58Pk8OgrAr5YiB7ZvDzjCA94p4r6DCI4qLm7FKobqBjf515w==} + '@smithy/middleware-content-length@4.2.7': + resolution: {integrity: sha512-GszfBfCcvt7kIbJ41LuNa5f0wvQCHhnGx/aDaZJCCT05Ld6x6U2s0xsc/0mBFONBZjQJp2U/0uSJ178OXOwbhg==} engines: {node: '>=18.0.0'} - '@smithy/middleware-endpoint@4.4.0': - resolution: {integrity: sha512-M6qWfUNny6NFNy8amrCGIb9TfOMUkHVtg9bHtEFGRgfH7A7AtPpn/fcrToGPjVDK1ECuMVvqGQOXcZxmu9K+7A==} + '@smithy/middleware-endpoint@4.4.1': + resolution: {integrity: sha512-gpLspUAoe6f1M6H0u4cVuFzxZBrsGZmjx2O9SigurTx4PbntYa4AJ+o0G0oGm1L2oSX6oBhcGHwrfJHup2JnJg==} engines: {node: '>=18.0.0'} - '@smithy/middleware-retry@4.4.16': - resolution: {integrity: sha512-XPpNhNRzm3vhYm7YCsyw3AtmWggJbg1wNGAoqb7NBYr5XA5isMRv14jgbYyUV6IvbTBFZQdf2QpeW43LrRdStQ==} + '@smithy/middleware-retry@4.4.17': + resolution: {integrity: sha512-MqbXK6Y9uq17h+4r0ogu/sBT6V/rdV+5NvYL7ZV444BKfQygYe8wAhDrVXagVebN6w2RE0Fm245l69mOsPGZzg==} engines: {node: '>=18.0.0'} - '@smithy/middleware-serde@4.2.7': - resolution: {integrity: sha512-PFMVHVPgtFECeu4iZ+4SX6VOQT0+dIpm4jSPLLL6JLSkp9RohGqKBKD0cbiXdeIFS08Forp0UHI6kc0gIHenSA==} + '@smithy/middleware-serde@4.2.8': + resolution: {integrity: sha512-8rDGYen5m5+NV9eHv9ry0sqm2gI6W7mc1VSFMtn6Igo25S507/HaOX9LTHAS2/J32VXD0xSzrY0H5FJtOMS4/w==} engines: {node: '>=18.0.0'} - '@smithy/middleware-stack@4.2.6': - resolution: {integrity: sha512-JSbALU3G+JS4kyBZPqnJ3hxIYwOVRV7r9GNQMS6j5VsQDo5+Es5nddLfr9TQlxZLNHPvKSh+XSB0OuWGfSWFcA==} + '@smithy/middleware-stack@4.2.7': + resolution: {integrity: sha512-bsOT0rJ+HHlZd9crHoS37mt8qRRN/h9jRve1SXUhVbkRzu0QaNYZp1i1jha4n098tsvROjcwfLlfvcFuJSXEsw==} engines: {node: '>=18.0.0'} - '@smithy/node-config-provider@4.3.6': - resolution: {integrity: sha512-fYEyL59Qe82Ha1p97YQTMEQPJYmBS+ux76foqluaTVWoG9Px5J53w6NvXZNE3wP7lIicLDF7Vj1Em18XTX7fsA==} + '@smithy/node-config-provider@4.3.7': + resolution: {integrity: sha512-7r58wq8sdOcrwWe+klL9y3bc4GW1gnlfnFOuL7CXa7UzfhzhxKuzNdtqgzmTV+53lEp9NXh5hY/S4UgjLOzPfw==} engines: {node: '>=18.0.0'} - '@smithy/node-http-handler@4.4.6': - resolution: {integrity: sha512-Gsb9jf4ido5BhPfani4ggyrKDd3ZK+vTFWmUaZeFg5G3E5nhFmqiTzAIbHqmPs1sARuJawDiGMGR/nY+Gw6+aQ==} + '@smithy/node-http-handler@4.4.7': + resolution: {integrity: sha512-NELpdmBOO6EpZtWgQiHjoShs1kmweaiNuETUpuup+cmm/xJYjT4eUjfhrXRP4jCOaAsS3c3yPsP3B+K+/fyPCQ==} engines: {node: '>=18.0.0'} - '@smithy/property-provider@4.2.6': - resolution: {integrity: sha512-a/tGSLPtaia2krbRdwR4xbZKO8lU67DjMk/jfY4QKt4PRlKML+2tL/gmAuhNdFDioO6wOq0sXkfnddNFH9mNUA==} + '@smithy/property-provider@4.2.7': + resolution: {integrity: sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA==} engines: {node: '>=18.0.0'} - '@smithy/protocol-http@5.3.6': - resolution: {integrity: sha512-qLRZzP2+PqhE3OSwvY2jpBbP0WKTZ9opTsn+6IWYI0SKVpbG+imcfNxXPq9fj5XeaUTr7odpsNpK6dmoiM1gJQ==} + '@smithy/protocol-http@5.3.7': + resolution: {integrity: sha512-1r07pb994I20dD/c2seaZhoCuNYm0rWrvBxhCQ70brNh11M5Ml2ew6qJVo0lclB3jMIXirD4s2XRXRe7QEi0xA==} engines: {node: '>=18.0.0'} - '@smithy/querystring-builder@4.2.6': - resolution: {integrity: sha512-MeM9fTAiD3HvoInK/aA8mgJaKQDvm8N0dKy6EiFaCfgpovQr4CaOkJC28XqlSRABM+sHdSQXbC8NZ0DShBMHqg==} + '@smithy/querystring-builder@4.2.7': + resolution: {integrity: sha512-eKONSywHZxK4tBxe2lXEysh8wbBdvDWiA+RIuaxZSgCMmA0zMgoDpGLJhnyj+c0leOQprVnXOmcB4m+W9Rw7sg==} engines: {node: '>=18.0.0'} - '@smithy/querystring-parser@4.2.6': - resolution: {integrity: sha512-YmWxl32SQRw/kIRccSOxzS/Ib8/b5/f9ex0r5PR40jRJg8X1wgM3KrR2In+8zvOGVhRSXgvyQpw9yOSlmfmSnA==} + '@smithy/querystring-parser@4.2.7': + resolution: {integrity: sha512-3X5ZvzUHmlSTHAXFlswrS6EGt8fMSIxX/c3Rm1Pni3+wYWB6cjGocmRIoqcQF9nU5OgGmL0u7l9m44tSUpfj9w==} engines: {node: '>=18.0.0'} - '@smithy/service-error-classification@4.2.6': - resolution: {integrity: sha512-Q73XBrzJlGTut2nf5RglSntHKgAG0+KiTJdO5QQblLfr4TdliGwIAha1iZIjwisc3rA5ulzqwwsYC6xrclxVQg==} + '@smithy/service-error-classification@4.2.7': + resolution: {integrity: sha512-YB7oCbukqEb2Dlh3340/8g8vNGbs/QsNNRms+gv3N2AtZz9/1vSBx6/6tpwQpZMEJFs7Uq8h4mmOn48ZZ72MkA==} engines: {node: '>=18.0.0'} - '@smithy/shared-ini-file-loader@4.4.1': - resolution: {integrity: sha512-tph+oQYPbpN6NamF030hx1gb5YN2Plog+GLaRHpoEDwp8+ZPG26rIJvStG9hkWzN2HBn3HcWg0sHeB0tmkYzqA==} + '@smithy/shared-ini-file-loader@4.4.2': + resolution: {integrity: sha512-M7iUUff/KwfNunmrgtqBfvZSzh3bmFgv/j/t1Y1dQ+8dNo34br1cqVEqy6v0mYEgi0DkGO7Xig0AnuOaEGVlcg==} engines: {node: '>=18.0.0'} - '@smithy/signature-v4@5.3.6': - resolution: {integrity: sha512-P1TXDHuQMadTMTOBv4oElZMURU4uyEhxhHfn+qOc2iofW9Rd4sZtBGx58Lzk112rIGVEYZT8eUMK4NftpewpRA==} + '@smithy/signature-v4@5.3.7': + resolution: {integrity: sha512-9oNUlqBlFZFOSdxgImA6X5GFuzE7V2H7VG/7E70cdLhidFbdtvxxt81EHgykGK5vq5D3FafH//X+Oy31j3CKOg==} engines: {node: '>=18.0.0'} - '@smithy/smithy-client@4.10.1': - resolution: {integrity: sha512-1ovWdxzYprhq+mWqiGZlt3kF69LJthuQcfY9BIyHx9MywTFKzFapluku1QXoaBB43GCsLDxNqS+1v30ure69AA==} + '@smithy/smithy-client@4.10.2': + resolution: {integrity: sha512-D5z79xQWpgrGpAHb054Fn2CCTQZpog7JELbVQ6XAvXs5MNKWf28U9gzSBlJkOyMl9LA1TZEjRtwvGXfP0Sl90g==} engines: {node: '>=18.0.0'} - '@smithy/types@4.10.0': - resolution: {integrity: sha512-K9mY7V/f3Ul+/Gz4LJANZ3vJ/yiBIwCyxe0sPT4vNJK63Srvd+Yk1IzP0t+nE7XFSpIGtzR71yljtnqpUTYFlQ==} + '@smithy/types@4.11.0': + resolution: {integrity: sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA==} engines: {node: '>=18.0.0'} - '@smithy/types@4.9.0': - resolution: {integrity: sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==} - engines: {node: '>=18.0.0'} - - '@smithy/url-parser@4.2.6': - resolution: {integrity: sha512-tVoyzJ2vXp4R3/aeV4EQjBDmCuWxRa8eo3KybL7Xv4wEM16nObYh7H1sNfcuLWHAAAzb0RVyxUz1S3sGj4X+Tg==} + '@smithy/url-parser@4.2.7': + resolution: {integrity: sha512-/RLtVsRV4uY3qPWhBDsjwahAtt3x2IsMGnP5W1b2VZIe+qgCqkLxI1UOHDZp1Q1QSOrdOR32MF3Ph2JfWT1VHg==} engines: {node: '>=18.0.0'} '@smithy/util-base64@4.3.0': @@ -1733,32 +1793,32 @@ packages: resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-browser@4.3.15': - resolution: {integrity: sha512-LiZQVAg/oO8kueX4c+oMls5njaD2cRLXRfcjlTYjhIqmwHnCwkQO5B3dMQH0c5PACILxGAQf6Mxsq7CjlDc76A==} + '@smithy/util-defaults-mode-browser@4.3.16': + resolution: {integrity: sha512-/eiSP3mzY3TsvUOYMeL4EqUX6fgUOj2eUOU4rMMgVbq67TiRLyxT7Xsjxq0bW3OwuzK009qOwF0L2OgJqperAQ==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-node@4.2.18': - resolution: {integrity: sha512-Kw2J+KzYm9C9Z9nY6+W0tEnoZOofstVCMTshli9jhQbQCy64rueGfKzPfuFBnVUqZD9JobxTh2DzHmPkp/Va/Q==} + '@smithy/util-defaults-mode-node@4.2.19': + resolution: {integrity: sha512-3a4+4mhf6VycEJyHIQLypRbiwG6aJvbQAeRAVXydMmfweEPnLLabRbdyo/Pjw8Rew9vjsh5WCdhmDaHkQnhhhA==} engines: {node: '>=18.0.0'} - '@smithy/util-endpoints@3.2.6': - resolution: {integrity: sha512-v60VNM2+mPvgHCBXEfMCYrQ0RepP6u6xvbAkMenfe4Mi872CqNkJzgcnQL837e8NdeDxBgrWQRTluKq5Lqdhfg==} + '@smithy/util-endpoints@3.2.7': + resolution: {integrity: sha512-s4ILhyAvVqhMDYREeTS68R43B1V5aenV5q/V1QpRQJkCXib5BPRo4s7uNdzGtIKxaPHCfU/8YkvPAEvTpxgspg==} engines: {node: '>=18.0.0'} '@smithy/util-hex-encoding@4.2.0': resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==} engines: {node: '>=18.0.0'} - '@smithy/util-middleware@4.2.6': - resolution: {integrity: sha512-qrvXUkxBSAFomM3/OEMuDVwjh4wtqK8D2uDZPShzIqOylPst6gor2Cdp6+XrH4dyksAWq/bE2aSDYBTTnj0Rxg==} + '@smithy/util-middleware@4.2.7': + resolution: {integrity: sha512-i1IkpbOae6NvIKsEeLLM9/2q4X+M90KV3oCFgWQI4q0Qz+yUZvsr+gZPdAEAtFhWQhAHpTsJO8DRJPuwVyln+w==} engines: {node: '>=18.0.0'} - '@smithy/util-retry@4.2.6': - resolution: {integrity: sha512-x7CeDQLPQ9cb6xN7fRJEjlP9NyGW/YeXWc4j/RUhg4I+H60F0PEeRc2c/z3rm9zmsdiMFzpV/rT+4UHW6KM1SA==} + '@smithy/util-retry@4.2.7': + resolution: {integrity: sha512-SvDdsQyF5CIASa4EYVT02LukPHVzAgUA4kMAuZ97QJc2BpAqZfA4PINB8/KOoCXEw9tsuv/jQjMeaHFvxdLNGg==} engines: {node: '>=18.0.0'} - '@smithy/util-stream@4.5.7': - resolution: {integrity: sha512-Uuy4S5Aj4oF6k1z+i2OtIBJUns4mlg29Ph4S+CqjR+f4XXpSFVgTCYLzMszHJTicYDBxKFtwq2/QSEDSS5l02A==} + '@smithy/util-stream@4.5.8': + resolution: {integrity: sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w==} engines: {node: '>=18.0.0'} '@smithy/util-uri-escape@4.2.0': @@ -1773,8 +1833,8 @@ packages: resolution: {integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==} engines: {node: '>=18.0.0'} - '@smithy/util-waiter@4.2.6': - resolution: {integrity: sha512-xU9HwUSik9UUCJmm530yvBy0AwlQFICveKmqvaaTukKkXEAhyiBdHtSrhPrH3rH+uz0ykyaE3LdgsX86C6mDCQ==} + '@smithy/util-waiter@4.2.7': + resolution: {integrity: sha512-vHJFXi9b7kUEpHWUCY3Twl+9NPOZvQ0SAi+Ewtn48mbiJk4JY9MZmKQjGB4SCvVb9WPiSphZJYY6RIbs+grrzw==} engines: {node: '>=18.0.0'} '@smithy/uuid@1.1.0': @@ -1913,8 +1973,8 @@ packages: peerDependencies: typescript: '>=4.7' - '@tanstack/db@0.5.12': - resolution: {integrity: sha512-NpQa+Mo9Y4YZ7qL7ugD7/z+ezcZJ67o1BlR63cr3OOxiBbb4Lx9OphWYsJy3g5eBcNI6DhS2hu9mYdlgAwsJlQ==} + '@tanstack/db@0.5.16': + resolution: {integrity: sha512-V4oCsGlighwgKGWldw1umaXaVYiDR0sK/1fCWictrx2lqxqmBMUEfmNtWnt0CFJXEbyRA/LF8TyFn1ooXtyZ3w==} peerDependencies: typescript: '>=4.7' @@ -1942,18 +2002,21 @@ packages: peerDependencies: vite: ^6.0.0 || ^7.0.0 - '@tanstack/devtools@0.9.1': - resolution: {integrity: sha512-fW/1ewT+g0LgJGraS/Irwle3uRgM1VDwfhi/NP3aGHhGyCDAWJI0+Id9FBzjChQ5BuEU5qD5fdegcFqTZShXHw==} + '@tanstack/devtools@0.10.0': + resolution: {integrity: sha512-UVN6wMntMMfMXk3Ozn7Ytr+SNhhzICqzOqVxmd4P2Kw+WzLkkEtmrBOZICII64eEIOPpRWgs9EG8uWVPQBt4IA==} engines: {node: '>=18'} peerDependencies: solid-js: '>=1.9.7' - '@tanstack/directive-functions-plugin@1.141.0': - resolution: {integrity: sha512-Ca8ylyh2c100Kn9nFUA4Gao95eISBGLbff+4unJ6MF+t+/FR3awIsIC5gBxeEVu+nv6HPaY9ZeD0/Ehh4OsXpQ==} + '@tanstack/directive-functions-plugin@1.142.1': + resolution: {integrity: sha512-k4HhAaitobp+z2pXBkmoWgE8Ollhx7fQXpVL+PQ7HeHZc2PilrQtC3ysxvoPunufrztIxweSE9HAWkZ2AFNaLw==} engines: {node: '>=12'} peerDependencies: vite: '>=6.0.0 || >=7.0.0' + '@tanstack/form-core@1.27.6': + resolution: {integrity: sha512-1C4PUpOcCpivddKxtAeqdeqncxnPKiPpTVDRknDExCba+6zCsAjxgL+p3qYA3hu+EFyUAdW71rU+uqYbEa7qqA==} + '@tanstack/history@1.141.0': resolution: {integrity: sha512-LS54XNyxyTs5m/pl1lkwlg7uZM3lvsv2FIIV1rsJgnfwVCnI+n4ZGZ2CcjNT13BPu/3hPP+iHmliBSscJxW5FQ==} engines: {node: '>=12'} @@ -1965,8 +2028,8 @@ packages: '@tanstack/query-core@5.90.12': resolution: {integrity: sha512-T1/8t5DhV/SisWjDnaiU2drl6ySvsHj1bHBCWNXd+/T+Hh1cf6JodyEYMd5sgwm+b/mETT4EV3H+zCVczCU5hg==} - '@tanstack/query-db-collection@1.0.8': - resolution: {integrity: sha512-7HzgJXd7OVnsCKhskjs9anqFhXb3JQygWmG3IzIkQT6DOM1c1VXpWJ9TzHravhyjeI9/MPE7I1NtolU9PnM9uw==} + '@tanstack/query-db-collection@1.0.12': + resolution: {integrity: sha512-kwE9lfGhbnRbRHut1k4yrshoTSDNqP/uY7Brr0l1HbOJZuW7V8Q1zQ1GN4TMAtsLohKaSsL/XDxZULCi6MGngg==} peerDependencies: '@tanstack/query-core': ^5.0.0 typescript: '>=4.7' @@ -1974,13 +2037,13 @@ packages: '@tanstack/query-devtools@5.91.1': resolution: {integrity: sha512-l8bxjk6BMsCaVQH6NzQEE/bEgFy1hAs5qbgXl0xhzezlaQbPk6Mgz9BqEg2vTLPOHD8N4k+w/gdgCbEzecGyNg==} - '@tanstack/react-db@0.1.56': - resolution: {integrity: sha512-7vfwx3tD6tgcUBu6tzpYVMFuYUGzYX7GHw8AtsW/P24eBhr7RR/dyF2ucoUGW6TZzdm8/bN/ql+8ftAV3iFsfA==} + '@tanstack/react-db@0.1.60': + resolution: {integrity: sha512-Pz3pwH4vgRxlS/L3+BszINjNlIUXahJ6EqSEsYBMBT19G36GzTzyd5Qq98JaOXuu8V0dkiFWEoyEoTv3BiHcrg==} peerDependencies: react: '>=16.8.0' - '@tanstack/react-devtools@0.8.4': - resolution: {integrity: sha512-fq7GrpHIRdIBa5HmNN+CmC7CopY3tfKE4AXoszNSLk4yHKjC8iEjx7rh4r4RO5iUxHnmoCKX+NPXDgfsIKtaog==} + '@tanstack/react-devtools@0.8.6': + resolution: {integrity: sha512-NUvbOlldLDzeL2qMONfLs5Ahb1bmygqyKMqYlNRl/UwAVW+ugIUGgDlXOa+kGt+ksCHO6CUopwEE9973z5tITg==} engines: {node: '>=18'} peerDependencies: '@types/react': '>=16.8' @@ -1988,6 +2051,15 @@ packages: react: '>=16.8' react-dom: '>=16.8' + '@tanstack/react-form@1.27.6': + resolution: {integrity: sha512-kq/68CKbCxK6TkFnGihtQ3qdrD5GPrVjfhkcqMFH/+X9jYOZDai52864T4997lC3nSEKFbUhkkXlaIy/wCSuNQ==} + peerDependencies: + '@tanstack/react-start': '*' + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@tanstack/react-start': + optional: true + '@tanstack/react-query-devtools@5.91.1': resolution: {integrity: sha512-tRnJYwEbH0kAOuToy8Ew7bJw1lX3AjkkgSlf/vzb+NpnqmHPdWM+lA2DSdGQSLi1SU0PDRrrCI1vnZnci96CsQ==} peerDependencies: @@ -1999,20 +2071,20 @@ packages: peerDependencies: react: ^18 || ^19 - '@tanstack/react-router-devtools@1.141.6': - resolution: {integrity: sha512-Uzb8GKg5Om8mCw2WjdDW1VBpyF+iaYOO/HK0ELbWO+TC6Nn/9pbbku/3HCMKHeLkmKPaMSW92do4Hu0bDYVglg==} + '@tanstack/react-router-devtools@1.143.4': + resolution: {integrity: sha512-+AKGHkC2aDL93XCWDMB9/cf8+N4awGylCK0mk0kJ5BUBVSoZpNVLtZiBFCxRuvZCQtY5PbdYT4xeUA0dbgH9Eg==} engines: {node: '>=12'} peerDependencies: - '@tanstack/react-router': ^1.141.6 - '@tanstack/router-core': ^1.141.6 + '@tanstack/react-router': ^1.143.4 + '@tanstack/router-core': ^1.143.4 react: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0' peerDependenciesMeta: '@tanstack/router-core': optional: true - '@tanstack/react-router-ssr-query@1.141.6': - resolution: {integrity: sha512-kdSnBAo8MnQvxabtAK0X/Z6vMW8pvr1woGznqCA0FgwPll4qbeN7k/nnSe3tZuxabqdT1PKz9TVjD+3RXxCAew==} + '@tanstack/react-router-ssr-query@1.143.4': + resolution: {integrity: sha512-2+JZ2ikGyl7cMftPv+7D54fcrsLUxMXb4QX8a3vVpOaD1ecyc5Qjh7fCPzx6u1OuwIa39UnxYX14Lb/TWGXYhA==} engines: {node: '>=12'} peerDependencies: '@tanstack/query-core': '>=5.90.0' @@ -2021,29 +2093,29 @@ packages: react: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0' - '@tanstack/react-router@1.141.6': - resolution: {integrity: sha512-qWFxi2D6eGc1L03RzUuhyEOplZ7Q6q62YOl7Of9Y0q4YjwQwxRm4zxwDVtvUIoy4RLVCpqp5UoE+Nxv2PY9trg==} + '@tanstack/react-router@1.143.4': + resolution: {integrity: sha512-7Tz7YwJc8RKDQga3yNY03zNc/ey+AIDA1A5ppGYqIM+UR47uGdAKc/4MSpItznqkSUi1Csrw2nVtICSkGanKdQ==} engines: {node: '>=12'} peerDependencies: react: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0' - '@tanstack/react-start-client@1.141.6': - resolution: {integrity: sha512-3RqVb7CUHvI4tQE9dI8QGiUKbS4xWvvABbC5BqKoKHn+/h392t2mZIc4u+BUo6lAbz1HyVe2b9aZuhjSLtTmtw==} + '@tanstack/react-start-client@1.143.4': + resolution: {integrity: sha512-83CnzYZki6zA/WUPAABQ3dVlMcwNCSAJdwwAJ6d3MJbryKROjqT8DnmAqa/eRoIeSkC1GCHgubPOGG1LAfY/QQ==} engines: {node: '>=22.12.0'} peerDependencies: react: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0' - '@tanstack/react-start-server@1.141.6': - resolution: {integrity: sha512-EmOtW2wqm8P7N44wCDQp0HOjRW0tmPSgAzlmw+2x++slNR+zf6OaGSiuHtP2WCpLVLvwDCX/KCIWIsw0uUXMSg==} + '@tanstack/react-start-server@1.143.4': + resolution: {integrity: sha512-mj5r5f1QTC+80cvoNOCiHrXZz2F4RHjhXmjt7cvukRsKsoWQkqo61IRH3llpJt2Tmrkib0rvnlG6k+DzKJrNrQ==} engines: {node: '>=22.12.0'} peerDependencies: react: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0' - '@tanstack/react-start@1.141.7': - resolution: {integrity: sha512-INzKDLYXApEI3ww5ZhyIqLmzJfpLQ1Bgw7cf9OP3R3MgongR8x8nmr+GZ0NraICeR2ITVHt2MjCH5+l6B7EB5Q==} + '@tanstack/react-start@1.143.4': + resolution: {integrity: sha512-dW1aKcb3UMjFOduzc2BSXoxhjc6iU6pgveE6TDmeK8luPIJH8XhBZZlCSlGSzNrLfZ90EhKiwzw9ObAbKpPyZQ==} engines: {node: '>=22.12.0'} peerDependencies: react: '>=18.0.0 || >=19.0.0' @@ -2056,31 +2128,38 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/router-core@1.141.6': - resolution: {integrity: sha512-AqH61axLq2xFaM+B0veGQ4OOzMzr2Ih+qXzBmGRy5e0wMJkr1efPZXLF0K7nEjF++bmL/excew2Br6v9xrZ/5g==} + '@tanstack/react-table@8.21.3': + resolution: {integrity: sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==} + engines: {node: '>=12'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + + '@tanstack/router-core@1.143.4': + resolution: {integrity: sha512-VlSXrYQ/oBoUUGJx6t93KfzGHeBvL6GOmKRouPbHNqKi4ueVnQ2PdRX+s9eZoDAdcVsgmS7YlTCRgIbh2sAQpA==} engines: {node: '>=12'} - '@tanstack/router-devtools-core@1.141.6': - resolution: {integrity: sha512-+qzAw16ELQWyj4bTX3zOIZDqGsq+AM6cRn1fp8/nzvw++TvN62k4hHAiRQn4EU+R03qjRUCE9315jzAf9Amslw==} + '@tanstack/router-devtools-core@1.143.4': + resolution: {integrity: sha512-f5uatl8LIlMS4O2uIQ/oh58pF62/N1qKrBPtYvc7B1Tvf16ER8Nr1t8d4a85MiQyyA4kgiqfnYryOfW+diLjwg==} engines: {node: '>=12'} peerDependencies: - '@tanstack/router-core': ^1.141.6 + '@tanstack/router-core': ^1.143.4 csstype: ^3.0.10 solid-js: '>=1.9.5' peerDependenciesMeta: csstype: optional: true - '@tanstack/router-generator@1.141.7': - resolution: {integrity: sha512-SgOI/PmG3IGRf5q9bbYVE9xH1tP1ah0jIzGiI2w1D1nlljU+rd1DpSY7kEr9P6EHJpwDeb50DNi4Aq1WbEljSQ==} + '@tanstack/router-generator@1.143.4': + resolution: {integrity: sha512-QBqJCNoXJQmWkoAR6VqSuA7nBUSf3y5p8t4JpbtLGUgQ7pLu03nUSjcnLqN84BednhpZXnh/Mw3jxnpA//UWCQ==} engines: {node: '>=12'} - '@tanstack/router-plugin@1.141.7': - resolution: {integrity: sha512-znYaRYaUIEl2uJ+lP2qkC//dKtowb2IwU7jOGa7ygnCRVpK3TcTUMezfyI67jfDiB0rM8ICj5sqONfhN9I/F2g==} + '@tanstack/router-plugin@1.143.4': + resolution: {integrity: sha512-gjqkdAHJ8lZ1pOcK2noboyLKtbwIH59H/3/a4OQu30yNmuRnDTN75OrSBMvHvgYnXM3a0qUo9uFCphsRbS9N6g==} engines: {node: '>=12'} peerDependencies: '@rsbuild/core': '>=1.0.2' - '@tanstack/react-router': ^1.141.6 + '@tanstack/react-router': ^1.143.4 vite: '>=5.0.0 || >=6.0.0 || >=7.0.0' vite-plugin-solid: ^2.11.10 webpack: '>=5.92.0' @@ -2096,8 +2175,8 @@ packages: webpack: optional: true - '@tanstack/router-ssr-query-core@1.141.6': - resolution: {integrity: sha512-Eg1ytbJUs7213LlKiektBNm9eiSD5/nK6NzNVAXi5LCyfI+QUyEsJvrsm2q7wV7Aas0twSYzS/kKZQIpxYS2XA==} + '@tanstack/router-ssr-query-core@1.143.4': + resolution: {integrity: sha512-76/dJNygkm0uG+AMqK94zXi0wbx1h76KKQ6AZUYT1g2fxwmzK1szsTLwBhGusuNKYz0Ause5MzsbJYJ4Nb3KuA==} engines: {node: '>=12'} peerDependencies: '@tanstack/query-core': '>=5.90.0' @@ -2107,71 +2186,63 @@ packages: resolution: {integrity: sha512-/eFGKCiix1SvjxwgzrmH4pHjMiMxc+GA4nIbgEkG2RdAJqyxLcRhd7RPLG0/LZaJ7d0ad3jrtRqsHLv2152Vbw==} engines: {node: '>=12'} - '@tanstack/server-functions-plugin@1.141.3': - resolution: {integrity: sha512-yHgVvw6mYwINyv2wGjCnk9Dw5yfsyGu5bAIptr3v6E9dByRVo3KexXhtxNM3vj++YEHYMQSbgCoxiVKp9cu5Iw==} + '@tanstack/server-functions-plugin@1.142.1': + resolution: {integrity: sha512-ltTOj6dIDlRV3M8+PzontDYFMnIQ+icUnD+OKzIRfKo6bbvC0qvy8ttuWmVJxmqHy9xsWgkNt4gZrKVjtWXIhQ==} engines: {node: '>=12'} - '@tanstack/start-client-core@1.141.6': - resolution: {integrity: sha512-6plMbt8ceacAKZwtpVpXxnZ0XhU2n4Vy0C9FLiin/iytpt4BHwm4mPsV4xQWFUgRBKvDtssQapyd+s61mPEshQ==} + '@tanstack/start-client-core@1.143.4': + resolution: {integrity: sha512-AZNMenaxSUE3LUzVAfOhx3tqbsQ+BVWlQHO5rmqTdHpiayqkCMcmXWwjLawuYBNo7lWxmAsXIDsI3rKyUq7mvg==} + engines: {node: '>=22.12.0'} + + '@tanstack/start-fn-stubs@1.142.9': + resolution: {integrity: sha512-wQL0l3AowOagUWklcfzmM78UuNOun9ziqu4/GhMw95wBLVAtAdXThMg8yjQfZwNWcNq1ebxISbz1XAjTudvJ1Q==} engines: {node: '>=22.12.0'} - '@tanstack/start-plugin-core@1.141.7': - resolution: {integrity: sha512-BWAnNQVE+KbcwhJHNVFLa/xpnESgo4EYLYE0XatQ6w1OppAyYnzKXGVon8jJy+0VUYnrNySuxlIT24f6fF5PKA==} + '@tanstack/start-plugin-core@1.143.4': + resolution: {integrity: sha512-kwqofplhEQUAZ7cLxCNh3+1AP4NkcQqw0JE1rGFIXDCmLBMMmUwOC1V6N7/MtCI3ly626xadAxtq8x7yCVeD4Q==} engines: {node: '>=22.12.0'} peerDependencies: vite: '>=7.0.0' - '@tanstack/start-server-core@1.141.6': - resolution: {integrity: sha512-RWTvjzyIgNlAdi7WyEBRF1/AhiEhY+B9ug9cWadu8SOcfgXvmNaE9Mjrkw0RKsZIf+f1lVWwiToYQ3yBm1pM6A==} + '@tanstack/start-server-core@1.143.4': + resolution: {integrity: sha512-Sn4nYtFQ3jRWHyKt/LePJzBHlj3WyTdUzXd04oDfs9tryl9T7if8SyDj6iXI7SYU+n5cnCAkbYZ4MS8gmFnP5Q==} engines: {node: '>=22.12.0'} - '@tanstack/start-storage-context@1.141.6': - resolution: {integrity: sha512-IBQVJ21lUT1L4Up2tYFjZwHHMmf53oq86cDE/QT3uKH8ia5ozo5jcsqn2mHg2TpJCJYivYwZ06UtQzdVNX2wnQ==} + '@tanstack/start-storage-context@1.143.4': + resolution: {integrity: sha512-XIh9pDOWIZMoJDVBpDsvJ8xYg2qVK+cYVsvuhxqiCOOG/h4NvJfA3MWXl/W39rOzoC+dMZ8qNYMwYZ+GtUMKXg==} engines: {node: '>=22.12.0'} + '@tanstack/store@0.7.7': + resolution: {integrity: sha512-xa6pTan1bcaqYDS9BDpSiS63qa6EoDkPN9RsRaxHuDdVDNntzq3xNwR5YKTU/V3SkSyC9T4YVOPh2zRQN0nhIQ==} + '@tanstack/store@0.8.0': resolution: {integrity: sha512-Om+BO0YfMZe//X2z0uLF2j+75nQga6TpTJgLJQBiq85aOyZNIhkCgleNcud2KQg4k4v9Y9l+Uhru3qWMPGTOzQ==} + '@tanstack/table-core@8.21.3': + resolution: {integrity: sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==} + engines: {node: '>=12'} + '@tanstack/virtual-file-routes@1.141.0': resolution: {integrity: sha512-CJrWtr6L9TVzEImm9S7dQINx+xJcYP/aDkIi6gnaWtIgbZs1pnzsE0yJc2noqXZ+yAOqLx3TBGpBEs9tS0P9/A==} engines: {node: '>=12'} - '@testing-library/dom@10.4.1': - resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} - engines: {node: '>=18'} - - '@testing-library/react@16.3.1': - resolution: {integrity: sha512-gr4KtAWqIOQoucWYD/f6ki+j5chXfcPc74Col/6poTyqTmn7zRmodWahWRCp8tYd+GMqBonw6hstNzqjbs6gjw==} - 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 - - '@trpc/client@11.8.0': - resolution: {integrity: sha512-imJQeESX1hAapDaC4JB91yvXg41AZfBuTh/scnEiN/hAubZa5s/ikp0n+w29q2GCf+hREkr3WptUFKFJoDAIug==} + '@trpc/client@11.8.1': + resolution: {integrity: sha512-L/SJFGanr9xGABmuDoeXR4xAdHJmsXsiF9OuH+apecJ+8sUITzVT1EPeqp0ebqA6lBhEl5pPfg3rngVhi/h60Q==} peerDependencies: - '@trpc/server': 11.8.0 + '@trpc/server': 11.8.1 typescript: '>=5.7.2' - '@trpc/server@11.8.0': - resolution: {integrity: sha512-DphyQnLuyX2nwJCQGWQ9zYz4hZGvRhSBqDhQ0SH3tDhQ3PU4u68xofA0pJ741Ir4InEAFD+TtJVLAQy+wVOkiQ==} + '@trpc/server@11.8.1': + resolution: {integrity: sha512-P4rzZRpEL7zDFgjxK65IdyH0e41FMFfTkQkuq0BA5tKcr7E6v9/v38DEklCpoDN6sPiB1Sigy/PUEzHENhswDA==} peerDependencies: typescript: '>=5.7.2' - '@trpc/tanstack-react-query@11.8.0': - resolution: {integrity: sha512-LtLVyYzv5MjviBUElkCn1X246BCcq2j58N7mNxg4IqaR9Uvw9y7q6VdJMo5jWO9XogBVltgvHc5sZCJ+7IE1NQ==} + '@trpc/tanstack-react-query@11.8.1': + resolution: {integrity: sha512-0gBbRmRuU9/IVZgNFJuzY7k6ktnkmqjyP78PtcUBO7EgPlBu1y2MA2TdI5GT/VtNNOOhzkVeQpJqtt+0xQ8TOQ==} peerDependencies: '@tanstack/react-query': ^5.80.3 - '@trpc/client': 11.8.0 - '@trpc/server': 11.8.0 + '@trpc/client': 11.8.1 + '@trpc/server': 11.8.1 react: '>=18.2.0' react-dom: '>=18.2.0' typescript: '>=5.7.2' @@ -2179,9 +2250,6 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} - '@types/aria-query@5.0.4': - resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} - '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -2308,9 +2376,6 @@ packages: '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/katex@0.16.7': resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} @@ -2382,15 +2447,6 @@ packages: '@vitest/utils@4.0.16': resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==} - accepts@2.0.0: - resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} - engines: {node: '>= 0.6'} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.15.0: resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} @@ -2400,38 +2456,12 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} - ai@5.0.115: - resolution: {integrity: sha512-aVuHx0orGxXvhyL7oXUyW8TnWQE6Al8f3Bl6VZjz0WHMV+WaACHPkSyvQ3wje2QCUGzdl5DBF5d+OaXyghPQyg==} + ai@6.0.3: + resolution: {integrity: sha512-OOo+/C+sEyscoLnbY3w42vjQDICioVNyS+F+ogwq6O5RJL/vgWGuiLzFwuP7oHTeni/MkmX8tIge48GTdaV7QQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 - ajv-formats@3.0.1: - resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - ansis@4.2.0: resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} engines: {node: '>=14'} @@ -2443,9 +2473,6 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -2454,8 +2481,8 @@ packages: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} - aws-cdk-lib@2.232.2: - resolution: {integrity: sha512-jrAxZy5mvSM9YVuF1M++hP8IIGyNmPzW8+C5nnvOnx+eYuySRiCSAzKVKlvB+UNpA0VEVCDNyTxKiu0mFBeg/g==} + aws-cdk-lib@2.233.0: + resolution: {integrity: sha512-rBOzIA8TGC5eB8TyVIvckAVlX7a0/gVPE634FguhSee9RFaovjgc5+IixGyyLJhu3lLsMSjqDoqTJg2ab+p8ng==} engines: {node: '>= 18.0.0'} peerDependencies: constructs: ^10.0.0 @@ -2483,12 +2510,12 @@ packages: babel-dead-code-elimination@1.0.11: resolution: {integrity: sha512-mwq3W3e/pKSI6TG8lXMiDWvEi1VXYlSBlJlB3l+I0bAb5u1RNUl88udos85eOPNK3m5EXK9uO7d2g08pesTySQ==} + babel-plugin-react-compiler@1.0.0: + resolution: {integrity: sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==} + bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - baseline-browser-mapping@2.9.10: resolution: {integrity: sha512-2VIKvDx8Z1a9rTB2eCkdPE5nSe28XnA+qivGnWHoB40hMMt/h1hSz0960Zqsn6ZyxWXUie0EBdElKv8may20AA==} hasBin: true @@ -2500,19 +2527,12 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - body-parser@2.2.1: - resolution: {integrity: sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==} - engines: {node: '>=18'} - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} bowser@2.13.1: resolution: {integrity: sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==} - brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -2522,42 +2542,16 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - - call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - caniuse-lite@1.0.30001760: resolution: {integrity: sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - cdk-nag@2.37.55: - resolution: {integrity: sha512-xcAkygwbph3pp7N0UEzJBmXUH/MIsluV7DYJSeZ/V3yCr0Y0QaRGO298WyD6mi4K+Rmnpl+EJoWUxcOblOqLKA==} - peerDependencies: - aws-cdk-lib: ^2.176.0 - constructs: ^10.0.5 - chai@6.2.1: resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==} engines: {node: '>=18'} - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - chalk@5.6.2: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} @@ -2600,13 +2594,6 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -2618,9 +2605,6 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} @@ -2631,46 +2615,22 @@ packages: constructs@10.4.4: resolution: {integrity: sha512-lP0qC1oViYf1cutHo9/KQ8QL637f/W29tDmv/6sy35F5zs+MD9f66nbAAIjicwc7fwyuF3rkg6PhZh4sfvWIpA==} - content-disposition@1.0.1: - resolution: {integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==} - engines: {node: '>=18'} - - content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} cookie-es@2.0.0: resolution: {integrity: sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg==} - cookie-signature@1.2.2: - resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} - engines: {node: '>=6.6.0'} - - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} - copy-anything@4.0.5: resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==} engines: {node: '>=18'} - cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - cose-base@1.0.3: resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} cose-base@2.2.0: resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - crossws@0.4.1: resolution: {integrity: sha512-E7WKBcHVhAVrY6JYD5kteNqVq1GSZxqGrdSiwXR9at+XHi43HJoCQKXcCczR5LBnBquFZPsB3o7HklulKoBU5w==} peerDependencies: @@ -2898,16 +2858,9 @@ packages: decode-named-character-reference@1.2.0: resolution: {integrity: sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==} - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} - depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -2923,9 +2876,6 @@ packages: resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} engines: {node: '>=0.3.1'} - dom-accessibility-api@0.5.16: - resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} - dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -2942,20 +2892,12 @@ packages: domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + electrodb@3.5.0: + resolution: {integrity: sha512-msJyMTQmx6AC/otRKSre0rktE3E0RUw7ez9u2F25ZU4iXEqzxeu/OyRJcR53hh+jv4Fefi/3F9R+JopgIUZJHQ==} electron-to-chromium@1.5.267: resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} - encodeurl@2.0.0: - resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} - engines: {node: '>= 0.8'} - encoding-sniffer@0.2.1: resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} @@ -2971,21 +2913,9 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - esbuild@0.25.12: resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} @@ -3000,126 +2930,49 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} - escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} - eslint-cdk-plugin@3.4.7: - resolution: {integrity: sha512-adiMtnibZ5j67CiUyOoOQNGrLFpLcGoUqD/2TZz2bx5TodhAwD1B0MLmC1yiR7eLp67Om0SRE2yNAYizv/BdGQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' - - eslint-scope@8.4.0: - resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@4.2.1: - resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint@9.39.1: - resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - espree@10.4.0: - resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - estree-util-is-identifier-name@3.0.0: resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} 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'} - - etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - eventsource-parser@3.0.6: resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} engines: {node: '>=18.0.0'} - eventsource@3.0.7: - resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} - engines: {node: '>=18.0.0'} - expect-type@1.3.0: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} - express-rate-limit@7.5.1: - resolution: {integrity: sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==} - engines: {node: '>= 16'} - peerDependencies: - express: '>= 4.11' - - express@5.2.1: - resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} - engines: {node: '>= 18'} - exsolve@1.0.8: resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} fast-xml-parser@5.2.5: resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} hasBin: true + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fd-package-json@2.0.0: + resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -3129,44 +2982,19 @@ packages: picomatch: optional: true - fetchdts@0.1.7: - resolution: {integrity: sha512-YoZjBdafyLIop9lSxXVI33oLD5kN31q4Td+CasofLLYeLXRFeOsuOw0Uo+XNRi9PZlbfdlN2GmRtm4tCEQ9/KA==} - - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - finalhandler@2.1.1: - resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} - engines: {node: '>= 18.0.0'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flatted@3.3.3: - resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} - - forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} + formatly@0.3.0: + resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==} + engines: {node: '>=18.3.0'} + hasBin: true fractional-indexing@3.2.0: resolution: {integrity: sha512-PcOxmqwYCW7O2ovKRU8OoQQj2yqTfEB/yeTYk4gPid6dN5ODRfU1hXd9tTVZzax/0NkO7AxpHykvZnT1aYp/BQ==} engines: {node: ^14.13.1 || >=16.0.0} - fresh@2.0.0: - resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} - engines: {node: '>= 0.8'} - fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -3177,9 +3005,6 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -3188,14 +3013,6 @@ packages: resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} engines: {node: '>=18'} - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - get-tsconfig@4.13.0: resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} @@ -3203,14 +3020,6 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} @@ -3219,15 +3028,11 @@ packages: peerDependencies: csstype: ^3.0.10 - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - h3@2.0.0-beta.5: - resolution: {integrity: sha512-ApIkLH+nTxzCC0Nq/GN1v6jkvu2eOLfdTnTs6ghiuG1EYHWJBDLzhk5tn7SZMEUNsLUjG4qfmqzBx2LG9I7Q/w==} + h3@2.0.1-rc.5: + resolution: {integrity: sha512-qkohAzCab0nLzXNm78tBjZDvtKMTmtygS8BJLT3VPczAQofdqlFXDPkXdLMJN4r05+xqneG8snZJ0HgkERCZTg==} engines: {node: '>=20.11.1'} peerDependencies: crossws: ^0.4.1 @@ -3235,8 +3040,8 @@ packages: crossws: optional: true - h3@2.0.1-rc.5: - resolution: {integrity: sha512-qkohAzCab0nLzXNm78tBjZDvtKMTmtygS8BJLT3VPczAQofdqlFXDPkXdLMJN4r05+xqneG8snZJ0HgkERCZTg==} + h3@2.0.1-rc.6: + resolution: {integrity: sha512-kKLFVFNJlDVTbQjakz1ZTFSHB9+oi9+Khf0v7xQsUKU3iOqu2qmrFzTD56YsDvvj2nBgqVDphGRXB2VRursw4w==} engines: {node: '>=20.11.1'} peerDependencies: crossws: ^0.4.1 @@ -3247,18 +3052,6 @@ packages: hachure-fill@0.5.2: resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - hast-util-from-dom@5.0.1: resolution: {integrity: sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==} @@ -3306,10 +3099,6 @@ packages: resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} engines: {node: '>=12.0.0'} - hono@4.11.1: - resolution: {integrity: sha512-KsFcH0xxHes0J4zaQgWbYwmz3UPOOskdqZmItstUG93+Wk1ePBLkLGwbP9zlmh1BFUiL8Qp+Xfu9P7feJWpGNg==} - engines: {node: '>=16.9.0'} - html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} @@ -3323,10 +3112,6 @@ packages: htmlparser2@10.0.0: resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} - http-errors@2.0.1: - resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} - engines: {node: '>= 0.8'} - http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} @@ -3339,25 +3124,6 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} - iconv-lite@0.7.1: - resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==} - engines: {node: '>=0.10.0'} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - inline-style-parser@0.2.7: resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} @@ -3368,10 +3134,6 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - is-alphabetical@2.0.1: resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} @@ -3407,9 +3169,6 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - is-promise@4.0.0: - resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - is-what@5.5.0: resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} engines: {node: '>=18'} @@ -3418,16 +3177,10 @@ packages: resolution: {integrity: sha512-VNfjM73zz2IBZmdShMfAUg10prm6t7HFUQmNAEOAVS4YH92ZrZcvkMcGX6cIgBJAzWDzPent/EeAtYEHNPNPBQ==} engines: {node: '>=18'} - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true - jose@6.1.3: - resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3449,39 +3202,32 @@ packages: engines: {node: '>=6'} hasBin: true - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - - json-schema-typed@8.0.2: - resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} - json-schema@0.4.0: resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true + jsonschema@1.2.7: + resolution: {integrity: sha512-3dFMg9hmI9LdHag/BRIhMefCfbq1hicvYMy8YhZQorAdzOzWz7NjniSpn39yjpzUAMIWtGyyZuH2KNBloH7ZLw==} + katex@0.16.27: resolution: {integrity: sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw==} hasBin: true - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - khroma@2.1.0: resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} + knip@5.77.1: + resolution: {integrity: sha512-+yA/vfQUDEFUOcR0XRn/dOZmNEsS10pIMztS5JbKUhk9zvQiAFvr3Mcc3zC7Dn9gBG8LeImhaXA6/D3uhzwZvg==} + engines: {node: '>=18.18.0'} + hasBin: true + peerDependencies: + '@types/node': '>=18' + typescript: '>=5.0.4 <7' + langium@3.3.1: resolution: {integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==} engines: {node: '>=16.0.0'} @@ -3495,10 +3241,6 @@ packages: layout-base@2.0.1: resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - lightningcss-android-arm64@1.30.2: resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} engines: {node: '>= 12.0.0'} @@ -3573,19 +3315,12 @@ packages: resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} engines: {node: '>= 12.0.0'} - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} lodash-es@4.17.22: resolution: {integrity: sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==} - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -3606,10 +3341,6 @@ packages: 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==} @@ -3621,10 +3352,6 @@ packages: engines: {node: '>= 20'} hasBin: true - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - mdast-util-find-and-replace@3.0.2: resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} @@ -3676,13 +3403,9 @@ packages: mdn-data@2.12.2: resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} - media-typer@1.1.0: - resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} - engines: {node: '>= 0.8'} - - merge-descriptors@2.0.0: - resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} - engines: {node: '>=18'} + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} mermaid@11.12.2: resolution: {integrity: sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==} @@ -3803,16 +3526,12 @@ packages: micromark@4.0.2: resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} - mime-db@1.54.0: - resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} - engines: {node: '>= 0.6'} - - mime-types@3.0.2: - resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} - engines: {node: '>=18'} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} mlly@1.8.0: resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} @@ -3828,13 +3547,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - negotiator@1.0.0: - resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} - engines: {node: '>= 0.6'} - nf3@0.1.12: resolution: {integrity: sha512-qbMXT7RTGh74MYWPeqTIED8nDW70NXOULVHpdWcdZ7IVHVnAsMV9fNugSNnvooipDc1FMOzpis7T9nXJEbJhvQ==} @@ -3867,14 +3579,6 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - object-inspect@1.13.4: - resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} - engines: {node: '>= 0.4'} - obliterator@1.6.1: resolution: {integrity: sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==} @@ -3887,65 +3591,45 @@ packages: ohash@2.0.11: resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} - on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - oniguruma-parser@0.12.1: resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==} oniguruma-to-es@4.3.4: resolution: {integrity: sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==} - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - oxc-minify@0.96.0: resolution: {integrity: sha512-dXeeGrfPJJ4rMdw+NrqiCRtbzVX2ogq//R0Xns08zql2HjV3Zi2SBJ65saqfDaJzd2bcHqvGWH+M44EQCHPAcA==} engines: {node: ^20.19.0 || >=22.12.0} + oxc-resolver@11.16.1: + resolution: {integrity: sha512-eN5tLRx2oyyNpPyWWItuPiNLY/EpGlqXVJll+Uptds4owQ4UQK3T8rPlR+wl8xBKvQZM4drFC1nKVLeZDUWpQg==} + oxc-transform@0.96.0: resolution: {integrity: sha512-dQPNIF+gHpSkmC0+Vg9IktNyhcn28Y8R3eTLyzn52UNymkasLicl3sFAtz7oEVuFmCpgGjaUTKkwk+jW2cHpDQ==} engines: {node: ^20.19.0 || >=22.12.0} - oxfmt@0.18.0: - resolution: {integrity: sha512-XqVS+LQi7ARsFlIftB69+jGN2qQaJNBjQU2b9ZQYt+iaUV9digh+dBIsU0isQIZhaQ1ihxGFfsTYQXE/Oak8Qw==} + oxfmt@0.20.0: + resolution: {integrity: sha512-+7f8eV8iaK3tENN/FUVxZM1g78HjPehybN8/+/dvEA1O893Dcvk6O7/Q1wTQOHMD7wvdwWdujKl+Uo8QMiKDrQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - oxlint-tsgolint@0.9.1: - resolution: {integrity: sha512-w1lIvUDkkiAPFyo268SFGrdh1LQ3Lcs1XShES7I4X75TliQA0os5XJ5hNZ4lYsSevqcofgEtq4xq7rBumv69iQ==} + oxlint-tsgolint@0.10.0: + resolution: {integrity: sha512-LDDSIu5J/4D4gFUuQQIEQpAC6maNEbMg4nC8JL/+Pe0cUDR86dtVZ09E2x5MwCh8f9yfktoaxt5x6UIVyzrajg==} hasBin: true - oxlint@1.33.0: - resolution: {integrity: sha512-4WCL0K8jiOshwJ8WrVk35VAuVaZHC0iX6asjKsrENOrynkAAGcTLLx0Urf0eXZ1Tq7r+qAe3Z9EyHMFPzVyUkg==} + oxlint@1.35.0: + resolution: {integrity: sha512-QDX1aUgaiqznkGfTM2qHwva2wtKqhVoqPSVXrnPz+yLUhlNadikD3QRuRtppHl7WGuy3wG6nKAuR8lash3aWSg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - oxlint-tsgolint: '>=0.9.0' + oxlint-tsgolint: '>=0.10.0' peerDependenciesMeta: oxlint-tsgolint: optional: true - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - package-manager-detector@1.6.0: resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - parse-entities@4.0.2: resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} @@ -3961,24 +3645,9 @@ packages: parse5@8.0.0: resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} - parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - path-data-parser@0.1.0: resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-to-regexp@8.3.0: - resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} - pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -3993,10 +3662,6 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} - pkce-challenge@5.0.1: - resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} - engines: {node: '>=16.20.0'} - pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -4010,50 +3675,26 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - prettier@3.7.4: resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==} engines: {node: '>=14'} hasBin: true - 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} - property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} - proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - qs@6.14.0: - resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} - engines: {node: '>=0.6'} - - range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - - raw-body@3.0.2: - resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} - engines: {node: '>= 0.10'} + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} react-dom@19.2.3: resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} peerDependencies: react: ^19.2.3 - react-is@17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - react-refresh@0.18.0: resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} engines: {node: '>=0.10.0'} @@ -4130,18 +3771,18 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} - rolldown@1.0.0-beta.53: - resolution: {integrity: sha512-Qd9c2p0XKZdgT5AYd+KgAMggJ8ZmCs3JnS9PTMWkyUfteKlfmKtxJbWTHkVakxwXs1Ub7jrRYVeFeF7N0sQxyw==} + rolldown@1.0.0-beta.56: + resolution: {integrity: sha512-9MHiUvRH2R8rb6ad6EaLxahS3RbQKdMMlrh9XKmbz2HiCGfK4IWKSNv4N6GhYr+7kHExg6oIc5EF1xA3iR4x1A==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -4159,9 +3800,8 @@ packages: roughjs@4.6.6: resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} - router@2.2.0: - resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} - engines: {node: '>= 18'} + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} rw@1.3.3: resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} @@ -4180,10 +3820,6 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - send@1.2.1: - resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} - engines: {node: '>= 18'} - seroval-plugins@1.3.3: resolution: {integrity: sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w==} engines: {node: '>=10'} @@ -4200,25 +3836,10 @@ packages: resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==} engines: {node: '>=10'} - seroval@1.4.0: - resolution: {integrity: sha512-BdrNXdzlofomLTiRnwJTSEAaGKyHHZkbMXIywOh7zlzp4uZnXErEwl9XZ+N1hJSNpeTtNxWvVwN0wUzAIQ4Hpg==} + seroval@1.4.1: + resolution: {integrity: sha512-9GOc+8T6LN4aByLN75uRvMbrwY5RDBW6lSlknsY4LEa9ZmWcxKcRe1G/Q3HZXjltxMHTrStnvrwAICxZrhldtg==} engines: {node: '>=10'} - serve-static@2.2.1: - resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} - engines: {node: '>= 18'} - - setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - shell-quote@1.8.3: resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} engines: {node: '>= 0.4'} @@ -4226,25 +3847,13 @@ packages: shiki@3.20.0: resolution: {integrity: sha512-kgCOlsnyWb+p0WU+01RjkCH+eBVsjL1jOwUYWv0YDWkM2/A46+LDKVs5yZCUXjJG6bj4ndFoAg5iLIIue6dulg==} - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + smol-toml@1.6.0: + resolution: {integrity: sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==} + engines: {node: '>= 18'} + solid-js@1.9.10: resolution: {integrity: sha512-Coz956cos/EPDlhs6+jsdTxKuJDPT7B5SVIWgABwROyxjY7Xbr8wkzD68Et+NxnV7DLJ3nJdAC2r9InuV/4Jew==} @@ -4266,11 +3875,6 @@ packages: space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - srvx@0.8.16: - resolution: {integrity: sha512-hmcGW4CgroeSmzgF1Ihwgl+Ths0JqAJ7HwjP2X7e3JzY7u4IydLMcdnlqGQiQGUswz+PO9oh/KtCpOISIvs9QQ==} - engines: {node: '>=20.16.0'} - hasBin: true - srvx@0.9.7: resolution: {integrity: sha512-N2a2nx8YTq13+A8qucg4lHZREfWOVnlMHAvrA9C2jbY9/QnVEAPzjdmpFHrY6/9BxSwIbvywCj7zahuGrVzCiQ==} engines: {node: '>=20.16.0'} @@ -4284,10 +3888,6 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - statuses@2.0.2: - resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} - engines: {node: '>= 0.8'} - std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} @@ -4299,9 +3899,9 @@ packages: stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} strnum@2.1.2: resolution: {integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==} @@ -4319,10 +3919,6 @@ packages: resolution: {integrity: sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==} engines: {node: '>=16'} - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - swr@2.3.8: resolution: {integrity: sha512-gaCPRVoMq8WGDcWj9p4YWzCMPHzE0WNl6W8ADIx9c3JBEIdMkJGMzW+uzXvxHMltwcYACr9jP+32H8/hgwMR7w==} peerDependencies: @@ -4381,10 +3977,6 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - tough-cookie@6.0.0: resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} engines: {node: '>=16'} @@ -4424,14 +4016,6 @@ packages: tw-animate-css@1.4.0: resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - type-is@2.0.1: - resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} - engines: {node: '>= 0.6'} - typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -4474,10 +4058,6 @@ packages: unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} - unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - unplugin@2.3.11: resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} engines: {node: '>=18.12.0'} @@ -4562,9 +4142,6 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - use-sync-external-store@1.6.0: resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} peerDependencies: @@ -4574,10 +4151,6 @@ packages: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true - vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - vfile-location@5.0.3: resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} @@ -4635,8 +4208,8 @@ packages: yaml: optional: true - vite@8.0.0-beta.0: - resolution: {integrity: sha512-bXHWmtg5hUxn/MB5zJ8qhBLphnsNmO1EYOFmBO/fVCBJekTdWDuqJ/GmUMLgrC0QUCCrxhw3JLgteWdiyqaVSQ==} + vite@8.0.0-beta.4: + resolution: {integrity: sha512-fTUZD8GE4HLfiq4JnQoHYPQozsVzD6AfMhqnzG0+whHaM2HVSuS8rPlFdptONr4YDfnsbPigEiyDQ6ngmCtOYQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -4741,12 +4314,13 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} + walk-up-path@4.0.0: + resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} + engines: {node: 20 || >=22} + web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} - web-vitals@5.1.0: - resolution: {integrity: sha512-ArI3kx5jI0atlTtmV0fWU3fjpLmq/nD3Zr1iFFlJLaqa5wLBkUSzINwBPySCX/8jRyjlmy1Volw1kz1g9XE4Jg==} - webidl-conversions@8.0.0: resolution: {integrity: sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==} engines: {node: '>=20'} @@ -4766,23 +4340,11 @@ packages: resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} engines: {node: '>=20'} - 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'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.18.3: resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} engines: {node: '>=10.0.0'} @@ -4809,15 +4371,6 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - - zod-to-json-schema@3.25.0: - resolution: {integrity: sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==} - peerDependencies: - zod: ^3.25 || ^4 - zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} @@ -4831,12 +4384,12 @@ snapshots: '@acemir/cssom@0.9.29': {} - '@ai-sdk/amazon-bedrock@3.0.70(zod@4.2.1)': + '@ai-sdk/amazon-bedrock@3.0.72(zod@4.2.1)': dependencies: '@ai-sdk/anthropic': 2.0.56(zod@4.2.1) '@ai-sdk/provider': 2.0.0 '@ai-sdk/provider-utils': 3.0.19(zod@4.2.1) - '@smithy/eventstream-codec': 4.2.6 + '@smithy/eventstream-codec': 4.2.7 '@smithy/util-utf8': 4.2.0 aws4fetch: 1.0.20 zod: 4.2.1 @@ -4847,23 +4400,23 @@ snapshots: '@ai-sdk/provider-utils': 3.0.19(zod@4.2.1) zod: 4.2.1 - '@ai-sdk/gateway@2.0.22(zod@4.2.1)': + '@ai-sdk/gateway@3.0.2(zod@4.2.1)': dependencies: - '@ai-sdk/provider': 2.0.0 - '@ai-sdk/provider-utils': 3.0.19(zod@4.2.1) + '@ai-sdk/provider': 3.0.0 + '@ai-sdk/provider-utils': 4.0.1(zod@4.2.1) '@vercel/oidc': 3.0.5 zod: 4.2.1 - '@ai-sdk/mcp@0.0.12(zod@4.2.1)': + '@ai-sdk/provider-utils@3.0.19(zod@4.2.1)': dependencies: '@ai-sdk/provider': 2.0.0 - '@ai-sdk/provider-utils': 3.0.19(zod@4.2.1) - pkce-challenge: 5.0.1 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.0.6 zod: 4.2.1 - '@ai-sdk/provider-utils@3.0.19(zod@4.2.1)': + '@ai-sdk/provider-utils@4.0.1(zod@4.2.1)': dependencies: - '@ai-sdk/provider': 2.0.0 + '@ai-sdk/provider': 3.0.0 '@standard-schema/spec': 1.1.0 eventsource-parser: 3.0.6 zod: 4.2.1 @@ -4872,15 +4425,19 @@ snapshots: dependencies: json-schema: 0.4.0 - '@ai-sdk/react@2.0.117(react@19.2.3)(zod@4.2.1)': + '@ai-sdk/provider@3.0.0': dependencies: - '@ai-sdk/provider-utils': 3.0.19(zod@4.2.1) - ai: 5.0.115(zod@4.2.1) + json-schema: 0.4.0 + + '@ai-sdk/react@3.0.3(react@19.2.3)(zod@4.2.1)': + dependencies: + '@ai-sdk/provider-utils': 4.0.1(zod@4.2.1) + ai: 6.0.3(zod@4.2.1) react: 19.2.3 swr: 2.3.8(react@19.2.3) throttleit: 2.1.0 - optionalDependencies: - zod: 4.2.1 + transitivePeerDependencies: + - zod '@antfu/install-pkg@1.1.0': dependencies: @@ -4914,7 +4471,7 @@ snapshots: '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.953.0 + '@aws-sdk/types': 3.957.0 tslib: 2.8.1 '@aws-crypto/sha256-browser@5.2.0': @@ -4922,15 +4479,15 @@ 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.953.0 - '@aws-sdk/util-locate-window': 3.953.0 + '@aws-sdk/types': 3.957.0 + '@aws-sdk/util-locate-window': 3.957.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.953.0 + '@aws-sdk/types': 3.957.0 tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': @@ -4939,393 +4496,393 @@ snapshots: '@aws-crypto/util@5.2.0': dependencies: - '@aws-sdk/types': 3.936.0 + '@aws-sdk/types': 3.957.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-dynamodb@3.954.0': + '@aws-sdk/client-dynamodb@3.958.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.954.0 - '@aws-sdk/credential-provider-node': 3.954.0 - '@aws-sdk/dynamodb-codec': 3.954.0(@aws-sdk/client-dynamodb@3.954.0) - '@aws-sdk/middleware-endpoint-discovery': 3.953.0 - '@aws-sdk/middleware-host-header': 3.953.0 - '@aws-sdk/middleware-logger': 3.953.0 - '@aws-sdk/middleware-recursion-detection': 3.953.0 - '@aws-sdk/middleware-user-agent': 3.954.0 - '@aws-sdk/region-config-resolver': 3.953.0 - '@aws-sdk/types': 3.953.0 - '@aws-sdk/util-endpoints': 3.953.0 - '@aws-sdk/util-user-agent-browser': 3.953.0 - '@aws-sdk/util-user-agent-node': 3.954.0 - '@smithy/config-resolver': 4.4.4 - '@smithy/core': 3.19.0 - '@smithy/fetch-http-handler': 5.3.7 - '@smithy/hash-node': 4.2.6 - '@smithy/invalid-dependency': 4.2.6 - '@smithy/middleware-content-length': 4.2.6 - '@smithy/middleware-endpoint': 4.4.0 - '@smithy/middleware-retry': 4.4.16 - '@smithy/middleware-serde': 4.2.7 - '@smithy/middleware-stack': 4.2.6 - '@smithy/node-config-provider': 4.3.6 - '@smithy/node-http-handler': 4.4.6 - '@smithy/protocol-http': 5.3.6 - '@smithy/smithy-client': 4.10.1 - '@smithy/types': 4.10.0 - '@smithy/url-parser': 4.2.6 + '@aws-sdk/core': 3.957.0 + '@aws-sdk/credential-provider-node': 3.958.0 + '@aws-sdk/dynamodb-codec': 3.957.0(@aws-sdk/client-dynamodb@3.958.0) + '@aws-sdk/middleware-endpoint-discovery': 3.957.0 + '@aws-sdk/middleware-host-header': 3.957.0 + '@aws-sdk/middleware-logger': 3.957.0 + '@aws-sdk/middleware-recursion-detection': 3.957.0 + '@aws-sdk/middleware-user-agent': 3.957.0 + '@aws-sdk/region-config-resolver': 3.957.0 + '@aws-sdk/types': 3.957.0 + '@aws-sdk/util-endpoints': 3.957.0 + '@aws-sdk/util-user-agent-browser': 3.957.0 + '@aws-sdk/util-user-agent-node': 3.957.0 + '@smithy/config-resolver': 4.4.5 + '@smithy/core': 3.20.0 + '@smithy/fetch-http-handler': 5.3.8 + '@smithy/hash-node': 4.2.7 + '@smithy/invalid-dependency': 4.2.7 + '@smithy/middleware-content-length': 4.2.7 + '@smithy/middleware-endpoint': 4.4.1 + '@smithy/middleware-retry': 4.4.17 + '@smithy/middleware-serde': 4.2.8 + '@smithy/middleware-stack': 4.2.7 + '@smithy/node-config-provider': 4.3.7 + '@smithy/node-http-handler': 4.4.7 + '@smithy/protocol-http': 5.3.7 + '@smithy/smithy-client': 4.10.2 + '@smithy/types': 4.11.0 + '@smithy/url-parser': 4.2.7 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.15 - '@smithy/util-defaults-mode-node': 4.2.18 - '@smithy/util-endpoints': 3.2.6 - '@smithy/util-middleware': 4.2.6 - '@smithy/util-retry': 4.2.6 + '@smithy/util-defaults-mode-browser': 4.3.16 + '@smithy/util-defaults-mode-node': 4.2.19 + '@smithy/util-endpoints': 3.2.7 + '@smithy/util-middleware': 4.2.7 + '@smithy/util-retry': 4.2.7 '@smithy/util-utf8': 4.2.0 - '@smithy/util-waiter': 4.2.6 + '@smithy/util-waiter': 4.2.7 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso@3.954.0': + '@aws-sdk/client-sso@3.958.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.954.0 - '@aws-sdk/middleware-host-header': 3.953.0 - '@aws-sdk/middleware-logger': 3.953.0 - '@aws-sdk/middleware-recursion-detection': 3.953.0 - '@aws-sdk/middleware-user-agent': 3.954.0 - '@aws-sdk/region-config-resolver': 3.953.0 - '@aws-sdk/types': 3.953.0 - '@aws-sdk/util-endpoints': 3.953.0 - '@aws-sdk/util-user-agent-browser': 3.953.0 - '@aws-sdk/util-user-agent-node': 3.954.0 - '@smithy/config-resolver': 4.4.4 - '@smithy/core': 3.19.0 - '@smithy/fetch-http-handler': 5.3.7 - '@smithy/hash-node': 4.2.6 - '@smithy/invalid-dependency': 4.2.6 - '@smithy/middleware-content-length': 4.2.6 - '@smithy/middleware-endpoint': 4.4.0 - '@smithy/middleware-retry': 4.4.16 - '@smithy/middleware-serde': 4.2.7 - '@smithy/middleware-stack': 4.2.6 - '@smithy/node-config-provider': 4.3.6 - '@smithy/node-http-handler': 4.4.6 - '@smithy/protocol-http': 5.3.6 - '@smithy/smithy-client': 4.10.1 - '@smithy/types': 4.10.0 - '@smithy/url-parser': 4.2.6 + '@aws-sdk/core': 3.957.0 + '@aws-sdk/middleware-host-header': 3.957.0 + '@aws-sdk/middleware-logger': 3.957.0 + '@aws-sdk/middleware-recursion-detection': 3.957.0 + '@aws-sdk/middleware-user-agent': 3.957.0 + '@aws-sdk/region-config-resolver': 3.957.0 + '@aws-sdk/types': 3.957.0 + '@aws-sdk/util-endpoints': 3.957.0 + '@aws-sdk/util-user-agent-browser': 3.957.0 + '@aws-sdk/util-user-agent-node': 3.957.0 + '@smithy/config-resolver': 4.4.5 + '@smithy/core': 3.20.0 + '@smithy/fetch-http-handler': 5.3.8 + '@smithy/hash-node': 4.2.7 + '@smithy/invalid-dependency': 4.2.7 + '@smithy/middleware-content-length': 4.2.7 + '@smithy/middleware-endpoint': 4.4.1 + '@smithy/middleware-retry': 4.4.17 + '@smithy/middleware-serde': 4.2.8 + '@smithy/middleware-stack': 4.2.7 + '@smithy/node-config-provider': 4.3.7 + '@smithy/node-http-handler': 4.4.7 + '@smithy/protocol-http': 5.3.7 + '@smithy/smithy-client': 4.10.2 + '@smithy/types': 4.11.0 + '@smithy/url-parser': 4.2.7 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.15 - '@smithy/util-defaults-mode-node': 4.2.18 - '@smithy/util-endpoints': 3.2.6 - '@smithy/util-middleware': 4.2.6 - '@smithy/util-retry': 4.2.6 + '@smithy/util-defaults-mode-browser': 4.3.16 + '@smithy/util-defaults-mode-node': 4.2.19 + '@smithy/util-endpoints': 3.2.7 + '@smithy/util-middleware': 4.2.7 + '@smithy/util-retry': 4.2.7 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.954.0': - dependencies: - '@aws-sdk/types': 3.953.0 - '@aws-sdk/xml-builder': 3.953.0 - '@smithy/core': 3.19.0 - '@smithy/node-config-provider': 4.3.6 - '@smithy/property-provider': 4.2.6 - '@smithy/protocol-http': 5.3.6 - '@smithy/signature-v4': 5.3.6 - '@smithy/smithy-client': 4.10.1 - '@smithy/types': 4.10.0 + '@aws-sdk/core@3.957.0': + dependencies: + '@aws-sdk/types': 3.957.0 + '@aws-sdk/xml-builder': 3.957.0 + '@smithy/core': 3.20.0 + '@smithy/node-config-provider': 4.3.7 + '@smithy/property-provider': 4.2.7 + '@smithy/protocol-http': 5.3.7 + '@smithy/signature-v4': 5.3.7 + '@smithy/smithy-client': 4.10.2 + '@smithy/types': 4.11.0 '@smithy/util-base64': 4.3.0 - '@smithy/util-middleware': 4.2.6 + '@smithy/util-middleware': 4.2.7 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.954.0': + '@aws-sdk/credential-provider-env@3.957.0': dependencies: - '@aws-sdk/core': 3.954.0 - '@aws-sdk/types': 3.953.0 - '@smithy/property-provider': 4.2.6 - '@smithy/types': 4.10.0 + '@aws-sdk/core': 3.957.0 + '@aws-sdk/types': 3.957.0 + '@smithy/property-provider': 4.2.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.954.0': - dependencies: - '@aws-sdk/core': 3.954.0 - '@aws-sdk/types': 3.953.0 - '@smithy/fetch-http-handler': 5.3.7 - '@smithy/node-http-handler': 4.4.6 - '@smithy/property-provider': 4.2.6 - '@smithy/protocol-http': 5.3.6 - '@smithy/smithy-client': 4.10.1 - '@smithy/types': 4.10.0 - '@smithy/util-stream': 4.5.7 + '@aws-sdk/credential-provider-http@3.957.0': + dependencies: + '@aws-sdk/core': 3.957.0 + '@aws-sdk/types': 3.957.0 + '@smithy/fetch-http-handler': 5.3.8 + '@smithy/node-http-handler': 4.4.7 + '@smithy/property-provider': 4.2.7 + '@smithy/protocol-http': 5.3.7 + '@smithy/smithy-client': 4.10.2 + '@smithy/types': 4.11.0 + '@smithy/util-stream': 4.5.8 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.954.0': - dependencies: - '@aws-sdk/core': 3.954.0 - '@aws-sdk/credential-provider-env': 3.954.0 - '@aws-sdk/credential-provider-http': 3.954.0 - '@aws-sdk/credential-provider-login': 3.954.0 - '@aws-sdk/credential-provider-process': 3.954.0 - '@aws-sdk/credential-provider-sso': 3.954.0 - '@aws-sdk/credential-provider-web-identity': 3.954.0 - '@aws-sdk/nested-clients': 3.954.0 - '@aws-sdk/types': 3.953.0 - '@smithy/credential-provider-imds': 4.2.6 - '@smithy/property-provider': 4.2.6 - '@smithy/shared-ini-file-loader': 4.4.1 - '@smithy/types': 4.10.0 + '@aws-sdk/credential-provider-ini@3.958.0': + dependencies: + '@aws-sdk/core': 3.957.0 + '@aws-sdk/credential-provider-env': 3.957.0 + '@aws-sdk/credential-provider-http': 3.957.0 + '@aws-sdk/credential-provider-login': 3.958.0 + '@aws-sdk/credential-provider-process': 3.957.0 + '@aws-sdk/credential-provider-sso': 3.958.0 + '@aws-sdk/credential-provider-web-identity': 3.958.0 + '@aws-sdk/nested-clients': 3.958.0 + '@aws-sdk/types': 3.957.0 + '@smithy/credential-provider-imds': 4.2.7 + '@smithy/property-provider': 4.2.7 + '@smithy/shared-ini-file-loader': 4.4.2 + '@smithy/types': 4.11.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-login@3.954.0': + '@aws-sdk/credential-provider-login@3.958.0': dependencies: - '@aws-sdk/core': 3.954.0 - '@aws-sdk/nested-clients': 3.954.0 - '@aws-sdk/types': 3.953.0 - '@smithy/property-provider': 4.2.6 - '@smithy/protocol-http': 5.3.6 - '@smithy/shared-ini-file-loader': 4.4.1 - '@smithy/types': 4.10.0 + '@aws-sdk/core': 3.957.0 + '@aws-sdk/nested-clients': 3.958.0 + '@aws-sdk/types': 3.957.0 + '@smithy/property-provider': 4.2.7 + '@smithy/protocol-http': 5.3.7 + '@smithy/shared-ini-file-loader': 4.4.2 + '@smithy/types': 4.11.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-node@3.954.0': - dependencies: - '@aws-sdk/credential-provider-env': 3.954.0 - '@aws-sdk/credential-provider-http': 3.954.0 - '@aws-sdk/credential-provider-ini': 3.954.0 - '@aws-sdk/credential-provider-process': 3.954.0 - '@aws-sdk/credential-provider-sso': 3.954.0 - '@aws-sdk/credential-provider-web-identity': 3.954.0 - '@aws-sdk/types': 3.953.0 - '@smithy/credential-provider-imds': 4.2.6 - '@smithy/property-provider': 4.2.6 - '@smithy/shared-ini-file-loader': 4.4.1 - '@smithy/types': 4.10.0 + '@aws-sdk/credential-provider-node@3.958.0': + dependencies: + '@aws-sdk/credential-provider-env': 3.957.0 + '@aws-sdk/credential-provider-http': 3.957.0 + '@aws-sdk/credential-provider-ini': 3.958.0 + '@aws-sdk/credential-provider-process': 3.957.0 + '@aws-sdk/credential-provider-sso': 3.958.0 + '@aws-sdk/credential-provider-web-identity': 3.958.0 + '@aws-sdk/types': 3.957.0 + '@smithy/credential-provider-imds': 4.2.7 + '@smithy/property-provider': 4.2.7 + '@smithy/shared-ini-file-loader': 4.4.2 + '@smithy/types': 4.11.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-process@3.954.0': + '@aws-sdk/credential-provider-process@3.957.0': dependencies: - '@aws-sdk/core': 3.954.0 - '@aws-sdk/types': 3.953.0 - '@smithy/property-provider': 4.2.6 - '@smithy/shared-ini-file-loader': 4.4.1 - '@smithy/types': 4.10.0 + '@aws-sdk/core': 3.957.0 + '@aws-sdk/types': 3.957.0 + '@smithy/property-provider': 4.2.7 + '@smithy/shared-ini-file-loader': 4.4.2 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.954.0': + '@aws-sdk/credential-provider-sso@3.958.0': dependencies: - '@aws-sdk/client-sso': 3.954.0 - '@aws-sdk/core': 3.954.0 - '@aws-sdk/token-providers': 3.954.0 - '@aws-sdk/types': 3.953.0 - '@smithy/property-provider': 4.2.6 - '@smithy/shared-ini-file-loader': 4.4.1 - '@smithy/types': 4.10.0 + '@aws-sdk/client-sso': 3.958.0 + '@aws-sdk/core': 3.957.0 + '@aws-sdk/token-providers': 3.958.0 + '@aws-sdk/types': 3.957.0 + '@smithy/property-provider': 4.2.7 + '@smithy/shared-ini-file-loader': 4.4.2 + '@smithy/types': 4.11.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-web-identity@3.954.0': + '@aws-sdk/credential-provider-web-identity@3.958.0': dependencies: - '@aws-sdk/core': 3.954.0 - '@aws-sdk/nested-clients': 3.954.0 - '@aws-sdk/types': 3.953.0 - '@smithy/property-provider': 4.2.6 - '@smithy/shared-ini-file-loader': 4.4.1 - '@smithy/types': 4.10.0 + '@aws-sdk/core': 3.957.0 + '@aws-sdk/nested-clients': 3.958.0 + '@aws-sdk/types': 3.957.0 + '@smithy/property-provider': 4.2.7 + '@smithy/shared-ini-file-loader': 4.4.2 + '@smithy/types': 4.11.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/dynamodb-codec@3.954.0(@aws-sdk/client-dynamodb@3.954.0)': + '@aws-sdk/dynamodb-codec@3.957.0(@aws-sdk/client-dynamodb@3.958.0)': dependencies: - '@aws-sdk/client-dynamodb': 3.954.0 - '@aws-sdk/core': 3.954.0 - '@smithy/core': 3.19.0 - '@smithy/smithy-client': 4.10.1 - '@smithy/types': 4.10.0 + '@aws-sdk/client-dynamodb': 3.958.0 + '@aws-sdk/core': 3.957.0 + '@smithy/core': 3.20.0 + '@smithy/smithy-client': 4.10.2 + '@smithy/types': 4.11.0 '@smithy/util-base64': 4.3.0 tslib: 2.8.1 - '@aws-sdk/endpoint-cache@3.953.0': + '@aws-sdk/endpoint-cache@3.957.0': dependencies: mnemonist: 0.38.3 tslib: 2.8.1 - '@aws-sdk/lib-dynamodb@3.954.0(@aws-sdk/client-dynamodb@3.954.0)': + '@aws-sdk/lib-dynamodb@3.958.0(@aws-sdk/client-dynamodb@3.958.0)': dependencies: - '@aws-sdk/client-dynamodb': 3.954.0 - '@aws-sdk/core': 3.954.0 - '@aws-sdk/util-dynamodb': 3.954.0(@aws-sdk/client-dynamodb@3.954.0) - '@smithy/core': 3.19.0 - '@smithy/smithy-client': 4.10.1 - '@smithy/types': 4.10.0 + '@aws-sdk/client-dynamodb': 3.958.0 + '@aws-sdk/core': 3.957.0 + '@aws-sdk/util-dynamodb': 3.958.0(@aws-sdk/client-dynamodb@3.958.0) + '@smithy/core': 3.20.0 + '@smithy/smithy-client': 4.10.2 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@aws-sdk/middleware-endpoint-discovery@3.953.0': + '@aws-sdk/middleware-endpoint-discovery@3.957.0': dependencies: - '@aws-sdk/endpoint-cache': 3.953.0 - '@aws-sdk/types': 3.953.0 - '@smithy/node-config-provider': 4.3.6 - '@smithy/protocol-http': 5.3.6 - '@smithy/types': 4.10.0 + '@aws-sdk/endpoint-cache': 3.957.0 + '@aws-sdk/types': 3.957.0 + '@smithy/node-config-provider': 4.3.7 + '@smithy/protocol-http': 5.3.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@aws-sdk/middleware-host-header@3.953.0': + '@aws-sdk/middleware-host-header@3.957.0': dependencies: - '@aws-sdk/types': 3.953.0 - '@smithy/protocol-http': 5.3.6 - '@smithy/types': 4.10.0 + '@aws-sdk/types': 3.957.0 + '@smithy/protocol-http': 5.3.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@aws-sdk/middleware-logger@3.953.0': + '@aws-sdk/middleware-logger@3.957.0': dependencies: - '@aws-sdk/types': 3.953.0 - '@smithy/types': 4.10.0 + '@aws-sdk/types': 3.957.0 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@aws-sdk/middleware-recursion-detection@3.953.0': + '@aws-sdk/middleware-recursion-detection@3.957.0': dependencies: - '@aws-sdk/types': 3.953.0 + '@aws-sdk/types': 3.957.0 '@aws/lambda-invoke-store': 0.2.2 - '@smithy/protocol-http': 5.3.6 - '@smithy/types': 4.10.0 + '@smithy/protocol-http': 5.3.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.954.0': + '@aws-sdk/middleware-user-agent@3.957.0': dependencies: - '@aws-sdk/core': 3.954.0 - '@aws-sdk/types': 3.953.0 - '@aws-sdk/util-endpoints': 3.953.0 - '@smithy/core': 3.19.0 - '@smithy/protocol-http': 5.3.6 - '@smithy/types': 4.10.0 + '@aws-sdk/core': 3.957.0 + '@aws-sdk/types': 3.957.0 + '@aws-sdk/util-endpoints': 3.957.0 + '@smithy/core': 3.20.0 + '@smithy/protocol-http': 5.3.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.954.0': + '@aws-sdk/nested-clients@3.958.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.954.0 - '@aws-sdk/middleware-host-header': 3.953.0 - '@aws-sdk/middleware-logger': 3.953.0 - '@aws-sdk/middleware-recursion-detection': 3.953.0 - '@aws-sdk/middleware-user-agent': 3.954.0 - '@aws-sdk/region-config-resolver': 3.953.0 - '@aws-sdk/types': 3.953.0 - '@aws-sdk/util-endpoints': 3.953.0 - '@aws-sdk/util-user-agent-browser': 3.953.0 - '@aws-sdk/util-user-agent-node': 3.954.0 - '@smithy/config-resolver': 4.4.4 - '@smithy/core': 3.19.0 - '@smithy/fetch-http-handler': 5.3.7 - '@smithy/hash-node': 4.2.6 - '@smithy/invalid-dependency': 4.2.6 - '@smithy/middleware-content-length': 4.2.6 - '@smithy/middleware-endpoint': 4.4.0 - '@smithy/middleware-retry': 4.4.16 - '@smithy/middleware-serde': 4.2.7 - '@smithy/middleware-stack': 4.2.6 - '@smithy/node-config-provider': 4.3.6 - '@smithy/node-http-handler': 4.4.6 - '@smithy/protocol-http': 5.3.6 - '@smithy/smithy-client': 4.10.1 - '@smithy/types': 4.10.0 - '@smithy/url-parser': 4.2.6 + '@aws-sdk/core': 3.957.0 + '@aws-sdk/middleware-host-header': 3.957.0 + '@aws-sdk/middleware-logger': 3.957.0 + '@aws-sdk/middleware-recursion-detection': 3.957.0 + '@aws-sdk/middleware-user-agent': 3.957.0 + '@aws-sdk/region-config-resolver': 3.957.0 + '@aws-sdk/types': 3.957.0 + '@aws-sdk/util-endpoints': 3.957.0 + '@aws-sdk/util-user-agent-browser': 3.957.0 + '@aws-sdk/util-user-agent-node': 3.957.0 + '@smithy/config-resolver': 4.4.5 + '@smithy/core': 3.20.0 + '@smithy/fetch-http-handler': 5.3.8 + '@smithy/hash-node': 4.2.7 + '@smithy/invalid-dependency': 4.2.7 + '@smithy/middleware-content-length': 4.2.7 + '@smithy/middleware-endpoint': 4.4.1 + '@smithy/middleware-retry': 4.4.17 + '@smithy/middleware-serde': 4.2.8 + '@smithy/middleware-stack': 4.2.7 + '@smithy/node-config-provider': 4.3.7 + '@smithy/node-http-handler': 4.4.7 + '@smithy/protocol-http': 5.3.7 + '@smithy/smithy-client': 4.10.2 + '@smithy/types': 4.11.0 + '@smithy/url-parser': 4.2.7 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.15 - '@smithy/util-defaults-mode-node': 4.2.18 - '@smithy/util-endpoints': 3.2.6 - '@smithy/util-middleware': 4.2.6 - '@smithy/util-retry': 4.2.6 + '@smithy/util-defaults-mode-browser': 4.3.16 + '@smithy/util-defaults-mode-node': 4.2.19 + '@smithy/util-endpoints': 3.2.7 + '@smithy/util-middleware': 4.2.7 + '@smithy/util-retry': 4.2.7 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/region-config-resolver@3.953.0': + '@aws-sdk/region-config-resolver@3.957.0': dependencies: - '@aws-sdk/types': 3.953.0 - '@smithy/config-resolver': 4.4.4 - '@smithy/node-config-provider': 4.3.6 - '@smithy/types': 4.10.0 + '@aws-sdk/types': 3.957.0 + '@smithy/config-resolver': 4.4.5 + '@smithy/node-config-provider': 4.3.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@aws-sdk/token-providers@3.954.0': + '@aws-sdk/token-providers@3.958.0': dependencies: - '@aws-sdk/core': 3.954.0 - '@aws-sdk/nested-clients': 3.954.0 - '@aws-sdk/types': 3.953.0 - '@smithy/property-provider': 4.2.6 - '@smithy/shared-ini-file-loader': 4.4.1 - '@smithy/types': 4.10.0 + '@aws-sdk/core': 3.957.0 + '@aws-sdk/nested-clients': 3.958.0 + '@aws-sdk/types': 3.957.0 + '@smithy/property-provider': 4.2.7 + '@smithy/shared-ini-file-loader': 4.4.2 + '@smithy/types': 4.11.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/types@3.936.0': + '@aws-sdk/types@3.957.0': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@aws-sdk/types@3.953.0': + '@aws-sdk/util-dynamodb@3.954.0(@aws-sdk/client-dynamodb@3.958.0)': dependencies: - '@smithy/types': 4.10.0 + '@aws-sdk/client-dynamodb': 3.958.0 tslib: 2.8.1 - '@aws-sdk/util-dynamodb@3.954.0(@aws-sdk/client-dynamodb@3.954.0)': + '@aws-sdk/util-dynamodb@3.958.0(@aws-sdk/client-dynamodb@3.958.0)': dependencies: - '@aws-sdk/client-dynamodb': 3.954.0 + '@aws-sdk/client-dynamodb': 3.958.0 tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.953.0': + '@aws-sdk/util-endpoints@3.957.0': dependencies: - '@aws-sdk/types': 3.953.0 - '@smithy/types': 4.10.0 - '@smithy/url-parser': 4.2.6 - '@smithy/util-endpoints': 3.2.6 + '@aws-sdk/types': 3.957.0 + '@smithy/types': 4.11.0 + '@smithy/url-parser': 4.2.7 + '@smithy/util-endpoints': 3.2.7 tslib: 2.8.1 - '@aws-sdk/util-locate-window@3.953.0': + '@aws-sdk/util-locate-window@3.957.0': dependencies: tslib: 2.8.1 - '@aws-sdk/util-user-agent-browser@3.953.0': + '@aws-sdk/util-user-agent-browser@3.957.0': dependencies: - '@aws-sdk/types': 3.953.0 - '@smithy/types': 4.10.0 + '@aws-sdk/types': 3.957.0 + '@smithy/types': 4.11.0 bowser: 2.13.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.954.0': + '@aws-sdk/util-user-agent-node@3.957.0': dependencies: - '@aws-sdk/middleware-user-agent': 3.954.0 - '@aws-sdk/types': 3.953.0 - '@smithy/node-config-provider': 4.3.6 - '@smithy/types': 4.10.0 + '@aws-sdk/middleware-user-agent': 3.957.0 + '@aws-sdk/types': 3.957.0 + '@smithy/node-config-provider': 4.3.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.953.0': + '@aws-sdk/xml-builder@3.957.0': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 fast-xml-parser: 5.2.5 tslib: 2.8.1 @@ -5510,8 +5067,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/runtime@7.28.4': {} - '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 @@ -5748,66 +5303,7 @@ snapshots: '@esbuild/win32-x64@0.27.2': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@2.6.1))': - dependencies: - eslint: 9.39.1(jiti@2.6.1) - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.2': {} - - '@eslint/config-array@0.21.1': - dependencies: - '@eslint/object-schema': 2.1.7 - debug: 4.4.3 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@eslint/config-helpers@0.4.2': - dependencies: - '@eslint/core': 0.17.0 - - '@eslint/core@0.17.0': - dependencies: - '@types/json-schema': 7.0.15 - - '@eslint/eslintrc@3.3.3': - dependencies: - ajv: 6.12.6 - debug: 4.4.3 - espree: 10.4.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.1.1 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@9.39.1': {} - - '@eslint/object-schema@2.1.7': {} - - '@eslint/plugin-kit@0.4.1': - dependencies: - '@eslint/core': 0.17.0 - levn: 0.4.1 - - '@hono/node-server@1.19.7(hono@4.11.1)': - dependencies: - hono: 4.11.1 - - '@humanfs/core@0.19.1': {} - - '@humanfs/node@0.16.7': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.4.3 - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.4.3': {} + '@faker-js/faker@10.1.0': {} '@iconify/types@2.0.0': {} @@ -5840,41 +5336,24 @@ snapshots: dependencies: langium: 3.3.1 - '@modelcontextprotocol/sdk@1.25.1(hono@4.11.1)(zod@4.2.1)': - dependencies: - '@hono/node-server': 1.19.7(hono@4.11.1) - ajv: 8.17.1 - ajv-formats: 3.0.1(ajv@8.17.1) - content-type: 1.0.5 - cors: 2.8.5 - cross-spawn: 7.0.6 - eventsource: 3.0.7 - eventsource-parser: 3.0.6 - express: 5.2.1 - express-rate-limit: 7.5.1(express@5.2.1) - jose: 6.1.3 - json-schema-typed: 8.0.2 - pkce-challenge: 5.0.1 - raw-body: 3.0.2 - zod: 4.2.1 - zod-to-json-schema: 3.25.0(zod@4.2.1) - transitivePeerDependencies: - - hono - - supports-color - - '@napi-rs/wasm-runtime@1.0.7': + '@napi-rs/wasm-runtime@1.1.0': dependencies: '@emnapi/core': 1.7.1 '@emnapi/runtime': 1.7.1 '@tybys/wasm-util': 0.10.1 optional: true - '@napi-rs/wasm-runtime@1.1.0': + '@nodelib/fs.scandir@2.1.5': dependencies: - '@emnapi/core': 1.7.1 - '@emnapi/runtime': 1.7.1 - '@tybys/wasm-util': 0.10.1 - optional: true + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 '@oozcitak/dom@2.0.2': dependencies: @@ -5933,7 +5412,7 @@ snapshots: '@oxc-minify/binding-wasm32-wasi@0.96.0': dependencies: - '@napi-rs/wasm-runtime': 1.0.7 + '@napi-rs/wasm-runtime': 1.1.0 optional: true '@oxc-minify/binding-win32-arm64-msvc@0.96.0': @@ -5942,9 +5421,71 @@ snapshots: '@oxc-minify/binding-win32-x64-msvc@0.96.0': optional: true - '@oxc-project/runtime@0.101.0': {} + '@oxc-project/runtime@0.103.0': {} + + '@oxc-project/types@0.103.0': {} + + '@oxc-resolver/binding-android-arm-eabi@11.16.1': + optional: true + + '@oxc-resolver/binding-android-arm64@11.16.1': + optional: true + + '@oxc-resolver/binding-darwin-arm64@11.16.1': + optional: true + + '@oxc-resolver/binding-darwin-x64@11.16.1': + optional: true + + '@oxc-resolver/binding-freebsd-x64@11.16.1': + optional: true + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.16.1': + optional: true + + '@oxc-resolver/binding-linux-arm-musleabihf@11.16.1': + optional: true + + '@oxc-resolver/binding-linux-arm64-gnu@11.16.1': + optional: true + + '@oxc-resolver/binding-linux-arm64-musl@11.16.1': + optional: true + + '@oxc-resolver/binding-linux-ppc64-gnu@11.16.1': + optional: true + + '@oxc-resolver/binding-linux-riscv64-gnu@11.16.1': + optional: true + + '@oxc-resolver/binding-linux-riscv64-musl@11.16.1': + optional: true + + '@oxc-resolver/binding-linux-s390x-gnu@11.16.1': + optional: true + + '@oxc-resolver/binding-linux-x64-gnu@11.16.1': + optional: true + + '@oxc-resolver/binding-linux-x64-musl@11.16.1': + optional: true + + '@oxc-resolver/binding-openharmony-arm64@11.16.1': + optional: true + + '@oxc-resolver/binding-wasm32-wasi@11.16.1': + dependencies: + '@napi-rs/wasm-runtime': 1.1.0 + optional: true + + '@oxc-resolver/binding-win32-arm64-msvc@11.16.1': + optional: true + + '@oxc-resolver/binding-win32-ia32-msvc@11.16.1': + optional: true - '@oxc-project/types@0.101.0': {} + '@oxc-resolver/binding-win32-x64-msvc@11.16.1': + optional: true '@oxc-transform/binding-android-arm64@0.96.0': optional: true @@ -5984,7 +5525,7 @@ snapshots: '@oxc-transform/binding-wasm32-wasi@0.96.0': dependencies: - '@napi-rs/wasm-runtime': 1.0.7 + '@napi-rs/wasm-runtime': 1.1.0 optional: true '@oxc-transform/binding-win32-arm64-msvc@0.96.0': @@ -5993,117 +5534,132 @@ snapshots: '@oxc-transform/binding-win32-x64-msvc@0.96.0': optional: true - '@oxfmt/darwin-arm64@0.18.0': + '@oxfmt/darwin-arm64@0.20.0': optional: true - '@oxfmt/darwin-x64@0.18.0': + '@oxfmt/darwin-x64@0.20.0': optional: true - '@oxfmt/linux-arm64-gnu@0.18.0': + '@oxfmt/linux-arm64-gnu@0.20.0': optional: true - '@oxfmt/linux-arm64-musl@0.18.0': + '@oxfmt/linux-arm64-musl@0.20.0': optional: true - '@oxfmt/linux-x64-gnu@0.18.0': + '@oxfmt/linux-x64-gnu@0.20.0': optional: true - '@oxfmt/linux-x64-musl@0.18.0': + '@oxfmt/linux-x64-musl@0.20.0': optional: true - '@oxfmt/win32-arm64@0.18.0': + '@oxfmt/win32-arm64@0.20.0': optional: true - '@oxfmt/win32-x64@0.18.0': + '@oxfmt/win32-x64@0.20.0': optional: true - '@oxlint-tsgolint/darwin-arm64@0.9.1': + '@oxlint-tsgolint/darwin-arm64@0.10.0': optional: true - '@oxlint-tsgolint/darwin-x64@0.9.1': + '@oxlint-tsgolint/darwin-x64@0.10.0': optional: true - '@oxlint-tsgolint/linux-arm64@0.9.1': + '@oxlint-tsgolint/linux-arm64@0.10.0': optional: true - '@oxlint-tsgolint/linux-x64@0.9.1': + '@oxlint-tsgolint/linux-x64@0.10.0': optional: true - '@oxlint-tsgolint/win32-arm64@0.9.1': + '@oxlint-tsgolint/win32-arm64@0.10.0': optional: true - '@oxlint-tsgolint/win32-x64@0.9.1': + '@oxlint-tsgolint/win32-x64@0.10.0': optional: true - '@oxlint/darwin-arm64@1.33.0': + '@oxlint/darwin-arm64@1.35.0': optional: true - '@oxlint/darwin-x64@1.33.0': + '@oxlint/darwin-x64@1.35.0': optional: true - '@oxlint/linux-arm64-gnu@1.33.0': + '@oxlint/linux-arm64-gnu@1.35.0': optional: true - '@oxlint/linux-arm64-musl@1.33.0': + '@oxlint/linux-arm64-musl@1.35.0': optional: true - '@oxlint/linux-x64-gnu@1.33.0': + '@oxlint/linux-x64-gnu@1.35.0': optional: true - '@oxlint/linux-x64-musl@1.33.0': + '@oxlint/linux-x64-musl@1.35.0': optional: true - '@oxlint/win32-arm64@1.33.0': + '@oxlint/win32-arm64@1.35.0': optional: true - '@oxlint/win32-x64@1.33.0': + '@oxlint/win32-x64@1.35.0': optional: true - '@rolldown/binding-android-arm64@1.0.0-beta.53': + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.7)(react@19.2.3)': + dependencies: + react: 19.2.3 + optionalDependencies: + '@types/react': 19.2.7 + + '@radix-ui/react-slot@1.2.4(@types/react@19.2.7)(react@19.2.3)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) + react: 19.2.3 + optionalDependencies: + '@types/react': 19.2.7 + + '@rolldown/binding-android-arm64@1.0.0-beta.56': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-beta.53': + '@rolldown/binding-darwin-arm64@1.0.0-beta.56': optional: true - '@rolldown/binding-darwin-x64@1.0.0-beta.53': + '@rolldown/binding-darwin-x64@1.0.0-beta.56': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-beta.53': + '@rolldown/binding-freebsd-x64@1.0.0-beta.56': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.56': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53': + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.56': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53': + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.56': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53': + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.56': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-beta.53': + '@rolldown/binding-linux-x64-musl@1.0.0-beta.56': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-beta.53': + '@rolldown/binding-openharmony-arm64@1.0.0-beta.56': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-beta.53': + '@rolldown/binding-wasm32-wasi@1.0.0-beta.56': dependencies: '@napi-rs/wasm-runtime': 1.1.0 optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53': + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.56': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.56': optional: true '@rolldown/pluginutils@1.0.0-beta.40': {} '@rolldown/pluginutils@1.0.0-beta.53': {} + '@rolldown/pluginutils@1.0.0-beta.56': {} + '@rollup/rollup-android-arm-eabi@4.53.5': optional: true @@ -6203,66 +5759,66 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} - '@smithy/abort-controller@4.2.6': + '@smithy/abort-controller@4.2.7': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/config-resolver@4.4.4': + '@smithy/config-resolver@4.4.5': dependencies: - '@smithy/node-config-provider': 4.3.6 - '@smithy/types': 4.10.0 + '@smithy/node-config-provider': 4.3.7 + '@smithy/types': 4.11.0 '@smithy/util-config-provider': 4.2.0 - '@smithy/util-endpoints': 3.2.6 - '@smithy/util-middleware': 4.2.6 + '@smithy/util-endpoints': 3.2.7 + '@smithy/util-middleware': 4.2.7 tslib: 2.8.1 - '@smithy/core@3.19.0': + '@smithy/core@3.20.0': dependencies: - '@smithy/middleware-serde': 4.2.7 - '@smithy/protocol-http': 5.3.6 - '@smithy/types': 4.10.0 + '@smithy/middleware-serde': 4.2.8 + '@smithy/protocol-http': 5.3.7 + '@smithy/types': 4.11.0 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 - '@smithy/util-middleware': 4.2.6 - '@smithy/util-stream': 4.5.7 + '@smithy/util-middleware': 4.2.7 + '@smithy/util-stream': 4.5.8 '@smithy/util-utf8': 4.2.0 '@smithy/uuid': 1.1.0 tslib: 2.8.1 - '@smithy/credential-provider-imds@4.2.6': + '@smithy/credential-provider-imds@4.2.7': dependencies: - '@smithy/node-config-provider': 4.3.6 - '@smithy/property-provider': 4.2.6 - '@smithy/types': 4.10.0 - '@smithy/url-parser': 4.2.6 + '@smithy/node-config-provider': 4.3.7 + '@smithy/property-provider': 4.2.7 + '@smithy/types': 4.11.0 + '@smithy/url-parser': 4.2.7 tslib: 2.8.1 - '@smithy/eventstream-codec@4.2.6': + '@smithy/eventstream-codec@4.2.7': dependencies: '@aws-crypto/crc32': 5.2.0 - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 '@smithy/util-hex-encoding': 4.2.0 tslib: 2.8.1 - '@smithy/fetch-http-handler@5.3.7': + '@smithy/fetch-http-handler@5.3.8': dependencies: - '@smithy/protocol-http': 5.3.6 - '@smithy/querystring-builder': 4.2.6 - '@smithy/types': 4.10.0 + '@smithy/protocol-http': 5.3.7 + '@smithy/querystring-builder': 4.2.7 + '@smithy/types': 4.11.0 '@smithy/util-base64': 4.3.0 tslib: 2.8.1 - '@smithy/hash-node@4.2.6': + '@smithy/hash-node@4.2.7': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 '@smithy/util-buffer-from': 4.2.0 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 - '@smithy/invalid-dependency@4.2.6': + '@smithy/invalid-dependency@4.2.7': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': @@ -6273,124 +5829,120 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/middleware-content-length@4.2.6': + '@smithy/middleware-content-length@4.2.7': dependencies: - '@smithy/protocol-http': 5.3.6 - '@smithy/types': 4.10.0 + '@smithy/protocol-http': 5.3.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/middleware-endpoint@4.4.0': + '@smithy/middleware-endpoint@4.4.1': dependencies: - '@smithy/core': 3.19.0 - '@smithy/middleware-serde': 4.2.7 - '@smithy/node-config-provider': 4.3.6 - '@smithy/shared-ini-file-loader': 4.4.1 - '@smithy/types': 4.10.0 - '@smithy/url-parser': 4.2.6 - '@smithy/util-middleware': 4.2.6 + '@smithy/core': 3.20.0 + '@smithy/middleware-serde': 4.2.8 + '@smithy/node-config-provider': 4.3.7 + '@smithy/shared-ini-file-loader': 4.4.2 + '@smithy/types': 4.11.0 + '@smithy/url-parser': 4.2.7 + '@smithy/util-middleware': 4.2.7 tslib: 2.8.1 - '@smithy/middleware-retry@4.4.16': + '@smithy/middleware-retry@4.4.17': dependencies: - '@smithy/node-config-provider': 4.3.6 - '@smithy/protocol-http': 5.3.6 - '@smithy/service-error-classification': 4.2.6 - '@smithy/smithy-client': 4.10.1 - '@smithy/types': 4.10.0 - '@smithy/util-middleware': 4.2.6 - '@smithy/util-retry': 4.2.6 + '@smithy/node-config-provider': 4.3.7 + '@smithy/protocol-http': 5.3.7 + '@smithy/service-error-classification': 4.2.7 + '@smithy/smithy-client': 4.10.2 + '@smithy/types': 4.11.0 + '@smithy/util-middleware': 4.2.7 + '@smithy/util-retry': 4.2.7 '@smithy/uuid': 1.1.0 tslib: 2.8.1 - '@smithy/middleware-serde@4.2.7': + '@smithy/middleware-serde@4.2.8': dependencies: - '@smithy/protocol-http': 5.3.6 - '@smithy/types': 4.10.0 + '@smithy/protocol-http': 5.3.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/middleware-stack@4.2.6': + '@smithy/middleware-stack@4.2.7': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/node-config-provider@4.3.6': + '@smithy/node-config-provider@4.3.7': dependencies: - '@smithy/property-provider': 4.2.6 - '@smithy/shared-ini-file-loader': 4.4.1 - '@smithy/types': 4.10.0 + '@smithy/property-provider': 4.2.7 + '@smithy/shared-ini-file-loader': 4.4.2 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/node-http-handler@4.4.6': + '@smithy/node-http-handler@4.4.7': dependencies: - '@smithy/abort-controller': 4.2.6 - '@smithy/protocol-http': 5.3.6 - '@smithy/querystring-builder': 4.2.6 - '@smithy/types': 4.10.0 + '@smithy/abort-controller': 4.2.7 + '@smithy/protocol-http': 5.3.7 + '@smithy/querystring-builder': 4.2.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/property-provider@4.2.6': + '@smithy/property-provider@4.2.7': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/protocol-http@5.3.6': + '@smithy/protocol-http@5.3.7': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/querystring-builder@4.2.6': + '@smithy/querystring-builder@4.2.7': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 '@smithy/util-uri-escape': 4.2.0 tslib: 2.8.1 - '@smithy/querystring-parser@4.2.6': + '@smithy/querystring-parser@4.2.7': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/service-error-classification@4.2.6': + '@smithy/service-error-classification@4.2.7': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 - '@smithy/shared-ini-file-loader@4.4.1': + '@smithy/shared-ini-file-loader@4.4.2': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/signature-v4@5.3.6': + '@smithy/signature-v4@5.3.7': dependencies: '@smithy/is-array-buffer': 4.2.0 - '@smithy/protocol-http': 5.3.6 - '@smithy/types': 4.10.0 + '@smithy/protocol-http': 5.3.7 + '@smithy/types': 4.11.0 '@smithy/util-hex-encoding': 4.2.0 - '@smithy/util-middleware': 4.2.6 + '@smithy/util-middleware': 4.2.7 '@smithy/util-uri-escape': 4.2.0 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 - '@smithy/smithy-client@4.10.1': + '@smithy/smithy-client@4.10.2': dependencies: - '@smithy/core': 3.19.0 - '@smithy/middleware-endpoint': 4.4.0 - '@smithy/middleware-stack': 4.2.6 - '@smithy/protocol-http': 5.3.6 - '@smithy/types': 4.10.0 - '@smithy/util-stream': 4.5.7 + '@smithy/core': 3.20.0 + '@smithy/middleware-endpoint': 4.4.1 + '@smithy/middleware-stack': 4.2.7 + '@smithy/protocol-http': 5.3.7 + '@smithy/types': 4.11.0 + '@smithy/util-stream': 4.5.8 tslib: 2.8.1 - '@smithy/types@4.10.0': + '@smithy/types@4.11.0': dependencies: tslib: 2.8.1 - '@smithy/types@4.9.0': + '@smithy/url-parser@4.2.7': dependencies: - tslib: 2.8.1 - - '@smithy/url-parser@4.2.6': - dependencies: - '@smithy/querystring-parser': 4.2.6 - '@smithy/types': 4.10.0 + '@smithy/querystring-parser': 4.2.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 '@smithy/util-base64@4.3.0': @@ -6421,49 +5973,49 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@4.3.15': + '@smithy/util-defaults-mode-browser@4.3.16': dependencies: - '@smithy/property-provider': 4.2.6 - '@smithy/smithy-client': 4.10.1 - '@smithy/types': 4.10.0 + '@smithy/property-provider': 4.2.7 + '@smithy/smithy-client': 4.10.2 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@4.2.18': + '@smithy/util-defaults-mode-node@4.2.19': dependencies: - '@smithy/config-resolver': 4.4.4 - '@smithy/credential-provider-imds': 4.2.6 - '@smithy/node-config-provider': 4.3.6 - '@smithy/property-provider': 4.2.6 - '@smithy/smithy-client': 4.10.1 - '@smithy/types': 4.10.0 + '@smithy/config-resolver': 4.4.5 + '@smithy/credential-provider-imds': 4.2.7 + '@smithy/node-config-provider': 4.3.7 + '@smithy/property-provider': 4.2.7 + '@smithy/smithy-client': 4.10.2 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/util-endpoints@3.2.6': + '@smithy/util-endpoints@3.2.7': dependencies: - '@smithy/node-config-provider': 4.3.6 - '@smithy/types': 4.10.0 + '@smithy/node-config-provider': 4.3.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 '@smithy/util-hex-encoding@4.2.0': dependencies: tslib: 2.8.1 - '@smithy/util-middleware@4.2.6': + '@smithy/util-middleware@4.2.7': dependencies: - '@smithy/types': 4.10.0 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/util-retry@4.2.6': + '@smithy/util-retry@4.2.7': dependencies: - '@smithy/service-error-classification': 4.2.6 - '@smithy/types': 4.10.0 + '@smithy/service-error-classification': 4.2.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 - '@smithy/util-stream@4.5.7': + '@smithy/util-stream@4.5.8': dependencies: - '@smithy/fetch-http-handler': 5.3.7 - '@smithy/node-http-handler': 4.4.6 - '@smithy/types': 4.10.0 + '@smithy/fetch-http-handler': 5.3.8 + '@smithy/node-http-handler': 4.4.7 + '@smithy/types': 4.11.0 '@smithy/util-base64': 4.3.0 '@smithy/util-buffer-from': 4.2.0 '@smithy/util-hex-encoding': 4.2.0 @@ -6484,10 +6036,10 @@ snapshots: '@smithy/util-buffer-from': 4.2.0 tslib: 2.8.1 - '@smithy/util-waiter@4.2.6': + '@smithy/util-waiter@4.2.7': dependencies: - '@smithy/abort-controller': 4.2.6 - '@smithy/types': 4.10.0 + '@smithy/abort-controller': 4.2.7 + '@smithy/types': 4.11.0 tslib: 2.8.1 '@smithy/uuid@1.1.0': @@ -6591,12 +6143,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 - '@tailwindcss/vite@4.1.18(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': + '@tailwindcss/vite@4.1.18(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': dependencies: '@tailwindcss/node': 4.1.18 '@tailwindcss/oxide': 4.1.18 tailwindcss: 4.1.18 - vite: 8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) + vite: 8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) '@tanstack/db-ivm@0.1.14(typescript@5.9.3)': dependencies: @@ -6604,7 +6156,7 @@ snapshots: sorted-btree: 1.8.1 typescript: 5.9.3 - '@tanstack/db@0.5.12(typescript@5.9.3)': + '@tanstack/db@0.5.16(typescript@5.9.3)': dependencies: '@standard-schema/spec': 1.1.0 '@tanstack/db-ivm': 0.1.14(typescript@5.9.3) @@ -6632,7 +6184,7 @@ snapshots: transitivePeerDependencies: - csstype - '@tanstack/devtools-vite@0.3.12(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': + '@tanstack/devtools-vite@0.3.12(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': dependencies: '@babel/core': 7.28.5 '@babel/generator': 7.28.5 @@ -6644,13 +6196,13 @@ snapshots: chalk: 5.6.2 launch-editor: 2.12.0 picomatch: 4.0.3 - vite: 8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) + vite: 8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - '@tanstack/devtools@0.9.1(csstype@3.2.3)(solid-js@1.9.10)': + '@tanstack/devtools@0.10.0(csstype@3.2.3)(solid-js@1.9.10)': dependencies: '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.10) '@solid-primitives/keyboard': 1.3.3(solid-js@1.9.10) @@ -6666,7 +6218,7 @@ snapshots: - csstype - utf-8-validate - '@tanstack/directive-functions-plugin@1.141.0(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': + '@tanstack/directive-functions-plugin@1.142.1(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': dependencies: '@babel/code-frame': 7.27.1 '@babel/core': 7.28.5 @@ -6676,36 +6228,42 @@ snapshots: babel-dead-code-elimination: 1.0.11 pathe: 2.0.3 tiny-invariant: 1.3.3 - vite: 8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) + vite: 8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) transitivePeerDependencies: - supports-color + '@tanstack/form-core@1.27.6': + dependencies: + '@tanstack/devtools-event-client': 0.4.0 + '@tanstack/pacer-lite': 0.1.1 + '@tanstack/store': 0.7.7 + '@tanstack/history@1.141.0': {} '@tanstack/pacer-lite@0.1.1': {} '@tanstack/query-core@5.90.12': {} - '@tanstack/query-db-collection@1.0.8(@tanstack/query-core@5.90.12)(typescript@5.9.3)': + '@tanstack/query-db-collection@1.0.12(@tanstack/query-core@5.90.12)(typescript@5.9.3)': dependencies: '@standard-schema/spec': 1.1.0 - '@tanstack/db': 0.5.12(typescript@5.9.3) + '@tanstack/db': 0.5.16(typescript@5.9.3) '@tanstack/query-core': 5.90.12 typescript: 5.9.3 '@tanstack/query-devtools@5.91.1': {} - '@tanstack/react-db@0.1.56(react@19.2.3)(typescript@5.9.3)': + '@tanstack/react-db@0.1.60(react@19.2.3)(typescript@5.9.3)': dependencies: - '@tanstack/db': 0.5.12(typescript@5.9.3) + '@tanstack/db': 0.5.16(typescript@5.9.3) react: 19.2.3 use-sync-external-store: 1.6.0(react@19.2.3) transitivePeerDependencies: - typescript - '@tanstack/react-devtools@0.8.4(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10)': + '@tanstack/react-devtools@0.8.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10)': dependencies: - '@tanstack/devtools': 0.9.1(csstype@3.2.3)(solid-js@1.9.10) + '@tanstack/devtools': 0.10.0(csstype@3.2.3)(solid-js@1.9.10) '@types/react': 19.2.7 '@types/react-dom': 19.2.3(@types/react@19.2.7) react: 19.2.3 @@ -6716,6 +6274,16 @@ snapshots: - solid-js - utf-8-validate + '@tanstack/react-form@1.27.6(@tanstack/react-start@1.143.4(crossws@0.4.1(srvx@0.9.7))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@tanstack/form-core': 1.27.6 + '@tanstack/react-store': 0.8.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: 19.2.3 + optionalDependencies: + '@tanstack/react-start': 1.143.4(crossws@0.4.1(srvx@0.9.7))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + transitivePeerDependencies: + - react-dom + '@tanstack/react-query-devtools@5.91.1(@tanstack/react-query@5.90.12(react@19.2.3))(react@19.2.3)': dependencies: '@tanstack/query-devtools': 5.91.1 @@ -6727,75 +6295,75 @@ snapshots: '@tanstack/query-core': 5.90.12 react: 19.2.3 - '@tanstack/react-router-devtools@1.141.6(@tanstack/react-router@1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.141.6)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10)': + '@tanstack/react-router-devtools@1.143.4(@tanstack/react-router@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.143.4)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.10)': dependencies: - '@tanstack/react-router': 1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/router-devtools-core': 1.141.6(@tanstack/router-core@1.141.6)(csstype@3.2.3)(solid-js@1.9.10) + '@tanstack/react-router': 1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@tanstack/router-devtools-core': 1.143.4(@tanstack/router-core@1.143.4)(csstype@3.2.3)(solid-js@1.9.10) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) optionalDependencies: - '@tanstack/router-core': 1.141.6 + '@tanstack/router-core': 1.143.4 transitivePeerDependencies: - csstype - solid-js - '@tanstack/react-router-ssr-query@1.141.6(@tanstack/query-core@5.90.12)(@tanstack/react-query@5.90.12(react@19.2.3))(@tanstack/react-router@1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.141.6)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + '@tanstack/react-router-ssr-query@1.143.4(@tanstack/query-core@5.90.12)(@tanstack/react-query@5.90.12(react@19.2.3))(@tanstack/react-router@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.143.4)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@tanstack/query-core': 5.90.12 '@tanstack/react-query': 5.90.12(react@19.2.3) - '@tanstack/react-router': 1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/router-ssr-query-core': 1.141.6(@tanstack/query-core@5.90.12)(@tanstack/router-core@1.141.6) + '@tanstack/react-router': 1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@tanstack/router-ssr-query-core': 1.143.4(@tanstack/query-core@5.90.12)(@tanstack/router-core@1.143.4) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) transitivePeerDependencies: - '@tanstack/router-core' - '@tanstack/react-router@1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + '@tanstack/react-router@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@tanstack/history': 1.141.0 '@tanstack/react-store': 0.8.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/router-core': 1.141.6 + '@tanstack/router-core': 1.143.4 isbot: 5.1.32 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/react-start-client@1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + '@tanstack/react-start-client@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: - '@tanstack/react-router': 1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/router-core': 1.141.6 - '@tanstack/start-client-core': 1.141.6 + '@tanstack/react-router': 1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@tanstack/router-core': 1.143.4 + '@tanstack/start-client-core': 1.143.4 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/react-start-server@1.141.6(crossws@0.4.1(srvx@0.9.7))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + '@tanstack/react-start-server@1.143.4(crossws@0.4.1(srvx@0.9.7))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@tanstack/history': 1.141.0 - '@tanstack/react-router': 1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/router-core': 1.141.6 - '@tanstack/start-client-core': 1.141.6 - '@tanstack/start-server-core': 1.141.6(crossws@0.4.1(srvx@0.9.7)) + '@tanstack/react-router': 1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@tanstack/router-core': 1.143.4 + '@tanstack/start-client-core': 1.143.4 + '@tanstack/start-server-core': 1.143.4(crossws@0.4.1(srvx@0.9.7)) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) transitivePeerDependencies: - crossws - '@tanstack/react-start@1.141.7(crossws@0.4.1(srvx@0.9.7))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': + '@tanstack/react-start@1.143.4(crossws@0.4.1(srvx@0.9.7))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': dependencies: - '@tanstack/react-router': 1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/react-start-client': 1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/react-start-server': 1.141.6(crossws@0.4.1(srvx@0.9.7))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@tanstack/react-router': 1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@tanstack/react-start-client': 1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@tanstack/react-start-server': 1.143.4(crossws@0.4.1(srvx@0.9.7))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/router-utils': 1.141.0 - '@tanstack/start-client-core': 1.141.6 - '@tanstack/start-plugin-core': 1.141.7(@tanstack/react-router@1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.1(srvx@0.9.7))(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) - '@tanstack/start-server-core': 1.141.6(crossws@0.4.1(srvx@0.9.7)) + '@tanstack/start-client-core': 1.143.4 + '@tanstack/start-plugin-core': 1.143.4(@tanstack/react-router@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.1(srvx@0.9.7))(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + '@tanstack/start-server-core': 1.143.4(crossws@0.4.1(srvx@0.9.7)) pathe: 2.0.3 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - vite: 8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) + vite: 8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) transitivePeerDependencies: - '@rsbuild/core' - crossws @@ -6810,19 +6378,25 @@ snapshots: react-dom: 19.2.3(react@19.2.3) use-sync-external-store: 1.6.0(react@19.2.3) - '@tanstack/router-core@1.141.6': + '@tanstack/react-table@8.21.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@tanstack/table-core': 8.21.3 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + + '@tanstack/router-core@1.143.4': dependencies: '@tanstack/history': 1.141.0 '@tanstack/store': 0.8.0 cookie-es: 2.0.0 - seroval: 1.4.0 - seroval-plugins: 1.4.0(seroval@1.4.0) + seroval: 1.4.1 + seroval-plugins: 1.4.0(seroval@1.4.1) tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/router-devtools-core@1.141.6(@tanstack/router-core@1.141.6)(csstype@3.2.3)(solid-js@1.9.10)': + '@tanstack/router-devtools-core@1.143.4(@tanstack/router-core@1.143.4)(csstype@3.2.3)(solid-js@1.9.10)': dependencies: - '@tanstack/router-core': 1.141.6 + '@tanstack/router-core': 1.143.4 clsx: 2.1.1 goober: 2.1.18(csstype@3.2.3) solid-js: 1.9.10 @@ -6830,9 +6404,9 @@ snapshots: optionalDependencies: csstype: 3.2.3 - '@tanstack/router-generator@1.141.7': + '@tanstack/router-generator@1.143.4': dependencies: - '@tanstack/router-core': 1.141.6 + '@tanstack/router-core': 1.143.4 '@tanstack/router-utils': 1.141.0 '@tanstack/virtual-file-routes': 1.141.0 prettier: 3.7.4 @@ -6843,7 +6417,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.141.7(@tanstack/react-router@1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': + '@tanstack/router-plugin@1.143.4(@tanstack/react-router@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) @@ -6851,8 +6425,8 @@ snapshots: '@babel/template': 7.27.2 '@babel/traverse': 7.28.5 '@babel/types': 7.28.5 - '@tanstack/router-core': 1.141.6 - '@tanstack/router-generator': 1.141.7 + '@tanstack/router-core': 1.143.4 + '@tanstack/router-generator': 1.143.4 '@tanstack/router-utils': 1.141.0 '@tanstack/virtual-file-routes': 1.141.0 babel-dead-code-elimination: 1.0.11 @@ -6860,15 +6434,15 @@ snapshots: unplugin: 2.3.11 zod: 3.25.76 optionalDependencies: - '@tanstack/react-router': 1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - vite: 8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) + '@tanstack/react-router': 1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + vite: 8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) transitivePeerDependencies: - supports-color - '@tanstack/router-ssr-query-core@1.141.6(@tanstack/query-core@5.90.12)(@tanstack/router-core@1.141.6)': + '@tanstack/router-ssr-query-core@1.143.4(@tanstack/query-core@5.90.12)(@tanstack/router-core@1.143.4)': dependencies: '@tanstack/query-core': 5.90.12 - '@tanstack/router-core': 1.141.6 + '@tanstack/router-core': 1.143.4 '@tanstack/router-utils@1.141.0': dependencies: @@ -6883,7 +6457,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/server-functions-plugin@1.141.3(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': + '@tanstack/server-functions-plugin@1.142.1(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': dependencies: '@babel/code-frame': 7.27.1 '@babel/core': 7.28.5 @@ -6892,34 +6466,37 @@ snapshots: '@babel/template': 7.27.2 '@babel/traverse': 7.28.5 '@babel/types': 7.28.5 - '@tanstack/directive-functions-plugin': 1.141.0(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + '@tanstack/directive-functions-plugin': 1.142.1(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) babel-dead-code-elimination: 1.0.11 tiny-invariant: 1.3.3 transitivePeerDependencies: - supports-color - vite - '@tanstack/start-client-core@1.141.6': + '@tanstack/start-client-core@1.143.4': dependencies: - '@tanstack/router-core': 1.141.6 - '@tanstack/start-storage-context': 1.141.6 - seroval: 1.4.0 + '@tanstack/router-core': 1.143.4 + '@tanstack/start-fn-stubs': 1.142.9 + '@tanstack/start-storage-context': 1.143.4 + seroval: 1.4.1 tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/start-plugin-core@1.141.7(@tanstack/react-router@1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.1(srvx@0.9.7))(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': + '@tanstack/start-fn-stubs@1.142.9': {} + + '@tanstack/start-plugin-core@1.143.4(@tanstack/react-router@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(crossws@0.4.1(srvx@0.9.7))(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': dependencies: '@babel/code-frame': 7.26.2 '@babel/core': 7.28.5 '@babel/types': 7.28.5 '@rolldown/pluginutils': 1.0.0-beta.40 - '@tanstack/router-core': 1.141.6 - '@tanstack/router-generator': 1.141.7 - '@tanstack/router-plugin': 1.141.7(@tanstack/react-router@1.141.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + '@tanstack/router-core': 1.143.4 + '@tanstack/router-generator': 1.143.4 + '@tanstack/router-plugin': 1.143.4(@tanstack/react-router@1.143.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) '@tanstack/router-utils': 1.141.0 - '@tanstack/server-functions-plugin': 1.141.3(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) - '@tanstack/start-client-core': 1.141.6 - '@tanstack/start-server-core': 1.141.6(crossws@0.4.1(srvx@0.9.7)) + '@tanstack/server-functions-plugin': 1.142.1(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + '@tanstack/start-client-core': 1.143.4 + '@tanstack/start-server-core': 1.143.4(crossws@0.4.1(srvx@0.9.7)) babel-dead-code-elimination: 1.0.11 cheerio: 1.1.2 exsolve: 1.0.8 @@ -6927,8 +6504,8 @@ snapshots: srvx: 0.9.8 tinyglobby: 0.2.15 ufo: 1.6.1 - vite: 8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) - vitefu: 1.1.1(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) + vite: 8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) + vitefu: 1.1.1(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)) xmlbuilder2: 4.0.3 zod: 3.25.76 transitivePeerDependencies: @@ -6939,61 +6516,44 @@ snapshots: - vite-plugin-solid - webpack - '@tanstack/start-server-core@1.141.6(crossws@0.4.1(srvx@0.9.7))': + '@tanstack/start-server-core@1.143.4(crossws@0.4.1(srvx@0.9.7))': dependencies: '@tanstack/history': 1.141.0 - '@tanstack/router-core': 1.141.6 - '@tanstack/start-client-core': 1.141.6 - '@tanstack/start-storage-context': 1.141.6 - h3-v2: h3@2.0.0-beta.5(crossws@0.4.1(srvx@0.9.7)) - seroval: 1.4.0 + '@tanstack/router-core': 1.143.4 + '@tanstack/start-client-core': 1.143.4 + '@tanstack/start-storage-context': 1.143.4 + h3-v2: h3@2.0.1-rc.6(crossws@0.4.1(srvx@0.9.7)) + seroval: 1.4.1 tiny-invariant: 1.3.3 transitivePeerDependencies: - crossws - '@tanstack/start-storage-context@1.141.6': + '@tanstack/start-storage-context@1.143.4': dependencies: - '@tanstack/router-core': 1.141.6 + '@tanstack/router-core': 1.143.4 - '@tanstack/store@0.8.0': {} + '@tanstack/store@0.7.7': {} - '@tanstack/virtual-file-routes@1.141.0': {} + '@tanstack/store@0.8.0': {} - '@testing-library/dom@10.4.1': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/runtime': 7.28.4 - '@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 + '@tanstack/table-core@8.21.3': {} - '@testing-library/react@16.3.1(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@babel/runtime': 7.28.4 - '@testing-library/dom': 10.4.1 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) + '@tanstack/virtual-file-routes@1.141.0': {} - '@trpc/client@11.8.0(@trpc/server@11.8.0(typescript@5.9.3))(typescript@5.9.3)': + '@trpc/client@11.8.1(@trpc/server@11.8.1(typescript@5.9.3))(typescript@5.9.3)': dependencies: - '@trpc/server': 11.8.0(typescript@5.9.3) + '@trpc/server': 11.8.1(typescript@5.9.3) typescript: 5.9.3 - '@trpc/server@11.8.0(typescript@5.9.3)': + '@trpc/server@11.8.1(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@trpc/tanstack-react-query@11.8.0(@tanstack/react-query@5.90.12(react@19.2.3))(@trpc/client@11.8.0(@trpc/server@11.8.0(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.8.0(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': + '@trpc/tanstack-react-query@11.8.1(@tanstack/react-query@5.90.12(react@19.2.3))(@trpc/client@11.8.1(@trpc/server@11.8.1(typescript@5.9.3))(typescript@5.9.3))(@trpc/server@11.8.1(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': dependencies: '@tanstack/react-query': 5.90.12(react@19.2.3) - '@trpc/client': 11.8.0(@trpc/server@11.8.0(typescript@5.9.3))(typescript@5.9.3) - '@trpc/server': 11.8.0(typescript@5.9.3) + '@trpc/client': 11.8.1(@trpc/server@11.8.1(typescript@5.9.3))(typescript@5.9.3) + '@trpc/server': 11.8.1(typescript@5.9.3) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) typescript: 5.9.3 @@ -7003,8 +6563,6 @@ snapshots: tslib: 2.8.1 optional: true - '@types/aria-query@5.0.4': {} - '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.28.5 @@ -7166,8 +6724,6 @@ snapshots: dependencies: '@types/unist': 3.0.3 - '@types/json-schema@7.0.15': {} - '@types/katex@0.16.7': {} '@types/mdast@4.0.4': @@ -7199,7 +6755,7 @@ snapshots: '@vercel/oidc@3.0.5': {} - '@vitejs/plugin-react@5.1.2(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': + '@vitejs/plugin-react@5.1.2(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) @@ -7207,7 +6763,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.53 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) + vite: 8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) transitivePeerDependencies: - supports-color @@ -7250,53 +6806,18 @@ snapshots: '@vitest/pretty-format': 4.0.16 tinyrainbow: 3.0.3 - accepts@2.0.0: - dependencies: - mime-types: 3.0.2 - negotiator: 1.0.0 - - acorn-jsx@5.3.2(acorn@8.15.0): - dependencies: - acorn: 8.15.0 - acorn@8.15.0: {} agent-base@7.1.4: {} - ai@5.0.115(zod@4.2.1): + ai@6.0.3(zod@4.2.1): dependencies: - '@ai-sdk/gateway': 2.0.22(zod@4.2.1) - '@ai-sdk/provider': 2.0.0 - '@ai-sdk/provider-utils': 3.0.19(zod@4.2.1) + '@ai-sdk/gateway': 3.0.2(zod@4.2.1) + '@ai-sdk/provider': 3.0.0 + '@ai-sdk/provider-utils': 4.0.1(zod@4.2.1) '@opentelemetry/api': 1.9.0 zod: 4.2.1 - ajv-formats@3.0.1(ajv@8.17.1): - optionalDependencies: - ajv: 8.17.1 - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ajv@8.17.1: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - - ansi-regex@5.0.1: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@5.2.0: {} - ansis@4.2.0: {} anymatch@3.1.3: @@ -7306,17 +6827,13 @@ snapshots: argparse@2.0.1: {} - aria-query@5.3.0: - dependencies: - dequal: 2.0.3 - assertion-error@2.0.1: {} ast-types@0.16.1: dependencies: tslib: 2.8.1 - aws-cdk-lib@2.232.2(constructs@10.4.4): + aws-cdk-lib@2.233.0(constructs@10.4.4): dependencies: '@aws-cdk/asset-awscli-v1': 2.2.242 '@aws-cdk/asset-node-proxy-agent-v6': 2.1.0 @@ -7338,9 +6855,11 @@ snapshots: transitivePeerDependencies: - supports-color - bail@2.0.2: {} + babel-plugin-react-compiler@1.0.0: + dependencies: + '@babel/types': 7.28.5 - balanced-match@1.0.2: {} + bail@2.0.2: {} baseline-browser-mapping@2.9.10: {} @@ -7350,29 +6869,10 @@ snapshots: binary-extensions@2.3.0: {} - body-parser@2.2.1: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 4.4.3 - http-errors: 2.0.1 - iconv-lite: 0.7.1 - on-finished: 2.4.1 - qs: 6.14.0 - raw-body: 3.0.2 - type-is: 2.0.1 - transitivePeerDependencies: - - supports-color - boolbase@1.0.0: {} bowser@2.13.1: {} - brace-expansion@1.1.12: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -7385,36 +6885,12 @@ snapshots: node-releases: 2.0.27 update-browserslist-db: 1.2.3(browserslist@4.28.1) - bytes@3.1.2: {} - - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 - - callsites@3.1.0: {} - caniuse-lite@1.0.30001760: {} ccount@2.0.1: {} - cdk-nag@2.37.55(aws-cdk-lib@2.232.2(constructs@10.4.4))(constructs@10.4.4): - dependencies: - aws-cdk-lib: 2.232.2(constructs@10.4.4) - constructs: 10.4.4 - chai@6.2.1: {} - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - chalk@5.6.2: {} character-entities-html4@2.1.0: {} @@ -7480,47 +6956,26 @@ snapshots: clsx@2.1.1: {} - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - comma-separated-tokens@2.0.3: {} commander@7.2.0: {} commander@8.3.0: {} - concat-map@0.0.1: {} - confbox@0.1.8: {} consola@3.4.2: {} constructs@10.4.4: {} - content-disposition@1.0.1: {} - - content-type@1.0.5: {} - convert-source-map@2.0.0: {} cookie-es@2.0.0: {} - cookie-signature@1.2.2: {} - - cookie@0.7.2: {} - copy-anything@4.0.5: dependencies: is-what: 5.5.0 - cors@2.8.5: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - cose-base@1.0.3: dependencies: layout-base: 1.0.2 @@ -7529,12 +6984,6 @@ snapshots: dependencies: layout-base: 2.0.1 - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - crossws@0.4.1(srvx@0.9.7): optionalDependencies: srvx: 0.9.7 @@ -7765,14 +7214,10 @@ snapshots: dependencies: character-entities: 2.0.2 - deep-is@0.1.4: {} - delaunator@5.0.1: dependencies: robust-predicates: 3.0.2 - depd@2.0.0: {} - dequal@2.0.3: {} detect-libc@2.1.2: {} @@ -7783,8 +7228,6 @@ snapshots: diff@8.0.2: {} - dom-accessibility-api@0.5.16: {} - dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -7807,18 +7250,16 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 - dunder-proto@1.0.1: + electrodb@3.5.0(@aws-sdk/client-dynamodb@3.958.0): dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - - ee-first@1.1.1: {} + '@aws-sdk/lib-dynamodb': 3.958.0(@aws-sdk/client-dynamodb@3.958.0) + '@aws-sdk/util-dynamodb': 3.954.0(@aws-sdk/client-dynamodb@3.958.0) + jsonschema: 1.2.7 + transitivePeerDependencies: + - '@aws-sdk/client-dynamodb' electron-to-chromium@1.5.267: {} - encodeurl@2.0.0: {} - encoding-sniffer@0.2.1: dependencies: iconv-lite: 0.6.3 @@ -7833,16 +7274,8 @@ snapshots: entities@6.0.1: {} - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - es-module-lexer@1.7.0: {} - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - esbuild@0.25.12: optionalDependencies: '@esbuild/aix-ppc64': 0.25.12 @@ -7904,229 +7337,68 @@ snapshots: escalade@3.2.0: {} - escape-html@1.0.3: {} - - escape-string-regexp@4.0.0: {} - escape-string-regexp@5.0.0: {} - eslint-cdk-plugin@3.4.7(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3): - dependencies: - eslint: 9.39.1(jiti@2.6.1) - typescript: 5.9.3 - - eslint-scope@8.4.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.1: {} - - eslint@9.39.1(jiti@2.6.1): - dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.1 - '@eslint/config-helpers': 0.4.2 - '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.3 - '@eslint/js': 9.39.1 - '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.7 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.3 - escape-string-regexp: 4.0.0 - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 2.6.1 - transitivePeerDependencies: - - supports-color - - espree@10.4.0: - dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) - eslint-visitor-keys: 4.2.1 - esprima@4.0.1: {} - esquery@1.6.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - estree-util-is-identifier-name@3.0.0: {} estree-walker@3.0.3: dependencies: '@types/estree': 1.0.8 - esutils@2.0.3: {} - - etag@1.8.1: {} - eventsource-parser@3.0.6: {} - eventsource@3.0.7: - dependencies: - eventsource-parser: 3.0.6 - expect-type@1.3.0: {} - express-rate-limit@7.5.1(express@5.2.1): - dependencies: - express: 5.2.1 - - express@5.2.1: - dependencies: - accepts: 2.0.0 - body-parser: 2.2.1 - content-disposition: 1.0.1 - content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.2.2 - debug: 4.4.3 - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 2.1.1 - fresh: 2.0.0 - http-errors: 2.0.1 - merge-descriptors: 2.0.0 - mime-types: 3.0.2 - on-finished: 2.4.1 - once: 1.4.0 - parseurl: 1.3.3 - proxy-addr: 2.0.7 - qs: 6.14.0 - range-parser: 1.2.1 - router: 2.2.0 - send: 1.2.1 - serve-static: 2.2.1 - statuses: 2.0.2 - type-is: 2.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - exsolve@1.0.8: {} extend@3.0.2: {} - fast-deep-equal@3.1.3: {} - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fast-uri@3.1.0: {} + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 fast-xml-parser@5.2.5: dependencies: strnum: 2.1.2 + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fd-package-json@2.0.0: + dependencies: + walk-up-path: 4.0.0 + fdir@6.5.0(picomatch@4.0.3): optionalDependencies: picomatch: 4.0.3 - fetchdts@0.1.7: {} - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 - finalhandler@2.1.1: + formatly@0.3.0: dependencies: - debug: 4.4.3 - encodeurl: 2.0.0 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.3 - keyv: 4.5.4 - - flatted@3.3.3: {} - - forwarded@0.2.0: {} + fd-package-json: 2.0.0 fractional-indexing@3.2.0: {} - fresh@2.0.0: {} - fsevents@2.3.2: optional: true fsevents@2.3.3: optional: true - function-bind@1.1.2: {} - gensync@1.0.0-beta.2: {} get-east-asian-width@1.4.0: {} - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - get-tsconfig@4.13.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -8135,48 +7407,30 @@ snapshots: dependencies: is-glob: 4.0.3 - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - globals@14.0.0: {} - globrex@0.1.2: {} goober@2.1.18(csstype@3.2.3): dependencies: csstype: 3.2.3 - gopd@1.2.0: {} - graceful-fs@4.2.11: {} - h3@2.0.0-beta.5(crossws@0.4.1(srvx@0.9.7)): + h3@2.0.1-rc.5(crossws@0.4.1(srvx@0.9.7)): dependencies: - cookie-es: 2.0.0 - fetchdts: 0.1.7 - rou3: 0.7.12 - srvx: 0.8.16 + rou3: 0.7.10 + srvx: 0.9.7 optionalDependencies: crossws: 0.4.1(srvx@0.9.7) - h3@2.0.1-rc.5(crossws@0.4.1(srvx@0.9.7)): + h3@2.0.1-rc.6(crossws@0.4.1(srvx@0.9.7)): dependencies: - rou3: 0.7.10 - srvx: 0.9.7 + rou3: 0.7.12 + srvx: 0.9.8 optionalDependencies: crossws: 0.4.1(srvx@0.9.7) hachure-fill@0.5.2: {} - has-flag@4.0.0: {} - - has-symbols@1.1.0: {} - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - hast-util-from-dom@5.0.1: dependencies: '@types/hast': 3.0.4 @@ -8301,8 +7555,6 @@ snapshots: highlight.js@11.11.1: {} - hono@4.11.1: {} - html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 @@ -8318,14 +7570,6 @@ snapshots: domutils: 3.2.2 entities: 6.0.1 - http-errors@2.0.1: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.2 - toidentifier: 1.0.1 - http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 @@ -8344,29 +7588,12 @@ snapshots: dependencies: safer-buffer: 2.1.2 - iconv-lite@0.7.1: - dependencies: - safer-buffer: 2.1.2 - - ignore@5.3.2: {} - - import-fresh@3.3.1: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - imurmurhash@0.1.4: {} - - inherits@2.0.4: {} - inline-style-parser@0.2.7: {} internmap@1.0.1: {} internmap@2.0.3: {} - ipaddr.js@1.9.1: {} - is-alphabetical@2.0.1: {} is-alphanumerical@2.0.1: @@ -8394,18 +7621,12 @@ snapshots: is-potential-custom-element-name@1.0.1: {} - is-promise@4.0.0: {} - is-what@5.5.0: {} isbot@5.1.32: {} - isexe@2.0.0: {} - jiti@2.6.1: {} - jose@6.1.3: {} - js-tokens@4.0.0: {} js-yaml@4.1.1: @@ -8441,30 +7662,35 @@ snapshots: jsesc@3.1.0: {} - json-buffer@3.0.1: {} - - json-schema-traverse@0.4.1: {} - - json-schema-traverse@1.0.0: {} - - json-schema-typed@8.0.2: {} - json-schema@0.4.0: {} - json-stable-stringify-without-jsonify@1.0.1: {} - json5@2.2.3: {} + jsonschema@1.2.7: {} + katex@0.16.27: dependencies: commander: 8.3.0 - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - khroma@2.1.0: {} + knip@5.77.1(@types/node@25.0.3)(typescript@5.9.3): + dependencies: + '@nodelib/fs.walk': 1.2.8 + '@types/node': 25.0.3 + fast-glob: 3.3.3 + formatly: 0.3.0 + jiti: 2.6.1 + js-yaml: 4.1.1 + minimist: 1.2.8 + oxc-resolver: 11.16.1 + picocolors: 1.1.1 + picomatch: 4.0.3 + smol-toml: 1.6.0 + strip-json-comments: 5.0.3 + typescript: 5.9.3 + zod: 4.2.1 + langium@3.3.1: dependencies: chevrotain: 11.0.3 @@ -8482,11 +7708,6 @@ snapshots: layout-base@2.0.1: {} - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - lightningcss-android-arm64@1.30.2: optional: true @@ -8536,16 +7757,10 @@ snapshots: lightningcss-win32-arm64-msvc: 1.30.2 lightningcss-win32-x64-msvc: 1.30.2 - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - lodash-es@4.17.21: {} lodash-es@4.17.22: {} - lodash.merge@4.6.2: {} - longest-streak@3.1.0: {} lru-cache@11.2.4: {} @@ -8562,8 +7777,6 @@ snapshots: dependencies: react: 19.2.3 - lz-string@1.5.0: {} - magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -8572,8 +7785,6 @@ snapshots: marked@16.4.2: {} - math-intrinsics@1.1.0: {} - mdast-util-find-and-replace@3.0.2: dependencies: '@types/mdast': 4.0.4 @@ -8741,9 +7952,7 @@ snapshots: mdn-data@2.12.2: {} - media-typer@1.1.0: {} - - merge-descriptors@2.0.0: {} + merge2@1.4.1: {} mermaid@11.12.2: dependencies: @@ -9001,15 +8210,12 @@ snapshots: transitivePeerDependencies: - supports-color - mime-db@1.54.0: {} - - mime-types@3.0.2: + micromatch@4.0.8: dependencies: - mime-db: 1.54.0 + braces: 3.0.3 + picomatch: 2.3.1 - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.12 + minimist@1.2.8: {} mlly@1.8.0: dependencies: @@ -9026,13 +8232,9 @@ snapshots: nanoid@3.3.11: {} - natural-compare@1.4.0: {} - - negotiator@1.0.0: {} - nf3@0.1.12: {} - nitro@3.0.1-alpha.1(aws4fetch@1.0.20)(lru-cache@11.2.4)(rollup@4.53.5)(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)): + nitro@3.0.1-alpha.1(aws4fetch@1.0.20)(lru-cache@11.2.4)(rollup@4.53.5)(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)): dependencies: consola: 3.4.2 crossws: 0.4.1(srvx@0.9.7) @@ -9050,7 +8252,7 @@ snapshots: unstorage: 2.0.0-alpha.4(aws4fetch@1.0.20)(db0@0.3.4)(lru-cache@11.2.4)(ofetch@2.0.0-alpha.3) optionalDependencies: rollup: 4.53.5 - vite: 8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) + vite: 8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -9088,10 +8290,6 @@ snapshots: dependencies: boolbase: 1.0.0 - object-assign@4.1.1: {} - - object-inspect@1.13.4: {} - obliterator@1.6.1: {} obug@2.1.1: {} @@ -9100,14 +8298,6 @@ snapshots: ohash@2.0.11: {} - on-finished@2.4.1: - dependencies: - ee-first: 1.1.1 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - oniguruma-parser@0.12.1: {} oniguruma-to-es@4.3.4: @@ -9116,15 +8306,6 @@ snapshots: regex: 6.1.0 regex-recursion: 6.0.2 - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - oxc-minify@0.96.0: optionalDependencies: '@oxc-minify/binding-android-arm64': 0.96.0 @@ -9143,6 +8324,29 @@ snapshots: '@oxc-minify/binding-win32-arm64-msvc': 0.96.0 '@oxc-minify/binding-win32-x64-msvc': 0.96.0 + oxc-resolver@11.16.1: + optionalDependencies: + '@oxc-resolver/binding-android-arm-eabi': 11.16.1 + '@oxc-resolver/binding-android-arm64': 11.16.1 + '@oxc-resolver/binding-darwin-arm64': 11.16.1 + '@oxc-resolver/binding-darwin-x64': 11.16.1 + '@oxc-resolver/binding-freebsd-x64': 11.16.1 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.16.1 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.16.1 + '@oxc-resolver/binding-linux-arm64-gnu': 11.16.1 + '@oxc-resolver/binding-linux-arm64-musl': 11.16.1 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.16.1 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.16.1 + '@oxc-resolver/binding-linux-riscv64-musl': 11.16.1 + '@oxc-resolver/binding-linux-s390x-gnu': 11.16.1 + '@oxc-resolver/binding-linux-x64-gnu': 11.16.1 + '@oxc-resolver/binding-linux-x64-musl': 11.16.1 + '@oxc-resolver/binding-openharmony-arm64': 11.16.1 + '@oxc-resolver/binding-wasm32-wasi': 11.16.1 + '@oxc-resolver/binding-win32-arm64-msvc': 11.16.1 + '@oxc-resolver/binding-win32-ia32-msvc': 11.16.1 + '@oxc-resolver/binding-win32-x64-msvc': 11.16.1 + oxc-transform@0.96.0: optionalDependencies: '@oxc-transform/binding-android-arm64': 0.96.0 @@ -9161,54 +8365,42 @@ snapshots: '@oxc-transform/binding-win32-arm64-msvc': 0.96.0 '@oxc-transform/binding-win32-x64-msvc': 0.96.0 - oxfmt@0.18.0: + oxfmt@0.20.0: dependencies: tinypool: 2.0.0 optionalDependencies: - '@oxfmt/darwin-arm64': 0.18.0 - '@oxfmt/darwin-x64': 0.18.0 - '@oxfmt/linux-arm64-gnu': 0.18.0 - '@oxfmt/linux-arm64-musl': 0.18.0 - '@oxfmt/linux-x64-gnu': 0.18.0 - '@oxfmt/linux-x64-musl': 0.18.0 - '@oxfmt/win32-arm64': 0.18.0 - '@oxfmt/win32-x64': 0.18.0 - - oxlint-tsgolint@0.9.1: + '@oxfmt/darwin-arm64': 0.20.0 + '@oxfmt/darwin-x64': 0.20.0 + '@oxfmt/linux-arm64-gnu': 0.20.0 + '@oxfmt/linux-arm64-musl': 0.20.0 + '@oxfmt/linux-x64-gnu': 0.20.0 + '@oxfmt/linux-x64-musl': 0.20.0 + '@oxfmt/win32-arm64': 0.20.0 + '@oxfmt/win32-x64': 0.20.0 + + oxlint-tsgolint@0.10.0: optionalDependencies: - '@oxlint-tsgolint/darwin-arm64': 0.9.1 - '@oxlint-tsgolint/darwin-x64': 0.9.1 - '@oxlint-tsgolint/linux-arm64': 0.9.1 - '@oxlint-tsgolint/linux-x64': 0.9.1 - '@oxlint-tsgolint/win32-arm64': 0.9.1 - '@oxlint-tsgolint/win32-x64': 0.9.1 - - oxlint@1.33.0(oxlint-tsgolint@0.9.1): + '@oxlint-tsgolint/darwin-arm64': 0.10.0 + '@oxlint-tsgolint/darwin-x64': 0.10.0 + '@oxlint-tsgolint/linux-arm64': 0.10.0 + '@oxlint-tsgolint/linux-x64': 0.10.0 + '@oxlint-tsgolint/win32-arm64': 0.10.0 + '@oxlint-tsgolint/win32-x64': 0.10.0 + + oxlint@1.35.0(oxlint-tsgolint@0.10.0): optionalDependencies: - '@oxlint/darwin-arm64': 1.33.0 - '@oxlint/darwin-x64': 1.33.0 - '@oxlint/linux-arm64-gnu': 1.33.0 - '@oxlint/linux-arm64-musl': 1.33.0 - '@oxlint/linux-x64-gnu': 1.33.0 - '@oxlint/linux-x64-musl': 1.33.0 - '@oxlint/win32-arm64': 1.33.0 - '@oxlint/win32-x64': 1.33.0 - oxlint-tsgolint: 0.9.1 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 + '@oxlint/darwin-arm64': 1.35.0 + '@oxlint/darwin-x64': 1.35.0 + '@oxlint/linux-arm64-gnu': 1.35.0 + '@oxlint/linux-arm64-musl': 1.35.0 + '@oxlint/linux-x64-gnu': 1.35.0 + '@oxlint/linux-x64-musl': 1.35.0 + '@oxlint/win32-arm64': 1.35.0 + '@oxlint/win32-x64': 1.35.0 + oxlint-tsgolint: 0.10.0 package-manager-detector@1.6.0: {} - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - parse-entities@4.0.2: dependencies: '@types/unist': 2.0.11 @@ -9236,16 +8428,8 @@ snapshots: dependencies: entities: 6.0.1 - parseurl@1.3.3: {} - path-data-parser@0.1.0: {} - path-exists@4.0.0: {} - - path-key@3.1.1: {} - - path-to-regexp@8.3.0: {} - pathe@2.0.3: {} picocolors@1.1.1: {} @@ -9254,8 +8438,6 @@ snapshots: picomatch@4.0.3: {} - pkce-challenge@5.0.1: {} - pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -9275,45 +8457,19 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - prelude-ls@1.2.1: {} - prettier@3.7.4: {} - pretty-format@27.5.1: - dependencies: - ansi-regex: 5.0.1 - ansi-styles: 5.2.0 - react-is: 17.0.2 - property-information@7.1.0: {} - proxy-addr@2.0.7: - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - punycode@2.3.1: {} - qs@6.14.0: - dependencies: - side-channel: 1.1.0 - - range-parser@1.2.1: {} - - raw-body@3.0.2: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.1 - iconv-lite: 0.7.1 - unpipe: 1.0.0 + queue-microtask@1.2.3: {} react-dom@19.2.3(react@19.2.3): dependencies: react: 19.2.3 scheduler: 0.27.0 - react-is@17.0.2: {} - react-refresh@0.18.0: {} react@19.2.3: {} @@ -9427,30 +8583,30 @@ snapshots: require-from-string@2.0.2: {} - resolve-from@4.0.0: {} - resolve-pkg-maps@1.0.0: {} + reusify@1.1.0: {} + robust-predicates@3.0.2: {} - rolldown@1.0.0-beta.53: + rolldown@1.0.0-beta.56: dependencies: - '@oxc-project/types': 0.101.0 - '@rolldown/pluginutils': 1.0.0-beta.53 + '@oxc-project/types': 0.103.0 + '@rolldown/pluginutils': 1.0.0-beta.56 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-beta.53 - '@rolldown/binding-darwin-arm64': 1.0.0-beta.53 - '@rolldown/binding-darwin-x64': 1.0.0-beta.53 - '@rolldown/binding-freebsd-x64': 1.0.0-beta.53 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.53 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.53 - '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.53 - '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.53 - '@rolldown/binding-linux-x64-musl': 1.0.0-beta.53 - '@rolldown/binding-openharmony-arm64': 1.0.0-beta.53 - '@rolldown/binding-wasm32-wasi': 1.0.0-beta.53 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.53 - '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.53 + '@rolldown/binding-android-arm64': 1.0.0-beta.56 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.56 + '@rolldown/binding-darwin-x64': 1.0.0-beta.56 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.56 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.56 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.56 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.56 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.56 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.56 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.56 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.56 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.56 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.56 rollup@4.53.5: dependencies: @@ -9491,15 +8647,9 @@ snapshots: points-on-curve: 0.2.0 points-on-path: 0.2.1 - router@2.2.0: + run-parallel@1.2.0: dependencies: - debug: 4.4.3 - depd: 2.0.0 - is-promise: 4.0.0 - parseurl: 1.3.3 - path-to-regexp: 8.3.0 - transitivePeerDependencies: - - supports-color + queue-microtask: 1.2.3 rw@1.3.3: {} @@ -9513,50 +8663,17 @@ snapshots: semver@6.3.1: {} - send@1.2.1: - dependencies: - debug: 4.4.3 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 2.0.0 - http-errors: 2.0.1 - mime-types: 3.0.2 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - seroval-plugins@1.3.3(seroval@1.3.2): dependencies: seroval: 1.3.2 - seroval-plugins@1.4.0(seroval@1.4.0): + seroval-plugins@1.4.0(seroval@1.4.1): dependencies: - seroval: 1.4.0 + seroval: 1.4.1 seroval@1.3.2: {} - seroval@1.4.0: {} - - serve-static@2.2.1: - dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 1.2.1 - transitivePeerDependencies: - - supports-color - - setprototypeof@1.2.0: {} - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} + seroval@1.4.1: {} shell-quote@1.8.3: {} @@ -9571,36 +8688,10 @@ snapshots: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - siginfo@2.0.0: {} + smol-toml@1.6.0: {} + solid-js@1.9.10: dependencies: csstype: 3.2.3 @@ -9617,16 +8708,12 @@ snapshots: space-separated-tokens@2.0.2: {} - srvx@0.8.16: {} - srvx@0.9.7: {} srvx@0.9.8: {} stackback@0.0.2: {} - statuses@2.0.2: {} - std-env@3.10.0: {} streamdown@1.6.10(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(react@19.2.3): @@ -9665,7 +8752,7 @@ snapshots: character-entities-html4: 2.1.0 character-entities-legacy: 3.0.0 - strip-json-comments@3.1.1: {} + strip-json-comments@5.0.3: {} strnum@2.1.2: {} @@ -9683,10 +8770,6 @@ snapshots: dependencies: copy-anything: 4.0.5 - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - swr@2.3.8(react@19.2.3): dependencies: dequal: 2.0.3 @@ -9730,8 +8813,6 @@ snapshots: dependencies: is-number: 7.0.0 - toidentifier@1.0.1: {} - tough-cookie@6.0.0: dependencies: tldts: 7.0.19 @@ -9761,16 +8842,6 @@ snapshots: tw-animate-css@1.4.0: {} - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - type-is@2.0.1: - dependencies: - content-type: 1.0.5 - media-typer: 1.1.0 - mime-types: 3.0.2 - typescript@5.9.3: {} ufo@1.6.1: {} @@ -9826,8 +8897,6 @@ snapshots: unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 - unpipe@1.0.0: {} - unplugin@2.3.11: dependencies: '@jridgewell/remapping': 2.3.5 @@ -9848,18 +8917,12 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - use-sync-external-store@1.6.0(react@19.2.3): dependencies: react: 19.2.3 uuid@11.1.0: {} - vary@1.1.2: {} - vfile-location@5.0.3: dependencies: '@types/unist': 3.0.3 @@ -9875,13 +8938,13 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-tsconfig-paths@6.0.3(typescript@5.9.3)(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)): + vite-tsconfig-paths@6.0.3(typescript@5.9.3)(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)): dependencies: debug: 4.4.3 globrex: 0.1.2 tsconfck: 3.1.6(typescript@5.9.3) optionalDependencies: - vite: 8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) + vite: 8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) transitivePeerDependencies: - supports-color - typescript @@ -9901,14 +8964,14 @@ snapshots: lightningcss: 1.30.2 tsx: 4.21.0 - vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0): + vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0): dependencies: - '@oxc-project/runtime': 0.101.0 + '@oxc-project/runtime': 0.103.0 fdir: 6.5.0(picomatch@4.0.3) lightningcss: 1.30.2 picomatch: 4.0.3 postcss: 8.5.6 - rolldown: 1.0.0-beta.53 + rolldown: 1.0.0-beta.56 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 25.0.3 @@ -9917,9 +8980,9 @@ snapshots: jiti: 2.6.1 tsx: 4.21.0 - vitefu@1.1.1(vite@8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)): + vitefu@1.1.1(vite@8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0)): optionalDependencies: - vite: 8.0.0-beta.0(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) + vite: 8.0.0-beta.4(@types/node@25.0.3)(esbuild@0.25.12)(jiti@2.6.1)(tsx@4.21.0) vitest@4.0.16(@opentelemetry/api@1.9.0)(@types/node@25.0.3)(jiti@2.6.1)(jsdom@27.3.0)(lightningcss@1.30.2)(tsx@4.21.0): dependencies: @@ -9981,9 +9044,9 @@ snapshots: dependencies: xml-name-validator: 5.0.0 - web-namespaces@2.0.1: {} + walk-up-path@4.0.0: {} - web-vitals@5.1.0: {} + web-namespaces@2.0.1: {} webidl-conversions@8.0.0: {} @@ -10000,19 +9063,11 @@ snapshots: tr46: 6.0.0 webidl-conversions: 8.0.0 - 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: {} - - wrappy@1.0.2: {} - ws@8.18.3: {} xml-name-validator@5.0.0: {} @@ -10028,12 +9083,6 @@ snapshots: yallist@3.1.1: {} - yocto-queue@0.1.0: {} - - zod-to-json-schema@3.25.0(zod@4.2.1): - dependencies: - zod: 4.2.1 - zod@3.25.76: {} zod@4.2.1: {} diff --git a/scripts/seed-persons.ts b/scripts/seed-persons.ts new file mode 100644 index 0000000..55fda90 --- /dev/null +++ b/scripts/seed-persons.ts @@ -0,0 +1,181 @@ +#!/usr/bin/env node +// oxlint-disable max-statements +/* oxlint-disable no-console, no-await-in-loop, no-magic-numbers */ +/** + * Seed Script for DB Persons + * + * Populates the DynamoDB Persons table with fake data. + * Uses ElectroDB client and faker data generators. + * + * Usage: + * pnpm seed:persons + * pnpm seed:persons 100 # Seed 100 persons + * pnpm seed:persons --clear # Clear existing data first + */ + +import type { ContactInfo, Employment, PersonWithRelations } from '#src/webapp/types/person.ts'; +import { generatePersons, initFaker } from '#src/webapp/data/fake-persons.ts'; +import { + createAddress, + createBankAccount, + createContact, + createEmployment, + createPerson, + deletePerson, + getAllPersons, +} from '#src/webapp/integrations/electrodb/personsClient.ts'; + +// ============================================================================= +// Configuration +// ============================================================================= + +const DEFAULT_COUNT = 50; +const BATCH_SIZE = 10; +const LOG_INTERVAL = 10; + +// ============================================================================= +// Helpers +// ============================================================================= + +const normalizeContactInfo = ( + contact: ContactInfo, +): Omit & { isVerified: boolean } => ({ + ...contact, + isVerified: contact.isVerified ?? false, +}); + +const normalizeEmployment = ( + employment: Employment, +): Omit & { endDate: string | undefined } => ({ + ...employment, + endDate: employment.endDate ?? undefined, +}); + +const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +// ============================================================================= +// Seed Functions +// ============================================================================= + +const seedOnePerson = async (personData: PersonWithRelations): Promise => { + // Create the person + await createPerson({ + id: personData.id, + firstName: personData.firstName, + lastName: personData.lastName, + dateOfBirth: personData.dateOfBirth, + gender: personData.gender, + createdAt: personData.createdAt, + updatedAt: personData.updatedAt, + }); + + // Create related entities in parallel + await Promise.all([ + ...personData.addresses.map((addr) => createAddress(addr)), + ...personData.bankAccounts.map((bank) => createBankAccount(bank)), + ...personData.contacts.map((contact) => createContact(normalizeContactInfo(contact))), + ...personData.employments.map((emp) => createEmployment(normalizeEmployment(emp))), + ]); +}; + +const seedPersonsBatch = async (persons: PersonWithRelations[]): Promise => { + let successCount = 0; + + for (const person of persons) { + try { + await seedOnePerson(person); + successCount++; + } catch (error) { + console.error(`Failed to seed person ${person.id}:`, error); + } + } + + return successCount; +}; + +const clearAllPersons = async (): Promise => { + console.log('Clearing existing persons...'); + + const existingPersons = await getAllPersons(); + let deletedCount = 0; + + for (const person of existingPersons) { + try { + await deletePerson(person.id); + deletedCount++; + if (deletedCount % LOG_INTERVAL === 0) { + console.log(` Deleted ${deletedCount}/${existingPersons.length} persons...`); + } + } catch (error) { + console.error(`Failed to delete person ${person.id}:`, error); + } + } + + console.log(`Cleared ${deletedCount} persons`); + return deletedCount; +}; + +// ============================================================================= +// Main +// ============================================================================= + +const main = async () => { + // Parse arguments + const args = process.argv.slice(2); + const shouldClear = args.includes('--clear'); + const countArg = args.find((arg) => !arg.startsWith('--')); + let count = DEFAULT_COUNT; + if (countArg) { + count = parseInt(countArg, 10); + } + + console.log('='.repeat(60)); + console.log('DB Persons Seed Script'); + console.log('='.repeat(60)); + + // Check for table name + const tableName = process.env.DDB_PERSONS_TABLE_NAME; + if (!tableName) { + console.error('Error: DDB_PERSONS_TABLE_NAME environment variable not set'); + console.log('\nRun: export DDB_PERSONS_TABLE_NAME='); + process.exit(1); + } + console.log(`Table: ${tableName}`); + + // Clear if requested + if (shouldClear) { + await clearAllPersons(); + console.log(''); + } + + // Generate fake data + console.log(`Generating ${count} persons...`); + initFaker(); + const persons = generatePersons(count); + console.log(`Generated ${persons.length} persons with relations`); + + // Seed in batches + console.log(`\nSeeding in batches of ${BATCH_SIZE}...`); + let totalSeeded = 0; + + for (let idx = 0; idx < persons.length; idx += BATCH_SIZE) { + const batch = persons.slice(idx, idx + BATCH_SIZE); + const seeded = await seedPersonsBatch(batch); + totalSeeded += seeded; + + console.log(` Seeded ${totalSeeded}/${persons.length} persons...`); + + // Small delay to avoid throttling + await sleep(100); + } + + console.log(''); + console.log('='.repeat(60)); + console.log(`Seed Complete: ${totalSeeded} persons created`); + console.log('='.repeat(60)); +}; + +main().catch((error) => { + console.error('Seed script failed:', error); + process.exit(1); +}); diff --git a/src/webapp/components/Header.tsx b/src/webapp/components/Header.tsx index 635655e..4372dc4 100644 --- a/src/webapp/components/Header.tsx +++ b/src/webapp/components/Header.tsx @@ -12,6 +12,7 @@ import { SquareFunction, StickyNote, Store, + Users, X, } from 'lucide-react'; import { useState } from 'react'; @@ -244,6 +245,18 @@ export default function Header() { DB Todo + setIsOpen(false)} + className="flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2" + activeProps={{ + className: + 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2', + }} + > + + DB Persons + {/* Demo Links End */} diff --git a/src/webapp/components/persons/AddressCard.tsx b/src/webapp/components/persons/AddressCard.tsx new file mode 100644 index 0000000..3e41de5 --- /dev/null +++ b/src/webapp/components/persons/AddressCard.tsx @@ -0,0 +1,83 @@ +import type { Address } from '#src/webapp/types/person'; +import { Button } from '#src/webapp/components/ui/button'; +import { MapPin, Pencil, Star, Trash2 } from 'lucide-react'; +import { useState } from 'react'; +import { ConfirmationModal } from './ConfirmationModal'; + +interface AddressCardProps { + address: Address; + onUpdate?: (addressId: string, updates: Partial
) => void; + onDelete?: (addressId: string) => void; + onEdit?: (address: Address) => void; + isLoading?: boolean; +} + +export const AddressCard = ({ address, onDelete, onEdit, isLoading }: AddressCardProps) => { + const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); + + const handleDeleteConfirm = () => { + onDelete?.(address.id); + setShowDeleteConfirm(false); + }; + + return ( +
+
+
+ +
+
+ + {address.type} + + {address.isPrimary && ( +
+ + Primary +
+ )} +
+

{address.street}

+

+ {address.city}, {address.state} {address.postalCode} +

+

{address.country}

+
+
+ +
+ + +
+
+ + setShowDeleteConfirm(false)} + /> +
+ ); +}; diff --git a/src/webapp/components/persons/AddressForm.tsx b/src/webapp/components/persons/AddressForm.tsx new file mode 100644 index 0000000..b3f69f7 --- /dev/null +++ b/src/webapp/components/persons/AddressForm.tsx @@ -0,0 +1,235 @@ +import { Button } from '#src/webapp/components/ui/button'; +import { type Address, AddressTypeEnum } from '#src/webapp/types/person'; +import { useForm } from '@tanstack/react-form'; +// oxlint-disable no-magic-numbers +// oxlint-disable no-ternary +import { z } from 'zod'; + +const AddressFormSchema = z.object({ + type: AddressTypeEnum, + street: z.string().min(1, 'Street is required').max(200), + city: z.string().min(1, 'City is required').max(100), + state: z.string().min(1, 'State is required').max(100), + postalCode: z.string().min(1, 'Postal code is required').max(20), + country: z.string().min(1, 'Country is required').max(100), + isPrimary: z.boolean().default(false), +}); + +type AddressFormValues = z.infer; + +interface AddressFormProps { + address?: Address; + onSave: (values: AddressFormValues) => void; + onCancel?: () => void; + isLoading?: boolean; +} + +export const AddressForm = ({ address, onSave, onCancel, isLoading }: AddressFormProps) => { + const formApi = useForm({ + defaultValues: { + type: address?.type ?? 'home', + street: address?.street ?? '', + city: address?.city ?? '', + state: address?.state ?? '', + postalCode: address?.postalCode ?? '', + country: address?.country ?? 'USA', + isPrimary: address?.isPrimary ?? false, + }, + validators: { + onChange: (({ value }: { value: AddressFormValues }) => { + const result = AddressFormSchema.safeParse(value); + if (!result.success) { + return result.error; + } + return undefined; + }) as any, + }, + onSubmit: ({ value }: { value: AddressFormValues }) => { + onSave(value); + }, + }); + const FormField = formApi.Field; + + return ( +
{ + event.preventDefault(); + formApi.handleSubmit(); + }} + className="space-y-4" + > + + {(field: any) => ( +
+ + + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ +
+ + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ? ( +

{firstError}

+ ) : null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ? ( +

{firstError}

+ ) : null; + })()} +
+ )} +
+
+ +
+ + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ? ( +

{firstError}

+ ) : null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ? ( +

{firstError}

+ ) : null; + })()} +
+ )} +
+
+ + + {(field: any) => ( +
+ field.handleChange(event.target.checked)} + onBlur={field.handleBlur} + /> +
+ Primary Address + This is your main address. +
+
+ )} +
+ +
+ {(() => { + let submitLabel = 'Add Address'; + if (address) { + submitLabel = 'Update Address'; + } + if (isLoading) { + submitLabel = 'Saving...'; + } + return ( + + ); + })()} + {onCancel && ( + + )} +
+
+ ); +}; diff --git a/src/webapp/components/persons/AddressFormModal.tsx b/src/webapp/components/persons/AddressFormModal.tsx new file mode 100644 index 0000000..78f5637 --- /dev/null +++ b/src/webapp/components/persons/AddressFormModal.tsx @@ -0,0 +1,51 @@ +import type { Address } from '#src/webapp/types/person'; +import { X } from 'lucide-react'; +import { AddressForm } from './AddressForm'; + +interface AddressFormModalProps { + personId: string; + address?: Address; + onSave: (address: Omit) => void; + onCancel: () => void; +} + +export const AddressFormModal = ({ + personId: _personId, + address, + onSave, + onCancel, +}: AddressFormModalProps) => { + let title = 'Add Address'; + if (address) { + title = 'Edit Address'; + } + + const handleSave = (values: { + type: Address['type']; + street: string; + city: string; + state: string; + postalCode: string; + country: string; + isPrimary: boolean; + }) => { + onSave({ ...values, personId: _personId }); + }; + + return ( +
+
+
+

{title}

+ +
+ +
+
+ ); +}; diff --git a/src/webapp/components/persons/BankAccountCard.tsx b/src/webapp/components/persons/BankAccountCard.tsx new file mode 100644 index 0000000..e58923e --- /dev/null +++ b/src/webapp/components/persons/BankAccountCard.tsx @@ -0,0 +1,106 @@ +import type { BankAccount } from '#src/webapp/types/person'; +import { Button } from '#src/webapp/components/ui/button'; +import { CreditCard, Landmark, Pencil, Star, Trash2 } from 'lucide-react'; +import { useState } from 'react'; +import { ConfirmationModal } from './ConfirmationModal'; + +interface BankAccountCardProps { + bankAccount: BankAccount; + onUpdate?: (accountId: string, updates: Partial) => void; + onDelete?: (accountId: string) => void; + onEdit?: (bankAccount: BankAccount) => void; + isLoading?: boolean; +} + +export const BankAccountCard = ({ + bankAccount, + onUpdate, + onDelete, + onEdit, + isLoading, +}: BankAccountCardProps) => { + const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); + + const handleDeleteConfirm = () => { + onDelete?.(bankAccount.id); + setShowDeleteConfirm(false); + }; + + const handleSetPrimary = () => { + onUpdate?.(bankAccount.id, { isPrimary: true }); + }; + + return ( +
+
+
+ +
+
+

{bankAccount.bankName}

+ {bankAccount.isPrimary && ( +
+ + Primary +
+ )} +
+
+ + {bankAccount.accountType} + + ****{bankAccount.accountNumberLast4} +
+ {bankAccount.iban &&

IBAN: {bankAccount.iban}

} + {bankAccount.bic &&

BIC: {bankAccount.bic}

} +
+
+ +
+ {!bankAccount.isPrimary && ( + + )} + + +
+
+ + setShowDeleteConfirm(false)} + /> +
+ ); +}; diff --git a/src/webapp/components/persons/BankAccountForm.tsx b/src/webapp/components/persons/BankAccountForm.tsx new file mode 100644 index 0000000..53aa68f --- /dev/null +++ b/src/webapp/components/persons/BankAccountForm.tsx @@ -0,0 +1,190 @@ +import type { BankAccount } from '#src/webapp/types/person'; +import { Button } from '#src/webapp/components/ui/button'; +// oxlint-disable no-magic-numbers +// oxlint-disable no-ternary +import { useForm } from '@tanstack/react-form'; +import { z } from 'zod'; + +const AccountTypeEnum = z.enum(['checking', 'savings', 'investment']); + +const BankAccountFormSchema = z.object({ + bankName: z.string().min(1, 'Bank name is required').max(100), + accountType: AccountTypeEnum, + accountNumberLast4: z.string().min(4, 'Last 4 digits').max(4), + iban: z.string().optional(), + bic: z.string().optional(), + isPrimary: z.boolean().default(false), +}); + +type BankAccountFormValues = z.infer; + +interface BankAccountFormProps { + account?: BankAccount; + onSave: (values: BankAccountFormValues) => void; + onCancel?: () => void; + isLoading?: boolean; +} + +export const BankAccountForm = ({ account, onSave, onCancel, isLoading }: BankAccountFormProps) => { + const formApi = useForm({ + defaultValues: { + bankName: account?.bankName ?? '', + accountType: account?.accountType ?? 'checking', + accountNumberLast4: account?.accountNumberLast4 ?? '', + iban: account?.iban ?? '', + bic: account?.bic ?? '', + isPrimary: account?.isPrimary ?? false, + }, + validators: { + onChange: (({ value }: { value: BankAccountFormValues }) => { + const result = BankAccountFormSchema.safeParse(value); + if (!result.success) { + return result.error; + } + return undefined; + }) as any, + }, + onSubmit: ({ value }: { value: BankAccountFormValues }) => { + onSave(value); + }, + }); + const FormField = formApi.Field; + + return ( +
{ + event.preventDefault(); + formApi.handleSubmit(); + }} + className="space-y-4" + > + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ field.handleChange(event.target.checked)} + onBlur={field.handleBlur} + /> + Primary +
+ )} +
+ +
+ {onCancel && ( + + )} + +
+
+ ); +}; diff --git a/src/webapp/components/persons/BankAccountFormModal.tsx b/src/webapp/components/persons/BankAccountFormModal.tsx new file mode 100644 index 0000000..b7c46d0 --- /dev/null +++ b/src/webapp/components/persons/BankAccountFormModal.tsx @@ -0,0 +1,50 @@ +import type { BankAccount } from '#src/webapp/types/person'; +import { X } from 'lucide-react'; +import { BankAccountForm } from './BankAccountForm.tsx'; + +interface BankAccountFormModalProps { + personId: string; + account?: BankAccount; + onSave: (account: Omit) => void; + onCancel: () => void; +} + +export const BankAccountFormModal = ({ + personId: _personId, + account, + onSave, + onCancel, +}: BankAccountFormModalProps) => { + let title = 'Add Bank Account'; + if (account) { + title = 'Edit Bank Account'; + } + + const handleSave = (values: { + bankName: string; + accountType: BankAccount['accountType']; + accountNumberLast4: string; + iban?: string; + bic?: string; + isPrimary: boolean; + }) => { + onSave({ ...values, personId: _personId }); + }; + + return ( +
+
+
+

{title}

+ +
+ +
+
+ ); +}; diff --git a/src/webapp/components/persons/ConfirmationModal.tsx b/src/webapp/components/persons/ConfirmationModal.tsx new file mode 100644 index 0000000..35c5e5b --- /dev/null +++ b/src/webapp/components/persons/ConfirmationModal.tsx @@ -0,0 +1,67 @@ +import { Button } from '#src/webapp/components/ui/button'; +import { X } from 'lucide-react'; + +// oxlint-disable no-ternary + +interface ConfirmationModalProps { + title: string; + message: string; + confirmLabel?: string; + cancelLabel?: string; + isOpen: boolean; + isLoading?: boolean; + onConfirm: () => void; + onCancel: () => void; + isDangerous?: boolean; +} + +export const ConfirmationModal = ({ + title, + message, + confirmLabel = 'Confirm', + cancelLabel = 'Cancel', + isOpen, + isLoading = false, + onConfirm, + onCancel, + isDangerous = false, +}: ConfirmationModalProps) => { + if (!isOpen) { + return null; + } + + return ( +
+
+
+

{title}

+ +
+ +

{message}

+ +
+ + +
+
+
+ ); +}; diff --git a/src/webapp/components/persons/ContactForm.tsx b/src/webapp/components/persons/ContactForm.tsx new file mode 100644 index 0000000..323a75b --- /dev/null +++ b/src/webapp/components/persons/ContactForm.tsx @@ -0,0 +1,139 @@ +import type { ContactInfo } from '#src/webapp/types/person'; +import { Button } from '#src/webapp/components/ui/button'; +// oxlint-disable no-magic-numbers +// oxlint-disable no-ternary +import { useForm } from '@tanstack/react-form'; +import { z } from 'zod'; + +const ContactTypeEnum = z.enum(['email', 'phone', 'mobile', 'linkedin', 'twitter']); + +const ContactFormSchema = z.object({ + type: ContactTypeEnum, + value: z.string().min(1, 'Value is required').max(200), + isPrimary: z.boolean().default(false), + isVerified: z.boolean().default(false), +}); + +type ContactFormValues = z.infer; + +interface ContactFormProps { + contact?: ContactInfo; + onSave: (values: ContactFormValues) => void; + onCancel?: () => void; + isLoading?: boolean; +} + +export const ContactForm = ({ contact, onSave, onCancel, isLoading }: ContactFormProps) => { + const formApi = useForm({ + defaultValues: { + type: contact?.type ?? 'email', + value: contact?.value ?? '', + isPrimary: contact?.isPrimary ?? false, + isVerified: contact?.isVerified ?? false, + }, + validators: { onChange: ContactFormSchema }, + onSubmit: ({ value }: { value: ContactFormValues }) => { + onSave(value); + }, + }); + const FormField = formApi.Field; + + return ( +
{ + event.preventDefault(); + formApi.handleSubmit(); + }} + className="space-y-4" + > + + {(field: any) => ( +
+ + + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ +
+ + {(field: any) => ( +
+ field.handleChange(event.target.checked)} + onBlur={field.handleBlur} + /> + Primary +
+ )} +
+ + + {(field: any) => ( +
+ field.handleChange(event.target.checked)} + onBlur={field.handleBlur} + /> + Verified +
+ )} +
+
+ +
+ {onCancel && ( + + )} + +
+
+ ); +}; diff --git a/src/webapp/components/persons/ContactFormModal.tsx b/src/webapp/components/persons/ContactFormModal.tsx new file mode 100644 index 0000000..3c28bd0 --- /dev/null +++ b/src/webapp/components/persons/ContactFormModal.tsx @@ -0,0 +1,48 @@ +import type { ContactInfo } from '#src/webapp/types/person'; +import { X } from 'lucide-react'; +import { ContactForm } from './ContactForm'; + +interface ContactFormModalProps { + personId: string; + contact?: ContactInfo; + onSave: (contact: Omit) => void; + onCancel: () => void; +} + +export const ContactFormModal = ({ + personId: _personId, + contact, + onSave, + onCancel, +}: ContactFormModalProps) => { + let title = 'Add Contact'; + if (contact) { + title = 'Edit Contact'; + } + + const handleSave = (values: { + type: ContactInfo['type']; + value: string; + isPrimary: boolean; + isVerified: boolean; + }) => { + onSave({ ...values, personId: _personId }); + }; + + return ( +
+
+
+

{title}

+ +
+ +
+
+ ); +}; diff --git a/src/webapp/components/persons/ContactInfoCard.tsx b/src/webapp/components/persons/ContactInfoCard.tsx new file mode 100644 index 0000000..7eca02f --- /dev/null +++ b/src/webapp/components/persons/ContactInfoCard.tsx @@ -0,0 +1,125 @@ +import type { ContactInfo } from '#src/webapp/types/person'; +import { Button } from '#src/webapp/components/ui/button'; +import { CheckCircle2, Linkedin, Mail, Pencil, Phone, Star, Trash2, Twitter } from 'lucide-react'; +import { useState } from 'react'; +import { ConfirmationModal } from './ConfirmationModal'; + +interface ContactInfoCardProps { + contact: ContactInfo; + onUpdate?: (contactId: string, updates: Partial) => void; + onDelete?: (contactId: string) => void; + onEdit?: (contact: ContactInfo) => void; + isLoading?: boolean; +} + +const getContactIcon = (type: string) => { + switch (type) { + case 'email': + return Mail; + case 'phone': + case 'mobile': + return Phone; + case 'linkedin': + return Linkedin; + case 'twitter': + return Twitter; + default: + return Mail; + } +}; + +export const ContactInfoCard = ({ + contact, + onUpdate, + onDelete, + onEdit, + isLoading, +}: ContactInfoCardProps) => { + const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); + + const handleDeleteConfirm = () => { + onDelete?.(contact.id); + setShowDeleteConfirm(false); + }; + + const handleSetPrimary = () => { + onUpdate?.(contact.id, { isPrimary: true }); + }; + + const Icon = getContactIcon(contact.type); + + return ( +
+
+
+ +
+
+ + {contact.type} + + {contact.isPrimary && ( +
+ + Primary +
+ )} + {contact.isVerified && ( +
+ + Verified +
+ )} +
+

{contact.value}

+
+
+ +
+ {!contact.isPrimary && ( + + )} + + +
+
+ + setShowDeleteConfirm(false)} + /> +
+ ); +}; diff --git a/src/webapp/components/persons/CreatePersonModal.tsx b/src/webapp/components/persons/CreatePersonModal.tsx new file mode 100644 index 0000000..4f26ec0 --- /dev/null +++ b/src/webapp/components/persons/CreatePersonModal.tsx @@ -0,0 +1,25 @@ +import type { Person } from '#src/webapp/types/person'; +import { X } from 'lucide-react'; +import { PersonForm } from './PersonForm'; + +interface CreatePersonModalProps { + onSave: (person: Omit) => void; + onCancel: () => void; +} + +export const CreatePersonModal = ({ onSave, onCancel }: CreatePersonModalProps) => ( +
+
+
+

Create Person

+ +
+ +
+
+); diff --git a/src/webapp/components/persons/EmploymentCard.tsx b/src/webapp/components/persons/EmploymentCard.tsx new file mode 100644 index 0000000..afddcdd --- /dev/null +++ b/src/webapp/components/persons/EmploymentCard.tsx @@ -0,0 +1,123 @@ +import type { Employment } from '#src/webapp/types/person'; +import { Badge } from '#src/webapp/components/ui/badge'; +import { Button } from '#src/webapp/components/ui/button'; +import { Briefcase, Building2, Calendar, DollarSign, Pencil, Trash2 } from 'lucide-react'; +import { useState } from 'react'; +import { ConfirmationModal } from './ConfirmationModal'; + +// oxlint-disable no-ternary + +interface EmploymentCardProps { + employment: Employment; + onUpdate?: (employmentId: string, updates: Partial) => void; + onDelete?: (employmentId: string) => void; + onEdit?: (employment: Employment) => void; + isLoading?: boolean; +} + +export const EmploymentCard = ({ + employment, + onDelete, + onEdit, + isLoading, +}: EmploymentCardProps) => { + const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); + + const handleDeleteConfirm = () => { + onDelete?.(employment.id); + setShowDeleteConfirm(false); + }; + + const formatDate = (dateString: string) => + new Date(dateString).toLocaleDateString('en-US', { + year: 'numeric', + month: 'short', + }); + + const formatSalary = (salary?: number, currency?: string) => { + if (!salary) { + return null; + } + return new Intl.NumberFormat('en-US', { + style: 'currency', + currency: currency ?? 'USD', + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }).format(salary); + }; + + return ( +
+
+
+ +
+
+

{employment.position}

+ {employment.isCurrent && Current} +
+ +
+ + {employment.companyName} + {employment.department && ( + <> + + {employment.department} + + )} +
+ +
+ + + {formatDate(employment.startDate)} -{' '} + {employment.endDate ? formatDate(employment.endDate) : 'Present'} + +
+ + {employment.salary && ( +
+ + {formatSalary(employment.salary, employment.currency)} +
+ )} +
+
+ +
+ + +
+
+ + setShowDeleteConfirm(false)} + /> +
+ ); +}; diff --git a/src/webapp/components/persons/EmploymentForm.tsx b/src/webapp/components/persons/EmploymentForm.tsx new file mode 100644 index 0000000..c39d16b --- /dev/null +++ b/src/webapp/components/persons/EmploymentForm.tsx @@ -0,0 +1,258 @@ +import type { Employment } from '#src/webapp/types/person'; +import { Button } from '#src/webapp/components/ui/button'; +// oxlint-disable no-ternary +// oxlint-disable no-magic-numbers +import { useForm } from '@tanstack/react-form'; +import { z } from 'zod'; + +const EmploymentFormSchema = z.object({ + companyName: z.string().min(1, 'Company name is required').max(100), + position: z.string().min(1, 'Position is required').max(100), + department: z.string().optional(), + startDate: z.string().min(1, 'Start date is required'), + endDate: z.string().nullable().optional(), + isCurrent: z.boolean().default(false), + salary: z.number().positive().optional(), + currency: z.string().length(3, 'Use a 3-letter currency code').default('USD'), +}); + +type EmploymentFormValues = z.infer; + +interface EmploymentFormProps { + employment?: Employment; + onSave: (values: EmploymentFormValues) => void; + onCancel?: () => void; + isLoading?: boolean; +} + +export const EmploymentForm = ({ + employment, + onSave, + onCancel, + isLoading, +}: EmploymentFormProps) => { + const formApi = useForm({ + defaultValues: { + companyName: employment?.companyName ?? '', + position: employment?.position ?? '', + department: employment?.department ?? '', + startDate: employment?.startDate ? employment.startDate.split('T')[0] : '', + endDate: employment?.endDate ? employment.endDate.split('T')[0] : '', + isCurrent: employment?.isCurrent ?? false, + salary: employment?.salary ?? undefined, + currency: employment?.currency ?? 'USD', + } satisfies EmploymentFormValues, + validators: { + onChange: (({ value }: { value: EmploymentFormValues }) => { + const result = EmploymentFormSchema.safeParse(value); + if (!result.success) { + return result.error; + } + return undefined; + }) as any, + }, + onSubmit: ({ value }: { value: EmploymentFormValues }) => { + const normalizedSalary = value.salary ?? undefined; + const normalizedEndDate = + value.isCurrent || !value.endDate ? null : new Date(value.endDate).toISOString(); + + onSave({ + ...value, + startDate: new Date(value.startDate).toISOString(), + endDate: normalizedEndDate, + salary: normalizedSalary, + }); + }, + }); + const FormField = formApi.Field; + + return ( +
{ + event.preventDefault(); + formApi.handleSubmit(); + }} + className="space-y-4" + > + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ +
+ + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ? ( +

{firstError}

+ ) : null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + disabled={formApi.state.values.isCurrent} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ? ( +

{firstError}

+ ) : null; + })()} +
+ )} +
+
+ + + {(field: any) => ( +
+ field.handleChange(event.target.checked)} + onBlur={field.handleBlur} + /> + Current Role +
+ )} +
+ +
+ + {(field: any) => ( +
+ + { + const valueStr = event.target.value; + field.handleChange(valueStr ? Number(valueStr) : undefined); + }} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ? ( +

{firstError}

+ ) : null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value.toUpperCase())} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ? ( +

{firstError}

+ ) : null; + })()} +
+ )} +
+
+ +
+ {onCancel && ( + + )} + +
+
+ ); +}; diff --git a/src/webapp/components/persons/EmploymentFormModal.tsx b/src/webapp/components/persons/EmploymentFormModal.tsx new file mode 100644 index 0000000..d8a8240 --- /dev/null +++ b/src/webapp/components/persons/EmploymentFormModal.tsx @@ -0,0 +1,52 @@ +import type { Employment } from '#src/webapp/types/person'; +import { X } from 'lucide-react'; +import { EmploymentForm } from './EmploymentForm.tsx'; + +interface EmploymentFormModalProps { + personId: string; + employment?: Employment; + onSave: (employment: Omit) => void; + onCancel: () => void; +} + +export const EmploymentFormModal = ({ + personId: _personId, + employment, + onSave, + onCancel, +}: EmploymentFormModalProps) => { + let title = 'Add Employment'; + if (employment) { + title = 'Edit Employment'; + } + + const handleSave = (values: { + companyName: string; + position: string; + department?: string; + startDate: string; + endDate?: string | null; + isCurrent: boolean; + salary?: number; + currency: string; + }) => { + onSave({ ...values, personId: _personId }); + }; + + return ( +
+
+
+

{title}

+ +
+ +
+
+ ); +}; diff --git a/src/webapp/components/persons/PersonDetailPanel.tsx b/src/webapp/components/persons/PersonDetailPanel.tsx new file mode 100644 index 0000000..4cd23b9 --- /dev/null +++ b/src/webapp/components/persons/PersonDetailPanel.tsx @@ -0,0 +1,352 @@ +import type { + Address, + BankAccount, + ContactInfo, + Employment, + Person, +} from '#src/webapp/types/person'; +import { usePersonDetail } from '#src/webapp/hooks/useDbPersons'; +// oxlint-disable no-ternary +// oxlint-disable no-magic-numbers +// oxlint-disable id-length +// oxlint-disable max-statements +import { Briefcase, Edit2, Landmark, Mail, MapPin, Plus, Trash2, User, X } from 'lucide-react'; +import { useState } from 'react'; +import { AddressCard } from './AddressCard'; +import { AddressFormModal } from './AddressFormModal.tsx'; +import { BankAccountCard } from './BankAccountCard'; +import { BankAccountFormModal } from './BankAccountFormModal.tsx'; +import { ContactFormModal } from './ContactFormModal.tsx'; +import { ContactInfoCard } from './ContactInfoCard'; +import { EmploymentCard } from './EmploymentCard'; +import { EmploymentFormModal } from './EmploymentFormModal.tsx'; +import { PersonEditModal } from './PersonEditModal.tsx'; + +interface PersonDetailPanelProps { + personId: string; + onClose: () => void; +} + +export const PersonDetailPanel = ({ personId, onClose }: PersonDetailPanelProps) => { + const { + person, + addresses, + contacts, + employments, + bankAccounts, + isLoading, + updatePerson, + deletePerson, + addAddress, + updateAddress, + deleteAddress, + addContact, + updateContact, + deleteContact, + addBankAccount, + updateBankAccount, + deleteBankAccount, + addEmployment, + updateEmployment, + deleteEmployment, + } = usePersonDetail(personId); + + const [editingPerson, setEditingPerson] = useState(false); + const [editingAddress, setEditingAddress] = useState
(null); + const [addingAddress, setAddingAddress] = useState(false); + const [editingContact, setEditingContact] = useState(null); + const [addingContact, setAddingContact] = useState(false); + const [editingBankAccount, setEditingBankAccount] = useState(null); + const [addingBankAccount, setAddingBankAccount] = useState(false); + const [editingEmployment, setEditingEmployment] = useState(null); + const [addingEmployment, setAddingEmployment] = useState(false); + + if (isLoading) { + return ( +
+
Loading person details...
+
+ ); + } + + if (!person) { + return null; + } + + const handleDeletePerson = () => { + if (confirm('Are you sure you want to delete this person? This cannot be undone.')) { + deletePerson(); + onClose(); + } + }; + + return ( + <> +
+ {/* Header */} +
+
+ +
+

+ {person.firstName} {person.lastName} +

+

ID: {person.id}

+
+
+
+ + + +
+
+ + {/* Content Grid - Scrollable */} +
+ {/* Addresses */} + setAddingAddress(true)} + > + {addresses.length === 0 ? ( +

No addresses

+ ) : ( + addresses.map((addressItem) => ( + updateAddress(id, updates)} + onDelete={(id) => deleteAddress(id)} + onEdit={(address) => setEditingAddress(address)} + /> + )) + )} +
+ + {/* Contacts */} + setAddingContact(true)} + > + {contacts.length === 0 ? ( +

No contacts

+ ) : ( + contacts.map((contactItem) => ( + updateContact(id, updates)} + onDelete={(id) => deleteContact(id)} + onEdit={(contact) => setEditingContact(contact)} + /> + )) + )} +
+ + {/* Employment */} + setAddingEmployment(true)} + > + {employments.length === 0 ? ( +

No employment records

+ ) : ( + employments.map((employmentItem) => ( + updateEmployment(id, updates)} + onDelete={(id) => deleteEmployment(id)} + onEdit={(employment) => setEditingEmployment(employment)} + /> + )) + )} +
+ + {/* Bank Accounts */} + setAddingBankAccount(true)} + > + {bankAccounts.length === 0 ? ( +

No bank accounts

+ ) : ( + bankAccounts.map((accountItem) => ( + updateBankAccount(id, updates)} + onDelete={(id) => deleteBankAccount(id)} + onEdit={(bankAccount) => setEditingBankAccount(bankAccount)} + /> + )) + )} +
+
+
+ + {/* Modals */} + {editingPerson && ( + ) => { + updatePerson(updates); + setEditingPerson(false); + }} + onCancel={() => setEditingPerson(false)} + /> + )} + + {addingAddress && ( + ) => { + addAddress(address); + setAddingAddress(false); + }} + onCancel={() => setAddingAddress(false)} + /> + )} + + {editingAddress && ( + ) => { + updateAddress(editingAddress.id, address); + setEditingAddress(null); + }} + onCancel={() => setEditingAddress(null)} + /> + )} + + {addingContact && ( + ) => { + addContact(contact); + setAddingContact(false); + }} + onCancel={() => setAddingContact(false)} + /> + )} + + {editingContact && ( + ) => { + updateContact(editingContact.id, contact); + setEditingContact(null); + }} + onCancel={() => setEditingContact(null)} + /> + )} + + {addingBankAccount && ( + ) => { + addBankAccount(account); + setAddingBankAccount(false); + }} + onCancel={() => setAddingBankAccount(false)} + /> + )} + + {editingBankAccount && ( + ) => { + updateBankAccount(editingBankAccount.id, account); + setEditingBankAccount(null); + }} + onCancel={() => setEditingBankAccount(null)} + /> + )} + + {addingEmployment && ( + ) => { + addEmployment(employment); + setAddingEmployment(false); + }} + onCancel={() => setAddingEmployment(false)} + /> + )} + + {editingEmployment && ( + ) => { + updateEmployment(editingEmployment.id, employment); + setEditingEmployment(null); + }} + onCancel={() => setEditingEmployment(null)} + /> + )} + + ); +}; + +// Helper Components + +interface DetailSectionProps { + title: string; + icon: React.ComponentType<{ className?: string }>; + count: number; + children: React.ReactNode; + onAdd?: () => void; +} + +const DetailSection = ({ title, icon: Icon, count, children, onAdd }: DetailSectionProps) => ( +
+
+ +

{title}

+ + {count} + + {onAdd && ( + + )} +
+
{children}
+
+); + +// Removed unused helper components and utilities diff --git a/src/webapp/components/persons/PersonEditModal.tsx b/src/webapp/components/persons/PersonEditModal.tsx new file mode 100644 index 0000000..f02b7ed --- /dev/null +++ b/src/webapp/components/persons/PersonEditModal.tsx @@ -0,0 +1,26 @@ +import type { Person } from '#src/webapp/types/person'; +import { X } from 'lucide-react'; +import { PersonForm } from './PersonForm'; + +interface PersonEditModalProps { + person: Person; + onSave: (updates: Partial) => void; + onCancel: () => void; +} + +export const PersonEditModal = ({ person, onSave, onCancel }: PersonEditModalProps) => ( +
+
+
+

Edit Person

+ +
+ +
+
+); diff --git a/src/webapp/components/persons/PersonForm.tsx b/src/webapp/components/persons/PersonForm.tsx new file mode 100644 index 0000000..d4d0c31 --- /dev/null +++ b/src/webapp/components/persons/PersonForm.tsx @@ -0,0 +1,186 @@ +import { Button } from '#src/webapp/components/ui/button'; +import { GenderEnum, type Person } from '#src/webapp/types/person'; +// oxlint-disable no-magic-numbers +// oxlint-disable no-ternary +import { useForm } from '@tanstack/react-form'; +import { z } from 'zod'; + +const PersonFormSchema = z.object({ + firstName: z.string().min(1, 'First name is required').max(100), + lastName: z.string().min(1, 'Last name is required').max(100), + dateOfBirth: z.string().optional(), + gender: GenderEnum.optional(), +}); + +type PersonFormValues = z.infer; + +interface PersonFormProps { + person?: Person; + onSave: (values: PersonFormValues) => void; + onCancel?: () => void; + isLoading?: boolean; +} + +export const PersonForm = ({ person, onSave, onCancel, isLoading }: PersonFormProps) => { + const formApi = useForm({ + defaultValues: { + firstName: person?.firstName ?? '', + lastName: person?.lastName ?? '', + dateOfBirth: person?.dateOfBirth + ? new Date(person.dateOfBirth).toISOString().split('T')[0] + : '', + gender: person?.gender, + } satisfies PersonFormValues, + validators: { + onChange: (({ value }: { value: PersonFormValues }) => { + const result = PersonFormSchema.safeParse(value); + if (!result.success) { + return result.error; + } + return undefined; + }) as any, + }, + onSubmit: ({ value }: { value: PersonFormValues }) => { + onSave({ + ...value, + dateOfBirth: value.dateOfBirth ? new Date(value.dateOfBirth).toISOString() : undefined, + }); + }, + }); + const FormField = formApi.Field; + + return ( +
{ + event.preventDefault(); + formApi.handleSubmit(); + }} + className="space-y-6" + > +
+ + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ? ( +

{firstError}

+ ) : null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> + {(() => { + const [firstError] = field.state.meta.errors; + return firstError ? ( +

{firstError}

+ ) : null; + })()} +
+ )} +
+
+ + + {(field: any) => ( +
+ + field.handleChange(event.target.value)} + onBlur={field.handleBlur} + /> +

Optional. Your date of birth.

+ {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ + + {(field: any) => ( +
+ + + +

Optional. How you identify.

+ {(() => { + const [firstError] = field.state.meta.errors; + return firstError ?

{firstError}

: null; + })()} +
+ )} +
+ +
+ + {onCancel && ( + + )} +
+
+ ); +}; diff --git a/src/webapp/components/persons/PersonsTable.tsx b/src/webapp/components/persons/PersonsTable.tsx new file mode 100644 index 0000000..f204391 --- /dev/null +++ b/src/webapp/components/persons/PersonsTable.tsx @@ -0,0 +1,161 @@ +// oxlint-disable no-ternary +// oxlint-disable no-magic-numbers +import { + createColumnHelper, + flexRender, + getCoreRowModel, + getSortedRowModel, + type SortingState, + useReactTable, +} from '@tanstack/react-table'; +import { ChevronDown, ChevronUp } from 'lucide-react'; +import { useState } from 'react'; + +export interface PersonTableRow { + id: string; + firstName: string; + lastName: string; + gender?: string; + dateOfBirth?: string; +} + +interface PersonsTableProps { + data: PersonTableRow[]; + loading?: boolean; + selectedId?: string; + onRowSelect?: (person: PersonTableRow) => void; +} + +const columnHelper = createColumnHelper(); + +const formatDate = (dateString?: string) => { + if (!dateString) { + return '-'; + } + const date = new Date(dateString); + return date.toLocaleDateString(); +}; + +const formatGender = (gender?: string) => { + if (!gender) { + return '-'; + } + return gender.charAt(0).toUpperCase() + gender.slice(1).replace(/_/g, ' '); +}; + +const columns = [ + columnHelper.accessor('firstName', { + header: 'First Name', + cell: (info) => info.getValue(), + }), + columnHelper.accessor('lastName', { + header: 'Last Name', + cell: (info) => info.getValue(), + }), + columnHelper.accessor('gender', { + header: 'Gender', + cell: (info) => formatGender(info.getValue()), + }), + columnHelper.accessor('dateOfBirth', { + header: 'Birth Date', + cell: (info) => formatDate(info.getValue()), + }), +]; + +const getRowClassName = (isSelected: boolean) => { + const base = 'border-b border-white/10 cursor-pointer transition-colors'; + if (isSelected) { + return `${base} bg-cyan-600/30 hover:bg-cyan-600/40`; + } + return `${base} hover:bg-white/10`; +}; + +export const PersonsTable = ({ data, loading, selectedId, onRowSelect }: PersonsTableProps) => { + const [sorting, setSorting] = useState([]); + + const table = useReactTable({ + data, + columns, + state: { + sorting, + }, + onSortingChange: setSorting, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + }); + + if (loading) { + return ( +
+
+
Loading persons...
+
+
+ ); + } + + const hasNoData = data.length === 0; + if (hasNoData) { + return ( +
+

No persons found

+

Try adjusting your search or add some persons.

+
+ ); + } + + const personLabel = data.length === 1 ? 'person' : 'persons'; + + return ( +
+
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + ))} + + ))} + + + {table.getRowModel().rows.map((row) => { + const isSelected = selectedId === row.original.id; + return ( + onRowSelect?.(row.original)} + className={getRowClassName(isSelected)} + > + {row.getVisibleCells().map((cell) => ( + + ))} + + ); + })} + +
+
+ {header.isPlaceholder + ? null + : flexRender(header.column.columnDef.header, header.getContext())} + {{ + asc: , + desc: , + }[header.column.getIsSorted() as string] ?? null} +
+
+ {flexRender(cell.column.columnDef.cell, cell.getContext())} +
+
+
+ {data.length} {personLabel} +
+
+ ); +}; diff --git a/src/webapp/components/ui/badge.tsx b/src/webapp/components/ui/badge.tsx new file mode 100644 index 0000000..0a0c5fd --- /dev/null +++ b/src/webapp/components/ui/badge.tsx @@ -0,0 +1,35 @@ +import { cn } from '#src/webapp/lib/utils'; +import { cva, type VariantProps } from 'class-variance-authority'; +// oxlint-disable react/jsx-props-no-spreading +import * as React from 'react'; + +const badgeVariants = cva( + 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2', + { + variants: { + variant: { + default: 'border-transparent bg-primary text-primary-foreground', + secondary: 'border-transparent bg-secondary text-secondary-foreground', + destructive: 'border-transparent bg-destructive text-destructive-foreground', + outline: 'text-foreground', + }, + }, + defaultVariants: { + variant: 'default', + }, + }, +); + +interface BadgeProps + extends React.HTMLAttributes, VariantProps {} + +const Badge = ({ className, variant, ...props }: BadgeProps) => ( +
+); + +export { Badge, }; diff --git a/src/webapp/components/ui/button.tsx b/src/webapp/components/ui/button.tsx new file mode 100644 index 0000000..3d135ce --- /dev/null +++ b/src/webapp/components/ui/button.tsx @@ -0,0 +1,59 @@ +import { cn } from '#src/webapp/lib/utils'; +import { Slot } from '@radix-ui/react-slot'; +import { cva, type VariantProps } from 'class-variance-authority'; +import * as React from 'react'; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + { + variants: { + variant: { + default: 'bg-primary text-primary-foreground hover:bg-primary/90', + destructive: + 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', + outline: + 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50', + secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50', + link: 'text-primary underline-offset-4 hover:underline', + }, + size: { + default: 'h-9 px-4 py-2 has-[>svg]:px-3', + sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5', + lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', + icon: 'size-9', + 'icon-sm': 'size-8', + 'icon-lg': 'size-10', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + }, +); + +function Button({ + className, + variant = 'default', + size = 'default', + asChild = false, + ...props +}: React.ComponentProps<'button'> & + VariantProps & { + asChild?: boolean; + }) { + const Comp = asChild ? Slot : 'button'; + + return ( + + ); +} + +export { Button, }; diff --git a/src/webapp/data/example-guitars.ts b/src/webapp/data/example-guitars.ts index 4d3183f..3731a38 100644 --- a/src/webapp/data/example-guitars.ts +++ b/src/webapp/data/example-guitars.ts @@ -1,5 +1,5 @@ // oxlint-disable sort-keys -export interface Guitar { +interface Guitar { id: number; name: string; image: string; diff --git a/src/webapp/data/fake-persons.ts b/src/webapp/data/fake-persons.ts new file mode 100644 index 0000000..949a5ae --- /dev/null +++ b/src/webapp/data/fake-persons.ts @@ -0,0 +1,287 @@ +// oxlint-disable func-style +import { faker } from '@faker-js/faker'; +import type { + AccountType, + Address, + AddressType, + BankAccount, + ContactInfo, + ContactType, + Employment, + Gender, + Person, + PersonWithRelations, +} from '#src/webapp/types/person.ts'; + +// ============================================================================= +// Seed for reproducible data +// ============================================================================= + +const SEED = 12345; + +/** + * Initialize faker with a seed for reproducible data + */ +export function initFaker(seed: number = SEED) { + faker.seed(seed); +} + +// ============================================================================= +// Individual Entity Generators +// ============================================================================= + +/** + * Generate a fake person + */ +function generatePerson(overrides?: Partial): Person { + const now = new Date().toISOString(); + const gender = faker.helpers.arrayElement([ + 'male', + 'female', + 'other', + 'prefer_not_to_say', + ]); + + return { + id: faker.string.uuid(), + firstName: faker.person.firstName( + // oxlint-disable-next-line no-nested-ternary + gender === 'male' ? 'male' : gender === 'female' ? 'female' : undefined, + ), + lastName: faker.person.lastName(), + dateOfBirth: faker.date.birthdate({ min: 18, max: 80, mode: 'age' }).toISOString(), + gender, + createdAt: now, + updatedAt: now, + ...overrides, + }; +} + +/** + * Generate a fake address for a person + */ +function generateAddress(personId: string, overrides?: Partial
): Address { + const addressTypes: AddressType[] = ['home', 'work', 'billing', 'shipping']; + + return { + id: faker.string.uuid(), + personId, + type: faker.helpers.arrayElement(addressTypes), + street: faker.location.streetAddress(), + city: faker.location.city(), + state: faker.location.state(), + postalCode: faker.location.zipCode(), + country: faker.location.country(), + isPrimary: false, + ...overrides, + }; +} + +/** + * Generate a fake bank account for a person + */ +function generateBankAccount( + personId: string, + overrides?: Partial, +): BankAccount { + const accountTypes: AccountType[] = ['checking', 'savings', 'investment']; + + return { + id: faker.string.uuid(), + personId, + bankName: faker.company.name() + ' Bank', + accountType: faker.helpers.arrayElement(accountTypes), + accountNumberLast4: faker.finance.accountNumber(4), + iban: faker.finance.iban(), + bic: faker.finance.bic(), + isPrimary: false, + ...overrides, + }; +} + +/** + * Generate a fake contact info for a person + */ +function generateContactInfo( + personId: string, + type?: ContactType, + overrides?: Partial, +): ContactInfo { + const contactTypes: ContactType[] = ['email', 'phone', 'mobile', 'linkedin', 'twitter']; + const selectedType = type ?? faker.helpers.arrayElement(contactTypes); + + let value: string; + switch (selectedType) { + case 'email': + value = faker.internet.email(); + break; + case 'phone': + case 'mobile': + value = faker.phone.number(); + break; + case 'linkedin': + value = `linkedin.com/in/${faker.internet.username()}`; + break; + case 'twitter': + value = `@${faker.internet.username()}`; + break; + default: + value = faker.internet.email(); + } + + return { + id: faker.string.uuid(), + personId, + type: selectedType, + value, + isPrimary: false, + isVerified: faker.datatype.boolean({ probability: 0.7 }), + ...overrides, + }; +} + +/** + * Generate a fake employment record for a person + */ +function generateEmployment( + personId: string, + isCurrent: boolean = false, + overrides?: Partial, +): Employment { + const startDate = faker.date.past({ years: isCurrent ? 5 : 15 }); + const endDate = isCurrent ? null : faker.date.between({ from: startDate, to: new Date() }); + + return { + id: faker.string.uuid(), + personId, + companyName: faker.company.name(), + position: faker.person.jobTitle(), + department: faker.commerce.department(), + startDate: startDate.toISOString(), + endDate: endDate?.toISOString() ?? null, + isCurrent, + salary: faker.number.int({ min: 30000, max: 250000 }), + currency: faker.helpers.arrayElement(['USD', 'EUR', 'GBP']), + ...overrides, + }; +} + +// ============================================================================= +// Person with Relations Generator +// ============================================================================= + +interface GeneratePersonOptions { + addressCount?: { min: number; max: number }; + bankAccountCount?: { min: number; max: number }; + contactCount?: { min: number; max: number }; + employmentCount?: { min: number; max: number }; +} + +const defaultOptions: Required = { + addressCount: { min: 1, max: 3 }, + bankAccountCount: { min: 1, max: 2 }, + contactCount: { min: 2, max: 5 }, + employmentCount: { min: 1, max: 4 }, +}; + +/** + * Generate a person with all related entities + */ +function generatePersonWithRelations(options?: GeneratePersonOptions): PersonWithRelations { + const opts = { ...defaultOptions, ...options }; + const person = generatePerson(); + + // Generate addresses + const addressCount = faker.number.int(opts.addressCount); + const addresses: Address[] = []; + for (let i = 0; i < addressCount; i++) { + addresses.push(generateAddress(person.id, { isPrimary: i === 0 })); + } + + // Generate bank accounts + const bankAccountCount = faker.number.int(opts.bankAccountCount); + const bankAccounts: BankAccount[] = []; + for (let i = 0; i < bankAccountCount; i++) { + bankAccounts.push(generateBankAccount(person.id, { isPrimary: i === 0 })); + } + + // Generate contacts - always include at least one email + const contactCount = faker.number.int(opts.contactCount); + const contacts: ContactInfo[] = [generateContactInfo(person.id, 'email', { isPrimary: true })]; + for (let i = 1; i < contactCount; i++) { + contacts.push(generateContactInfo(person.id)); + } + + // Generate employments - at least one current + const employmentCount = faker.number.int(opts.employmentCount); + const employments: Employment[] = [ + generateEmployment(person.id, true), // Current job + ]; + for (let i = 1; i < employmentCount; i++) { + employments.push(generateEmployment(person.id, false)); // Past jobs + } + + return { + ...person, + addresses, + bankAccounts, + contacts, + employments, + }; +} + +// ============================================================================= +// Batch Generation +// ============================================================================= + +/** + * Generate multiple persons with relations + */ +export function generatePersons( + count: number, + options?: GeneratePersonOptions, +): PersonWithRelations[] { + initFaker(); // Reset seed for reproducibility + const persons: PersonWithRelations[] = []; + + for (let i = 0; i < count; i++) { + persons.push(generatePersonWithRelations(options)); + } + + return persons; +} + +// ============================================================================= +// Utility Functions +// ============================================================================= + +/** + * Get primary email from contacts + */ +function getPrimaryEmail(contacts: ContactInfo[]): string | undefined { + const primary = contacts.find((c) => c.type === 'email' && c.isPrimary); + return primary?.value ?? contacts.find((c) => c.type === 'email')?.value; +} + +/** + * Get primary address city + */ +function getPrimaryCity(addresses: Address[]): string | undefined { + const primary = addresses.find((a) => a.isPrimary); + return primary?.city ?? addresses[0]?.city; +} + +/** + * Get current employer + */ +function getCurrentEmployer(employments: Employment[]): string | undefined { + const current = employments.find((e) => e.isCurrent); + return current?.companyName; +} + +/** + * Get full name + */ +function getFullName(person: Person): string { + return `${person.firstName} ${person.lastName}`; +} diff --git a/src/webapp/db-collections/persons.ts b/src/webapp/db-collections/persons.ts new file mode 100644 index 0000000..0c6b580 --- /dev/null +++ b/src/webapp/db-collections/persons.ts @@ -0,0 +1,306 @@ +import * as electrodbClient from '#src/webapp/integrations/electrodb/personsClient'; +import { getContext } from '#src/webapp/integrations/tanstack-query/root-provider'; +import { + type Address, + AddressSchema, + type BankAccount, + BankAccountSchema, + type ContactInfo, + ContactInfoSchema, + type Employment, + EmploymentSchema, + type Person, + PersonSchema, +} from '#src/webapp/types/person'; +import { queryCollectionOptions } from '@tanstack/query-db-collection'; +import { createCollection } from '@tanstack/react-db'; +import { createServerFn } from '@tanstack/react-start'; + +// ============================================================================= +// Server Functions +// ============================================================================= + +/** + * Get all persons (profile only) + */ +const fetchPersons = createServerFn({ method: 'GET' }).handler(async () => + electrodbClient.getAllPersons(), +); + +/** + * Create a new person + */ +const createPersonFn = createServerFn({ method: 'POST' }) + .inputValidator((input: Person) => PersonSchema.parse(input)) + .handler(async ({ data }) => electrodbClient.createPerson(data)); + +/** + * Update a person + */ +const updatePersonFn = createServerFn({ method: 'POST' }) + .inputValidator((input: { personId: string; updates: Partial }) => input) + .handler(async ({ data }) => electrodbClient.updatePerson(data.personId, data.updates)); + +/** + * Delete a person + */ +const deletePersonFn = createServerFn({ method: 'POST' }) + .inputValidator((input: string) => input) + .handler(async ({ data: personId }) => electrodbClient.deletePerson(personId)); + +// --- Address Server Functions --- + +const fetchAddresses = createServerFn({ method: 'GET' }) + .inputValidator((input: string) => input) + .handler(async ({ data: personId }) => electrodbClient.getAddressesByPersonId(personId)); + +const createAddressFn = createServerFn({ method: 'POST' }) + .inputValidator((input: Address) => AddressSchema.parse(input)) + .handler(async ({ data }) => electrodbClient.createAddress(data)); + +const updateAddressFn = createServerFn({ method: 'POST' }) + .inputValidator((input: Address) => AddressSchema.parse(input)) + .handler(async ({ data }) => electrodbClient.updateAddress(data)); + +const deleteAddressFn = createServerFn({ method: 'POST' }) + .inputValidator((input: { personId: string; addressId: string }) => input) + .handler(async ({ data }) => electrodbClient.deleteAddress(data.personId, data.addressId)); + +// --- BankAccount Server Functions --- + +const fetchBankAccounts = createServerFn({ method: 'GET' }) + .inputValidator((input: string) => input) + .handler(async ({ data: personId }) => electrodbClient.getBankAccountsByPersonId(personId)); + +const createBankAccountFn = createServerFn({ method: 'POST' }) + .inputValidator((input: BankAccount) => BankAccountSchema.parse(input)) + .handler(async ({ data }) => electrodbClient.createBankAccount(data)); + +const updateBankAccountFn = createServerFn({ method: 'POST' }) + .inputValidator((input: BankAccount) => BankAccountSchema.parse(input)) + .handler(async ({ data }) => electrodbClient.updateBankAccount(data)); + +const deleteBankAccountFn = createServerFn({ method: 'POST' }) + .inputValidator((input: { personId: string; bankId: string }) => input) + .handler(async ({ data }) => electrodbClient.deleteBankAccount(data.personId, data.bankId)); + +// --- ContactInfo Server Functions --- + +const fetchContacts = createServerFn({ method: 'GET' }) + .inputValidator((input: string) => input) + .handler(async ({ data: personId }) => electrodbClient.getContactsByPersonId(personId)); + +const createContactFn = createServerFn({ method: 'POST' }) + .inputValidator((input: ContactInfo) => ContactInfoSchema.parse(input)) + .handler(async ({ data }) => electrodbClient.createContact(data)); + +const updateContactFn = createServerFn({ method: 'POST' }) + .inputValidator((input: ContactInfo) => ContactInfoSchema.parse(input)) + .handler(async ({ data }) => electrodbClient.updateContact(data)); + +const deleteContactFn = createServerFn({ method: 'POST' }) + .inputValidator((input: { personId: string; contactId: string }) => input) + .handler(async ({ data }) => electrodbClient.deleteContact(data.personId, data.contactId)); + +// --- Employment Server Functions --- + +const fetchEmployments = createServerFn({ method: 'GET' }) + .inputValidator((input: string) => input) + .handler(async ({ data: personId }) => electrodbClient.getEmploymentsByPersonId(personId)); + +const createEmploymentFn = createServerFn({ method: 'POST' }) + .inputValidator((input: Employment) => EmploymentSchema.parse(input)) + .handler(async ({ data }) => electrodbClient.createEmployment(data)); + +const updateEmploymentFn = createServerFn({ method: 'POST' }) + .inputValidator((input: Employment) => EmploymentSchema.parse(input)) + .handler(async ({ data }) => electrodbClient.updateEmployment(data)); + +const deleteEmploymentFn = createServerFn({ method: 'POST' }) + .inputValidator((input: { personId: string; employmentId: string }) => input) + .handler(async ({ data }) => electrodbClient.deleteEmployment(data.personId, data.employmentId)); + +// ============================================================================= +// TanStack DB Collections +// ============================================================================= + +/** + * Persons Collection - Main collection for person profiles + */ +export const personsCollection = createCollection( + queryCollectionOptions({ + queryKey: ['persons'], + queryFn: () => fetchPersons(), + queryClient: getContext().queryClient, + getKey: (item) => item.id, + onInsert: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + createPersonFn({ data: mutation.modified as Person }), + ), + ); + }, + onUpdate: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + updatePersonFn({ + data: { + personId: mutation.key as string, + updates: mutation.changes as Partial, + }, + }), + ), + ); + }, + onDelete: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => deletePersonFn({ data: mutation.key as string })), + ); + }, + }), +); + +/** + * Create a collection for addresses of a specific person + * This is a factory function since we need personId context + */ +export const createAddressesCollection = (personId: string) => + createCollection( + queryCollectionOptions
({ + queryKey: ['persons', personId, 'addresses'], + queryFn: () => fetchAddresses({ data: personId }), + queryClient: getContext().queryClient, + getKey: (item) => item.id, + onInsert: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + createAddressFn({ data: mutation.modified as Address }), + ), + ); + }, + onUpdate: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + updateAddressFn({ data: mutation.modified as Address }), + ), + ); + }, + onDelete: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + deleteAddressFn({ + data: { personId, addressId: mutation.key as string }, + }), + ), + ); + }, + }), + ); + +/** + * Create a collection for bank accounts of a specific person + */ +export const createBankAccountsCollection = (personId: string) => + createCollection( + queryCollectionOptions({ + queryKey: ['persons', personId, 'bankAccounts'], + queryFn: () => fetchBankAccounts({ data: personId }), + queryClient: getContext().queryClient, + getKey: (item) => item.id, + onInsert: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + createBankAccountFn({ data: mutation.modified as BankAccount }), + ), + ); + }, + onUpdate: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + updateBankAccountFn({ data: mutation.modified as BankAccount }), + ), + ); + }, + onDelete: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + deleteBankAccountFn({ + data: { personId, bankId: mutation.key as string }, + }), + ), + ); + }, + }), + ); + +/** + * Create a collection for contacts of a specific person + */ +export const createContactsCollection = (personId: string) => + createCollection( + queryCollectionOptions({ + queryKey: ['persons', personId, 'contacts'], + queryFn: () => fetchContacts({ data: personId }), + queryClient: getContext().queryClient, + getKey: (item) => item.id, + onInsert: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + createContactFn({ data: mutation.modified as ContactInfo }), + ), + ); + }, + onUpdate: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + updateContactFn({ data: mutation.modified as ContactInfo }), + ), + ); + }, + onDelete: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + deleteContactFn({ + data: { personId, contactId: mutation.key as string }, + }), + ), + ); + }, + }), + ); + +/** + * Create a collection for employments of a specific person + */ +export const createEmploymentsCollection = (personId: string) => + createCollection( + queryCollectionOptions({ + queryKey: ['persons', personId, 'employments'], + queryFn: () => fetchEmployments({ data: personId }), + queryClient: getContext().queryClient, + getKey: (item) => item.id, + onInsert: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + createEmploymentFn({ data: mutation.modified as Employment }), + ), + ); + }, + onUpdate: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + updateEmploymentFn({ data: mutation.modified as Employment }), + ), + ); + }, + onDelete: async ({ transaction }) => { + await Promise.all( + transaction.mutations.map((mutation) => + deleteEmploymentFn({ + data: { personId, employmentId: mutation.key as string }, + }), + ), + ); + }, + }), + ); diff --git a/src/webapp/db-collections/todos.ts b/src/webapp/db-collections/todos.ts index 807fbfe..f31f55e 100644 --- a/src/webapp/db-collections/todos.ts +++ b/src/webapp/db-collections/todos.ts @@ -1,6 +1,6 @@ import { queryCollectionOptions } from '@tanstack/query-db-collection'; import { createCollection } from '@tanstack/react-db'; -import { getContext } from '@/webapp/integrations/tanstack-query/root-provider'; +import { getContext } from '#src/webapp/integrations/tanstack-query/root-provider'; import { type Todo, todoSchema } from '../types/todo'; // const todoApiPath = '/demo/api/tq-todos'; diff --git a/src/webapp/hooks/useDbPersons.ts b/src/webapp/hooks/useDbPersons.ts new file mode 100644 index 0000000..d99b07b --- /dev/null +++ b/src/webapp/hooks/useDbPersons.ts @@ -0,0 +1,254 @@ +import type { + Address, + BankAccount, + ContactInfo, + Employment, + Person, +} from '#src/webapp/types/person'; +import { + createAddressesCollection, + createBankAccountsCollection, + createContactsCollection, + createEmploymentsCollection, + personsCollection, +} from '#src/webapp/db-collections/persons'; +// oxlint-disable no-magic-numbers +// oxlint-disable func-style +import { useLiveQuery } from '@tanstack/react-db'; +import { useMemo } from 'react'; + +// ============================================================================= +// Persons List Hook +// ============================================================================= + +/** + * Hook for accessing and mutating the persons collection + */ +export function usePersons() { + // Live query for all persons + const query = useLiveQuery(personsCollection); + + // Mutation functions (React Compiler handles memoization) + const addPerson = (person: Person) => { + personsCollection.insert(person); + }; + + const updatePerson = (id: string, changes: Partial) => { + personsCollection.update(id, (draft) => { + Object.assign(draft, changes, { updatedAt: new Date().toISOString() }); + }); + }; + + const deletePerson = (id: string) => { + personsCollection.delete(id); + }; + + return { + persons: query.data ?? [], + isLoading: query.isLoading, + isError: query.isError, + addPerson, + updatePerson, + deletePerson, + }; +} + +// ============================================================================= +// Person Detail Hooks (for related entities) +// ============================================================================= + +/** + * Hook for accessing addresses of a specific person + */ +function usePersonAddresses(personId: string) { + const collection = useMemo(() => createAddressesCollection(personId), [personId]); + + const query = useLiveQuery(collection); + + const addAddress = (address: Omit) => { + const newAddress: Address = { + ...address, + id: crypto.randomUUID(), + personId, + }; + collection.insert(newAddress); + }; + + const updateAddress = (addressId: string, changes: Partial
) => { + collection.update(addressId, (draft) => { + Object.assign(draft, changes); + }); + }; + + const deleteAddress = (addressId: string) => { + collection.delete(addressId); + }; + + return { + addresses: query.data ?? [], + isLoading: query.isLoading, + isError: query.isError, + addAddress, + updateAddress, + deleteAddress, + }; +} + +/** + * Hook for accessing bank accounts of a specific person + */ +function usePersonBankAccounts(personId: string) { + const collection = useMemo(() => createBankAccountsCollection(personId), [personId]); + + const query = useLiveQuery(collection); + + const addBankAccount = (account: Omit) => { + const newAccount: BankAccount = { + ...account, + id: crypto.randomUUID(), + personId, + }; + collection.insert(newAccount); + }; + + const updateBankAccount = (accountId: string, changes: Partial) => { + collection.update(accountId, (draft) => { + Object.assign(draft, changes); + }); + }; + + const deleteBankAccount = (accountId: string) => { + collection.delete(accountId); + }; + + return { + bankAccounts: query.data ?? [], + isLoading: query.isLoading, + error: query.error, + addBankAccount, + updateBankAccount, + deleteBankAccount, + }; +} + +/** + * Hook for accessing contacts of a specific person + */ +function usePersonContacts(personId: string) { + const collection = useMemo(() => createContactsCollection(personId), [personId]); + + const query = useLiveQuery(collection); + + const addContact = (contact: Omit) => { + const newContact: ContactInfo = { + ...contact, + id: crypto.randomUUID(), + personId, + }; + collection.insert(newContact); + }; + + const updateContact = (contactId: string, changes: Partial) => { + collection.update(contactId, (draft) => { + Object.assign(draft, changes); + }); + }; + + const deleteContact = (contactId: string) => { + collection.delete(contactId); + }; + + return { + contacts: query.data ?? [], + isLoading: query.isLoading, + isError: query.isError, + addContact, + updateContact, + deleteContact, + }; +} + +/** + * Hook for accessing employments of a specific person + */ +function usePersonEmployments(personId: string) { + const collection = useMemo(() => createEmploymentsCollection(personId), [personId]); + + const query = useLiveQuery(collection); + + const addEmployment = (employment: Omit) => { + const newEmployment: Employment = { + ...employment, + id: crypto.randomUUID(), + personId, + }; + collection.insert(newEmployment); + }; + + const updateEmployment = (employmentId: string, changes: Partial) => { + collection.update(employmentId, (draft) => { + Object.assign(draft, changes); + }); + }; + + const deleteEmployment = (employmentId: string) => { + collection.delete(employmentId); + }; + + return { + employments: query.data ?? [], + isLoading: query.isLoading, + isError: query.isError, + addEmployment, + updateEmployment, + deleteEmployment, + }; +} + +// ============================================================================= +// Combined Person Detail Hook +// ============================================================================= + +/** + * Hook for accessing a person with all related entities + */ +export function usePersonDetail(personId: string) { + const { persons, updatePerson, deletePerson } = usePersons(); + const person = useMemo(() => persons.find((p) => p.id === personId), [persons, personId]); + + const addresses = usePersonAddresses(personId); + const bankAccounts = usePersonBankAccounts(personId); + const contacts = usePersonContacts(personId); + const employments = usePersonEmployments(personId); + + const isLoading = + addresses.isLoading || bankAccounts.isLoading || contacts.isLoading || employments.isLoading; + + return { + person, + addresses: addresses.addresses, + bankAccounts: bankAccounts.bankAccounts, + contacts: contacts.contacts, + employments: employments.employments, + isLoading, + // Person mutations + updatePerson: (changes: Partial) => updatePerson(personId, changes), + deletePerson: () => deletePerson(personId), + // Address mutations + addAddress: addresses.addAddress, + updateAddress: addresses.updateAddress, + deleteAddress: addresses.deleteAddress, + // Bank account mutations + addBankAccount: bankAccounts.addBankAccount, + updateBankAccount: bankAccounts.updateBankAccount, + deleteBankAccount: bankAccounts.deleteBankAccount, + // Contact mutations + addContact: contacts.addContact, + updateContact: contacts.updateContact, + deleteContact: contacts.deleteContact, + // Employment mutations + addEmployment: employments.addEmployment, + updateEmployment: employments.updateEmployment, + deleteEmployment: employments.deleteEmployment, + }; +} diff --git a/src/webapp/hooks/useDbTodos.ts b/src/webapp/hooks/useDbTodos.ts index 3de2590..2043194 100644 --- a/src/webapp/hooks/useDbTodos.ts +++ b/src/webapp/hooks/useDbTodos.ts @@ -1,6 +1,6 @@ import { useLiveQuery } from '@tanstack/react-db'; // oxlint-disable func-style -import { todosCollection } from '@/webapp/db-collections/todos'; +import { todosCollection } from '#src/webapp/db-collections/todos'; import type { Todo } from '../types/todo'; export function useTodo() { diff --git a/src/webapp/integrations/ddb-client/ddbClient.ts b/src/webapp/integrations/ddb-client/ddbClient.ts index bf209ef..c100afa 100644 --- a/src/webapp/integrations/ddb-client/ddbClient.ts +++ b/src/webapp/integrations/ddb-client/ddbClient.ts @@ -6,7 +6,7 @@ import { QueryCommand, UpdateCommand, } from '@aws-sdk/lib-dynamodb'; -import { type Todo, todoSchema, type TodoUpdate } from '@/webapp/types/todo'; +import { type Todo, todoSchema, type TodoUpdate } from '#src/webapp/types/todo.ts'; const TODOS_PK = 'TODO'; const TODOS_TABLE_ENV = 'DDB_TODOS_TABLE_NAME'; @@ -30,7 +30,7 @@ export const getDdbDocClient = (): DynamoDBDocumentClient => { return ddbDocSingleton; }; -export const requireEnvVar = (name: string): string => { +const requireEnvVar = (name: string): string => { const value = process.env[name]; if (!value) { throw new Error(`Missing env var: ${name}`); @@ -39,7 +39,7 @@ export const requireEnvVar = (name: string): string => { return value; }; -export const getTodosTableName = (): string => requireEnvVar(TODOS_TABLE_ENV); +const getTodosTableName = (): string => requireEnvVar(TODOS_TABLE_ENV); const todoSortKey = (id: number): string => `TODO#${id}`; @@ -65,7 +65,7 @@ const chunkItems = (items: Item[], chunkSize: number): Item[][] => { return out; }; -export type TodosDdbClient = { +type TodosDdbClient = { getTodos: () => Promise; putTodo: (todo: Todo) => Promise; updateTodos: (updates: TodoUpdate[]) => Promise; diff --git a/src/webapp/integrations/electrodb/entities.ts b/src/webapp/integrations/electrodb/entities.ts new file mode 100644 index 0000000..b610b0b --- /dev/null +++ b/src/webapp/integrations/electrodb/entities.ts @@ -0,0 +1,179 @@ +import { getDdbDocClient } from '#src/webapp/integrations/ddb-client/ddbClient.ts'; +import { zodToElectroDBAttributes } from '#src/webapp/integrations/electrodb/zod-to-electrodb.ts'; +import { + AddressSchema, + BankAccountSchema, + ContactInfoSchema, + EmploymentSchema, + PersonSchema, +} from '#src/webapp/types/person.ts'; +import { Entity, type EntityConfiguration, Service } from 'electrodb'; + +// ============================================================================= +// Table Configuration +// ============================================================================= + +const TABLE_NAME = process.env.DDB_PERSONS_TABLE_NAME ?? 'TanstackAwsStack-db-persons'; + +const getEntityConfig = (): EntityConfiguration => ({ + client: getDdbDocClient(), + table: TABLE_NAME, +}); + +// ============================================================================= +// Derived ElectroDB Attributes from Zod Schemas (Single Source of Truth) +// ============================================================================= + +const personAttributes = zodToElectroDBAttributes(PersonSchema); +const addressAttributes = zodToElectroDBAttributes(AddressSchema); +const bankAccountAttributes = zodToElectroDBAttributes(BankAccountSchema); +const contactInfoAttributes = zodToElectroDBAttributes(ContactInfoSchema); +const employmentAttributes = zodToElectroDBAttributes(EmploymentSchema); + +// ============================================================================= +// Person Entity +// ============================================================================= + +export const PersonEntity = new Entity( + { + model: { + entity: 'Person', + version: '1', + service: 'persons', + }, + attributes: personAttributes, + indexes: { + primary: { + pk: { field: 'pk', composite: ['id'] }, + sk: { field: 'sk', composite: [] }, + }, + // GSI1: List all persons + allPersons: { + index: 'GSI1', + pk: { field: 'gsi1pk', composite: [], template: 'PERSONS' }, + sk: { field: 'gsi1sk', composite: ['lastName', 'firstName', 'id'] }, + }, + }, + }, + getEntityConfig(), +); + +// ============================================================================= +// Address Entity +// ============================================================================= + +export const AddressEntity = new Entity( + { + model: { + entity: 'Address', + version: '1', + service: 'persons', + }, + attributes: addressAttributes, + indexes: { + primary: { + pk: { field: 'pk', composite: ['personId'] }, + sk: { field: 'sk', composite: ['id'] }, + }, + }, + }, + getEntityConfig(), +); + +// ============================================================================= +// BankAccount Entity +// ============================================================================= + +export const BankAccountEntity = new Entity( + { + model: { + entity: 'BankAccount', + version: '1', + service: 'persons', + }, + attributes: bankAccountAttributes, + indexes: { + primary: { + pk: { field: 'pk', composite: ['personId'] }, + sk: { field: 'sk', composite: ['id'] }, + }, + }, + }, + getEntityConfig(), +); + +// ============================================================================= +// ContactInfo Entity +// ============================================================================= + +export const ContactInfoEntity = new Entity( + { + model: { + entity: 'ContactInfo', + version: '1', + service: 'persons', + }, + attributes: contactInfoAttributes, + indexes: { + primary: { + pk: { field: 'pk', composite: ['personId'] }, + sk: { field: 'sk', composite: ['id'] }, + }, + }, + }, + getEntityConfig(), +); + +// ============================================================================= +// Employment Entity +// ============================================================================= + +export const EmploymentEntity = new Entity( + { + model: { + entity: 'Employment', + version: '1', + service: 'persons', + }, + attributes: employmentAttributes, + indexes: { + primary: { + pk: { field: 'pk', composite: ['personId'] }, + sk: { field: 'sk', composite: ['id'] }, + }, + }, + }, + getEntityConfig(), +); + +// ============================================================================= +// Persons Service - Collection Queries +// ============================================================================= + +const PersonsService = new Service( + { + person: PersonEntity, + address: AddressEntity, + bankAccount: BankAccountEntity, + contactInfo: ContactInfoEntity, + employment: EmploymentEntity, + }, + getEntityConfig(), +); + +// ============================================================================= +// Type Exports +// ============================================================================= + +type PersonEntityType = typeof PersonEntity; +type AddressEntityType = typeof AddressEntity; +type BankAccountEntityType = typeof BankAccountEntity; +type ContactInfoEntityType = typeof ContactInfoEntity; +type EmploymentEntityType = typeof EmploymentEntity; + +// ElectroDB inferred types +type PersonItem = ReturnType; +type AddressItem = ReturnType; +type BankAccountItem = ReturnType; +type ContactInfoItem = ReturnType; +type EmploymentItem = ReturnType; diff --git a/src/webapp/integrations/electrodb/personsClient.ts b/src/webapp/integrations/electrodb/personsClient.ts new file mode 100644 index 0000000..ce48d1f --- /dev/null +++ b/src/webapp/integrations/electrodb/personsClient.ts @@ -0,0 +1,185 @@ +/** + * ElectroDB-based Persons Client + * + * Uses ElectroDB entities for type-safe DynamoDB operations. + */ + +import type { + Address, + BankAccount, + ContactInfo, + Employment, + Person, +} from '#src/webapp/types/person.ts'; +import { + AddressEntity, + BankAccountEntity, + ContactInfoEntity, + EmploymentEntity, + PersonEntity, +} from '#src/webapp/integrations/electrodb/entities.ts'; + +// ============================================================================= +// Types for All Data Response +// ============================================================================= + +// Note: AllEntitiesData types are removed as GSI2 (used for Orama search) is postponed. +// These will be added back when search functionality is implemented. + +// ============================================================================= +// Person Operations +// ============================================================================= + +/** + * Get all persons using GSI1 + */ +export const getAllPersons = async (): Promise => { + const result = await PersonEntity.query.allPersons({}).go(); + return result.data.map((item) => ({ + id: item.id, + firstName: item.firstName, + lastName: item.lastName, + dateOfBirth: item.dateOfBirth, + gender: item.gender, + createdAt: item.createdAt, + updatedAt: item.updatedAt, + })); +}; + +/** + * Create a new person + */ +export const createPerson = async (person: Person): Promise => { + const result = await PersonEntity.put(person).go(); + return result.data as Person; +}; + +/** + * Update a person + */ +export const updatePerson = async (personId: string, updates: Partial): Promise => { + const result = await PersonEntity.patch({ id: personId }) + .set(updates) + .go({ response: 'all_new' }); + return result.data as Person; +}; + +/** + * Delete a person and all related entities + */ +export const deletePerson = async (personId: string): Promise => { + // Delete all related entities first + const [addresses, bankAccounts, contacts, employments] = await Promise.all([ + AddressEntity.query.primary({ personId }).go(), + BankAccountEntity.query.primary({ personId }).go(), + ContactInfoEntity.query.primary({ personId }).go(), + EmploymentEntity.query.primary({ personId }).go(), + ]); + + // Delete all related items + await Promise.all([ + ...addresses.data.map((addr) => AddressEntity.delete({ personId, id: addr.id }).go()), + ...bankAccounts.data.map((bank) => BankAccountEntity.delete({ personId, id: bank.id }).go()), + ...contacts.data.map((contact) => ContactInfoEntity.delete({ personId, id: contact.id }).go()), + ...employments.data.map((emp) => EmploymentEntity.delete({ personId, id: emp.id }).go()), + PersonEntity.delete({ id: personId }).go(), + ]); +}; + +// ============================================================================= +// Address Operations +// ============================================================================= + +export const getAddressesByPersonId = async (personId: string): Promise => { + const result = await AddressEntity.query.primary({ personId }).go(); + return result.data as Address[]; +}; + +export const createAddress = async (address: Address): Promise
=> { + const result = await AddressEntity.put(address).go(); + return result.data as Address; +}; + +export const updateAddress = async (address: Address): Promise
=> { + const result = await AddressEntity.put(address).go(); + return result.data as Address; +}; + +export const deleteAddress = async (personId: string, addressId: string): Promise => { + await AddressEntity.delete({ personId, id: addressId }).go(); +}; + +// ============================================================================= +// BankAccount Operations +// ============================================================================= + +export const getBankAccountsByPersonId = async (personId: string): Promise => { + const result = await BankAccountEntity.query.primary({ personId }).go(); + return result.data as BankAccount[]; +}; + +export const createBankAccount = async (bankAccount: BankAccount): Promise => { + const result = await BankAccountEntity.put(bankAccount).go(); + return result.data as BankAccount; +}; + +export const updateBankAccount = async (bankAccount: BankAccount): Promise => { + const result = await BankAccountEntity.put(bankAccount).go(); + return result.data as BankAccount; +}; + +export const deleteBankAccount = async (personId: string, bankAccountId: string): Promise => { + await BankAccountEntity.delete({ personId, id: bankAccountId }).go(); +}; + +// ============================================================================= +// ContactInfo Operations +// ============================================================================= + +export const getContactsByPersonId = async (personId: string): Promise => { + const result = await ContactInfoEntity.query.primary({ personId }).go(); + return result.data as ContactInfo[]; +}; + +export const createContact = async (contact: ContactInfo): Promise => { + const result = await ContactInfoEntity.put(contact).go(); + return result.data as ContactInfo; +}; + +export const updateContact = async (contact: ContactInfo): Promise => { + const result = await ContactInfoEntity.put(contact).go(); + return result.data as ContactInfo; +}; + +export const deleteContact = async (personId: string, contactId: string): Promise => { + await ContactInfoEntity.delete({ personId, id: contactId }).go(); +}; + +// ============================================================================= +// Employment Operations +// ============================================================================= + +// Helper to convert null to undefined for ElectroDB compatibility +const normalizeEmployment = (employment: Employment) => ({ + ...employment, + endDate: employment.endDate ?? undefined, +}); + +export const getEmploymentsByPersonId = async (personId: string): Promise => { + const result = await EmploymentEntity.query.primary({ personId }).go(); + return result.data as Employment[]; +}; + +export const createEmployment = async (employment: Employment): Promise => { + const result = await EmploymentEntity.put(normalizeEmployment(employment)).go(); + return result.data as Employment; +}; + +export const updateEmployment = async (employment: Employment): Promise => { + const result = await EmploymentEntity.put(normalizeEmployment(employment)).go(); + return result.data as Employment; +}; + +export const deleteEmployment = async (personId: string, employmentId: string): Promise => { + await EmploymentEntity.delete({ personId, id: employmentId }).go(); +}; diff --git a/src/webapp/integrations/electrodb/zod-to-electrodb.ts b/src/webapp/integrations/electrodb/zod-to-electrodb.ts new file mode 100644 index 0000000..02a663b --- /dev/null +++ b/src/webapp/integrations/electrodb/zod-to-electrodb.ts @@ -0,0 +1,185 @@ +import { type ZodObject, type ZodRawShape, type ZodType } from 'zod'; + +// Helper to get the schema's internal type discriminator (Zod 4 uses def.type) +const getZodTypeName = (schema: ZodType): string => { + // Access the internal _zod.def.type which exists in Zod 4 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const internals = (schema as any)._zod?.def?.type ?? (schema as any).def?.type ?? ''; + return internals; +}; + +// Helper to unwrap wrapper types and get inner schema +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const unwrapSchema = (schema: ZodType): ZodType => (schema as any).unwrap?.() ?? schema; + +// Helper to resolve default value +const resolveDefaultValue = (defaultValue: unknown): unknown => { + if (typeof defaultValue === 'function') { + return defaultValue(); + } + return defaultValue; +}; + +/** + * Attribute result type - using 'any' to match ElectroDB's flexible attribute types + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type ElectroDBAttributeResult = Record; + +// Handle wrapper types (optional, nullable, default) +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handleWrapperType = (typeName: string, zodType: ZodType): any | null => { + if (typeName === 'optional' || typeName === 'nullable') { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + return { ...convertZodType(unwrapSchema(zodType)), required: false }; + } + if (typeName === 'default') { + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-use-before-define + const inner = convertZodType(unwrapSchema(zodType)); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const defaultValue = (zodType as any)._zod?.def?.defaultValue; + return { ...inner, default: resolveDefaultValue(defaultValue) }; + } + return null; +}; + +// Handle primitive types (string, number, boolean) +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handlePrimitiveType = (typeName: string): any | null => { + if (typeName === 'string') { + return { type: 'string', required: true }; + } + if (typeName === 'number' || typeName === 'int') { + return { type: 'number', required: true }; + } + if (typeName === 'boolean') { + return { type: 'boolean', required: true }; + } + return null; +}; + +// Handle enum types +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handleEnumType = (typeName: string, zodType: ZodType): any | null => { + if (typeName === 'enum') { + // Zod 4: .options is an array of enum values, or extract from entries object + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const { options } = zodType as any; + if (Array.isArray(options) && options.length) { + return { type: options as readonly string[], required: true }; + } + // Fallback: entries is an object like { male: 'male', female: 'female' } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const entries = (zodType as any)._zod?.def?.entries; + if (entries && typeof entries === 'object') { + return { type: Object.values(entries) as readonly string[], required: true }; + } + // Default to string if enum extraction fails + return { type: 'string', required: true }; + } + return null; +}; + +// Handle collection types (array, object) +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handleCollectionType = (typeName: string): any | null => { + if (typeName === 'array' || typeName === 'tuple') { + return { type: 'list', required: true }; + } + if (typeName === 'object' || typeName === 'record') { + return { type: 'map', required: true }; + } + return null; +}; + +// Handle union and intersection types +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handleUnionType = (typeName: string): any | null => { + if (typeName === 'union') { + return { type: 'any', required: true }; + } + if (typeName === 'intersection') { + return { type: 'map', required: true }; + } + return null; +}; + +// Handle pipe/transform types +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handlePipeType = (typeName: string, zodType: ZodType): any | null => { + if (typeName === 'pipe' || typeName === 'transform') { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + return convertZodType(unwrapSchema(zodType)); + } + return null; +}; + +// Handle literal types +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const handleLiteralType = (typeName: string, zodType: ZodType): any | null => { + if (typeName !== 'literal') { + return null; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const value = (zodType as any)._zod?.def?.value; + if (typeof value === 'string') { + return { type: [value] as readonly string[], required: true }; + } + if (typeof value === 'number') { + return { type: 'number', required: true }; + } + if (typeof value === 'boolean') { + return { type: 'boolean', required: true }; + } + return { type: 'any', required: true }; +}; + +/** + * Convert a single Zod type to ElectroDB attribute definition + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const convertZodType = (zodType: ZodType): any => { + const typeName = getZodTypeName(zodType); + + return ( + handleWrapperType(typeName, zodType) ?? + handlePrimitiveType(typeName) ?? + handleEnumType(typeName, zodType) ?? + handleCollectionType(typeName) ?? + handleUnionType(typeName) ?? + handlePipeType(typeName, zodType) ?? + handleLiteralType(typeName, zodType) ?? { type: 'string', required: true } + ); +}; + +/** + * Convert a Zod schema to ElectroDB attributes + * This ensures Zod is the single source of truth for schema definitions + * + * @example + * ```typescript + * const personAttributes = zodToElectroDBAttributes(PersonSchema) + * // Returns: { id: { type: 'string', required: true }, firstName: { type: 'string', required: true }, ... } + * ``` + */ +export const zodToElectroDBAttributes = ( + schema: ZodObject, +): ElectroDBAttributeResult => { + const { shape } = schema; + const attributes: ElectroDBAttributeResult = {}; + + for (const [key, zodType] of Object.entries(shape)) { + attributes[key] = convertZodType(zodType as ZodType); + } + + return attributes; +}; + +/** + * Helper to extract enum values from a Zod enum schema + * Useful for ElectroDB enum validation + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const getEnumValues = (enumSchema: ZodType): readonly string[] => + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (enumSchema as any)._zod?.def?.entries ?? (enumSchema as any)._zod?.values ?? []; diff --git a/src/webapp/integrations/tanstack-query/root-provider.tsx b/src/webapp/integrations/tanstack-query/root-provider.tsx index 62725c2..becd32d 100644 --- a/src/webapp/integrations/tanstack-query/root-provider.tsx +++ b/src/webapp/integrations/tanstack-query/root-provider.tsx @@ -3,8 +3,8 @@ import { QueryClient } from '@tanstack/react-query'; import { createTRPCClient, httpBatchStreamLink } from '@trpc/client'; import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query'; import superjson from 'superjson'; -import type { TRPCRouter } from '@/webapp/integrations/trpc/router'; -import { TRPCProvider } from '@/webapp/integrations/trpc/react'; +import type { TRPCRouter } from '#src/webapp/integrations/trpc/router'; +import { TRPCProvider } from '#src/webapp/integrations/trpc/react'; function getUrl() { const base = (() => { @@ -17,7 +17,7 @@ function getUrl() { return `${base}/api/trpc`; } -export const trpcClient = createTRPCClient({ +const trpcClient = createTRPCClient({ links: [ httpBatchStreamLink({ transformer: superjson, diff --git a/src/webapp/integrations/trpc/react.ts b/src/webapp/integrations/trpc/react.ts index 9e50bf1..8bdc3d9 100644 --- a/src/webapp/integrations/trpc/react.ts +++ b/src/webapp/integrations/trpc/react.ts @@ -1,4 +1,4 @@ import { createTRPCContext } from '@trpc/tanstack-react-query'; -import type { TRPCRouter } from '@/webapp/integrations/trpc/router'; +import type { TRPCRouter } from '#src/webapp/integrations/trpc/router'; export const { TRPCProvider, useTRPC } = createTRPCContext(); diff --git a/src/webapp/routeTree.gen.ts b/src/webapp/routeTree.gen.ts index c9b64c3..19fe2b3 100644 --- a/src/webapp/routeTree.gen.ts +++ b/src/webapp/routeTree.gen.ts @@ -15,6 +15,7 @@ import { Route as DemoTanstackQueryRouteImport } from './routes/demo/tanstack-qu import { Route as DemoTanchatRouteImport } from './routes/demo/tanchat' import { Route as DemoStoreRouteImport } from './routes/demo/store' import { Route as DemoDbTodoRouteImport } from './routes/demo/db-todo' +import { Route as DemoDbPersonRouteImport } from './routes/demo/db-person' import { Route as ExampleGuitarsIndexRouteImport } from './routes/example.guitars/index' import { Route as ExampleGuitarsGuitarIdRouteImport } from './routes/example.guitars/$guitarId' import { Route as DemoStartServerFuncsRouteImport } from './routes/demo/start.server-funcs' @@ -59,6 +60,11 @@ const DemoDbTodoRoute = DemoDbTodoRouteImport.update({ path: '/demo/db-todo', getParentRoute: () => rootRouteImport, } as any) +const DemoDbPersonRoute = DemoDbPersonRouteImport.update({ + id: '/demo/db-person', + path: '/demo/db-person', + getParentRoute: () => rootRouteImport, +} as any) const ExampleGuitarsIndexRoute = ExampleGuitarsIndexRouteImport.update({ id: '/example/guitars/', path: '/example/guitars/', @@ -127,6 +133,7 @@ const DemoStartSsrDataOnlyRoute = DemoStartSsrDataOnlyRouteImport.update({ export interface FileRoutesByFullPath { '/': typeof IndexRoute + '/demo/db-person': typeof DemoDbPersonRoute '/demo/db-todo': typeof DemoDbTodoRoute '/demo/store': typeof DemoStoreRoute '/demo/tanchat': typeof DemoTanchatRoute @@ -148,6 +155,7 @@ export interface FileRoutesByFullPath { } export interface FileRoutesByTo { '/': typeof IndexRoute + '/demo/db-person': typeof DemoDbPersonRoute '/demo/db-todo': typeof DemoDbTodoRoute '/demo/store': typeof DemoStoreRoute '/demo/tanchat': typeof DemoTanchatRoute @@ -170,6 +178,7 @@ export interface FileRoutesByTo { export interface FileRoutesById { __root__: typeof rootRouteImport '/': typeof IndexRoute + '/demo/db-person': typeof DemoDbPersonRoute '/demo/db-todo': typeof DemoDbTodoRoute '/demo/store': typeof DemoStoreRoute '/demo/tanchat': typeof DemoTanchatRoute @@ -193,6 +202,7 @@ export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath fullPaths: | '/' + | '/demo/db-person' | '/demo/db-todo' | '/demo/store' | '/demo/tanchat' @@ -214,6 +224,7 @@ export interface FileRouteTypes { fileRoutesByTo: FileRoutesByTo to: | '/' + | '/demo/db-person' | '/demo/db-todo' | '/demo/store' | '/demo/tanchat' @@ -235,6 +246,7 @@ export interface FileRouteTypes { id: | '__root__' | '/' + | '/demo/db-person' | '/demo/db-todo' | '/demo/store' | '/demo/tanchat' @@ -257,6 +269,7 @@ export interface FileRouteTypes { } export interface RootRouteChildren { IndexRoute: typeof IndexRoute + DemoDbPersonRoute: typeof DemoDbPersonRoute DemoDbTodoRoute: typeof DemoDbTodoRoute DemoStoreRoute: typeof DemoStoreRoute DemoTanchatRoute: typeof DemoTanchatRoute @@ -321,6 +334,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof DemoDbTodoRouteImport parentRoute: typeof rootRouteImport } + '/demo/db-person': { + id: '/demo/db-person' + path: '/demo/db-person' + fullPath: '/demo/db-person' + preLoaderRoute: typeof DemoDbPersonRouteImport + parentRoute: typeof rootRouteImport + } '/example/guitars/': { id: '/example/guitars/' path: '/example/guitars' @@ -417,6 +437,7 @@ declare module '@tanstack/react-router' { const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, + DemoDbPersonRoute: DemoDbPersonRoute, DemoDbTodoRoute: DemoDbTodoRoute, DemoStoreRoute: DemoStoreRoute, DemoTanchatRoute: DemoTanchatRoute, diff --git a/src/webapp/routes/__root.tsx b/src/webapp/routes/__root.tsx index 3796503..2d378a9 100644 --- a/src/webapp/routes/__root.tsx +++ b/src/webapp/routes/__root.tsx @@ -4,7 +4,7 @@ import type { TRPCOptionsProxy } from '@trpc/tanstack-react-query'; import { TanStackDevtools } from '@tanstack/react-devtools'; import { createRootRouteWithContext, HeadContent, Scripts } from '@tanstack/react-router'; import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'; -import type { TRPCRouter } from '@/webapp/integrations/trpc/router'; +import type { TRPCRouter } from '#src/webapp/integrations/trpc/router'; import Header from '../components/Header'; import TanStackQueryDevtools from '../integrations/tanstack-query/devtools'; import StoreDevtools from '../lib/demo-store-devtools'; diff --git a/src/webapp/routes/api.trpc.$.tsx b/src/webapp/routes/api.trpc.$.tsx index 6737d1b..8d64131 100644 --- a/src/webapp/routes/api.trpc.$.tsx +++ b/src/webapp/routes/api.trpc.$.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router'; import { fetchRequestHandler } from '@trpc/server/adapters/fetch'; -import { trpcRouter } from '@/webapp/integrations/trpc/router'; +import { trpcRouter } from '#src/webapp/integrations/trpc/router'; function handler({ request }: { request: Request }) { return fetchRequestHandler({ diff --git a/src/webapp/routes/demo/api.ddb-todos.ts b/src/webapp/routes/demo/api.ddb-todos.ts index fca5596..0490f59 100644 --- a/src/webapp/routes/demo/api.ddb-todos.ts +++ b/src/webapp/routes/demo/api.ddb-todos.ts @@ -1,11 +1,11 @@ // oxlint-disable func-style import { createFileRoute } from '@tanstack/react-router'; -import { createTodosDdbClient } from '@/webapp/integrations/ddb-client/ddbClient'; +import { createTodosDdbClient } from '#src/webapp/integrations/ddb-client/ddbClient'; import { createTodoRequestSchema, deleteTodosRequestSchema, updateTodosRequestSchema, -} from '@/webapp/types/todo'; +} from '#src/webapp/types/todo'; const todosClient = createTodosDdbClient(); diff --git a/src/webapp/routes/demo/api.tanchat.ts b/src/webapp/routes/demo/api.tanchat.ts index cb97cbf..1877e6c 100644 --- a/src/webapp/routes/demo/api.tanchat.ts +++ b/src/webapp/routes/demo/api.tanchat.ts @@ -2,7 +2,7 @@ import { bedrock } from '@ai-sdk/amazon-bedrock'; import { createFileRoute } from '@tanstack/react-router'; import { convertToModelMessages, stepCountIs, streamText } from 'ai'; -import getTools from '@/webapp/utils/demo.tools'; +import getTools from '#src/webapp/utils/demo.tools'; const SYSTEM_PROMPT = `You are a helpful assistant for a store that sells guitars. @@ -33,6 +33,7 @@ export const Route = createFileRoute('/demo/api/tanchat')({ return result.toUIMessageStreamResponse(); } catch (error) { + // oxlint-disable-next-line no-console console.error('Chat API error:', error); return new Response(JSON.stringify({ error: 'Failed to process chat request' }), { status: 500, diff --git a/src/webapp/routes/demo/api.tq-todos.ts b/src/webapp/routes/demo/api.tq-todos.ts index 33c8c98..5270366 100644 --- a/src/webapp/routes/demo/api.tq-todos.ts +++ b/src/webapp/routes/demo/api.tq-todos.ts @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router'; import { z } from 'zod'; -import { type Todo, todoSchema } from '@/webapp/types/todo'; +import { type Todo, todoSchema } from '#src/webapp/types/todo'; let todos: Todo[] = [ { diff --git a/src/webapp/routes/demo/db-person.tsx b/src/webapp/routes/demo/db-person.tsx new file mode 100644 index 0000000..4b206ba --- /dev/null +++ b/src/webapp/routes/demo/db-person.tsx @@ -0,0 +1,106 @@ +// oxlint-disable max-statements +import { CreatePersonModal } from '#src/webapp/components/persons/CreatePersonModal'; +import { PersonDetailPanel } from '#src/webapp/components/persons/PersonDetailPanel'; +import { PersonsTable, type PersonTableRow } from '#src/webapp/components/persons/PersonsTable'; +import { Button } from '#src/webapp/components/ui/button'; +import { usePersons } from '#src/webapp/hooks/useDbPersons'; +// oxlint-disable func-style +import { createFileRoute } from '@tanstack/react-router'; +import { useState } from 'react'; + +export const Route = createFileRoute('/demo/db-person')({ + ssr: false, + component: DbPersons, +}); + +function DbPersons() { + const [selectedPersonId, setSelectedPersonId] = useState(null); + const [showCreateModal, setShowCreateModal] = useState(false); + + const { persons, isLoading, addPerson } = usePersons(); + + // Convert persons to table rows (React Compiler handles memoization) + const startDisplay = 0; + const maxDisplay = 100; + const tableData: PersonTableRow[] = persons.slice(startDisplay, maxDisplay).map((person) => ({ + id: String(person.id), + firstName: String(person.firstName), + lastName: String(person.lastName), + gender: person.gender, + dateOfBirth: person.dateOfBirth, + })); + + const handleRowSelect = (person: PersonTableRow) => { + setSelectedPersonId(person.id); + }; + + const handleCloseDetail = () => { + setSelectedPersonId(null); + }; + + const getTableContainerClass = (hasSelection: string | null) => { + if (hasSelection) { + return 'w-1/2 min-w-0'; + } + return 'w-full'; + }; + + return ( +
+ {/* Header */} +
+
+

DB Persons

+

Browse and manage persons with multi-entity support

+
+ +
+ + {/* Main Content - Table and Detail Panel */} +
+ {/* Persons Table */} +
+ +
+ + {/* Selected Person Detail Panel */} + {selectedPersonId && ( +
+ +
+ )} +
+ {showCreateModal && ( + setShowCreateModal(false)} + onSave={(values) => { + const now = new Date().toISOString(); + addPerson({ + id: crypto.randomUUID(), + firstName: values.firstName, + lastName: values.lastName, + dateOfBirth: values.dateOfBirth ?? '', + gender: values.gender ?? 'other', + createdAt: now, + updatedAt: now, + } as any); + setShowCreateModal(false); + }} + /> + )} +
+ ); +} diff --git a/src/webapp/routes/demo/db-todo.tsx b/src/webapp/routes/demo/db-todo.tsx index 54cd56c..57e2590 100644 --- a/src/webapp/routes/demo/db-todo.tsx +++ b/src/webapp/routes/demo/db-todo.tsx @@ -2,7 +2,7 @@ import { createFileRoute } from '@tanstack/react-router'; import { Trash2 } from 'lucide-react'; import { useState } from 'react'; -import { useTodo, useTodos } from '@/webapp/hooks/useDbTodos'; +import { useTodo, useTodos } from '#src/webapp/hooks/useDbTodos'; export const Route = createFileRoute('/demo/db-todo')({ ssr: false, diff --git a/src/webapp/routes/demo/start.server-funcs.tsx b/src/webapp/routes/demo/start.server-funcs.tsx index b8c0a1e..bb016ec 100644 --- a/src/webapp/routes/demo/start.server-funcs.tsx +++ b/src/webapp/routes/demo/start.server-funcs.tsx @@ -1,3 +1,4 @@ +// oxlint-disable no-magic-numbers import { createFileRoute, useRouter } from '@tanstack/react-router'; import { createServerFn } from '@tanstack/react-start'; import fs from 'node:fs'; @@ -38,7 +39,7 @@ const getTodos = createServerFn({ }).handler(async () => await readTodos()); const addTodo = createServerFn({ method: 'POST' }) - .inputValidator((d: string) => d) + .inputValidator((data: string) => data) .handler(async ({ data }) => { const todos = await readTodos(); todos.push({ id: todos.length + 1, name: data }); diff --git a/src/webapp/routes/demo/start.ssr.data-only.tsx b/src/webapp/routes/demo/start.ssr.data-only.tsx index 86d7373..74cab0b 100644 --- a/src/webapp/routes/demo/start.ssr.data-only.tsx +++ b/src/webapp/routes/demo/start.ssr.data-only.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/react-router'; -import { getPunkSongs } from '@/webapp/data/demo.punk-songs'; +import { getPunkSongs } from '#src/webapp/data/demo.punk-songs'; export const Route = createFileRoute('/demo/start/ssr/data-only')({ ssr: 'data-only', diff --git a/src/webapp/routes/demo/start.ssr.full-ssr.tsx b/src/webapp/routes/demo/start.ssr.full-ssr.tsx index ef1103e..55b4010 100644 --- a/src/webapp/routes/demo/start.ssr.full-ssr.tsx +++ b/src/webapp/routes/demo/start.ssr.full-ssr.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/react-router'; -import { getPunkSongs } from '@/webapp/data/demo.punk-songs'; +import { getPunkSongs } from '#src/webapp/data/demo.punk-songs'; export const Route = createFileRoute('/demo/start/ssr/full-ssr')({ component: RouteComponent, diff --git a/src/webapp/routes/demo/start.ssr.spa-mode.tsx b/src/webapp/routes/demo/start.ssr.spa-mode.tsx index 2bfd53c..fed4a8f 100644 --- a/src/webapp/routes/demo/start.ssr.spa-mode.tsx +++ b/src/webapp/routes/demo/start.ssr.spa-mode.tsx @@ -1,7 +1,7 @@ import { createFileRoute } from '@tanstack/react-router'; // oxlint-disable func-style import { useEffect, useState } from 'react'; -import { getPunkSongs } from '@/webapp/data/demo.punk-songs'; +import { getPunkSongs } from '#src/webapp/data/demo.punk-songs'; export const Route = createFileRoute('/demo/start/ssr/spa-mode')({ component: RouteComponent, diff --git a/src/webapp/routes/demo/store.tsx b/src/webapp/routes/demo/store.tsx index 54947a7..bcf3066 100644 --- a/src/webapp/routes/demo/store.tsx +++ b/src/webapp/routes/demo/store.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router'; import { useStore } from '@tanstack/react-store'; -import { fullName, store } from '@/webapp/lib/demo-store'; +import { fullName, store } from '#src/webapp/lib/demo-store'; export const Route = createFileRoute('/demo/store')({ component: DemoStore, diff --git a/src/webapp/routes/demo/tanchat.tsx b/src/webapp/routes/demo/tanchat.tsx index c9238b4..6f569d8 100644 --- a/src/webapp/routes/demo/tanchat.tsx +++ b/src/webapp/routes/demo/tanchat.tsx @@ -5,7 +5,7 @@ import { DefaultChatTransport } from 'ai'; import { Send } from 'lucide-react'; import { useEffect, useRef, useState } from 'react'; import { Streamdown } from 'streamdown'; -import GuitarRecommendation from '@/webapp/components/example-GuitarRecommendation'; +import GuitarRecommendation from '#src/webapp/components/example-GuitarRecommendation'; import './tanchat.css'; function InitalLayout({ children }: { children: React.ReactNode }) { diff --git a/src/webapp/routes/demo/tanstack-query.tsx b/src/webapp/routes/demo/tanstack-query.tsx index 8f94905..793b03d 100644 --- a/src/webapp/routes/demo/tanstack-query.tsx +++ b/src/webapp/routes/demo/tanstack-query.tsx @@ -3,7 +3,7 @@ import { useMutation, useQuery } from '@tanstack/react-query'; import { createFileRoute } from '@tanstack/react-router'; import { Trash2 } from 'lucide-react'; import { useCallback, useState } from 'react'; -import { type Todo, todoSchema } from '@/webapp/types/todo'; +import { type Todo, todoSchema } from '#src/webapp/types/todo'; export const Route = createFileRoute('/demo/tanstack-query')({ component: TanStackQueryDemo, diff --git a/src/webapp/routes/demo/trpc-todo.tsx b/src/webapp/routes/demo/trpc-todo.tsx index ff73179..05d4b61 100644 --- a/src/webapp/routes/demo/trpc-todo.tsx +++ b/src/webapp/routes/demo/trpc-todo.tsx @@ -2,7 +2,7 @@ import { useMutation, useQuery } from '@tanstack/react-query'; import { createFileRoute } from '@tanstack/react-router'; import { useCallback, useState } from 'react'; -import { useTRPC } from '@/webapp/integrations/trpc/react'; +import { useTRPC } from '#src/webapp/integrations/trpc/react'; export const Route = createFileRoute('/demo/trpc-todo')({ component: TRPCTodos, diff --git a/src/webapp/types/person.ts b/src/webapp/types/person.ts new file mode 100644 index 0000000..982c7e8 --- /dev/null +++ b/src/webapp/types/person.ts @@ -0,0 +1,118 @@ +// oxlint-disable no-magic-numbers +import { z } from 'zod'; + +// ============================================================================= +// Enums +// ============================================================================= + +export const GenderEnum = z.enum(['male', 'female', 'other', 'prefer_not_to_say']); +export type Gender = z.infer; + +export const AddressTypeEnum = z.enum(['home', 'work', 'billing', 'shipping']); +export type AddressType = z.infer; + +const AccountTypeEnum = z.enum(['checking', 'savings', 'investment']); +export type AccountType = z.infer; + +const ContactTypeEnum = z.enum(['email', 'phone', 'mobile', 'linkedin', 'twitter']); +export type ContactType = z.infer; + +// ============================================================================= +// Entity Schemas +// ============================================================================= + +/** + * Person - Core entity with personal information + */ +export const PersonSchema = z.object({ + id: z.uuid(), + firstName: z.string().min(1).max(100), + lastName: z.string().min(1).max(100), + dateOfBirth: z.iso.datetime().optional(), + gender: GenderEnum.optional(), + createdAt: z.iso.datetime(), + updatedAt: z.iso.datetime(), +}); + +export type Person = z.infer; + +/** + * Address - Physical/mailing addresses (1:N with Person) + */ +export const AddressSchema = z.object({ + id: z.uuid(), + personId: z.uuid(), + type: AddressTypeEnum, + street: z.string().min(1).max(200), + city: z.string().min(1).max(100), + state: z.string().min(1).max(100), + postalCode: z.string().min(1).max(20), + country: z.string().min(1).max(100), + isPrimary: z.boolean().default(false), +}); + +export type Address = z.infer; + +/** + * BankAccount - Banking information (1:N with Person) + */ +export const BankAccountSchema = z.object({ + id: z.uuid(), + personId: z.uuid(), + bankName: z.string().min(1).max(100), + accountType: AccountTypeEnum, + accountNumberLast4: z.string().length(4), + iban: z.string().min(15).max(34).optional(), + bic: z.string().min(8).max(11).optional(), + isPrimary: z.boolean().default(false), +}); + +export type BankAccount = z.infer; + +/** + * ContactInfo - Email, phone, social media (1:N with Person) + */ +export const ContactInfoSchema = z.object({ + id: z.uuid(), + personId: z.uuid(), + type: ContactTypeEnum, + value: z.string().min(1).max(200), + isPrimary: z.boolean().default(false), + isVerified: z.boolean().default(false), +}); + +export type ContactInfo = z.infer; + +/** + * Employment - Job history and current employment (1:N with Person) + */ +export const EmploymentSchema = z.object({ + id: z.uuid(), + personId: z.uuid(), + companyName: z.string().min(1).max(200), + position: z.string().min(1).max(100), + department: z.string().max(100).optional(), + startDate: z.iso.datetime(), + endDate: z.iso.datetime().nullable().optional(), + isCurrent: z.boolean().default(false), + salary: z.number().positive().optional(), + currency: z.string().length(3).default('USD'), +}); + +export type Employment = z.infer; + +// ============================================================================= +// Composite Types +// ============================================================================= + +/** + * Person with all related entities (addresses, bank accounts, contacts, employments) + */ +const PersonWithRelationsSchema = PersonSchema.extend({ + addresses: z.array(AddressSchema), + bankAccounts: z.array(BankAccountSchema), + contacts: z.array(ContactInfoSchema), + employments: z.array(EmploymentSchema), +}); + +export type PersonWithRelations = z.infer; diff --git a/src/webapp/types/todo.ts b/src/webapp/types/todo.ts index 4f14945..ce77147 100644 --- a/src/webapp/types/todo.ts +++ b/src/webapp/types/todo.ts @@ -9,9 +9,9 @@ export const todoSchema = z.object({ export type Todo = z.infer; export const createTodoRequestSchema = todoSchema; -export type CreateTodoRequest = z.infer; +type CreateTodoRequest = z.infer; -export const todoUpdateSchema = z.object({ +const todoUpdateSchema = z.object({ id: z.number(), changes: z .object({ @@ -23,7 +23,7 @@ export const todoUpdateSchema = z.object({ export type TodoUpdate = z.infer; export const updateTodosRequestSchema = z.array(todoUpdateSchema); -export type UpdateTodosRequest = z.infer; +type UpdateTodosRequest = z.infer; export const deleteTodosRequestSchema = z.array(z.number()); -export type DeleteTodosRequest = z.infer; +type DeleteTodosRequest = z.infer; diff --git a/tsconfig.json b/tsconfig.json index b536622..0ef2950 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -31,7 +31,7 @@ "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true, "paths": { - "@/*": [ + "#src/*": [ "./src/*" ] } diff --git a/vite.config.ts b/vite.config.ts index d3c1518..0844ae5 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -19,7 +19,7 @@ const config = defineConfig({ }, preset: 'aws-lambda', }), - // this is the plugin that enables path aliases + // This is the plugin that enables path aliases viteTsConfigPaths({ projects: ['./tsconfig.json'], }), @@ -27,7 +27,11 @@ const config = defineConfig({ tanstackStart({ srcDirectory: 'src/webapp', }), - viteReact(), + viteReact({ + babel: { + plugins: [['babel-plugin-react-compiler', {}]], + }, + }), ], });