diff --git a/.env.example b/.env.example index de3201c..6de9bea 100644 --- a/.env.example +++ b/.env.example @@ -2,3 +2,8 @@ PUBLIC_SUPABASE_URL=your_supabase_url PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key GOOGLE_API_KEY=your_google_api_key + +# Google Service Account for Calendar push (create/update/delete events) +# Paste the full JSON key file contents, or base64-encode it +# The calendar must be shared with the service account email (with "Make changes to events" permission) +GOOGLE_SERVICE_ACCOUNT_KEY= diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0858e58 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + ci: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Lint (svelte-check) + run: npm run check + + - name: Unit tests + run: npx vitest run --project server + + - name: Build + run: npm run build diff --git a/.gitignore b/.gitignore index 48052c3..8ee777b 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,8 @@ lerna-debug.log* coverage .nyc_output *.lcov +tests/e2e/.auth/ +test-results/ # Typescript *.tsbuildinfo @@ -89,3 +91,6 @@ supabase/.temp # Sentry .sentryclirc +# Paraglide +src/lib/paraglide +project.inlang/cache/ diff --git a/AUDIT.md b/AUDIT.md index f92ea16..c1eb398 100644 --- a/AUDIT.md +++ b/AUDIT.md @@ -1,10 +1,12 @@ -# Comprehensive Codebase Audit Report (v2) +# Comprehensive Codebase Audit Report (v4) **Project:** root-org (SvelteKit + Supabase + Tailwind v4) -**Date:** 2026-02-06 (updated) +**Date:** 2026-02-06 (v4 update) **Auditor:** Cascade > **Changes since v1:** Dead stores (auth, organizations, documents, kanban, theme) deleted. `OrgWithRole` moved to `$lib/api/organizations.ts`. `FileTree` removed. Documents pages refactored into shared `FileBrowser` component. Document locking added (`document-locks` API + migration). Calendar `$derived` bugs fixed. `buildDocumentTree`/`DocumentWithChildren` removed. Editor CSS typo fixed. Invite page routes corrected. KanbanBoard button label fixed. +> +> **Changes in v4:** Type safety (shared `OrgLayoutData`, `as any` casts fixed, `role`→`userRole` dedup). Architecture (settings page split into 4 components, FileBrowser migrated to API modules, `createDocument` supports kanban). Performance (folder listings exclude content, kanban queries parallelized, card moves batched, realtime incremental). Testing (43 unit tests, expanded E2E coverage, GitHub Actions CI). --- @@ -657,10 +659,84 @@ expires_at: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(), 3. **Continue splitting settings page** (A-1) — Members, Roles, and Integrations tabs still inline. Extract each into its own component. -### Suggested Order of Operations (updated) +### Resolved Since v3 -1. **Immediate (security):** S-1 (rotate keys — manual), S-4 (server-side auth for settings mutations) -2. **Type safety (1 hour):** T-1 (regenerate Supabase types), T-2→T-5 (fix remaining type issues) -3. **Architecture (1-2 days):** A-1 (finish splitting settings tabs), A-2 (migrate FileBrowser to use API modules), A-3 (add kanban type to createDocument) -4. **Performance (1 day):** P-1 (select only needed columns), P-2 (parallelize kanban queries), P-4 (incremental realtime updates) -5. **Polish:** E-5 (reliable lock release), M-1→M-3 (constants, consistent patterns), F-1 (permission enforcement), F-2 (scoped subscriptions) +| ID | Issue | Resolution | +|----|-------|------------| +| — | Icon buttons not round | All inline icon buttons (`rounded-lg`) changed to `rounded-full` across KanbanCard, KanbanBoard, DocumentViewer, Calendar, Modal, ContextMenu | +| — | Add column/card buttons missing plus icon | Replaced inline buttons with `Button` component using `icon="add"` prop | +| — | Kanban columns not reorderable | Added column drag-and-drop with grip handle, drop indicators, and DB persistence | +| — | Inconsistent cursor styles | Added global CSS rules: `cursor-pointer` on all `button`/`a`/`[role="button"]`, `cursor-grab` on `[draggable="true"]` | +| — | Blurred spinner loading overlay | Replaced `backdrop-blur-sm` spinner with context-aware `PageSkeleton` component (kanban/files/calendar/settings/default variants) | +| — | Language switcher missing | Added locale picker (English/Eesti) to account settings using Paraglide `setLocale()` | +| — | File browser view mode not persisted | Confirmed already working via `localStorage` (`root:viewMode` key) | + +### Resolved Since v4 + +| ID | Issue | Resolution | +|----|-------|------------| +| T-1 | 2 remaining `as any` casts | Replaced with properly typed casts in invite page and CardDetailModal | +| T-2→T-5 | Untyped parent layout data | Created shared `OrgLayoutData` type in `$lib/types/layout.ts`; applied across all 8 page servers | +| R-4 | Duplicate `role`/`userRole` | Removed `role` from layout server return; migrated all consumers to `userRole` | +| A-1 | Settings page god component (1200+ lines) | Extracted `SettingsMembers`, `SettingsRoles`, `SettingsIntegrations` into `$lib/components/settings/`; page reduced to ~470 lines | +| A-2 | FileBrowser direct Supabase calls | Migrated all CRUD operations to use `$lib/api/documents.ts` (`moveDocument`, `updateDocument`, `deleteDocument`, `createDocument`, `copyDocument`) | +| A-3 | `createDocument` missing kanban type | Added `'kanban'` to type union with optional `id` and `content` params | +| E-3 | Calendar date click no-op | Already implemented — clicking a day opens create event modal pre-filled with date | +| P-1 | Folder listings fetch `select('*')` | Changed to select only metadata columns, excluding heavy `content` JSON | +| P-2 | Kanban queries sequential | Board+columns now fetched in parallel; tags+checklists+assignees fetched in parallel | +| P-3 | `moveCard` fires N updates | Now skips cards whose position didn't change — typically 2-3 updates instead of N | +| P-4 | Realtime full board reload | Upgraded `subscribeToBoard` to pass granular payloads; kanban page applies INSERT/UPDATE/DELETE diffs incrementally | +| T6 | No unit tests | Added 43 Vitest unit tests: `logger.test.ts` (10), `google-calendar.test.ts` (11), `calendar.test.ts` (12), `documents.test.ts` (10) | +| T6 | Incomplete E2E coverage | Added Playwright tests for Tags tab, calendar CRUD (create/view/delete), kanban card CRUD (create/detail modal) | +| T6 | No CI pipeline | Created `.github/workflows/ci.yml`: lint → check → unit tests → build | +| T6 | Test cleanup incomplete | Updated `cleanup.ts` to handle test tags, calendar events, and new board prefixes | + +--- + +## Area Scores (v4) + +Scores reflect the current state of the codebase after all v1–v4 fixes. + +| Area | Score | Notes | +|------|-------|-------| +| **Security** | ⭐⭐⭐ 3/5 | S-2, S-3, S-5 fixed. **S-1 (credential rotation) and S-4 (server-side auth for mutations) remain critical/high.** S-6 (lock cleanup race) still open. | +| **Type Safety** | ⭐⭐⭐⭐ 4/5 | `OrgLayoutData` shared type eliminates parent casts. 2 targeted `as any` casts fixed. Remaining `as any` casts are in Supabase join results that need full type regeneration (T-1). | +| **Dead Code** | ⭐⭐⭐⭐⭐ 5/5 | All dead stores, unused components, placeholder tests, empty files, and unused dependencies removed in v2. No known dead code remains. | +| **Architecture** | ⭐⭐⭐⭐ 4/5 | Settings page split into 4 components. FileBrowser migrated to API modules. `createDocument` supports all types. Remaining: some components still have inline Supabase calls (CardDetailModal, CardComments). | +| **Performance** | ⭐⭐⭐⭐ 4/5 | Folder listings exclude content. Kanban queries parallelized. Card moves batched smartly. Realtime is incremental. Remaining: full org document fetch for breadcrumbs could be optimized further. | +| **Error Handling** | ⭐⭐⭐⭐ 4/5 | `alert()` replaced with toasts. Structured logger adopted in API routes. `$effect` sync blocks added. Remaining: `console.error` in 3-4 files (calendar page, invite page), lock release in `onDestroy`. | +| **Testing** | ⭐⭐⭐⭐ 4/5 | 43 unit tests (logger, calendar, google-calendar, documents API). 35+ Playwright E2E tests covering all major flows. CI pipeline on GitHub Actions. Remaining: visual regression tests, Svelte component tests. | +| **Code Quality** | ⭐⭐⭐⭐ 4/5 | Consistent API module pattern. Shared types. i18n complete. Duplication eliminated. Remaining: `role`/`userRole` fully migrated but some inline SVGs and magic numbers persist. | +| **Dependencies** | ⭐⭐⭐⭐⭐ 5/5 | `lucide-svelte` removed. All deps actively used. No known unused packages. | +| **Future-Proofing** | ⭐⭐⭐ 3/5 | Permission system defined but not enforced (F-1). Kanban realtime subscription unscoped (F-2). No search, notifications, or keyboard shortcuts yet. | + +### Overall Score: ⭐⭐⭐⭐ 4.0 / 5 + +**Breakdown:** 41 out of 50 possible stars across 10 areas. + +### Remaining High-Priority Items + +1. **S-1: Rotate credentials & purge `.env` from git history** — Critical security risk. Must be done manually. +2. **S-4: Server-side auth for settings mutations** — Move destructive operations to SvelteKit form actions with explicit authorization. +3. **T-1: Regenerate Supabase types** — `supabase gen types typescript` to eliminate remaining `as any` casts from join results. +4. **F-1: Permission enforcement** — Create `hasPermission()` utility; the permission system is defined but never checked. + +### Remaining Medium-Priority Items + +5. **S-6: Lock cleanup race condition** — Consolidate to server-side cron only. +6. **E-2: Replace remaining `console.*` calls** — 3-4 files still use raw console instead of structured logger. +7. **E-5: Lock release in `onDestroy`** — Use `navigator.sendBeacon` for reliable cleanup. +8. **F-2: Scoped realtime subscriptions** — Filter kanban card changes to current board's columns. +9. **M-1/M-3: Magic numbers and inline SVGs** — Extract constants, use Icon component consistently. + +### Feature Backlog (Tier 5) + +10. Notifications system (mentions, assignments, due dates) +11. Global search across documents, kanban cards, calendar events +12. Keyboard shortcuts for common actions +13. Mobile responsive layout (sidebar drawer, touch-friendly kanban) +14. Dark/light theme toggle +15. Export/import (CSV/JSON/Markdown) +16. Undo/redo with toast-based undo for destructive actions +17. Onboarding flow for new users +18. Visual regression tests for key pages diff --git a/messages/en.json b/messages/en.json new file mode 100644 index 0000000..bdd2a21 --- /dev/null +++ b/messages/en.json @@ -0,0 +1,255 @@ +{ + "$schema": "https://inlang.com/schema/inlang-message-format", + "app_name": "Root", + "nav_files": "Files", + "nav_calendar": "Calendar", + "nav_settings": "Settings", + "nav_kanban": "Kanban", + "user_menu_account_settings": "Account Settings", + "user_menu_switch_org": "Switch Organization", + "user_menu_logout": "Log Out", + "btn_new": "+ New", + "btn_create": "Create", + "btn_cancel": "Cancel", + "btn_save": "Save", + "btn_delete": "Delete", + "btn_edit": "Edit", + "btn_close": "Close", + "btn_upload": "Upload", + "btn_remove": "Remove", + "login_title": "Welcome to Root", + "login_subtitle": "Your team's workspace for docs, boards, and calendars.", + "login_tab_login": "Log In", + "login_tab_signup": "Sign Up", + "login_email_label": "Email", + "login_email_placeholder": "you@example.com", + "login_password_label": "Password", + "login_password_placeholder": "••••••••", + "login_btn_login": "Log In", + "login_btn_signup": "Sign Up", + "login_or_continue": "or continue with", + "login_google": "Continue with Google", + "login_signup_prompt": "Don't have an account?", + "login_login_prompt": "Already have an account?", + "login_signup_success_title": "Check your email", + "login_signup_success_text": "We sent a confirmation link to {email}. Click it to activate your account.", + "org_selector_title": "Your Organizations", + "org_selector_create": "Create Organization", + "org_selector_create_title": "Create Organization", + "org_selector_name_label": "Organization Name", + "org_selector_name_placeholder": "My Team", + "org_selector_slug_label": "URL Slug", + "org_selector_slug_placeholder": "my-team", + "org_overview": "Organization Overview", + "files_title": "Files", + "files_breadcrumb_home": "Home", + "files_create_title": "Create New", + "files_type_document": "Document", + "files_type_folder": "Folder", + "files_type_kanban": "Kanban", + "files_name_label": "Name", + "files_doc_placeholder": "Document name", + "files_folder_placeholder": "Folder name", + "files_kanban_placeholder": "Kanban board name", + "files_rename_title": "Rename", + "files_context_rename": "Rename", + "files_context_move": "Move to...", + "files_context_delete": "Delete", + "files_context_open_tab": "Open in new tab", + "files_empty": "No files yet. Click + New to create one.", + "files_toggle_view": "Toggle view", + "kanban_title": "Kanban", + "kanban_create_board": "Create Board", + "kanban_board_name_label": "Board Name", + "kanban_board_name_placeholder": "e.g. Sprint 1", + "kanban_edit_board": "Edit Board", + "kanban_rename_board": "Rename Board", + "kanban_delete_board": "Delete Board", + "kanban_add_column": "Add Column", + "kanban_column_name_label": "Column Name", + "kanban_column_name_placeholder": "e.g. To Do, In Progress, Done", + "kanban_add_card": "Add Card", + "kanban_card_details": "Card Details", + "kanban_card_title_label": "Title", + "kanban_card_title_placeholder": "Card title", + "kanban_card_desc_label": "Description", + "kanban_card_desc_placeholder": "Add a more detailed description...", + "kanban_tags": "Tags", + "kanban_tag_placeholder": "Tag name", + "kanban_tag_add": "Add", + "kanban_empty": "Kanban boards are now managed in Files", + "kanban_go_to_files": "Go to Files", + "kanban_select_board": "Select a board above", + "calendar_title": "Calendar", + "calendar_subscribe": "Subscribe to Calendar", + "calendar_refresh": "Refresh Events", + "calendar_settings": "Calendar Settings", + "calendar_create_event": "Create Event", + "calendar_edit_event": "Edit Event", + "calendar_event_title": "Title", + "calendar_event_title_placeholder": "Event title", + "calendar_event_date": "Date", + "calendar_event_time": "Time", + "calendar_event_desc": "Description", + "settings_title": "Settings", + "settings_tab_general": "General", + "settings_tab_members": "Members", + "settings_tab_roles": "Roles", + "settings_tab_tags": "Tags", + "settings_tab_integrations": "Integrations", + "settings_general_title": "Organization details", + "settings_general_avatar": "Avatar", + "settings_general_name": "Name", + "settings_general_name_placeholder": "Organization name", + "settings_general_slug": "URL slug (yoursite.com/...)", + "settings_general_slug_placeholder": "my-org", + "settings_general_save": "Save Changes", + "settings_general_danger_zone": "Danger Zone", + "settings_general_delete_org": "Delete Organization", + "settings_general_delete_org_desc": "Permanently delete this organization and all its data.", + "settings_general_leave_org": "Leave Organization", + "settings_general_leave_org_desc": "Leave this organization. You will need to be re-invited to rejoin.", + "settings_general_leave_btn": "Leave {orgName}", + "settings_tags_title": "Organization Tags", + "settings_tags_desc": "Manage tags that can be used across all Kanban boards.", + "settings_tags_create": "Create Tag", + "settings_tags_empty": "No tags yet. Create your first tag to organize Kanban cards.", + "settings_tags_name_placeholder": "Tag name", + "settings_members_title": "Team Members ({count})", + "settings_members_invite": "Invite Member", + "settings_members_pending": "Pending Invites", + "settings_members_invited_as": "Invited as {role} • Expires {date}", + "settings_members_copy_link": "Copy Link", + "settings_members_unknown": "Unknown User", + "settings_members_no_name": "No name", + "settings_members_no_email": "No email", + "settings_members_remove": "Remove from Org", + "settings_invite_title": "Invite Member", + "settings_invite_email": "Email address", + "settings_invite_email_placeholder": "colleague@example.com", + "settings_invite_role": "Role", + "settings_invite_send": "Send Invite", + "settings_invite_role_viewer": "Viewer - Can view content", + "settings_invite_role_commenter": "Commenter - Can view and comment", + "settings_invite_role_editor": "Editor - Can create and edit content", + "settings_invite_role_admin": "Admin - Can manage members and settings", + "settings_edit_member": "Edit Member", + "settings_roles_title": "Roles", + "settings_roles_desc": "Create custom roles with specific permissions.", + "settings_roles_create": "Create Role", + "settings_roles_edit": "Edit Role", + "settings_roles_system": "System", + "settings_roles_default": "Default", + "settings_roles_all_perms": "All Permissions", + "settings_roles_more": "+{count} more", + "settings_roles_name_label": "Name", + "settings_roles_name_placeholder": "e.g., Moderator", + "settings_roles_color": "Color", + "settings_roles_permissions": "Permissions", + "settings_integrations_google_cal": "Google Calendar", + "settings_integrations_google_cal_desc": "Share a Google Calendar with all organization members.", + "settings_integrations_connected": "Connected", + "settings_integrations_disconnect": "Disconnect", + "settings_integrations_connect": "Connect Google Calendar", + "settings_integrations_discord": "Discord", + "settings_integrations_discord_desc": "Get notifications in your Discord server.", + "settings_integrations_slack": "Slack", + "settings_integrations_slack_desc": "Get notifications in your Slack workspace.", + "settings_integrations_coming_soon": "Coming soon", + "settings_connect_cal_title": "Connect Public Google Calendar", + "settings_connect_cal_desc": "Paste your Google Calendar's shareable link or calendar ID. The calendar must be set to public in Google Calendar settings.", + "settings_connect_cal_how": "How to get your calendar link:", + "settings_connect_cal_step1": "Open Google Calendar", + "settings_connect_cal_step2": "Click the 3 dots next to your calendar → Settings", + "settings_connect_cal_step3": "Under \"Access permissions\", check \"Make available to public\"", + "settings_connect_cal_step4": "Scroll to \"Integrate calendar\" and copy the Calendar ID or Public URL", + "settings_connect_cal_input_label": "Calendar URL or ID", + "settings_connect_cal_input_placeholder": "Paste calendar URL or ID (e.g., abc123@group.calendar.google.com)", + "settings_connect_cal_btn": "Connect", + "account_title": "Account Settings", + "account_subtitle": "Manage your personal profile and preferences.", + "account_profile": "Profile", + "account_photo": "Photo", + "account_sync_google": "Sync Google", + "account_remove_photo": "Remove photo", + "account_display_name": "Display Name", + "account_display_name_placeholder": "Your name", + "account_email": "Email", + "account_save_profile": "Save Profile", + "account_appearance": "Appearance", + "account_theme": "Theme", + "account_theme_dark": "Dark", + "account_theme_light": "Light (Coming Soon)", + "account_theme_system": "System (Coming Soon)", + "account_accent_color": "Accent Color", + "account_use_org_theme": "Use Organization Theme", + "account_use_org_theme_desc": "Override your personal theme with the org's settings.", + "account_language": "Language", + "account_language_desc": "Choose your preferred language for the interface.", + "account_save_preferences": "Save Preferences", + "account_security": "Security & Sessions", + "account_password": "Password", + "account_password_desc": "If you signed in with Google, your password is managed by Google. Otherwise, you can reset your password via email.", + "account_send_reset": "Send Reset Email", + "account_active_sessions": "Active Sessions", + "account_sessions_desc": "Sign out of all other sessions if you suspect unauthorized access.", + "account_signout_others": "Sign Out Other Sessions", + "editor_save": "Save", + "editor_saving": "Saving...", + "editor_saved": "Saved", + "editor_error": "Error", + "editor_placeholder": "Start writing...", + "editor_bold": "Bold (Ctrl+B)", + "editor_italic": "Italic (Ctrl+I)", + "editor_strikethrough": "Strikethrough", + "editor_bullet_list": "Bullet List", + "editor_numbered_list": "Numbered List", + "editor_quote": "Quote", + "editor_code_block": "Code Block", + "toast_error_delete_org": "Failed to delete organization.", + "toast_error_leave_org": "Failed to leave organization.", + "toast_error_invite": "Failed to send invite: {error}", + "toast_error_update_role": "Failed to update role.", + "toast_error_remove_member": "Failed to remove member.", + "toast_error_delete_role": "Failed to delete role.", + "toast_error_disconnect_cal": "Failed to disconnect calendar.", + "toast_error_reset_email": "Failed to send reset email.", + "toast_success_reset_email": "Password reset email sent.", + "toast_success_signout_others": "Other sessions signed out.", + "confirm_delete_role": "Delete role \"{name}\"? Members with this role will need to be reassigned.", + "confirm_leave_org": "Are you sure you want to leave {orgName}?", + "confirm_delete_org": "Type \"{orgName}\" to confirm deletion:", + "confirm_remove_member": "Remove {name} from the organization?", + "confirm_disconnect_cal": "Disconnect Google Calendar?", + "role_viewer": "Viewer", + "role_commenter": "Commenter", + "role_editor": "Editor", + "role_admin": "Admin", + "role_owner": "Owner", + "error_owner_cant_leave": "Owners cannot leave. Transfer ownership first or delete the organization.", + "overview_title": "Organization Overview", + "overview_stat_members": "Members", + "overview_stat_documents": "Documents", + "overview_stat_folders": "Folders", + "overview_stat_boards": "Boards", + "overview_quick_links": "Quick Links", + "activity_title": "Recent Activity", + "activity_empty": "No recent activity yet.", + "activity_created": "{user} created {entityType} \"{name}\"", + "activity_updated": "{user} updated {entityType} \"{name}\"", + "activity_deleted": "{user} deleted {entityType} \"{name}\"", + "activity_moved": "{user} moved {entityType} \"{name}\"", + "activity_renamed": "{user} renamed {entityType} \"{name}\"", + "activity_just_now": "Just now", + "activity_minutes_ago": "{count}m ago", + "activity_hours_ago": "{count}h ago", + "activity_days_ago": "{count}d ago", + "entity_document": "document", + "entity_folder": "folder", + "entity_kanban_board": "board", + "entity_kanban_card": "card", + "entity_kanban_column": "column", + "entity_member": "member", + "entity_role": "role", + "entity_invite": "invite" +} \ No newline at end of file diff --git a/messages/et.json b/messages/et.json new file mode 100644 index 0000000..deba226 --- /dev/null +++ b/messages/et.json @@ -0,0 +1,255 @@ +{ + "$schema": "https://inlang.com/schema/inlang-message-format", + "app_name": "Root", + "nav_files": "Failid", + "nav_calendar": "Kalender", + "nav_settings": "Seaded", + "nav_kanban": "Kanban", + "user_menu_account_settings": "Konto seaded", + "user_menu_switch_org": "Vaheta organisatsiooni", + "user_menu_logout": "Logi välja", + "btn_new": "+ Uus", + "btn_create": "Loo", + "btn_cancel": "Tühista", + "btn_save": "Salvesta", + "btn_delete": "Kustuta", + "btn_edit": "Muuda", + "btn_close": "Sulge", + "btn_upload": "Laadi üles", + "btn_remove": "Eemalda", + "login_title": "Tere tulemast Rooti", + "login_subtitle": "Sinu meeskonna tööruum dokumentide, tahvlite ja kalendrite jaoks.", + "login_tab_login": "Logi sisse", + "login_tab_signup": "Registreeru", + "login_email_label": "E-post", + "login_email_placeholder": "sina@näide.ee", + "login_password_label": "Parool", + "login_password_placeholder": "••••••••", + "login_btn_login": "Logi sisse", + "login_btn_signup": "Registreeru", + "login_or_continue": "või jätka", + "login_google": "Jätka Google'iga", + "login_signup_prompt": "Pole kontot?", + "login_login_prompt": "On juba konto?", + "login_signup_success_title": "Kontrolli oma e-posti", + "login_signup_success_text": "Saatsime kinnituslingi aadressile {email}. Kliki sellel, et oma konto aktiveerida.", + "org_selector_title": "Sinu organisatsioonid", + "org_selector_create": "Loo organisatsioon", + "org_selector_create_title": "Loo organisatsioon", + "org_selector_name_label": "Organisatsiooni nimi", + "org_selector_name_placeholder": "Minu meeskond", + "org_selector_slug_label": "URL-i lühend", + "org_selector_slug_placeholder": "minu-meeskond", + "org_overview": "Organisatsiooni ülevaade", + "files_title": "Failid", + "files_breadcrumb_home": "Avaleht", + "files_create_title": "Loo uus", + "files_type_document": "Dokument", + "files_type_folder": "Kaust", + "files_type_kanban": "Kanban", + "files_name_label": "Nimi", + "files_doc_placeholder": "Dokumendi nimi", + "files_folder_placeholder": "Kausta nimi", + "files_kanban_placeholder": "Kanban tahvli nimi", + "files_rename_title": "Nimeta ümber", + "files_context_rename": "Nimeta ümber", + "files_context_move": "Teisalda...", + "files_context_delete": "Kustuta", + "files_context_open_tab": "Ava uuel vahelehel", + "files_empty": "Faile pole veel. Kliki + Uus, et luua.", + "files_toggle_view": "Vaheta vaadet", + "kanban_title": "Kanban", + "kanban_create_board": "Loo tahvel", + "kanban_board_name_label": "Tahvli nimi", + "kanban_board_name_placeholder": "nt Sprint 1", + "kanban_edit_board": "Muuda tahvlit", + "kanban_rename_board": "Nimeta tahvel ümber", + "kanban_delete_board": "Kustuta tahvel", + "kanban_add_column": "Lisa veerg", + "kanban_column_name_label": "Veeru nimi", + "kanban_column_name_placeholder": "nt Teha, Töös, Valmis", + "kanban_add_card": "Lisa kaart", + "kanban_card_details": "Kaardi üksikasjad", + "kanban_card_title_label": "Pealkiri", + "kanban_card_title_placeholder": "Kaardi pealkiri", + "kanban_card_desc_label": "Kirjeldus", + "kanban_card_desc_placeholder": "Lisa üksikasjalikum kirjeldus...", + "kanban_tags": "Sildid", + "kanban_tag_placeholder": "Sildi nimi", + "kanban_tag_add": "Lisa", + "kanban_empty": "Kanban tahvleid hallatakse nüüd Failides", + "kanban_go_to_files": "Mine Failidesse", + "kanban_select_board": "Vali tahvel ülalt", + "calendar_title": "Kalender", + "calendar_subscribe": "Telli kalender", + "calendar_refresh": "Värskenda sündmusi", + "calendar_settings": "Kalendri seaded", + "calendar_create_event": "Loo sündmus", + "calendar_edit_event": "Muuda sündmust", + "calendar_event_title": "Pealkiri", + "calendar_event_title_placeholder": "Sündmuse pealkiri", + "calendar_event_date": "Kuupäev", + "calendar_event_time": "Kellaaeg", + "calendar_event_desc": "Kirjeldus", + "settings_title": "Seaded", + "settings_tab_general": "Üldine", + "settings_tab_members": "Liikmed", + "settings_tab_roles": "Rollid", + "settings_tab_tags": "Sildid", + "settings_tab_integrations": "Integratsioonid", + "settings_general_title": "Organisatsiooni andmed", + "settings_general_avatar": "Avatar", + "settings_general_name": "Nimi", + "settings_general_name_placeholder": "Organisatsiooni nimi", + "settings_general_slug": "URL-i lühend (sait.ee/...)", + "settings_general_slug_placeholder": "minu-org", + "settings_general_save": "Salvesta muudatused", + "settings_general_danger_zone": "Ohutsoon", + "settings_general_delete_org": "Kustuta organisatsioon", + "settings_general_delete_org_desc": "Kustuta see organisatsioon ja kõik selle andmed jäädavalt.", + "settings_general_leave_org": "Lahku organisatsioonist", + "settings_general_leave_org_desc": "Lahku sellest organisatsioonist. Tagasi liitumiseks on vaja uut kutset.", + "settings_general_leave_btn": "Lahku {orgName}", + "settings_tags_title": "Organisatsiooni sildid", + "settings_tags_desc": "Halda silte, mida saab kasutada kõigil Kanban tahvlitel.", + "settings_tags_create": "Loo silt", + "settings_tags_empty": "Silte pole veel. Loo oma esimene silt Kanban kaartide korraldamiseks.", + "settings_tags_name_placeholder": "Sildi nimi", + "settings_members_title": "Meeskonna liikmed ({count})", + "settings_members_invite": "Kutsu liige", + "settings_members_pending": "Ootel kutsed", + "settings_members_invited_as": "Kutsutud kui {role} • Aegub {date}", + "settings_members_copy_link": "Kopeeri link", + "settings_members_unknown": "Tundmatu kasutaja", + "settings_members_no_name": "Nimi puudub", + "settings_members_no_email": "E-post puudub", + "settings_members_remove": "Eemalda organisatsioonist", + "settings_invite_title": "Kutsu liige", + "settings_invite_email": "E-posti aadress", + "settings_invite_email_placeholder": "kolleeg@näide.ee", + "settings_invite_role": "Roll", + "settings_invite_send": "Saada kutse", + "settings_invite_role_viewer": "Vaataja - Saab sisu vaadata", + "settings_invite_role_commenter": "Kommenteerija - Saab vaadata ja kommenteerida", + "settings_invite_role_editor": "Toimetaja - Saab sisu luua ja muuta", + "settings_invite_role_admin": "Admin - Saab hallata liikmeid ja seadeid", + "settings_edit_member": "Muuda liiget", + "settings_roles_title": "Rollid", + "settings_roles_desc": "Loo kohandatud rolle kindlate õigustega.", + "settings_roles_create": "Loo roll", + "settings_roles_edit": "Muuda rolli", + "settings_roles_system": "Süsteemne", + "settings_roles_default": "Vaikimisi", + "settings_roles_all_perms": "Kõik õigused", + "settings_roles_more": "+{count} veel", + "settings_roles_name_label": "Nimi", + "settings_roles_name_placeholder": "nt Moderaator", + "settings_roles_color": "Värv", + "settings_roles_permissions": "Õigused", + "settings_integrations_google_cal": "Google'i kalender", + "settings_integrations_google_cal_desc": "Jaga Google'i kalendrit kõigi organisatsiooni liikmetega.", + "settings_integrations_connected": "Ühendatud", + "settings_integrations_disconnect": "Katkesta ühendus", + "settings_integrations_connect": "Ühenda Google'i kalender", + "settings_integrations_discord": "Discord", + "settings_integrations_discord_desc": "Saa teavitusi oma Discordi serveris.", + "settings_integrations_slack": "Slack", + "settings_integrations_slack_desc": "Saa teavitusi oma Slacki tööruumis.", + "settings_integrations_coming_soon": "Tulekul", + "settings_connect_cal_title": "Ühenda avalik Google'i kalender", + "settings_connect_cal_desc": "Kleebi oma Google'i kalendri jagamislink või kalendri ID. Kalender peab olema Google'i kalendri seadetes avalikuks seatud.", + "settings_connect_cal_how": "Kuidas saada kalendri linki:", + "settings_connect_cal_step1": "Ava Google'i kalender", + "settings_connect_cal_step2": "Kliki kalendri kõrval 3 punkti → Seaded", + "settings_connect_cal_step3": "\"Juurdepääsuõiguste\" all märgi \"Tee avalikuks\"", + "settings_connect_cal_step4": "Keri alla \"Kalendri integreerimine\" ja kopeeri kalendri ID või avalik URL", + "settings_connect_cal_input_label": "Kalendri URL või ID", + "settings_connect_cal_input_placeholder": "Kleebi kalendri URL või ID (nt abc123@group.calendar.google.com)", + "settings_connect_cal_btn": "Ühenda", + "account_title": "Konto seaded", + "account_subtitle": "Halda oma isiklikku profiili ja eelistusi.", + "account_profile": "Profiil", + "account_photo": "Foto", + "account_sync_google": "Sünkrooni Google", + "account_remove_photo": "Eemalda foto", + "account_display_name": "Kuvatav nimi", + "account_display_name_placeholder": "Sinu nimi", + "account_email": "E-post", + "account_save_profile": "Salvesta profiil", + "account_appearance": "Välimus", + "account_theme": "Teema", + "account_theme_dark": "Tume", + "account_theme_light": "Hele (tulekul)", + "account_theme_system": "Süsteemne (tulekul)", + "account_accent_color": "Aktsentvärv", + "account_use_org_theme": "Kasuta organisatsiooni teemat", + "account_use_org_theme_desc": "Asenda oma isiklik teema organisatsiooni seadetega.", + "account_language": "Keel", + "account_language_desc": "Vali eelistatud liidese keel.", + "account_save_preferences": "Salvesta eelistused", + "account_security": "Turvalisus ja seansid", + "account_password": "Parool", + "account_password_desc": "Kui logisid sisse Google'iga, haldab sinu parooli Google. Muul juhul saad parooli e-posti teel lähtestada.", + "account_send_reset": "Saada lähtestamise e-kiri", + "account_active_sessions": "Aktiivsed seansid", + "account_sessions_desc": "Logi välja kõigist teistest seanssidest, kui kahtlustad volitamata juurdepääsu.", + "account_signout_others": "Logi teised seansid välja", + "editor_save": "Salvesta", + "editor_saving": "Salvestamine...", + "editor_saved": "Salvestatud", + "editor_error": "Viga", + "editor_placeholder": "Alusta kirjutamist...", + "editor_bold": "Paks (Ctrl+B)", + "editor_italic": "Kursiiv (Ctrl+I)", + "editor_strikethrough": "Läbikriipsutus", + "editor_bullet_list": "Täpploend", + "editor_numbered_list": "Nummerdatud loend", + "editor_quote": "Tsitaat", + "editor_code_block": "Koodiplokk", + "toast_error_delete_org": "Organisatsiooni kustutamine ebaõnnestus.", + "toast_error_leave_org": "Organisatsioonist lahkumine ebaõnnestus.", + "toast_error_invite": "Kutse saatmine ebaõnnestus: {error}", + "toast_error_update_role": "Rolli uuendamine ebaõnnestus.", + "toast_error_remove_member": "Liikme eemaldamine ebaõnnestus.", + "toast_error_delete_role": "Rolli kustutamine ebaõnnestus.", + "toast_error_disconnect_cal": "Kalendri lahtiühendamine ebaõnnestus.", + "toast_error_reset_email": "Lähtestamise e-kirja saatmine ebaõnnestus.", + "toast_success_reset_email": "Parooli lähtestamise e-kiri saadetud.", + "toast_success_signout_others": "Teised seansid välja logitud.", + "confirm_delete_role": "Kustuta roll \"{name}\"? Selle rolliga liikmed tuleb ümber määrata.", + "confirm_leave_org": "Kas oled kindel, et soovid lahkuda {orgName}?", + "confirm_delete_org": "Sisesta \"{orgName}\" kustutamise kinnitamiseks:", + "confirm_remove_member": "Eemalda {name} organisatsioonist?", + "confirm_disconnect_cal": "Katkesta Google'i kalendri ühendus?", + "role_viewer": "Vaataja", + "role_commenter": "Kommenteerija", + "role_editor": "Toimetaja", + "role_admin": "Admin", + "role_owner": "Omanik", + "error_owner_cant_leave": "Omanikud ei saa lahkuda. Kõigepealt anna omandiõigus üle või kustuta organisatsioon.", + "overview_title": "Organisatsiooni ülevaade", + "overview_stat_members": "Liikmed", + "overview_stat_documents": "Dokumendid", + "overview_stat_folders": "Kaustad", + "overview_stat_boards": "Tahvlid", + "overview_quick_links": "Kiirlingid", + "activity_title": "Viimane tegevus", + "activity_empty": "Viimast tegevust pole veel.", + "activity_created": "{user} lõi {entityType} \"{name}\"", + "activity_updated": "{user} uuendas {entityType} \"{name}\"", + "activity_deleted": "{user} kustutas {entityType} \"{name}\"", + "activity_moved": "{user} teisaldas {entityType} \"{name}\"", + "activity_renamed": "{user} nimetas ümber {entityType} \"{name}\"", + "activity_just_now": "Just praegu", + "activity_minutes_ago": "{count} min tagasi", + "activity_hours_ago": "{count}t tagasi", + "activity_days_ago": "{count}p tagasi", + "entity_document": "dokumendi", + "entity_folder": "kausta", + "entity_kanban_board": "tahvli", + "entity_kanban_card": "kaardi", + "entity_kanban_column": "veeru", + "entity_member": "liikme", + "entity_role": "rolli", + "entity_invite": "kutse" +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e04eb35..b75ab85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,14 +8,18 @@ "name": "root-org", "version": "0.0.1", "dependencies": { + "@inlang/paraglide-js": "^2.10.0", "@supabase/ssr": "^0.8.0", "@supabase/supabase-js": "^2.94.0", "@tiptap/core": "^3.19.0", "@tiptap/extension-placeholder": "^3.19.0", "@tiptap/pm": "^3.19.0", - "@tiptap/starter-kit": "^3.19.0" + "@tiptap/starter-kit": "^3.19.0", + "google-auth-library": "^10.5.0" }, "devDependencies": { + "@inlang/paraglide-js": "^2.10.0", + "@playwright/test": "^1.58.1", "@sveltejs/adapter-node": "^5.5.2", "@sveltejs/kit": "^2.50.1", "@sveltejs/vite-plugin-svelte": "^6.2.4", @@ -475,6 +479,69 @@ "node": ">=18" } }, + "node_modules/@inlang/paraglide-js": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@inlang/paraglide-js/-/paraglide-js-2.10.0.tgz", + "integrity": "sha512-3xQveEyZMV9IOLP7Vy9Ttye+Yzryqz6KM06tvVwvmbCPDTdzmFoc34KlREXGpHuBAlxRZGfAhcJKfnSXXQDmXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inlang/recommend-sherlock": "^0.2.1", + "@inlang/sdk": "2.6.2", + "commander": "11.1.0", + "consola": "3.4.0", + "json5": "2.2.3", + "unplugin": "^2.1.2", + "urlpattern-polyfill": "^10.0.0" + }, + "bin": { + "paraglide-js": "bin/run.js" + } + }, + "node_modules/@inlang/recommend-sherlock": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@inlang/recommend-sherlock/-/recommend-sherlock-0.2.1.tgz", + "integrity": "sha512-ckv8HvHy/iTqaVAEKrr+gnl+p3XFNwe5D2+6w6wJk2ORV2XkcRkKOJ/XsTUJbPSiyi4PI+p+T3bqbmNx/rDUlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "comment-json": "^4.2.3" + } + }, + "node_modules/@inlang/sdk": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@inlang/sdk/-/sdk-2.6.2.tgz", + "integrity": "sha512-eOgAX+eQpHvD/H4BMILc4tZ85XviTlwr/51RKkKUHozVVthj5avUPKP+4N4vcTUrqSscl2atTh9NbNTuvoBN0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lix-js/sdk": "0.4.7", + "@sinclair/typebox": "^0.31.17", + "kysely": "^0.27.4", + "sqlite-wasm-kysely": "0.3.0", + "uuid": "^13.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -525,6 +592,72 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@lix-js/sdk": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@lix-js/sdk/-/sdk-0.4.7.tgz", + "integrity": "sha512-pRbW+joG12L0ULfMiWYosIW0plmW4AsUdiPCp+Z8rAsElJ+wJ6in58zhD3UwUcd4BNcpldEGjg6PdA7e0RgsDQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@lix-js/server-protocol-schema": "0.1.1", + "dedent": "1.5.1", + "human-id": "^4.1.1", + "js-sha256": "^0.11.0", + "kysely": "^0.27.4", + "sqlite-wasm-kysely": "0.3.0", + "uuid": "^10.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@lix-js/sdk/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@lix-js/server-protocol-schema": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@lix-js/server-protocol-schema/-/server-protocol-schema-0.1.1.tgz", + "integrity": "sha512-jBeALB6prAbtr5q4vTuxnRZZv1M2rKe8iNqRQhFJ4Tv7150unEa0vKyz0hs8Gl3fUGsWaNJBh3J8++fpbrpRBQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@playwright/test": { + "version": "1.58.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.1.tgz", + "integrity": "sha512-6LdVIUERWxQMmUSSQi0I53GgCBYgM2RpGngCPY7hSeju+VrKjq3lvs7HpJoPbDiY5QM5EYRtRX5fvrinnMAz3w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.58.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.29", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", @@ -984,6 +1117,23 @@ "win32" ] }, + "node_modules/@sinclair/typebox": { + "version": "0.31.28", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.31.28.tgz", + "integrity": "sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sqlite.org/sqlite-wasm": { + "version": "3.48.0-build4", + "resolved": "https://registry.npmjs.org/@sqlite.org/sqlite-wasm/-/sqlite-wasm-3.48.0-build4.tgz", + "integrity": "sha512-hI6twvUkzOmyGZhQMza1gpfqErZxXRw6JEsiVjUbo7tFanVD+8Oil0Ih3l2nGzHdxPI41zFmfUQG7GHqhciKZQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "sqlite-wasm": "bin/index.js" + } + }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", @@ -2176,6 +2326,39 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2192,6 +2375,13 @@ "node": ">= 0.4" } }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true, + "license": "MIT" + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -2212,6 +2402,56 @@ "node": ">= 0.4" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", @@ -2248,6 +2488,49 @@ "node": ">=6" } }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/comment-json": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.5.1.tgz", + "integrity": "sha512-taEtr3ozUmOB7it68Jll7s0Pwm+aoiHyXKrEC8SEodL4rNpdfDLqa7PfBlrgFoCNNdR8ImL+muti5IGvktJAAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-timsort": "^1.0.3", + "core-util-is": "^1.0.3", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -2255,6 +2538,16 @@ "dev": true, "license": "MIT" }, + "node_modules/consola": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.0.tgz", + "integrity": "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, "node_modules/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", @@ -2265,12 +2558,33 @@ "node": ">= 0.6" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, "node_modules/crelt": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", "license": "MIT" }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -2284,6 +2598,47 @@ "node": ">=4" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -2311,6 +2666,27 @@ "dev": true, "license": "MIT" }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, "node_modules/enhanced-resolve": { "version": "5.19.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", @@ -2405,6 +2781,20 @@ "dev": true, "license": "MIT" }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/esrap": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.2.tgz", @@ -2432,6 +2822,12 @@ "node": ">=12.0.0" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -2450,6 +2846,57 @@ } } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -2475,6 +2922,83 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gaxios": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", + "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/google-auth-library": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz", + "integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^8.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -2482,6 +3006,19 @@ "dev": true, "license": "ISC" }, + "node_modules/gtoken": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", + "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "license": "MIT", + "dependencies": { + "gaxios": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -2495,6 +3032,29 @@ "node": ">= 0.4" } }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-id": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.1.3.tgz", + "integrity": "sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==", + "dev": true, + "license": "MIT", + "bin": { + "human-id": "dist/cli.js" + } + }, "node_modules/iceberg-js": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz", @@ -2520,6 +3080,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", @@ -2537,6 +3106,27 @@ "@types/estree": "*" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -2547,6 +3137,56 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/js-sha256": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.11.1.tgz", + "integrity": "sha512-o6WSo/LUvY2uC4j7mO50a2ms7E/EAdbP0swigLV+nzHKTTaYnaLIWJ02VdXrsJX0vGedDESQnLsOekr94ryfjg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -2557,6 +3197,17 @@ "node": ">=6" } }, + "node_modules/kysely": { + "version": "0.27.6", + "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.27.6.tgz", + "integrity": "sha512-FIyV/64EkKhJmjgC0g2hygpBv5RNWVPyNCqSAD7eTCv6eFWNIi4PN1UvdSJGicN/o35bnevgis4Y0UDC0qi8jQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/lightningcss": { "version": "1.30.2", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", @@ -2840,6 +3491,12 @@ "dev": true, "license": "MIT" }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -2883,6 +3540,30 @@ "mini-svg-data-uri": "cli.js" } }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -2903,6 +3584,12 @@ "node": ">=10" } }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -2922,6 +3609,44 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/obug": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", @@ -2939,6 +3664,21 @@ "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", "license": "MIT" }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -2946,6 +3686,22 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -3314,6 +4070,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "4.57.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", @@ -3379,6 +4150,26 @@ "node": ">=6" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/set-cookie-parser": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.0.1.tgz", @@ -3386,6 +4177,27 @@ "dev": true, "license": "MIT" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", @@ -3393,6 +4205,18 @@ "dev": true, "license": "ISC" }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/sirv": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", @@ -3418,6 +4242,18 @@ "node": ">=0.10.0" } }, + "node_modules/sqlite-wasm-kysely": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/sqlite-wasm-kysely/-/sqlite-wasm-kysely-0.3.0.tgz", + "integrity": "sha512-TzjBNv7KwRw6E3pdKdlRyZiTmUIE0UttT/Sl56MVwVARl/u5gp978KepazCJZewFUnlWHz9i3NQd4kOtP/Afdg==", + "dev": true, + "dependencies": { + "@sqlite.org/sqlite-wasm": "^3.48.0-build2" + }, + "peerDependencies": { + "kysely": "*" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -3432,6 +4268,102 @@ "dev": true, "license": "MIT" }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -3616,6 +4548,29 @@ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT" }, + "node_modules/unplugin": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.11.tgz", + "integrity": "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "acorn": "^8.15.0", + "picomatch": "^4.0.3", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/urlpattern-polyfill": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", + "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==", + "dev": true, + "license": "MIT" + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -3623,6 +4578,20 @@ "dev": true, "license": "MIT" }, + "node_modules/uuid": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, "node_modules/vite": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", @@ -3836,6 +4805,37 @@ "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", "license": "MIT" }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", @@ -3853,6 +4853,97 @@ "node": ">=8" } }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ws": { "version": "8.19.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", diff --git a/package.json b/package.json index cea9930..64d70ed 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,8 @@ "test": "npm run test:unit -- --run" }, "devDependencies": { + "@inlang/paraglide-js": "^2.10.0", + "@playwright/test": "^1.58.1", "@sveltejs/adapter-node": "^5.5.2", "@sveltejs/kit": "^2.50.1", "@sveltejs/vite-plugin-svelte": "^6.2.4", @@ -31,11 +33,13 @@ "vitest-browser-svelte": "^2.0.2" }, "dependencies": { + "@inlang/paraglide-js": "^2.10.0", "@supabase/ssr": "^0.8.0", "@supabase/supabase-js": "^2.94.0", "@tiptap/core": "^3.19.0", "@tiptap/extension-placeholder": "^3.19.0", "@tiptap/pm": "^3.19.0", - "@tiptap/starter-kit": "^3.19.0" + "@tiptap/starter-kit": "^3.19.0", + "google-auth-library": "^10.5.0" } } diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..3ba5674 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,32 @@ +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + testDir: './tests/e2e', + globalTeardown: './tests/e2e/cleanup.ts', + fullyParallel: false, + forbidOnly: !!process.env.CI, + retries: 0, + workers: 1, + reporter: 'list', + timeout: 60000, + use: { + baseURL: 'http://localhost:5173', + trace: 'on-first-retry', + screenshot: 'only-on-failure', + navigationTimeout: 30000, + }, + projects: [ + { + name: 'setup', + testMatch: /auth\.setup\.ts/, + }, + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + storageState: 'tests/e2e/.auth/user.json', + }, + dependencies: ['setup'], + }, + ], +}); diff --git a/project.inlang/settings.json b/project.inlang/settings.json new file mode 100644 index 0000000..9358285 --- /dev/null +++ b/project.inlang/settings.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://inlang.com/schema/project-settings", + "modules": [ + "https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js" + ], + "plugin.inlang.messageFormat": { + "pathPattern": "./messages/{locale}.json" + }, + "baseLocale": "en", + "locales": [ + "en", + "et" + ] +} diff --git a/src/app.html b/src/app.html index f273cc5..c4fbc02 100644 --- a/src/app.html +++ b/src/app.html @@ -1,11 +1,18 @@ - + +
- + + + %sveltekit.head% - + ++
{card.title}
diff --git a/src/lib/components/settings/SettingsIntegrations.svelte b/src/lib/components/settings/SettingsIntegrations.svelte new file mode 100644 index 0000000..ee12a1c --- /dev/null +++ b/src/lib/components/settings/SettingsIntegrations.svelte @@ -0,0 +1,369 @@ + + ++ Sync events between your organization and Google + Calendar. +
+ + {#if orgCalendar} ++ Connected +
++ {orgCalendar.calendar_name || + "Google Calendar"} +
++ {orgCalendar.calendar_id} +
++ Events sync both ways — create here or + in Google Calendar. +
+ + + Open in Google Calendar + ++ Setup required +
+
+ A server administrator needs to configure the GOOGLE_SERVICE_ACCOUNT_KEY environment variable before calendars can be connected.
+
+ Get notifications in your Discord server. +
+Coming soon
++ Get notifications in your Slack workspace. +
+Coming soon
++ Connect any Google Calendar to your organization. Events you create + here will automatically appear in Google Calendar and vice versa. +
+ + + {#if serviceAccountEmail} ++ Step 1: Share your calendar +
++ In Google Calendar, go to your calendar's settings → "Share + with specific people" → add this email with "Make changes to events" permission: +
+
+ {serviceAccountEmail}
+
+ + {serviceAccountEmail ? "Step 2" : "Step 1"}: Paste your Calendar + ID +
++ In your calendar settings, scroll to "Integrate calendar" and + copy the Calendar ID. +
+{calendarError}
+ {/if} + +{invite.email}
++ Invited as {invite.role} • Expires {new Date( + invite.expires_at, + ).toLocaleDateString()} +
++ {profile?.full_name || + profile?.email || + "Unknown User"} +
++ {profile?.email || "No email"} +
++ {memberProfile?.full_name || "No name"} +
++ {memberProfile?.email || "No email"} +
++ Create custom roles with specific permissions. +
++ {group.name} +
+Organization Overview
+{m.overview_title()}
+ {stat.value} +
+{stat.label}
++ {stat.value} +
+{stat.label}
+{m.activity_empty()}
++ {getActivityDescription(entry)} +
++ {formatTimeAgo(entry.created_at)} +
++ {member.profiles?.full_name || + member.profiles?.email || + "Unknown"} +
++ {member.role} +
++ {m.account_subtitle()} +
++ {m.account_use_org_theme()} +
++ {m.account_use_org_theme_desc()} +
++ {m.account_language_desc()} +
++ {m.account_password()} +
++ {m.account_password_desc()} +
++ {m.account_active_sessions()} +
++ {m.account_sessions_desc()} +
+{invite.email}
-- Invited as {invite.role} • Expires {new Date( - invite.expires_at, - ).toLocaleDateString()} -
-- {profile?.full_name || - profile?.email || - "Unknown User"} -
-- {profile?.email || "No email"} -
-- Create custom roles with specific permissions. + {m.settings_tags_desc()}
{m.settings_tags_empty()}
++ {tag.name} +
++ {tag.color || "#00A3E0"} +
+- Share a Google Calendar with all organization - members. -
- - {#if orgCalendar} -- Connected -
-- {orgCalendar.calendar_name || - "Google Calendar"} -
-- {orgCalendar.calendar_id - .length > 40 - ? orgCalendar.calendar_id.slice( - 0, - 40, - ) + "..." - : orgCalendar.calendar_id} -
-- Get notifications in your Discord server. -
-- Coming soon -
-- Get notifications in your Slack workspace. -
-- Coming soon -
-- {memberProfile?.full_name || "No name"} -
-- {memberProfile?.email || "No email"} -
-- {group.name} -
-- Paste your Google Calendar's shareable link or calendar ID. The - calendar must be set to public in Google Calendar settings. -
- -- How to get your calendar link: -
-{calendarError}
- {/if} -