diff --git a/AGENTS.md b/AGENTS.md index 4832b93..3b57367 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,3 +1,22 @@ + +# OpenSpec Instructions + +These instructions are for AI assistants working in this project. + +Always open `@/openspec/AGENTS.md` when the request: +- Mentions planning or proposals (words like proposal, spec, change, plan) +- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work +- Sounds ambiguous and you need the authoritative spec before coding + +Use `@/openspec/AGENTS.md` to learn: +- How to create and apply change proposals +- Spec format and conventions +- Project structure and guidelines + +Keep this managed block so 'openspec update' can refresh the instructions. + + + # AGENTS.md: SolidStart AI Task List _Last updated: 2025-11-22_ @@ -15,10 +34,11 @@ This is a **Local-First AI Task Manager** built with **SolidStart**. It is desig - **Framework**: SolidStart (SolidJS meta-framework) using `vinxi`. - **Language**: TypeScript. -- **Data Layer (Local-First)**: **Y.js** for state and CRDTs, persisted via **IndexedDB** (`y-indexeddb`). There is **no** traditional backend database (Postgres/MySQL). +- **Data Layer (Local-First)**: **cr-sqlite** for structured queries with CRDTs, persisted via **OPFS** (Origin Private File System) with IndexedDB fallback. Tasks stored in SQL tables. There is **no** traditional backend database (Postgres/MySQL). - **AI Layer**: Vercel AI SDK (`ai`, `@ai-sdk/google`) running on Server Actions to interface with Gemini. - **Styling**: Modern vanilla CSS with CSS Variables, layers, CSS nesting, scoped component CSS, features like View Transitions and modern size values. - **Ordering**: `lexorank` for efficient drag-and-drop sorting. +- **Sync Architecture**: File-based encrypted changesets stored in **Cloudflare R2**. Sync is pull-to-refresh (no real-time WebSocket). Device-to-device pairing via QR codes with end-to-end encryption. **Golden Rule**: When unsure about implementation details, architectural choices, or requirements, **ALWAYS consult the developer** rather than making assumptions. @@ -46,8 +66,9 @@ This is a **Local-First AI Task Manager** built with **SolidStart**. It is desig - **Never** destructure props in Solid components (you lose reactivity). Access them via `props.value`. - **Control Flow**: Use Solid's ``, ``, ``, `` components instead of `array.map()` or ternary operators for rendering. - **Data Persistence**: - - All persistent data goes through `src/stores/taskStore.ts`. - - Mutations must happen inside `doc.transact(() => { ... })`. + - All persistent data goes through `src/stores/taskStore.ts` and `src/stores/vaultStore.ts`. + - Task mutations happen via SQL queries to cr-sqlite database. + - Vault keys and sync state stored in IndexedDB. - **Styling**: - Use minimal amount of classes, enhance css + html with data attributes for variable styling, (e.g., button[type="submit"] or .container[data-size="large"]) - Design for mobile-first experience, targeting media queries only above certain screen sizes. @@ -71,10 +92,10 @@ This is a **Local-First AI Task Manager** built with **SolidStart**. It is desig ## Key Architectural Concepts -### 1. Local-First Data (Y.js + IndexedDB) -- **Concept**: The app works offline. Data is stored in a Y.js `Doc` which syncs to IndexedDB via `y-indexeddb`. -- **State**: The UI reads from a Solid `createStore` that mirrors the Y.js map. -- **Sync**: `yTasks.observe` triggers a `reconcile` on the Solid store to update the UI efficiently. +### 1. Local-First Data (cr-sqlite + OPFS) +- **Concept**: The app works offline. Data is stored in cr-sqlite WASM database persisted via OPFS (Origin Private File System) with IndexedDB fallback. +- **State**: The UI reads from a Solid `createStore` that mirrors SQLite queries. +- **Sync**: Changes trigger reactive updates to the Solid store to update the UI efficiently. - **Implication**: Do not try to fetch tasks from an API endpoint. Read them from `tasks()` in `taskStore.ts`. ### 2. Server Actions for AI @@ -84,12 +105,26 @@ This is a **Local-First AI Task Manager** built with **SolidStart**. It is desig 2. `breakdownTask` action (in `src/actions/taskActions.ts`) runs on the server. 3. Server calls Google Gemini via Vercel AI SDK. 4. Action returns structured data (JSON) to the client. - 5. Client receives data and updates the **local** Y.js store. + 5. Client receives data and updates the **local** SQLite database. ### 3. Lexorank Ordering - **Concept**: To support drag-and-drop without re-indexing the whole list, we use `lexorank`. - **Usage**: Every task has a `rank` string. When moving a task, calculate the new rank between the previous and next sibling. +### 4. Vault-Based Sync (Cloudflare R2 + cr-sqlite CRDTs) +- **Concept**: Optional sync via encrypted changesets stored in Cloudflare R2. Device pairing via QR codes. +- **Flow**: + 1. First device = local-only (no sync) + 2. Adding first paired device generates vault key and stores in IndexedDB + 3. QR code contains vault key + device ID + 4. cr-sqlite generates changesets on local changes + 5. Changesets encrypted with vault key (AES-GCM) before upload + 6. Upload to R2 with path = SHA256(vaultKey) (prevents enumeration) + 7. Sync on page load: fetch changesets since last sync, decrypt, apply to local DB + 8. Offline queue for failed uploads with retry on next sync +- **Zero-Knowledge**: Server (R2 proxy) never sees unencrypted data. All encryption happens client-side. +- **CRDT Merger**: cr-sqlite handles conflicts automatically with last-write-wins per column. + --- ## Common Pitfalls (SolidJS Specific) @@ -97,9 +132,12 @@ This is a **Local-First AI Task Manager** built with **SolidStart**. It is desig - **Destructuring Props**: `const { title } = props;` breaks reactivity. **Always** use `props.title`. - **Dependency Arrays**: `createEffect` tracks dependencies automatically. Do not pass a dependency array like in React. - **Class vs ClassName**: Solid uses `class="..."`, not `className`. -- **Server vs Client**: - - Files with `"use server"` run only on the server. - - Components using browser APIs (like `IndexedDB` or `document`) must be wrapped in `clientOnly` or checked with `isServer` / `onMount`. +- **Server vs Client**: + - Files with `"use server"` run only on the server. + - Components using browser APIs (like `IndexedDB`, `document`, or `crypto`) must be wrapped in `clientOnly` or checked with `isServer` / `onMount`. +- **SQL Database**: + - When working with cr-sqlite, always use camelCase for TypeScript types (e.g., `parentId`, `dueAt`) but snake_case for SQL queries (e.g., `parent_id`, `due_at`). + - Convert between types using helper functions (e.g., `dbRowToTask`). --- diff --git a/app.config.ts b/app.config.ts index 2f06014..759936d 100644 --- a/app.config.ts +++ b/app.config.ts @@ -3,14 +3,14 @@ import { defineConfig } from "@solidjs/start/config"; export default defineConfig({ server: { experimental: { - websocket: true + websocket: false } + }, + vite: { + optimizeDeps: { + exclude: ["@vlcn.io/crsqlite-wasm"] + }, + assetsInclude: ["**/*.wasm"] } -}).addRouter({ - name: "ws", - type: "http", - handler: "./src/ws.ts", - target: "server", - base: "/ws", }); diff --git a/package.json b/package.json index 9250f7c..d29deb6 100644 --- a/package.json +++ b/package.json @@ -13,21 +13,25 @@ }, "dependencies": { "@ai-sdk/google": "^2.0.42", + "@aws-sdk/client-s3": "^3.972.0", + "@aws-sdk/s3-request-presigner": "^3.972.0", "@solidjs/meta": "^0.29.4", "@solidjs/router": "^0.15.4", "@solidjs/start": "^1.2.0", "@thisbeyond/solid-dnd": "^0.7.5", + "@types/qrcode": "^1.5.6", + "@vlcn.io/crsqlite-wasm": "^0.16.0", + "@vlcn.io/ws-client": "^0.2.0", "ai": "^5.0.100", "dotenv": "^17.2.3", - "level": "^10.0.0", + "html5-qrcode": "^2.3.8", "lexorank": "^1.0.5", "lucide-solid": "^0.554.0", "nanoid": "^5.1.6", + "qrcode": "^1.5.4", "solid-js": "^1.9.10", "ufo": "^1.6.1", "vinxi": "^0.5.8", - "y-indexeddb": "^9.0.12", - "yjs": "^13.6.27", "zod": "^4.1.12" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eba298c..9569bf6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,12 @@ importers: '@ai-sdk/google': specifier: ^2.0.42 version: 2.0.42(zod@4.1.12) + '@aws-sdk/client-s3': + specifier: ^3.972.0 + version: 3.972.0 + '@aws-sdk/s3-request-presigner': + specifier: ^3.972.0 + version: 3.972.0 '@solidjs/meta': specifier: ^0.29.4 version: 0.29.4(solid-js@1.9.10) @@ -23,15 +29,24 @@ importers: '@thisbeyond/solid-dnd': specifier: ^0.7.5 version: 0.7.5(solid-js@1.9.10) + '@types/qrcode': + specifier: ^1.5.6 + version: 1.5.6 + '@vlcn.io/crsqlite-wasm': + specifier: ^0.16.0 + version: 0.16.0 + '@vlcn.io/ws-client': + specifier: ^0.2.0 + version: 0.2.0 ai: specifier: ^5.0.100 version: 5.0.100(zod@4.1.12) dotenv: specifier: ^17.2.3 version: 17.2.3 - level: - specifier: ^10.0.0 - version: 10.0.0 + html5-qrcode: + specifier: ^2.3.8 + version: 2.3.8 lexorank: specifier: ^1.0.5 version: 1.0.5 @@ -41,6 +56,9 @@ importers: nanoid: specifier: ^5.1.6 version: 5.1.6 + qrcode: + specifier: ^1.5.4 + version: 1.5.4 solid-js: specifier: ^1.9.10 version: 1.9.10 @@ -50,12 +68,6 @@ importers: vinxi: specifier: ^0.5.8 version: 0.5.8(@types/node@22.19.1)(db0@0.3.4)(ioredis@5.8.2)(jiti@2.6.1)(terser@5.44.1) - y-indexeddb: - specifier: ^9.0.12 - version: 9.0.12(yjs@13.6.27) - yjs: - specifier: ^13.6.27 - version: 13.6.27 zod: specifier: ^4.1.12 version: 4.1.12 @@ -133,6 +145,177 @@ packages: '@asamuzakjp/nwsapi@2.3.9': resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/crc32c@5.2.0': + resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} + + '@aws-crypto/sha1-browser@5.2.0': + resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-s3@3.972.0': + resolution: {integrity: sha512-ghpDQtjZvbhbnHWymq/V5TL8NppdAGF2THAxYRRBLCJ5JRlq71T24NdovAzvzYaGdH7HtcRkgErBRsFT1gtq4g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-sso@3.972.0': + resolution: {integrity: sha512-5qw6qLiRE4SUiz0hWy878dSR13tSVhbTWhsvFT8mGHe37NRRiaobm5MA2sWD0deRAuO98djSiV+dhWXa1xIFNw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.972.0': + resolution: {integrity: sha512-nEeUW2M9F+xdIaD98F5MBcQ4ITtykj3yKbgFZ6J0JtL3bq+Z90szQ6Yy8H/BLPYXTs3V4n9ifnBo8cprRDiE6A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/crc64-nvme@3.972.0': + resolution: {integrity: sha512-ThlLhTqX68jvoIVv+pryOdb5coP1cX1/MaTbB9xkGDCbWbsqQcLqzPxuSoW1DCnAAIacmXCWpzUNOB9pv+xXQw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-env@3.972.0': + resolution: {integrity: sha512-kKHoNv+maHlPQOAhYamhap0PObd16SAb3jwaY0KYgNTiSbeXlbGUZPLioo9oA3wU10zItJzx83ClU7d7h40luA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-http@3.972.0': + resolution: {integrity: sha512-xzEi81L7I5jGUbpmqEHCe7zZr54hCABdj4H+3LzktHYuovV/oqnvoDdvZpGFR0e/KAw1+PL38NbGrpG30j6qlA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-ini@3.972.0': + resolution: {integrity: sha512-ruhAMceUIq2aknFd3jhWxmO0P0Efab5efjyIXOkI9i80g+zDY5VekeSxfqRKStEEJSKSCHDLQuOu0BnAn4Rzew==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-login@3.972.0': + resolution: {integrity: sha512-SsrsFJsEYAJHO4N/r2P0aK6o8si6f1lprR+Ej8J731XJqTckSGs/HFHcbxOyW/iKt+LNUvZa59/VlJmjhF4bEQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-node@3.972.0': + resolution: {integrity: sha512-wwJDpEGl6+sOygic8QKu0OHVB8SiodqF1fr5jvUlSFfS6tJss/E9vBc2aFjl7zI6KpAIYfIzIgM006lRrZtWCQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-process@3.972.0': + resolution: {integrity: sha512-nmzYhamLDJ8K+v3zWck79IaKMc350xZnWsf/GeaXO6E3MewSzd3lYkTiMi7lEp3/UwDm9NHfPguoPm+mhlSWQQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-sso@3.972.0': + resolution: {integrity: sha512-6mYyfk1SrMZ15cH9T53yAF4YSnvq4yU1Xlgm3nqV1gZVQzmF5kr4t/F3BU3ygbvzi4uSwWxG3I3TYYS5eMlAyg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.972.0': + resolution: {integrity: sha512-vsJXBGL8H54kz4T6do3p5elATj5d1izVGUXMluRJntm9/I0be/zUYtdd4oDTM2kSUmd4Zhyw3fMQ9lw7CVhd4A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-bucket-endpoint@3.972.0': + resolution: {integrity: sha512-IrIjAehc3PrseAGfk2ldtAf+N0BAnNHR1DCZIDh9IAcFrTVWC3Fi9KJdtabrxcY3Onpt/8opOco4EIEAWgMz7A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-expect-continue@3.972.0': + resolution: {integrity: sha512-xyhDoY0qse8MvQC4RZCpT5WoIQ4/kwqv71Dh1s3mdXjL789Z4a6L/khBTSXECR5+egSZ960AInj3aR+CrezDRQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-flexible-checksums@3.972.0': + resolution: {integrity: sha512-zxK0ezmT7fLEPJ650S8QBc4rGDq5+5rdsLnnuZ6hPaZE4/+QtUoTw+gSDETyiWodNcRuz2ZWnqi17K+7nKtSRg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-host-header@3.972.0': + resolution: {integrity: sha512-3eztFI6F9/eHtkIaWKN3nT+PM+eQ6p1MALDuNshFk323ixuCZzOOVT8oUqtZa30Z6dycNXJwhlIq7NhUVFfimw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-location-constraint@3.972.0': + resolution: {integrity: sha512-WpsxoVPzbGPQGb/jupNYjpE0REcCPtjz7Q7zAt+dyo7fxsLBn4J+Rp6AYzSa04J9VrmrvCqCbVLu6B88PlSKSQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-logger@3.972.0': + resolution: {integrity: sha512-ZvdyVRwzK+ra31v1pQrgbqR/KsLD+wwJjHgko6JfoKUBIcEfAwJzQKO6HspHxdHWTVUz6MgvwskheR/TTYZl2g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.972.0': + resolution: {integrity: sha512-F2SmUeO+S6l1h6dydNet3BQIk173uAkcfU1HDkw/bUdRLAnh15D3HP9vCZ7oCPBNcdEICbXYDmx0BR9rRUHGlQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.972.0': + resolution: {integrity: sha512-0bcKFXWx+NZ7tIlOo7KjQ+O2rydiHdIQahrq+fN6k9Osky29v17guy68urUKfhTobR6iY6KvxkroFWaFtTgS5w==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-ssec@3.972.0': + resolution: {integrity: sha512-cEr2HtK4R2fi8Y0P95cjbr4KJOjKBt8ms95mEJhabJN8KM4CpD4iS/J1lhvMj+qWir0KBTV6gKmxECXdfL9S6w==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-user-agent@3.972.0': + resolution: {integrity: sha512-kFHQm2OCBJCzGWRafgdWHGFjitUXY/OxXngymcX4l8CiyiNDZB27HDDBg2yLj3OUJc4z4fexLMmP8r9vgag19g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/nested-clients@3.972.0': + resolution: {integrity: sha512-QGlbnuGzSQJVG6bR9Qw6G0Blh6abFR4VxNa61ttMbzy9jt28xmk2iGtrYLrQPlCCPhY6enHqjTWm3n3LOb0wAw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/region-config-resolver@3.972.0': + resolution: {integrity: sha512-JyOf+R/6vJW8OEVFCAyzEOn2reri/Q+L0z9zx4JQSKWvTmJ1qeFO25sOm8VIfB8URKhfGRTQF30pfYaH2zxt/A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/s3-request-presigner@3.972.0': + resolution: {integrity: sha512-AsmnNkW+RF+UQ86bYduMN4e6DuEAsy9nragtBAdGnlVYILTB7C2AjMVzp2EM1WOzjZ4dDsOUS/t099rzi+GcfQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.972.0': + resolution: {integrity: sha512-2udiRijmjpN81Pvajje4TsjbXDZNP6K9bYUanBYH8hXa/tZG5qfGCySD+TyX0sgDxCQmEDMg3LaQdfjNHBDEgQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.972.0': + resolution: {integrity: sha512-kWlXG+y5nZhgXGEtb72Je+EvqepBPs8E3vZse//1PYLWs2speFqbGE/ywCXmzEJgHgVqSB/u/lqBvs5WlYmSqQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.972.0': + resolution: {integrity: sha512-U7xBIbLSetONxb2bNzHyDgND3oKGoIfmknrEVnoEU4GUSs+0augUOIn9DIWGUO2ETcRFdsRUnmx9KhPT9Ojbug==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-arn-parser@3.972.0': + resolution: {integrity: sha512-RM5Mmo/KJ593iMSrALlHEOcc9YOIyOsDmS5x2NLOMdEmzv1o00fcpAkCQ02IGu1eFneBFT7uX0Mpag0HI+Cz2g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-endpoints@3.972.0': + resolution: {integrity: sha512-6JHsl1V/a1ZW8D8AFfd4R52fwZPnZ5H4U6DS8m/bWT8qad72NvbOFAC7U2cDtFs2TShqUO3TEiX/EJibtY3ijg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-format-url@3.972.0': + resolution: {integrity: sha512-o4zqsW/PxrcsTla/Yh2dkRS26kP76QQWZq/i/JgVNFBAr9x0E2oJcCeh8Daj2AA+8AZ8VWln9x706FFzWWQwvQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-locate-window@3.965.3': + resolution: {integrity: sha512-FNUqAjlKAGA7GM05kywE99q8wiPHPZqrzhq3wXRga6PRD6A0kzT85Pb0AzYBVTBRpSrKyyr6M92Y6bnSBVp2BA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-user-agent-browser@3.972.0': + resolution: {integrity: sha512-eOLdkQyoRbDgioTS3Orr7iVsVEutJyMZxvyZ6WAF95IrF0kfWx5Rd/KXnfbnG/VKa2CvjZiitWfouLzfVEyvJA==} + + '@aws-sdk/util-user-agent-node@3.972.0': + resolution: {integrity: sha512-GOy+AiSrE9kGiojiwlZvVVSXwylu4+fmP0MJfvras/MwP09RB/YtQuOVR1E0fKQc6OMwaTNBjgAbOEhxuWFbAw==} + engines: {node: '>=20.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.972.0': + resolution: {integrity: sha512-POaGMcXnozzqBUyJM3HLUZ9GR6OKJWPGJEmhtTnxZXt8B6JcJ/6K3xRJ5H/j8oovVLz8Wg6vFxAHv8lvuASxMg==} + engines: {node: '>=20.0.0'} + + '@aws/lambda-invoke-store@0.2.3': + resolution: {integrity: sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==} + engines: {node: '>=18.0.0'} + '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} @@ -895,6 +1078,222 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} + '@smithy/abort-controller@4.2.8': + resolution: {integrity: sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==} + engines: {node: '>=18.0.0'} + + '@smithy/chunked-blob-reader-native@4.2.1': + resolution: {integrity: sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==} + engines: {node: '>=18.0.0'} + + '@smithy/chunked-blob-reader@5.2.0': + resolution: {integrity: sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==} + engines: {node: '>=18.0.0'} + + '@smithy/config-resolver@4.4.6': + resolution: {integrity: sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==} + engines: {node: '>=18.0.0'} + + '@smithy/core@3.21.0': + resolution: {integrity: sha512-bg2TfzgsERyETAxc/Ims/eJX8eAnIeTi4r4LHpMpfF/2NyO6RsWis0rjKcCPaGksljmOb23BZRiCeT/3NvwkXw==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.2.8': + resolution: {integrity: sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-codec@4.2.8': + resolution: {integrity: sha512-jS/O5Q14UsufqoGhov7dHLOPCzkYJl9QDzusI2Psh4wyYx/izhzvX9P4D69aTxcdfVhEPhjK+wYyn/PzLjKbbw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-browser@4.2.8': + resolution: {integrity: sha512-MTfQT/CRQz5g24ayXdjg53V0mhucZth4PESoA5IhvaWVDTOQLfo8qI9vzqHcPsdd2v6sqfTYqF5L/l+pea5Uyw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-config-resolver@4.3.8': + resolution: {integrity: sha512-ah12+luBiDGzBruhu3efNy1IlbwSEdNiw8fOZksoKoWW1ZHvO/04MQsdnws/9Aj+5b0YXSSN2JXKy/ClIsW8MQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-node@4.2.8': + resolution: {integrity: sha512-cYpCpp29z6EJHa5T9WL0KAlq3SOKUQkcgSoeRfRVwjGgSFl7Uh32eYGt7IDYCX20skiEdRffyDpvF2efEZPC0A==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-universal@4.2.8': + resolution: {integrity: sha512-iJ6YNJd0bntJYnX6s52NC4WFYcZeKrPUr1Kmmr5AwZcwCSzVpS7oavAmxMR7pMq7V+D1G4s9F5NJK0xwOsKAlQ==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.3.9': + resolution: {integrity: sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-blob-browser@4.2.9': + resolution: {integrity: sha512-m80d/iicI7DlBDxyQP6Th7BW/ejDGiF0bgI754+tiwK0lgMkcaIBgvwwVc7OFbY4eUzpGtnig52MhPAEJ7iNYg==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-node@4.2.8': + resolution: {integrity: sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-stream-node@4.2.8': + resolution: {integrity: sha512-v0FLTXgHrTeheYZFGhR+ehX5qUm4IQsjAiL9qehad2cyjMWcN2QG6/4mSwbSgEQzI7jwfoXj7z4fxZUx/Mhj2w==} + engines: {node: '>=18.0.0'} + + '@smithy/invalid-dependency@4.2.8': + resolution: {integrity: sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@4.2.0': + resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==} + engines: {node: '>=18.0.0'} + + '@smithy/md5-js@4.2.8': + resolution: {integrity: sha512-oGMaLj4tVZzLi3itBa9TCswgMBr7k9b+qKYowQ6x1rTyTuO1IU2YHdHUa+891OsOH+wCsH7aTPRsTJO3RMQmjQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-content-length@4.2.8': + resolution: {integrity: sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-endpoint@4.4.10': + resolution: {integrity: sha512-kwWpNltpxrvPabnjEFvwSmA+66l6s2ReCvgVSzW/z92LU4T28fTdgZ18IdYRYOrisu2NMQ0jUndRScbO65A/zg==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.4.26': + resolution: {integrity: sha512-ozZMoTAr+B2aVYfLYfkssFvc8ZV3p/vLpVQ7/k277xxUOA9ykSPe5obL2j6yHfbdrM/SZV7qj0uk/hSqavHrLw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-serde@4.2.9': + resolution: {integrity: sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-stack@4.2.8': + resolution: {integrity: sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-config-provider@4.3.8': + resolution: {integrity: sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.4.8': + resolution: {integrity: sha512-q9u+MSbJVIJ1QmJ4+1u+cERXkrhuILCBDsJUBAW1MPE6sFonbCNaegFuwW9ll8kh5UdyY3jOkoOGlc7BesoLpg==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.2.8': + resolution: {integrity: sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@5.3.8': + resolution: {integrity: sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.2.8': + resolution: {integrity: sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-parser@4.2.8': + resolution: {integrity: sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==} + engines: {node: '>=18.0.0'} + + '@smithy/service-error-classification@4.2.8': + resolution: {integrity: sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.4.3': + resolution: {integrity: sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.3.8': + resolution: {integrity: sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.10.11': + resolution: {integrity: sha512-6o804SCyHGMXAb5mFJ+iTy9kVKv7F91a9szN0J+9X6p8A0NrdpUxdaC57aye2ipQkP2C4IAqETEpGZ0Zj77Haw==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.12.0': + resolution: {integrity: sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.2.8': + resolution: {integrity: sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-base64@4.3.0': + resolution: {integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-browser@4.2.0': + resolution: {integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-node@4.2.1': + resolution: {integrity: sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@4.2.0': + resolution: {integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==} + engines: {node: '>=18.0.0'} + + '@smithy/util-config-provider@4.2.0': + resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-browser@4.3.25': + resolution: {integrity: sha512-8ugoNMtss2dJHsXnqsibGPqoaafvWJPACmYKxJ4E6QWaDrixsAemmiMMAVbvwYadjR0H9G2+AlzsInSzRi8PSw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.2.28': + resolution: {integrity: sha512-mjUdcP8h3E0K/XvNMi9oBXRV3DMCzeRiYIieZ1LQ7jq5tu6GH/GTWym7a1xIIE0pKSoLcpGsaImuQhGPSIJzAA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.2.8': + resolution: {integrity: sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw==} + 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.8': + resolution: {integrity: sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.2.8': + resolution: {integrity: sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.5.10': + resolution: {integrity: sha512-jbqemy51UFSZSp2y0ZmRfckmrzuKww95zT9BYMmuJ8v3altGcqjwoV1tzpOwuHaKrwQrCjIzOib499ymr2f98g==} + engines: {node: '>=18.0.0'} + + '@smithy/util-uri-escape@4.2.0': + resolution: {integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.2.0': + resolution: {integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-waiter@4.2.8': + resolution: {integrity: sha512-n+lahlMWk+aejGuax7DPWtqav8HYnWxQwR+LCG2BgCUmaGcTe9qZCFsmw8TMg9iG75HOwhrJCX9TCJRLH+Yzqg==} + engines: {node: '>=18.0.0'} + + '@smithy/uuid@1.1.0': + resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} + engines: {node: '>=18.0.0'} + '@solidjs/meta@0.29.4': resolution: {integrity: sha512-zdIWBGpR9zGx1p1bzIPqF5Gs+Ks/BH8R6fWhmUa/dcK1L2rUC8BAcZJzNRYBQv74kScf1TSOs0EY//Vd/I0V8g==} peerDependencies: @@ -996,9 +1395,15 @@ packages: '@types/node@22.19.1': resolution: {integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==} + '@types/qrcode@1.5.6': + resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + '@types/throttle-debounce@5.0.2': + resolution: {integrity: sha512-pDzSNulqooSKvSNcksnV72nk8p7gRqN8As71Sp28nov1IgmPKWbOEIwAWvBME5pPTtaXJAvG3O4oc76HlQ4kqQ==} + '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -1116,6 +1521,21 @@ packages: '@vitest/utils@4.0.13': resolution: {integrity: sha512-ydozWyQ4LZuu8rLp47xFUWis5VOKMdHjXCWhs1LuJsTNKww+pTHQNK4e0assIB9K80TxFyskENL6vCu3j34EYA==} + '@vlcn.io/crsqlite-wasm@0.16.0': + resolution: {integrity: sha512-5gf52eyMYvZirxuEUo4QS65JhEsw3fndoO+tCtCEOxuiIEtvaKB2/6wuuKGRlMVkxIp4Bls70D3DCF5v9lcJxA==} + + '@vlcn.io/wa-sqlite@0.22.0': + resolution: {integrity: sha512-OujKro0mAqP7/efUeCGB6zBiyMoSCFVe7jQKPF0n47U9ZhOaIW3kQUVCwF+CmzvzQfN1Vl4PrFQRNNxlSwTCNQ==} + + '@vlcn.io/ws-client@0.2.0': + resolution: {integrity: sha512-0Nwqh/vBrKZNmRvVS2/LHUm8ssgfXbAzS5J3h3b2l9FQWDDsF3f+DfFekR/ExNagFGHEk8ZEjTQtIzj+F9doJw==} + + '@vlcn.io/ws-common@0.2.0': + resolution: {integrity: sha512-c7a470fCAzKzsjn+dchp+zAHXXem2eG2W7RxjHowZuO9PUfLjMAKp0GpZ9rsKAyLiyYRMOFAFnpl0HmFxERjig==} + + '@vlcn.io/xplat-api@0.15.0': + resolution: {integrity: sha512-2/aE7VgI3EbIO5EcJGrskAJuCa2pteY1rWNWfhovFKMERe9NhJdlDMIB1I31X0sN/WC2DnF30RqcdTXNfYyzhQ==} + abbrev@3.0.1: resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==} engines: {node: ^18.17.0 || >=20.5.0} @@ -1124,10 +1544,6 @@ packages: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} - abstract-level@3.1.1: - resolution: {integrity: sha512-CW2gKbJFTuX1feMvOrvsVMmijAOgI9kg2Ie9Dq3gOcMt/dVVoVmqNlLcEUCT13NxHFMEajcUcVBIplbyDroDiw==} - engines: {node: '>=18'} - acorn-import-attributes@1.9.5: resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} peerDependencies: @@ -1226,6 +1642,9 @@ packages: resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} hasBin: true + async-mutex@0.4.1: + resolution: {integrity: sha512-WfoBo4E/TbCX1G95XTjbWTE3X2XLG0m1Xbv2cwOtuPdyH9CZvnaA5nCt1ucjaKEgW2A5IF71hxrRhr83Je5xjA==} + async-sema@3.1.1: resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} @@ -1281,6 +1700,9 @@ packages: bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + bowser@2.13.1: + resolution: {integrity: sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==} + boxen@8.0.1: resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} engines: {node: '>=18'} @@ -1295,9 +1717,6 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browser-level@3.0.0: - resolution: {integrity: sha512-kGXtLh29jMwqKaskz5xeDLtCtN1KBz/DbQSqmvH7QdJiyGRC7RAM8PPg6gvUiNMa+wVnaxS9eSmEtP/f5ajOVw==} - browserslist@4.28.0: resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -1325,6 +1744,10 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + camelcase@8.0.0: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} @@ -1364,10 +1787,6 @@ packages: citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} - classic-level@3.0.0: - resolution: {integrity: sha512-yGy8j8LjPbN0Bh3+ygmyYvrmskVita92pD/zCoalfcC9XxZj6iDtZTAnz+ot7GG8p9KLTG+MZ84tSA4AhkgVZQ==} - engines: {node: '>=18'} - cli-boxes@3.0.0: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} @@ -1376,6 +1795,9 @@ packages: resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} engines: {node: '>=18'} + cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1391,6 +1813,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + comlink@4.4.2: + resolution: {integrity: sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==} + comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -1513,6 +1938,10 @@ packages: supports-color: optional: true + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} @@ -1565,6 +1994,9 @@ packages: resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} engines: {node: '>=0.3.1'} + dijkstrajs@1.0.3: + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} @@ -1753,6 +2185,10 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-xml-parser@5.2.5: + resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} + hasBin: true + fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -1776,6 +2212,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -1909,6 +2349,9 @@ packages: html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + html5-qrcode@2.3.8: + resolution: {integrity: sha512-jsr4vafJhwoLVEDW3n1KvPnCCXWaQfRng0/EEYk1vNcQGcG/htAdhJX0be8YyqMoSz7+hZvOZSTAepsabiuhiQ==} + http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -1980,10 +2423,6 @@ packages: iron-webcrypto@1.2.1: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} - is-buffer@2.0.5: - resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} - engines: {node: '>=4'} - is-core-module@2.16.1: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} @@ -2145,18 +2584,6 @@ packages: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} engines: {node: '>= 0.6.3'} - level-supports@6.2.0: - resolution: {integrity: sha512-QNxVXP0IRnBmMsJIh+sb2kwNCYcKciQZJEt+L1hPCHrKNELllXhvrlClVHXBYZVT+a7aTSM6StgNXdAldoab3w==} - engines: {node: '>=16'} - - level-transcoder@1.0.1: - resolution: {integrity: sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==} - engines: {node: '>=12'} - - level@10.0.0: - resolution: {integrity: sha512-aZJvdfRr/f0VBbSRF5C81FHON47ZsC2TkGxbBezXpGGXAUEL/s6+GP73nnhAYRSCIqUNsmJjfeOF4lzRDKbUig==} - engines: {node: '>=18'} - levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -2177,6 +2604,10 @@ packages: resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} engines: {node: '>=14'} + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -2221,10 +2652,6 @@ packages: magicast@0.5.1: resolution: {integrity: sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==} - maybe-combine-errors@1.0.0: - resolution: {integrity: sha512-eefp6IduNPT6fVdwPp+1NgD0PML1NU5P6j1Mj5nz1nidX8/sWY7119WL8vTAHgqfsY74TzW0w1XPgdYEKkGZ5A==} - engines: {node: '>=10'} - mdast-util-to-hast@13.2.0: resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} @@ -2314,10 +2741,6 @@ packages: mlly@1.8.0: resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} - module-error@1.0.2: - resolution: {integrity: sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==} - engines: {node: '>=10'} - ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -2334,9 +2757,6 @@ packages: engines: {node: ^18 || >=20} hasBin: true - napi-macros@2.2.2: - resolution: {integrity: sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==} - natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -2422,14 +2842,26 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -2499,6 +2931,10 @@ packages: pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -2529,6 +2965,11 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + qrcode@1.5.4: + resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} + engines: {node: '>=10.13.0'} + hasBin: true + quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} @@ -2598,6 +3039,9 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} @@ -2706,6 +3150,9 @@ packages: resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} engines: {node: '>= 18'} + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -2833,6 +3280,9 @@ packages: strip-literal@3.1.0: resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + strnum@2.1.2: + resolution: {integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==} + style-to-object@1.0.14: resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} @@ -3273,6 +3723,9 @@ packages: whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -3296,6 +3749,10 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -3327,11 +3784,8 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - y-indexeddb@9.0.12: - resolution: {integrity: sha512-9oCFRSPPzBK7/w5vOkJBaVCQZKHXB/v6SIT+WYhnJxlEC61juqG0hBrAf+y3gmSMLFLwICNH9nQ53uscuse6Hg==} - engines: {node: '>=16.0.0', npm: '>=8.0.0'} - peerDependencies: - yjs: ^13.0.0 + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} @@ -3344,18 +3798,22 @@ packages: resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} engines: {node: '>=18'} + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} - yjs@13.6.27: - resolution: {integrity: sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw==} - engines: {node: '>=16.0.0', npm: '>=8.0.0'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -3409,23 +3867,526 @@ snapshots: dependencies: json-schema: 0.4.0 - '@asamuzakjp/css-color@4.1.0': + '@asamuzakjp/css-color@4.1.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 11.2.2 + + '@asamuzakjp/dom-selector@6.7.4': + dependencies: + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.1.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.2.2 + + '@asamuzakjp/nwsapi@2.3.9': {} + + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.972.0 + tslib: 2.8.1 + + '@aws-crypto/crc32c@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.972.0 + tslib: 2.8.1 + + '@aws-crypto/sha1-browser@5.2.0': + dependencies: + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-locate-window': 3.965.3 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@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.972.0 + '@aws-sdk/util-locate-window': 3.965.3 + '@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.972.0 + tslib: 2.8.1 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.8.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/client-s3@3.972.0': + dependencies: + '@aws-crypto/sha1-browser': 5.2.0 + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/credential-provider-node': 3.972.0 + '@aws-sdk/middleware-bucket-endpoint': 3.972.0 + '@aws-sdk/middleware-expect-continue': 3.972.0 + '@aws-sdk/middleware-flexible-checksums': 3.972.0 + '@aws-sdk/middleware-host-header': 3.972.0 + '@aws-sdk/middleware-location-constraint': 3.972.0 + '@aws-sdk/middleware-logger': 3.972.0 + '@aws-sdk/middleware-recursion-detection': 3.972.0 + '@aws-sdk/middleware-sdk-s3': 3.972.0 + '@aws-sdk/middleware-ssec': 3.972.0 + '@aws-sdk/middleware-user-agent': 3.972.0 + '@aws-sdk/region-config-resolver': 3.972.0 + '@aws-sdk/signature-v4-multi-region': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-endpoints': 3.972.0 + '@aws-sdk/util-user-agent-browser': 3.972.0 + '@aws-sdk/util-user-agent-node': 3.972.0 + '@smithy/config-resolver': 4.4.6 + '@smithy/core': 3.21.0 + '@smithy/eventstream-serde-browser': 4.2.8 + '@smithy/eventstream-serde-config-resolver': 4.3.8 + '@smithy/eventstream-serde-node': 4.2.8 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/hash-blob-browser': 4.2.9 + '@smithy/hash-node': 4.2.8 + '@smithy/hash-stream-node': 4.2.8 + '@smithy/invalid-dependency': 4.2.8 + '@smithy/md5-js': 4.2.8 + '@smithy/middleware-content-length': 4.2.8 + '@smithy/middleware-endpoint': 4.4.10 + '@smithy/middleware-retry': 4.4.26 + '@smithy/middleware-serde': 4.2.9 + '@smithy/middleware-stack': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/node-http-handler': 4.4.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.10.11 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@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.25 + '@smithy/util-defaults-mode-node': 4.2.28 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/util-stream': 4.5.10 + '@smithy/util-utf8': 4.2.0 + '@smithy/util-waiter': 4.2.8 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso@3.972.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/middleware-host-header': 3.972.0 + '@aws-sdk/middleware-logger': 3.972.0 + '@aws-sdk/middleware-recursion-detection': 3.972.0 + '@aws-sdk/middleware-user-agent': 3.972.0 + '@aws-sdk/region-config-resolver': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-endpoints': 3.972.0 + '@aws-sdk/util-user-agent-browser': 3.972.0 + '@aws-sdk/util-user-agent-node': 3.972.0 + '@smithy/config-resolver': 4.4.6 + '@smithy/core': 3.21.0 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/hash-node': 4.2.8 + '@smithy/invalid-dependency': 4.2.8 + '@smithy/middleware-content-length': 4.2.8 + '@smithy/middleware-endpoint': 4.4.10 + '@smithy/middleware-retry': 4.4.26 + '@smithy/middleware-serde': 4.2.9 + '@smithy/middleware-stack': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/node-http-handler': 4.4.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.10.11 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@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.25 + '@smithy/util-defaults-mode-node': 4.2.28 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@aws-sdk/xml-builder': 3.972.0 + '@smithy/core': 3.21.0 + '@smithy/node-config-provider': 4.3.8 + '@smithy/property-provider': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/signature-v4': 5.3.8 + '@smithy/smithy-client': 4.10.11 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/crc64-nvme@3.972.0': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.972.0': + dependencies: + '@aws-sdk/core': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/property-provider': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.0': + dependencies: + '@aws-sdk/core': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/node-http-handler': 4.4.8 + '@smithy/property-provider': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.10.11 + '@smithy/types': 4.12.0 + '@smithy/util-stream': 4.5.10 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.972.0': + dependencies: + '@aws-sdk/core': 3.972.0 + '@aws-sdk/credential-provider-env': 3.972.0 + '@aws-sdk/credential-provider-http': 3.972.0 + '@aws-sdk/credential-provider-login': 3.972.0 + '@aws-sdk/credential-provider-process': 3.972.0 + '@aws-sdk/credential-provider-sso': 3.972.0 + '@aws-sdk/credential-provider-web-identity': 3.972.0 + '@aws-sdk/nested-clients': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/credential-provider-imds': 4.2.8 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-login@3.972.0': + dependencies: + '@aws-sdk/core': 3.972.0 + '@aws-sdk/nested-clients': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/property-provider': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.972.0': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.0 + '@aws-sdk/credential-provider-http': 3.972.0 + '@aws-sdk/credential-provider-ini': 3.972.0 + '@aws-sdk/credential-provider-process': 3.972.0 + '@aws-sdk/credential-provider-sso': 3.972.0 + '@aws-sdk/credential-provider-web-identity': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/credential-provider-imds': 4.2.8 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.972.0': + dependencies: + '@aws-sdk/core': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.972.0': + dependencies: + '@aws-sdk/client-sso': 3.972.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/token-providers': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.972.0': + dependencies: + '@aws-sdk/core': 3.972.0 + '@aws-sdk/nested-clients': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/middleware-bucket-endpoint@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-arn-parser': 3.972.0 + '@smithy/node-config-provider': 4.3.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-config-provider': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-expect-continue@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-flexible-checksums@3.972.0': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/crc32c': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/crc64-nvme': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/is-array-buffer': 4.2.0 + '@smithy/node-config-provider': 4.3.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-stream': 4.5.10 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-host-header@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-location-constraint@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-logger@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-recursion-detection@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@aws/lambda-invoke-store': 0.2.3 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-s3@3.972.0': + dependencies: + '@aws-sdk/core': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-arn-parser': 3.972.0 + '@smithy/core': 3.21.0 + '@smithy/node-config-provider': 4.3.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/signature-v4': 5.3.8 + '@smithy/smithy-client': 4.10.11 + '@smithy/types': 4.12.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-stream': 4.5.10 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-ssec@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-user-agent@3.972.0': + dependencies: + '@aws-sdk/core': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-endpoints': 3.972.0 + '@smithy/core': 3.21.0 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.972.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/middleware-host-header': 3.972.0 + '@aws-sdk/middleware-logger': 3.972.0 + '@aws-sdk/middleware-recursion-detection': 3.972.0 + '@aws-sdk/middleware-user-agent': 3.972.0 + '@aws-sdk/region-config-resolver': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-endpoints': 3.972.0 + '@aws-sdk/util-user-agent-browser': 3.972.0 + '@aws-sdk/util-user-agent-node': 3.972.0 + '@smithy/config-resolver': 4.4.6 + '@smithy/core': 3.21.0 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/hash-node': 4.2.8 + '@smithy/invalid-dependency': 4.2.8 + '@smithy/middleware-content-length': 4.2.8 + '@smithy/middleware-endpoint': 4.4.10 + '@smithy/middleware-retry': 4.4.26 + '@smithy/middleware-serde': 4.2.9 + '@smithy/middleware-stack': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/node-http-handler': 4.4.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.10.11 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@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.25 + '@smithy/util-defaults-mode-node': 4.2.28 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@smithy/config-resolver': 4.4.6 + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/s3-request-presigner@3.972.0': + dependencies: + '@aws-sdk/signature-v4-multi-region': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-format-url': 3.972.0 + '@smithy/middleware-endpoint': 4.4.10 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.10.11 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.972.0': + dependencies: + '@aws-sdk/middleware-sdk-s3': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/protocol-http': 5.3.8 + '@smithy/signature-v4': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.972.0': + dependencies: + '@aws-sdk/core': 3.972.0 + '@aws-sdk/nested-clients': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.972.0': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/util-arn-parser@3.972.0': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-endpoints': 3.2.8 + tslib: 2.8.1 + + '@aws-sdk/util-format-url@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@smithy/querystring-builder': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.965.3': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-browser@3.972.0': + dependencies: + '@aws-sdk/types': 3.972.0 + '@smithy/types': 4.12.0 + bowser: 2.13.1 + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-node@3.972.0': dependencies: - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - lru-cache: 11.2.2 + '@aws-sdk/middleware-user-agent': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 - '@asamuzakjp/dom-selector@6.7.4': + '@aws-sdk/xml-builder@3.972.0': dependencies: - '@asamuzakjp/nwsapi': 2.3.9 - bidi-js: 1.0.3 - css-tree: 3.1.0 - is-potential-custom-element-name: 1.0.1 - lru-cache: 11.2.2 + '@smithy/types': 4.12.0 + fast-xml-parser: 5.2.5 + tslib: 2.8.1 - '@asamuzakjp/nwsapi@2.3.9': {} + '@aws/lambda-invoke-store@0.2.3': {} '@babel/code-frame@7.26.2': dependencies: @@ -4112,6 +5073,344 @@ snapshots: '@sindresorhus/merge-streams@4.0.0': {} + '@smithy/abort-controller@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/chunked-blob-reader-native@4.2.1': + dependencies: + '@smithy/util-base64': 4.3.0 + tslib: 2.8.1 + + '@smithy/chunked-blob-reader@5.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/config-resolver@4.4.6': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + tslib: 2.8.1 + + '@smithy/core@3.21.0': + dependencies: + '@smithy/middleware-serde': 4.2.9 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-stream': 4.5.10 + '@smithy/util-utf8': 4.2.0 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.2.8': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/property-provider': 4.2.8 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + tslib: 2.8.1 + + '@smithy/eventstream-codec@4.2.8': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.12.0 + '@smithy/util-hex-encoding': 4.2.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-browser@4.2.8': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.3.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.2.8': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-universal@4.2.8': + dependencies: + '@smithy/eventstream-codec': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.3.9': + dependencies: + '@smithy/protocol-http': 5.3.8 + '@smithy/querystring-builder': 4.2.8 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + tslib: 2.8.1 + + '@smithy/hash-blob-browser@4.2.9': + dependencies: + '@smithy/chunked-blob-reader': 5.2.0 + '@smithy/chunked-blob-reader-native': 4.2.1 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/hash-node@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/hash-stream-node@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/invalid-dependency@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/is-array-buffer@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/md5-js@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/middleware-content-length@4.2.8': + dependencies: + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/middleware-endpoint@4.4.10': + dependencies: + '@smithy/core': 3.21.0 + '@smithy/middleware-serde': 4.2.9 + '@smithy/node-config-provider': 4.3.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-middleware': 4.2.8 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.4.26': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/service-error-classification': 4.2.8 + '@smithy/smithy-client': 4.10.11 + '@smithy/types': 4.12.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/middleware-serde@4.2.9': + dependencies: + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.3.8': + dependencies: + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.4.8': + dependencies: + '@smithy/abort-controller': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/querystring-builder': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/property-provider@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/protocol-http@5.3.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/querystring-builder@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/util-uri-escape': 4.2.0 + tslib: 2.8.1 + + '@smithy/querystring-parser@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/service-error-classification@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + + '@smithy/shared-ini-file-loader@4.4.3': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.3.8': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-uri-escape': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/smithy-client@4.10.11': + dependencies: + '@smithy/core': 3.21.0 + '@smithy/middleware-endpoint': 4.4.10 + '@smithy/middleware-stack': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-stream': 4.5.10 + tslib: 2.8.1 + + '@smithy/types@4.12.0': + dependencies: + tslib: 2.8.1 + + '@smithy/url-parser@4.2.8': + dependencies: + '@smithy/querystring-parser': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-base64@4.3.0': + dependencies: + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-body-length-browser@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-body-length-node@4.2.1': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-buffer-from@4.2.0': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-config-provider@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-defaults-mode-browser@4.3.25': + dependencies: + '@smithy/property-provider': 4.2.8 + '@smithy/smithy-client': 4.10.11 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-defaults-mode-node@4.2.28': + dependencies: + '@smithy/config-resolver': 4.4.6 + '@smithy/credential-provider-imds': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/property-provider': 4.2.8 + '@smithy/smithy-client': 4.10.11 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-endpoints@3.2.8': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-hex-encoding@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-middleware@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-retry@4.2.8': + dependencies: + '@smithy/service-error-classification': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-stream@4.5.10': + dependencies: + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/node-http-handler': 4.4.8 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-uri-escape@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@4.2.0': + dependencies: + '@smithy/util-buffer-from': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-waiter@4.2.8': + dependencies: + '@smithy/abort-controller': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/uuid@1.1.0': + dependencies: + tslib: 2.8.1 + '@solidjs/meta@0.29.4(solid-js@1.9.10)': dependencies: solid-js: 1.9.10 @@ -4273,8 +5572,14 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/qrcode@1.5.6': + dependencies: + '@types/node': 22.19.1 + '@types/resolve@1.20.2': {} + '@types/throttle-debounce@5.0.2': {} + '@types/unist@3.0.3': {} '@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': @@ -4476,21 +5781,33 @@ snapshots: '@vitest/pretty-format': 4.0.13 tinyrainbow: 3.0.3 + '@vlcn.io/crsqlite-wasm@0.16.0': + dependencies: + '@vlcn.io/wa-sqlite': 0.22.0 + '@vlcn.io/xplat-api': 0.15.0 + async-mutex: 0.4.1 + + '@vlcn.io/wa-sqlite@0.22.0': {} + + '@vlcn.io/ws-client@0.2.0': + dependencies: + '@types/throttle-debounce': 5.0.2 + '@vlcn.io/ws-common': 0.2.0 + + '@vlcn.io/ws-common@0.2.0': + dependencies: + lib0: 0.2.114 + + '@vlcn.io/xplat-api@0.15.0': + dependencies: + comlink: 4.4.2 + abbrev@3.0.1: {} abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 - abstract-level@3.1.1: - dependencies: - buffer: 6.0.3 - is-buffer: 2.0.5 - level-supports: 6.2.0 - level-transcoder: 1.0.1 - maybe-combine-errors: 1.0.0 - module-error: 1.0.2 - acorn-import-attributes@1.9.5(acorn@8.15.0): dependencies: acorn: 8.15.0 @@ -4588,6 +5905,10 @@ snapshots: astring@1.9.0: {} + async-mutex@0.4.1: + dependencies: + tslib: 2.8.1 + async-sema@3.1.1: {} async@3.2.6: {} @@ -4635,6 +5956,8 @@ snapshots: dependencies: file-uri-to-path: 1.0.0 + bowser@2.13.1: {} + boxen@8.0.1: dependencies: ansi-align: 3.0.1 @@ -4659,10 +5982,6 @@ snapshots: dependencies: fill-range: 7.1.1 - browser-level@3.0.0: - dependencies: - abstract-level: 3.1.1 - browserslist@4.28.0: dependencies: baseline-browser-mapping: 2.8.30 @@ -4699,6 +6018,8 @@ snapshots: callsites@3.1.0: {} + camelcase@5.3.1: {} + camelcase@8.0.0: {} caniuse-lite@1.0.30001756: {} @@ -4728,13 +6049,6 @@ snapshots: dependencies: consola: 3.4.2 - classic-level@3.0.0: - dependencies: - abstract-level: 3.1.1 - module-error: 1.0.2 - napi-macros: 2.2.2 - node-gyp-build: 4.8.4 - cli-boxes@3.0.0: {} clipboardy@4.0.0: @@ -4743,6 +6057,12 @@ snapshots: is-wsl: 3.1.0 is64bit: 2.0.0 + cliui@6.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -4757,6 +6077,8 @@ snapshots: color-name@1.1.4: {} + comlink@4.4.2: {} + comma-separated-tokens@2.0.3: {} commander@2.20.3: {} @@ -4843,6 +6165,8 @@ snapshots: dependencies: ms: 2.1.3 + decamelize@1.2.0: {} + decimal.js@10.6.0: {} deep-is@0.1.4: {} @@ -4873,6 +6197,8 @@ snapshots: diff@8.0.2: {} + dijkstrajs@1.0.3: {} + dom-accessibility-api@0.5.16: {} dom-accessibility-api@0.6.3: {} @@ -5087,6 +6413,10 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-xml-parser@5.2.5: + dependencies: + strnum: 2.1.2 + fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -5105,6 +6435,11 @@ snapshots: dependencies: to-regex-range: 5.0.1 + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -5250,6 +6585,8 @@ snapshots: html-void-elements@3.0.0: {} + html5-qrcode@2.3.8: {} + http-errors@2.0.0: dependencies: depd: 2.0.0 @@ -5333,8 +6670,6 @@ snapshots: iron-webcrypto@1.2.1: {} - is-buffer@2.0.5: {} - is-core-module@2.16.1: dependencies: hasown: 2.0.2 @@ -5470,19 +6805,6 @@ snapshots: dependencies: readable-stream: 2.3.8 - level-supports@6.2.0: {} - - level-transcoder@1.0.1: - dependencies: - buffer: 6.0.3 - module-error: 1.0.2 - - level@10.0.0: - dependencies: - abstract-level: 3.1.1 - browser-level: 3.0.0 - classic-level: 3.0.0 - levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -5521,6 +6843,10 @@ snapshots: pkg-types: 2.3.0 quansync: 0.2.11 + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -5563,8 +6889,6 @@ snapshots: '@babel/types': 7.28.5 source-map-js: 1.2.1 - maybe-combine-errors@1.0.0: {} - mdast-util-to-hast@13.2.0: dependencies: '@types/hast': 3.0.4 @@ -5650,8 +6974,6 @@ snapshots: pkg-types: 1.3.1 ufo: 1.6.1 - module-error@1.0.2: {} - ms@2.0.0: {} ms@2.1.3: {} @@ -5660,8 +6982,6 @@ snapshots: nanoid@5.1.6: {} - napi-macros@2.2.2: {} - natural-compare@1.4.0: {} nitropack@2.12.9: @@ -5837,14 +7157,24 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + p-locate@5.0.0: dependencies: p-limit: 3.1.0 + p-try@2.2.0: {} + package-json-from-dist@1.0.1: {} parent-module@1.0.1: @@ -5902,6 +7232,8 @@ snapshots: exsolve: 1.0.8 pathe: 2.0.3 + pngjs@5.0.0: {} + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -5926,6 +7258,12 @@ snapshots: punycode@2.3.1: {} + qrcode@1.5.4: + dependencies: + dijkstrajs: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + quansync@0.2.11: {} queue-microtask@1.2.3: {} @@ -6003,6 +7341,8 @@ snapshots: require-from-string@2.0.2: {} + require-main-filename@2.0.0: {} + requires-port@1.0.0: {} resolve-from@4.0.0: {} @@ -6146,6 +7486,8 @@ snapshots: transitivePeerDependencies: - supports-color + set-blocking@2.0.0: {} + setprototypeof@1.2.0: {} shebang-command@2.0.0: @@ -6277,6 +7619,8 @@ snapshots: dependencies: js-tokens: 9.0.1 + strnum@2.1.2: {} + style-to-object@1.0.14: dependencies: inline-style-parser: 0.2.7 @@ -6725,6 +8069,8 @@ snapshots: tr46: 0.0.3 webidl-conversions: 3.0.1 + which-module@2.0.1: {} + which@2.0.2: dependencies: isexe: 2.0.0 @@ -6744,6 +8090,12 @@ snapshots: word-wrap@1.2.5: {} + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -6768,10 +8120,7 @@ snapshots: xmlchars@2.2.0: {} - y-indexeddb@9.0.12(yjs@13.6.27): - dependencies: - lib0: 0.2.114 - yjs: 13.6.27 + y18n@4.0.3: {} y18n@5.0.8: {} @@ -6779,8 +8128,27 @@ snapshots: yallist@5.0.0: {} + yargs-parser@18.1.3: + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + yargs-parser@21.1.1: {} + yargs@15.4.1: + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + yargs@17.7.2: dependencies: cliui: 8.0.1 @@ -6791,10 +8159,6 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - yjs@13.6.27: - dependencies: - lib0: 0.2.114 - yocto-queue@0.1.0: {} youch-core@0.3.3: diff --git a/src/actions/syncActions.ts b/src/actions/syncActions.ts new file mode 100644 index 0000000..8958f83 --- /dev/null +++ b/src/actions/syncActions.ts @@ -0,0 +1,103 @@ +import { action } from "@solidjs/router"; +import { + S3Client, + PutObjectCommand, + GetObjectCommand, + ListObjectsV2Command, +} from "@aws-sdk/client-s3"; + +const s3Client = new S3Client({ + region: "auto", + endpoint: process.env.R2_PUBLIC_URL, + credentials: { + accessKeyId: process.env.R2_ACCESS_KEY_ID || "", + secretAccessKey: process.env.R2_SECRET_ACCESS_KEY || "", + }, +}); + +const bucketName = process.env.R2_BUCKET_NAME || "microstep-vaults"; + +export interface PresignedUploadUrl { + url: string; + key: string; +} + +export interface PresignedDownloadUrl { + url: string; + key: string; + lastModified: Date; +} + +export const generateUploadUrl = action(async ( + vaultPath: string, + deviceId: string, + timestamp: number +): Promise => { + "use server"; + const key = `${vaultPath}/${timestamp}-${deviceId}.bin`; + + const command = new PutObjectCommand({ + Bucket: bucketName, + Key: key, + ContentType: "application/octet-stream", + }); + + const url = await generatePresignedUrl(s3Client, command, { expiresIn: 300 }); + + return { url, key }; +}); + +export const listChangesets = action(async ( + vaultPath: string, + afterTimestamp?: number +): Promise => { + "use server"; + const command = new ListObjectsV2Command({ + Bucket: bucketName, + Prefix: vaultPath, + }); + + const response = await s3Client.send(command); + + const objects = response.Contents || []; + + let filteredObjects = objects; + if (afterTimestamp) { + filteredObjects = objects.filter(obj => { + const lastModified = obj.LastModified?.getTime() || 0; + return lastModified > afterTimestamp; + }); + } + + const results = await Promise.all( + filteredObjects.map(async (obj) => { + if (!obj.Key) return null; + + const key = obj.Key; + const command = new GetObjectCommand({ + Bucket: bucketName, + Key: key, + }); + + const url = await generatePresignedUrl(s3Client, command, { expiresIn: 300 }); + + return { + url, + key, + lastModified: obj.LastModified || new Date(), + }; + }) + ); + + return results.filter((url): url is PresignedDownloadUrl => url !== null); +}); + +import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; + +const generatePresignedUrl = async ( + client: S3Client, + command: PutObjectCommand | GetObjectCommand, + options: { expiresIn: number } +): Promise => { + return getSignedUrl(client, command, options); +}; diff --git a/src/actions/taskActions.ts b/src/actions/taskActions.ts index 83048ce..80d878c 100644 --- a/src/actions/taskActions.ts +++ b/src/actions/taskActions.ts @@ -13,6 +13,7 @@ export const breakdownTask = action(async (data: FormData) => { const granularity = data.get("granularity") as string; const clarification = data.get("clarification") as string | null; const hasClarification = !!clarification; + console.log("[server] breakdownTask request", { task, granularity, hasClarification }); let granularityInstruction = "Break tasks into standard, manageable chunks."; if (granularity === "low") granularityInstruction = "Keep tasks high-level and broad. Do not over-fragment."; @@ -62,9 +63,11 @@ ${ const { toolName, input } = steps[steps.length - 1].content[0]; - return { + const response = { ok: true, action: toolName, ...input - } + }; + console.log("[server] breakdownTask response", response); + return response; }, "task"); diff --git a/src/app.tsx b/src/app.tsx index 1f1bf32..21d8e53 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,10 +1,22 @@ import { MetaProvider, Title } from "@solidjs/meta"; import { Router } from "@solidjs/router"; import { FileRoutes } from "@solidjs/start/router"; -import { Suspense } from "solid-js"; +import { Suspense, onMount } from "solid-js"; +import { initializeVaultStore } from "~/stores/vaultStore"; +import { initializeTaskStore } from "~/stores/taskStore"; +import { initializeSync } from "~/lib/sync"; import "./app.css"; export default function App() { + onMount(async () => { + await initializeVaultStore(); + await initializeTaskStore(); + + if (typeof window !== "undefined") { + initializeSync(); + } + }); + return ( ( diff --git a/src/components/DevicePairing/QRDisplay.tsx b/src/components/DevicePairing/QRDisplay.tsx new file mode 100644 index 0000000..7a71329 --- /dev/null +++ b/src/components/DevicePairing/QRDisplay.tsx @@ -0,0 +1,44 @@ +import { Component, createSignal, onMount } from "solid-js"; +import QRCode from "qrcode"; +import { vaultState } from "~/stores/vaultStore"; + +export const QRDisplay: Component = () => { + const [qrDataUrl, setQrDataUrl] = createSignal(""); + const [error, setError] = createSignal(null); + + onMount(async () => { + try { + if (!vaultState.vaultKey) { + setError("No vault key available"); + return; + } + + const qrString = JSON.stringify({ + key: vaultState.vaultKey, + deviceId: vaultState.deviceId, + }); + + const dataUrl = await QRCode.toDataURL(qrString, { + width: 300, + margin: 2, + color: { + dark: "#000000", + light: "#ffffff", + }, + }); + + setQrDataUrl(dataUrl); + } catch (err) { + setError(err instanceof Error ? err.message : "Failed to generate QR code"); + } + }); + + return ( +
+ {error() &&
{error()}
} + {!error() && qrDataUrl() && ( + Vault QR Code + )} +
+ ); +}; diff --git a/src/components/DevicePairing/QRScanner.tsx b/src/components/DevicePairing/QRScanner.tsx new file mode 100644 index 0000000..2bf9783 --- /dev/null +++ b/src/components/DevicePairing/QRScanner.tsx @@ -0,0 +1,87 @@ +import { Component, createSignal, onCleanup, onMount } from "solid-js"; +import { Html5Qrcode } from "html5-qrcode"; +import { joinVault } from "~/stores/vaultStore"; + +export const QRScanner: Component = () => { + const [error, setError] = createSignal(null); + const [scanning, setScanning] = createSignal(false); + let scannerInstance: Html5Qrcode | null = null; + + const startScanning = () => { + setError(null); + setScanning(true); + + scannerInstance = new Html5Qrcode("qr-reader"); + + const config = { + fps: 10, + qrbox: { width: 250, height: 250 }, + aspectRatio: 1.0, + }; + + scannerInstance.start( + { facingMode: "environment" }, + config, + async (decodedText) => { + try { + const data = JSON.parse(decodedText); + + if (!data.key || !data.deviceId) { + throw new Error("Invalid QR code format"); + } + + await stopScanning(); + await joinVault(data.key); + + alert("Device paired successfully!"); + window.location.href = "/"; + } catch (err) { + setError(err instanceof Error ? err.message : "Invalid QR code"); + } + }, + (errorMessage) => { + // Ignore scan errors (expected while scanning) + } + ).catch((err) => { + setError(err instanceof Error ? err.message : "Failed to start camera"); + setScanning(false); + }); + }; + + const stopScanning = async () => { + if (scannerInstance && scannerInstance.isScanning) { + await scannerInstance.stop(); + setScanning(false); + } + }; + + onMount(() => { + startScanning(); + }); + + onCleanup(() => { + stopScanning(); + }); + + return ( +
+
+
+
+ {error() &&
{error()}
} + {scanning() && ( +
+ Scanning... + +
+ )} + {!scanning() && ( + + )} +
+ ); +}; diff --git a/src/components/DevicePairing/index.ts b/src/components/DevicePairing/index.ts new file mode 100644 index 0000000..3a3992b --- /dev/null +++ b/src/components/DevicePairing/index.ts @@ -0,0 +1,2 @@ +export { QRDisplay } from "./QRDisplay"; +export { QRScanner } from "./QRScanner"; diff --git a/src/components/DragProvider.tsx b/src/components/DragProvider.tsx new file mode 100644 index 0000000..4adc355 --- /dev/null +++ b/src/components/DragProvider.tsx @@ -0,0 +1,258 @@ +import { createContext, useContext, type JSX, type ParentComponent, Show, batch, onCleanup } from "solid-js"; +import { createStore } from "solid-js/store"; +import { Portal } from "solid-js/web"; + +export type DropPosition = "above" | "below" | "inside" | null; + +type DragState = { + status: "IDLE" | "PRESSED" | "DRAGGING" | "DROPPING"; + draggedId: string | null; + targetId: string | null; + dropPosition: DropPosition; + startCoord: { x: number; y: number }; + currentCoord: { x: number; y: number }; + grabOffset: { x: number; y: number }; + originalRect: DOMRect | null; +}; + +type DragContextValue = { + state: DragState; + startDrag: (event: PointerEvent, id: string, el: HTMLElement) => void; +}; + +type DragProviderProps = { + onDrop: (draggedId: string, targetId: string, position: Exclude) => void; + renderOverlay?: (id: string | null) => JSX.Element | null; +}; + +const DragContext = createContext(); + +const MOVEMENT_THRESHOLD = 5; +const HOT_ZONE = 100; + +const calculateDropPosition = (pointerY: number, rect: DOMRect): Exclude => { + const relativeY = (pointerY - rect.top) / rect.height; + if (relativeY < 0.25) return "above"; + if (relativeY > 0.75) return "below"; + return "inside"; +}; + +export const DragProvider: ParentComponent = (props) => { + const [state, setState] = createStore({ + status: "IDLE", + draggedId: null, + targetId: null, + dropPosition: null, + startCoord: { x: 0, y: 0 }, + currentCoord: { x: 0, y: 0 }, + grabOffset: { x: 0, y: 0 }, + originalRect: null, + }); + + let autoScrollFrame: number | undefined; + let announcerTimeout: number | undefined; + + const announce = (message: string) => { + const announcer = document.getElementById("dnd-announcer"); + if (!announcer) return; + announcer.textContent = message; + if (announcerTimeout) { + clearTimeout(announcerTimeout); + } + announcerTimeout = window.setTimeout(() => { + announcer.textContent = ""; + }, 800); + }; + + const startAutoScroll = () => { + const loop = () => { + if (state.status !== "DRAGGING") return; + + const { y } = state.currentCoord; + const height = window.innerHeight; + + if (y > height - HOT_ZONE) { + window.scrollBy(0, 6 + (y - (height - HOT_ZONE)) / 8); + } else if (y < HOT_ZONE) { + window.scrollBy(0, -(6 + (HOT_ZONE - y) / 8)); + } + + autoScrollFrame = requestAnimationFrame(loop); + }; + loop(); + }; + + const resetState = () => { + batch(() => { + setState({ + status: "IDLE", + draggedId: null, + targetId: null, + dropPosition: null, + startCoord: { x: 0, y: 0 }, + currentCoord: { x: 0, y: 0 }, + grabOffset: { x: 0, y: 0 }, + originalRect: null, + }); + }); + }; + + const handlePointerMove = (event: PointerEvent) => { + if (state.status === "PRESSED") { + const dist = Math.hypot( + event.clientX - state.startCoord.x, + event.clientY - state.startCoord.y, + ); + + if (dist > MOVEMENT_THRESHOLD) { + batch(() => { + setState("status", "DRAGGING"); + setState("currentCoord", { x: event.clientX, y: event.clientY }); + }); + startAutoScroll(); + announce("Dragging"); + } + return; + } + + if (state.status !== "DRAGGING") return; + + event.preventDefault(); + setState("currentCoord", { x: event.clientX, y: event.clientY }); + + const targets = document.elementsFromPoint(event.clientX, event.clientY); + const targetEl = targets.find((el) => el.hasAttribute("data-task-id")) as HTMLElement | undefined; + + if (!targetEl) { + setState("targetId", null); + setState("dropPosition", null); + return; + } + + const targetId = targetEl.getAttribute("data-task-id"); + if (!targetId || targetId === state.draggedId) return; + + const rect = targetEl.getBoundingClientRect(); + const position = calculateDropPosition(event.clientY, rect); + + batch(() => { + setState("targetId", targetId); + setState("dropPosition", position); + }); + }; + + const finishDrag = (event: PointerEvent) => { + if (autoScrollFrame) cancelAnimationFrame(autoScrollFrame); + window.removeEventListener("pointermove", handlePointerMove); + window.removeEventListener("pointerup", finishDrag); + + if (state.status === "DRAGGING" && state.targetId && state.dropPosition) { + props.onDrop(state.draggedId!, state.targetId, state.dropPosition); + } + + if (state.status === "DRAGGING") { + setState("status", "DROPPING"); + announce("Drop complete"); + window.setTimeout(resetState, 220); + } else { + resetState(); + } + + if (event.target instanceof Element) { + event.target.releasePointerCapture(event.pointerId); + } + }; + + const startDrag = (event: PointerEvent, id: string, el: HTMLElement) => { + event.preventDefault(); + event.stopPropagation(); + el.setPointerCapture(event.pointerId); + + const rect = el.closest("[data-task-id]")?.getBoundingClientRect() ?? el.getBoundingClientRect(); + + batch(() => { + setState({ + status: "PRESSED", + draggedId: id, + targetId: null, + dropPosition: null, + startCoord: { x: event.clientX, y: event.clientY }, + currentCoord: { x: event.clientX, y: event.clientY }, + grabOffset: { x: event.clientX - rect.left, y: event.clientY - rect.top }, + originalRect: rect, + }); + }); + + window.addEventListener("pointermove", handlePointerMove, { passive: false }); + window.addEventListener("pointerup", finishDrag); + }; + + onCleanup(() => { + if (autoScrollFrame) cancelAnimationFrame(autoScrollFrame); + if (announcerTimeout) clearTimeout(announcerTimeout); + window.removeEventListener("pointermove", handlePointerMove); + window.removeEventListener("pointerup", finishDrag); + }); + + const overlayStyle = () => { + if (!state.originalRect) return {}; + + const common = { + width: `${state.originalRect.width}px`, + "z-index": "9999", + "pointer-events": "none", + transition: "transform 160ms cubic-bezier(0.25, 0.9, 0.3, 1), opacity 160ms ease", + } as const; + + if (state.status === "DROPPING") { + return { + ...common, + transform: `translate3d(${state.originalRect.left}px, ${state.originalRect.top}px, 0) scale(1)`, + opacity: 0.6, + }; + } + + const x = state.currentCoord.x - state.grabOffset.x; + const y = state.currentCoord.y - state.grabOffset.y; + + return { + ...common, + transform: `translate3d(${x}px, ${y}px, 0) scale(${state.status === "PRESSED" ? 0.985 : 1.01})`, + opacity: state.status === "PRESSED" ? 0.75 : 1, + }; + }; + + return ( + + {props.children} + + +
+ + Dragging +
+ }> + {props.renderOverlay ? props.renderOverlay(state.draggedId) : null} +
+
+
+
+ + + ); +}; + +export const useDrag = () => { + const ctx = useContext(DragContext); + if (!ctx) throw new Error("useDrag must be used within DragProvider"); + return ctx; +}; diff --git a/src/components/TaskItem.css b/src/components/TaskItem.css index aba5ca8..63d93bb 100644 --- a/src/components/TaskItem.css +++ b/src/components/TaskItem.css @@ -29,6 +29,10 @@ border-color: color-mix(in srgb, var(--accent, #1a9bb2) 25%, var(--border-subtle border-radius: 12px; color: var(--muted, #5b6475); cursor: grab; + touch-action: none; + user-select: none; + display: grid; + place-items: center; } :has(input[type="checkbox"]:checked) { @@ -57,6 +61,14 @@ border-color: color-mix(in srgb, var(--accent, #1a9bb2) 25%, var(--border-subtle } } +.task-item__drag-shadow { + background: var(--surface, #fff); + border-radius: var(--radius-lg, 16px); + padding: 0.75rem 1rem; + box-shadow: 0 24px 60px -32px rgba(15, 23, 42, 0.5); + border: 1px solid var(--border-subtle, #d8e2ec); +} + .task-item__checkbox { width: 1.2rem; height: 1.2rem; diff --git a/src/components/TaskItem.tsx b/src/components/TaskItem.tsx index 58e5dcd..ca02a7d 100644 --- a/src/components/TaskItem.tsx +++ b/src/components/TaskItem.tsx @@ -4,6 +4,7 @@ import GripVertical from "lucide-solid/icons/grip-vertical"; import X from "lucide-solid/icons/x"; import { deleteTask, updateTask } from "~/stores/taskStore"; import type { Task } from "~/stores/taskStore"; +import { useDrag } from "./DragProvider"; import './TaskItem.css'; @@ -12,6 +13,7 @@ type TaskItemProps = Task & { }; export default function TaskItem(props: TaskItemProps) { + const drag = useDrag(); const [isEditing, setIsEditing] = createSignal(false); const [draft, setDraft] = createSignal(props.text); let inputRef: HTMLInputElement | undefined; @@ -42,7 +44,14 @@ export default function TaskItem(props: TaskItemProps) { return (
- + drag.startDrag(event, props.id, event.currentTarget as HTMLElement)} + > + +
(""); + const runWithTransition = async (fn: () => void | Promise) => { + const startViewTransition = (document as Document & { + startViewTransition?: (cb: () => void | Promise) => { finished: Promise }; + }).startViewTransition; + + if (startViewTransition) { + const transition = startViewTransition.call(document, () => fn()); + await transition.finished; + return; + } + + await fn(); + }; + createEffect(async () => { if (submission.result) { + console.log("[client] breakdownTask result", submission.result); switch (submission.result.action) { case "createTasks": const { tasks } = submission.result; let newTask; - let transition = document.startViewTransition(async () => { - newTask = addTask({ content: submission.result.title, dueDate: undefined }); - await transition.finished; + await runWithTransition(async () => { + newTask = await addTask({ content: submission.result.title, dueDate: undefined }); }); - console.log(newTask); + console.log("[client] root task created", newTask); + if (!newTask) return; for (const t of tasks) { - transition = document.startViewTransition(() => { - addTask(t, newTask!.id); - }); - - await transition.finished; + await runWithTransition(() => addTask(t, newTask.id)); } + console.log("[client] subtasks added", tasks.length); break; case "askClarification": setMode("clarify"); @@ -50,7 +62,13 @@ export default function TaskPrompt() { let textareaRef: HTMLTextAreaElement | undefined; return ( -
+ { + console.log("[client] submitting breakdownTask", { granularity: granularity() }); + }} + >
diff --git a/src/components/TasksList.css b/src/components/TasksList.css index c89c820..a9528fc 100644 --- a/src/components/TasksList.css +++ b/src/components/TasksList.css @@ -12,17 +12,59 @@ width: 100%; margin: 0; padding: 0; + gap: 0.5rem; } .task-node { position: relative; display: flex; flex-direction: column; - gap: 0.6rem; + gap: 0; + transition: transform 200ms ease, opacity 180ms ease; + /* Create local stacking context to prevent shelf overlap with siblings */ + z-index: 1; +} + +/* Ensure expanded node is above siblings during animation */ +.task-node.is-expanded { + z-index: 2; +} + +.task-node.is-dragged .task-item { + opacity: 0.35; +} + +.task-node.is-drop-target.drop-inside .task-item { + outline: 2px solid var(--accent, #1a9bb2); + outline-offset: 2px; + background: color-mix(in srgb, var(--accent-soft, #e6f5f7) 70%, #fff); + transform: scale(1.005); +} + +.task-node.is-drop-target.drop-above::before, +.task-node.is-drop-target.drop-below::after { + content: ""; + position: absolute; + left: 12px; + right: 12px; + height: 2px; + background: var(--accent, #1a9bb2); + border-radius: 999px; + z-index: 10; +} + +.task-node.is-drop-target.drop-above::before { + top: -6px; +} + +.task-node.is-drop-target.drop-below::after { + bottom: -6px; } .task-node__card { position: relative; + /* Ensure card content is above shelf */ + z-index: 2; } .task-node__card .task-item { @@ -50,14 +92,14 @@ position: absolute; left: 1.75%; width: 96.5%; - height: 40px; + height: 100%; background: var(--surface, #fff); border: 1px solid var(--border-subtle, #d8e2ec); border-radius: var(--radius-lg, 16px); box-shadow: var(--card-shadow, 0 24px 60px -38px rgba(15, 23, 42, 0.52)); transform-origin: top center; transition: - transform 360ms cubic-bezier(0.175, 0.885, 0.32, 1.275), + transform 300ms cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 200ms ease, border-color 160ms ease; @@ -89,33 +131,49 @@ .task-node.is-expanded .shelf-card { opacity: 0; - transform: translateY(0) scale(1); + /* Slide slightly up to "hide" behind the main card as it opens */ + transform: translateY(2px) scale(0.98); + transition: transform 200ms ease, opacity 150ms ease; } -.node-children { - display: grid; - grid-template-rows: 0fr; - transition: grid-template-rows 360ms ease; +.node-children-wrapper { + position: relative; margin-left: 22px; padding-left: 14px; - position: relative; + /* Animate the margin/spacing if needed, but keeping it static is safer for layout stability */ + margin-top: 0; + transition: margin-top 360ms cubic-bezier(0.4, 0, 0.2, 1); +} + +.task-node.is-expanded > .node-children-wrapper { + margin-top: 16px; +} + +.node-children-animator { + /* Grid trick for height animation */ + display: grid; + grid-template-rows: 0fr; + transition: grid-template-rows 360ms cubic-bezier(0.4, 0, 0.2, 1); + /* Overflow hidden is required for the grid animation to clip content */ + overflow: hidden; } .spine-line { position: absolute; left: 0; - top: 0; - bottom: 12px; + top: -12px; /* Connect to parent */ + bottom: 10px; /* Don't go all the way down */ width: 2px; background: var(--border-subtle, #d8e2ec); + border-radius: 2px; opacity: 0; transition: opacity 200ms ease; } .spine-tab { position: absolute; - left: -10px; - top: -12px; + left: -11px; + top: -14px; width: 24px; height: 24px; padding: 0; @@ -129,7 +187,8 @@ opacity: 0; transform: scale(0.8); transition: all 260ms cubic-bezier(0.175, 0.885, 0.32, 1.275); - z-index: 3; + z-index: 5; + box-shadow: 0 2px 4px rgba(0,0,0,0.05); } .spine-tab:hover { @@ -139,31 +198,33 @@ } .node-children-inner { - overflow: hidden; + min-height: 0; + /* Removed overflow: hidden to prevent clipping of nested shadows/items */ opacity: 0; - transform: translateY(-8px); + transform: translateY(-10px); transition: opacity 200ms ease, transform 200ms ease; display: flex; flex-direction: column; gap: 0.8rem; pointer-events: none; + padding-top: 0.25rem; + padding-bottom: 0.5rem; /* Ensure shadows aren't clipped by parent */ } -.task-node.is-expanded > .node-children { +.task-node.is-expanded .node-children-animator { grid-template-rows: 1fr; - margin-top: 12px; } -.task-node.is-expanded > .node-children .spine-line { +.task-node.is-expanded .spine-line { opacity: 1; } -.task-node.is-expanded > .node-children .spine-tab { +.task-node.is-expanded .spine-tab { opacity: 1; transform: scale(1); } -.task-node.is-expanded > .node-children > .node-children-inner { +.task-node.is-expanded .node-children-inner { opacity: 1; transform: translateY(0); pointer-events: auto; @@ -173,3 +234,36 @@ opacity: 0.85; transform: scale(0.98); } + +.drag-overlay__card { + background: var(--surface, #fff); + border-radius: var(--radius-lg, 16px); + border: 1px solid var(--border-subtle, #d8e2ec); + box-shadow: var(--card-shadow, 0 24px 60px -38px rgba(15, 23, 42, 0.52)); + padding: 0.75rem 1rem; + animation: float-lift 160ms ease both; + z-index: 100; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + +@keyframes float-lift { + from { + opacity: 0.4; + transform: scale(0.98); + } + to { + opacity: 1; + transform: scale(1); + } +} diff --git a/src/components/TasksList.tsx b/src/components/TasksList.tsx index d04395c..963c3f2 100644 --- a/src/components/TasksList.tsx +++ b/src/components/TasksList.tsx @@ -3,7 +3,8 @@ import { createStore } from "solid-js/store"; import { clientOnly } from "@solidjs/start"; import Minus from "lucide-solid/icons/minus"; import TaskItem from "./TaskItem"; -import { type TreeNode } from "~/stores/taskStore"; +import { DragProvider, useDrag, type DropPosition } from "./DragProvider"; +import { moveTask, tasks as tasksStore, type TreeNode } from "~/stores/taskStore"; import './TasksList.css'; export default clientOnly(async () => ({ default: TasksList }), { lazy: true }); @@ -23,17 +24,100 @@ type ExpansionState = { function TasksList(props: TasksListProps) { const [expandedMap, setExpandedMap] = createStore>({}); + const handleDrop = (draggedId: string, targetId: string, position: Exclude) => { + const tree = tasksStore(); + + const nodeIndex = new Map(); + const parentIndex = new Map(); + + const indexTree = (nodes: TreeNode[], parentId: string | null) => { + nodes.forEach(node => { + nodeIndex.set(node.id, node); + parentIndex.set(node.id, parentId); + indexTree(node.children, node.id); + }); + }; + + indexTree(tree, null); + + const draggedNode = nodeIndex.get(draggedId); + const targetNode = nodeIndex.get(targetId); + + if (!draggedNode || !targetNode || draggedId === targetId) return; + + const isDescendant = (candidateId: string, ancestorId: string) => { + let current: string | null | undefined = candidateId; + while (current) { + const parent = parentIndex.get(current); + if (!parent) return false; + if (parent === ancestorId) return true; + current = parent; + } + return false; + }; + + if (isDescendant(targetId, draggedId)) return; // Prevent dropping into own subtree + + const getSiblings = (parentId: string | null) => { + if (parentId === null) return tree; + const parentNode = nodeIndex.get(parentId); + return parentNode ? parentNode.children : []; + }; + + if (position === "inside") { + const siblings = targetNode.children.filter(child => child.id !== draggedId); + const last = siblings[siblings.length - 1]; + moveTask(draggedId, targetId, last?.rank, undefined); + return; + } + + const newParentId = parentIndex.get(targetId) ?? null; + const siblings = getSiblings(newParentId).filter(child => child.id !== draggedId); + const targetIndex = siblings.findIndex(child => child.id === targetId); + if (targetIndex === -1) return; + + const insertIndex = position === "above" ? targetIndex : targetIndex + 1; + const prev = siblings[insertIndex - 1]; + const next = siblings[insertIndex]; + + moveTask(draggedId, newParentId, prev?.rank, next?.rank); + }; + + const renderOverlay = (id: string | null) => { + if (!id) return null; + + const findNode = (nodes: TreeNode[]): TreeNode | undefined => { + for (const node of nodes) { + if (node.id === id) return node; + const nested = findNode(node.children); + if (nested) return nested; + } + return undefined; + }; + + const node = findNode(tasksStore()); + if (!node) return null; + + return ( +
+ {node.text} +
+ ); + }; + const expansion: ExpansionState = { isExpanded: (id) => expandedMap[id] ?? !!props.defaultExpanded, setExpanded: (id, value) => setExpandedMap(id, value), }; return ( - + + + ); } @@ -67,8 +151,11 @@ type TaskNodeProps = { }; function TaskNode(props: TaskNodeProps) { + const drag = useDrag(); const isExpanded = () => props.expansion.isExpanded(props.node.id); const hasChildren = () => props.node.children.length > 0; + const isDragged = () => drag.state.draggedId === props.node.id; + const isTarget = () => drag.state.targetId === props.node.id; const expand = () => { if (hasChildren()) { @@ -84,7 +171,13 @@ function TaskNode(props: TaskNodeProps) { classList={{ "is-expanded": isExpanded(), "has-children": hasChildren(), + "is-dragged": isDragged(), + "is-drop-target": isTarget(), + "drop-above": isTarget() && drag.state.dropPosition === "above", + "drop-below": isTarget() && drag.state.dropPosition === "below", + "drop-inside": isTarget() && drag.state.dropPosition === "inside", }} + data-task-id={props.node.id} >
@@ -104,7 +197,7 @@ function TaskNode(props: TaskNodeProps) {
-
+